<commit_before>"use strict";

/** Import an orthogonal tilemap from Tiled: Map Editor and draw on the screen
 * @constructor
 * @alias Splat.Tilemap
 * @param {Object} file JSON file exported from Tiled. This should be required in a scene enter
 * script and passed to the function.
 * @param {EntityPool} entities EntityPool from game.entities
 */
function ImportTilemap(file, entities) { // eslint-disable-line no-unused-vars

	var tile, image, image_index, tile_pos, cols, tileset, tileset_index = 0;
	var collider, layer, object, entity;

	for (var i = 0; i < file.layers.length; i++) {
		layer = file.layers[i];

		// Render Tile Layers
		if (layer.type == "tilelayer") {
			for (j = 0; j < layer.data.length; j++) {

				// Select tileset index based on firstgid and image index
				// Set image index minus firstgid for positioning math
				for (var k = 0; k < file.tilesets.length; k++) {
					if (layer.data[j] > file.tilesets[k].firstgid) {
						tileset_index = k;
					}
				}
				cols = file.tilesets[tileset_index].imagewidth / file.tilesets[tileset_index].tilewidth;
				image_index = layer.data[j] - file.tilesets[tileset_index].firstgid;
				tileset = file.tilesets[tileset_index];

				if (image_index >= 0) {

					// Create tile and get properties
					tile = entities.create();
					entities.set(tile, "name", "tile");
					entities.set(tile, "tile", true);
					entities.set(tile, "image", {"name": ""});
					entities.set(tile, "position", {"x": 0, "y": 0});
					image = entities.get(tile, "image");
					tile_pos = entities.get(tile, "position");

					// Position based on index
					tile_pos.x = (j % file.width) * file.tilewidth;
					tile_pos.y = Math.floor(j / file.width) * file.tileheight;

					// Character position z: 1 so anything without background true will layer over player
					tile_pos.z = (layer.properties.Background == "True") ? -1 : 2;

					// Select which "tile" of the tileset image to render
					image.name = tileset.image;
					image.sourceWidth = tileset.tilewidth;
					image.sourceHeight = tileset.tileheight;
					image.destinationWidth = tileset.tilewidth;
					image.destinationHeight = tileset.tileheight;
					image.sourceX = (image_index % cols) * tileset.tilewidth + ((image_index % cols) * tileset.spacing) + tileset.margin;
					image.sourceY = Math.floor(image_index / cols) * tileset.tileheight + (Math.floor(image_index / cols) * tileset.spacing) + tileset.margin;

				}
			}
		}

		// Loop object layer for collisions and spawn point
		// TODO Bug spawn chance triggers, doors, switches (buttons), warp zones, NPC Spawn points
		if (layer.type == "objectgroup") {
			for (var j = 0; j < layer.objects.length; j++) {
				object = layer.objects[j];
				entity = entities.create();
				entities.set(entity, "size", { "width": object.width, "height": object.height });
				entities.set(entity, "position", { "x": object.x, "y": object.y });
				Object.keys(object.properties).forEach(function(key) {
					if(!isNaN(object.properties[key])) {
						object.properties[key] = parseInt(object.properties[key], 10);
					}
					if(new String(object.properties[key]).toLowerCase() == "true" || object.properties[key] == "1") {
						object.properties[key] = true;
					}
					if(new String(object.properties[key]).toLowerCase() == "false" || object.properties[key] == "0") {
						object.properties[key] = false;
					}
				});
				entities.set(entity, "tiled_properties", object.properties);

				// Collision box prefabs
				if (object.properties.Collidable) {
					collider = entities.create();
					entities.set(entity, "name", "collider");
					entities.set(entity, "collisions", []);
				}

				// Spawn points
				if (object.properties.Spawn) {
					var spawn = entities.create();
					entities.set(entity, "name", "spawn");
					entities.set(entity, "spawn", true);
				}
			}
		}
	}

	var map_size = {
		"width": file.width * file.tilewidth,
		"height": file.height * file.tileheight
	};
	var container = entities.create();
	entities.set(container, "name", "container");
	entities.set(container, "container", true);
	entities.set(container, "position", {"x": 0, "y": 0});
	entities.set(container, "size", map_size);

}

module.exports = ImportTilemap;
<commit_msg>documentation<commit_after>"use strict";

/** Import an orthogonal tilemap from Tiled: Map Editor and draw on the screen
 * @module Import From Tiled
 * @param {Object} file JSON file exported from Tiled. This should be required in a scene enter
 * script and passed to the function.
 * @param {EntityPool} entities EntityPool from game.entities
 */
function ImportTilemap(file, entities) { // eslint-disable-line no-unused-vars

	var tile, image, image_index, tile_pos, cols, tileset, tileset_index = 0;
	var layer, object, entity;

	for (var i = 0; i < file.layers.length; i++) {
		layer = file.layers[i];

		// Render Tile Layers
		if (layer.type == "tilelayer") {
			for (j = 0; j < layer.data.length; j++) {

				// Select tileset index based on firstgid and image index
				// Set image index minus firstgid for positioning math
				for (var k = 0; k < file.tilesets.length; k++) {
					if (layer.data[j] > file.tilesets[k].firstgid) {
						tileset_index = k;
					}
				}
				cols = file.tilesets[tileset_index].imagewidth / file.tilesets[tileset_index].tilewidth;
				image_index = layer.data[j] - file.tilesets[tileset_index].firstgid;
				tileset = file.tilesets[tileset_index];

				if (image_index >= 0) {

					// Create tile and get properties
					tile = entities.create();
					entities.set(tile, "name", "tile");
					entities.set(tile, "tile", true);
					entities.set(tile, "image", { "name": "" });
					entities.set(tile, "position", { "x": 0, "y": 0 });
					image = entities.get(tile, "image");
					tile_pos = entities.get(tile, "position");

					// Position based on index
					tile_pos.x = (j % file.width) * file.tilewidth;
					tile_pos.y = Math.floor(j / file.width) * file.tileheight;

					// Character position z: 1 so anything without background true will layer over player
					tile_pos.z = (layer.properties.Background == "True") ? -1 : 2;

					// Select which "tile" of the tileset image to render
					image.name = tileset.image;
					image.sourceWidth = tileset.tilewidth;
					image.sourceHeight = tileset.tileheight;
					image.destinationWidth = tileset.tilewidth;
					image.destinationHeight = tileset.tileheight;
					image.sourceX = (image_index % cols) * tileset.tilewidth + ((image_index % cols) * tileset.spacing) + tileset.margin;
					image.sourceY = Math.floor(image_index / cols) * tileset.tileheight + (Math.floor(image_index / cols) * tileset.spacing) + tileset.margin;

				}
			}
		}

		/**
		 * Collidable: True or False
Cause this object to have a collision component. Currently collisions are handled as a simulation system in the project.
		 *
All other properties end up in a "tiled_properties" component to be handled on a per-game basis.
		 * @function Object Properties:
		 */
		// Loop object layer for collisions and spawn point
		if (layer.type == "objectgroup") {
			for (var j = 0; j < layer.objects.length; j++) {
				object = layer.objects[j];
				entity = entities.create();
				entities.set(entity, "size", { "width": object.width, "height": object.height });
				entities.set(entity, "position", { "x": object.x, "y": object.y });
				Object.keys(object.properties).forEach(function(key) {
					if (!isNaN(object.properties[key])) {
						object.properties[key] = parseInt(object.properties[key], 10);
					}
					if (new String(object.properties[key]).toLowerCase() == "true" || object.properties[key] == "1") {
						object.properties[key] = true;
					}
					if (new String(object.properties[key]).toLowerCase() == "false" || object.properties[key] == "0") {
						object.properties[key] = false;
					}
				});
				entities.set(entity, "tiled_properties", object.properties);

				// Collision box prefabs
				if (object.properties.Collidable) {
					entities.set(entity, "name", "collider");
					entities.set(entity, "collisions", []);
				}

				// Spawn points
				if (object.properties.Spawn) {
					entities.set(entity, "name", "spawn");
					entities.set(entity, "spawn", true);
				}
			}
		}
	}

	var map_size = {
		"width": file.width * file.tilewidth,
		"height": file.height * file.tileheight
	};
	var container = entities.create();
	entities.set(container, "name", "container");
	entities.set(container, "container", true);
	entities.set(container, "position", { "x": 0, "y": 0 });
	entities.set(container, "size", map_size);

}

module.exports = ImportTilemap;
<|endoftext|>


<commit_before>const https = require('https')
const mkdirp = require('mkdirp')
const tar = require('tar')
const npmrc = require('../utils/npmrc')
const { URL } = require('url')
const path = require('path')
const nm = require('../utils/nm')
const bin = require('./bin')

const installer = (dep, deps, base, resolve, reject) => {
  mkdirp.sync(nm)
  mkdirp.sync(path.join(nm, '.bin'))
  const target = (base.length === 0)
    ? path.join(nm, dep)
    : path.join(nm, base.join('/'), 'node_modules', dep)
  const url = new URL(deps[dep].tarball)
  mkdirp.sync(target)

if (base.length > 0) console.log(target)

  https.get({
    host: url.host,
    path: url.pathname,
    headers: npmrc.userAgent
    }, (res) => {
    res.pipe(
      tar.extract({
        cwd: target,
        sync: true,
        strip: 1
      })
    )
    res.on('end', () => {
      global.dependenciesCount += 1
      bin(dep, target)
      if (!deps[dep].dependencies) return resolve()
      const tasks = Object.keys(deps[dep].dependencies).map((item) => {
        const list = deps[dep].dependencies
        let keys = [].concat(base, dep)
        if (keys.length > 1) keys.splice(-1, 0, 'node_modules')
        return new Promise((resolve, reject) => {
          installer(item, list, keys, resolve, reject)
        })
      })
    })
  }).on('error', reject)
}

module.exports = (deps) => {
  return Object.keys(deps).map((dep) => {
    return new Promise((resolve, reject) => installer(dep, deps, [], resolve, reject))
  })
}
<commit_msg>remove unused console.log<commit_after>const https = require('https')
const mkdirp = require('mkdirp')
const tar = require('tar')
const npmrc = require('../utils/npmrc')
const { URL } = require('url')
const path = require('path')
const nm = require('../utils/nm')
const bin = require('./bin')

const installer = (dep, deps, base, resolve, reject) => {
  mkdirp.sync(nm)
  mkdirp.sync(path.join(nm, '.bin'))
  const target = (base.length === 0)
    ? path.join(nm, dep)
    : path.join(nm, base.join('/'), 'node_modules', dep)
  const url = new URL(deps[dep].tarball)
  mkdirp.sync(target)

  https.get({
    host: url.host,
    path: url.pathname,
    headers: npmrc.userAgent
    }, (res) => {
    res.pipe(
      tar.extract({
        cwd: target,
        sync: true,
        strip: 1
      })
    )
    res.on('end', () => {
      global.dependenciesCount += 1
      bin(dep, target)
      if (!deps[dep].dependencies) return resolve()
      const tasks = Object.keys(deps[dep].dependencies).map((item) => {
        const list = deps[dep].dependencies
        let keys = [].concat(base, dep)
        if (keys.length > 1) keys.splice(-1, 0, 'node_modules')
        return new Promise((resolve, reject) => {
          installer(item, list, keys, resolve, reject)
        })
      })
    })
  }).on('error', reject)
}

module.exports = (deps) => {
  return Object.keys(deps).map((dep) => {
    return new Promise((resolve, reject) => installer(dep, deps, [], resolve, reject))
  })
}
<|endoftext|>


<commit_before>// Miscellaneous core Javascript functions for Moodle

function popupchecker(msg) {
    var testwindow = window.open('itestwin.html', '', 'width=1,height=1,left=0,top=0,scrollbars=no');
    if (testwindow == null)
        {alert(msg);}
    else {
        testwindow.close();
    }
}

/*
function popUpProperties(inobj) {
/// Legacy function
  var op = window.open();
  op.document.open('text/plain');
  for (objprop in inobj) {
    op.document.write(objprop + ' => ' + inobj[objprop] + '\n');
  }
  op.document.close();
}

function fillmessagebox(text) {
/// Legacy function
  document.form.message.value = text;
}

function copyrichtext(textname) {
/// Legacy stub for old editor - to be removed soon
  return true;
}
*/

function checkall() {
  var el = document.getElementsByTagName('input');
  for(var i=0; i<el.length; i++) {
    if(el[i].type == 'checkbox') {
      el[i].checked = true;
    }
  }
}

function checknone() {
  var el = document.getElementsByTagName('input');
  for(var i=0; i<el.length; i++) {
    if(el[i].type == 'checkbox') {
      el[i].checked = false;
    }
  }
}

function lockoptions(formid, master, subitems) {
  // Subitems is an array of names of sub items.
  // Optionally, each item in subitems may have a
  // companion hidden item in the form with the
  // same name but prefixed by "h".
  var form = document.forms[formid];

  if (eval("form."+master+".checked")) {
    for (i=0; i<subitems.length; i++) {
      unlockoption(form, subitems[i]);
    }
  } else {
    for (i=0; i<subitems.length; i++) {
      lockoption(form, subitems[i]);
    }
  }
  return(true);
}

function lockoption(form,item) {
  eval("form."+item+".disabled=true");/* IE thing */
  if(form.elements['h'+item]) {
    eval("form.h"+item+".value=1");
  }
}

function unlockoption(form,item) {
  eval("form."+item+".disabled=false");/* IE thing */
  if(form.elements['h'+item]) {
    eval("form.h"+item+".value=0");
  }
}

function lockoptionsall(formid) {
    var form = document.forms[formid];
    var dependons = eval(formid+'items');
    for (var dependon in dependons) {
        var master = form[dependon];
        for (var condition in dependons[dependon]) {
            for (var value in dependons[dependon][condition]) {
                var lock;
                switch (condition) {
                  case 'notchecked':
                      lock = !master.checked; break;
                  case 'checked':
                      lock = master.checked; break;
                  case 'noitemselected':
                      lock = master.selectedIndex==-1; break;
                  case 'eq':
                      lock = master.value==value; break;
                  default:
                      lock = master.value!=value; break;
                }
                for (var ei in dependons[dependon][condition][value]) {
                    var formelement = form[dependons[dependon][condition][value][ei]];
                    formelement.disabled = lock;
                }
            }
        }
    }
    return true;
}

function lockoptionsallsetup(formid) {
    var form = document.forms[formid];
    var dependons = eval(formid+'items');
    for (var dependon in dependons) {
        var master = form[dependon];
        master.onclick  = function() {return lockoptionsall(this.form.getAttribute('id'));};
        master.onblur   = function() {return lockoptionsall(this.form.getAttribute('id'));};
        master.onchange = function() {return lockoptionsall(this.form.getAttribute('id'));};
    }
    for (var i = 0; i < form.elements.length; i++){
        var formelement = form.elements[i];
        if (formelement.type=='reset') {
            formelement.onclick  = function() {this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
            formelement.onblur   = function() {this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
            formelement.onchange = function() {this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
        }
    }
    return lockoptionsall(formid);
}

function submitFormById(id) {
    var theform = document.getElementById(id);
    if(!theform) {
        return false;
    }
    if(theform.tagName != 'form') {
        return false;
    }
    if(!theform.onsubmit || theform.onsubmit()) {
        return theform.submit();
    }
}

function select_all_in(elTagName, elClass, elId) {
    var inputs = document.getElementsByTagName('input');
    inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
    for(var i = 0; i < inputs.length; ++i) {
        if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
            inputs[i].checked = 'checked';
        }
    }
}

function deselect_all_in(elTagName, elClass, elId) {
    var inputs = document.getElementsByTagName('INPUT');
    inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
    for(var i = 0; i < inputs.length; ++i) {
        if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
            inputs[i].checked = '';
        }
    }
}

function confirm_if(expr, message) {
    if(!expr) {
        return true;
    }
    return confirm(message);
}

/*
    findParentNode (start, elementName, elementClass, elementID)

    Travels up the DOM hierarchy to find a parent element with the
    specified tag name, class, and id. All conditions must be met,
    but any can be ommitted. Returns the BODY element if no match
    found.
*/
function findParentNode(el, elName, elClass, elId) {
    while(el.nodeName != 'BODY') {
        if(
            (!elName || el.nodeName == elName) &&
            (!elClass || el.className.indexOf(elClass) != -1) &&
            (!elId || el.id == elId))
        {
            break;
        }
        el = el.parentNode;
    }
    return el;
}
/*
    findChildNode (start, elementName, elementClass, elementID)

    Travels down the DOM hierarchy to find all child elements with the
    specified tag name, class, and id. All conditions must be met,
    but any can be ommitted.
    Doesn't examine children of matches.
*/
function findChildNodes(start, tagName, elementClass, elementID, elementName) {
    var children = new Array();
    for (var childIndex in start.childNodes) {
        var classfound = false;
        var child = start.childNodes[childIndex];
        if((child.nodeType == 1) &&//element node type
                  (elementClass && (typeof(child.className)=='string'))){
            var childClasses = child.className.split(/\s+/);
            for (var childClassIndex in childClasses){
                if (childClasses[childClassIndex]==elementClass){
                    classfound = true;
                    break;
                }
            }
        }
        if(child.nodeType == 1) { //element node type
            if  ( (!tagName || child.nodeName == tagName) &&
                (!elementClass || classfound)&&
                (!elementID || child.id == elementID) &&
                (!elementName || child.name == elementName))
            {
                children = children.concat(child);
            } else {
                children = children.concat(findChildNodes(child, tagName, elementClass, elementID, elementName));
            }
        }
    }
    return children;
}
/*
    elementSetHide (elements, hide)

    Adds or removes the "hide" class for the specified elements depending on boolean hide.
*/
function elementShowAdvanced(elements, show) {
    for (var elementIndex in elements){
        element = elements[elementIndex];
        element.className = element.className.replace(new RegExp(' ?hide'), '')
        if(!show) {
            element.className += ' hide';
        }
    }
}

function showAdvancedOnClick(button, hidetext, showtext){
    var toSet=findChildNodes(button.form, null, 'advanced');
    var buttontext = '';
    if (button.form.elements['mform_showadvanced_last'].value == '0') {
        elementShowAdvanced(toSet, true);
        buttontext = hidetext;
        button.form.elements['mform_showadvanced_last'].value = '1';
    } else {
        elementShowAdvanced(toSet, false);
        buttontext = showtext;
        button.form.elements['mform_showadvanced_last'].value = '0';
    }
    var formelements = button.form.elements;
    for (var i in formelements){
        if (formelements[i].name=='mform_showadvanced'){
            formelements[i].value = buttontext;
        }
    }
    //never submit the form if js is enabled.
    return false;
}

/*
    elementToggleHide (element, elementFinder)

    If elementFinder is not provided, toggles the "hidden" class for the specified element.
    If elementFinder is provided, then the "hidden" class will be toggled for the object
    returned by the function call elementFinder(element).

    If persistent == true, also sets a cookie for this.
*/
function elementToggleHide(el, persistent, elementFinder) {
    if(!elementFinder) {
        var obj = el;
    }
    else {
        var obj = elementFinder(el);
    }
    if(obj.className.indexOf('hidden') == -1) {
        obj.className += ' hidden';
        var shown = 0;
    }
    else {
        obj.className = obj.className.replace(new RegExp(' ?hidden'), '')
        var shown = 1;
    }

    if(persistent == true) {
        new cookie('hide:' + obj.id, 1, (shown ? -1 : 356), '/').set();
    }
}

function elementCookieHide(id) {
    var obj  = document.getElementById(id);
    var cook = new cookie('hide:' + id).read();
    if(cook != null) {
        elementToggleHide(obj, false);
    }
}

function filterByParent(elCollection, parentFinder) {
    var filteredCollection = [];
    for(var i = 0; i < elCollection.length; ++i) {
        var findParent = parentFinder(elCollection[i]);
        if(findParent.nodeName != 'BODY') {
            filteredCollection.push(elCollection[i]);
        }
    }
    return filteredCollection;
}

/*
    All this is here just so that IE gets to handle oversized blocks
    in a visually pleasing manner. It does a browser detect. So sue me.
*/

function fix_column_widths() {
    var agt = navigator.userAgent.toLowerCase();
    if ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1)) {
        fix_column_width('left-column');
        fix_column_width('right-column');
    }
}

function fix_column_width(colName) {
    if(column = document.getElementById(colName)) {
        if(!column.offsetWidth) {
            setTimeout("fix_column_width('" + colName + "')", 20);
            return;
        }

        var width = 0;
        var nodes = column.childNodes;

        for(i = 0; i < nodes.length; ++i) {
            if(nodes[i].className.indexOf("sideblock") != -1 ) {
                if(width < nodes[i].offsetWidth) {
                    width = nodes[i].offsetWidth;
                }
            }
        }

        for(i = 0; i < nodes.length; ++i) {
            if(nodes[i].className.indexOf("sideblock") != -1 ) {
                nodes[i].style.width = width + 'px';
            }
        }
    }
}

/*
	Insert myValue at current cursor position
*/
function insertAtCursor(myField, myValue) {
	// IE support
	if (document.selection) {
		myField.focus();
		sel = document.selection.createRange();
		sel.text = myValue;
	}
	// Mozilla/Netscape support
	else if (myField.selectionStart || myField.selectionStart == '0') {
		var startPos = myField.selectionStart;
		var endPos = myField.selectionEnd;
		myField.value = myField.value.substring(0, startPos)
			+ myValue + myField.value.substring(endPos, myField.value.length);
	} else {
		myField.value += myValue;
	}
}
<commit_msg>fixed function of advanced button in formslib - you had to click it twice initially<commit_after>// Miscellaneous core Javascript functions for Moodle

function popupchecker(msg) {
    var testwindow = window.open('itestwin.html', '', 'width=1,height=1,left=0,top=0,scrollbars=no');
    if (testwindow == null)
        {alert(msg);}
    else {
        testwindow.close();
    }
}

/*
function popUpProperties(inobj) {
/// Legacy function
  var op = window.open();
  op.document.open('text/plain');
  for (objprop in inobj) {
    op.document.write(objprop + ' => ' + inobj[objprop] + '\n');
  }
  op.document.close();
}

function fillmessagebox(text) {
/// Legacy function
  document.form.message.value = text;
}

function copyrichtext(textname) {
/// Legacy stub for old editor - to be removed soon
  return true;
}
*/

function checkall() {
  var el = document.getElementsByTagName('input');
  for(var i=0; i<el.length; i++) {
    if(el[i].type == 'checkbox') {
      el[i].checked = true;
    }
  }
}

function checknone() {
  var el = document.getElementsByTagName('input');
  for(var i=0; i<el.length; i++) {
    if(el[i].type == 'checkbox') {
      el[i].checked = false;
    }
  }
}

function lockoptions(formid, master, subitems) {
  // Subitems is an array of names of sub items.
  // Optionally, each item in subitems may have a
  // companion hidden item in the form with the
  // same name but prefixed by "h".
  var form = document.forms[formid];

  if (eval("form."+master+".checked")) {
    for (i=0; i<subitems.length; i++) {
      unlockoption(form, subitems[i]);
    }
  } else {
    for (i=0; i<subitems.length; i++) {
      lockoption(form, subitems[i]);
    }
  }
  return(true);
}

function lockoption(form,item) {
  eval("form."+item+".disabled=true");/* IE thing */
  if(form.elements['h'+item]) {
    eval("form.h"+item+".value=1");
  }
}

function unlockoption(form,item) {
  eval("form."+item+".disabled=false");/* IE thing */
  if(form.elements['h'+item]) {
    eval("form.h"+item+".value=0");
  }
}

function lockoptionsall(formid) {
    var form = document.forms[formid];
    var dependons = eval(formid+'items');
    for (var dependon in dependons) {
        var master = form[dependon];
        for (var condition in dependons[dependon]) {
            for (var value in dependons[dependon][condition]) {
                var lock;
                switch (condition) {
                  case 'notchecked':
                      lock = !master.checked; break;
                  case 'checked':
                      lock = master.checked; break;
                  case 'noitemselected':
                      lock = master.selectedIndex==-1; break;
                  case 'eq':
                      lock = master.value==value; break;
                  default:
                      lock = master.value!=value; break;
                }
                for (var ei in dependons[dependon][condition][value]) {
                    var formelement = form[dependons[dependon][condition][value][ei]];
                    formelement.disabled = lock;
                }
            }
        }
    }
    return true;
}

function lockoptionsallsetup(formid) {
    var form = document.forms[formid];
    var dependons = eval(formid+'items');
    for (var dependon in dependons) {
        var master = form[dependon];
        master.onclick  = function() {return lockoptionsall(this.form.getAttribute('id'));};
        master.onblur   = function() {return lockoptionsall(this.form.getAttribute('id'));};
        master.onchange = function() {return lockoptionsall(this.form.getAttribute('id'));};
    }
    for (var i = 0; i < form.elements.length; i++){
        var formelement = form.elements[i];
        if (formelement.type=='reset') {
            formelement.onclick  = function() {this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
            formelement.onblur   = function() {this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
            formelement.onchange = function() {this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
        }
    }
    return lockoptionsall(formid);
}

function submitFormById(id) {
    var theform = document.getElementById(id);
    if(!theform) {
        return false;
    }
    if(theform.tagName != 'form') {
        return false;
    }
    if(!theform.onsubmit || theform.onsubmit()) {
        return theform.submit();
    }
}

function select_all_in(elTagName, elClass, elId) {
    var inputs = document.getElementsByTagName('input');
    inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
    for(var i = 0; i < inputs.length; ++i) {
        if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
            inputs[i].checked = 'checked';
        }
    }
}

function deselect_all_in(elTagName, elClass, elId) {
    var inputs = document.getElementsByTagName('INPUT');
    inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
    for(var i = 0; i < inputs.length; ++i) {
        if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
            inputs[i].checked = '';
        }
    }
}

function confirm_if(expr, message) {
    if(!expr) {
        return true;
    }
    return confirm(message);
}

/*
    findParentNode (start, elementName, elementClass, elementID)

    Travels up the DOM hierarchy to find a parent element with the
    specified tag name, class, and id. All conditions must be met,
    but any can be ommitted. Returns the BODY element if no match
    found.
*/
function findParentNode(el, elName, elClass, elId) {
    while(el.nodeName != 'BODY') {
        if(
            (!elName || el.nodeName == elName) &&
            (!elClass || el.className.indexOf(elClass) != -1) &&
            (!elId || el.id == elId))
        {
            break;
        }
        el = el.parentNode;
    }
    return el;
}
/*
    findChildNode (start, elementName, elementClass, elementID)

    Travels down the DOM hierarchy to find all child elements with the
    specified tag name, class, and id. All conditions must be met,
    but any can be ommitted.
    Doesn't examine children of matches.
*/
function findChildNodes(start, tagName, elementClass, elementID, elementName) {
    var children = new Array();
    for (var childIndex in start.childNodes) {
        var classfound = false;
        var child = start.childNodes[childIndex];
        if((child.nodeType == 1) &&//element node type
                  (elementClass && (typeof(child.className)=='string'))){
            var childClasses = child.className.split(/\s+/);
            for (var childClassIndex in childClasses){
                if (childClasses[childClassIndex]==elementClass){
                    classfound = true;
                    break;
                }
            }
        }
        if(child.nodeType == 1) { //element node type
            if  ( (!tagName || child.nodeName == tagName) &&
                (!elementClass || classfound)&&
                (!elementID || child.id == elementID) &&
                (!elementName || child.name == elementName))
            {
                children = children.concat(child);
            } else {
                children = children.concat(findChildNodes(child, tagName, elementClass, elementID, elementName));
            }
        }
    }
    return children;
}
/*
    elementSetHide (elements, hide)

    Adds or removes the "hide" class for the specified elements depending on boolean hide.
*/
function elementShowAdvanced(elements, show) {
    for (var elementIndex in elements){
        element = elements[elementIndex];
        element.className = element.className.replace(new RegExp(' ?hide'), '')
        if(!show) {
            element.className += ' hide';
        }
    }
}

function showAdvancedOnClick(button, hidetext, showtext){
    var toSet=findChildNodes(button.form, null, 'advanced');
    var buttontext = '';
    if (button.form.elements['mform_showadvanced_last'].value == '0' ||  button.form.elements['mform_showadvanced_last'].value == '' ) {
        elementShowAdvanced(toSet, true);
        buttontext = hidetext;
        button.form.elements['mform_showadvanced_last'].value = '1';
    } else {
        elementShowAdvanced(toSet, false);
        buttontext = showtext;
        button.form.elements['mform_showadvanced_last'].value = '0';
    }
    var formelements = button.form.elements;
    for (var i in formelements){
        if (formelements[i].name=='mform_showadvanced'){
            formelements[i].value = buttontext;
        }
    }
    //never submit the form if js is enabled.
    return false;
}

/*
    elementToggleHide (element, elementFinder)

    If elementFinder is not provided, toggles the "hidden" class for the specified element.
    If elementFinder is provided, then the "hidden" class will be toggled for the object
    returned by the function call elementFinder(element).

    If persistent == true, also sets a cookie for this.
*/
function elementToggleHide(el, persistent, elementFinder) {
    if(!elementFinder) {
        var obj = el;
    }
    else {
        var obj = elementFinder(el);
    }
    if(obj.className.indexOf('hidden') == -1) {
        obj.className += ' hidden';
        var shown = 0;
    }
    else {
        obj.className = obj.className.replace(new RegExp(' ?hidden'), '')
        var shown = 1;
    }

    if(persistent == true) {
        new cookie('hide:' + obj.id, 1, (shown ? -1 : 356), '/').set();
    }
}

function elementCookieHide(id) {
    var obj  = document.getElementById(id);
    var cook = new cookie('hide:' + id).read();
    if(cook != null) {
        elementToggleHide(obj, false);
    }
}

function filterByParent(elCollection, parentFinder) {
    var filteredCollection = [];
    for(var i = 0; i < elCollection.length; ++i) {
        var findParent = parentFinder(elCollection[i]);
        if(findParent.nodeName != 'BODY') {
            filteredCollection.push(elCollection[i]);
        }
    }
    return filteredCollection;
}

/*
    All this is here just so that IE gets to handle oversized blocks
    in a visually pleasing manner. It does a browser detect. So sue me.
*/

function fix_column_widths() {
    var agt = navigator.userAgent.toLowerCase();
    if ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1)) {
        fix_column_width('left-column');
        fix_column_width('right-column');
    }
}

function fix_column_width(colName) {
    if(column = document.getElementById(colName)) {
        if(!column.offsetWidth) {
            setTimeout("fix_column_width('" + colName + "')", 20);
            return;
        }

        var width = 0;
        var nodes = column.childNodes;

        for(i = 0; i < nodes.length; ++i) {
            if(nodes[i].className.indexOf("sideblock") != -1 ) {
                if(width < nodes[i].offsetWidth) {
                    width = nodes[i].offsetWidth;
                }
            }
        }

        for(i = 0; i < nodes.length; ++i) {
            if(nodes[i].className.indexOf("sideblock") != -1 ) {
                nodes[i].style.width = width + 'px';
            }
        }
    }
}

/*
	Insert myValue at current cursor position
*/
function insertAtCursor(myField, myValue) {
	// IE support
	if (document.selection) {
		myField.focus();
		sel = document.selection.createRange();
		sel.text = myValue;
	}
	// Mozilla/Netscape support
	else if (myField.selectionStart || myField.selectionStart == '0') {
		var startPos = myField.selectionStart;
		var endPos = myField.selectionEnd;
		myField.value = myField.value.substring(0, startPos)
			+ myValue + myField.value.substring(endPos, myField.value.length);
	} else {
		myField.value += myValue;
	}
}
<|endoftext|>


<commit_before>
(function ($) {
	var handleFiles, ProgressBar, FileList;

	$.fileTypeIcon = function (fileId, file) {
		if(file.type.substring(0,6) == 'image/') {
			return $('');
		} else if(file.type == 'application/pdf') {
			return $('');
		} else if(file.type.indexOf("sheet") != -1) {
			return $('');
		} else if(file.type.indexOf("zip") != -1) {
			return $('');
		} else if (file.type.substring(0,6) == 'video/') {
			return $('');
		} else if (file.type.indexOf("word") != -1) {
			return $('');
		} else {
			return $('');
		}
	};

	ProgressBar = function (options) {
		var bar = this;
		this.segments = [];
		this.updateSegment = function (number, current, total) {
			bar.segments[number] = [current, total];
			bar.update();
		};
		this.update = function () {
			var total = 0, current = 0;
			$.each(bar.segments, function (k, item) {
				current += item[0];
				total += item[1];
			});

			options.progress(current, total);

			if (current === total) {
				options.done();
			}
		};
	};

	FileList = function (options) {
		var $list = $(options.list);
		this.clearErrors = function () {
			$list.find('.text-danger').remove();
		};
		this.addError = function (file) {
			var $li = $('
').appendTo($list);

			$li.text(file.name);
			$li.addClass('text-danger');
		};
		this.addFile = function (fileId, file) {
			var $li = $('
').appendTo($list);

			$li
				.text(file.name)
				.prepend($.fileTypeIcon(fileId, file));
			$('<input type="hidden" name="file[]">')
				.attr('value', fileId)
				.appendTo($li)
		};
	};

	handleFiles = function (input) {
		var files = input.files,
			galleryId = input.galleryId,
			progressBar = input.progress,
			fileList = input.list;

		var uploadUrl = $.service('file', 'upload');
		$.each(files, function (k, file) {
			var reader = new FileReader();
			progressBar.updateSegment(k, 0, file.size);

			$(window).queue('process-upload', function () {
				reader.onloadend = function (e) {
					var xhr, provider, sendData, data;

					xhr = jQuery.ajaxSettings.xhr();
					if (xhr.upload) {
						xhr.upload.addEventListener('progress', function (e) {
							if (e.lengthComputable) {
								progressBar.updateSegment(k, e.loaded, e.total);
							}
						}, false);
					}
					provider = function () {
						return xhr;
					};

					sendData = {
						type: 'POST',
						url: uploadUrl,
						xhr: provider,
						dataType: 'json',
						success: function (data) {
							var fileId = data.fileId;
							fileList.addFile(data.fileId, file);
						},
						error: function (jqxhr) {
							progressBar.updateSegment(k, 0, 0);
							fileList.addError(file);
						},
						complete: function () {
							$(window).dequeue('process-upload');
						}
					};

					if (window.FormData) {
						sendData.processData = false;
						sendData.contentType = false;
						sendData.cache = false;

						sendData.data = new FormData;
						sendData.data.append('galleryId', galleryId);
						sendData.data.append('data', file);
					} else {
						data = e.target.result;
						sendData.data = {
							name: file.name,
							size: file.size,
							type: file.type,
							data: data.substr(data.indexOf('base64') + 7),
							galleryId: galleryId
						};
					}

					$.ajax(sendData);
				};
				reader.readAsDataURL(file);
			});
		});
		$(window).dequeue('process-upload');
	};

	$(document).on('submit', 'form.file-uploader', function (e) {
		e.preventDefault();
	});

	function doUpload($form, files) {
		var progress, list;

		progress = new ProgressBar({
			progress: function (current, total) {
				var percentage = Math.round(current / total * 100);

				$form.find('.progress').removeClass('hidden');
				$form.find('.progress-bar')
					.attr('aria-valuenow', percentage)
					.width(percentage + '%');
				$form.find('.progress-bar .sr-only .count')
					.text(percentage);
			},
			done: function () {
				$form.find('.progress').addClass('hidden');
				$form.find('.progress-bar')
					.attr('aria-valuenow', 0)
					.width('0%');
				$form.find('.progress-bar .sr-only .count')
					.text(percentage);
			}
		});

		list = new FileList({
			list: $form.parent().find('.file-uploader-result ul')[0]
		});

		list.clearErrors();

		handleFiles({
			galleryId: $form.data('gallery-id'),
			files: files,
			progress: progress,
			list: list
		});
	}

	$(document).on('change', 'form.file-uploader input[type=file]', function () {
		var $clone, $form = $(this).closest('form'), progress, list;
		if (this.files) {
			doUpload($form, this.files);

			$(this).val('');
			$clone = $(this).clone(true);
			$(this).replaceWith($clone);
		}
	});

	if (window.FileReader) {
		$(document).ready(function () {
			$('.drop-message').show();
		});
		$(document).on('dragenter', '.file-uploader', function (e) {
			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '2px dashed gray');
			return false;
		});
		$(document).on('dragexit', '.file-uploader', function (e) {
			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '');
			return false;
		});
		$(document).on('dragover', '.file-uploader', function (e) {
			e.preventDefault();
			e.stopPropagation();
			return false;
		});
		$(document).on('drop', '.file-uploader', function (e) {
			var $form = $(this);

			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '');

			var dataTransfer = e.dataTransfer;
			if (! dataTransfer) {
				dataTransfer = e.originalEvent.dataTransfer;
			}

			if (dataTransfer && dataTransfer.files) {
				doUpload($form, dataTransfer.files);
			}
			return false;
		});
	}

	function browserAddFile(link)
	{
		var content = $(link).closest('.media-body').clone(true),
			icon = $(link).closest('.media').find('.media-object').children().clone(true),
			nav = $(link).closest('.file-browser').find('.selection ul'),
			item = $('
'),
			a = $('').text($(link).text());

		a
			.prepend(' ')
			.prepend(icon);
		item.append(a);
		nav.append(item);

		item.append($('<input type="hidden" name="file[]">')
			.attr('value', $(link).data('object')));

		nav.closest('.selection').removeClass('hidden');
	}

	$(document).on('click', '.file-browser .gallery-list .pagination a', function (e) {
		e.preventDefault();
		$(this).closest('.modal').animate({ scrollTop: 0 }, 'slow');
		$(this).closest('.gallery-list')
			.tikiModal(tr('Loading...'))
			.load($(this).attr('href'), function () {
				$(this).tikiModal('');
			});
	});

	$(document).on('click', '.file-browser .gallery-list .media-heading a', function (e) {
		e.preventDefault();
		browserAddFile(this);
	});

	$(document).on('click', '.file-browser .selection a', function (e) {
		var list = $(this).closest('ul');
		$(this).closest('li').remove();
		if (list.children('li').length === 0) {
			list.closest('.selection').addClass('hidden');
		}
	});

	$(document).on('submit', '.file-browser .form-inline', function (e) {
		e.preventDefault();
		$(this).closest('.file-browser').find('.gallery-list')
			.tikiModal(tr('Loading...'))
			.load($(this).attr('action'), $(this).serialize(), function () {
				$(this).tikiModal('');
			});
	});
})(jQuery);
<commit_msg>[ENH] Additional visual feedback when selecting files, toggle on re-select<commit_after>
(function ($) {
	var handleFiles, ProgressBar, FileList;

	$.fileTypeIcon = function (fileId, file) {
		if(file.type.substring(0,6) == 'image/') {
			return $('');
		} else if(file.type == 'application/pdf') {
			return $('');
		} else if(file.type.indexOf("sheet") != -1) {
			return $('');
		} else if(file.type.indexOf("zip") != -1) {
			return $('');
		} else if (file.type.substring(0,6) == 'video/') {
			return $('');
		} else if (file.type.indexOf("word") != -1) {
			return $('');
		} else {
			return $('');
		}
	};

	ProgressBar = function (options) {
		var bar = this;
		this.segments = [];
		this.updateSegment = function (number, current, total) {
			bar.segments[number] = [current, total];
			bar.update();
		};
		this.update = function () {
			var total = 0, current = 0;
			$.each(bar.segments, function (k, item) {
				current += item[0];
				total += item[1];
			});

			options.progress(current, total);

			if (current === total) {
				options.done();
			}
		};
	};

	FileList = function (options) {
		var $list = $(options.list);
		this.clearErrors = function () {
			$list.find('.text-danger').remove();
		};
		this.addError = function (file) {
			var $li = $('
').appendTo($list);

			$li.text(file.name);
			$li.addClass('text-danger');
		};
		this.addFile = function (fileId, file) {
			var $li = $('
').appendTo($list);

			$li
				.text(file.name)
				.prepend($.fileTypeIcon(fileId, file));
			$('<input type="hidden" name="file[]">')
				.attr('value', fileId)
				.appendTo($li)
		};
	};

	handleFiles = function (input) {
		var files = input.files,
			galleryId = input.galleryId,
			progressBar = input.progress,
			fileList = input.list;

		var uploadUrl = $.service('file', 'upload');
		$.each(files, function (k, file) {
			var reader = new FileReader();
			progressBar.updateSegment(k, 0, file.size);

			$(window).queue('process-upload', function () {
				reader.onloadend = function (e) {
					var xhr, provider, sendData, data;

					xhr = jQuery.ajaxSettings.xhr();
					if (xhr.upload) {
						xhr.upload.addEventListener('progress', function (e) {
							if (e.lengthComputable) {
								progressBar.updateSegment(k, e.loaded, e.total);
							}
						}, false);
					}
					provider = function () {
						return xhr;
					};

					sendData = {
						type: 'POST',
						url: uploadUrl,
						xhr: provider,
						dataType: 'json',
						success: function (data) {
							var fileId = data.fileId;
							fileList.addFile(data.fileId, file);
						},
						error: function (jqxhr) {
							progressBar.updateSegment(k, 0, 0);
							fileList.addError(file);
						},
						complete: function () {
							$(window).dequeue('process-upload');
						}
					};

					if (window.FormData) {
						sendData.processData = false;
						sendData.contentType = false;
						sendData.cache = false;

						sendData.data = new FormData;
						sendData.data.append('galleryId', galleryId);
						sendData.data.append('data', file);
					} else {
						data = e.target.result;
						sendData.data = {
							name: file.name,
							size: file.size,
							type: file.type,
							data: data.substr(data.indexOf('base64') + 7),
							galleryId: galleryId
						};
					}

					$.ajax(sendData);
				};
				reader.readAsDataURL(file);
			});
		});
		$(window).dequeue('process-upload');
	};

	$(document).on('submit', 'form.file-uploader', function (e) {
		e.preventDefault();
	});

	function doUpload($form, files) {
		var progress, list;

		progress = new ProgressBar({
			progress: function (current, total) {
				var percentage = Math.round(current / total * 100);

				$form.find('.progress').removeClass('hidden');
				$form.find('.progress-bar')
					.attr('aria-valuenow', percentage)
					.width(percentage + '%');
				$form.find('.progress-bar .sr-only .count')
					.text(percentage);
			},
			done: function () {
				$form.find('.progress').addClass('hidden');
				$form.find('.progress-bar')
					.attr('aria-valuenow', 0)
					.width('0%');
				$form.find('.progress-bar .sr-only .count')
					.text(percentage);
			}
		});

		list = new FileList({
			list: $form.parent().find('.file-uploader-result ul')[0]
		});

		list.clearErrors();

		handleFiles({
			galleryId: $form.data('gallery-id'),
			files: files,
			progress: progress,
			list: list
		});
	}

	$(document).on('change', 'form.file-uploader input[type=file]', function () {
		var $clone, $form = $(this).closest('form'), progress, list;
		if (this.files) {
			doUpload($form, this.files);

			$(this).val('');
			$clone = $(this).clone(true);
			$(this).replaceWith($clone);
		}
	});

	if (window.FileReader) {
		$(document).ready(function () {
			$('.drop-message').show();
		});
		$(document).on('dragenter', '.file-uploader', function (e) {
			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '2px dashed gray');
			return false;
		});
		$(document).on('dragexit', '.file-uploader', function (e) {
			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '');
			return false;
		});
		$(document).on('dragover', '.file-uploader', function (e) {
			e.preventDefault();
			e.stopPropagation();
			return false;
		});
		$(document).on('drop', '.file-uploader', function (e) {
			var $form = $(this);

			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '');

			var dataTransfer = e.dataTransfer;
			if (! dataTransfer) {
				dataTransfer = e.originalEvent.dataTransfer;
			}

			if (dataTransfer && dataTransfer.files) {
				doUpload($form, dataTransfer.files);
			}
			return false;
		});
	}

	function browserRemoveFile(link)
	{
		var list = $(link).closest('ul');
		$(link).closest('li').remove();
		if (list.children('li').length === 0) {
			list.closest('.selection').addClass('hidden');
		}

		list.closest('.file-browser').trigger('selection-update');
	}

	function browserAddFile(link)
	{
		var content = $(link).closest('.media-body').clone(true),
			icon = $(link).closest('.media').find('.media-object').children().clone(true),
			nav = $(link).closest('.file-browser').find('.selection ul'),
			item = $('
'),
			a = $('').text($(link).text()),
			id = $(link).data('object'),
			current = nav.find('input[type=hidden]').filter(function () {
				return parseInt($(this).val(), 10) === id;
			});

		if (current.length > 0) {
			// Already in the list
			browserRemoveFile(current[0]);
			return;
		}

		a
			.prepend(' ')
			.prepend(icon);
		item.append(a);
		nav.append(item);

		item.append($('<input type="hidden" name="file[]">')
			.attr('value', id));

		nav.closest('.selection').removeClass('hidden');
		nav.closest('.file-browser').trigger('selection-update');
	}

	$(document).on('selection-update', '.file-browser', function (e) {
		var selection = $('.selection input[type=hidden]', this).map(function () {
			return parseInt($(this).val(), 10);
		});

		$('.gallery-list .media-heading a', this).each(function () {
			var id = $(this).data('object');
			$(this).closest('.media').toggleClass('bg-info', -1 !== $.inArray(id, selection));
		});
	});

	$(document).on('click', '.file-browser .gallery-list .pagination a', function (e) {
		e.preventDefault();
		$(this).closest('.modal').animate({ scrollTop: 0 }, 'slow');
		$(this).closest('.gallery-list')
			.tikiModal(tr('Loading...'))
			.load($(this).attr('href'), function () {
				$(this).tikiModal('');
				$(this).closest('.file-browser').trigger('selection-update');
			});
	});

	$(document).on('click', '.file-browser .gallery-list .media-heading a', function (e) {
		e.preventDefault();
		browserAddFile(this);
	});

	$(document).on('click', '.file-browser .selection a', function (e) {
		e.preventDefault();
		browserRemoveFile(this);
	});

	$(document).on('submit', '.file-browser .form-inline', function (e) {
		e.preventDefault();
		$(this).closest('.file-browser').find('.gallery-list')
			.tikiModal(tr('Loading...'))
			.load($(this).attr('action'), $(this).serialize(), function () {
				$(this).tikiModal('');
				$(this).closest('.file-browser').trigger('selection-update');
			});
	});
})(jQuery);
<|endoftext|>


<commit_before>const _ = require('lodash')

const UUID_MATCHER = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i
const UUID_DISPLAY_SIZE = 4
const ARG_DELIMITER = '.'

const isUuid = uuid =>
    UUID_MATCHER.test(uuid)

const toString = value =>
    _.isString(value)
        ? isUuid(value)
            ? value.substr(-UUID_DISPLAY_SIZE)
            : value
        : JSON.stringify(value)

const argsJoiner = args =>
    _.compact(args.map(arg => toString(arg))).join(ARG_DELIMITER)

const tag = (tag, ...args) => `${tag}<${argsJoiner(args)}>`

module.exports = {
    tag
}
<commit_msg> Improved Tag filtering of null arguments.<commit_after>const _ = require('lodash')

const UUID_MATCHER = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i
const UUID_DISPLAY_SIZE = 4
const ARG_DELIMITER = '.'

const isUuid = uuid =>
    UUID_MATCHER.test(uuid)

const toString = value =>
    _.isString(value)
        ? isUuid(value)
            ? value.substr(-UUID_DISPLAY_SIZE)
            : value
        : JSON.stringify(value)

const argsJoiner = args =>
    args.filter(arg => !_.isNil(arg)).map(arg => toString(arg)).join(ARG_DELIMITER)

const tag = (tag, ...args) => `${tag}<${argsJoiner(args)}>`

module.exports = {
    tag
}
<|endoftext|>


<commit_before>JustifiedColumns = (function(window) {

	function pxAsNum(px) {
	    return 1 * px.split('px')[0];
	 }

	function stretch(s, plus) {
	    var sHeight = s.offsetHeight;
	    var sWidth = s.offsetWidth;
	    var newHeight = sHeight + plus;
	    var newWidth = sWidth * (newHeight / sHeight);
	    s.style.minHeight = newHeight + 'px';
	    s.style.minWidth = newWidth + 'px';
	}

	function Justifier(config) {
        this.setGrid(config.grid || config);
        this.stretchSelector = config.stretch || 'img';
        this.autoResize = config.hasOwnProperty('autoResize') ? config.autoResize : true;
        this.grid.Justifier = this;
        this.boundReset = this.reset.bind(this);
        this.boundJustify = this.justify.bind(this);
        this.enable();
	}

	Justifier.prototype.setGrid = function(grid) {
        if (typeof grid === 'string') {
            this.grid = document.querySelector(grid);
        }
        else {
    		this.grid = grid.jquery ? grid[0] : grid;
        }
	};

	Justifier.prototype.justify = function() {
	    var self = this,
	    	columns = [],
	        currentColumn = -1,
	        tallestColumn = 0,
	        currentOffset;

	    //sort the grid into columns based on offsetLeft; cache column height
	    [].slice.call(this.grid.children).forEach(function(gridItem) {
	        var gridItemStyle = window.getComputedStyle(gridItem);
	        var gridItemOffsetLeft = gridItem.offsetLeft; //saves like 40% of execution time to cache this
	        if (gridItemOffsetLeft !== currentOffset) {
	            if (currentColumn !== -1) tallestColumn = Math.max(columns[currentColumn].height, tallestColumn);
	            currentColumn++;
	            currentOffset = gridItemOffsetLeft;
	            columns.push({
		            items: [],
		            height: pxAsNum(gridItemStyle.getPropertyValue('margin-top'))
		        });
	        }
	        gridItem.cachedHeight = gridItem.offsetHeight;
	        columns[currentColumn].items.push(gridItem);
	        columns[currentColumn].height += (gridItem.cachedHeight + pxAsNum(gridItemStyle.getPropertyValue('margin-bottom')));
	    });
	    tallestColumn = Math.max(columns[currentColumn].height, tallestColumn); //last column could be tallest, too

	    //expand "things" in each of the non-tallest columns' items to fit
	    columns.forEach(function(column, index) {
	        if (column.height < tallestColumn) {
	            var columnDelta = tallestColumn - column.height;
	            //console.log("columnDelta", index, columnDelta);
	            column.items.forEach(function(gridItem) {
	                var stretchable = gridItem.querySelector(self.stretchSelector);
	                var stretchablePercent = gridItem.cachedHeight / column.height;
	                var stretchableDelta = stretchablePercent * columnDelta;
                    stretchable.parentNode.style.overflowX = 'hidden';
	                stretch(stretchable, stretchableDelta);
	                //sometimes JS gets the math very slightly wrong.  In that case, fill in the last stretchable.
	                if (index === column.length - 1) {
	                    var remainderDelta = tallestColumn - column.height;
	                    if (remainderDelta > 0) {
	                        stretch(stretchable, remainderDelta);
	                    }
	                }
	            });
	        }
	    });
	};

	Justifier.prototype.reset = function() {
		this.grid.querySelectorAll(this.stretchSelector).forEach(function(s) {
			s.style.minWidth = '';
			s.style.minHeight = '';
            s.parentNode.style.overflowX = '';
		})
	};

    Justifier.prototype.enable = function() {
        if (this.autoResize) {
            window.addEventListener('resize', this.boundReset);
            window.addEventListener('resize', this.boundJustify);
        }
		this.justify();
    };

    Justifier.prototype.disable = function() {
        if (this.autoResize) {
            window.removeEventListener('resize', this.boundReset);
            window.removeEventListener('resize', this.boundJustify);
        }
        this.reset();
    };

	return Justifier;

})(window);<commit_msg>missed a ;<commit_after>JustifiedColumns = (function(window) {

	function pxAsNum(px) {
	    return 1 * px.split('px')[0];
	 }

	function stretch(s, plus) {
	    var sHeight = s.offsetHeight;
	    var sWidth = s.offsetWidth;
	    var newHeight = sHeight + plus;
	    var newWidth = sWidth * (newHeight / sHeight);
	    s.style.minHeight = newHeight + 'px';
	    s.style.minWidth = newWidth + 'px';
	}

	function Justifier(config) {
        this.setGrid(config.grid || config);
        this.stretchSelector = config.stretch || 'img';
        this.autoResize = config.hasOwnProperty('autoResize') ? config.autoResize : true;
        this.grid.Justifier = this;
        this.boundReset = this.reset.bind(this);
        this.boundJustify = this.justify.bind(this);
        this.enable();
	}

	Justifier.prototype.setGrid = function(grid) {
        if (typeof grid === 'string') {
            this.grid = document.querySelector(grid);
        }
        else {
    		this.grid = grid.jquery ? grid[0] : grid;
        }
	};

	Justifier.prototype.justify = function() {
	    var self = this,
	    	columns = [],
	        currentColumn = -1,
	        tallestColumn = 0,
	        currentOffset;

	    //sort the grid into columns based on offsetLeft; cache column height
	    [].slice.call(this.grid.children).forEach(function(gridItem) {
	        var gridItemStyle = window.getComputedStyle(gridItem);
	        var gridItemOffsetLeft = gridItem.offsetLeft; //saves like 40% of execution time to cache this
	        if (gridItemOffsetLeft !== currentOffset) {
	            if (currentColumn !== -1) tallestColumn = Math.max(columns[currentColumn].height, tallestColumn);
	            currentColumn++;
	            currentOffset = gridItemOffsetLeft;
	            columns.push({
		            items: [],
		            height: pxAsNum(gridItemStyle.getPropertyValue('margin-top'))
		        });
	        }
	        gridItem.cachedHeight = gridItem.offsetHeight;
	        columns[currentColumn].items.push(gridItem);
	        columns[currentColumn].height += (gridItem.cachedHeight + pxAsNum(gridItemStyle.getPropertyValue('margin-bottom')));
	    });
	    tallestColumn = Math.max(columns[currentColumn].height, tallestColumn); //last column could be tallest, too

	    //expand "things" in each of the non-tallest columns' items to fit
	    columns.forEach(function(column, index) {
	        if (column.height < tallestColumn) {
	            var columnDelta = tallestColumn - column.height;
	            //console.log("columnDelta", index, columnDelta);
	            column.items.forEach(function(gridItem) {
	                var stretchable = gridItem.querySelector(self.stretchSelector);
	                var stretchablePercent = gridItem.cachedHeight / column.height;
	                var stretchableDelta = stretchablePercent * columnDelta;
                    stretchable.parentNode.style.overflowX = 'hidden';
	                stretch(stretchable, stretchableDelta);
	                //sometimes JS gets the math very slightly wrong.  In that case, fill in the last stretchable.
	                if (index === column.length - 1) {
	                    var remainderDelta = tallestColumn - column.height;
	                    if (remainderDelta > 0) {
	                        stretch(stretchable, remainderDelta);
	                    }
	                }
	            });
	        }
	    });
	};

	Justifier.prototype.reset = function() {
		this.grid.querySelectorAll(this.stretchSelector).forEach(function(s) {
			s.style.minWidth = '';
			s.style.minHeight = '';
            s.parentNode.style.overflowX = '';
		});
	};

    Justifier.prototype.enable = function() {
        if (this.autoResize) {
            window.addEventListener('resize', this.boundReset);
            window.addEventListener('resize', this.boundJustify);
        }
		this.justify();
    };

    Justifier.prototype.disable = function() {
        if (this.autoResize) {
            window.removeEventListener('resize', this.boundReset);
            window.removeEventListener('resize', this.boundJustify);
        }
        this.reset();
    };

	return Justifier;

})(window);<|endoftext|>


<commit_before>JustifiedColumns = (function(window) {

    var DEFAULT_THROTTLE = 25,
        WRAPPER_CLASS = 'justified-columns-wrapper',
        NEEDS_WRAPPER = document.documentElement.style.objectFit === undefined;

    function pxAsNum(px) {
        return 1 * px.split('px')[0];
    }

    function throttle(fn, threshhold, scope) {
        threshhold || (threshhold = 250);
        var last,
            deferTimer;

        return function() {
            var context = scope || this;

            var now = +new Date,
                args = arguments;

            if (last && now < last + threshhold) {
                clearTimeout(deferTimer);
                deferTimer = setTimeout(function() {
                    last = now;
                    fn.apply(context, args);
                }, threshhold);
            } else {
                last = now;
                fn.apply(context, args);
            }
        };
    }

    function Justifier(config) {
        this.setGrid(config.grid || config);
        this.stretchSelector = config.stretch || 'img';
        this.shrink = config.shrink || false; //or 'shrink' (column-justify);
        this.autoResize = config.hasOwnProperty('autoResize') ? config.autoResize : true;
        this.grid.Justifier = this;
        this.boundReset = config.throttle === 0 ? this.reset.bind(this) : throttle(this.reset.bind(this), config.throttle || DEFAULT_THROTTLE);
        this.boundJustify = config.throttle === 0 ? this.justify.bind(this) : throttle(this.justify.bind(this), config.throttle || DEFAULT_THROTTLE);
        this.enable();
    }

    Justifier.prototype.setGrid = function(grid) {
        if (typeof grid === 'string') {
            this.grid = document.querySelector(grid);
        } else {
            this.grid = grid.jquery ? grid[0] : grid;
        }
    };

    Justifier.prototype.justify = function() {
        var self = this,
            refColComparator = Math[this.shrink ? 'min' : 'max'],
            columns = [],
            currentColumn = -1,
            referenceColumn = this.shrink ? Number.POSITIVE_INFINITY : 0,
            currentOffset;

        //sort the grid into columns based on offsetLeft; cache heights
        [].slice.call(this.grid.children).forEach(function(gridItem) {
            var gridItemStyle = window.getComputedStyle(gridItem);
            var gridItemOffsetLeft = gridItem.offsetLeft; //saves like 40% of execution time to cache this
            if (gridItemOffsetLeft !== currentOffset) {
                if (currentColumn !== -1) referenceColumn = refColComparator(columns[currentColumn].height, referenceColumn);
                currentColumn++;
                currentOffset = gridItemOffsetLeft;
                columns.push({
                    items: [],
                    height: pxAsNum(gridItemStyle.getPropertyValue('margin-top')),
                    totalImagesHeight: 0
                });
            }
            gridItem.stretchable = gridItem.querySelector(self.stretchSelector);
            if (gridItem.stretchable) {
                gridItem.stretchableHeight = gridItem.stretchable.offsetHeight;
            }
            columns[currentColumn].items.push(gridItem);
            columns[currentColumn].height += (gridItem.offsetHeight + pxAsNum(gridItemStyle.getPropertyValue('margin-bottom')));
            columns[currentColumn].totalImagesHeight += (gridItem.stretchableHeight ? gridItem.stretchableHeight : 0);
        });
        referenceColumn = refColComparator(columns[currentColumn].height, referenceColumn); //last column could be reference, too

        //modify height of "stretchable" items (if present) in each of the non-reference-columns' items
        columns.forEach(function(column, colIndex) {
            if (column.height < referenceColumn || (self.shrink && column.height > referenceColumn)) {
                var columnDelta = referenceColumn - column.height;
                var stretchedImagesDelta = 0;
                column.items.forEach(function(gridItem, itemIndex) {
                    var stretchable = gridItem.querySelector(self.stretchSelector);
                    if (stretchable) {
                        var stretchablePercent = columnDelta / column.totalImagesHeight,
                            stretchableDelta = gridItem.stretchableHeight * stretchablePercent,
                            newHeight = gridItem.stretchableHeight + stretchableDelta,
                            heightProperty = (self.shrink ? 'max' : 'min') + 'Height';
                        if (stretchable.nodeName !== 'IMG') {
                            // not an image, so just set max/min-height and call it a day
                            stretchable.style[heightProperty] = newHeight + 'px';
                        } else if (!NEEDS_WRAPPER) {
                            // can rely on objectFit, so set the max/min-height, then use objectFit to handle resize + overflow
                            stretchable.style[heightProperty] = newHeight + 'px';
                            stretchable.style.objectFit = 'cover';
                            stretchable.style.objectPosition = 'center';
                        } else {
                            //it's an IMG and we're in older IE, ugh
                            if (stretchable.parentNode.className !== WRAPPER_CLASS) {
                                //create overflow wrapper
                                var wrapper = document.createElement('DIV');
                                wrapper.className = WRAPPER_CLASS;
                                wrapper.style.overflow = 'hidden';
                                wrapper.style.fontSize = 0; //otherwise IE will add just a liiiiitle bit of extra space
                                wrapper.style[heightProperty] = newHeight + 'px';
                                stretchable.parentNode.replaceChild(wrapper, stretchable);
                                wrapper.appendChild(stretchable);
                            }
                            //set wrapper max/min-height, position within wrapper
                            if (self.shrink) {
                                var sOffset = 0.5 * (newHeight - gridItem.stretchableHeight);
                                stretchable.style.marginTop = sOffset + 'px';
                                stretchable.style.marginBottom = -1 * sOffset + 'px';
                            } else {
                                var sWidth = stretchable.offsetWidth,
                                    newWidth = sWidth * (newHeight / gridItem.stretchableHeight);
                                stretchable.style.minHeight = newHeight + 'px';
                                stretchable.style.minWidth = newWidth + 'px';
                                stretchable.style.marginLeft = -0.5 * (newWidth - sWidth) + 'px';
                            }
                        }
                        stretchedImagesDelta += stretchableDelta;
                    }
                });
                column.height += stretchedImagesDelta;
                column.totalImagesHeight += stretchedImagesDelta;
            }
        });

        //Fix the stupid IE10/11 interactions between column-count grid and height/max-height children
        if (NEEDS_WRAPPER) {
            var resizeHeight = referenceColumn + 2,
                gridStyle = getComputedStyle(this.grid);
            if (gridStyle.boxSizing === 'border-box') {
                ['paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth'].forEach(function(spacer) {
                    resizeHeight += pxAsNum(gridStyle[spacer]);
                });
            }
            if (Math.abs(this.grid.offsetHeight - resizeHeight) >= 2) {
                this.grid.style.height = resizeHeight + 'px';
            }
        }

    };

    Justifier.prototype.reset = function() {
        [].slice.call(this.grid.querySelectorAll(this.stretchSelector)).forEach(function(s) {
            s.style.maxHeight = '';
            s.style.minHeight = '';
            if (NEEDS_WRAPPER) {
                s.style.minWidth = '';
                s.style.marginLeft = '';
                s.style.marginTop = '';
            } else {
                s.style.objectFit = '';
                s.style.objectPosition = '';
            }
        });
        if (NEEDS_WRAPPER) {
            [].slice.call(this.grid.getElementsByClassName(WRAPPER_CLASS)).forEach(function(wrapper) {
                wrapper.parentNode.replaceChild(wrapper.firstChild, wrapper);
            });
            this.grid.style.height = '';
        }
    };

    Justifier.prototype.enable = function() {
        if (this.autoResize) {
            window.addEventListener('resize', this.boundReset);
            window.addEventListener('resize', this.boundJustify);
        }
        this.justify();
    };

    Justifier.prototype.disable = function() {
        if (this.autoResize) {
            window.removeEventListener('resize', this.boundReset);
            window.removeEventListener('resize', this.boundJustify);
        }
        this.reset();
    };

    return Justifier;

})(window);<commit_msg>GLBE-6005 Wrap plugin in UMD<commit_after>(function (root, factory) {
    if ( typeof define === 'function' && define.amd ) {
        define([], function () {
            return factory(root);
        });
    } else if ( typeof exports === 'object' ) {
        module.exports = factory(root);
    } else {
        root.JustifiedColumns = factory(root);
    }
})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, function (window) {
    var DEFAULT_THROTTLE = 25,
        WRAPPER_CLASS = 'justified-columns-wrapper',
        NEEDS_WRAPPER = document.documentElement.style.objectFit === undefined;

    function pxAsNum(px) {
        return 1 * px.split('px')[0];
    }

    function throttle(fn, threshhold, scope) {
        threshhold || (threshhold = 250);
        var last,
            deferTimer;

        return function() {
            var context = scope || this;

            var now = +new Date,
                args = arguments;

            if (last && now < last + threshhold) {
                clearTimeout(deferTimer);
                deferTimer = setTimeout(function() {
                    last = now;
                    fn.apply(context, args);
                }, threshhold);
            } else {
                last = now;
                fn.apply(context, args);
            }
        };
    }

    function Justifier(config) {
        this.setGrid(config.grid || config);
        this.stretchSelector = config.stretch || 'img';
        this.shrink = config.shrink || false; //or 'shrink' (column-justify);
        this.autoResize = config.hasOwnProperty('autoResize') ? config.autoResize : true;
        this.grid.Justifier = this;
        this.boundReset = config.throttle === 0 ? this.reset.bind(this) : throttle(this.reset.bind(this), config.throttle || DEFAULT_THROTTLE);
        this.boundJustify = config.throttle === 0 ? this.justify.bind(this) : throttle(this.justify.bind(this), config.throttle || DEFAULT_THROTTLE);
        this.enable();
    }

    Justifier.prototype.setGrid = function(grid) {
        if (typeof grid === 'string') {
            this.grid = document.querySelector(grid);
        } else {
            this.grid = grid.jquery ? grid[0] : grid;
        }
    };

    Justifier.prototype.justify = function() {
        var self = this,
            refColComparator = Math[this.shrink ? 'min' : 'max'],
            columns = [],
            currentColumn = -1,
            referenceColumn = this.shrink ? Number.POSITIVE_INFINITY : 0,
            currentOffset;

        //sort the grid into columns based on offsetLeft; cache heights
        [].slice.call(this.grid.children).forEach(function(gridItem) {
            var gridItemStyle = window.getComputedStyle(gridItem);
            var gridItemOffsetLeft = gridItem.offsetLeft; //saves like 40% of execution time to cache this
            if (gridItemOffsetLeft !== currentOffset) {
                if (currentColumn !== -1) referenceColumn = refColComparator(columns[currentColumn].height, referenceColumn);
                currentColumn++;
                currentOffset = gridItemOffsetLeft;
                columns.push({
                    items: [],
                    height: pxAsNum(gridItemStyle.getPropertyValue('margin-top')),
                    totalImagesHeight: 0
                });
            }
            gridItem.stretchable = gridItem.querySelector(self.stretchSelector);
            if (gridItem.stretchable) {
                gridItem.stretchableHeight = gridItem.stretchable.offsetHeight;
            }
            columns[currentColumn].items.push(gridItem);
            columns[currentColumn].height += (gridItem.offsetHeight + pxAsNum(gridItemStyle.getPropertyValue('margin-bottom')));
            columns[currentColumn].totalImagesHeight += (gridItem.stretchableHeight ? gridItem.stretchableHeight : 0);
        });
        referenceColumn = refColComparator(columns[currentColumn].height, referenceColumn); //last column could be reference, too

        //modify height of "stretchable" items (if present) in each of the non-reference-columns' items
        columns.forEach(function(column, colIndex) {
            if (column.height < referenceColumn || (self.shrink && column.height > referenceColumn)) {
                var columnDelta = referenceColumn - column.height;
                var stretchedImagesDelta = 0;
                column.items.forEach(function(gridItem, itemIndex) {
                    var stretchable = gridItem.querySelector(self.stretchSelector);
                    if (stretchable) {
                        var stretchablePercent = columnDelta / column.totalImagesHeight,
                            stretchableDelta = gridItem.stretchableHeight * stretchablePercent,
                            newHeight = gridItem.stretchableHeight + stretchableDelta,
                            heightProperty = (self.shrink ? 'max' : 'min') + 'Height';
                        if (stretchable.nodeName !== 'IMG') {
                            // not an image, so just set max/min-height and call it a day
                            stretchable.style[heightProperty] = newHeight + 'px';
                        } else if (!NEEDS_WRAPPER) {
                            // can rely on objectFit, so set the max/min-height, then use objectFit to handle resize + overflow
                            stretchable.style[heightProperty] = newHeight + 'px';
                            stretchable.style.objectFit = 'cover';
                            stretchable.style.objectPosition = 'center';
                        } else {
                            //it's an IMG and we're in older IE, ugh
                            if (stretchable.parentNode.className !== WRAPPER_CLASS) {
                                //create overflow wrapper
                                var wrapper = document.createElement('DIV');
                                wrapper.className = WRAPPER_CLASS;
                                wrapper.style.overflow = 'hidden';
                                wrapper.style.fontSize = 0; //otherwise IE will add just a liiiiitle bit of extra space
                                wrapper.style[heightProperty] = newHeight + 'px';
                                stretchable.parentNode.replaceChild(wrapper, stretchable);
                                wrapper.appendChild(stretchable);
                            }
                            //set wrapper max/min-height, position within wrapper
                            if (self.shrink) {
                                var sOffset = 0.5 * (newHeight - gridItem.stretchableHeight);
                                stretchable.style.marginTop = sOffset + 'px';
                                stretchable.style.marginBottom = -1 * sOffset + 'px';
                            } else {
                                var sWidth = stretchable.offsetWidth,
                                    newWidth = sWidth * (newHeight / gridItem.stretchableHeight);
                                stretchable.style.minHeight = newHeight + 'px';
                                stretchable.style.minWidth = newWidth + 'px';
                                stretchable.style.marginLeft = -0.5 * (newWidth - sWidth) + 'px';
                            }
                        }
                        stretchedImagesDelta += stretchableDelta;
                    }
                });
                column.height += stretchedImagesDelta;
                column.totalImagesHeight += stretchedImagesDelta;
            }
        });

        //Fix the stupid IE10/11 interactions between column-count grid and height/max-height children
        if (NEEDS_WRAPPER) {
            var resizeHeight = referenceColumn + 2,
                gridStyle = getComputedStyle(this.grid);
            if (gridStyle.boxSizing === 'border-box') {
                ['paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth'].forEach(function(spacer) {
                    resizeHeight += pxAsNum(gridStyle[spacer]);
                });
            }
            if (Math.abs(this.grid.offsetHeight - resizeHeight) >= 2) {
                this.grid.style.height = resizeHeight + 'px';
            }
        }

    };

    Justifier.prototype.reset = function() {
        [].slice.call(this.grid.querySelectorAll(this.stretchSelector)).forEach(function(s) {
            s.style.maxHeight = '';
            s.style.minHeight = '';
            if (NEEDS_WRAPPER) {
                s.style.minWidth = '';
                s.style.marginLeft = '';
                s.style.marginTop = '';
            } else {
                s.style.objectFit = '';
                s.style.objectPosition = '';
            }
        });
        if (NEEDS_WRAPPER) {
            [].slice.call(this.grid.getElementsByClassName(WRAPPER_CLASS)).forEach(function(wrapper) {
                wrapper.parentNode.replaceChild(wrapper.firstChild, wrapper);
            });
            this.grid.style.height = '';
        }
    };

    Justifier.prototype.enable = function() {
        if (this.autoResize) {
            window.addEventListener('resize', this.boundReset);
            window.addEventListener('resize', this.boundJustify);
        }
        this.justify();
    };

    Justifier.prototype.disable = function() {
        if (this.autoResize) {
            window.removeEventListener('resize', this.boundReset);
            window.removeEventListener('resize', this.boundJustify);
        }
        this.reset();
    };

    return Justifier;
});
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of perseo-fe
 *
 * perseo-fe is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * perseo-fe is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with perseo-fe.
 * If not, see http://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with iot_support at tid dot es
 */

'use strict';

var domain = require('domain'),
    uuid = require('uuid'),
    logger = require('logops'),
    constants = require('../constants'),
    metrics = require('../models/metrics'),
    config = require('../../config'),
    shortid = require('shortid'),
    CORR_SUFFIX = '; node=' + shortid.generate() + ' ; perseocep=',
    MAX_INT_SAFE = (1 << 53) - 1,
    corrSequence = 0;

/**
 * Express middleware that creates a domain per request
 * It also generates a unique request id that can be used to track requests in logs.
 *
 * @return {Function} Express middleWare.
 */
function requestDomain() {
    return function requestDomain(req, res, next) {
        var reqDomain = domain.create();
        reqDomain.add(req);
        reqDomain.add(res);
        reqDomain.context = {};
        reqDomain.context.path = req.path;
        reqDomain.context.op = req.url;
        reqDomain.context.comp = constants.COMPONENT_NAME;

        reqDomain.start = Date.now();

        var cleanDomain, domainErrorHandler;

        cleanDomain = function() {
            var responseTime = Date.now() - reqDomain.start;
            logger.debug('response-time: ' + responseTime + ' statusCode: ' + res.statusCode);
            if (
                req.url.indexOf(config.endpoint.actionsPath) !== 0 &&
                req.url.indexOf(config.endpoint.checkPath) !== 0 &&
                req.url.indexOf(config.endpoint.versionPath) !== 0 &&
                req.url.indexOf(config.endpoint.logPath) !== 0 &&
                req.url.indexOf(config.endpoint.metricsPath) !== 0
            ) {
                metrics.IncMetrics(req.service, req.subservice, metrics.serviceTime, responseTime);
            }
            reqDomain.removeListener('error', domainErrorHandler);
            reqDomain.remove(req);
            reqDomain.remove(res);
            delete reqDomain.context;
            reqDomain.exit();
        };

        domainErrorHandler = function(err) {
            logger.error(err);
            cleanDomain();
        };

        function requestHandler() {
            var corr, realIP;

            reqDomain.context.trans = req.requestId = uuid.v4();

            corr = req.get(constants.CORRELATOR_HEADER);
            if (!corr) {
                corr = reqDomain.context.trans;
            }

            if (corr.indexOf(CORR_SUFFIX) === -1) {
                // first time it arrives to perseo, tainted it
                corr += CORR_SUFFIX + corrSequence;
                if (corrSequence + 1 < MAX_INT_SAFE) {
                    corrSequence++;
                } else {
                    corrSequence = 0;
                }
            }
            reqDomain.context.corr = corr;
            res.set(constants.CORRELATOR_HEADER, reqDomain.context.corr);

            reqDomain.context.srv = req.service;
            reqDomain.context.subsrv = req.subservice;

            realIP = req.get(constants.REALIP_HEADER);
            if (realIP) {
                reqDomain.context.from = realIP;
            } else {
                reqDomain.context.from = req.connection.remoteAddress;
            }
            next();
        }

        res.once('finish', cleanDomain);
        reqDomain.on('error', domainErrorHandler);
        reqDomain.run(requestHandler);
    };
}
/**
 * Express middleWare that creates a domain per request
 * It also generates a unique request id that can be used to track requests in logs.
 *
 * @return {Function} Express middleWare.
 */
exports.requestDomain = requestDomain;
<commit_msg>remove separator<commit_after>/*
 * Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of perseo-fe
 *
 * perseo-fe is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * perseo-fe is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with perseo-fe.
 * If not, see http://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with iot_support at tid dot es
 */

'use strict';

var domain = require('domain'),
    uuid = require('uuid'),
    logger = require('logops'),
    constants = require('../constants'),
    metrics = require('../models/metrics'),
    config = require('../../config'),
    shortid = require('shortid'),
    CORR_SUFFIX = '; node=' + shortid.generate() + '; perseocep=',
    MAX_INT_SAFE = (1 << 53) - 1,
    corrSequence = 0;

/**
 * Express middleware that creates a domain per request
 * It also generates a unique request id that can be used to track requests in logs.
 *
 * @return {Function} Express middleWare.
 */
function requestDomain() {
    return function requestDomain(req, res, next) {
        var reqDomain = domain.create();
        reqDomain.add(req);
        reqDomain.add(res);
        reqDomain.context = {};
        reqDomain.context.path = req.path;
        reqDomain.context.op = req.url;
        reqDomain.context.comp = constants.COMPONENT_NAME;

        reqDomain.start = Date.now();

        var cleanDomain, domainErrorHandler;

        cleanDomain = function() {
            var responseTime = Date.now() - reqDomain.start;
            logger.debug('response-time: ' + responseTime + ' statusCode: ' + res.statusCode);
            if (
                req.url.indexOf(config.endpoint.actionsPath) !== 0 &&
                req.url.indexOf(config.endpoint.checkPath) !== 0 &&
                req.url.indexOf(config.endpoint.versionPath) !== 0 &&
                req.url.indexOf(config.endpoint.logPath) !== 0 &&
                req.url.indexOf(config.endpoint.metricsPath) !== 0
            ) {
                metrics.IncMetrics(req.service, req.subservice, metrics.serviceTime, responseTime);
            }
            reqDomain.removeListener('error', domainErrorHandler);
            reqDomain.remove(req);
            reqDomain.remove(res);
            delete reqDomain.context;
            reqDomain.exit();
        };

        domainErrorHandler = function(err) {
            logger.error(err);
            cleanDomain();
        };

        function requestHandler() {
            var corr, realIP;

            reqDomain.context.trans = req.requestId = uuid.v4();

            corr = req.get(constants.CORRELATOR_HEADER);
            if (!corr) {
                corr = reqDomain.context.trans;
            }

            if (corr.indexOf(CORR_SUFFIX) === -1) {
                // first time it arrives to perseo, tainted it
                corr += CORR_SUFFIX + corrSequence;
                if (corrSequence + 1 < MAX_INT_SAFE) {
                    corrSequence++;
                } else {
                    corrSequence = 0;
                }
            }
            reqDomain.context.corr = corr;
            res.set(constants.CORRELATOR_HEADER, reqDomain.context.corr);

            reqDomain.context.srv = req.service;
            reqDomain.context.subsrv = req.subservice;

            realIP = req.get(constants.REALIP_HEADER);
            if (realIP) {
                reqDomain.context.from = realIP;
            } else {
                reqDomain.context.from = req.connection.remoteAddress;
            }
            next();
        }

        res.once('finish', cleanDomain);
        reqDomain.on('error', domainErrorHandler);
        reqDomain.run(requestHandler);
    };
}
/**
 * Express middleWare that creates a domain per request
 * It also generates a unique request id that can be used to track requests in logs.
 *
 * @return {Function} Express middleWare.
 */
exports.requestDomain = requestDomain;
<|endoftext|>


<commit_before>const helmet = require('helmet');

module.exports = function(config) {
    if (config.enableHelmet) {
        return helmet({
            contentSecurityPolicy: {
                directives: {
                    defaultSrc: [
                        "'self'",
                        'fonts.googleapis.com',
                        'fonts.gstatic.com',
                        'data:',
                        'gravatar.com',
                    ],
                },
            },
        });
    }
    return (req, res, next) => {
        next();
    };
};
<commit_msg>fix: lax helmet csp config for styles.<commit_after>const helmet = require('helmet');

module.exports = function(config) {
    if (config.enableHelmet) {
        return helmet({
            contentSecurityPolicy: {
                directives: {
                    defaultSrc: [
                        "'self'",
                        'fonts.googleapis.com',
                        'fonts.gstatic.com',
                        'data:',
                        'gravatar.com',
                    ],
                    styleSrc: [
                        "'self'",
                        'fonts.googleapis.com',
                        'fonts.gstatic.com',
                        'data:',
                        'unsafe-inline',
                    ],
                },
            },
        });
    }
    return (req, res, next) => {
        next();
    };
};
<|endoftext|>


<commit_before>
/*!
 * Connect - staticProvider
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var fs = require('fs')
  , path = require('path')
  , join = path.join
  , basename = path.basename
  , normalize = path.normalize
  , utils = require('../utils')
  , Buffer = require('buffer').Buffer
  , parse = require('url').parse
  , mime = require('mime');

/**
 * Static file server with the given `root` path.
 *
 * Examples:
 *
 *     var oneDay = 86400000;
 *
 *     connect(
 *       connect.static(__dirname + '/public')
 *     ).listen(3000);
 *
 *     connect(
 *       connect.static(__dirname + '/public', { maxAge: oneDay })
 *     ).listen(3000);
 *
 * Options:
 *
 *    - `maxAge`   Browser cache maxAge in milliseconds. defaults to 0
 *    - `hidden`   Allow transfer of hidden files. defaults to false
 *
 * @param {String} root
 * @param {Object} options
 * @return {Function}
 * @api public
 */

exports = module.exports = function static(root, options){
  options = options || {};

  // root required
  if (!root) throw new Error('static() root path required');
  options.root = root;

  return function static(req, res, next) {
    options.path = req.url;
    send(req, res, next, options);
  };
};

/**
 * Expose mime module.
 */

exports.mime = mime;

/**
 * Respond with 416  "Requested Range Not Satisfiable"
 *
 * @param {ServerResponse} res
 * @api private
 */

function invalidRange(res) {
  var body = 'Requested Range Not Satisfiable';
  res.setHeader('Content-Type', 'text/plain');
  res.setHeader('Content-Length', body.length);
  res.statusCode = 416;
  res.end(body);
}

/**
 * Attempt to tranfer the requseted file to `res`.
 *
 * @param {ServerRequest}
 * @param {ServerResponse}
 * @param {Function} next
 * @param {Object} options
 * @api private
 */

var send = exports.send = function(req, res, next, options){
  options = options || {};
  if (!options.path) throw new Error('path required');

  // setup
  var maxAge = options.maxAge || 0
    , ranges = req.headers.range
    , head = 'HEAD' == req.method
    , root = options.root ? normalize(options.root) : null
    , fn = options.callback
    , hidden = options.hidden
    , done;

  // replace next() with callback when available
  if (fn) next = fn;

  // ignore non-GET requests
  if ('GET' != req.method && !head) return next();

  // parse url
  var url = parse(options.path)
    , path = decodeURIComponent(url.pathname)
    , type;

  // when root is not given, consider .. malicious
  if (!root && ~path.indexOf('..')) return utils.forbidden(res);

  // join / normalize from optional root dir
  path = normalize(join(root, path));

  // malicious path
  if (root && 0 != path.indexOf(root)) return fn
    ? fn(new Error('Forbidden'))
    : utils.forbidden(res);

  // index.html support
  if ('/' == path[path.length - 1]) path += 'index.html';

  // "hidden" file
  if (!hidden && '.' == basename(path)[0]) return next();

  // mime type
  type = mime.lookup(path);

  fs.stat(path, function(err, stat){
    // ignore ENOENT
    if (err) {
      if (fn) return fn(err);
      return 'ENOENT' == err.code
        ? next()
        : next(err);
    // ignore directories
    } else if (stat.isDirectory()) {
      return fn
        ? fn(new Error('Cannot Transfer Directory'))
        : next();
    }

    var opts = {};

    // we have a Range request
    if (ranges) {
      ranges = utils.parseRange(stat.size, ranges);
      // valid
      if (ranges) {
        // TODO: stream options
        // TODO: multiple support
        opts.start = ranges[0].start;
        opts.end = ranges[0].end;
        res.statusCode = 206;
        res.setHeader('Content-Range', 'bytes '
          + opts.start
          + '-'
          + opts.end
          + '/'
          + stat.size);
      // invalid
      } else {
        return fn
          ? fn(new Error('Requested Range Not Satisfiable'))
          : invalidRange(res);
      }
    // stream the entire file
    } else {
      res.setHeader('Content-Length', stat.size);
      res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
      res.setHeader('Last-Modified', stat.mtime.toUTCString());
      res.setHeader('ETag', utils.etag(stat));

      // conditional GET support
      if (utils.conditionalGET(req)) {
        if (!utils.modified(req, res)) {
          return utils.notModified(res);
        }
      }
    }

    // header fields
    if (!res.getHeader('content-type')) {
      var charset = mime.charsets.lookup(type);
      res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
    }
    res.setHeader('Accept-Ranges', 'bytes');

    // transfer
    if (head) return res.end();

    // stream
    var stream = fs.createReadStream(path, opts);
    stream.pipe(res);

    // callback
    if (fn) {
      function callback(err) { done || fn(err); done = true }
      req.on('close', callback);
      req.socket.on('error', callback);
      stream.on('end', callback);
    }
  });
};
<commit_msg>Added `getOnly` option to `connect.static.send()`<commit_after>
/*!
 * Connect - staticProvider
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var fs = require('fs')
  , path = require('path')
  , join = path.join
  , basename = path.basename
  , normalize = path.normalize
  , utils = require('../utils')
  , Buffer = require('buffer').Buffer
  , parse = require('url').parse
  , mime = require('mime');

/**
 * Static file server with the given `root` path.
 *
 * Examples:
 *
 *     var oneDay = 86400000;
 *
 *     connect(
 *       connect.static(__dirname + '/public')
 *     ).listen(3000);
 *
 *     connect(
 *       connect.static(__dirname + '/public', { maxAge: oneDay })
 *     ).listen(3000);
 *
 * Options:
 *
 *    - `maxAge`   Browser cache maxAge in milliseconds. defaults to 0
 *    - `hidden`   Allow transfer of hidden files. defaults to false
 *
 * @param {String} root
 * @param {Object} options
 * @return {Function}
 * @api public
 */

exports = module.exports = function static(root, options){
  options = options || {};

  // root required
  if (!root) throw new Error('static() root path required');
  options.root = root;

  return function static(req, res, next) {
    options.path = req.url;
    options.getOnly = true;
    send(req, res, next, options);
  };
};

/**
 * Expose mime module.
 */

exports.mime = mime;

/**
 * Respond with 416  "Requested Range Not Satisfiable"
 *
 * @param {ServerResponse} res
 * @api private
 */

function invalidRange(res) {
  var body = 'Requested Range Not Satisfiable';
  res.setHeader('Content-Type', 'text/plain');
  res.setHeader('Content-Length', body.length);
  res.statusCode = 416;
  res.end(body);
}

/**
 * Attempt to tranfer the requseted file to `res`.
 *
 * @param {ServerRequest}
 * @param {ServerResponse}
 * @param {Function} next
 * @param {Object} options
 * @api private
 */

var send = exports.send = function(req, res, next, options){
  options = options || {};
  if (!options.path) throw new Error('path required');

  // setup
  var maxAge = options.maxAge || 0
    , ranges = req.headers.range
    , head = 'HEAD' == req.method
    , get = 'GET' == req.method
    , root = options.root ? normalize(options.root) : null
    , getOnly = options.getOnly
    , fn = options.callback
    , hidden = options.hidden
    , done;

  // replace next() with callback when available
  if (fn) next = fn;

  // ignore non-GET requests
  if (getOnly && !get && !head) return next();

  // parse url
  var url = parse(options.path)
    , path = decodeURIComponent(url.pathname)
    , type;

  // when root is not given, consider .. malicious
  if (!root && ~path.indexOf('..')) return utils.forbidden(res);

  // join / normalize from optional root dir
  path = normalize(join(root, path));

  // malicious path
  if (root && 0 != path.indexOf(root)) return fn
    ? fn(new Error('Forbidden'))
    : utils.forbidden(res);

  // index.html support
  if ('/' == path[path.length - 1]) path += 'index.html';

  // "hidden" file
  if (!hidden && '.' == basename(path)[0]) return next();

  // mime type
  type = mime.lookup(path);

  fs.stat(path, function(err, stat){
    // ignore ENOENT
    if (err) {
      if (fn) return fn(err);
      return 'ENOENT' == err.code
        ? next()
        : next(err);
    // ignore directories
    } else if (stat.isDirectory()) {
      return fn
        ? fn(new Error('Cannot Transfer Directory'))
        : next();
    }

    var opts = {};

    // we have a Range request
    if (ranges) {
      ranges = utils.parseRange(stat.size, ranges);
      // valid
      if (ranges) {
        // TODO: stream options
        // TODO: multiple support
        opts.start = ranges[0].start;
        opts.end = ranges[0].end;
        res.statusCode = 206;
        res.setHeader('Content-Range', 'bytes '
          + opts.start
          + '-'
          + opts.end
          + '/'
          + stat.size);
      // invalid
      } else {
        return fn
          ? fn(new Error('Requested Range Not Satisfiable'))
          : invalidRange(res);
      }
    // stream the entire file
    } else {
      res.setHeader('Content-Length', stat.size);
      res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
      res.setHeader('Last-Modified', stat.mtime.toUTCString());
      res.setHeader('ETag', utils.etag(stat));

      // conditional GET support
      if (utils.conditionalGET(req)) {
        if (!utils.modified(req, res)) {
          return utils.notModified(res);
        }
      }
    }

    // header fields
    if (!res.getHeader('content-type')) {
      var charset = mime.charsets.lookup(type);
      res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
    }
    res.setHeader('Accept-Ranges', 'bytes');

    // transfer
    if (head) return res.end();

    // stream
    var stream = fs.createReadStream(path, opts);
    stream.pipe(res);

    // callback
    if (fn) {
      function callback(err) { done || fn(err); done = true }
      req.on('close', callback);
      req.socket.on('error', callback);
      stream.on('end', callback);
    }
  });
};
<|endoftext|>