<commit_before>/**
 * Extracts Fujifilm flavored Makernotes which are always stored in little
 * endian, no matter what the rest of the file is. Additionally the offsets
 * are relative to the start of the Makernote instead of the start of the
 * TIFF header.
 */
exports.extractMakernotes = function (data, makernoteOffset, tiffOffset) {

	var makernoteData = {};

	// List of vendor specific Makernote tags found on
	// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/FujiFilm.html
	var tags = {

		0x0000 : "Version",
		0x1000 : "InternalSerialNumber",
		0x1000 : "Quality",
		0x1001 : "Sharpness",
		0x1002 : "WhiteBalance",
		0x1003 : "Saturation",
		0x1004 : "Contrast",
		0x1005 : "ColorTemperature",
		0x1006 : "Contrast",
		0x100a : "WhiteBalanceFineTune",
		0x100b : "NoiseReduction",
		0x100e : "HighISONoiseReduction",
		0x1010 : "FujiFlashMode",
		0x1011 : "FlashExposureComp",
		0x1020 : "Macro",
		0x1021 : "FocusMode",
		0x1023 : "FocusPixel",
		0x1030 : "SlowSync",
		0x1033 : "EXRAuto",
		0x1034 : "EXRMode",
		0x1100 : "AutoBracketing",
		0x1101 : "SequenceNumber",
		0x1210 : "ColorMode",
		0x1300 : "BlurWarning",
		0x1301 : "FocusWarning",
		0x1302 : "ExposureWarning",
		0x1304 : "GEImageSize",
		0x1400 : "DynamicRange",
		0x1401 : "FilmMode",
		0x1402 : "DynamicRangeSetting",
		0x1403 : "DevelopmentDynamicRange",
		0x1404 : "MinFocalLength",
		0x1405 : "MaxFocalLength",
		0x1406 : "MaxApertureAtMinFocal",
		0x1407 : "MaxApertureAtMaxFocal",
		0x140b : "AutoDynamicRange",
		0x4100 : "FacesDetected",
		0x4103 : "FacePositions",
		0x4282 : "FaceRecInfo",
		0x8000 : "FileSource",
		0x8002 : "OrderNumber",
		0x8003 : "FrameNumber",
		0xb211 : "Parallax"

	};

	// Start of the Fujifilm flavored Makernote data is determined by the four
	// bytes following the Makernote vendor name
	var ifdOffset = makernoteOffset + data.getLong(makernoteOffset + 8, false, tiffOffset);

	console.log(ifdOffset);

	// Get the number of entries and extract them
	var numberOfEntries = data.getShort(ifdOffset, false, tiffOffset);

	console.log(numberOfEntries);

	for (var i = 0; i < numberOfEntries; i++) {
		var exifEntry = this.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), makernoteOffset, false, tags);
		if (exifEntry && exifEntry.tagName !== null) makernoteData[exifEntry.tagName] = exifEntry.value;
	}

	console.log(makernoteData);

	return makernoteData;

};<commit_msg>Removed debug output<commit_after>/**
 * Extracts Fujifilm flavored Makernotes which are always stored in little
 * endian, no matter what the rest of the file is. Additionally the offsets
 * are relative to the start of the Makernote instead of the start of the
 * TIFF header.
 */
exports.extractMakernotes = function (data, makernoteOffset, tiffOffset) {

	var makernoteData = {};

	// List of vendor specific Makernote tags found on
	// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/FujiFilm.html
	var tags = {

		0x0000 : "Version",
		0x1000 : "InternalSerialNumber",
		0x1000 : "Quality",
		0x1001 : "Sharpness",
		0x1002 : "WhiteBalance",
		0x1003 : "Saturation",
		0x1004 : "Contrast",
		0x1005 : "ColorTemperature",
		0x1006 : "Contrast",
		0x100a : "WhiteBalanceFineTune",
		0x100b : "NoiseReduction",
		0x100e : "HighISONoiseReduction",
		0x1010 : "FujiFlashMode",
		0x1011 : "FlashExposureComp",
		0x1020 : "Macro",
		0x1021 : "FocusMode",
		0x1023 : "FocusPixel",
		0x1030 : "SlowSync",
		0x1033 : "EXRAuto",
		0x1034 : "EXRMode",
		0x1100 : "AutoBracketing",
		0x1101 : "SequenceNumber",
		0x1210 : "ColorMode",
		0x1300 : "BlurWarning",
		0x1301 : "FocusWarning",
		0x1302 : "ExposureWarning",
		0x1304 : "GEImageSize",
		0x1400 : "DynamicRange",
		0x1401 : "FilmMode",
		0x1402 : "DynamicRangeSetting",
		0x1403 : "DevelopmentDynamicRange",
		0x1404 : "MinFocalLength",
		0x1405 : "MaxFocalLength",
		0x1406 : "MaxApertureAtMinFocal",
		0x1407 : "MaxApertureAtMaxFocal",
		0x140b : "AutoDynamicRange",
		0x4100 : "FacesDetected",
		0x4103 : "FacePositions",
		0x4282 : "FaceRecInfo",
		0x8000 : "FileSource",
		0x8002 : "OrderNumber",
		0x8003 : "FrameNumber",
		0xb211 : "Parallax"

	};

	// Start of the Fujifilm flavored Makernote data is determined by the four
	// bytes following the Makernote vendor name
	var ifdOffset = makernoteOffset + data.getLong(makernoteOffset + 8, false, tiffOffset);

	// Get the number of entries and extract them
	var numberOfEntries = data.getShort(ifdOffset, false, tiffOffset);

	for (var i = 0; i < numberOfEntries; i++) {
		var exifEntry = this.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), makernoteOffset, false, tags);
		if (exifEntry && exifEntry.tagName !== null) makernoteData[exifEntry.tagName] = exifEntry.value;
	}

	return makernoteData;

};<|endoftext|>


<commit_before>var m = require('mithril');
var classSet = require('common').classSet;
var button = require('../view/button');
var game = require('game').game;

function renderClock(ctrl, player, position) {
  var time = ctrl.clock.data[player.color];
  var running = ctrl.isClockRunning() && ctrl.data.game.player === player.color;
  var isPlayer = ctrl.data.player.color === player.color;
  return [
    m('div', {
      class: 'clock clock_' + player.color + ' clock_' + position + ' ' + classSet({
        'outoftime': !time,
        'running': running,
        'emerg': time < ctrl.clock.data.emerg
      })
    }, [
      showBar(ctrl.clock, player.color, time, ctrl.vm.goneBerserk[player.color]),
      m('div.time', {
        config: function(el, isUpdate, ctx) {
          if (player.color !== ctx.color) {
            ctrl.clock.elements[player.color].time = el;
            ctx.color = player.color;
          }
          ctrl.clock.elements[player.color].time.innerHTML = formatClockTime(ctrl.clock.data, time * 1000, running);
        }
      }),
      renderBerserk(ctrl, player.color, position),
      isPlayer ? goBerserk(ctrl) : button.moretime(ctrl),
      tourRank(ctrl, player.color, position)
    ])
  ];
}

function prefixInteger(num, length) {
  return (num / Math.pow(10, length)).toFixed(length).substr(2);
}

var sepHigh = '<sep>:</sep>';
var sepLow = '<sep class="low">:</sep>';

function formatClockTime(data, time, running) {
  var date = new Date(time);
  var minutes = prefixInteger(date.getUTCMinutes(), 2);
  var secs = date.getSeconds();
  var seconds = prefixInteger(secs, 2);
  var tenths = Math.floor(date.getMilliseconds() / 100);
  var hundredths = function() {
    return Math.floor(date.getMilliseconds() / 10) - tenths * 10;
  };
  var sep = (running && tenths < 5) ? sepLow : sepHigh;
  if ((data.showTenths == 2 && time < 3600000) || (data.showTenths == 1 && time < 10000)) {
    var showHundredths = !running && secs < 1;
    return minutes + sep + seconds +
    '<tenths><sep>.</sep>' + tenths + (showHundredths ? '<huns>' + hundredths() + '</huns>' : '') + '</tenths>';
  } else if (time >= 3600000) {
    var hours = prefixInteger(date.getUTCHours(), 2);
    return hours + sepHigh + minutes + sep + seconds;
  } else
  return minutes + sep + seconds;
}

function barWidth(data, time) {
  return Math.max(0, Math.min(100, (time / data.barTime) * 100)) + '%';
}

function showBar(ctrl, color, time, berserk) {
  return ctrl.data.showBar ? m('div', {
    class: 'bar' + (berserk ? ' berserk' : '')
  }, m('span', {
    config: function(el, isUpdate, ctx) {
      if (color !== ctx.color) {
        ctrl.elements[color].bar = el;
        ctx.color = color;
      }
      ctrl.elements[color].bar.style.width = barWidth(ctrl.data, time);
    }
  })) : null;
}

function updateElements(data, elements, color) {
  var els = elements[color];
  if (els) {
    els.time.innerHTML = formatClockTime(data, data[color] * 1000, true);
    if (els.bar) els.bar.style.width = barWidth(data, data[color]);
  } else {
    m.redraw();
  }
}

function showBerserk(ctrl, color) {
  return ctrl.vm.goneBerserk[color] &&
  ctrl.data.game.turns <= 1 &&
  game.playable(ctrl.data);
}

function renderBerserk(ctrl, color, position) {
  if (showBerserk(ctrl, color)) return m('div', {
    class: 'berserk_alert ' + position,
    'data-icon': '`'
  });
}

function goBerserk(ctrl) {
  if (!game.berserkableBy(ctrl.data)) return;
  if (ctrl.vm.goneBerserk[ctrl.data.player.color]) return;
  return m('button', {
    class: 'fbt berserk hint--bottom-left',
    'data-hint': "GO BERSERK! Half the time, bonus point",
    onclick: ctrl.goBerserk
  }, m('span', {
    'data-icon': '`'
  }));
}

function tourRank(ctrl, color, position) {
  var d = ctrl.data;
  if (d.tournament && d.tournament.ranks && !showBerserk(ctrl, color)) return m('div', {
    class: 'tournament_rank ' + position,
    title: 'Current tournament rank'
  }, '#' + d.tournament.ranks[color]);
}

module.exports = {
  renderClock: renderClock,
  updateElements: updateElements
};
<commit_msg>Clean up game clock fun<commit_after>var m = require('mithril');
var classSet = require('common').classSet;
var button = require('../view/button');
var game = require('game').game;

function renderClock(ctrl, player, position) {
  var time = ctrl.clock.data[player.color];
  var running = ctrl.isClockRunning() && ctrl.data.game.player === player.color;
  var isPlayer = ctrl.data.player.color === player.color;
  return [
    m('div', {
      class: 'clock clock_' + player.color + ' clock_' + position + ' ' + classSet({
        'outoftime': !time,
        'running': running,
        'emerg': time < ctrl.clock.data.emerg
      })
    }, [
      showBar(ctrl.clock, player.color, time, ctrl.vm.goneBerserk[player.color]),
      m('div.time', {
        config: function(el, isUpdate, ctx) {
          if (player.color !== ctx.color) {
            ctrl.clock.elements[player.color].time = el;
            ctx.color = player.color;
          }
          ctrl.clock.elements[player.color].time.innerHTML = formatClockTime(ctrl.clock.data, time * 1000, running);
        }
      }),
      renderBerserk(ctrl, player.color, position),
      isPlayer ? goBerserk(ctrl) : button.moretime(ctrl),
      tourRank(ctrl, player.color, position)
    ])
  ];
}

function _pad2(num) {
  return (num < 10 ? '0' : '') + num;
}

var sepHigh = '<sep>:</sep>';
var sepLow = '<sep class="low">:</sep>';

function formatClockTime(data, time, running) {
  var date = new Date(time);
  var millis = date.getUTCMilliseconds();
  var sep = (running && millis < 500) ? sepLow : sepHigh;
  var baseStr = _pad2(date.getUTCMinutes()) + sep + _pad2(date.getUTCSeconds());
  if (time >= 3600000) {
    var hours = _pad2(Math.floor(time / 3600000));
    return hours + sepHigh + baseStr;
  } else if (time >= 10000 && date.showTenths != 2 || data.showTenths == 0) {
    return baseStr;
  } else {
    var tenthsStr = Math.floor(millis / 100).toString();
    if (!running && time < 1000) {
      tenthsStr += '<huns>' + (Math.floor(millis / 10) % 10) + '</huns>';
    }

    return baseStr + '<tenths><sep>.</sep>' + tenthsStr + '</tenths>';
  }
}

function barWidth(data, time) {
  return Math.max(0, Math.min(100, (time / data.barTime) * 100)) + '%';
}

function showBar(ctrl, color, time, berserk) {
  return ctrl.data.showBar ? m('div', {
    class: 'bar' + (berserk ? ' berserk' : '')
  }, m('span', {
    config: function(el, isUpdate, ctx) {
      if (color !== ctx.color) {
        ctrl.elements[color].bar = el;
        ctx.color = color;
      }
      ctrl.elements[color].bar.style.width = barWidth(ctrl.data, time);
    }
  })) : null;
}

function updateElements(data, elements, color) {
  var els = elements[color];
  if (els) {
    els.time.innerHTML = formatClockTime(data, data[color] * 1000, true);
    if (els.bar) els.bar.style.width = barWidth(data, data[color]);
  } else {
    m.redraw();
  }
}

function showBerserk(ctrl, color) {
  return ctrl.vm.goneBerserk[color] &&
  ctrl.data.game.turns <= 1 &&
  game.playable(ctrl.data);
}

function renderBerserk(ctrl, color, position) {
  if (showBerserk(ctrl, color)) return m('div', {
    class: 'berserk_alert ' + position,
    'data-icon': '`'
  });
}

function goBerserk(ctrl) {
  if (!game.berserkableBy(ctrl.data)) return;
  if (ctrl.vm.goneBerserk[ctrl.data.player.color]) return;
  return m('button', {
    class: 'fbt berserk hint--bottom-left',
    'data-hint': "GO BERSERK! Half the time, bonus point",
    onclick: ctrl.goBerserk
  }, m('span', {
    'data-icon': '`'
  }));
}

function tourRank(ctrl, color, position) {
  var d = ctrl.data;
  if (d.tournament && d.tournament.ranks && !showBerserk(ctrl, color)) return m('div', {
    class: 'tournament_rank ' + position,
    title: 'Current tournament rank'
  }, '#' + d.tournament.ranks[color]);
}

module.exports = {
  renderClock: renderClock,
  updateElements: updateElements
};
<|endoftext|>


<commit_before>import queryString from 'query-string';

export default function getStatLink(collection, field, value,) {
  const params = {
    [`filter:${field}`]: value,
  };
  if (collection) {
    params['filter:collection_id'] = collection.id;
  }
  const query = queryString.stringify(params);
  return `/search?${query}`;
}
<commit_msg>modified collection stat links to link to collection-level search instead of site-wide search<commit_after>import queryString from 'query-string';

import getCollectionLink from 'util/getCollectionLink';

export default function getStatLink(collection, field, value,) {
  if (collection) {
    const params = {
      [`entitiesfilter:${field}`]: value,
    };
    const query = queryString.stringify(params);
    return `${getCollectionLink(collection)}?${query}#mode=search`;
  }

  const params = {
    [`filter:${field}`]: value,
  };
  const query = queryString.stringify(params);

  return `/search?${query}`;
}
<|endoftext|>


<commit_before>function citation_tool(url, cite_id) {
	// Modal part
	$('#citation_modal_table tbody').empty();
    var modal = document.getElementById('citation-tool');
    var span = document.getElementById("close-citation");
    modal.classList.add("modal");
    setTimeout(function(){
    	modal.style.display = "block";
    }, 200)

    span.onclick = function() {
        modal.style.display = "none";
        $(".article_option").remove();
        $(".article").remove();
        $(".cite-submenu").remove();
    }
    window.onclick = function(event) {
        if (event.target == modal) {
            modal.style.display = "none";
            $(".article_option").remove();
            $(".article").remove();
            $(".cite-submenu").remove();
        }
    }

    // Process location
    var this_site = parse_url_long(url);
    var highlight_main = false;
    if (window.location.pathname==='/') {
    	highlight_main = true
    }

    // AJAX to create citation list
    var dropdown_articles = document.getElementById("dropdown_articles");
    var article_list = document.getElementById("article_list");
    var env = url.split('//')[1].split('/')[0];
    var main_ref_id = [];
    var cit_request = new XMLHttpRequest();
    var domains = ["gpcrdb.org", "gproteindb.org", "arrestindb.org"];
    var filter_for = false;
    if (env==="gpcrdb.org" || cite_id==="cite_gpcrdb") {
    	filter_for = "gpcrdb";
    }
    else if (env==="gproteindb.org" || cite_id==="cite_gproteindb") {
    	filter_for = "gproteindb";
    }
    else if (env==="arrestindb.org" || cite_id==="cite_arrestindb") {
    	filter_for = "arrestindb";
    }
    else if (env==="biasedsignalingatlas.org" || cite_id==="cite_biasedsignalingatlas") {
    	filter_for = "biasedsignalingatlas";
    }
    cit_request.open('GET', url.split('/')[0] + '/citations');
    // env = "gpcrdb.org";
    cit_request.onload = function() {
		var data = JSON.parse(cit_request.responseText)
		for (let i = 0; i < data.length; i++) {
			var link = "";
			if (!domains.includes(env)) {
				link = "/" + data[i][0].split("//")[1].split("/").slice(1).join("/");
			}
			else {
				link = data[i][0];
			}
			if (link[link.length-1]==='/') {
				link = link.substring(0, link.length-1);
			}
			if (link==='/GPCR-Gprotein_Mutations.xlsx') {
				link = 'https://files.gpcrdb.org/GPCR-Gprotein_Mutations.xlsx'
			}
			else if (link==='/mutations.html#mutation-data-submission') {
				link = 'https://docs.gpcrdb.org/mutations.html#mutation-data-submission'
			}
			if ($('a[href="'+link+'"]').first().parent().parent().parent().first().hasClass('dropdown-submenu')) {
				data[i].push($('a[href="'+link+'"]').first().parent().parent().parent().parent().parent().first().find(">:first-child").text().trim());
			}
			else {
				if (link==="/protein/ste2_yeast") {
					data[i].push("GPCRdb");
				}
				else {
					data[i].push($('a[href="'+link+'"]').first().parent().parent().parent().first().find(">:first-child").text().trim());
				}
			}
		}
		// Create HTML once per call
		var articles = {};
		var tags = [];
		for (let i = 0; i < data.length; i++) {
			if (data[i][11]==='') {
				continue;
			}
			if (filter_for==="gpcrdb" && data[i][11]!=="GPCRdb") {
				continue;
			}
			else if (filter_for==="gproteindb" && data[i][11]!=="GproteinDb") {
				continue;
			}
			else if (filter_for==="arrestindb" && data[i][11]!=="ArrestinDb") {
				continue;
			}
			else if (filter_for==="biasedsignalingatlas" && data[i][11]!=="BiasedSignalingAtlas") {
				continue;
			}
			else if (filter_for==="arrestindb" && data[i][11]==="ArrestinDb") {
				data[i][5] = "The arrestin database, ArrestinDb";
				data[i][6] = "Jimmy Caroli, Gáspár Pándy-Szekeres, Alexander S. Hauser, György M. Keserű, Albert J. Kooistra and David E. Gloriam";
				data[i][7] = 2022;
				data[i][8] = "";
				data[i][9] = "Manuscript";
				data[i][10] = "";
			}
			else if (filter_for==="biasedsignalingatlas" && data[i][11]==="BiasedSignalingAtlas") {
				data[i][5] = "Manuscript";
				data[i][6] = "Jimmy Caroli, Alibek Mamyrbekov, Kasper Harpsøe, Sahar Gardizi, Linda Dörries, Eshan Ghosh, Alexander S. Hauser, Albert J. Kooistra, and David E. Gloriam";
				data[i][7] = 2022;
				data[i][8] = "";
				data[i][9] = "TBD";
				data[i][10] = "";
			}
			var site = parse_url_long(data[i][0]);
			tags.push(site);
			// Dropdown menus
			var a_sub, submenu, submenu_ul;
			if (document.getElementById(data[i][11])===null) {
				submenu = document.createElement("li");
				submenu.setAttribute("id", data[i][11]);
				submenu.classList.add("dropdown-submenu");
				submenu.classList.add("cite-submenu");
				a_sub = document.createElement("a");
				a_sub.innerHTML = data[i][11];
				a_sub.setAttribute('tabindex', '0');
				submenu.appendChild(a_sub);
				submenu_ul = document.createElement("ul");
				submenu_ul.classList.add('dropdown-menu');
				submenu_ul.classList.add('dropdown-auto-overflow')
				submenu.appendChild(submenu_ul);
			}
			else {
				submenu = document.getElementById(data[i][11])
				submenu_ul = submenu.getElementsByTagName('ul')[0];
			}

			// Dropdown options
			var option = document.createElement("li");
			var option_link = document.createElement("a");
			option_link.innerHTML = data[i][4];
			option_link.classList.add("article_option");
			option.appendChild(option_link);
			option.setAttribute("id", site.replace('#', '_').replace('.', '_'));
			option.setAttribute("role", "button");

			if (site===this_site) {
				option.setAttribute("selected", "selected");
				$('#page_select_button').html(data[i][4]);
			}

			submenu_ul.appendChild(option);
			dropdown_articles.appendChild(submenu);

			// Reformat data
			if (!(data[i][5] in articles)) {
				articles[data[i][5]] = {'tools':{}};
				articles[data[i][5]]['tools'][site] = option.innerHTML;
				articles[data[i][5]]['main'] = data[i][3];
				articles[data[i][5]]['authors'] = data[i][6];
				articles[data[i][5]]['year'] = data[i][7];
				articles[data[i][5]]['reference'] = data[i][8];
				articles[data[i][5]]['journal'] = data[i][9];
				articles[data[i][5]]['doi'] = data[i][10];
				articles[data[i][5]]['menu'] = data[i][11];
				if (data[i][3] === "GPCRdb" || data[i][3] === "GproteinDb") {
					main_ref_id.push(site);
				}
			}
			else {
				articles[data[i][5]]['tools'][site] = option.innerHTML;
				if (data[i][3]=="GPCRdb" || data[i][3]=="GproteinDb") {
					main_ref_id.push(site);
				}
			}
		}

		// Create HTML
		for (var key in articles) {
			var main_ref = false
			var entry = document.createElement("ul");
			entry.setAttribute("id", articles[key]['doi']);
			var entry_holder = document.createElement("div");
			var tools_list = document.createElement("div");
			// Loop through tools list to add them with ID
			var selected = false;
			for (var tool_key in articles[key]['tools']) {
				if (tool_key===this_site) {
					selected = true;
				}
				var tool = document.createElement("div");
				tool.innerHTML = articles[key]['tools'][tool_key].bold();
				tool.setAttribute("id", tool_key.replace('#', '_').replace('.', '_')+'_tag');
				tool.style.display = 'none';
				tools_list.appendChild(tool);
				// var separator = document.createElement("div");
				// separator.innerHTML = '\u00A0•\u00A0';
				// separator.style.display = 'inline-block';
				// tools_list.appendChild(separator);
				if (main_ref_id.includes(tool_key)) {
					main_ref = true;
				}
			}
			// tools_list.removeChild(tools_list.lastChild);
			tools_list.style.display = 'block';

			var ref = document.createElement("div");
			var p = document.createElement("p");
			var d1 = document.createElement("div");
			var d2 = document.createElement("div");
			var d3 = document.createElement("div");
			d1.innerHTML = key;
			d2.innerHTML = articles[key]['authors'];

			// Link
			var a = document.createElement("a");
			a.innerHTML = articles[key]['journal'].italics() + ", " + articles[key]['year'] + ", " + articles[key]['reference'];
  			a.title = key;
  			a.href = "https://doi.org/"+articles[key]['doi'];
  			a.target = "_blank";
  			d3.appendChild(a);
			p.appendChild(d1);
			p.appendChild(d2);
			p.appendChild(d3);
			ref.appendChild(p);
			ref.style.display = 'block';

			entry_holder.appendChild(tools_list);
			entry_holder.appendChild(ref);
			entry.appendChild(entry_holder);
			entry.classList.add('article');
			if (selected) {
				entry.classList.add('highlight_reference');
			}
			if (main_ref) {
				var main_ref_list = document.getElementById("main_reference");

				main_ref_list.appendChild(entry);
			}
			else {
				article_list.appendChild(entry);
			}
		}
		if (env=="gproteindb.org") {
			main_ref_id = main_ref_id[0];
		}
		else {
			main_ref_id = main_ref_id[1];
		}
		var color = "#BE00BE";
		if (filter_for==="gproteindb") {
			color = "#F46615";
		}
		else if (filter_for==="arrestindb") {
			color = "#55AE35";
		}
		$(".article").first().css("border-top","4px solid "+color);
		// $(".article").eq(1).css("border-top","4px solid #BE00BE");
		if (highlight_main || $('.highlight_reference').length==0) {
			highlight_article(main_ref_id);
			$('#dropdown_articles option#'+main_ref_id).attr('selected', 'selected');
		}
    };
    cit_request.send();
}

function highlight_article(key) {
	$('.highlight_reference').removeClass('highlight_reference');
	$('#'+key+'_tag').parent().parent().parent().addClass('highlight_reference');
}

function parse_url(url) {
	var url_split = url.split('/');
	if (url_split[url_split.length-1]==="") {
    	var this_site = url_split[url_split.length-2];
    	if (this_site==='targetselection') {
    		this_site = url_split[url_split.length-3]+'-'+this_site;
    	}
    }
    else {
    	var this_site = url_split[url_split.length-1];
    	if (this_site==='targetselection') {
    		this_site = url_split[url_split.length-2]+'-'+this_site;
    	}
    }
    return this_site
}

function parse_url_long(url) {
	var url_split = url.split('/');
	if (url_split[url_split.length-1]==="") {
		if (url_split.length>5) {
			return url_split[3]+"-"+url_split[4];
		}
		else {
			return url_split[3];
		}
	}
	else if (url_split.length===4) {
		return url_split[3];
	}
	else {
		return url_split[3]+"-"+url_split[4];
	}
}

function toggle_widget() {
	$("#ref_widget").animate({width: "toggle"});
    if ($("#widget_chevron").hasClass("glyphicon glyphicon-chevron-left")) {
        $("#widget_chevron").removeClass("glyphicon glyphicon-chevron-left");
        $("#widget_chevron").addClass("glyphicon glyphicon-chevron-right");
        $("#widget_infosign").show();
    }
    else {
        $("#widget_chevron").removeClass("glyphicon glyphicon-chevron-right");
        $("#widget_chevron").addClass("glyphicon glyphicon-chevron-left");
        $("#widget_infosign").hide();
        setTimeout(function() {
        	$("#ref_widget").animate({width: "toggle"});
        	$("#widget_chevron").removeClass("glyphicon glyphicon-chevron-left");
        	$("#widget_chevron").addClass("glyphicon glyphicon-chevron-right");
        	$("#widget_infosign").show();
        }, 8000)
    }
}

async function check_for_video(url) {
	var this_site = parse_url_long(url);
	var cit_request = new XMLHttpRequest();
    cit_request.open('GET', url.split('/')[0] + '/citations');
    cit_request.onload = function() {
		var data = JSON.parse(cit_request.responseText)
		var video = false;
		for (i = 0; i < data.length; i++) {
			var site = parse_url_long(data[i][0]);
			if (site===this_site && data[i][1]!=null) {
				video = data[i][1];
				$('#icon_video').attr('href', video);
				$('#icon_video').css('display','inline');
			}
		}
	}
	cit_request.send();
}
<commit_msg>FIX: update citation tool for BSA<commit_after>function citation_tool(url, cite_id) {
	// Modal part
	$('#citation_modal_table tbody').empty();
    var modal = document.getElementById('citation-tool');
    var span = document.getElementById("close-citation");
    modal.classList.add("modal");
    setTimeout(function(){
    	modal.style.display = "block";
    }, 200)

    span.onclick = function() {
        modal.style.display = "none";
        $(".article_option").remove();
        $(".article").remove();
        $(".cite-submenu").remove();
    }
    window.onclick = function(event) {
        if (event.target == modal) {
            modal.style.display = "none";
            $(".article_option").remove();
            $(".article").remove();
            $(".cite-submenu").remove();
        }
    }

    // Process location
    var this_site = parse_url_long(url);
    var highlight_main = false;
    if (window.location.pathname==='/') {
    	highlight_main = true
    }

    // AJAX to create citation list
    var dropdown_articles = document.getElementById("dropdown_articles");
    var article_list = document.getElementById("article_list");
    var env = url.split('//')[1].split('/')[0];
    var main_ref_id = [];
    var cit_request = new XMLHttpRequest();
    var domains = ["gpcrdb.org", "gproteindb.org", "arrestindb.org", "biasedsignalingatlas.org"];
    var filter_for = false;
    if (env==="gpcrdb.org" || cite_id==="cite_gpcrdb") {
    	filter_for = "gpcrdb";
    }
    else if (env==="gproteindb.org" || cite_id==="cite_gproteindb") {
    	filter_for = "gproteindb";
    }
    else if (env==="arrestindb.org" || cite_id==="cite_arrestindb") {
    	filter_for = "arrestindb";
    }
    else if (env==="biasedsignalingatlas.org" || cite_id==="cite_biasedsignalingatlas") {
    	filter_for = "biasedsignalingatlas";
    }
    cit_request.open('GET', url.split('/')[0] + '/citations');
    cit_request.onload = function() {
		var data = JSON.parse(cit_request.responseText)
		for (let i = 0; i < data.length; i++) {
			var link = "";
			if (!domains.includes(env)) {
				link = "/" + data[i][0].split("//")[1].split("/").slice(1).join("/");
			}
			else {
				link = data[i][0];
			}
			if (link[link.length-1]==='/') {
				link = link.substring(0, link.length-1);
			}
			if (link==='/GPCR-Gprotein_Mutations.xlsx') {
				link = 'https://files.gpcrdb.org/GPCR-Gprotein_Mutations.xlsx'
			}
			else if (link==='/mutations.html#mutation-data-submission') {
				link = 'https://docs.gpcrdb.org/mutations.html#mutation-data-submission'
			}
			if ($('a[href="'+link+'"]').first().parent().parent().parent().first().hasClass('dropdown-submenu')) {
				data[i].push($('a[href="'+link+'"]').first().parent().parent().parent().parent().parent().first().find(">:first-child").text().trim());
			}
			else {
				if (link==="/protein/ste2_yeast") {
					data[i].push("GPCRdb");
				}
				else {
					data[i].push($('a[href="'+link+'"]').first().parent().parent().parent().first().find(">:first-child").text().trim());
				}
			}
		}
		// Create HTML once per call
		var articles = {};
		var tags = [];
		for (let i = 0; i < data.length; i++) {
			if (data[i][11]==='') {
				continue;
			}
			if (filter_for==="gpcrdb" && data[i][11]!=="GPCRdb") {
				continue;
			}
			else if (filter_for==="gproteindb" && data[i][11]!=="GproteinDb") {
				continue;
			}
			else if (filter_for==="arrestindb" && data[i][11]!=="ArrestinDb") {
				continue;
			}
			else if (filter_for==="biasedsignalingatlas" && data[i][11]!=="Biased Signaling Atlas") {
				continue;
			}
			else if (filter_for==="arrestindb" && data[i][11]==="ArrestinDb") {
				data[i][5] = "The arrestin database, ArrestinDb";
				data[i][6] = "Jimmy Caroli, Gáspár Pándy-Szekeres, Alexander S. Hauser, György M. Keserű, Albert J. Kooistra and David E. Gloriam";
				data[i][7] = 2022;
				data[i][8] = "";
				data[i][9] = "Manuscript";
				data[i][10] = "";
			}
			else if (filter_for==="biasedsignalingatlas" && data[i][11]==="Biased Signaling Atlas") {
				data[i][5] = "An Online Biased Signaling Atlas";
				data[i][6] = "Jimmy Caroli, Alibek Mamyrbekov, Kasper Harpsøe, Sahar Gardizi, Linda Dörries, Eshan Ghosh, Alexander S. Hauser, Albert J. Kooistra, and David E. Gloriam";
				data[i][7] = 2022;
				data[i][8] = "";
				data[i][9] = "Manuscript";
				data[i][10] = "";
			}
			var site = parse_url_long(data[i][0]);
			tags.push(site);
			// Dropdown menus
			var a_sub, submenu, submenu_ul;
			if (document.getElementById(data[i][11])===null) {
				submenu = document.createElement("li");
				submenu.setAttribute("id", data[i][11]);
				submenu.classList.add("dropdown-submenu");
				submenu.classList.add("cite-submenu");
				a_sub = document.createElement("a");
				a_sub.innerHTML = data[i][11];
				a_sub.setAttribute('tabindex', '0');
				submenu.appendChild(a_sub);
				submenu_ul = document.createElement("ul");
				submenu_ul.classList.add('dropdown-menu');
				submenu_ul.classList.add('dropdown-auto-overflow')
				submenu.appendChild(submenu_ul);
			}
			else {
				submenu = document.getElementById(data[i][11])
				submenu_ul = submenu.getElementsByTagName('ul')[0];
			}

			// Dropdown options
			var option = document.createElement("li");
			var option_link = document.createElement("a");
			option_link.innerHTML = data[i][4];
			option_link.classList.add("article_option");
			option.appendChild(option_link);
			option.setAttribute("id", site.replace('#', '_').replace('.', '_'));
			option.setAttribute("role", "button");

			if (site===this_site) {
				option.setAttribute("selected", "selected");
				$('#page_select_button').html(data[i][4]);
			}

			submenu_ul.appendChild(option);
			dropdown_articles.appendChild(submenu);

			// Reformat data
			if (!(data[i][5] in articles)) {
				articles[data[i][5]] = {'tools':{}};
				articles[data[i][5]]['tools'][site] = option.innerHTML;
				articles[data[i][5]]['main'] = data[i][3];
				articles[data[i][5]]['authors'] = data[i][6];
				articles[data[i][5]]['year'] = data[i][7];
				articles[data[i][5]]['reference'] = data[i][8];
				articles[data[i][5]]['journal'] = data[i][9];
				articles[data[i][5]]['doi'] = data[i][10];
				articles[data[i][5]]['menu'] = data[i][11];
				if (data[i][3] === "GPCRdb" || data[i][3] === "GproteinDb") {
					main_ref_id.push(site);
				}
			}
			else {
				articles[data[i][5]]['tools'][site] = option.innerHTML;
				if (data[i][3]=="GPCRdb" || data[i][3]=="GproteinDb") {
					main_ref_id.push(site);
				}
			}
		}

		// Create HTML
		for (var key in articles) {
			var main_ref = false
			var entry = document.createElement("ul");
			entry.setAttribute("id", articles[key]['doi']);
			var entry_holder = document.createElement("div");
			var tools_list = document.createElement("div");
			// Loop through tools list to add them with ID
			var selected = false;
			for (var tool_key in articles[key]['tools']) {
				if (tool_key===this_site) {
					selected = true;
				}
				var tool = document.createElement("div");
				tool.innerHTML = articles[key]['tools'][tool_key].bold();
				tool.setAttribute("id", tool_key.replace('#', '_').replace('.', '_')+'_tag');
				tool.style.display = 'none';
				tools_list.appendChild(tool);
				// var separator = document.createElement("div");
				// separator.innerHTML = '\u00A0•\u00A0';
				// separator.style.display = 'inline-block';
				// tools_list.appendChild(separator);
				if (main_ref_id.includes(tool_key)) {
					main_ref = true;
				}
			}
			// tools_list.removeChild(tools_list.lastChild);
			tools_list.style.display = 'block';

			var ref = document.createElement("div");
			var p = document.createElement("p");
			var d1 = document.createElement("div");
			var d2 = document.createElement("div");
			var d3 = document.createElement("div");
			d1.innerHTML = key;
			d2.innerHTML = articles[key]['authors'];

			// Link
			var a = document.createElement("a");
			a.innerHTML = articles[key]['journal'].italics() + ", " + articles[key]['year'] + ", " + articles[key]['reference'];
  			a.title = key;
  			a.href = "https://doi.org/"+articles[key]['doi'];
  			a.target = "_blank";
  			d3.appendChild(a);
			p.appendChild(d1);
			p.appendChild(d2);
			p.appendChild(d3);
			ref.appendChild(p);
			ref.style.display = 'block';

			entry_holder.appendChild(tools_list);
			entry_holder.appendChild(ref);
			entry.appendChild(entry_holder);
			entry.classList.add('article');
			if (selected) {
				entry.classList.add('highlight_reference');
			}
			if (main_ref) {
				var main_ref_list = document.getElementById("main_reference");

				main_ref_list.appendChild(entry);
			}
			else {
				article_list.appendChild(entry);
			}
		}
		if (env=="gproteindb.org") {
			main_ref_id = main_ref_id[0];
		}
		else {
			main_ref_id = main_ref_id[1];
		}
		var color = "#BE00BE";
		if (filter_for==="gproteindb") {
			color = "#F46615";
		}
		else if (filter_for==="arrestindb") {
			color = "#55AE35";
		}
		$(".article").first().css("border-top","4px solid "+color);
		// $(".article").eq(1).css("border-top","4px solid #BE00BE");
		if (highlight_main || $('.highlight_reference').length==0) {
			highlight_article(main_ref_id);
			$('#dropdown_articles option#'+main_ref_id).attr('selected', 'selected');
		}
    };
    cit_request.send();
}

function highlight_article(key) {
	$('.highlight_reference').removeClass('highlight_reference');
	$('#'+key+'_tag').parent().parent().parent().addClass('highlight_reference');
}

function parse_url(url) {
	var url_split = url.split('/');
	if (url_split[url_split.length-1]==="") {
    	var this_site = url_split[url_split.length-2];
    	if (this_site==='targetselection') {
    		this_site = url_split[url_split.length-3]+'-'+this_site;
    	}
    }
    else {
    	var this_site = url_split[url_split.length-1];
    	if (this_site==='targetselection') {
    		this_site = url_split[url_split.length-2]+'-'+this_site;
    	}
    }
    return this_site
}

function parse_url_long(url) {
	var url_split = url.split('/');
	if (url_split[url_split.length-1]==="") {
		if (url_split.length>5) {
			return url_split[3]+"-"+url_split[4];
		}
		else {
			return url_split[3];
		}
	}
	else if (url_split.length===4) {
		return url_split[3];
	}
	else {
		return url_split[3]+"-"+url_split[4];
	}
}

function toggle_widget() {
	$("#ref_widget").animate({width: "toggle"});
    if ($("#widget_chevron").hasClass("glyphicon glyphicon-chevron-left")) {
        $("#widget_chevron").removeClass("glyphicon glyphicon-chevron-left");
        $("#widget_chevron").addClass("glyphicon glyphicon-chevron-right");
        $("#widget_infosign").show();
    }
    else {
        $("#widget_chevron").removeClass("glyphicon glyphicon-chevron-right");
        $("#widget_chevron").addClass("glyphicon glyphicon-chevron-left");
        $("#widget_infosign").hide();
        setTimeout(function() {
        	$("#ref_widget").animate({width: "toggle"});
        	$("#widget_chevron").removeClass("glyphicon glyphicon-chevron-left");
        	$("#widget_chevron").addClass("glyphicon glyphicon-chevron-right");
        	$("#widget_infosign").show();
        }, 8000)
    }
}

async function check_for_video(url) {
	var this_site = parse_url_long(url);
	var cit_request = new XMLHttpRequest();
    cit_request.open('GET', url.split('/')[0] + '/citations');
    cit_request.onload = function() {
		var data = JSON.parse(cit_request.responseText)
		var video = false;
		for (i = 0; i < data.length; i++) {
			var site = parse_url_long(data[i][0]);
			if (site===this_site && data[i][1]!=null) {
				video = data[i][1];
				$('#icon_video').attr('href', video);
				$('#icon_video').css('display','inline');
			}
		}
	}
	cit_request.send();
}
<|endoftext|>


<commit_before>define(
    'imcms-link-validator-tab-builder',
    ['imcms-super-admin-tab', 'imcms-i18n-texts', 'imcms-components-builder',
        'imcms-field-wrapper', 'imcms-bem-builder', 'jquery', 'imcms-link-validator-rest-api'],
    function (SuperAdminTab, texts, components, fieldWrapper, BEM, $, linksValidatorRestApi) {

        texts = texts.superAdmin.linkValidator;

        let $startIdInput;
        let $endIdInput;
        let $filterBrokenLinks;
        let $resultContainer;

        function showOnlyBrokenLinks() {

        }

        function buildTitleText() {
            return fieldWrapper.wrap(components.texts.titleText('<div>', texts.name))
        }

        function buildFilterOnlyBrokenLinks() {
            return $filterBrokenLinks = components.checkboxes.imcmsCheckbox('<div>', {
                text: texts.titleOnlyBrokenLinks,
                click: showOnlyBrokenLinks
            });
        }

        function buildContainerInputIdsValidation() {

            function buildFieldStartId() {
                return $startIdInput = components.texts.textNumber('<div>', {
                    text: texts.titleStartId,
                });
            }

            function buildFieldEndId() {
                return $endIdInput = components.texts.textNumber('<div>', {
                    text: texts.titleEndId,
                });
            }

            var linkListBuilder = function ($searchResultContainer) {
                this.$searchResultContainer = $searchResultContainer;
                this.linkAppender = this.appendLinks.bind(this);
            };

            linkListBuilder.prototype = {
                isEmpty: true,
                clearList: function () {
                    this.$searchResultContainer.empty();
                    this.isEmpty = true;

                    return this;
                },
                linkToRow: function (validationLink) {
                    return new BEM({
                        block: "link-info-row",
                        elements: {
                            'link-page-alias': $('<div>', {
                                text: validationLink.documentData.alias
                            }),
                            'link-status': $('<div>', {
                                text: validationLink.documentData.documentStatus
                            }),
                            'link-type': $('<div>', {
                                text: validationLink.documentData.type
                            }),
                            'link-admin': $('<div>', {
                                text: validationLink.documentData.title
                            }),
                            'link-name': $('<div>', {
                                text: validationLink.url
                            }),
                            'link-host-found': $('<div>', {
                                text: (validationLink.hostFound) ? "V" : "X",
                            }),
                            'link-host-reachable': $('<div>', {
                                text: (validationLink.hostReachable) ? "V" : "X",
                            }),
                            'link-page-found': $('<div>', {
                                text: (validationLink.pageFound) ? "V" : "X",
                            }),
                        }
                    }).buildBlockStructure("<div>");
                },
                prepareTitleRow: function () {
                    let titleRow = new BEM({
                        block: 'table-title-row',
                        elements: {
                            'page-alias': $('<div>', {text: texts.linkInfoRow.pageAlias}),
                            'status': $('<div>', {text: texts.linkInfoRow.status}),
                            'type': $('<div>', {text: texts.linkInfoRow.type}),
                            'admin': $('<div>', {text: texts.linkInfoRow.admin}),
                            'ref': $('<div>', {text: texts.linkInfoRow.reference}),
                            'link': $('<div>', {text: texts.linkInfoRow.link}),
                            'host-found': $('<div>', {text: texts.linkInfoRow.hostFound}),
                            'host-reachable': $('<div>', {text: texts.linkInfoRow.hostReachable}),
                            'page-found': $('<div>', {text: texts.linkInfoRow.pageFound})
                        }
                    }).buildBlockStructure('<div>', {
                        'class': 'table-title'
                    });
                    this.$searchResultContainer.append(titleRow);
                    return this;
                },
                rowsAddToList: function (linkRows) {
                    this.$searchResultContainer.css('display', 'inline-block').append(linkRows);
                    return this;
                },
                appendLinks: function (validationLinks) {
                    this.prepareTitleRow()
                        .rowsAddToList(validationLinks.map(this.linkToRow));
                }
            };

            function listValidationLinks() {
                var linksValidationParams = {
                    filterBrokenLinks: $filterBrokenLinks.isChecked(),
                    startDocumentId: $startIdInput.getInput().val(),
                    endDocumentId: $endIdInput.getInput().val()
                };
                var tableBuilder = new linkListBuilder($resultContainer).clearList();
                linksValidatorRestApi.validate(linksValidationParams).done(tableBuilder.linkAppender);
            }

            function buildButtonValidation() {
                let $button = components.buttons.positiveButton({
                    text: texts.buttonValidation,
                    click: listValidationLinks
                });

                return components.buttons.buttonsContainer('<div>', [$button]);
            }

            return new BEM({
                block: 'link-params-block',
                elements: {
                    'links-field-start': buildFieldStartId(),
                    'links-field-end': buildFieldEndId(),
                    'button-validation': buildButtonValidation()
                }
            }).buildBlockStructure('<div>');
        }

        function buildLinksContainer() {
            return $('<div>', {
                'class': 'table-links',
                style: 'display: none;'
            });
        }

        return new SuperAdminTab(texts.name, [
            buildTitleText(),
            buildFilterOnlyBrokenLinks(),
            buildContainerInputIdsValidation(),
            $resultContainer = buildLinksContainer()
        ]);
    }
);
<commit_msg>IMCMS-334 New design to super admin page: link validator tab - Clean up<commit_after>define(
    'imcms-link-validator-tab-builder',
    ['imcms-super-admin-tab', 'imcms-i18n-texts', 'imcms-components-builder',
        'imcms-field-wrapper', 'imcms-bem-builder', 'jquery', 'imcms-link-validator-rest-api'],
    function (SuperAdminTab, texts, components, fieldWrapper, BEM, $, linksValidatorRestApi) {

        texts = texts.superAdmin.linkValidator;

        let $startIdInput;
        let $endIdInput;
        let $filterBrokenLinks;
        let $resultContainer;

        function showOnlyBrokenLinks() {

        }

        function buildTitleText() {
            return fieldWrapper.wrap(components.texts.titleText('<div>', texts.name))
        }

        function buildFilterOnlyBrokenLinks() {
            return $filterBrokenLinks = components.checkboxes.imcmsCheckbox('<div>', {
                text: texts.titleOnlyBrokenLinks,
                click: showOnlyBrokenLinks
            });
        }

        function buildContainerInputIdsValidation() {

            function buildFieldStartId() {
                return $startIdInput = components.texts.textNumber('<div>', {
                    text: texts.titleStartId,
                });
            }

            function buildFieldEndId() {
                return $endIdInput = components.texts.textNumber('<div>', {
                    text: texts.titleEndId,
                });
            }

            var linkListBuilder = function ($searchResultContainer) {
                this.$searchResultContainer = $searchResultContainer;
                this.linkAppender = this.appendLinks.bind(this);
            };

            linkListBuilder.prototype = {
                isEmpty: true,
                clearList: function () {
                    this.$searchResultContainer.empty();
                    this.isEmpty = true;

                    return this;
                },
                linkToRow: function (validationLink) {
                    return new BEM({
                        block: "link-info-row",
                        elements: {
                            'link-page-alias': $('<div>', {
                                text: validationLink.documentData.alias
                            }),
                            'link-status': $('<div>', {
                                text: validationLink.documentData.documentStatus
                            }),
                            'link-type': $('<div>', {
                                text: validationLink.documentData.type
                            }),
                            'link-admin': $('<div>', {
                                text: validationLink.documentData.title
                            }),
                            'link-name': $('<div>', {
                                text: validationLink.url
                            }),
                            'link-host-found': validationLink.hostFound
                                ? components.controls.check().hover()
                                : components.controls.remove(),
                            'link-host-reachable': validationLink.hostReachable
                                ? components.controls.check()
                                : components.controls.remove(),
                            'link-page-found': validationLink.pageFound
                                ? components.controls.check()
                                : components.controls.remove()
                        }
                    }).buildBlockStructure("<div>");
                },
                prepareTitleRow: function () {
                    let titleRow = new BEM({
                        block: 'table-title-row',
                        elements: {
                            'page-alias': $('<div>', {text: texts.linkInfoRow.pageAlias}),
                            'status': $('<div>', {text: texts.linkInfoRow.status}),
                            'type': $('<div>', {text: texts.linkInfoRow.type}),
                            'admin': $('<div>', {text: texts.linkInfoRow.admin}),
                            //'ref': $('<div>', {text: texts.linkInfoRow.reference}),
                            'link': $('<div>', {text: texts.linkInfoRow.link}),
                            'host-found': $('<div>', {text: texts.linkInfoRow.hostFound}),
                            'host-reachable': $('<div>', {text: texts.linkInfoRow.hostReachable}),
                            'page-found': $('<div>', {text: texts.linkInfoRow.pageFound})
                        }
                    }).buildBlockStructure('<div>', {
                        'class': 'table-title'
                    });
                    this.$searchResultContainer.append(titleRow);
                    return this;
                },
                rowsAddToList: function (linkRows) {
                    this.$searchResultContainer.css('display', 'inline-block').append(linkRows);
                    return this;
                },
                appendLinks: function (validationLinks) {
                    this.prepareTitleRow()
                        .rowsAddToList(validationLinks.map(this.linkToRow));
                }
            };

            function listValidationLinks() {
                var linksValidationParams = {
                    filterBrokenLinks: $filterBrokenLinks.isChecked(),
                    startDocumentId: $startIdInput.getInput().val(),
                    endDocumentId: $endIdInput.getInput().val()
                };
                var tableBuilder = new linkListBuilder($resultContainer).clearList();
                linksValidatorRestApi.validate(linksValidationParams).done(tableBuilder.linkAppender);
            }

            function buildButtonValidation() {
                let $button = components.buttons.positiveButton({
                    text: texts.buttonValidation,
                    click: listValidationLinks
                });

                return components.buttons.buttonsContainer('<div>', [$button]);
            }

            return new BEM({
                block: 'link-params-block',
                elements: {
                    'links-field-start': buildFieldStartId(),
                    'links-field-end': buildFieldEndId(),
                    'button-validation': buildButtonValidation()
                }
            }).buildBlockStructure('<div>');
        }

        function buildLinksContainer() {
            return $('<div>', {
                'class': 'table-links',
                style: 'display: none;'
            });
        }

        return new SuperAdminTab(texts.name, [
            buildTitleText(),
            buildFilterOnlyBrokenLinks(),
            buildContainerInputIdsValidation(),
            $resultContainer = buildLinksContainer()
        ]);
    }
);
<|endoftext|>


<commit_before>import { ServerClient } from './serverclient.js';

/**
 * Represents the URLSearchParams of the
 * the client is in, holds information such as the
 * session ID and the screen name of the current user.
 * @type {URLSearchParams}
 */
const urlParameters = new URLSearchParams(window.location.search);

/**
 * Represents the ServerClient object responsible for
 * keeping up-to-date with the current session and handles many
 * of the client-to-server interactions, like passing the controller.
 * @type {ServerClient}
 */
const client = new ServerClient(urlParameters);

/**
 * This waits until the webpage loads and then it calls the
 * anonymous function, which calls main.
 */
window.onload = function() { main(); }

/**
 * function main() connects the client to a session and begins many of
 * the behind the scenes operations, like caching.
 */
function main() {
  addOnClickListenerToElements();
}

/**
 * Adds an onclick event listener to some of the elements on the
 * in-session webpage.
 */
function addOnClickListenerToElements() {
  document.getElementById('session-info-span').addEventListener('click',
      openSessionInfo);
  document.querySelectorAll('.close').forEach(element => {
    element.addEventListener('click', event => {
      closeParentDisplay(event.target);
    });
  });
  document.querySelectorAll('.session-id-input').forEach(element => {
    element.addEventListener('click', event => {
      copyTextToClipboard(event.target);
    });
  });
}

/**
 * function buildAttendeeDiv() adds the div element containing
 * all the elements representing an attendee to the session info
 * attendees div.
 * @param {string} nameOfAttendee name of attendee to build
 * @param {string} controller name of the controller of the session
 */
function buildAttendeeDiv(nameOfAttendee, controller) {
  const /** HTMLElement */ sessionInfoAttendeesDiv =
      document.getElementById('session-info-attendees');
  const /** HTMLDivElement */ attendeeDiv = document.createElement('div');
  attendeeDiv.className = 'attendee-div'
  const /** HTMLSpanElement */ controllerToggle =
      document.createElement('span');
  controllerToggle.className = 'controller-toggle';
  controllerToggle.addEventListener('click', event => {
    changeControllerTo(event, controller);
  }, /**AddEventListenerOptions=*/false);
  const /** HTMLHeadingElement */ attendeeName =
      document.createElement('h3');
  attendeeName.innerHTML = nameOfAttendee;
  attendeeName.className = 'attendee-name'
  attendeeName.id = nameOfAttendee;
  attendeeDiv.appendChild(controllerToggle);
  attendeeDiv.appendChild(attendeeName);
  sessionInfoAttendeesDiv.appendChild(attendeeDiv);
}

/**
 * If the current controller of the session clicks on the controller
 * toggle, their controller status is revoked and the server is updated
 * with information on the new controller.
 * @param {MouseEvent} event the event that captures what was clicked on
 * @param {string} controller name of the controller of the session
 */
function changeControllerTo(event, controller) {
  if (urlParameters.get('name') === controller) {
    try {
      client.changeControllerTo(/**newControllerName=*/
          event.target.parentElement.querySelector('h3').id);
    } catch (e) {
      window.alert('No contact with the server!');
    }
  }
}
/**
 * function openSessionInfo() displays the div container
 * that has information about the session.
 */
function openSessionInfo() {
  document.getElementById('session-info-div').style.display = 'block';
}

/**
 * function closeParentDisplay() changes the display of the
 * parent of the element passed in to 'none'.
 * @param {HTMLElement} element
 */
function closeParentDisplay(element) {
  element.parentElement.style.display = 'none';
}

/**
 * function copyTextToClipboard() copies the text of the element passed
 * in into the clipboard.
 * @param {HTMLInputElement} element
 */
function copyTextToClipboard(element) {
  element.select();
  document.execCommand('copy');
}

export { openSessionInfo, closeParentDisplay, copyTextToClipboard,
  addOnClickListenerToElements, buildAttendeeDiv, changeControllerTo };
<commit_msg>Changes urlParamert and client<commit_after>import { ServerClient } from './serverclient.js';

/**
 * Represents the URLSearchParams the client is in,
 * holds information such as the session ID and
 * the screen name of the current user.
 * @type {URLSearchParams}
 */
let urlParameters;

/**
 * Represents the ServerClient object responsible for
 * keeping up-to-date with the current session and handles many
 * of the client-to-server interactions, like changing the controller.
 * @type {ServerClient}
 */
let client;

/**
 * This waits until the webpage loads and then it calls the
 * anonymous function, which calls main.
 */
window.onload = function() { main(); }

/**
 * function main() connects the client to a session and begins many of
 * the behind the scenes operations, like caching.
 */
function main() {
  urlParameters = new URLSearchParams(window.location.search);
  client = new ServerClient(urlParameters);
  addOnClickListenerToElements();
}

/**
 * Adds an onclick event listener to some of the elements on the
 * in-session webpage.
 */
function addOnClickListenerToElements() {
  document.getElementById('session-info-span').addEventListener('click',
      openSessionInfo);
  document.querySelectorAll('.close').forEach(element => {
    element.addEventListener('click', event => {
      closeParentDisplay(event.target);
    });
  });
  document.querySelectorAll('.session-id-input').forEach(element => {
    element.addEventListener('click', event => {
      copyTextToClipboard(event.target);
    });
  });
}

/**
 * function buildAttendeeDiv() adds the div element containing
 * all the elements representing an attendee to the session info
 * attendees div.
 * @param {string} nameOfAttendee name of attendee to build
 * @param {string} controller name of the controller of the session
 */
function buildAttendeeDiv(nameOfAttendee, controller) {
  const /** HTMLElement */ sessionInfoAttendeesDiv =
      document.getElementById('session-info-attendees');
  const /** HTMLDivElement */ attendeeDiv = document.createElement('div');
  attendeeDiv.className = 'attendee-div'
  const /** HTMLSpanElement */ controllerToggle =
      document.createElement('span');
  controllerToggle.className = 'controller-toggle';
  controllerToggle.addEventListener('click', event => {
    changeControllerTo(event, controller);
  }, /**AddEventListenerOptions=*/false);
  const /** HTMLHeadingElement */ attendeeName =
      document.createElement('h3');
  attendeeName.innerHTML = nameOfAttendee;
  attendeeName.className = 'attendee-name'
  attendeeName.id = nameOfAttendee;
  attendeeDiv.appendChild(controllerToggle);
  attendeeDiv.appendChild(attendeeName);
  sessionInfoAttendeesDiv.appendChild(attendeeDiv);
}

/**
 * If the current controller of the session clicks on the controller
 * toggle, their controller status is revoked and the server is updated
 * with information on the new controller.
 * @param {MouseEvent} event the event that captures what was clicked on
 * @param {string} controller name of the controller of the session
 */
function changeControllerTo(event, controller) {
  if (urlParameters.get('name') === controller) {
    try {
      client.changeControllerTo(/**newControllerName=*/
          event.target.parentElement.querySelector('h3').id);
    } catch (e) {
      window.alert('No contact with the server!');
    }
  }
}
/**
 * function openSessionInfo() displays the div container
 * that has information about the session.
 */
function openSessionInfo() {
  document.getElementById('session-info-div').style.display = 'block';
}

/**
 * function closeParentDisplay() changes the display of the
 * parent of the element passed in to 'none'.
 * @param {HTMLElement} element
 */
function closeParentDisplay(element) {
  element.parentElement.style.display = 'none';
}

/**
 * function copyTextToClipboard() copies the text of the element passed
 * in into the clipboard.
 * @param {HTMLInputElement} element
 */
function copyTextToClipboard(element) {
  element.select();
  document.execCommand('copy');
}

export { openSessionInfo, closeParentDisplay, copyTextToClipboard,
  addOnClickListenerToElements, buildAttendeeDiv, changeControllerTo };
<|endoftext|>


<commit_before>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2012 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*  generic pattern: hook  */
$cs.pattern.hook = $cs.trait({
    mixin: [
        $cs.pattern.eventing
    ],
    protos: {
        /*  latch into a hook  */
        latch: function () {
            /*  determine parameters  */
            var params = $cs.params("latch", arguments, {
                name:   { pos: 0,     def: null,    req: true },
                ctx:    {             def: this               },
                func:   { pos: 1,     def: $cs.nop, req: true },
                args:   { pos: "...", def: []                 }
            });

            /*  subscribe to hook event  */
            var id = this.subscribe({
                name: "hook." + params.name,
                ctx:  params.ctx,
                func: params.func,
                args: params.args
            });

            return id;
        },

        /*  notch from a hook  */
        notch: function () {
            /*  determine parameters  */
            var params = $cs.params("notch", arguments, {
                id: { pos: 0, req: true }
            });

            /*  unsubsribe from hook event  */
            this.unsubscribe(params.id);
        },

        /*  perform the hook  */
        hook: function () {
            /*  determine parameters  */
            var params = $cs.params("hook", arguments, {
                name:   { pos: 0,     def: null,  req: true },
                args:   { pos: "...", def: []               }
            });

            /*  dispatch hook event onto target component  */
            this.publish({
                name: "hook." + params.name,
                args: params.args,
                capturing: false,
                bubbling: false,
                async: false
            });
        }
    }
});

<commit_msg>use direct result for hooks<commit_after>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2012 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*  generic pattern: hook  */
$cs.pattern.hook = $cs.trait({
    mixin: [
        $cs.pattern.eventing
    ],
    protos: {
        /*  latch into a hook  */
        latch: function () {
            /*  determine parameters  */
            var params = $cs.params("latch", arguments, {
                name:   { pos: 0,     def: null,    req: true },
                ctx:    {             def: this               },
                func:   { pos: 1,     def: $cs.nop, req: true },
                args:   { pos: "...", def: []                 }
            });

            /*  subscribe to hook event  */
            var id = this.subscribe({
                name: "hook." + params.name,
                ctx:  params.ctx,
                func: params.func,
                args: params.args
            });

            return id;
        },

        /*  notch from a hook  */
        notch: function () {
            /*  determine parameters  */
            var params = $cs.params("notch", arguments, {
                id: { pos: 0, req: true }
            });

            /*  unsubsribe from hook event  */
            this.unsubscribe(params.id);
        },

        /*  perform the hook  */
        hook: function () {
            /*  determine parameters  */
            var params = $cs.params("hook", arguments, {
                name:   { pos: 0,     def: null,  req: true },
                args:   { pos: "...", def: []               }
            });

            /*  dispatch hook event onto target component  */
            this.publish({
                name: "hook." + params.name,
                args: params.args,
                capturing: false,
                bubbling: false,
                async: false,
                directresult: true
            });
        }
    }
});

<|endoftext|>


<commit_before>/**
 * This is the entry point for the Narrative's front-end. It initializes
 * the login session, fires up the data and function widgets, and creates
 * the kbaseNarrativeWorkspace wrapper around the IPython notebook that
 * does fun things like manage widgets and cells and kernel events to talk to them.
 */
"use strict";

$('#kb-save-btn').click(function(e) {
    if (IPython && IPython.notebook) {
        var narrName = IPython.notebook.notebook_name;
        // we do not allow users to leave thier narratives untitled
        if (narrName.trim().toLowerCase()==='untitled' || narrName.trim().length === 0) {
            IPython.save_widget.rename_notebook("Please name your Narrative before saving.", false);
        } else {
            IPython.notebook.save_checkpoint();
        }
    }
});
$('#kb-narr-name #name').click(function(e) {
    if (IPython && IPython.save_widget) {
        IPython.save_widget.rename_notebook("Rename your Narrative.", true);
        var narrName = IPython.notebook.notebook_name;
        // this code needs to move to the save widget since rename_notebook is async!!
        //$('#kb-narr-name #name').text(narrName);
    }
});
$('#kb-kernel-int-btn').click(function(e) {
    if (IPython && IPython.notebook && IPython.notebook.kernel) {
        IPython.notebook.kernel.interrupt();
    }
});
$('#kb-kernel-ref-btn').click(function(e) {
    if (IPython && IPython.notebook && IPython.notebook.kernel) {
        IPython.notebook.kernel.restart();
    }
});

(function() {
    var $dataList = $('
');
    var $shareWidget = $dataList["kbaseNarrativeSharePanel"]({});
    $('#kb-share-btn').popover({
        html : true,
        placement : "bottom",
        //title: function() {
        //    return "Share this Narrative & Data";
        //},
        content: function() {
            // we do not allow users to leave thier narratives untitled
            if (IPython && IPython.notebook) {
                var narrName = IPython.notebook.notebook_name;
                if (narrName.trim().toLowerCase()==='untitled' || narrName.trim().length === 0) {
                    IPython.save_widget.rename_notebook("Your Narrative must be named before you can share it with others.", false);
                    return "

Please name your Narrative before sharing.

"
                }
            }

            //!! arg!! I have to refresh to get reattach the events, which are lost when
            //the popover is hidden!!!  makes it a little slower because we refetch permissions from ws each time
            $shareWidget.refresh();
            return $dataList;
        }
    });
})();

/**
 * A fun little idea... but it doesn't really work. We need an actual way to poke at endpoints to see if they're alive.
 * But I'm leaving this in here for now. --Bill
 */
var EndpointTester = function(url, target) {
    this.loadingImage = 'static/kbase/images/ajax-loader.gif';
    this.okayText = 'ok';
    this.downText = 'down';
    this.url = url;
    this.$target = target;
};

EndpointTester.prototype.test = function(url) {
    this.$target.html('');
    var postTestParams = {
        type: 'POST',
        data: '{"params":{}, "version":"1.1", "method":"", "id":"' + Math.random() + '"}',
        url: this.url,
        success: $.proxy(function() { this.$target.html(this.okayText); }, this),
        error: $.proxy(function(error) {
            console.log('error!');
            console.log(error);
            this.$target.html(this.downText);
        }, this),
    };
    var getTestParams = {
        type: 'GET',
        url: this.url,
        success: $.proxy(function() { this.$target.html(this.okayText); }, this),
        error: $.proxy(function(error) {
            $.ajax(postTestParams);
            this.$target.html(this.downText);
        }, this),
    }
    $.ajax(getTestParams);
};

var narrative = {};
narrative.init = function() {
    var narr_ws = null;
    var readonly = false; /* whether whole narrative is read-only */
    var authToken = null;

    $([IPython.events]).on('status_idle.Kernel',function () {
        $("#kb-kernel-icon").removeClass().addClass('fa fa-circle-o');
    });

    $([IPython.events]).on('status_busy.Kernel',function () {
        $("#kb-kernel-icon").removeClass().addClass('fa fa-circle');
    });

    var versionHtml = 'KBase Narrative
Alpha version';
    var endpointTesters = [];
    if (window.kbconfig &&
        window.kbconfig.name &&
        window.kbconfig.version) {
        var $versionDiv = $('
')
                          .append('Version: ' + window.kbconfig.version);
        if (window.kbconfig.git_commit_hash && window.kbconfig.git_commit_time)
            $versionDiv.append('
Git Commit: ' + window.kbconfig.git_commit_hash + ' -- ' + window.kbconfig.git_commit_time);

        // not used, but left in as legacy if we go back to it.
        // $versionInfo = window.kbconfig.name + '
' + window.kbconfig.version;

        if (window.kbconfig.urls) {
            var urlList = Object.keys(window.kbconfig.urls).sort();
            var $versionTable = $('
')
                                .addClass('table table-striped table-bordered');
            $.each(urlList,
                function(idx, val) {
                    var url = window.kbconfig.urls[val].toString();
                    // if url looks like a url (starts with http), include it.
                    if (url && url.toLowerCase().indexOf('http') == 0) {
                        var $testTarget = $('');
                        $versionTable.append($('
')
                                             .append($('').append(val))
                                             .append($('').append(url)));
                        //                      .append($testTarget));
                        // endpointTesters.push(new EndpointTester(url, $testTarget));
                    }
                }
            );
            $versionDiv.append($versionTable);
        }
    }

    var $shutdownButton = $('<button>')
                          .attr({'type':'button', 'data-dismiss':'modal'})
                          .addClass('btn btn-danger')
                          .append('Okay. Shut it all down!')
                          .click(function(e) {
                              var user = 'wjriehl';
                              var prom = $.ajax({
                                  contentType: 'applcation/json',
                                  url: '/narrative_shutdown/' + user,
                                  type: 'DELETE',
                                  crossDomain: true
                              });
                              prom.done(function(jqXHR, response, status) {
                                  setTimeout(function(){window.close();}, 200);
                              });
                              prom.fail(function(jqXHR, response, error) {
                                  alert('Unable to close your Narrative session\nError: ' + jqXHR.status + ' ' + error);
                              });
                          });
    var $reallyShutdownPanel = $('
')
                               .append('This will shutdown your Narrative session and close this window.
Any unsaved data in any open Narrative in any window WILL BE LOST!
')
                               .append($shutdownButton)
                               .hide();

    var $firstShutdownBtn = $('<button>')
                            .attr({'type':'button'})
                            .addClass('btn btn-danger')
                            .append('Shutdown')
                            .click(function(e) {
                                $reallyShutdownPanel.slideDown('fast');
                            });

    var $versionModal = $('
')
                        .addClass('modal fade')
                        .append($('
')
                                .addClass('modal-dialog')
                                .append($('
')
                                    .addClass('modal-content')
                                    .append($('
')
                                            .addClass('modal-header')
                                            .append($('
')
                                                    .addClass('modal-title')
                                                    .attr('id', 'kb-version-label')
                                                    .append('KBase Narrative Properties')))
                                    .append($('
')
                                            .addClass('modal-body')
                                            .append($versionDiv))
                                    .append($('
')
                                            .addClass('modal-footer')
                                            .append($('
')
                                                    .append($('<button type="button" data-dismiss="modal">')
                                                            .addClass('btn btn-default')
                                                            .append('Dismiss')
                                                            .click(function(e) {
                                                                $reallyShutdownPanel.hide();
                                                            }))
                                                    .append($firstShutdownBtn))
                                            .append($reallyShutdownPanel))));

//    var $versionBtn = $('About')
    $('#kb-about-btn').click(function(event) {
                          event.preventDefault();
                          event.stopPropagation();
                          $versionModal.modal('show');
                          for (var i=0; i<endpointTesters.length; i++) {
                              endpointTesters[i].test();
                          }
                      });

//    $('#kb-version-stamp').empty().append($versionBtn);
    $('#notebook').append($versionModal);
    $('[data-toggle="tooltip"]').tooltip()
    /*
     * Before we get everything loading, just grey out the whole %^! page
     */
    var $sidePanel = $('#kb-side-panel').kbaseNarrativeSidePanel({ autorender: false });

    var curCell = null;
    $([IPython.events]).on('select.Cell', function(event, data) {
        if (curCell && data.cell != this.curCell)
            curCell.celltoolbar.hide();
        curCell = data.cell;
        if (!curCell.metadata['kb-cell'])
            curCell.celltoolbar.show();
    });

    /*
     * Once everything else is loaded and the Kernel is idle,
     * Go ahead and fill in the rest of the Javascript stuff.
     */
    $([IPython.events]).one('status_started.Kernel', function() {
        // NAR-271 - Firefox needs to be told where the top of the page is. :P
        window.scrollTo(0,0);

        IPython.notebook.set_autosave_interval(0);
        IPython.CellToolbar.activate_preset("KBase");

        var ws_name = null;
        if (IPython && IPython.notebook && IPython.notebook.metadata) {
            ws_name = IPython.notebook.metadata.ws_name;
            var narrname = IPython.notebook.notebook_name;
            var username = IPython.notebook.metadata.creator;
            $('#kb-narr-name #name').text(narrname);
            $('#kb-narr-creator').text(username);
            $('.kb-narr-namestamp').css({'display':'block'});

            var token = null;
            if (window.kb && window.kb.token)
                token = window.kb.token;

            $.ajax({
                type: 'GET',
                url: 'https://kbase.us/services/genome_comparison/users?usernames=' + username + '&token=' + token,
                dataType: 'json',
                crossDomain: true,
                success: function(data, res, jqXHR) {
                    if (username in data.data && data.data[username].fullName) {
                        var fullName = data.data[username].fullName;
                        $('#kb-narr-creator').text(fullName + ' (' + username + ')');
                    }
                }
            });

        }
        if (ws_name) {
            /* It's ON like DONKEY KONG! */
            $('a#workspace-link').attr('href',
                    $('a#workspace-link').attr('href') +
                    'objects/' + ws_name);
            var narr_ws = $('#notebook_panel').kbaseNarrativeWorkspace({
                loadingImage: "/static/kbase/images/ajax-loader.gif",
                ws_id: IPython.notebook.metadata.ws_name
            });
            $sidePanel.render();
            $(document).trigger('setWorkspaceName.Narrative', {'wsId' : ws_name, 'narrController': narr_ws});
            // $dataWidget.setNarrWs(narr_ws); //as a callback
            // $dataWidget.setWorkspace(ws_name);
            // setTimeout(function() { $jobsWidget.refresh(); }, 750);
        }
        else {
            /* ??? */
        }
    });
};
<commit_msg>Fixed issue with getting user name of Narrative instance to shut down.<commit_after>/**
 * This is the entry point for the Narrative's front-end. It initializes
 * the login session, fires up the data and function widgets, and creates
 * the kbaseNarrativeWorkspace wrapper around the IPython notebook that
 * does fun things like manage widgets and cells and kernel events to talk to them.
 */
"use strict";

$('#kb-save-btn').click(function(e) {
    if (IPython && IPython.notebook) {
        var narrName = IPython.notebook.notebook_name;
        // we do not allow users to leave thier narratives untitled
        if (narrName.trim().toLowerCase()==='untitled' || narrName.trim().length === 0) {
            IPython.save_widget.rename_notebook("Please name your Narrative before saving.", false);
        } else {
            IPython.notebook.save_checkpoint();
        }
    }
});
$('#kb-narr-name #name').click(function(e) {
    if (IPython && IPython.save_widget) {
        IPython.save_widget.rename_notebook("Rename your Narrative.", true);
        var narrName = IPython.notebook.notebook_name;
        // this code needs to move to the save widget since rename_notebook is async!!
        //$('#kb-narr-name #name').text(narrName);
    }
});
$('#kb-kernel-int-btn').click(function(e) {
    if (IPython && IPython.notebook && IPython.notebook.kernel) {
        IPython.notebook.kernel.interrupt();
    }
});
$('#kb-kernel-ref-btn').click(function(e) {
    if (IPython && IPython.notebook && IPython.notebook.kernel) {
        IPython.notebook.kernel.restart();
    }
});

(function() {
    var $dataList = $('
');
    var $shareWidget = $dataList["kbaseNarrativeSharePanel"]({});
    $('#kb-share-btn').popover({
        html : true,
        placement : "bottom",
        //title: function() {
        //    return "Share this Narrative & Data";
        //},
        content: function() {
            // we do not allow users to leave thier narratives untitled
            if (IPython && IPython.notebook) {
                var narrName = IPython.notebook.notebook_name;
                if (narrName.trim().toLowerCase()==='untitled' || narrName.trim().length === 0) {
                    IPython.save_widget.rename_notebook("Your Narrative must be named before you can share it with others.", false);
                    return "

Please name your Narrative before sharing.

"
                }
            }

            //!! arg!! I have to refresh to get reattach the events, which are lost when
            //the popover is hidden!!!  makes it a little slower because we refetch permissions from ws each time
            $shareWidget.refresh();
            return $dataList;
        }
    });
})();

/**
 * A fun little idea... but it doesn't really work. We need an actual way to poke at endpoints to see if they're alive.
 * But I'm leaving this in here for now. --Bill
 */
var EndpointTester = function(url, target) {
    this.loadingImage = 'static/kbase/images/ajax-loader.gif';
    this.okayText = 'ok';
    this.downText = 'down';
    this.url = url;
    this.$target = target;
};

EndpointTester.prototype.test = function(url) {
    this.$target.html('');
    var postTestParams = {
        type: 'POST',
        data: '{"params":{}, "version":"1.1", "method":"", "id":"' + Math.random() + '"}',
        url: this.url,
        success: $.proxy(function() { this.$target.html(this.okayText); }, this),
        error: $.proxy(function(error) {
            console.log('error!');
            console.log(error);
            this.$target.html(this.downText);
        }, this),
    };
    var getTestParams = {
        type: 'GET',
        url: this.url,
        success: $.proxy(function() { this.$target.html(this.okayText); }, this),
        error: $.proxy(function(error) {
            $.ajax(postTestParams);
            this.$target.html(this.downText);
        }, this),
    }
    $.ajax(getTestParams);
};

var narrative = {};
narrative.init = function() {
    var narr_ws = null;
    var readonly = false; /* whether whole narrative is read-only */
    var authToken = null;

    $([IPython.events]).on('status_idle.Kernel',function () {
        $("#kb-kernel-icon").removeClass().addClass('fa fa-circle-o');
    });

    $([IPython.events]).on('status_busy.Kernel',function () {
        $("#kb-kernel-icon").removeClass().addClass('fa fa-circle');
    });

    var versionHtml = 'KBase Narrative
Alpha version';
    var endpointTesters = [];
    if (window.kbconfig &&
        window.kbconfig.name &&
        window.kbconfig.version) {
        var $versionDiv = $('
')
                          .append('Version: ' + window.kbconfig.version);
        if (window.kbconfig.git_commit_hash && window.kbconfig.git_commit_time)
            $versionDiv.append('
Git Commit: ' + window.kbconfig.git_commit_hash + ' -- ' + window.kbconfig.git_commit_time);

        // not used, but left in as legacy if we go back to it.
        // $versionInfo = window.kbconfig.name + '
' + window.kbconfig.version;

        if (window.kbconfig.urls) {
            var urlList = Object.keys(window.kbconfig.urls).sort();
            var $versionTable = $('
')
                                .addClass('table table-striped table-bordered');
            $.each(urlList,
                function(idx, val) {
                    var url = window.kbconfig.urls[val].toString();
                    // if url looks like a url (starts with http), include it.
                    if (url && url.toLowerCase().indexOf('http') == 0) {
                        var $testTarget = $('');
                        $versionTable.append($('
')
                                             .append($('').append(val))
                                             .append($('').append(url)));
                        //                      .append($testTarget));
                        // endpointTesters.push(new EndpointTester(url, $testTarget));
                    }
                }
            );
            $versionDiv.append($versionTable);
        }
    }

    var $shutdownButton = $('<button>')
                          .attr({'type':'button', 'data-dismiss':'modal'})
                          .addClass('btn btn-danger')
                          .append('Okay. Shut it all down!')
                          .click(function(e) {
                              var user = $('#signin-button').kbaseLogin('session', 'user_id');
                              var prom = $.ajax({
                                  contentType: 'applcation/json',
                                  url: '/narrative_shutdown/' + user,
                                  type: 'DELETE',
                                  crossDomain: true
                              });
                              prom.done(function(jqXHR, response, status) {
                                  setTimeout(function(){window.close();}, 200);
                              });
                              prom.fail(function(jqXHR, response, error) {
                                  alert('Unable to close your Narrative session\nError: ' + jqXHR.status + ' ' + error);
                              });
                          });
    var $reallyShutdownPanel = $('
')
                               .append('This will shutdown your Narrative session and close this window.
Any unsaved data in any open Narrative in any window WILL BE LOST!
')
                               .append($shutdownButton)
                               .hide();

    var $firstShutdownBtn = $('<button>')
                            .attr({'type':'button'})
                            .addClass('btn btn-danger')
                            .append('Shutdown')
                            .click(function(e) {
                                $reallyShutdownPanel.slideDown('fast');
                            });

    var $versionModal = $('
')
                        .addClass('modal fade')
                        .append($('
')
                                .addClass('modal-dialog')
                                .append($('
')
                                    .addClass('modal-content')
                                    .append($('
')
                                            .addClass('modal-header')
                                            .append($('
')
                                                    .addClass('modal-title')
                                                    .attr('id', 'kb-version-label')
                                                    .append('KBase Narrative Properties')))
                                    .append($('
')
                                            .addClass('modal-body')
                                            .append($versionDiv))
                                    .append($('
')
                                            .addClass('modal-footer')
                                            .append($('
')
                                                    .append($('<button type="button" data-dismiss="modal">')
                                                            .addClass('btn btn-default')
                                                            .append('Dismiss')
                                                            .click(function(e) {
                                                                $reallyShutdownPanel.hide();
                                                            }))
                                                    .append($firstShutdownBtn))
                                            .append($reallyShutdownPanel))));

//    var $versionBtn = $('About')
    $('#kb-about-btn').click(function(event) {
                          event.preventDefault();
                          event.stopPropagation();
                          $versionModal.modal('show');
                          for (var i=0; i<endpointTesters.length; i++) {
                              endpointTesters[i].test();
                          }
                      });

//    $('#kb-version-stamp').empty().append($versionBtn);
    $('#notebook').append($versionModal);
    $('[data-toggle="tooltip"]').tooltip()
    /*
     * Before we get everything loading, just grey out the whole %^! page
     */
    var $sidePanel = $('#kb-side-panel').kbaseNarrativeSidePanel({ autorender: false });

    var curCell = null;
    $([IPython.events]).on('select.Cell', function(event, data) {
        if (curCell && data.cell != this.curCell)
            curCell.celltoolbar.hide();
        curCell = data.cell;
        if (!curCell.metadata['kb-cell'])
            curCell.celltoolbar.show();
    });

    /*
     * Once everything else is loaded and the Kernel is idle,
     * Go ahead and fill in the rest of the Javascript stuff.
     */
    $([IPython.events]).one('status_started.Kernel', function() {
        // NAR-271 - Firefox needs to be told where the top of the page is. :P
        window.scrollTo(0,0);

        IPython.notebook.set_autosave_interval(0);
        IPython.CellToolbar.activate_preset("KBase");

        var ws_name = null;
        if (IPython && IPython.notebook && IPython.notebook.metadata) {
            ws_name = IPython.notebook.metadata.ws_name;
            var narrname = IPython.notebook.notebook_name;
            var username = IPython.notebook.metadata.creator;
            $('#kb-narr-name #name').text(narrname);
            $('#kb-narr-creator').text(username);
            $('.kb-narr-namestamp').css({'display':'block'});

            var token = null;
            if (window.kb && window.kb.token)
                token = window.kb.token;

            $.ajax({
                type: 'GET',
                url: 'https://kbase.us/services/genome_comparison/users?usernames=' + username + '&token=' + token,
                dataType: 'json',
                crossDomain: true,
                success: function(data, res, jqXHR) {
                    if (username in data.data && data.data[username].fullName) {
                        var fullName = data.data[username].fullName;
                        $('#kb-narr-creator').text(fullName + ' (' + username + ')');
                    }
                }
            });

        }
        if (ws_name) {
            /* It's ON like DONKEY KONG! */
            $('a#workspace-link').attr('href',
                    $('a#workspace-link').attr('href') +
                    'objects/' + ws_name);
            var narr_ws = $('#notebook_panel').kbaseNarrativeWorkspace({
                loadingImage: "/static/kbase/images/ajax-loader.gif",
                ws_id: IPython.notebook.metadata.ws_name
            });
            $sidePanel.render();
            $(document).trigger('setWorkspaceName.Narrative', {'wsId' : ws_name, 'narrController': narr_ws});
            // $dataWidget.setNarrWs(narr_ws); //as a callback
            // $dataWidget.setWorkspace(ws_name);
            // setTimeout(function() { $jobsWidget.refresh(); }, 750);
        }
        else {
            /* ??? */
        }
    });
};
<|endoftext|>


<commit_before>/**
 * Copyright 2015, Mapacode Inc.
 */
'use strict';

var _posts = [
    {
        title: 'Botbone 入門',
        md: 'botbone-getting-started.md',
        img: 'botbone.png',
        published: '2015-02-25',
        author: 'Sirius Wu',
        preview: 'BotBone 帶你進自動化及工業 4.0 的世界，你可以透過它學到...'
    },
    {
        title: 'BotBone 教學',
        md: 'botbone-tutorials.md',
        published: '2015-02-25',
        author: 'Sirius Wu',
        preview: '使用 BotBone 的一些小技巧...'
    },
    {
        title: 'Botnana 工業物聯網開發平台',
        md: 'botnana-platform-architecture.md',
        published: '2015-02-25',
        author: 'Sirius Wu',
        preview: 'BotBone 內建的工業物聯網開發環境整合了微型部落格、簡易 SCADA/HMI 以及硬體控制語言 MSL 及其執行環境。'
    }
];

module.exports = _posts;

<commit_msg>CCWU: added blog section.<commit_after>/**
 * Copyright 2015, Mapacode Inc.
 */
'use strict';

var _posts = {
    section: 'tutorials',
    posts: [
        {
            title: 'Botbone 入門',
            md: 'botbone-getting-started.md',
            img: 'botbone.png',
            published: '2015-02-25',
            author: 'Sirius Wu',
            preview: 'BotBone 帶你進自動化及工業 4.0 的世界，你可以透過它學到...'
        },
        {
            title: 'BotBone 教學',
            md: 'botbone-tutorials.md',
            published: '2015-02-25',
            author: 'Sirius Wu',
            preview: '使用 BotBone 的一些小技巧...'
        },
        {
            title: 'Botnana 工業物聯網開發平台',
            md: 'botnana-platform-architecture.md',
            published: '2015-02-25',
            author: 'Sirius Wu',
            preview: 'BotBone 內建的工業物聯網開發環境整合了微型部落格、簡易 SCADA/HMI 以及硬體控制語言 MSL 及其執行環境。'
        }
    ]
};

module.exports = _posts;

<|endoftext|>


<commit_before>(function(win) {
	"use strict";
	var urlData = readURL();

	getFile(urlData, urlData.pathToMeta +'.gh-embed.json', function(d) {
		if(d.error) {
			return error('Cannot load .gh-embed.json: ' + d.error);
		}

		try {
			d = JSON.parse(d);
		} catch(e) {
			return error('Cannot parse .gh-embed.json: ' + e);
		}

		embed(d);

	});

	$('.on-github').href='//github.com/'+urlData.owner+'/'+urlData.repo+'/tree/'+urlData.ref+'/'+urlData.pathToMeta;

	function error(err) {
		$('main').classList.add('error');
		$('.error-text').textContent = err;
	}

    function embed(o) {
		var el = $('main'),
			nav = $('nav'),
			frames = $('.frames'),
			loadedCount = 0,
			hasActive;

		o.embed.forEach(function(item) {
			var frame,
				link;

			item.owner = item.owner || urlData.owner;
			item.repo = item.repo || urlData.repo;
			item.ref = item.ref || urlData.ref;
			item.type = item.type || item.path.match(/.*\.(\S+)$/);

			if(item.type == 'htmlpage') {
				frame = frames.appendChild(create('iframe', {
					src: item.url,
					onload: loaded,
					onerror: loaded,
					className: 'frame'
				}));

				link = nav.appendChild(create('a', {
					innerHTML: item.label || 'HTML Page'
				}));

			} else {
				link = nav.appendChild(create('a', {
					innerHTML: item.label || item.path
				}));

				frame = frames.appendChild(create('pre', {
					className: 'frame'
				}));

				getFile(item, item.path, function(data) {
					frame.classList.add('prettyprint', 'lang-' + item.type);
					if(o.linenums !== false) {
						frame.classList.add('linenums');
					}

					frame.textContent = data.error ? 'Error' : data;

					loaded();
				});
			}

			link.classList.add('l');

			if(item.active && !hasActive) {
				link.classList.add('active');
				frame.classList.add('active');
				hasActive = true;
			}

			link.addEventListener('click', function(evt) {
				var activeLink = $('a.active', nav),
					activeFrame = $('.frame.active', frames)

				if(activeLink) {
					activeLink.classList.remove('active');
				}

				if(activeFrame) {
					activeFrame.classList.remove('active');
				}

				link.classList.add('active');
				frame.classList.add('active');
			});
		});

		if(!hasActive) {
			$('a.l', nav).classList.add('active');
			$('.frame', frames).classList.add('active');
		}

		function loaded() {
			if(++loadedCount == o.embed.length) {
				el.classList.remove('loading');
				prettyPrint();
			}
		}
	}

	function readURL() {
		var loc = document.location,
			path = loc.pathname.match(/\/v(\d+)\/([^\/]+)\/([^\/]+)\/([^\/]+)?/);

		return {
			owner: path[2],
			repo: path[3],
			pathToMeta: path[4] ? (path[4] + '/') : '',
			ref: (loc.search.match(/\S*(\?|&)ref=(\S+)\S*/) || [])[2] || 'master'
		};
	}

	function getFile(data, path, callback) {
		var xhr = new XMLHttpRequest();
		xhr.open('GET', 'https://api.github.com/repos/'+data.owner+'/'+data.repo+'/contents/'+path+'?ref=' + data.ref, true);

		xhr.onload = function() {
			var resp = JSON.parse(xhr.responseText);
			if(resp.content) {
				callback(atob(resp.content));
			} else {
				xhr.onerror();
			}
		}

		// fallback in case if API limmit is exceeded
		xhr.onerror = function() {
			var xhr2 = new XMLHttpRequest();
			xhr2.open('GET', 'https://raw.githubusercontent.com/'+data.owner+'/'+data.repo+'/'+data.ref+'/'+path, true);
			xhr2.onload = function() {
				if(xhr2.status !== 200) {
					callback({ error: xhr2.statusText })
				} else {
					callback(xhr2.responseText);
				}
			}

			xhr2.onerror = function() {
				callback({ error: xhr2.statusText });
			}

			xhr2.send();
		}

		xhr.send();
	}

	function create(tagName, props, el, i, hasOwn) {
		el = document.createElement(tagName);
		hasOwn = 'hasOwnProperty';
		if (props) {
			for (i in props) {
				el[i] = props[i];
			}
		}
		return el;
	};

	function $(s, ctx) {
		return (ctx || document).querySelector(s);
	}
})(window);
<commit_msg>trying to fix error in safari<commit_after>(function(win) {
	"use strict";
	var urlData = readURL();

	getFile(urlData, urlData.pathToMeta +'.gh-embed.json', function(d) {
		if(d.error) {
			return error('Cannot load .gh-embed.json: ' + d.error);
		}

		try {
			d = JSON.parse(d);
		} catch(e) {
			return error('Cannot parse .gh-embed.json: ' + e);
		}

		embed(d);

	});

	$('.on-github').href='//github.com/'+urlData.owner+'/'+urlData.repo+'/tree/'+urlData.ref+'/'+urlData.pathToMeta;

	function error(err) {
		$('main').classList.add('error');
		$('.error-text').textContent = err;
	}

    function embed(o) {
		var el = $('main'),
			nav = $('nav'),
			frames = $('.frames'),
			loadedCount = 0,
			hasActive;

		o.embed.forEach(function(item) {
			var frame,
				link;

			item.owner = item.owner || urlData.owner;
			item.repo = item.repo || urlData.repo;
			item.ref = item.ref || urlData.ref;
			item.type = item.type || item.path.match(/.*\.(\S+)$/);

			if(item.type == 'htmlpage') {
				frame = frames.appendChild(create('iframe', {
					src: item.url,
					onload: loaded,
					onerror: loaded,
					className: 'frame'
				}));

				link = nav.appendChild(create('a', {
					innerHTML: item.label || 'HTML Page'
				}));

			} else {
				link = nav.appendChild(create('a', {
					innerHTML: item.label || item.path
				}));

				frame = frames.appendChild(create('pre', {
					className: 'frame'
				}));

				getFile(item, item.path, function(data) {
					frame.classList.add('prettyprint', 'lang-' + item.type);
					if(o.linenums !== false) {
						frame.classList.add('linenums');
					}

					frame.textContent = data.error ? 'Error' : data;

					loaded();
				});
			}

			link.classList.add('l');

			if(item.active && !hasActive) {
				link.classList.add('active');
				frame.classList.add('active');
				hasActive = true;
			}

			link.addEventListener('click', function(evt) {
				var activeLink = $('a.active', nav),
					activeFrame = $('.frame.active', frames)

				if(activeLink) {
					activeLink.classList.remove('active');
				}

				if(activeFrame) {
					activeFrame.classList.remove('active');
				}

				link.classList.add('active');
				frame.classList.add('active');
			});
		});

		if(!hasActive) {
			$('a.l', nav).classList.add('active');
			$('.frame', frames).classList.add('active');
		}

		function loaded() {
			if(++loadedCount == o.embed.length) {
				el.classList.remove('loading');
				prettyPrint();
			}
		}
	}

	function readURL() {
		var loc = document.location,
			path = loc.pathname.match(/\/v(\d+)\/([^\/]+)\/([^\/]+)\/([^\/]+)?/);

		return {
			owner: path[2],
			repo: path[3],
			pathToMeta: path[4] ? (path[4] + '/') : '',
			ref: (loc.search.match(/\S*(\?|&)ref=(\S+)\S*/) || [])[2] || 'master'
		};
	}

	function getFile(data, path, callback) {
		var xhr = new XMLHttpRequest();
		xhr.open('GET', 'https://api.github.com/repos/'+data.owner+'/'+data.repo+'/contents/'+path+'?ref=' + data.ref, true);

		xhr.onload = function() {
			var resp = JSON.parse(xhr.responseText);
			if(resp.content) {
			  console.log(resp.content);
				callback(atob(resp.content.replace(/\s/g, '')));
			} else {
				xhr.onerror();
			}
		}

		// fallback in case if API limmit is exceeded
		xhr.onerror = function() {
			var xhr2 = new XMLHttpRequest();
			xhr2.open('GET', 'https://raw.githubusercontent.com/'+data.owner+'/'+data.repo+'/'+data.ref+'/'+path, true);
			xhr2.onload = function() {
				if(xhr2.status !== 200) {
					callback({ error: xhr2.statusText })
				} else {
					callback(xhr2.responseText);
				}
			}

			xhr2.onerror = function() {
				callback({ error: xhr2.statusText });
			}

			xhr2.send();
		}

		xhr.send();
	}

	function create(tagName, props, el, i, hasOwn) {
		el = document.createElement(tagName);
		hasOwn = 'hasOwnProperty';
		if (props) {
			for (i in props) {
				el[i] = props[i];
			}
		}
		return el;
	};

	function $(s, ctx) {
		return (ctx || document).querySelector(s);
	}
})(window);
<|endoftext|>