<commit_before>/*
 * @brief contains functions for bootstrap modal handling
 */
$(document).ready(function(){
	// Clear bs modal on close
	// We need this to prevent that the modal displays old content
	$('body, footer').on('hidden.bs.modal', '.modal', function () {
		$(this).removeData('bs.modal');
		$("#modal-title").empty();
		$('#modal-body').empty();
		// remove the file browser from jot (else we would have problems
		// with ajaxupload
		$(".fbrowser").remove();
	});

	// Clear bs modal on close
	// We need this to prevent that the modal displays old content
	$('body').on('hidden.bs.modal', '#jot-modal', function () {
		// restore cached jot at its hidden position ("#jot-content")
		$("#jot-content").append(jotcache);
		// clear the jotcache
		jotcache = ''
	});

	// Add Colorbox for viewing Network page images
	//var cBoxClasses = new Array();
	$("body").on("click", ".wall-item-body a img", function(){
		var aElem = $(this).parent();
		var imgHref = aElem.attr("href");

		// We need to make sure we only put a Colorbox on links to Friendica images
		// We'll try to do this by looking for links of the form
		// .../photo/ab803d8eg08daf85023adfec08 (with nothing more following), in hopes
		// that that will be unique enough
		if(imgHref.match(/\/photo\/[a-fA-F0-9]+(-[0-9]\.[\w]+?)?$/)) {

			// Add a unique class to all the images of a certain post, to allow scrolling through
			var cBoxClass = $(this).closest(".wall-item-body").attr("id") + "-lightbox";
			$(this).addClass(cBoxClass);

//			if( $.inArray(cBoxClass, cBoxClasses) < 0 ) {
//				cBoxClasses.push(cBoxClass);
//			}

			aElem.colorbox({
				maxHeight: '90%',
				photo: true, // Colorbox doesn't recognize a URL that don't end in .jpg, etc. as a photo
				rel: cBoxClass //$(this).attr("class").match(/wall-item-body-[\d]+-lightbox/)[0]
			});
		}
	});

	// Jot nav menu.
	$("body").on("click", "#jot-modal .jot-nav li a", function(e){
		e.preventDefault();
		toggleJotNav(this);
	});

	// Open filebrowser for elements with the class "image-select"
	// The following part handles the filebrowser for field_fileinput.tpl
	$("body").on("click", ".image-select", function(e){
		// set a extra attribute to mark the clicked button
		this.setAttribute("image-input", "select");
		Dialog.doImageBrowser("input");
	});

	// Insert filebrowser images into the input field (field_fileinput.tpl)
	$("body").on("fbrowser.image.input", function(e, filename, embedcode, id, img) {
		// select the clicked button by it's attribute
		var elm = $("[image-input='select']")
		// select the input field which belongs to this button
		var input = elm.parent(".input-group").children("input");
		// remove the special indicator attribut from the button
		elm.removeAttr("image-input");
		// inserte the link from the image into the input field
		input.val(img);

	});
});

// overwrite Dialog.show from main js to load the filebrowser into a bs modal
Dialog.show = function(url) {
	var modal = $('#modal').modal();
	modal
		.find('#modal-body')
		.load(url, function (responseText, textStatus) {
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				modal.show();

				$(function() {Dialog._load(url);});
			}
		});
};

// overwrite the function _get_url from main.js
Dialog._get_url = function(type, name, id) {
	var hash = name;
	if (id !== undefined) hash = hash + "-" + id;
	return "fbrowser/"+type+"/?mode=none#"+hash;
};

// does load the filebrowser into the jot modal
Dialog.showJot = function() {
	var type = "image";
	var name = "main";

	var url = Dialog._get_url(type, name);
	if(($(".modal-body #jot-fbrowser-wrapper .fbrowser").length) < 1 ) {
		// load new content to fbrowser window
		$("#jot-fbrowser-wrapper").load(url,function(responseText, textStatus){
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				$(function() {Dialog._load(url);});
			}
		});
	}
};

// init the filebrowser after page load
Dialog._load = function(url) {
	// get nickname & filebrowser type from the modal content
	var nickname = $("#fb-nickname").attr("value");
	var type = $("#fb-type").attr("value");

	// try to fetch the hash form the url
	var match = url.match(/fbrowser\/[a-z]+\/\?mode=none(.*)/);
	var hash = match[1];

	// initialize the filebrowser
	var jsbrowser = function() {
		FileBrowser.init(nickname, type, hash);
	}
	loadScript("view/theme/frio/js/filebrowser.js", jsbrowser);
};

/**
 * @brief Add first element with the class "heading" as modal title
 *
 * Note: this should be really done in the template
 * and is the solution where we havent done it until this
 * moment or where it isn't possible because of design
 */
function loadModalTitle() {
	// clear the text of the title
	//$("#modal-title").empty();

	// hide the first element with the class "heading" of the modal body
	$("#modal-body .heading").first().hide();

	// get the text of the first element with "heading" class
	var title = $("#modal-body .heading").first().text();

	// and append it to modal title
	if (title!=="") {
		$("#modal-title").append(title);
	}
}

// This function loads html content from a friendica page
// into a modal
function addToModal(url) {
	var char = qOrAmp(url);

	var url = url + char + 'mode=none';
	var modal = $('#modal').modal();

	modal
		.find('#modal-body')
		.load(url, function (responseText, textStatus) {
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				modal.show();

				//Get first element with the class "heading"
				//and use it as title
				loadModalTitle();
			}
		});
};

// function to load the html from the edit post page into
// the jot modal
function editpost(url) {
	// next to normel posts the post can be an event post. The event posts don't
	// use the normal Jot modal. For event posts we will use a normal modal
	// But first we have to test if the url links to an event. So we will split up
	// the url in its parts
	var splitURL = parseUrl(url);
	// Test if in the url path containing "events/event". If the path containing this
	// expression then we will call the addToModal function and exit this function at
	// this point
	if (splitURL.path.indexOf('events/event') > -1) {
		addToModal(splitURL.path);
		return;
	}

	var modal = $('#jot-modal').modal();
	var url = url + " #profile-jot-form";

	//var rand_num = random_digits(12);
	$(".jot-nav #jot-perms-lnk").parent("li").hide();

	// For editpost we load the modal html form the edit page. So we would have two jot forms in
	// the page html. To avoid js conflicts we store the original jot in the variable jotcache.
	// After closing the modal original jot should be restored at its orginal position in the html structure.
	jotcache = $("#jot-content > #profile-jot-form");

	// remove the original Jot as long as the edit Jot is open
	jotcache.remove();

	// add the class "edit" to the modal to have some kind of identifier to
	// have the possibility to e.g. put special event-listener
	$("#jot-modal").addClass("edit-jot");

	jotreset();

	modal
		.find('#jot-modal-body')
		.load(url, function (responseText, textStatus) {
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				// get the item type and hide the input for title and category if it isn't needed
				var type = $(responseText).find("#profile-jot-form input[name='type']").val();
				if(type === "wall-comment" || type === "remote-comment")
				{
					// hide title and category input fields because we don't
					$("#profile-jot-form #jot-title-wrap").hide();
					$("#profile-jot-form #jot-category-wrap").hide();
				}

				modal.show();
				$("#jot-popup").show();
			}
		});
}

// remove content from the jot modal
function jotreset() {
	// Clear bs modal on close
	// We need this to prevent that the modal displays old content
	$('body').on('hidden.bs.modal', '#jot-modal.edit-jot', function () {
		$(this).removeData('bs.modal');
		$(".jot-nav #jot-perms-lnk").parent("li").show();
		$("#profile-jot-form #jot-title-wrap").show();
		$("#profile-jot-form #jot-category-wrap").show();

		// the following was commented out because it is needed anymore
		// because we changed the behavior at an other place
	//		var rand_num = random_digits(12);
	//		$('#jot-title, #jot-category, #profile-jot-text').val("");
	//		$( "#profile-jot-form input[name='type']" ).val("wall");
	//		$( "#profile-jot-form input[name='post_id']" ).val("");
	//		$( "#profile-jot-form input[name='post_id_random']" ).val(rand_num);

		// remove the "edit-jot" class so we can the standard behavior on close
		$("#jot-modal.edit-jot").removeClass("edit-jot");
		$("#jot-modal-body").empty();
	});
}

// Give the active "jot-nav" list element the class "active"
function toggleJotNav (elm) {
	// select all li of jot-nav and remove the active class
	$(elm).closest(".jot-nav").children("li").removeClass("active");
	// add the active class to the parent of the link which was selected
	$(elm).parent("li").addClass("active");
}

<commit_msg>Frio: make jslint more happy<commit_after>/*
 * @brief contains functions for bootstrap modal handling
 */
$(document).ready(function(){
	// Clear bs modal on close
	// We need this to prevent that the modal displays old content
	$('body, footer').on('hidden.bs.modal', '.modal', function () {
		$(this).removeData('bs.modal');
		$("#modal-title").empty();
		$('#modal-body').empty();
		// remove the file browser from jot (else we would have problems
		// with ajaxupload
		$(".fbrowser").remove();
	});

	// Clear bs modal on close
	// We need this to prevent that the modal displays old content
	$('body').on('hidden.bs.modal', '#jot-modal', function () {
		// restore cached jot at its hidden position ("#jot-content")
		$("#jot-content").append(jotcache);
		// clear the jotcache
		jotcache = '';
	});

	// Add Colorbox for viewing Network page images
	//var cBoxClasses = new Array();
	$("body").on("click", ".wall-item-body a img", function(){
		var aElem = $(this).parent();
		var imgHref = aElem.attr("href");

		// We need to make sure we only put a Colorbox on links to Friendica images
		// We'll try to do this by looking for links of the form
		// .../photo/ab803d8eg08daf85023adfec08 (with nothing more following), in hopes
		// that that will be unique enough
		if(imgHref.match(/\/photo\/[a-fA-F0-9]+(-[0-9]\.[\w]+?)?$/)) {

			// Add a unique class to all the images of a certain post, to allow scrolling through
			var cBoxClass = $(this).closest(".wall-item-body").attr("id") + "-lightbox";
			$(this).addClass(cBoxClass);

//			if( $.inArray(cBoxClass, cBoxClasses) < 0 ) {
//				cBoxClasses.push(cBoxClass);
//			}

			aElem.colorbox({
				maxHeight: '90%',
				photo: true, // Colorbox doesn't recognize a URL that don't end in .jpg, etc. as a photo
				rel: cBoxClass //$(this).attr("class").match(/wall-item-body-[\d]+-lightbox/)[0]
			});
		}
	});

	// Jot nav menu.
	$("body").on("click", "#jot-modal .jot-nav li a", function(e){
		e.preventDefault();
		toggleJotNav(this);
	});

	// Open filebrowser for elements with the class "image-select"
	// The following part handles the filebrowser for field_fileinput.tpl
	$("body").on("click", ".image-select", function(){
		// set a extra attribute to mark the clicked button
		this.setAttribute("image-input", "select");
		Dialog.doImageBrowser("input");
	});

	// Insert filebrowser images into the input field (field_fileinput.tpl)
	$("body").on("fbrowser.image.input", function(e, filename, embedcode, id, img) {
		// select the clicked button by it's attribute
		var elm = $("[image-input='select']");
		// select the input field which belongs to this button
		var input = elm.parent(".input-group").children("input");
		// remove the special indicator attribut from the button
		elm.removeAttr("image-input");
		// inserte the link from the image into the input field
		input.val(img);

	});
});

// overwrite Dialog.show from main js to load the filebrowser into a bs modal
Dialog.show = function(url) {
	var modal = $('#modal').modal();
	modal
		.find('#modal-body')
		.load(url, function (responseText, textStatus) {
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				modal.show();

				$(function() {Dialog._load(url);});
			}
		});
};

// overwrite the function _get_url from main.js
Dialog._get_url = function(type, name, id) {
	var hash = name;
	if (id !== undefined) hash = hash + "-" + id;
	return "fbrowser/"+type+"/?mode=none#"+hash;
};

// does load the filebrowser into the jot modal
Dialog.showJot = function() {
	var type = "image";
	var name = "main";

	var url = Dialog._get_url(type, name);
	if(($(".modal-body #jot-fbrowser-wrapper .fbrowser").length) < 1 ) {
		// load new content to fbrowser window
		$("#jot-fbrowser-wrapper").load(url,function(responseText, textStatus){
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				$(function() {Dialog._load(url);});
			}
		});
	}
};

// init the filebrowser after page load
Dialog._load = function(url) {
	// get nickname & filebrowser type from the modal content
	var nickname = $("#fb-nickname").attr("value");
	var type = $("#fb-type").attr("value");

	// try to fetch the hash form the url
	var match = url.match(/fbrowser\/[a-z]+\/\?mode=none(.*)/);
	var hash = match[1];

	// initialize the filebrowser
	var jsbrowser = function() {
		FileBrowser.init(nickname, type, hash);
	};
	loadScript("view/theme/frio/js/filebrowser.js", jsbrowser);
};

/**
 * @brief Add first element with the class "heading" as modal title
 *
 * Note: this should be really done in the template
 * and is the solution where we havent done it until this
 * moment or where it isn't possible because of design
 */
function loadModalTitle() {
	// clear the text of the title
	//$("#modal-title").empty();

	// hide the first element with the class "heading" of the modal body
	$("#modal-body .heading").first().hide();

	// get the text of the first element with "heading" class
	var title = $("#modal-body .heading").first().text();

	// and append it to modal title
	if (title!=="") {
		$("#modal-title").append(title);
	}
}

// This function loads html content from a friendica page
// into a modal
function addToModal(url) {
	var char = qOrAmp(url);

	url = url + char + 'mode=none';
	var modal = $('#modal').modal();

	modal
		.find('#modal-body')
		.load(url, function (responseText, textStatus) {
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				modal.show();

				//Get first element with the class "heading"
				//and use it as title
				loadModalTitle();
			}
		});
}

// function to load the html from the edit post page into
// the jot modal
function editpost(url) {
	// next to normel posts the post can be an event post. The event posts don't
	// use the normal Jot modal. For event posts we will use a normal modal
	// But first we have to test if the url links to an event. So we will split up
	// the url in its parts
	var splitURL = parseUrl(url);
	// Test if in the url path containing "events/event". If the path containing this
	// expression then we will call the addToModal function and exit this function at
	// this point
	if (splitURL.path.indexOf('events/event') > -1) {
		addToModal(splitURL.path);
		return;
	}

	var modal = $('#jot-modal').modal();
	url = url + " #profile-jot-form";

	//var rand_num = random_digits(12);
	$(".jot-nav #jot-perms-lnk").parent("li").hide();

	// For editpost we load the modal html form the edit page. So we would have two jot forms in
	// the page html. To avoid js conflicts we store the original jot in the variable jotcache.
	// After closing the modal original jot should be restored at its orginal position in the html structure.
	jotcache = $("#jot-content > #profile-jot-form");

	// remove the original Jot as long as the edit Jot is open
	jotcache.remove();

	// add the class "edit" to the modal to have some kind of identifier to
	// have the possibility to e.g. put special event-listener
	$("#jot-modal").addClass("edit-jot");

	jotreset();

	modal
		.find('#jot-modal-body')
		.load(url, function (responseText, textStatus) {
			if ( textStatus === 'success' ||
				textStatus === 'notmodified')
			{
				// get the item type and hide the input for title and category if it isn't needed
				var type = $(responseText).find("#profile-jot-form input[name='type']").val();
				if(type === "wall-comment" || type === "remote-comment")
				{
					// hide title and category input fields because we don't
					$("#profile-jot-form #jot-title-wrap").hide();
					$("#profile-jot-form #jot-category-wrap").hide();
				}

				modal.show();
				$("#jot-popup").show();
			}
		});
}

// remove content from the jot modal
function jotreset() {
	// Clear bs modal on close
	// We need this to prevent that the modal displays old content
	$('body').on('hidden.bs.modal', '#jot-modal.edit-jot', function () {
		$(this).removeData('bs.modal');
		$(".jot-nav #jot-perms-lnk").parent("li").show();
		$("#profile-jot-form #jot-title-wrap").show();
		$("#profile-jot-form #jot-category-wrap").show();

		// the following was commented out because it is needed anymore
		// because we changed the behavior at an other place
	//		var rand_num = random_digits(12);
	//		$('#jot-title, #jot-category, #profile-jot-text').val("");
	//		$( "#profile-jot-form input[name='type']" ).val("wall");
	//		$( "#profile-jot-form input[name='post_id']" ).val("");
	//		$( "#profile-jot-form input[name='post_id_random']" ).val(rand_num);

		// remove the "edit-jot" class so we can the standard behavior on close
		$("#jot-modal.edit-jot").removeClass("edit-jot");
		$("#jot-modal-body").empty();
	});
}

// Give the active "jot-nav" list element the class "active"
function toggleJotNav (elm) {
	// select all li of jot-nav and remove the active class
	$(elm).closest(".jot-nav").children("li").removeClass("active");
	// add the active class to the parent of the link which was selected
	$(elm).parent("li").addClass("active");
}

<|endoftext|>


<commit_before>/*!
 * viewport-units-buggyfill v0.4
 * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
 * @author: Rodney Rehm - http://rodneyrehm.de/en/
 */

(function (root, factory) {
  'use strict';
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like enviroments that support module.exports,
    // like Node.
    module.exports = factory();
  } else {
    // Browser globals (root is window)
    root.viewportUnitsBuggyfill = factory();
  }
}(this, function () {
  'use strict';
  /*global document, window, location, XMLHttpRequest, XDomainRequest*/

  var initialized = false;
  var options;
  var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(window.navigator.userAgent);
  var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
  var forEach = [].forEach;
  var dimensions;
  var declarations;
  var styleNode;
  var is_bad_IE = false;

  /*
   * Do not remove this comment before.  It is used by IE to test what version
   * we are running.
   */

  /*@cc_on

  @if (@_jscript_version <= 10)
    is_bad_IE = true;
    no_vmin_in_calc = true;
    no_vmin_vmax = true;
  @end

  @*/

  function debounce(func, wait) {
    var timeout;
    return function() {
      var context = this;
      var args = arguments;
      var callback = function() {
        func.apply(context, args);
      };

      clearTimeout(timeout);
      timeout = setTimeout(callback, wait);
    };
  }

  // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
  function inIframe() {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }

  function initialize(initOptions) {
    if (initialized) {
      return;
    }

    if (initOptions === true) {
      initOptions = {
        force: true
      };
    }

    options = initOptions || {};
    options.isMobileSafari = isMobileSafari;

    if (!options.force && !isMobileSafari && !is_bad_IE && (!options.hacks || !options.hacks.required(options))) {
      // this buggyfill only applies to mobile safari
      return;
    }

    options.hacks && options.hacks.initialize(options);

    initialized = true;
    styleNode = document.createElement('style');
    styleNode.id = 'patched-viewport';
    document.head.appendChild(styleNode);

    // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
    // therefore download and inject them as <style> to circumvent SOP.
    importCrossOriginLinks(function() {
      var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
      // doing a full refresh rather than updateStyles because an orientationchange
      // could activate different stylesheets
      window.addEventListener('orientationchange', _refresh, true);
      // orientationchange might have happened while in a different window
      window.addEventListener('pageshow', _refresh, true);

      if (options.force || is_bad_IE || inIframe()) {
        window.addEventListener('resize', _refresh, true);
        options._listetingToResize = true;
      }

      options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);

      refresh();
    });
  }

  function updateStyles() {
    styleNode.textContent = getReplacedViewportUnits();
  }

  function refresh() {
    if (!initialized) {
      return;
    }

    findProperties();

    // iOS Safari will report window.innerWidth and .innerHeight as 0
    // unless a timeout is used here.
    // TODO: figure out WHY innerWidth === 0
    setTimeout(function() {
      updateStyles();
    }, 1);
  }

  function findProperties() {
    declarations = [];
    forEach.call(document.styleSheets, function(sheet) {
      if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
        // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
        return;
      }

      if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
        // skip entire sheet because media attribute doesn't match
        return;
      }

      forEach.call(sheet.cssRules, findDeclarations);
    });

    return declarations;
  }

  function findDeclarations(rule) {
    if (rule.type === 7) {
      var value = rule.cssText;
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        // KeyframesRule does not have a CSS-PropertyName
        declarations.push([rule, null, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
      }

      return;
    }

    if (!rule.style) {
      if (!rule.cssRules) {
        return;
      }

      forEach.call(rule.cssRules, function(_rule) {
        findDeclarations(_rule);
      });

      return;
    }

    forEach.call(rule.style, function(name) {
      var value = rule.style.getPropertyValue(name);
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        declarations.push([rule, name, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
      }
    });
  }

  function getReplacedViewportUnits() {
    dimensions = getViewport();

    var css = [];
    var buffer = [];
    var open;
    var close;

    declarations.forEach(function(item) {
      var _item = overwriteDeclaration.apply(null, item);
      var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
      var _close = new Array(_item.selector.length + 1).join('\n}');

      if (!_open || _open !== open) {
        if (buffer.length) {
          css.push(open + buffer.join('\n') + close);
          buffer.length = 0;
        }

        if (_open) {
          open = _open;
          close = _close;
          buffer.push(_item.content);
        } else {
          css.push(_item.content);
          open = null;
          close = null;
        }

        return;
      }

      if (_open && !open) {
        open = _open;
        close = _close;
      }

      buffer.push(_item.content);
    });

    if (buffer.length) {
      css.push(open + buffer.join('\n') + close);
    }

    return css.join('\n\n');
  }

  function overwriteDeclaration(rule, name, value) {
    var _value = value.replace(viewportUnitExpression, replaceValues);
    var  _selectors = [];

    if (options.hacks) {
      _value = options.hacks.overwriteDeclaration(rule, name, _value);
    }

    if (name) {
      // skipping KeyframesRule
      _selectors.push(rule.selectorText);
      _value = name + ': ' + _value + ';';
    }

    var _rule = rule.parentRule;
    while (_rule) {
      _selectors.unshift('@media ' + _rule.media.mediaText);
      _rule = _rule.parentRule;
    }

    return {
      selector: _selectors,
      content: _value
    };
  }

  function replaceValues(match, number, unit) {
    var _base = dimensions[unit];
    var _number = parseFloat(number) / 100;
    return (_number * _base) + 'px';
  }

  function getViewport() {
    var vh = window.innerHeight;
    var vw = window.innerWidth;

    return {
      vh: vh,
      vw: vw,
      vmax: Math.max(vw, vh),
      vmin: Math.min(vw, vh)
    };
  }

  function importCrossOriginLinks(next) {
    var _waiting = 0;
    var decrease = function() {
      _waiting--;
      if (!_waiting) {
        next();
      }
    };

    forEach.call(document.styleSheets, function(sheet) {
      if (!sheet.href || origin(sheet.href) === origin(location.href)) {
        // skip <style> and <link> from same origin
        return;
      }

      _waiting++;
      convertLinkToStyle(sheet.ownerNode, decrease);
    });

    if (!_waiting) {
      next();
    }
  }

  function origin(url) {
    return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
  }

  function convertLinkToStyle(link, next) {
    getCors(link.href, function() {
      var style = document.createElement('style');
      style.media = link.media;
      style.setAttribute('data-href', link.href);
      style.textContent = this.responseText;
      link.parentNode.replaceChild(style, link);
      next();
    }, next);
  }

  function getCors(url, success, error) {
    var xhr = new XMLHttpRequest();
    if ('withCredentials' in xhr) {
      // XHR for Chrome/Firefox/Opera/Safari.
      xhr.open('GET', url, true);
    } else if (typeof XDomainRequest !== 'undefined') {
      // XDomainRequest for IE.
      xhr = new XDomainRequest();
      xhr.open('GET', url);
    } else {
      throw new Error('cross-domain XHR not supported');
    }

    xhr.onload = success;
    xhr.onerror = error;
    xhr.send();
    return xhr;
  }

  return {
    version: '0.3.1',
    findProperties: findProperties,
    getCss: getReplacedViewportUnits,
    init: initialize,
    refresh: refresh
  };

}));
<commit_msg>variable names<commit_after>/*!
 * viewport-units-buggyfill v0.4
 * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
 * @author: Rodney Rehm - http://rodneyrehm.de/en/
 */

(function (root, factory) {
  'use strict';
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like enviroments that support module.exports,
    // like Node.
    module.exports = factory();
  } else {
    // Browser globals (root is window)
    root.viewportUnitsBuggyfill = factory();
  }
}(this, function () {
  'use strict';
  /*global document, window, location, XMLHttpRequest, XDomainRequest*/

  var initialized = false;
  var options;
  var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(window.navigator.userAgent);
  var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
  var forEach = [].forEach;
  var dimensions;
  var declarations;
  var styleNode;
  var isOldInternetExplorer = false;

  /*
   * Do not remove this comment before.  It is used by IE to test what version
   * we are running.
   */

  /*@cc_on

  @if (@_jscript_version <= 10)
    isOldInternetExplorer = true;
    no_vmin_in_calc = true;
    no_vmin_vmax = true;
  @end

  @*/

  function debounce(func, wait) {
    var timeout;
    return function() {
      var context = this;
      var args = arguments;
      var callback = function() {
        func.apply(context, args);
      };

      clearTimeout(timeout);
      timeout = setTimeout(callback, wait);
    };
  }

  // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
  function inIframe() {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }

  function initialize(initOptions) {
    if (initialized) {
      return;
    }

    if (initOptions === true) {
      initOptions = {
        force: true
      };
    }

    options = initOptions || {};
    options.isMobileSafari = isMobileSafari;

    if (!options.force && !isMobileSafari && !isOldInternetExplorer && (!options.hacks || !options.hacks.required(options))) {
      // this buggyfill only applies to mobile safari
      return;
    }

    options.hacks && options.hacks.initialize(options);

    initialized = true;
    styleNode = document.createElement('style');
    styleNode.id = 'patched-viewport';
    document.head.appendChild(styleNode);

    // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
    // therefore download and inject them as <style> to circumvent SOP.
    importCrossOriginLinks(function() {
      var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
      // doing a full refresh rather than updateStyles because an orientationchange
      // could activate different stylesheets
      window.addEventListener('orientationchange', _refresh, true);
      // orientationchange might have happened while in a different window
      window.addEventListener('pageshow', _refresh, true);

      if (options.force || isOldInternetExplorer || inIframe()) {
        window.addEventListener('resize', _refresh, true);
        options._listetingToResize = true;
      }

      options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);

      refresh();
    });
  }

  function updateStyles() {
    styleNode.textContent = getReplacedViewportUnits();
  }

  function refresh() {
    if (!initialized) {
      return;
    }

    findProperties();

    // iOS Safari will report window.innerWidth and .innerHeight as 0
    // unless a timeout is used here.
    // TODO: figure out WHY innerWidth === 0
    setTimeout(function() {
      updateStyles();
    }, 1);
  }

  function findProperties() {
    declarations = [];
    forEach.call(document.styleSheets, function(sheet) {
      if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
        // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
        return;
      }

      if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
        // skip entire sheet because media attribute doesn't match
        return;
      }

      forEach.call(sheet.cssRules, findDeclarations);
    });

    return declarations;
  }

  function findDeclarations(rule) {
    if (rule.type === 7) {
      var value = rule.cssText;
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        // KeyframesRule does not have a CSS-PropertyName
        declarations.push([rule, null, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
      }

      return;
    }

    if (!rule.style) {
      if (!rule.cssRules) {
        return;
      }

      forEach.call(rule.cssRules, function(_rule) {
        findDeclarations(_rule);
      });

      return;
    }

    forEach.call(rule.style, function(name) {
      var value = rule.style.getPropertyValue(name);
      viewportUnitExpression.lastIndex = 0;
      if (viewportUnitExpression.test(value)) {
        declarations.push([rule, name, value]);
        options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
      }
    });
  }

  function getReplacedViewportUnits() {
    dimensions = getViewport();

    var css = [];
    var buffer = [];
    var open;
    var close;

    declarations.forEach(function(item) {
      var _item = overwriteDeclaration.apply(null, item);
      var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
      var _close = new Array(_item.selector.length + 1).join('\n}');

      if (!_open || _open !== open) {
        if (buffer.length) {
          css.push(open + buffer.join('\n') + close);
          buffer.length = 0;
        }

        if (_open) {
          open = _open;
          close = _close;
          buffer.push(_item.content);
        } else {
          css.push(_item.content);
          open = null;
          close = null;
        }

        return;
      }

      if (_open && !open) {
        open = _open;
        close = _close;
      }

      buffer.push(_item.content);
    });

    if (buffer.length) {
      css.push(open + buffer.join('\n') + close);
    }

    return css.join('\n\n');
  }

  function overwriteDeclaration(rule, name, value) {
    var _value = value.replace(viewportUnitExpression, replaceValues);
    var  _selectors = [];

    if (options.hacks) {
      _value = options.hacks.overwriteDeclaration(rule, name, _value);
    }

    if (name) {
      // skipping KeyframesRule
      _selectors.push(rule.selectorText);
      _value = name + ': ' + _value + ';';
    }

    var _rule = rule.parentRule;
    while (_rule) {
      _selectors.unshift('@media ' + _rule.media.mediaText);
      _rule = _rule.parentRule;
    }

    return {
      selector: _selectors,
      content: _value
    };
  }

  function replaceValues(match, number, unit) {
    var _base = dimensions[unit];
    var _number = parseFloat(number) / 100;
    return (_number * _base) + 'px';
  }

  function getViewport() {
    var vh = window.innerHeight;
    var vw = window.innerWidth;

    return {
      vh: vh,
      vw: vw,
      vmax: Math.max(vw, vh),
      vmin: Math.min(vw, vh)
    };
  }

  function importCrossOriginLinks(next) {
    var _waiting = 0;
    var decrease = function() {
      _waiting--;
      if (!_waiting) {
        next();
      }
    };

    forEach.call(document.styleSheets, function(sheet) {
      if (!sheet.href || origin(sheet.href) === origin(location.href)) {
        // skip <style> and <link> from same origin
        return;
      }

      _waiting++;
      convertLinkToStyle(sheet.ownerNode, decrease);
    });

    if (!_waiting) {
      next();
    }
  }

  function origin(url) {
    return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
  }

  function convertLinkToStyle(link, next) {
    getCors(link.href, function() {
      var style = document.createElement('style');
      style.media = link.media;
      style.setAttribute('data-href', link.href);
      style.textContent = this.responseText;
      link.parentNode.replaceChild(style, link);
      next();
    }, next);
  }

  function getCors(url, success, error) {
    var xhr = new XMLHttpRequest();
    if ('withCredentials' in xhr) {
      // XHR for Chrome/Firefox/Opera/Safari.
      xhr.open('GET', url, true);
    } else if (typeof XDomainRequest !== 'undefined') {
      // XDomainRequest for IE.
      xhr = new XDomainRequest();
      xhr.open('GET', url);
    } else {
      throw new Error('cross-domain XHR not supported');
    }

    xhr.onload = success;
    xhr.onerror = error;
    xhr.send();
    return xhr;
  }

  return {
    version: '0.3.1',
    findProperties: findProperties,
    getCss: getReplacedViewportUnits,
    init: initialize,
    refresh: refresh
  };

}));
<|endoftext|>


<commit_before>function getParameterByName(name) {
    'use strict';
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) {
        return null;
    }
    if (!results[2]) {
        return '';
    }
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function hash(name, value) {
    'use strict';
    var hash;
    try {
        hash = window.location.hash;
        if (hash.startsWith('#')) {
            hash = hash.substring(1);
        }
        hash = JSON.parse(hash);
    } catch(ex) {
        hash = {};
    }
    if (value === undefined) {
        return hash[name];
    }
    hash[name] = value;
    hash = '#' + JSON.stringify(hash);
    window.history.replaceState(undefined, undefined, hash);
}

var autoExpandToAndSelectPath = hash('selected');

function findNodesByUrl(searchUrl) {
    'use strict';
    var nodes = [];
    var jstree = $('#tree').jstree();
    function recurse(nodeId) {
        var node = jstree.get_node(nodeId)
        if (node.data) {
            if (node.data.url === searchUrl) {
                nodes.push(node);
                return;
            }
            if (searchUrl.indexOf(node.data.url) != 0) {
                return;
            }
        }
        node.children.forEach(recurse);
    }
    recurse('#');
    return nodes;
}

function createResource() {
    'use strict';
    var relPath = $('#nameOfResourceToCreate').val();
    if(!relPath) {
        $('#nameOfResourceToCreate').effect('highlight', {color: '#F88'}, 200);
        return;
    }
    var basePath = $('#nameOfResourceToCreateBaseUrl').text();
    var url = basePath + relPath;
    $.ajax({
        url: url,
        type: 'PUT',
        data: '{}'
    }).then(function () {
        var affectedParentNodes = findNodesByUrl(basePath);
        autoExpandToAndSelectPath = url;
        var jstree = $('#tree').jstree();
        jstree.deselect_all();
        affectedParentNodes.forEach(function(node) {
            jstree.refresh_node(node);
        });
        jstree.refresh_node(basePath);
        $('#dialogCreateResource').parent().effect('highlight', {color: '#8F8'}, 200);
    });
}

function deleteResource() {
    'use strict';
    var url = $('#nameOfResourceToDelete').text();
    $.ajax({
        url: url,
        type: 'DELETE'
    }).then(function () {
        var jstree = $('#tree').jstree();
        var affectedNodes = findNodesByUrl(url);
        affectedNodes.forEach(function(node) {
            node = jstree.get_parent(node);
            jstree.refresh_node(node);
            jstree.select_node(node);
        });
        $('#dialogDeleteResource').dialog('close');
    });
}

$(function ($) {
    'use strict';

    /**************************************************************************************************************
     * Make the tree horizontally resizable (width)
     *   - Note the hack to go around the problem with the iframe
     *   - store the width in localStorage and set it on page load from loacalStorage
     *************************************************************************************************************/
    $('#treeResizable').resizable({
        handles: {e: $('#resize-handle')},
        start: function () {
            // hack: we need an overlay above the iframe so that we continue to get mouse-move-events (while resizing is active)
            $('#editor-hide-iframe-overlay').show();
        },
        stop: function () {
            var width = $('#treeResizable').width();
            window.localStorage.setItem('vertx-rest-storage-editor.treeWidth', width);
            $('#editor-hide-iframe-overlay').hide();
        }
    });
    var width = window.localStorage.getItem('vertx-rest-storage-editor.treeWidth');
    if (width) {
        $('#treeResizable').width(width);
    }

    $('#dialogCreateResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });
    $('#dialogDeleteResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });

    /**************************************************************************************************************
     * Setup jstree (see http://www.jstree.com)
     *************************************************************************************************************/
    var treeBase = getParameterByName('treeBase');
    if (!treeBase.endsWith('/')) {
        treeBase += '/';
    }
    var rootNodes = [{
        text: treeBase,
        data: {url: treeBase},
        icon: 'fa fa-folder',
        children: true
    }];

    try {
        var pinnedUrls = JSON.parse(window.localStorage.getItem('pinnedUrls'));
       pinnedUrls.forEach(function(url) {
           rootNodes.push({
               text: url,
               data: {url: url, pinned: true},
               children: url.endsWith('/')
           });
       });
    } catch (ignore) {
    }

    $('#tree').jstree({
        core: {
            /**************************************************************************************************************
             * basic settings for jstree
             *************************************************************************************************************/
            check_callback: true,
            animation: false,
            themes: {
                name: 'proton',
                responsive: true,
                dots : true,
                icons: true
            },
            /**************************************************************************************************************
             * the 'lazy' data loader - called automatically when opening an unloaded node
             * creates child nodes which are either nodes-with-children ('directory') or leafs ('resources')
             * We distinguish from vertx-rest-storage with a trailing slash (i.e. "img/" is a node-with-children while" "img" is a resource
             *************************************************************************************************************/
            data: function (node, callback) {
                if (node.id === '#') {
                    // initialize the one-and-only rood node
                    callback.call(this, rootNodes);
                    return;
                }

                var nodeUrl = node.data.url;
                var childrenNodes = [];
                function addEntriesToParentNode(entries) {
                    entries.forEach(function (c) {
                        var isLeaf = !c.endsWith('/');
                        var childNode = {
                            text: c,
                            data: {
                                url: nodeUrl + c
                            },
                            icon: isLeaf ? 'fa fa-file-text-o' : 'fa fa-folder',
                            children: !isLeaf   // to force jstree to show a '+' icon and to be able to open a not-yet loaded tree
                        };
                        childrenNodes.push(childNode);
                    });
                }

                $.get(nodeUrl, function success(data) {
                    for (var property in data) {
                        if (data.hasOwnProperty(property)) {
                            addEntriesToParentNode(data[property]);
                        }
                    }
                }).fail(function (err) {
                    // show a single red error children on AJAX error
                    childrenNodes.push({
                        text: err.responseText || err.statusText,
                        data: {url: nodeUrl + '[errorIndicator]'},
                        li_attr: {style: 'color: red;'},
                        icon: null
                    });
                }).always(function() {
                    callback.call(this, childrenNodes);
                });
            }
        },
        /**************************************************************************************************************
         * Context menu on every tree node
         *************************************************************************************************************/
        plugins: [ 'contextmenu'],
        contextmenu: {
            show_at_node: false,
            items: function (node) {
                var m = {};
                m.title = {label: node.data.url, separator_after: true, _disabled: true};
                m.pin = {
                    label: node.data.pinned ? 'Unpin this node' : 'Pin this node',
                    icon: 'fa fa-thumb-tack',
                    separator_after: true,
                    action: function () {
                        if (node.data.pinned) {
                            $('#tree').jstree().delete_node(node);
                        } else {
                            $('#tree').jstree().create_node('#', {
                                text: node.data.url,
                                icon: 'fa fa-thumb-tack',
                                data: {url: node.data.url, pinned: true}
                           });
                        }
                        // store list of pinned urls to localStorage
                        var pinnedUrls = [];
                        jstree.get_node('#').children.forEach(function(c) {
                            var n = jstree.get_node(c);
                            if (n.data.pinned) {
                                pinnedUrls.push(n.data.url);
                            }
                        });
                        window.localStorage.setItem('pinnedUrls', JSON.stringify(pinnedUrls));
                    }
                };
                if (node.data.url.endsWith('/')) {
                    m.create = {
                        label: 'Create resource',
                        action: function() {
                            $('#dialogCreateResource').dialog('option', 'position', {
                                my: 'left center',
                                at: 'left+150 top',
                                of: $('#tree').jstree().get_node(node, true),
                                collision: 'fit'
                            }).dialog('open');
                            $('#nameOfResourceToCreateBaseUrl').text(node.data.url);
                            $('#nameOfResourceToCreate').val('');
                        }
                    };
                }
                m.delete = {
                    label: node.data.url.endsWith('/') ? 'Delete whole tree' : 'Delete resource',
                    icon: 'fa fa-trash',
                    action: function() {
                        $('#dialogDeleteResource').dialog('option', 'position', {
                            my: 'left center',
                            at: 'left+150 top',
                            of: $('#tree').jstree().get_node(node, true),
                            collision: 'fit'
                        }).dialog('open');
                        $('#nameOfResourceToDelete').text(node.data.url);
                    }
                };
                return m;
            }
        }
    });

    var jstree = $('#tree').jstree();
    $('#tree').on('load_node.jstree', function (e, data) {
        var node = data.node;
        if (node.id === '#') {
            // open the root nodes automatically
            jstree.open_node(node.children[0]);
        }
    });

    $('#tree').on('after_open.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder-open');  // show the 'open' folder icon
        /**************************************************************************************************************
         * on page load we open the tree node-by-node to a preselected path
         * so we can 'stabilize' the view on "Browser refresh"
         *************************************************************************************************************/
        if (autoExpandToAndSelectPath) {
            for (var i = 0; i < node.children.length; i++) {
                var childNode = jstree.get_node(node.children[i]);
                var childUrl = childNode.data.url;
                if (autoExpandToAndSelectPath === childUrl) {
                    // found the target
                    node = childNode;
                    break;
                } else if (childUrl.endsWith('/') && autoExpandToAndSelectPath.indexOf(childUrl) === 0) {
                    // this is a child-node which matches the searched url - so open it (and we will be called again)
                    jstree.open_node(childNode);
                    return;
                }
            }
            // no children matches the path _or_ perfect match found
            autoExpandToAndSelectPath = null;
            jstree.select_node(node);
            var offset = jstree.get_node(node, true).offset();
            var height = $('#tree').height();
            $('#tree').scrollTop(offset.top - height / 3);
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder'); // show the 'closed' folder icon
    });
    $('#tree').on('select_node.jstree', function (e, data) {
        var node = data.node;
        $('#editor-iframe').attr('src', '');
        hash('selected', node.data.url);
        if (!node.data.url.endsWith('/')) {
            if (!node.data.url.endsWith('[errorIndicator]')) {
                openInEditor(node.data.url); // open in editor
            }
        } else if (data.node.state.loaded) {
            // hm... better to close the node - we can reload by open it again (as 'close' removes the childs)
            jstree.refresh_node(node);
        } else {
            jstree.open_node(node); // click on node-text to open subtree
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        // we only want to remove children to force fresh reload when opening node again
        // but this is slow in jstree --> we remove the whole node (which is quite fast) and re-insert a reincarnation of it @same position
        var node = data.node;
        var parentNode = jstree.get_node(jstree.get_parent(node));
        var pos = parentNode.children.indexOf(node.id);
        jstree.delete_node(node);
        var reincarnationNode = {
            text: node.text,
            data: {
                url: node.data.url
            },
            state: {
                selected: node.state.selected
            },
            icon: node.icon,
            children: true
        };
        jstree.create_node(parentNode, reincarnationNode, pos);
    });
});

// toggle raw <-> editor mode
function toggleRawMode() {
    'use strict';
    $('#raw-mode-toggler').toggleClass('active');
    openInEditor();
}

// load node by id into the editor
function openInEditor(url) {
    'use strict';

    var rawMode = $('#raw-mode-toggler').hasClass('active');
    var editMode = !rawMode;
    if (url && editMode) {
        var editor = getParameterByName('editor') || 'editor.html';
        url = editor + '#' + url;
    }
    // $('#editor-iframe').attr('src', '');
    window.setTimeout(function () {
        $('#editor-iframe').attr('src', url);
    }, 10);
}<commit_msg>Reimplement Tree-View to solve various issues (not yet finished)<commit_after>function getParameterByName(name) {
    'use strict';
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) {
        return null;
    }
    if (!results[2]) {
        return '';
    }
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function hash(name, value) {
    'use strict';
    var hash;
    try {
        hash = window.location.hash;
        if (hash.startsWith('#')) {
            hash = hash.substring(1);
        }
        hash = JSON.parse(hash);
    } catch(ex) {
        hash = {};
    }
    if (value === undefined) {
        return hash[name];
    }
    hash[name] = value;
    hash = '#' + JSON.stringify(hash);
    window.history.replaceState(undefined, undefined, hash);
}

var autoExpandToAndSelectPath = hash('selected');

function findNodesByUrl(searchUrl) {
    'use strict';
    var nodes = [];
    var jstree = $('#tree').jstree();
    function recurse(nodeId) {
        var node = jstree.get_node(nodeId)
        if (node.data) {
            if (node.data.url === searchUrl) {
                nodes.push(node);
                return;
            }
            if (searchUrl.indexOf(node.data.url) != 0) {
                return;
            }
        }
        node.children.forEach(recurse);
    }
    recurse('#');
    return nodes;
}

function createResource() {
    'use strict';
    var relPath = $('#nameOfResourceToCreate').val();
    if(!relPath) {
        $('#nameOfResourceToCreate').effect('highlight', {color: '#F88'}, 200);
        return;
    }
    var basePath = $('#nameOfResourceToCreateBaseUrl').text();
    var url = basePath + relPath;
    $.ajax({
        url: url,
        type: 'PUT',
        data: '{}'
    }).then(function () {
        var affectedParentNodes = findNodesByUrl(basePath);
        autoExpandToAndSelectPath = url;
        var jstree = $('#tree').jstree();
        jstree.deselect_all();
        affectedParentNodes.forEach(function(node) {
            jstree.refresh_node(node);
        });
        jstree.refresh_node(basePath);
        $('#dialogCreateResource').parent().effect('highlight', {color: '#8F8'}, 200);
    });
}

function deleteResource() {
    'use strict';
    var url = $('#nameOfResourceToDelete').text();
    $.ajax({
        url: url,
        type: 'DELETE'
    }).then(function () {
        var jstree = $('#tree').jstree();
        var affectedNodes = findNodesByUrl(url);
        affectedNodes.forEach(function(node) {
            node = jstree.get_parent(node);
            jstree.refresh_node(node);
            jstree.select_node(node);
        });
        $('#dialogDeleteResource').dialog('close');
    });
}

$(function ($) {
    'use strict';

    /**************************************************************************************************************
     * Make the tree horizontally resizable (width)
     *   - Note the hack to go around the problem with the iframe
     *   - store the width in localStorage and set it on page load from loacalStorage
     *************************************************************************************************************/
    $('#treeResizable').resizable({
        handles: {e: $('#resize-handle')},
        start: function () {
            // hack: we need an overlay above the iframe so that we continue to get mouse-move-events (while resizing is active)
            $('#editor-hide-iframe-overlay').show();
        },
        stop: function () {
            var width = $('#treeResizable').width();
            window.localStorage.setItem('vertx-rest-storage-editor.treeWidth', width);
            $('#editor-hide-iframe-overlay').hide();
        }
    });
    var width = window.localStorage.getItem('vertx-rest-storage-editor.treeWidth');
    if (width) {
        $('#treeResizable').width(width);
    }

    $('#dialogCreateResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });
    $('#dialogDeleteResource').dialog({
        autoOpen: false,
        modal: true,
        width: '50vw'
    });

    /**************************************************************************************************************
     * Setup jstree (see http://www.jstree.com)
     *************************************************************************************************************/
    var treeBase = getParameterByName('treeBase');
    if (!treeBase.endsWith('/')) {
        treeBase += '/';
    }
    var rootNodes = [{
        text: treeBase,
        data: {url: treeBase},
        icon: 'fa fa-folder',
        children: true
    }];

    try {
        var pinnedUrls = JSON.parse(window.localStorage.getItem('pinnedUrls'));
       pinnedUrls.forEach(function(url) {
           rootNodes.push({
               text: url,
               data: {url: url, pinned: true},
               children: url.endsWith('/')
           });
       });
    } catch (ignore) {
    }

    $('#tree').jstree({
        core: {
            /**************************************************************************************************************
             * basic settings for jstree
             *************************************************************************************************************/
            check_callback: true,
            animation: false,
            themes: {
                name: 'proton',
                responsive: true,
                dots : true,
                icons: true
            },
            /**************************************************************************************************************
             * the 'lazy' data loader - called automatically when opening an unloaded node
             * creates child nodes which are either nodes-with-children ('directory') or leafs ('resources')
             * We distinguish from vertx-rest-storage with a trailing slash (i.e. "img/" is a node-with-children while" "img" is a resource
             *************************************************************************************************************/
            data: function (node, callback) {
                if (node.id === '#') {
                    // initialize the one-and-only rood node
                    callback.call(this, rootNodes);
                    return;
                }

                var nodeUrl = node.data.url;
                var childrenNodes = [];
                function addEntriesToParentNode(entries) {
                    entries.forEach(function (c) {
                        var isLeaf = !c.endsWith('/');
                        var childNode = {
                            text: c,
                            data: {
                                url: nodeUrl + c
                            },
                            icon: isLeaf ? 'fa fa-file-text-o' : 'fa fa-folder',
                            children: !isLeaf   // to force jstree to show a '+' icon and to be able to open a not-yet loaded tree
                        };
                        childrenNodes.push(childNode);
                    });
                }

                $.get(nodeUrl, function success(data) {
                    for (var property in data) {
                        if (data.hasOwnProperty(property)) {
                            addEntriesToParentNode(data[property]);
                        }
                    }
                }).fail(function (err) {
                    // show a single red error children on AJAX error
                    childrenNodes.push({
                        text: err.responseText || err.statusText,
                        data: {url: nodeUrl + '[errorIndicator]'},
                        li_attr: {style: 'color: red;'},
                        icon: null
                    });
                }).always(function() {
                    callback.call(this, childrenNodes);
                });
            }
        },
        /**************************************************************************************************************
         * Context menu on every tree node
         *************************************************************************************************************/
        plugins: [ 'contextmenu'],
        contextmenu: {
            show_at_node: false,
            items: function (node) {
                var m = {};
                m.title = {label: node.data.url, separator_after: true, _disabled: true};
                m.pin = {
                    label: node.data.pinned ? 'Unpin this node' : 'Pin this node',
                    icon: 'fa fa-thumb-tack',
                    separator_after: true,
                    action: function () {
                        if (node.data.pinned) {
                            $('#tree').jstree().delete_node(node);
                        } else {
                            $('#tree').jstree().create_node('#', {
                                text: node.data.url,
                                icon: 'fa fa-thumb-tack',
                                data: {url: node.data.url, pinned: true}
                           });
                        }
                        // store list of pinned urls to localStorage
                        var pinnedUrls = [];
                        jstree.get_node('#').children.forEach(function(c) {
                            var n = jstree.get_node(c);
                            if (n.data.pinned) {
                                pinnedUrls.push(n.data.url);
                            }
                        });
                        window.localStorage.setItem('pinnedUrls', JSON.stringify(pinnedUrls));
                    }
                };
                if (node.data.url.endsWith('/')) {
                    m.create = {
                        label: 'Create resource',
                        action: function() {
                            $('#dialogCreateResource').dialog('option', 'position', {
                                my: 'left center',
                                at: 'left+150 top',
                                of: $('#tree').jstree().get_node(node, true),
                                collision: 'fit'
                            }).dialog('open');
                            $('#nameOfResourceToCreateBaseUrl').text(node.data.url);
                            $('#nameOfResourceToCreate').val('');
                        }
                    };
                }
                m.delete = {
                    label: node.data.url.endsWith('/') ? 'Delete whole tree' : 'Delete resource',
                    icon: 'fa fa-trash',
                    action: function() {
                        $('#dialogDeleteResource').dialog('option', 'position', {
                            my: 'left center',
                            at: 'left+150 top',
                            of: $('#tree').jstree().get_node(node, true),
                            collision: 'fit'
                        }).dialog('open');
                        $('#nameOfResourceToDelete').text(node.data.url);
                    }
                };
                return m;
            }
        }
    });

    var jstree = $('#tree').jstree();
    $('#tree').on('load_node.jstree', function (e, data) {
        var node = data.node;
        if (node.id === '#') {
            // open the root nodes automatically
            jstree.open_node(node.children[0]);
        }
    });

    $('#tree').on('after_open.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder-open');  // show the 'open' folder icon
        /**************************************************************************************************************
         * on page load we open the tree node-by-node to a preselected path
         * so we can 'stabilize' the view on "Browser refresh"
         *************************************************************************************************************/
        if (autoExpandToAndSelectPath) {
            for (var i = 0; i < node.children.length; i++) {
                var childNode = jstree.get_node(node.children[i]);
                var childUrl = childNode.data.url;
                if (autoExpandToAndSelectPath === childUrl) {
                    // found the target
                    node = childNode;
                    break;
                } else if (childUrl.endsWith('/') && autoExpandToAndSelectPath.indexOf(childUrl) === 0) {
                    // this is a child-node which matches the searched url - so open it (and we will be called again)
                    jstree.open_node(childNode);
                    return;
                }
            }
            // no children matches the path _or_ perfect match found
            autoExpandToAndSelectPath = null;
            jstree.select_node(node);
            var offset = jstree.get_node(node, true).offset();
            var height = $('#tree').height();
            $('#tree').scrollTop(offset.top - height / 3);
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        var node = data.node;
        jstree.set_icon(node,'fa fa-folder'); // show the 'closed' folder icon
    });
    $('#tree').on('select_node.jstree', function (e, data) {
        var node = data.node;
        $('#editor-iframe').attr('src', '');
        hash('selected', node.data.url);
        if (!node.data.url.endsWith('/')) {
            if (!node.data.url.endsWith('[errorIndicator]')) {
                openInEditor(node.data.url); // open in editor
            }
        } else if (data.node.state.loaded) {
            // hm... better to close the node - we can reload by open it again (as 'close' removes the childs)
            jstree.refresh_node(node);
        } else {
            jstree.open_node(node); // click on node-text to open subtree
        }
    });
    $('#tree').on('after_close.jstree', function (e, data) {
        // we only want to remove children to force fresh reload when opening node again
        // but this is slow in jstree --> we remove the whole node (which is quite fast) and re-insert a reincarnation of it @same position
        var node = data.node;
        var parentNode = jstree.get_node(jstree.get_parent(node));
        var pos = parentNode.children.indexOf(node.id);
        jstree.delete_node(node);
        var reincarnationNode = {
            text: node.text,
            data: node.data,
            state: {
                selected: node.state.selected
            },
            icon: node.icon,
            children: true
        };
        jstree.create_node(parentNode, reincarnationNode, pos);
    });
});

// toggle raw <-> editor mode
function toggleRawMode() {
    'use strict';
    $('#raw-mode-toggler').toggleClass('active');
    openInEditor();
}

// load node by id into the editor
function openInEditor(url) {
    'use strict';

    var rawMode = $('#raw-mode-toggler').hasClass('active');
    var editMode = !rawMode;
    if (url && editMode) {
        var editor = getParameterByName('editor') || 'editor.html';
        url = editor + '#' + url;
    }
    // $('#editor-iframe').attr('src', '');
    window.setTimeout(function () {
        $('#editor-iframe').attr('src', url);
    }, 10);
}<|endoftext|>


<commit_before>const FetchApi = function () {};

FetchApi.prototype = {

    getRequestOptions: function (method, token, content) {
        let options = {
            method: method,
            headers: this.getHeaders(token),
            mode: 'cors',
            cache: 'default',
            credentials: 'omit'
        };
        if (content !== '') {
            options = Object.assign(options, { body: JSON.stringify(content) });
        }
        return options;
    },

    getHeaders: function (token) {
        const headers = new Headers();
        headers.append('Accept', 'application/json');
        headers.append('Content-Type', 'application/json');
        if (token !== '') {
            headers.append('Authorization', `Bearer ${token}`);
        }
        return headers;
    },

    Patch: function (url, token, content) {
        return this.Fetch(url, 'PATCH', token, content);
    },

    Post: function (url, token, content) {
        return this.Fetch(url, 'POST', token, content);
    },

    Delete: function (url, token) {
        return this.Fetch(url, 'DELETE', token, '');
    },

    Get: function (url, token) {
        return this.Fetch(url, 'GET', token, '');
    },

    isEdge: function () {
        return /Edge/.test(navigator.userAgent);
    },

    Fetch: function (url, method, token, content) {
        const options = this.getRequestOptions(method, token, content);
        return this.isEdge()
            ? this.xhrFetch(url, options)
            : this.apiFetch(url, options);
    },

    apiFetch: (url, options) => fetch(url, options).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err))),

    xhrFetch: function (url, options) {
        return new Promise(function (resolve, reject) {
            const xhr = new XMLHttpRequest();
            // checks if CORS available
            if ('withCredentials' in xhr) {
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 && xhr.status < 400) {
                            resolve(JSON.parse(xhr.responseText)); // load();
                        } else {
                            reject(new Error(
                                `XHR error ${xhr.status || ''} ${xhr.statusText || ''} loading ${url}
                                ----
                                ${xhr.responseText}
                                ----`)); // error();
                        }
                    }
                };
                xhr.open(options.method, url, true);
                for (const key of options.headers.keys()) {
                    xhr.setRequestHeader(key, options.headers.get(key));
                }
                xhr.send(options.body);
            } else {
                reject(new Error('Browser doesn\'t suppotr CORS requests!'));
            }
        });
    }

};
<commit_msg>Old IE fetch code removed<commit_after>const FetchApi = function () {};

FetchApi.prototype = {

    getRequestOptions: function (method, token, content) {
        let options = {
            method: method,
            headers: this.getHeaders(token),
            mode: 'cors',
            cache: 'default',
            credentials: 'omit'
        };
        if (content !== '') {
            options = Object.assign(options, { body: JSON.stringify(content) });
        }
        return options;
    },

    getHeaders: function (token) {
        const headers = {
            Accept: 'application/json',
            'Content-Type': 'application/json'
        };
        if (token !== '') {
            headers.Authorization = `Bearer ${token}`;
        }
        return headers;
    },

    Patch: function (url, token, content) {
        return this.Fetch(url, 'PATCH', token, content);
    },

    Post: function (url, token, content) {
        return this.Fetch(url, 'POST', token, content);
    },

    Delete: function (url, token) {
        return this.Fetch(url, 'DELETE', token, '');
    },

    Get: function (url, token) {
        return this.Fetch(url, 'GET', token, '');
    },

    Fetch: function (url, method, token, content) {
        const options = this.getRequestOptions(method, token, content);
        return fetch(url, options).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)));
    }
};
<|endoftext|>


<commit_before>// This function will return "Hello World"
function helloworld(){
  return "Hello Famhi"
}
<commit_msg>Brach 2 merge conflict test.<commit_after>// This function will return "Hello World"
function helloworld(){
  return "Hello brach merge 2"
}
<|endoftext|>


<commit_before>
// HEX TO RGB
function hexToRgb(hex) {
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16),
        toString: function (alpha) {
            if (alpha == undefined) {
                return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
            }
            if (alpha > 1) {
                alpha = 1;
            } else if (alpha < 0) {
                alpha = 0;
            }
            return "rgb(" + this.r + ", " + this.g + ", " + this.b + ", " + alpha + ")";
        }
    } : null;
}

// RGB TO HEX
function rgbToHex(r, g, b) {
    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

/*
This function expects something in the range of

    rgba(255, 255, 0, 0.25)

This function is designed to be forgiving of rgba or rgb.
It will throw away the alpha layer.
*/
function rgbStringToHex(rgb) {
    rgbStringToHex(rgb);
}

function rgbaStringToHex(rgb) {
    var result = /^rgb[a]?\(([\d]+)[ \n]*,[ \n]*([\d]+)[ \n]*,[ \n]*([\d]+)[ \n]*,?[ \n]*([.\d]+)?[ \n]*\)$/i.exec(rgb);
    console.log(result);
    return rgbToHex(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]));
}

function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}
<commit_msg>Added an alpha parameter to the hexToRgb function.<commit_after>
// HEX TO RGB
function hexToRgb(hex, alpha) {
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    var toString = function () {
        if (this.alpha == undefined) {
            return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
        }
        if (this.alpha > 1) {
            this.alpha = 1;
        } else if (this.alpha < 0) {
            this.alpha = 0;
        }
        return "rgb(" + this.r + ", " + this.g + ", " + this.b + ", " + this.alpha + ")";
    }
    if (alpha == undefined) {
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16),
            toString: toString
        } : null;
    }
    if (alpha > 1) {
        alpha = 1;
    } else if (alpha < 0) {
        alpha = 0;
    }
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16),
        alpha: alpha,
        toString: toString
    } : null;
}

// RGB TO HEX
function rgbToHex(r, g, b) {
    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

/*
This function expects something in the range of

    rgba(255, 255, 0, 0.25)

This function is designed to be forgiving of rgba or rgb.
It will throw away the alpha layer.
*/
function rgbStringToHex(rgb) {
    rgbStringToHex(rgb);
}

function rgbaStringToHex(rgb) {
    var result = /^rgb[a]?\(([\d]+)[ \n]*,[ \n]*([\d]+)[ \n]*,[ \n]*([\d]+)[ \n]*,?[ \n]*([.\d]+)?[ \n]*\)$/i.exec(rgb);
    console.log(result);
    return rgbToHex(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]));
}

function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}
<|endoftext|>


<commit_before>'use strict';

import IndexHtml from 'html-webpack-plugin';
import webpack from 'webpack';
import {watch} from 'chokidar';
import {resolve} from 'path';
import {readFileSync} from 'fs';
import mime from 'mime';
import bundler from '../webpack.client.config';
import {socket, options, minify} from '../config';
import {green} from 'chalk';

export default notesPage;

function notesPage() {
  bundler.entry.app = `${process.cwd()}/${__dirname}/app.js`;
  bundler.output.path = `${process.cwd()}/notes/${options.env}`;
  bundler.plugins[1] = new IndexHtml({
    template: `${__dirname}/index.html`,
    inject: true,
    minify: minify.html,
  });

  // compile the module with webpack
  webpack(bundler, () => {
    // watch all hot update files in the compilation folder
    const hotUpdWatch = watch('*.hot-update.json', {
      cwd: `${process.cwd()}/${__dirname}/${options.env}`,
      // ignore hidden files
      ignored: /^\./,
    });

    socket.on('connection', io => {
      // whenever a hot-update file gets created, emit a hot-update event to all
      // sockets connected to this page
      hotUpdWatch.on('add', () => {
        console.log(green('File changed'));

        io.emit('hot-update');
      });
    });
  });

  return async (ctx, next) => {
    // we only deal with GET requests here
    if(ctx.method !== 'GET') {
      await next();
    }

    const path = resolve(ctx.path);
    if(path === '/' || path === '/index.html') {
      ctx.type = 'html';
      ctx.body = readFileSync(`${__dirname}/${options.env}/index.html`, 'utf-8');
    } else {
      ctx.type = mime.lookup(path);
      ctx.body = readFileSync(`${__dirname}/${options.env}/${path}`, 'utf-8');
    }

    await next();
  };
}
<commit_msg>Removed the notes folder entirely, now that the home folder is the main page<commit_after>'use strict';

import IndexHtml from 'html-webpack-plugin';
import webpack from 'webpack';
import {watch} from 'chokidar';
import {resolve} from 'path';
import {readFileSync} from 'fs';
import mime from 'mime';
import bundler from '../webpack.client.config';
import {socket, options, minify} from '../config';
import {green} from 'chalk';

export default homePage;

function homePage() {
  bundler.entry.app = `${process.cwd()}/${__dirname}/app.js`;
  bundler.output.path = `${process.cwd()}/home/${options.env}`;
  bundler.plugins[1] = new IndexHtml({
    template: `${__dirname}/index.html`,
    inject: true,
    minify: minify.html,
  });

  // compile the module with webpack
  webpack(bundler, () => {
    // watch all hot update files in the compilation folder
    const hotUpdWatch = watch('*.hot-update.json', {
      cwd: `${process.cwd()}/${__dirname}/${options.env}`,
      // ignore hidden files
      ignored: /^\./,
    });

    socket.on('connection', io => {
      // whenever a hot-update file gets created, emit a hot-update event to all
      // sockets connected to this page
      hotUpdWatch.on('add', () => {
        console.log(green('File changed'));

        io.emit('hot-update');
      });
    });
  });

  return async (ctx, next) => {
    // we only deal with GET requests here
    if(ctx.method !== 'GET') {
      await next();
    }

    const path = resolve(ctx.path);
    if(path === '/' || path === '/index.html') {
      ctx.type = 'html';
      ctx.body = readFileSync(`${__dirname}/${options.env}/index.html`, 'utf-8');
    } else {
      ctx.type = mime.lookup(path);
      ctx.body = readFileSync(`${__dirname}/${options.env}/${path}`, 'utf-8');
    }

    await next();
  };
}
<|endoftext|>


<commit_before>/**
 * Ponyville Live! Header Banner Include
 * Requires jQuery 1.8+
 *
 * Usage:
 * Immediately after  tag, add:
 * Ponyville Live!
 *
 */

if (jQuery) {

    var pvl_static_base = '//ponyvillelive.com/static';

	(function($) {

		// Load supporting CSS.
		$("head").append("<link rel='stylesheet' href='"+pvl_static_base+"/header/header.css' type='text/css' media='screen'>");

        // Move existing link to top of body if detected, or recreate.
        if ($('#pvl_header_link').length > 0)
            $(document.body).prepend($('#pvl_header_link').detach());
        else
            $(document.body).prepend('Ponyville Live!');

        var header_link = $('#pvl_header_link');
        header_link.wrap('
').wrap('
');
        header_link.html('');

	})(jQuery);

}<commit_msg>Minor spacing fix on header script.<commit_after>/**
 * Ponyville Live! Header Banner Include
 * Requires jQuery 1.8+
 *
 * Usage:
 * Immediately after  tag, add:
 * Ponyville Live!
 *
 */

if (jQuery) {

    var pvl_static_base = '//ponyvillelive.com/static';

    (function($) {

        // Load supporting CSS.
        $("head").append("<link rel='stylesheet' href='"+pvl_static_base+"/header/header.css' type='text/css' media='screen'>");

        // Move existing link to top of body if detected, or recreate.
        if ($('#pvl_header_link').length > 0)
            $(document.body).prepend($('#pvl_header_link').detach());
        else
            $(document.body).prepend('Ponyville Live!');

        var header_link = $('#pvl_header_link');
        header_link.wrap('
').wrap('
');
        header_link.html('');

    })(jQuery);

}<|endoftext|>


<commit_before>import React from 'react';

import { Putro } from 'CONTRIBUTORS';
import SpellLink from 'common/SpellLink';
import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import ItemLink from 'common/ItemLink';

export default [
  {
    date: new Date('2018-07-24'),
    changes: <React.Fragment>Implements better <SpellLink id={SPELLS.SERPENT_STING_SV.id} /> handling, aswell as <SpellLink id={SPELLS.VIPERS_VENOM_TALENT.id} /> support. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-07-23'),
    changes: 'Survival analyzer updated to be 8.0.1 compatible',
    contributors: [Putro],
  },
  {
    date: new Date('2018-04-22'),
    changes: <React.Fragment>Implements the checklist for Survival. Fixes a display bug with <SpellLink id={SPELLS.ASPECT_OF_THE_EAGLE.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-04-10'),
    changes: <React.Fragment>Adds a <SpellLink id={SPELLS.ASPECT_OF_THE_EAGLE.id} /> module to provide suggestions with poor usage, and also updates Way of the Mok'Nathal module to be more accurate when displaying refreshes.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-04-05'),
    changes: <React.Fragment>Added tracking for <SpellLink id={SPELLS.ON_THE_TRAIL_DAMAGE.id} icon /> and Lacerate to help identify when you're casting this too much. Added additional refreshing information into Way of the Mok'Nathal module, aswell as average time remaining on <SpellLink id={SPELLS.MONGOOSE_FURY.id} icon /> upon using <SpellLink id={SPELLS.FURY_OF_THE_EAGLE_TRAIT.id} icon /> and other minor behind the scenes updates. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-20'),
    changes: <React.Fragment>Spring cleaning in many modules. Added icons to Focus Usage modules and elsewhere around the analyzer and added support for Caltrops.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-14'),
    changes: <React.Fragment>Added a module for <SpellLink id={SPELLS.FURY_OF_THE_EAGLE_TRAIT.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-12'),
    changes: <React.Fragment>Added modules for Mortal Wounds and merged <SpellLink id={SPELLS.CARVE.id} /> and <SpellLink id={SPELLS.BUTCHERY_TALENT.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-12'),
    changes: <React.Fragment>Added support for the most prominent traits into the listbox <SpellLink id={SPELLS.ASPECT_OF_THE_SKYLORD_TRAIT.id} />, <SpellLink id={SPELLS.EAGLES_BITE_TRAIT.id} />, <SpellLink id={SPELLS.ECHOES_OF_OHNARA_TRAIT.id} />, <SpellLink id={SPELLS.TALON_BOND_TRAIT.id} />, <SpellLink id={SPELLS.TALON_STRIKE_TRAIT.id} />. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-11'),
    changes: <React.Fragment>Added support for <SpellLink id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id} />, <SpellLink id={SPELLS.SERPENT_STING_TALENT.id} />, A Murder of Crows, Dragonsfire Grenade, Throwing Axes into the Talents/Trait listbox.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-11'),
    changes: <React.Fragment>Added a preliminary Talents and Traits list which will include damage information about various talents and traits as they get implemented. Implemented modules for <SpellLink id={SPELLS.STEEL_TRAP_TALENT.id} />, Explosive Trap, Caltrops and added prepull handling for all three. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-05'),
    changes: <React.Fragment>Added additional information to the <ItemLink id={ITEMS.CALL_OF_THE_WILD.id} /> module, to show cooldown reduction on the various affected spells. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-02'),
    changes: <React.Fragment>Added a module for tracking <SpellLink id={SPELLS.SPITTING_COBRA_TALENT.id} />, and ensure cast efficiency works properly for the talent even if precast. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-02'),
    changes: <React.Fragment>Added support for <ItemLink id={ITEMS.BUTCHERS_BONE_APRON.id} />, <ItemLink id={ITEMS.FRIZZOS_FINGERTRAP.id} />, <ItemLink id={ITEMS.HELBRINE_ROPE_OF_THE_MIST_MARAUDER.id} />, <ItemLink id={ITEMS.NESINGWARYS_TRAPPING_TREADS.id} />, <ItemLink id={ITEMS.UNSEEN_PREDATORS_CLOAK.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-31'),
    changes: <React.Fragment>Added a module for tracking Way of the Mok'Nathal. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-30'),
    changes: <React.Fragment>Added two statistic modules for <SpellLink id={SPELLS.MONGOOSE_FURY.id} /></React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-30'),
    changes: 'Added a focus usage chart to track what you\'re spending your focus on',
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-18'),
    changes: <React.Fragment>Added support for <SpellLink id={SPELLS.HUNTER_SV_T20_2P_BONUS.id} />, <SpellLink id={SPELLS.HUNTER_SV_T20_4P_BONUS.id} />, <SpellLink id={SPELLS.HUNTER_SV_T21_2P_BONUS.id} />, <SpellLink id={SPELLS.HUNTER_SV_T21_4P_BONUS.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-17'),
    changes: 'Initial support of survival.',
    contributors: [Putro],
  },
];
<commit_msg>update changelog<commit_after>import React from 'react';

import { Putro } from 'CONTRIBUTORS';
import SpellLink from 'common/SpellLink';
import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import ItemLink from 'common/ItemLink';

export default [
  {
    date: new Date('2018-07-30'),
    changes: <React.Fragment>Updates GCD for <SpellLink id={SPELLS.HARPOON.id} /> and updates cast efficiency for a few spells. Adds a <SpellLink id={SPELLS.BIRDS_OF_PREY_TALENT.id} /> module into the tooltip for <SpellLink id={SPELLS.COORDINATED_ASSAULT.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-07-30'),
    changes: <React.Fragment>Adds average targets hit for <SpellLink id={SPELLS.CHAKRAMS_TALENT.id} />, <SpellLink id={SPELLS.WILDFIRE_BOMB.id} />, <SpellLink id={SPELLS.BUTCHERY_TALENT.id} /> and <SpellLink id={SPELLS.CARVE.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-07-30'),
    changes: <React.Fragment>Adds <SpellLink id={SPELLS.STEEL_TRAP_TALENT.id} /> to Traits and Talents list, and adds a check/suggestion whether casting <SpellLink id={SPELLS.WILDFIRE_BOMB.id} /> was the right choice for the player.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-07-30'),
    changes: <React.Fragment>Adds two modules for <SpellLink id={SPELLS.MONGOOSE_BITE_TALENT.id} /> to track its efficiency, and also checks for <SpellLink id={SPELLS.SERPENT_STING_SV.id} /> casts without <SpellLink id={SPELLS.VIPERS_VENOM_TALENT.id} /> buff up during <SpellLink id={SPELLS.MONGOOSE_FURY.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-07-24'),
    changes: <React.Fragment>Implements better <SpellLink id={SPELLS.SERPENT_STING_SV.id} /> handling, aswell as <SpellLink id={SPELLS.VIPERS_VENOM_TALENT.id} /> support. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-07-23'),
    changes: 'Survival analyzer updated to be 8.0.1 compatible',
    contributors: [Putro],
  },
  {
    date: new Date('2018-04-22'),
    changes: <React.Fragment>Implements the checklist for Survival. Fixes a display bug with <SpellLink id={SPELLS.ASPECT_OF_THE_EAGLE.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-04-10'),
    changes: <React.Fragment>Adds a <SpellLink id={SPELLS.ASPECT_OF_THE_EAGLE.id} /> module to provide suggestions with poor usage, and also updates Way of the Mok'Nathal module to be more accurate when displaying refreshes.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-04-05'),
    changes: <React.Fragment>Added tracking for <SpellLink id={SPELLS.ON_THE_TRAIL_DAMAGE.id} icon /> and Lacerate to help identify when you're casting this too much. Added additional refreshing information into Way of the Mok'Nathal module, aswell as average time remaining on <SpellLink id={SPELLS.MONGOOSE_FURY.id} icon /> upon using <SpellLink id={SPELLS.FURY_OF_THE_EAGLE_TRAIT.id} icon /> and other minor behind the scenes updates. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-20'),
    changes: <React.Fragment>Spring cleaning in many modules. Added icons to Focus Usage modules and elsewhere around the analyzer and added support for Caltrops.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-14'),
    changes: <React.Fragment>Added a module for <SpellLink id={SPELLS.FURY_OF_THE_EAGLE_TRAIT.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-12'),
    changes: <React.Fragment>Added modules for Mortal Wounds and merged <SpellLink id={SPELLS.CARVE.id} /> and <SpellLink id={SPELLS.BUTCHERY_TALENT.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-12'),
    changes: <React.Fragment>Added support for the most prominent traits into the listbox <SpellLink id={SPELLS.ASPECT_OF_THE_SKYLORD_TRAIT.id} />, <SpellLink id={SPELLS.EAGLES_BITE_TRAIT.id} />, <SpellLink id={SPELLS.ECHOES_OF_OHNARA_TRAIT.id} />, <SpellLink id={SPELLS.TALON_BOND_TRAIT.id} />, <SpellLink id={SPELLS.TALON_STRIKE_TRAIT.id} />. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-11'),
    changes: <React.Fragment>Added support for <SpellLink id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id} />, <SpellLink id={SPELLS.SERPENT_STING_TALENT.id} />, A Murder of Crows, Dragonsfire Grenade, Throwing Axes into the Talents/Trait listbox.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-11'),
    changes: <React.Fragment>Added a preliminary Talents and Traits list which will include damage information about various talents and traits as they get implemented. Implemented modules for <SpellLink id={SPELLS.STEEL_TRAP_TALENT.id} />, Explosive Trap, Caltrops and added prepull handling for all three. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-05'),
    changes: <React.Fragment>Added additional information to the <ItemLink id={ITEMS.CALL_OF_THE_WILD.id} /> module, to show cooldown reduction on the various affected spells. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-02'),
    changes: <React.Fragment>Added a module for tracking <SpellLink id={SPELLS.SPITTING_COBRA_TALENT.id} />, and ensure cast efficiency works properly for the talent even if precast. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-02-02'),
    changes: <React.Fragment>Added support for <ItemLink id={ITEMS.BUTCHERS_BONE_APRON.id} />, <ItemLink id={ITEMS.FRIZZOS_FINGERTRAP.id} />, <ItemLink id={ITEMS.HELBRINE_ROPE_OF_THE_MIST_MARAUDER.id} />, <ItemLink id={ITEMS.NESINGWARYS_TRAPPING_TREADS.id} />, <ItemLink id={ITEMS.UNSEEN_PREDATORS_CLOAK.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-31'),
    changes: <React.Fragment>Added a module for tracking Way of the Mok'Nathal. </React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-30'),
    changes: <React.Fragment>Added two statistic modules for <SpellLink id={SPELLS.MONGOOSE_FURY.id} /></React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-30'),
    changes: 'Added a focus usage chart to track what you\'re spending your focus on',
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-18'),
    changes: <React.Fragment>Added support for <SpellLink id={SPELLS.HUNTER_SV_T20_2P_BONUS.id} />, <SpellLink id={SPELLS.HUNTER_SV_T20_4P_BONUS.id} />, <SpellLink id={SPELLS.HUNTER_SV_T21_2P_BONUS.id} />, <SpellLink id={SPELLS.HUNTER_SV_T21_4P_BONUS.id} />.</React.Fragment>,
    contributors: [Putro],
  },
  {
    date: new Date('2018-01-17'),
    changes: 'Initial support of survival.',
    contributors: [Putro],
  },
];
<|endoftext|>


<commit_before>//module.exports = function(){
	var htmlparser = require("htmlparser");
	var fs = require('fs');
	var rawHtml = fs.readFileSync('./data/formResponses1.html');
	debugger;

	var handler = new htmlparser.DefaultHandler(function (error, dom) {
	    if (error){

	    } else {

	    }
	});
	var parser = new htmlparser.Parser(handler);
	parser.parseComplete(rawHtml);

	var inputArray = [];
	var inputRow = {};
	var headerRowArray = handler.dom[4].children[0].children[1].children[0].children;

	for (i=1; i<headerRowArray.length; i++){
		var prefix = headerRowArray[i].children[0];
		if (prefix.type === "tag"){
			prefix = headerRowArray[i].children[0].children[0];
		}
		inputRow[prefix.data] = '';
	}

	//sys.puts(sys.inspect(handler.dom, false, null));
//}<commit_msg>successfully parsed html file into javavascript data structure<commit_after>//module.exports = function(){
	var htmlparser = require("htmlparser");
	var fs = require('fs');
	var rawHtml = fs.readFileSync('./data/formResponses1.html');

	var handler = new htmlparser.DefaultHandler(function (error, dom) {
	    if (error){

	    } else {

	    }
	});
	var parser = new htmlparser.Parser(handler);
	parser.parseComplete(rawHtml);

	var inputArray = [];
	var inputRow = [];
	var headerRowArray = handler.dom[4].children[0].children[1].children[0].children;

	for (i=1; i<headerRowArray.length; i++){
		var prefix = headerRowArray[i].children[0];
		if (prefix.type === "tag"){
			prefix = headerRowArray[i].children[0].children[0];
		}
		inputRow.push(prefix.data);
	}

	var tableArray = handler.dom[4].children[0].children[1].children;
	for (rowIdx = 2; rowIdx<tableArray.length; rowIdx++){
		var rowArray = tableArray[rowIdx].children;
		var newRowObject = {};
		for (cellIdx=1; cellIdx<rowArray.length; cellIdx++){
			if (typeof rowArray[cellIdx].children !== 'undefined'){
				prefix = rowArray[cellIdx].children[0];
				if (prefix.type === "tag"){
					prefix = rowArray[cellIdx].children[0].children[0];
				}
				newRowObject[inputRow[cellIdx-1]] = prefix.data;
				//console.log('cell contents: ', prefix.data);
			} else {
				newRowObject[inputRow[cellIdx-1]] = '';
			}
		}
		inputArray.push(newRowObject);

	}
	debugger;
	//sys.puts(sys.inspect(handler.dom, false, null));
//}<|endoftext|>