<commit_before>/**
 * Contains the logic for the export button.
 * @returns {{}}
 */
module.exports = function (graph) {

	var exportMenu = {},
		exportSvgButton,
		exportFilename,
		exportJsonButton,
		exportableJsonText;

	/**
	 * Adds the export button to the website.
	 */
	exportMenu.setup = function () {
		exportSvgButton = d3.select("#exportSvg")
			.on("click", exportSvg);
		exportJsonButton = d3.select("#exportJson")
			.on("click", exportJson);

		var menuEntry= d3.select("#export");
		menuEntry.on("mouseover",function(){
			var searchMenu=graph.options().searchMenu();
			searchMenu.hideSearchEntries();
		});
	};

	exportMenu.setFilename = function (filename) {
		exportFilename = filename || "export";
	};

	exportMenu.setJsonText = function (jsonText) {
		exportableJsonText = jsonText;
	};

	function exportSvg() {
		// Get the d3js SVG element
		var graphSvg = d3.select(graph.options().graphContainerSelector()).select("svg"),
			graphSvgCode,
			escapedGraphSvgCode,
			dataURI;

		// inline the styles, so that the exported svg code contains the css rules
		inlineVowlStyles();
		hideNonExportableElements();

		graphSvgCode = graphSvg.attr("version", 1.1)
			.attr("xmlns", "http://www.w3.org/2000/svg")
			.node().parentNode.innerHTML;

		// Insert the reference to VOWL
		graphSvgCode = "<!-- Created with WebVOWL (version " + webvowl.version + ")" +
		               ", http://vowl.visualdataweb.org -->\n" + graphSvgCode;

		escapedGraphSvgCode = escapeUnicodeCharacters(graphSvgCode);
		//btoa(); Creates a base-64 encoded ASCII string from a "string" of binary data.
		dataURI = "data:image/svg+xml;base64," + btoa(escapedGraphSvgCode);

		exportSvgButton.attr("href", dataURI)
			.attr("download", exportFilename + ".svg");

		// remove graphic styles for interaction to go back to normal
		removeVowlInlineStyles();
		showNonExportableElements();
	}

	function escapeUnicodeCharacters(text) {
		var textSnippets = [],
			i, textLength = text.length,
			character,
			charCode;

		for (i = 0; i < textLength; i++) {
			character = text.charAt(i);
			charCode = character.charCodeAt(0);

			if (charCode < 128) {
				textSnippets.push(character);
			} else {
				textSnippets.push("&#" + charCode + ";");
			}
		}

		return textSnippets.join("");
	}

	function inlineVowlStyles() {
		setStyleSensitively(".text", [{name: "font-family", value: "Helvetica, Arial, sans-serif"}, {name: "font-size", value: "12px"}]);
		setStyleSensitively(".subtext", [{name: "font-size", value: "9px"}]);
		setStyleSensitively(".text.instance-count", [{name: "fill", value: "#666"}]);
		setStyleSensitively(".external + text .instance-count", [{name: "fill", value: "#aaa"}]);
		setStyleSensitively(".cardinality", [{name: "font-size", value: "10px"}]);
		setStyleSensitively(".text, .embedded", [{name: "pointer-events", value: "none"}]);
		setStyleSensitively(".class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty, .allvaluesfromproperty, .somevaluesfromproperty", [{name: "fill", value: "#acf"}]);
		setStyleSensitively(".label .datatype, .datatypeproperty", [{name: "fill", value: "#9c6"}]);
		setStyleSensitively(".rdf, .rdfproperty", [{name: "fill", value: "#c9c"}]);
		setStyleSensitively(".literal, .node .datatype", [{name: "fill", value: "#fc3"}]);
		setStyleSensitively(".deprecated, .deprecatedproperty", [{name: "fill", value: "#ccc"}]);
		setStyleSensitively(".external, .externalproperty", [{name: "fill", value: "#36c"}]);
		setStyleSensitively("path, .nofill", [{name: "fill", value: "none"}]);
		setStyleSensitively("marker path", [{name: "fill", value: "#000"}]);
		setStyleSensitively(".class, path, line, .fineline", [{name: "stroke", value: "#000"}]);
		setStyleSensitively(".white, .subclass, .subclassproperty, .external + text", [{name: "fill", value: "#fff"}]);
		setStyleSensitively(".class.hovered, .property.hovered, .cardinality.hovered, .cardinality.focused, circle.pin, .filled.hovered, .filled.focused", [{name: "fill", value: "#f00"}, {name: "cursor", value: "pointer"}]);
		setStyleSensitively(".focused, path.hovered", [{name: "stroke", value: "#f00"}]);
		setStyleSensitively(".indirect-highlighting, .feature:hover", [{name: "fill", value: "#f90"}]);
		setStyleSensitively(".values-from", [{name: "stroke", value: "#69c"}]);
		setStyleSensitively(".symbol, .values-from.filled", [{name: "fill", value: "#69c"}]);
		setStyleSensitively(".class, path, line", [{name: "stroke-width", value: "2"}]);
		setStyleSensitively(".fineline", [{name: "stroke-width", value: "1"}]);
		setStyleSensitively(".dashed, .anonymous", [{name: "stroke-dasharray", value: "8"}]);
		setStyleSensitively(".dotted", [{name: "stroke-dasharray", value: "3"}]);
		setStyleSensitively("rect.focused, circle.focused", [{name: "stroke-width", value: "4px"}]);
		setStyleSensitively(".nostroke", [{name: "stroke", value: "none"}]);
		setStyleSensitively("marker path", [{name: "stroke-dasharray", value: "100"}]);
	}

	function setStyleSensitively(selector, styles) {
		var elements = d3.selectAll(selector);
		if (elements.empty()) {
			return;
		}

		styles.forEach(function (style) {
			elements.each(function () {
				var element = d3.select(this);
				if (!shouldntChangeInlineCss(element, style.name)) {
					element.style(style.name, style.value);
				}
			});
		});
	}

	function shouldntChangeInlineCss(element, style) {
		return style === "fill" && hasBackgroundColorSet(element);
	}

	function hasBackgroundColorSet(element) {
		var data = element.datum();
		return data.backgroundColor && !!data.backgroundColor();
	}

	/**
	 * For example the pin of the pick&pin module should be invisible in the exported graphic.
	 */
	function hideNonExportableElements() {
		d3.selectAll(".hidden-in-export").style("display", "none");
	}

	function removeVowlInlineStyles() {
		d3.selectAll(".text, .subtext, .text.instance-count, .external + text .instance-count, .cardinality, .text, .embedded, .class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty, .allvaluesfromproperty, .somevaluesfromproperty, .label .datatype, .datatypeproperty, .rdf, .rdfproperty, .literal, .node .datatype, .deprecated, .deprecatedproperty, .external, .externalproperty, path, .nofill, .symbol, .values-from.filled, marker path, .class, path, line, .fineline, .white, .subclass, .subclassproperty, .external + text, .class.hovered, .property.hovered, .cardinality.hovered, .cardinality.focused, circle.pin, .filled.hovered, .filled.focused, .focused, path.hovered, .indirect-highlighting, .feature:hover, .values-from, .class, path, line, .fineline, .dashed, .anonymous, .dotted, rect.focused, circle.focused, .nostroke, marker path")
			.each(function () {
				var element = d3.select(this);

				var inlineStyles = element.node().style;
				for (var styleName in inlineStyles) {
					if (inlineStyles.hasOwnProperty(styleName)) {
						if (shouldntChangeInlineCss(element, styleName)) {
							continue;
						}
						element.style(styleName, null);
					}
				}
				if (element.datum && element.datum().type){
					if (element.datum().type()==="rdfs:subClassOf") {
						element.style("fill", null);
					}
				}
			});
	}

	function showNonExportableElements() {
		d3.selectAll(".hidden-in-export").style("display", null);
	}

	function exportJson() {
		/**  check if there is data **/
		if (!exportableJsonText) {
			alert("No graph data available.");
			// Stop the redirection to the path of the href attribute
			d3.event.preventDefault();
			return;
		}

		if(graph.options().exportWithGraphChanges()) {
			exportableJsonText = JSON.stringify(graph.addGraphChanges(JSON.parse(exportableJsonText)));
		}

		var i; // an index variable for the for-loops

		/** get data for exporter **/
		var nodeElements = graph.graphNodeElements();  // get visible nodes
		var propElements = graph.graphLabelElements(); // get visible labels
		var jsonObj = JSON.parse(exportableJsonText);	   // reparse the original input json

		/** modify comment **/
		var comment = jsonObj._comment;
		var additionalString = " [Additional Information added by WebVOWL Exporter Version: " + "@@WEBVOWL_VERSION" + "]";
		// adding new string to comment only if it does not exist
		if (comment.indexOf(additionalString) === -1) {
			jsonObj._comment = comment + " [Additional Information added by WebVOWL Exporter Version: " + "@@WEBVOWL_VERSION" + "]";
		}

		var classAttribute = jsonObj.classAttribute;
		var propAttribute = jsonObj.propertyAttribute;
		/**  remove previously stored variables **/
		for (i = 0; i < classAttribute.length; i++) {
			var classObj = classAttribute[i];
			delete classObj.pos;
			delete classObj.pinned;
		}
		var propertyObj;
		for (i = 0; i < propAttribute.length; i++) {
			propertyObj = propAttribute[i];
			delete propertyObj.pos;
			delete propertyObj.pinned;
		}
		/**  add new variables to jsonObj  **/
		// class attribute variables
		nodeElements.each(function (node) {
			var nodeId = node.id();
			for (i = 0; i < classAttribute.length; i++) {
				var classObj = classAttribute[i];
				if (classObj.id === nodeId) {
					// store relative positions
					classObj.pos = [node.x, node.y];
					if (node.pinned())
						classObj.pinned = true;
					break;
				}
			}
		});
		// property attribute variables
		for (var j = 0; j < propElements.length; j++) {
			var correspondingProp = propElements[j].property();
			for (i = 0; i < propAttribute.length; i++) {
				propertyObj = propAttribute[i];
				if (propertyObj.id === correspondingProp.id()) {
					propertyObj.pos = [propElements[j].x, propElements[j].y];
					if (propElements[j].pinned())
						propertyObj.pinned = true;
					break;
				}
			}
		}
		/** create the variable for settings and set their values **/
		jsonObj.settings = {};

		// Global Settings
		var zoom = graph.scaleFactor();
		var paused = graph.paused();
		var translation = graph.translation();
		jsonObj.settings.global = {};
		jsonObj.settings.global.zoom = zoom;
		jsonObj.settings.global.translation = translation;
		jsonObj.settings.global.paused = paused;

		// shared variable declaration
		var cb_text;
		var isEnabled;
		var cb_obj;

		// Gravity Settings
		var classDistance = graph.options().classDistance();
		var datatypeDistance = graph.options().datatypeDistance();
		jsonObj.settings.gravity = {};
		jsonObj.settings.gravity.classDistance = classDistance;
		jsonObj.settings.gravity.datatypeDistance = datatypeDistance;

		// Filter Settings
		var fMenu = graph.options().filterMenu();
		var fContainer = fMenu.getCheckBoxContainer();
		var cbCont = [];
		for (i = 0; i < fContainer.length; i++) {
			cb_text = fContainer[i].checkbox.attr("id");
			isEnabled = fContainer[i].checkbox.property("checked");
			cb_obj = {};
			cb_obj.id = cb_text;
			cb_obj.checked = isEnabled;
			cbCont.push(cb_obj);
		}
		var degreeSliderVal = fMenu.getDegreeSliderValue();
		jsonObj.settings.filter = {};
		jsonObj.settings.filter.checkBox = cbCont;
		jsonObj.settings.filter.degreeSliderValue = degreeSliderVal;

		// Modes Settings
		var mMenu = graph.options().modeMenu();
		var mContainer = mMenu.getCheckBoxContainer();
		var cb_modes = [];
		for (i = 0; i < mContainer.length; i++) {
			cb_text = mContainer[i].attr("id");
			isEnabled = mContainer[i].property("checked");
			cb_obj = {};
			cb_obj.id = cb_text;
			cb_obj.checked = isEnabled;
			cb_modes.push(cb_obj);
		}
		var colorSwitchState = mMenu.colorModeState();
		jsonObj.settings.modes = {};
		jsonObj.settings.modes.checkBox = cb_modes;
		jsonObj.settings.modes.colorSwitchState = colorSwitchState;

		var exportObj = {};
		// todo: [ ] find better way for ordering the objects
		// hack for ordering of objects, so settings is after metrics
		exportObj._comment = jsonObj._comment;
		exportObj.header = jsonObj.header;
		exportObj.namespace = jsonObj.namespace;
		exportObj.metrics = jsonObj.metrics;
		exportObj.settings = jsonObj.settings;
		exportObj.class = jsonObj.class;
		exportObj.classAttribute = jsonObj.classAttribute;
		exportObj.property = jsonObj.property;
		exportObj.propertyAttribute = jsonObj.propertyAttribute;

		// make a string again;
		var exportText = JSON.stringify(exportObj, null, '  ');
		// write the data
		var dataURI = "data:text/json;charset=utf-8," + encodeURIComponent(exportText);
		exportJsonButton.attr("href", dataURI)
			.attr("download", exportFilename + ".json");
	}

	return exportMenu;
};
<commit_msg>Exported JSON nicely formatted<commit_after>/**
 * Contains the logic for the export button.
 * @returns {{}}
 */
module.exports = function (graph) {

	var exportMenu = {},
		exportSvgButton,
		exportFilename,
		exportJsonButton,
		exportableJsonText;

	/**
	 * Adds the export button to the website.
	 */
	exportMenu.setup = function () {
		exportSvgButton = d3.select("#exportSvg")
			.on("click", exportSvg);
		exportJsonButton = d3.select("#exportJson")
			.on("click", exportJson);

		var menuEntry= d3.select("#export");
		menuEntry.on("mouseover",function(){
			var searchMenu=graph.options().searchMenu();
			searchMenu.hideSearchEntries();
		});
	};

	exportMenu.setFilename = function (filename) {
		exportFilename = filename || "export";
	};

	exportMenu.setJsonText = function (jsonText) {
		exportableJsonText = jsonText;
	};

	function exportSvg() {
		// Get the d3js SVG element
		var graphSvg = d3.select(graph.options().graphContainerSelector()).select("svg"),
			graphSvgCode,
			escapedGraphSvgCode,
			dataURI;

		// inline the styles, so that the exported svg code contains the css rules
		inlineVowlStyles();
		hideNonExportableElements();

		graphSvgCode = graphSvg.attr("version", 1.1)
			.attr("xmlns", "http://www.w3.org/2000/svg")
			.node().parentNode.innerHTML;

		// Insert the reference to VOWL
		graphSvgCode = "<!-- Created with WebVOWL (version " + webvowl.version + ")" +
		               ", http://vowl.visualdataweb.org -->\n" + graphSvgCode;

		escapedGraphSvgCode = escapeUnicodeCharacters(graphSvgCode);
		//btoa(); Creates a base-64 encoded ASCII string from a "string" of binary data.
		dataURI = "data:image/svg+xml;base64," + btoa(escapedGraphSvgCode);

		exportSvgButton.attr("href", dataURI)
			.attr("download", exportFilename + ".svg");

		// remove graphic styles for interaction to go back to normal
		removeVowlInlineStyles();
		showNonExportableElements();
	}

	function escapeUnicodeCharacters(text) {
		var textSnippets = [],
			i, textLength = text.length,
			character,
			charCode;

		for (i = 0; i < textLength; i++) {
			character = text.charAt(i);
			charCode = character.charCodeAt(0);

			if (charCode < 128) {
				textSnippets.push(character);
			} else {
				textSnippets.push("&#" + charCode + ";");
			}
		}

		return textSnippets.join("");
	}

	function inlineVowlStyles() {
		setStyleSensitively(".text", [{name: "font-family", value: "Helvetica, Arial, sans-serif"}, {name: "font-size", value: "12px"}]);
		setStyleSensitively(".subtext", [{name: "font-size", value: "9px"}]);
		setStyleSensitively(".text.instance-count", [{name: "fill", value: "#666"}]);
		setStyleSensitively(".external + text .instance-count", [{name: "fill", value: "#aaa"}]);
		setStyleSensitively(".cardinality", [{name: "font-size", value: "10px"}]);
		setStyleSensitively(".text, .embedded", [{name: "pointer-events", value: "none"}]);
		setStyleSensitively(".class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty, .allvaluesfromproperty, .somevaluesfromproperty", [{name: "fill", value: "#acf"}]);
		setStyleSensitively(".label .datatype, .datatypeproperty", [{name: "fill", value: "#9c6"}]);
		setStyleSensitively(".rdf, .rdfproperty", [{name: "fill", value: "#c9c"}]);
		setStyleSensitively(".literal, .node .datatype", [{name: "fill", value: "#fc3"}]);
		setStyleSensitively(".deprecated, .deprecatedproperty", [{name: "fill", value: "#ccc"}]);
		setStyleSensitively(".external, .externalproperty", [{name: "fill", value: "#36c"}]);
		setStyleSensitively("path, .nofill", [{name: "fill", value: "none"}]);
		setStyleSensitively("marker path", [{name: "fill", value: "#000"}]);
		setStyleSensitively(".class, path, line, .fineline", [{name: "stroke", value: "#000"}]);
		setStyleSensitively(".white, .subclass, .subclassproperty, .external + text", [{name: "fill", value: "#fff"}]);
		setStyleSensitively(".class.hovered, .property.hovered, .cardinality.hovered, .cardinality.focused, circle.pin, .filled.hovered, .filled.focused", [{name: "fill", value: "#f00"}, {name: "cursor", value: "pointer"}]);
		setStyleSensitively(".focused, path.hovered", [{name: "stroke", value: "#f00"}]);
		setStyleSensitively(".indirect-highlighting, .feature:hover", [{name: "fill", value: "#f90"}]);
		setStyleSensitively(".values-from", [{name: "stroke", value: "#69c"}]);
		setStyleSensitively(".symbol, .values-from.filled", [{name: "fill", value: "#69c"}]);
		setStyleSensitively(".class, path, line", [{name: "stroke-width", value: "2"}]);
		setStyleSensitively(".fineline", [{name: "stroke-width", value: "1"}]);
		setStyleSensitively(".dashed, .anonymous", [{name: "stroke-dasharray", value: "8"}]);
		setStyleSensitively(".dotted", [{name: "stroke-dasharray", value: "3"}]);
		setStyleSensitively("rect.focused, circle.focused", [{name: "stroke-width", value: "4px"}]);
		setStyleSensitively(".nostroke", [{name: "stroke", value: "none"}]);
		setStyleSensitively("marker path", [{name: "stroke-dasharray", value: "100"}]);
	}

	function setStyleSensitively(selector, styles) {
		var elements = d3.selectAll(selector);
		if (elements.empty()) {
			return;
		}

		styles.forEach(function (style) {
			elements.each(function () {
				var element = d3.select(this);
				if (!shouldntChangeInlineCss(element, style.name)) {
					element.style(style.name, style.value);
				}
			});
		});
	}

	function shouldntChangeInlineCss(element, style) {
		return style === "fill" && hasBackgroundColorSet(element);
	}

	function hasBackgroundColorSet(element) {
		var data = element.datum();
		return data.backgroundColor && !!data.backgroundColor();
	}

	/**
	 * For example the pin of the pick&pin module should be invisible in the exported graphic.
	 */
	function hideNonExportableElements() {
		d3.selectAll(".hidden-in-export").style("display", "none");
	}

	function removeVowlInlineStyles() {
		d3.selectAll(".text, .subtext, .text.instance-count, .external + text .instance-count, .cardinality, .text, .embedded, .class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty, .allvaluesfromproperty, .somevaluesfromproperty, .label .datatype, .datatypeproperty, .rdf, .rdfproperty, .literal, .node .datatype, .deprecated, .deprecatedproperty, .external, .externalproperty, path, .nofill, .symbol, .values-from.filled, marker path, .class, path, line, .fineline, .white, .subclass, .subclassproperty, .external + text, .class.hovered, .property.hovered, .cardinality.hovered, .cardinality.focused, circle.pin, .filled.hovered, .filled.focused, .focused, path.hovered, .indirect-highlighting, .feature:hover, .values-from, .class, path, line, .fineline, .dashed, .anonymous, .dotted, rect.focused, circle.focused, .nostroke, marker path")
			.each(function () {
				var element = d3.select(this);

				var inlineStyles = element.node().style;
				for (var styleName in inlineStyles) {
					if (inlineStyles.hasOwnProperty(styleName)) {
						if (shouldntChangeInlineCss(element, styleName)) {
							continue;
						}
						element.style(styleName, null);
					}
				}
				if (element.datum && element.datum().type){
					if (element.datum().type()==="rdfs:subClassOf") {
						element.style("fill", null);
					}
				}
			});
	}

	function showNonExportableElements() {
		d3.selectAll(".hidden-in-export").style("display", null);
	}

	function exportJson() {
		/**  check if there is data **/
		if (!exportableJsonText) {
			alert("No graph data available.");
			// Stop the redirection to the path of the href attribute
			d3.event.preventDefault();
			return;
		}

		var exportableWithGraphChanges;

		if(graph.options().exportWithGraphChanges()) {
			exportableWithGraphChanges = graph.addGraphChanges(JSON.parse(exportableJsonText));
			exportableJsonText = JSON.stringify(exportableWithGraphChanges, null, 2);
		}

		var i; // an index variable for the for-loops

		/** get data for exporter **/
		var nodeElements = graph.graphNodeElements();  // get visible nodes
		var propElements = graph.graphLabelElements(); // get visible labels
		var jsonObj = JSON.parse(exportableJsonText);	   // reparse the original input json

		/** modify comment **/
		var comment = jsonObj._comment;
		var additionalString = " [Additional Information added by WebVOWL Exporter Version: " + "@@WEBVOWL_VERSION" + "]";
		// adding new string to comment only if it does not exist
		if (comment.indexOf(additionalString) === -1) {
			jsonObj._comment = comment + " [Additional Information added by WebVOWL Exporter Version: " + "@@WEBVOWL_VERSION" + "]";
		}

		var classAttribute = jsonObj.classAttribute;
		var propAttribute = jsonObj.propertyAttribute;
		/**  remove previously stored variables **/
		for (i = 0; i < classAttribute.length; i++) {
			var classObj = classAttribute[i];
			delete classObj.pos;
			delete classObj.pinned;
		}
		var propertyObj;
		for (i = 0; i < propAttribute.length; i++) {
			propertyObj = propAttribute[i];
			delete propertyObj.pos;
			delete propertyObj.pinned;
		}
		/**  add new variables to jsonObj  **/
		// class attribute variables
		nodeElements.each(function (node) {
			var nodeId = node.id();
			for (i = 0; i < classAttribute.length; i++) {
				var classObj = classAttribute[i];
				if (classObj.id === nodeId) {
					// store relative positions
					classObj.pos = [node.x, node.y];
					if (node.pinned())
						classObj.pinned = true;
					break;
				}
			}
		});
		// property attribute variables
		for (var j = 0; j < propElements.length; j++) {
			var correspondingProp = propElements[j].property();
			for (i = 0; i < propAttribute.length; i++) {
				propertyObj = propAttribute[i];
				if (propertyObj.id === correspondingProp.id()) {
					propertyObj.pos = [propElements[j].x, propElements[j].y];
					if (propElements[j].pinned())
						propertyObj.pinned = true;
					break;
				}
			}
		}
		/** create the variable for settings and set their values **/
		jsonObj.settings = {};

		// Global Settings
		var zoom = graph.scaleFactor();
		var paused = graph.paused();
		var translation = graph.translation();
		jsonObj.settings.global = {};
		jsonObj.settings.global.zoom = zoom;
		jsonObj.settings.global.translation = translation;
		jsonObj.settings.global.paused = paused;

		// shared variable declaration
		var cb_text;
		var isEnabled;
		var cb_obj;

		// Gravity Settings
		var classDistance = graph.options().classDistance();
		var datatypeDistance = graph.options().datatypeDistance();
		jsonObj.settings.gravity = {};
		jsonObj.settings.gravity.classDistance = classDistance;
		jsonObj.settings.gravity.datatypeDistance = datatypeDistance;

		// Filter Settings
		var fMenu = graph.options().filterMenu();
		var fContainer = fMenu.getCheckBoxContainer();
		var cbCont = [];
		for (i = 0; i < fContainer.length; i++) {
			cb_text = fContainer[i].checkbox.attr("id");
			isEnabled = fContainer[i].checkbox.property("checked");
			cb_obj = {};
			cb_obj.id = cb_text;
			cb_obj.checked = isEnabled;
			cbCont.push(cb_obj);
		}
		var degreeSliderVal = fMenu.getDegreeSliderValue();
		jsonObj.settings.filter = {};
		jsonObj.settings.filter.checkBox = cbCont;
		jsonObj.settings.filter.degreeSliderValue = degreeSliderVal;

		// Modes Settings
		var mMenu = graph.options().modeMenu();
		var mContainer = mMenu.getCheckBoxContainer();
		var cb_modes = [];
		for (i = 0; i < mContainer.length; i++) {
			cb_text = mContainer[i].attr("id");
			isEnabled = mContainer[i].property("checked");
			cb_obj = {};
			cb_obj.id = cb_text;
			cb_obj.checked = isEnabled;
			cb_modes.push(cb_obj);
		}
		var colorSwitchState = mMenu.colorModeState();
		jsonObj.settings.modes = {};
		jsonObj.settings.modes.checkBox = cb_modes;
		jsonObj.settings.modes.colorSwitchState = colorSwitchState;

		var exportObj = {};
		// todo: [ ] find better way for ordering the objects
		// hack for ordering of objects, so settings is after metrics
		exportObj._comment = jsonObj._comment;
		exportObj.header = jsonObj.header;
		exportObj.namespace = jsonObj.namespace;
		exportObj.metrics = jsonObj.metrics;
		exportObj.settings = jsonObj.settings;
		exportObj.class = jsonObj.class;
		exportObj.classAttribute = jsonObj.classAttribute;
		exportObj.property = jsonObj.property;
		exportObj.propertyAttribute = jsonObj.propertyAttribute;

		// make a string again;
		var exportText = JSON.stringify(exportObj, null, '  ');
		// write the data
		var dataURI = "data:text/json;charset=utf-8," + encodeURIComponent(exportText);
		exportJsonButton.attr("href", dataURI)
			.attr("download", exportFilename + ".json");
	}

	return exportMenu;
};
<|endoftext|>


<commit_before>const Bluebird = require('bluebird');
const config = require('../config');
const Postcard = require('../models/postcard');
const braintree = require('braintree');
const logger = require('../utils/logger').logger();
const uuid = require('uuid/v4');

const gateway = braintree.connect({
  environment: braintree.Environment.Sandbox,
  merchantId: config.braintreeMerchantId,
  publicKey: config.braintreePublicKey,
  privateKey: config.braintreePrivateKey
});

const createSaleObject = (amount, nonce) => {
	return {
	  amount,
	  paymentMethodNonce: nonce,
	  orderId: uuid(),
	  options: {
	  	submitForSettlement: true
	  }
  };
};

module.exports = {

	//generate token required to get a nonce in the client
	generateToken: () => {
		const clientToken = gateway.clientToken;

		return clientToken.generate({})
		.then(function(token){
			return token;
		});
	},

	//process payment
	makeSale: (amount, nonce) => {
		const saleRequest = createSaleObject(amount, nonce);

		return gateway.transaction.sale(saleRequest)
		.then(function(result){
			console.log('result', result)
			if (!result.success) throw new Error(result.message);

			return result.transaction;
		});
	},

	processRefund: (transactionId, amount) => {
		logger.info('Processing refund', transactionId, amount);
		return gateway.transaction.find(transactionId)
		.then(transaction => {
			if (!amount) amount = transaction.amount;

			if (transaction.status === 'settled' || transaction.status === 'settling') {
				return gateway.transaction.refund(transaction.id, amount);
			}
			else {
				return gateway.transaction.void(transaction.id, amount);
			}
		})
		.then(result => {
			if (!result.success) throw new Error(result.message);

			return result;
		})
		.catch(function(err){
			logger.error(err);
			throw new Error(err);
		})
	}
};
<commit_msg>enable production mode for braintree<commit_after>const Bluebird = require('bluebird');
const config = require('../config');
const Postcard = require('../models/postcard');
const braintree = require('braintree');
const logger = require('../utils/logger').logger();
const uuid = require('uuid/v4');

const braintreeEnvironment = config.nodeEnv === 'production' ? braintree.Environment.Production : braintree.Environment.Sandbox;

const gateway = braintree.connect({
  environment: braintreeEbvironment,
  merchantId: config.braintreeMerchantId,
  publicKey: config.braintreePublicKey,
  privateKey: config.braintreePrivateKey
});

const createSaleObject = (amount, nonce) => {
	return {
	  amount,
	  paymentMethodNonce: nonce,
	  orderId: uuid(),
	  options: {
	  	submitForSettlement: true
	  }
  };
};

module.exports = {

	//generate token required to get a nonce in the client
	generateToken: () => {
		const clientToken = gateway.clientToken;

		return clientToken.generate({})
		.then(function(token){
			return token;
		});
	},

	//process payment
	makeSale: (amount, nonce) => {
		const saleRequest = createSaleObject(amount, nonce);

		return gateway.transaction.sale(saleRequest)
		.then(function(result){
			if (!result.success) throw new Error(result.message);

			return result.transaction;
		});
	},

	processRefund: (transactionId, amount) => {
		logger.info('Processing refund', transactionId, amount);
		return gateway.transaction.find(transactionId)
		.then(transaction => {
			if (!amount) amount = transaction.amount;

			if (transaction.status === 'settled' || transaction.status === 'settling') {
				return gateway.transaction.refund(transaction.id, amount);
			}
			else {
				return gateway.transaction.void(transaction.id, amount);
			}
		})
		.then(result => {
			if (!result.success) throw new Error(result.message);

			return result;
		})
		.catch(function(err){
			logger.error(err);
			throw new Error(err);
		})
	}
};
<|endoftext|>


<commit_before>$(document).ready(function() {

	// Declaring selectors ahead of time for speed
	var $window = $(window);
	var $header = $('header');
	var $placeholder = $('#header-placeholder');

	// "Sticky" the navigation when the user scrolls below the header
	var offsetHeader;
	var heightHeader;

	var updateHeaderStats = function() {
		offsetHeader = $header.offset().top;
		heightHeader = $header.outerHeight();
		$placeholder.height( heightHeader );
	};

	updateHeaderStats();

	$window.resize( updateHeaderStats );

	var stickyNavigation = function() {
		if( $window.scrollTop() > offsetHeader ) {
			$header.addClass('sticky');
			$placeholder.show();
		}else{
			$header.removeClass('sticky');
			$placeholder.hide();
		}

	};

	stickyNavigation();

	$window.scroll( stickyNavigation );
	$window.resize( stickyNavigation );

	// Helper function to get query string, sufficient for our purpose
	function param(name) {
		return (location.search.split(name + '=')[1] || '').split('&')[0];
	}

	// Get initial slide number
	var initial = param('q') || 0;

	// Initialize the slideshow
	var slideshow = new Swiper ('.swiper-container', {

		loop: true,

		initialSlide: 0, // zero-indexed, default is 0

		onInit: function( swiper ) {
			swiper.slideTo(initial, 0);
		},

		autoplayDisableOnInteraction: false,
		autoplay: 2000,
		speed: 650,

		pagination: '.swiper-pagination',

	});

});
<commit_msg>Fix header jitter on resize<commit_after>$(document).ready(function() {

	// Declaring selectors ahead of time for speed
	var $window = $(window);
	var $header = $('header');
	var $placeholder = $('#header-placeholder');

	// "Sticky" the navigation when the user scrolls below the header
	var offsetHeader;
	var heightHeader;

	var updateHeaderStats = function() {
		if( $placeholder.is(":visible") ) {
			offsetHeader = $placeholder.offset().top;
		} else {
			offsetHeader = $header.offset().top;
		}
		heightHeader = $header.outerHeight();
		$placeholder.height( heightHeader );
	};

	updateHeaderStats();

	$window.resize( updateHeaderStats );

	var stickyNavigation = function() {
		if( $window.scrollTop() > offsetHeader ) {
			$header.addClass('sticky');
			$placeholder.show();
		}else{
			$header.removeClass('sticky');
			$placeholder.hide();
		}

	};

	stickyNavigation();

	$window.scroll( stickyNavigation );
	$window.resize( stickyNavigation );

	// Helper function to get query string, sufficient for our purpose
	function param(name) {
		return (location.search.split(name + '=')[1] || '').split('&')[0];
	}

	// Get initial slide number
	var initial = param('q') || 0;

	// Initialize the slideshow
	var slideshow = new Swiper ('.swiper-container', {

		loop: true,

		initialSlide: 0, // zero-indexed, default is 0

		onInit: function( swiper ) {
			swiper.slideTo(initial, 0);
		},

		autoplayDisableOnInteraction: false,
		autoplay: 2000,
		speed: 650,

		pagination: '.swiper-pagination',

	});

});
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import Matrix from 'matrix-js-sdk';
import GuestAccess from './GuestAccess';

const localStorage = window.localStorage;

function deviceId() {
    // XXX: is Math.random()'s deterministicity a problem here?
    var id = Math.floor(Math.random()*16777215).toString(16);
    id = "W" + "000000".substring(id.length) + id;
    if (localStorage) {
        id = localStorage.getItem("mx_device_id") || id;
        localStorage.setItem("mx_device_id", id);
    }
    return id;
}

// A thing that holds your Matrix Client
// Also magically works across sessions through the power of localstorage
class MatrixClientPeg {
    constructor(guestAccess) {
        this.matrixClient = null;
        this.guestAccess = guestAccess;
    }

    get(): MatrixClient {
        return this.matrixClient;
    }

    unset() {
        this.matrixClient = null;
    }

    replaceUsingUrls(hs_url, is_url) {
        this.replaceClient(hs_url, is_url);
    }

    replaceUsingAccessToken(hs_url, is_url, user_id, access_token, isGuest) {
        this.replaceClient(hs_url, is_url, user_id, access_token, isGuest);
    }

    replaceClient(hs_url, is_url, user_id, access_token, isGuest) {
        if (localStorage) {
            try {
                localStorage.clear();
            } catch (e) {
                console.warn("Error clearing local storage", e);
            }
        }
        this.guestAccess.markAsGuest(Boolean(isGuest));
        this._createClient(hs_url, is_url, user_id, access_token);
        if (localStorage) {
            try {
                localStorage.setItem("mx_hs_url", hs_url);
                localStorage.setItem("mx_is_url", is_url);
                localStorage.setItem("mx_user_id", user_id);
                localStorage.setItem("mx_access_token", access_token);
                console.log("Session persisted for %s", user_id);
            } catch (e) {
                console.warn("Error using local storage: can't persist session!", e);
            }
        } else {
            console.warn("No local storage available: can't persist session!");
        }
    }

    getCredentials() {
        return [
            this.matrixClient.baseUrl,
            this.matrixClient.idBaseUrl,
            this.matrixClient.credentials.userId,
            this.matrixClient.getAccessToken(),
            this.guestAccess.isGuest(),
        ];
    }

    tryRestore() {
        if (localStorage) {
            const hs_url = localStorage.getItem("mx_hs_url");
            const is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org';
            const access_token = localStorage.getItem("mx_access_token");
            const user_id = localStorage.getItem("mx_user_id");
            const guestAccess = new GuestAccess(localStorage);
            if (access_token && user_id && hs_url) {
                console.log("Restoring session for %s", user_id);
                this._createClient(hs_url, is_url, user_id, access_token, guestAccess);
            } else {
                console.log("Session not found.");
            }
        }
    }

    _createClient(hs_url, is_url, user_id, access_token) {
        var opts = {
            baseUrl: hs_url,
            idBaseUrl: is_url,
            accessToken: access_token,
            userId: user_id,
            timelineSupport: true,
        };

        if (localStorage) {
            opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage);
            opts.deviceId = deviceId();
        }

        this.matrixClient = Matrix.createClient(opts);

        // we're going to add eventlisteners for each matrix event tile, so the
        // potential number of event listeners is quite high.
        this.matrixClient.setMaxListeners(500);

        if (this.guestAccess) {
            console.log("Guest: %s", this.guestAccess.isGuest());
            this.matrixClient.setGuest(this.guestAccess.isGuest());
            var peekedRoomId = this.guestAccess.getPeekedRoom();
            if (peekedRoomId) {
                console.log("Peeking in room %s", peekedRoomId);
                this.matrixClient.peekInRoom(peekedRoomId);
            }
        }
    }
}

if (!global.mxMatrixClientPeg) {
    global.mxMatrixClientPeg = new MatrixClientPeg(new GuestAccess(localStorage));
    global.mxMatrixClientPeg.tryRestore();
}
module.exports = global.mxMatrixClientPeg;
<commit_msg>Remove other guestAccess arg<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import Matrix from 'matrix-js-sdk';
import GuestAccess from './GuestAccess';

const localStorage = window.localStorage;

function deviceId() {
    // XXX: is Math.random()'s deterministicity a problem here?
    var id = Math.floor(Math.random()*16777215).toString(16);
    id = "W" + "000000".substring(id.length) + id;
    if (localStorage) {
        id = localStorage.getItem("mx_device_id") || id;
        localStorage.setItem("mx_device_id", id);
    }
    return id;
}

// A thing that holds your Matrix Client
// Also magically works across sessions through the power of localstorage
class MatrixClientPeg {
    constructor(guestAccess) {
        this.matrixClient = null;
        this.guestAccess = guestAccess;
    }

    get(): MatrixClient {
        return this.matrixClient;
    }

    unset() {
        this.matrixClient = null;
    }

    replaceUsingUrls(hs_url, is_url) {
        this.replaceClient(hs_url, is_url);
    }

    replaceUsingAccessToken(hs_url, is_url, user_id, access_token, isGuest) {
        this.replaceClient(hs_url, is_url, user_id, access_token, isGuest);
    }

    replaceClient(hs_url, is_url, user_id, access_token, isGuest) {
        if (localStorage) {
            try {
                localStorage.clear();
            } catch (e) {
                console.warn("Error clearing local storage", e);
            }
        }
        this.guestAccess.markAsGuest(Boolean(isGuest));
        this._createClient(hs_url, is_url, user_id, access_token);
        if (localStorage) {
            try {
                localStorage.setItem("mx_hs_url", hs_url);
                localStorage.setItem("mx_is_url", is_url);
                localStorage.setItem("mx_user_id", user_id);
                localStorage.setItem("mx_access_token", access_token);
                console.log("Session persisted for %s", user_id);
            } catch (e) {
                console.warn("Error using local storage: can't persist session!", e);
            }
        } else {
            console.warn("No local storage available: can't persist session!");
        }
    }

    getCredentials() {
        return [
            this.matrixClient.baseUrl,
            this.matrixClient.idBaseUrl,
            this.matrixClient.credentials.userId,
            this.matrixClient.getAccessToken(),
            this.guestAccess.isGuest(),
        ];
    }

    tryRestore() {
        if (localStorage) {
            const hs_url = localStorage.getItem("mx_hs_url");
            const is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org';
            const access_token = localStorage.getItem("mx_access_token");
            const user_id = localStorage.getItem("mx_user_id");
            const guestAccess = new GuestAccess(localStorage);
            if (access_token && user_id && hs_url) {
                console.log("Restoring session for %s", user_id);
                this._createClient(hs_url, is_url, user_id, access_token);
            } else {
                console.log("Session not found.");
            }
        }
    }

    _createClient(hs_url, is_url, user_id, access_token) {
        var opts = {
            baseUrl: hs_url,
            idBaseUrl: is_url,
            accessToken: access_token,
            userId: user_id,
            timelineSupport: true,
        };

        if (localStorage) {
            opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage);
            opts.deviceId = deviceId();
        }

        this.matrixClient = Matrix.createClient(opts);

        // we're going to add eventlisteners for each matrix event tile, so the
        // potential number of event listeners is quite high.
        this.matrixClient.setMaxListeners(500);

        if (this.guestAccess) {
            console.log("Guest: %s", this.guestAccess.isGuest());
            this.matrixClient.setGuest(this.guestAccess.isGuest());
            var peekedRoomId = this.guestAccess.getPeekedRoom();
            if (peekedRoomId) {
                console.log("Peeking in room %s", peekedRoomId);
                this.matrixClient.peekInRoom(peekedRoomId);
            }
        }
    }
}

if (!global.mxMatrixClientPeg) {
    global.mxMatrixClientPeg = new MatrixClientPeg(new GuestAccess(localStorage));
    global.mxMatrixClientPeg.tryRestore();
}
module.exports = global.mxMatrixClientPeg;
<|endoftext|>


<commit_before>var keystone = require('keystone');

exports = module.exports = function (req, res) {

	var view = new keystone.View(req, res);
	var locals = res.locals;

	// Set locals
	locals.section = 'blog';
	locals.filters = {
		post: req.params.post,
	};
	locals.data = {
		posts: [],
	};

	// Load the current post
	view.on('init', function (next) {

		var q = keystone.list('Post').model.findOne({
			state: 'published',
			slug: locals.filters.post,
		}).populate('author categories');

		q.exec(function (err, result) {
			locals.data.post = result;
			next(err);
		});

	});

	// Load other posts
	view.on('init', function (next) {

		var q = keystone.list('Post').model.find().where('state', 'published').sort('-publishedDate').populate('author').limit('4');

		q.exec(function (err, results) {
			locals.data.posts = results;
			next(err);
		});

	});

	// Render the view
	view.render('post');
};
<commit_msg>fix - 'limit' field must be numeric<commit_after>var keystone = require('keystone');

exports = module.exports = function (req, res) {

	var view = new keystone.View(req, res);
	var locals = res.locals;

	// Set locals
	locals.section = 'blog';
	locals.filters = {
		post: req.params.post,
	};
	locals.data = {
		posts: [],
	};

	// Load the current post
	view.on('init', function (next) {

		var q = keystone.list('Post').model.findOne({
			state: 'published',
			slug: locals.filters.post,
		}).populate('author categories');

		q.exec(function (err, result) {
			locals.data.post = result;
			next(err);
		});

	});

	// Load other posts
	view.on('init', function (next) {

		var q = keystone.list('Post').model.find().where('state', 'published').sort('-publishedDate').populate('author').limit(4);

		q.exec(function (err, results) {
			locals.data.posts = results;
			next(err);
		});

	});

	// Render the view
	view.render('post');
};
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var gulpSequence = require('gulp-sequence').use(gulp);

gulp.task('test', gulpSequence('lint', 'test-node', 'test-browser'));
<commit_msg>run browser and node tests in parallel<commit_after>'use strict';

var gulp = require('gulp');
var gulpSequence = require('gulp-sequence').use(gulp);

gulp.task('test', gulpSequence('lint', ['test-node', 'test-browser']));
<|endoftext|>


<commit_before>
/*
 * Copyright (c) Burak Arslan (burak.arslan-qx@arskom.com.tr).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Arskom Consultancy Ltd. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

qx.Class.define("soap.Call", {extend: qx.core.Object
    ,properties: {
         _client : {check: "soap.Client"}
        ,_params : {check: "soap.Parameters"}
        ,_name : {check: "String"}
        ,_simple : { check: "Boolean", init:false}
    }

    ,construct: function(client, name, params) {

    }

    ,members: {
        easy: function() {
            var args = arguments;
            var client = this.get_client();

            args.unshift(this.get_name());
            client.easy.apply(client, args);
        }

        ,callAsync: function(callback,errback) {
            var client = this.get_client();

            client.callAsync(this.get_name(), this.get_params(),
                                          this.get_simple(), callback, errback);
        }
    }
});
<commit_msg>added ctor params<commit_after>
/*
 * Copyright (c) Burak Arslan (burak.arslan-qx@arskom.com.tr).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Arskom Consultancy Ltd. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

qx.Class.define("soap.Call", {extend: qx.core.Object
    ,properties: {
         _client : {check: "soap.Client"}
        ,_params : {check: "soap.Parameters"}
        ,_name : {check: "String"}
        ,_simple : { check: "Boolean", init:false}
    }

    ,construct: function(client, name, params) {
        this.set_client(client);
        this.set_name(name);
        this.set_params(params);
    }

    ,members: {
        easy: function() {
            var args = arguments;
            var client = this.get_client();

            args.unshift(this.get_name());
            client.easy.apply(client, args);
        }

        ,callAsync: function(callback,errback) {
            var client = this.get_client();

            client.callAsync(this.get_name(), this.get_params(),
                                          this.get_simple(), callback, errback);
        }
    }
});
<|endoftext|>


<commit_before>/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2014 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     New BSD License
 */

pimcore.registerNS("pimcore.asset.metadata");
pimcore.asset.metadata = Class.create({

    initialize: function(asset) {
        this.asset = asset;
    },

    getLayout: function () {

        if (this.grid == null) {

            if(this.asset.data.metadata.length < 1) {
                // default fields
                if(this.asset.data.type == "image") {
                    this.asset.data.metadata.push({
                        name: "title",
                        type: "input",
                        language: "",
                        value: ""
                    });
                    this.asset.data.metadata.push({
                        name: "alt",
                        type: "input",
                        language: "",
                        value: ""
                    });
                    this.asset.data.metadata.push({
                        name: "copyright",
                        type: "input",
                        language: "",
                        value: ""
                    });
                }
            }

            var customKey = new Ext.form.TextField({
                name: 'key',
                emptyText: t('key')
            });

            var customType = new Ext.form.ComboBox({
                fieldLabel: t('type'),
                name: "type",
                valueField: "id",
                displayField:'name',
                store: [
                    ["input", t("input")],
                    ["textarea", t("textarea")],
                    ["document", "Document"],
                    ["asset", "Asset"],
                    ["object", "Object"],
                    ["date", "Date"],
                    ["checkbox", "checkbox"]
                ],
                editable: false,
                triggerAction: 'all',
                mode: "local",
                width: 120,
                listWidth: 120,
                value: "input",
                emptyText: t('type')
            });

            var languagestore = [["",t("none")]];
            for (var i=0; i<pimcore.settings.websiteLanguages.length; i++) {
                languagestore.push([pimcore.settings.websiteLanguages[i],pimcore.settings.websiteLanguages[i]]);
            }

            var customLanguage = new Ext.form.ComboBox({
                fieldLabel: t('language'),
                name: "language",
                store: languagestore,
                editable: false,
                triggerAction: 'all',
                mode: "local",
                width: 100,
                listWidth: 100,
                emptyText: t('language')
            });

            var store = new Ext.data.JsonStore({
                fields: ['name', "type", {
                    name: "data",
                    convert: function (v, r) {
                        if (r.type == "date") {
                            var d = new Date(intval(v) * 1000);
                            return d;
                        }
                        return v;
                    }
                }, "language", "config"],
                data: this.asset.data.metadata
            });

            this.grid = new Ext.grid.EditorGridPanel({
                title: t("metadata"),
                autoScroll: true,
                region: "center",
                iconCls: "pimcore_icon_metadata",
                reference: this,
                trackMouseOver: true,
                store: store,
                tbar: [{
                    xtype: "tbtext",
                    text: t('add') + "   "
                },customKey, customType, customLanguage, {
                    xtype: "button",
                    handler: this.addSetFromUserDefined.bind(this, customKey, customType, customLanguage),
                    iconCls: "pimcore_icon_add"
                }
                ,{
                    xtype: "tbspacer",
                    width: 20
                },"-",{
                    xtype: "tbspacer",
                    width: 20
                },
                {
                    xtype: "button",
                    text: t('add_predefined_metadata_definitions'),
                    handler: this.addSetFromPredefinedDefined.bind(this),
                    iconCls: "pimcore_icon_add"
                }
                ],
                clicksToEdit: 1,
                autoExpandColumn: "value_col",
                columnLines: true,
                stripeRows: true,
                rowupdated: this.updateRows.bind(this, "rowupdated"),
                refresh: this.updateRows.bind(this, "refresh"),
                view: new Ext.grid.GridView({
                    listeners: {
                        rowupdated: this.updateRows.bind(this, "rowupdated"),
                        refresh: this.updateRows.bind(this, "refresh")
                    }
                }),
                columns: [
                    {
                        header: t("type"),
                        dataIndex: 'type',
                        editable: false,
                        width: 40,
                        renderer: this.getTypeRenderer.bind(this),
                        sortable: true
                    },
                    {
                        header: t("name"),
                        dataIndex: 'name',
                        editor: new Ext.form.TextField({
                            allowBlank: false
                        }),
                        sortable: true,
                        width: 230
                    },
                    {
                        header: t('language'),
                        sortable: true,
                        dataIndex: "language",
                        editor: new Ext.form.ComboBox({
                            name: "language",
                            store: languagestore,
                            editable: false,
                            triggerAction: 'all',
                            mode: "local"
                        }),
                        width: 80
                    },
                    {
                        id: "value_col",
                        header: t("value"),
                        dataIndex: 'data',
                        getCellEditor: this.getCellEditor.bind(this),
                        editable: true,
                        renderer: this.getCellRenderer.bind(this),
                        listeners: {
                            "mousedown": this.cellMousedown.bind(this)
                        }
                    },
                    {
                        xtype: 'actioncolumn',
                        width: 30,
                        items: [{
                            tooltip: t('open'),
                            icon: "/pimcore/static/img/icon/pencil_go.png",
                            handler: function (grid, rowIndex) {
                                var pData = grid.getStore().getAt(rowIndex).data;
                                if (pData.data) {
                                    pimcore.helpers.openElement(pData.data, pData.type);
                                }
                            }.bind(this),
                            getClass: function(v, meta, rec) {  // Or return a class from a function
                                if(rec.get('type') != "object" && rec.get('type') != "document"
                                    && rec.get('type') != "asset") {
                                    return "pimcore_hidden";
                                }
                            }
                        }]
                    },
                    {
                        xtype: 'actioncolumn',
                        width: 30,
                        items: [{
                            tooltip: t('delete'),
                            icon: "/pimcore/static/img/icon/cross.png",
                            handler: function (grid, rowIndex) {
                                grid.getStore().removeAt(rowIndex);
                            }.bind(this)
                        }]
                    }
                ]
            });

            this.grid.on("viewready", this.updateRows.bind(this));
            store.on("update", this.updateRows.bind(this));
        }

        return this.grid;
    },

    updateRows: function (event) {
        var rows = Ext.get(this.grid.getEl().dom).query(".x-grid3-row");

        for (var i = 0; i < rows.length; i++) {

            try {
                var propertyName = Ext.get(rows[i]).query(".x-grid3-cell-first div div")[0].getAttribute("name");
                var storeIndex = this.grid.getStore().findExact("name", propertyName);

                var data = this.grid.getStore().getAt(storeIndex).data;

                if(in_array(data.name, this.disallowedKeys)) {
                    Ext.get(rows[i]).addClass("pimcore_properties_hidden_row");
                }

                if (data.type == "document" || data.type == "asset" || data.type == "object") {

                    // add dnd support
                    var dd = new Ext.dd.DropZone(rows[i], {
                        ddGroup: "element",

                        getTargetFromEvent: function(e) {
                            return this.getEl();
                        },

                        onNodeOver : function(dataRow, target, dd, e, data) {
                            if(dataRow.type == data.node.attributes.elementType) {
                                return Ext.dd.DropZone.prototype.dropAllowed;
                            }
                            return Ext.dd.DropZone.prototype.dropNotAllowed;
                        }.bind(this, data),

                        onNodeDrop : function(myRowIndex, target, dd, e, data) {

                            var rec = this.grid.getStore().getAt(myRowIndex);

                            if(data.node.attributes.elementType != rec.get("type")) {
                                return false;
                            }

                            rec.set("data", data.node.attributes.path);

                            this.updateRows();

                            return true;
                        }.bind(this, storeIndex)
                    });

                }
            }
            catch (e) {
                console.log(e);
            }
        }
    },

    getTypeRenderer: function (value, metaData, record, rowIndex, colIndex, store) {

        if (value == "input") {
            value = "text";
        }
        return '

';
    },

    getCellRenderer: function (value, metaData, record, rowIndex, colIndex, store) {

        var data = store.getAt(rowIndex).data;
        var type = data.type;

        if (type == "textarea") {
            return nl2br(value);
        } else if (type == "document" || type == "asset" || type == "object") {
            if (value) {
                return '
' + value + '
';
            } else {
                return '

';
            }
        } else if (type == "date") {
            if (value) {
                return value.format("Y-m-d");
            }
        } else if (type == "checkbox") {
            metaData.css += ' x-grid3-check-col-td';
            return String.format('

', value ? '-on' : '');
        }

        return value;
    },

    addSetFromUserDefined: function (customKey, customType, customLanguage) {
        this.add(customKey.getValue(), customType.getValue(), false, customLanguage.getValue());
    },

    add: function (key, type, value, language) {

        var store = this.grid.getStore();

        // check for empty key & type
        if (key.length < 2 || type.length < 1) {
            Ext.MessageBox.alert(t("error"), t("name_and_key_must_be_defined"));
            return;
        }

        if (!value) {
            if (type == "input" || type == "textarea") {
                value = "";
            }
            value = "";
        }

        if(!language) {
            language = "";
        }

        // check for duplicate name
        var dublicateIndex = store.findBy(function (record, id) {
            if (record.data.name.toLowerCase() == key.toLowerCase()) {
                if(record.data.language.toLowerCase() == language.toLowerCase()) {
                    return true;
                }
            }
            return false;
        });

        if (dublicateIndex >= 0) {
            Ext.MessageBox.alert(t("error"), t("name_already_in_use"));
            return;
        }

        var newRecord = new store.recordType({
            name: key,
            data: value,
            type: type,
            language: language
        });

        store.add(newRecord);
        this.grid.getView().refresh();
    },

    cellMousedown: function (col, grid, rowIndex, event) {

        // this is used for the boolean field type

        var store = grid.getStore();
        var record = store.getAt(rowIndex);
        var data = record.data;
        var type = data.type;

        if (type == "checkbox") {
            record.set("data", !record.data.data);
        }
    },

    getCellEditor: function (rowIndex) {

        var store = this.grid.getStore();
        var data = store.getAt(rowIndex).data;

        var type = data.type;
        var property;

        if (type == "input") {
            property = new Ext.form.TextField();
        } else if (type == "textarea") {
            property = new Ext.form.TextArea();
        } else if (type == "document" || type == "asset" || type == "object") {

            property = new Ext.form.TextField({
                disabled: true,
                propertyGrid: this.grid,
                myRowIndex: rowIndex,
                style: {
                    visibility: "hidden"
                }
            });
        } else if (type == "date") {
            property = new Ext.form.DateField();
        } else if (type == "checkbox") {
            property = new Ext.form.Checkbox();
            return false;
        } else if (type == "select") {
            var config = data.config;
            property = new Ext.form.ComboBox({
                triggerAction: 'all',
                editable: false,
                store: config.split(",")
            });
        }

        return new Ext.grid.GridEditor(property);
    },

    getValues : function () {

        if (!this.grid.rendered) {
            throw "metadata not available";
        }

        var values = [];
        var store = this.grid.getStore();
        store.commitChanges();

        var records = store.getRange();

        for (var i = 0; i < records.length; i++) {
            var currentData = records[i];
            if (currentData) {
                var data = currentData.data.data;
                if (currentData.data.type == "date") {
                    data = data.valueOf() / 1000;
                };
                values.push({
                    data: data,
                    type: currentData.data.type,
                    name: currentData.data.name,
                    language: currentData.data.language
                });
            }
        }

        return values;
    },

    addSetFromPredefinedDefined: function() {

        Ext.Ajax.request({
            url: "/admin/settings/get-predefined-metadata",
            params: {
                type: "asset",
                subType: this.asset.type
            },
            success: this.doAddSet.bind(this)

        });

    },

    doAddSet: function(response) {
        var data = Ext.decode(response.responseText);
        data = data.data;
        var store = this.grid.getStore();
        var added = false;

        var i;
        for (i = 0; i < data.length; i++) {
            var item = data[i];
            var key = item.name;
            var language = item.language;
            if (!key) {
                key = "";
            }
            if (!language) {
                language = "";
            }

            if (!item.type){
                continue;
            }

            var dublicateIndex = store.findBy(function (record, id) {
                if (record.data.name.toLowerCase() == key.toLowerCase()) {
                    if(record.data.language.toLowerCase() == language.toLowerCase()) {
                        return true;
                    }
                }
                return false;
            });

            if (dublicateIndex < 0) {

                var value = item.data;
                if (item.type == "date" && value) {
                    value = new Date(intval(value) * 1000);
                }
                var newRecord = new store.recordType({
                    name: key,
                    data: value,
                    type: item.type,
                    config: item.config,
                    language: language
                });

                store.add(newRecord);
                added = true;
            }

        }

        if (added) {
            this.grid.getView().refresh();
        }

    }
});<commit_msg>PIMCORE-2551 - Asset Metadata - Add types checkbox and select<commit_after>/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2014 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     New BSD License
 */

pimcore.registerNS("pimcore.asset.metadata");
pimcore.asset.metadata = Class.create({

    initialize: function(asset) {
        this.asset = asset;
    },

    getLayout: function () {

        if (this.grid == null) {

            if(this.asset.data.metadata.length < 1) {
                // default fields
                if(this.asset.data.type == "image") {
                    this.asset.data.metadata.push({
                        name: "title",
                        type: "input",
                        language: "",
                        value: ""
                    });
                    this.asset.data.metadata.push({
                        name: "alt",
                        type: "input",
                        language: "",
                        value: ""
                    });
                    this.asset.data.metadata.push({
                        name: "copyright",
                        type: "input",
                        language: "",
                        value: ""
                    });
                }
            }

            var customKey = new Ext.form.TextField({
                name: 'key',
                emptyText: t('key')
            });

            var customType = new Ext.form.ComboBox({
                fieldLabel: t('type'),
                name: "type",
                valueField: "id",
                displayField:'name',
                store: [
                    ["input", t("input")],
                    ["textarea", t("textarea")],
                    ["document", "Document"],
                    ["asset", "Asset"],
                    ["object", "Object"],
                    ["date", "Date"],
                    ["checkbox", "checkbox"]
                ],
                editable: false,
                triggerAction: 'all',
                mode: "local",
                width: 120,
                listWidth: 120,
                value: "input",
                emptyText: t('type')
            });

            var languagestore = [["",t("none")]];
            for (var i=0; i<pimcore.settings.websiteLanguages.length; i++) {
                languagestore.push([pimcore.settings.websiteLanguages[i],pimcore.settings.websiteLanguages[i]]);
            }

            var customLanguage = new Ext.form.ComboBox({
                fieldLabel: t('language'),
                name: "language",
                store: languagestore,
                editable: false,
                triggerAction: 'all',
                mode: "local",
                width: 100,
                listWidth: 100,
                emptyText: t('language')
            });

            var store = new Ext.data.JsonStore({
                fields: ['name', "type", {
                    name: "data",
                    convert: function (v, r) {
                        if (r.type == "date") {
                            var d = new Date(intval(v) * 1000);
                            return d;
                        }
                        return v;
                    }
                }, "language", "config"],
                data: this.asset.data.metadata
            });

            this.grid = new Ext.grid.EditorGridPanel({
                title: t("metadata"),
                autoScroll: true,
                region: "center",
                iconCls: "pimcore_icon_metadata",
                reference: this,
                trackMouseOver: true,
                store: store,
                tbar: [{
                    xtype: "tbtext",
                    text: t('add') + "   "
                },customKey, customType, customLanguage, {
                    xtype: "button",
                    handler: this.addSetFromUserDefined.bind(this, customKey, customType, customLanguage),
                    iconCls: "pimcore_icon_add"
                }
                ,{
                    xtype: "tbspacer",
                    width: 20
                },"-",{
                    xtype: "tbspacer",
                    width: 20
                },
                {
                    xtype: "button",
                    text: t('add_predefined_metadata_definitions'),
                    handler: this.addSetFromPredefinedDefined.bind(this),
                    iconCls: "pimcore_icon_add"
                }
                ],
                clicksToEdit: 1,
                autoExpandColumn: "value_col",
                columnLines: true,
                stripeRows: true,
                rowupdated: this.updateRows.bind(this, "rowupdated"),
                refresh: this.updateRows.bind(this, "refresh"),
                view: new Ext.grid.GridView({
                    listeners: {
                        rowupdated: this.updateRows.bind(this, "rowupdated"),
                        refresh: this.updateRows.bind(this, "refresh")
                    }
                }),
                columns: [
                    {
                        header: t("type"),
                        dataIndex: 'type',
                        editable: false,
                        width: 40,
                        renderer: this.getTypeRenderer.bind(this),
                        sortable: true
                    },
                    {
                        header: t("name"),
                        dataIndex: 'name',
                        editor: new Ext.form.TextField({
                            allowBlank: false
                        }),
                        sortable: true,
                        width: 230
                    },
                    {
                        header: t('language'),
                        sortable: true,
                        dataIndex: "language",
                        editor: new Ext.form.ComboBox({
                            name: "language",
                            store: languagestore,
                            editable: false,
                            triggerAction: 'all',
                            mode: "local"
                        }),
                        width: 80
                    },
                    {
                        id: "value_col",
                        header: t("value"),
                        dataIndex: 'data',
                        getCellEditor: this.getCellEditor.bind(this),
                        editable: true,
                        renderer: this.getCellRenderer.bind(this),
                        listeners: {
                            "mousedown": this.cellMousedown.bind(this)
                        }
                    },
                    {
                        xtype: 'actioncolumn',
                        width: 30,
                        items: [{
                            tooltip: t('open'),
                            icon: "/pimcore/static/img/icon/pencil_go.png",
                            handler: function (grid, rowIndex) {
                                var pData = grid.getStore().getAt(rowIndex).data;
                                if (pData.data) {
                                    pimcore.helpers.openElement(pData.data, pData.type);
                                }
                            }.bind(this),
                            getClass: function(v, meta, rec) {  // Or return a class from a function
                                if(rec.get('type') != "object" && rec.get('type') != "document"
                                    && rec.get('type') != "asset") {
                                    return "pimcore_hidden";
                                }
                            }
                        }]
                    },
                    {
                        xtype: 'actioncolumn',
                        width: 30,
                        items: [{
                            tooltip: t('delete'),
                            icon: "/pimcore/static/img/icon/cross.png",
                            handler: function (grid, rowIndex) {
                                grid.getStore().removeAt(rowIndex);
                            }.bind(this)
                        }]
                    }
                ]
            });

            this.grid.on("viewready", this.updateRows.bind(this));
            store.on("update", this.updateRows.bind(this));
        }

        return this.grid;
    },

    updateRows: function (event) {
        var rows = Ext.get(this.grid.getEl().dom).query(".x-grid3-row");

        for (var i = 0; i < rows.length; i++) {

            try {
                var propertyName = Ext.get(rows[i]).query(".x-grid3-cell-first div div")[0].getAttribute("name");
                var storeIndex = this.grid.getStore().findExact("name", propertyName);

                var data = this.grid.getStore().getAt(storeIndex).data;

                if(in_array(data.name, this.disallowedKeys)) {
                    Ext.get(rows[i]).addClass("pimcore_properties_hidden_row");
                }

                if (data.type == "document" || data.type == "asset" || data.type == "object") {

                    // add dnd support
                    var dd = new Ext.dd.DropZone(rows[i], {
                        ddGroup: "element",

                        getTargetFromEvent: function(e) {
                            return this.getEl();
                        },

                        onNodeOver : function(dataRow, target, dd, e, data) {
                            if(dataRow.type == data.node.attributes.elementType) {
                                return Ext.dd.DropZone.prototype.dropAllowed;
                            }
                            return Ext.dd.DropZone.prototype.dropNotAllowed;
                        }.bind(this, data),

                        onNodeDrop : function(myRowIndex, target, dd, e, data) {

                            var rec = this.grid.getStore().getAt(myRowIndex);

                            if(data.node.attributes.elementType != rec.get("type")) {
                                return false;
                            }

                            rec.set("data", data.node.attributes.path);

                            this.updateRows();

                            return true;
                        }.bind(this, storeIndex)
                    });

                }
            }
            catch (e) {
                console.log(e);
            }
        }
    },

    getTypeRenderer: function (value, metaData, record, rowIndex, colIndex, store) {

        if (value == "input") {
            value = "text";
        }
        return '

';
    },

    getCellRenderer: function (value, metaData, record, rowIndex, colIndex, store) {

        var data = store.getAt(rowIndex).data;
        var type = data.type;

        if (type == "textarea") {
            return nl2br(value);
        } else if (type == "document" || type == "asset" || type == "object") {
            if (value) {
                return '
' + value + '
';
            } else {
                return '

';
            }
        } else if (type == "date") {
            if (value) {
                return value.format("Y-m-d");
            }
        } else if (type == "checkbox") {
            metaData.css += ' x-grid3-check-col-td';
            return String.format('

', value ? '-on' : '');
        }

        return value;
    },

    addSetFromUserDefined: function (customKey, customType, customLanguage) {
        this.add(customKey.getValue(), customType.getValue(), false, customLanguage.getValue());
    },

    add: function (key, type, value, language) {

        var store = this.grid.getStore();

        // check for empty key & type
        if (key.length < 2 || type.length < 1) {
            Ext.MessageBox.alert(t("error"), t("name_and_key_must_be_defined"));
            return;
        }

        if (!value) {
            if (type == "input" || type == "textarea") {
                value = "";
            }
            value = "";
        }

        if(!language) {
            language = "";
        }

        // check for duplicate name
        var dublicateIndex = store.findBy(function (record, id) {
            if (record.data.name.toLowerCase() == key.toLowerCase()) {
                if(record.data.language.toLowerCase() == language.toLowerCase()) {
                    return true;
                }
            }
            return false;
        });

        if (dublicateIndex >= 0) {
            Ext.MessageBox.alert(t("error"), t("name_already_in_use"));
            return;
        }

        var newRecord = new store.recordType({
            name: key,
            data: value,
            type: type,
            language: language
        });

        store.add(newRecord);
        this.grid.getView().refresh();
    },

    cellMousedown: function (col, grid, rowIndex, event) {

        // this is used for the boolean field type

        var store = grid.getStore();
        var record = store.getAt(rowIndex);
        var data = record.data;
        var type = data.type;

        if (type == "checkbox") {
            record.set("data", !record.data.data);
        }
    },

    getCellEditor: function (rowIndex) {

        var store = this.grid.getStore();
        var data = store.getAt(rowIndex).data;

        var type = data.type;
        var property;

        if (type == "input") {
            property = new Ext.form.TextField();
        } else if (type == "textarea") {
            property = new Ext.form.TextArea();
        } else if (type == "document" || type == "asset" || type == "object") {

            property = new Ext.form.TextField({
                disabled: true,
                propertyGrid: this.grid,
                myRowIndex: rowIndex,
                style: {
                    visibility: "hidden"
                }
            });
        } else if (type == "date") {
            property = new Ext.form.DateField();
        } else if (type == "checkbox") {
            property = new Ext.form.Checkbox();
            return false;
        } else if (type == "select") {
            var config = data.config;
            property = new Ext.form.ComboBox({
                triggerAction: 'all',
                editable: false,
                store: config.split(",")
            });
        }

        return new Ext.grid.GridEditor(property);
    },

    getValues : function () {

        if (!this.grid.rendered) {
            throw "metadata not available";
        }

        var values = [];
        var store = this.grid.getStore();
        store.commitChanges();

        var records = store.getRange();

        for (var i = 0; i < records.length; i++) {
            var currentData = records[i];
            if (currentData) {
                var data = currentData.data.data;
                if (data && currentData.data.type == "date") {
                    data = data.valueOf() / 1000;
                }
                values.push({
                    data: data,
                    type: currentData.data.type,
                    name: currentData.data.name,
                    language: currentData.data.language
                });
            }
        }

        return values;
    },

    addSetFromPredefinedDefined: function() {

        Ext.Ajax.request({
            url: "/admin/settings/get-predefined-metadata",
            params: {
                type: "asset",
                subType: this.asset.type
            },
            success: this.doAddSet.bind(this)

        });

    },

    doAddSet: function(response) {
        var data = Ext.decode(response.responseText);
        data = data.data;
        var store = this.grid.getStore();
        var added = false;

        var i;
        for (i = 0; i < data.length; i++) {
            var item = data[i];
            var key = item.name;
            var language = item.language;
            if (!key) {
                key = "";
            }
            if (!language) {
                language = "";
            }

            if (!item.type){
                continue;
            }

            var dublicateIndex = store.findBy(function (record, id) {
                if (record.data.name.toLowerCase() == key.toLowerCase()) {
                    if(record.data.language.toLowerCase() == language.toLowerCase()) {
                        return true;
                    }
                }
                return false;
            });

            if (dublicateIndex < 0) {

                var value = item.data;
                if (item.type == "date" && value) {
                    value = new Date(intval(value) * 1000);
                }
                var newRecord = new store.recordType({
                    name: key,
                    data: value,
                    type: item.type,
                    config: item.config,
                    language: language
                });

                store.add(newRecord);
                added = true;
            }

        }

        if (added) {
            this.grid.getView().refresh();
        }

    }
});<|endoftext|>


<commit_before>/*
Copyright 2016 Mozilla

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/

import Immutable from 'immutable';

import { logger } from '../../../shared/logging';
import Page from '../model/page';
import Pages from '../model/pages';
import PageState from '../model/page-state';
import SSLCertificateModel from '../model/ssl-certificate';
import PageLocalHistoryItem from '../model/page-local-history-item';
import * as UIConstants from '../constants/ui';
import * as ActionTypes from '../constants/action-types';

export default function(state = new Pages(), action) {
  switch (action.type) {
    case ActionTypes.CREATE_PAGE:
      return createPage(state, action.id, action.location, action.options);

    case ActionTypes.REMOVE_PAGE:
      return removePage(state, action.pageId);

    case ActionTypes.SET_SELECTED_PAGE:
      return setSelectedPage(state, action.pageId);

    case ActionTypes.RESET_PAGE_DATA:
      return resetPageData(state, action.pageId);

    case ActionTypes.SET_PAGE_INDEX:
      return setPageIndex(state, action.pageId, action.pageIndex);

    case ActionTypes.SET_PAGE_DETAILS:
      return setPageDetails(state, action.pageId, action.pageDetails);

    case ActionTypes.SET_PAGE_META:
      return setPageMeta(state, action.pageId, action.pageMeta);

    case ActionTypes.SET_PAGE_STATE:
      return setPageState(state, action.pageId, action.pageState);

    case ActionTypes.SET_PAGE_UI_STATE:
      return setPageUIState(state, action.pageId, action.pageUIState);

    case ActionTypes.SET_LOCAL_PAGE_HISTORY:
      return setLocalPageHistory(state, action.pageId, action.history, action.historyIndex);

    default:
      return state;
  }
}

function createPage(state, id, location = UIConstants.HOME_PAGE, options = {
  selected: true,
  index: null,
}) {
  return state.withMutations(mut => {
    const page = new Page({ id, location });
    const pageIndex = options.index != null ? options.index : state.displayOrder.size;

    mut.update('displayOrder', l => l.insert(pageIndex, page.id));
    mut.update('ids', s => s.add(page.id));
    mut.update('map', m => m.set(page.id, page));

    if (options.selected) {
      mut.set('selectedId', page.id);
    }
  });
}

function removePage(state, pageId) {
  return state.withMutations(mut => {
    const pageCount = state.displayOrder.size;
    const pageIndex = state.displayOrder.findIndex(id => id === pageId);

    // Remove page first.
    mut.update('displayOrder', l => l.delete(pageIndex));
    mut.update('ids', s => s.delete(pageId));
    mut.update('map', m => m.delete(pageId));

    // If the last page was removed, there's no other page remaining to select.
    // However, we won't allow states where there aren't any pages available,
    // the action creator will dispatch an action to add another page.
    if (pageCount === 1) {
      mut.set('selectedId', '');
      return;
    }

    // If we had at least two pages before removing, select the previous one
    // this isn't the first page, otherwise the next one.
    if (pageIndex === 0) {
      mut.set('selectedId', state.displayOrder.get(1));
    } else {
      mut.set('selectedId', state.displayOrder.get(pageIndex - 1));
    }
  });
}

function setSelectedPage(state, pageId) {
  return state.set('selectedId', pageId);
}

function resetPageData(state, pageId) {
  return state.withMutations(mut => {
    const fresh = new Page({ id: pageId }).entries();
    for (const [key, value] of fresh) {
      // Don't reset the `uiState`, `history` and `historyIndex` properties
      // on the page.
      if (key !== 'uiState' && key !== 'history' && key !== 'historyIndex') {
        mut.update('map', m => m.setIn([pageId, key], value));
      }
    }
  });
}

function setPageIndex(state, pageId, pageIndex) {
  return state.withMutations(mut => {
    const oldIndex = state.displayOrder.findIndex(id => id === pageId);
    mut.update('displayOrder', l => l.delete(oldIndex));
    mut.update('displayOrder', l => l.insert(pageIndex, pageId));
  });
}

function setPageDetails(state, pageId, pageDetails) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageDetails)) {
      if (key === 'id') {
        logger.warn('Skipping setting of `id` on page.');
        continue;
      }
      if (typeof value === 'object' && !Immutable.Iterable.isIterable(value)) {
        logger.warn(`Setting a non-immutable object \`${key}\` on page.`);
      }
      mut.update('map', m => m.setIn([pageId, key], value));
    }
  });
}

function setPageMeta(state, pageId, pageMeta) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageMeta)) {
      mut.update('map', m => m.setIn([pageId, 'meta', key], value));
    }
  });
}

function setPageState(state, pageId, pageState) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageState)) {
      const prevValue = state.getIn(['map', pageId, 'state', key]);
      let nextValue = value;

      // Don't update the page load state to "LOADED" if it's not "LOADING".
      // We're dong this to avoid overwriting failed load states.
      if (key === 'load' &&
          value === PageState.STATES.LOADED &&
          prevValue !== PageState.STATES.LOADING) {
        logger.warn('Skipping setting a `LOADED` page state.');
        continue;
      }

      if (key === 'certificate') {
        nextValue = new SSLCertificateModel(value);
      }

      mut.update('map', m => m.setIn([pageId, 'state', key], nextValue));
    }
  });
}

function setPageUIState(state, pageId, pageUIState) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageUIState)) {
      mut.update('map', m => m.setIn([pageId, 'uiState', key], value));
    }
  });
}

function setLocalPageHistory(state, pageId, history, historyIndex) {
  return state.withMutations(mut => {
    const records = history.map((location, index) => new PageLocalHistoryItem({
      url: location,
      active: index === historyIndex,
    }));
    mut.setIn(['map', pageId, 'history'], Immutable.List(records));
    mut.setIn(['map', pageId, 'historyIndex'], historyIndex);
  });
}
<commit_msg>When closing a tab, select the next available tab. Fixes #1185. r=vporof (#1279)<commit_after>/*
Copyright 2016 Mozilla

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/

import Immutable from 'immutable';

import { logger } from '../../../shared/logging';
import Page from '../model/page';
import Pages from '../model/pages';
import PageState from '../model/page-state';
import SSLCertificateModel from '../model/ssl-certificate';
import PageLocalHistoryItem from '../model/page-local-history-item';
import * as UIConstants from '../constants/ui';
import * as ActionTypes from '../constants/action-types';

export default function(state = new Pages(), action) {
  switch (action.type) {
    case ActionTypes.CREATE_PAGE:
      return createPage(state, action.id, action.location, action.options);

    case ActionTypes.REMOVE_PAGE:
      return removePage(state, action.pageId);

    case ActionTypes.SET_SELECTED_PAGE:
      return setSelectedPage(state, action.pageId);

    case ActionTypes.RESET_PAGE_DATA:
      return resetPageData(state, action.pageId);

    case ActionTypes.SET_PAGE_INDEX:
      return setPageIndex(state, action.pageId, action.pageIndex);

    case ActionTypes.SET_PAGE_DETAILS:
      return setPageDetails(state, action.pageId, action.pageDetails);

    case ActionTypes.SET_PAGE_META:
      return setPageMeta(state, action.pageId, action.pageMeta);

    case ActionTypes.SET_PAGE_STATE:
      return setPageState(state, action.pageId, action.pageState);

    case ActionTypes.SET_PAGE_UI_STATE:
      return setPageUIState(state, action.pageId, action.pageUIState);

    case ActionTypes.SET_LOCAL_PAGE_HISTORY:
      return setLocalPageHistory(state, action.pageId, action.history, action.historyIndex);

    default:
      return state;
  }
}

function createPage(state, id, location = UIConstants.HOME_PAGE, options = {
  selected: true,
  index: null,
}) {
  return state.withMutations(mut => {
    const page = new Page({ id, location });
    const pageIndex = options.index != null ? options.index : state.displayOrder.size;

    mut.update('displayOrder', l => l.insert(pageIndex, page.id));
    mut.update('ids', s => s.add(page.id));
    mut.update('map', m => m.set(page.id, page));

    if (options.selected) {
      mut.set('selectedId', page.id);
    }
  });
}

function removePage(state, pageId) {
  return state.withMutations(mut => {
    const pageCount = state.displayOrder.size;
    const pageIndex = state.displayOrder.findIndex(id => id === pageId);
    const selectedId = state.get('selectedId');

    // Remove page first.
    mut.update('displayOrder', l => l.delete(pageIndex));
    mut.update('ids', s => s.delete(pageId));
    mut.update('map', m => m.delete(pageId));

    // If the last page was removed, there's no other page remaining to select.
    // However, we won't allow states where there aren't any pages available,
    // the action creator will dispatch an action to add another page.
    if (pageCount === 1) {
      mut.set('selectedId', '');
      return;
    }

    // If we had at least two pages before removing, select the next one
    // if we are removing the currently selected page. If there isn't a next tab, select
    // the previous.
    let newSelectedId;
    if (pageId === selectedId) {
      if (pageIndex === pageCount - 1) {
        newSelectedId = state.displayOrder.get(pageIndex - 1);
      } else {
        newSelectedId = state.displayOrder.get(pageIndex + 1);
      }
      mut.set('selectedId', newSelectedId);
    }
  });
}

function setSelectedPage(state, pageId) {
  return state.set('selectedId', pageId);
}

function resetPageData(state, pageId) {
  return state.withMutations(mut => {
    const fresh = new Page({ id: pageId }).entries();
    for (const [key, value] of fresh) {
      // Don't reset the `uiState`, `history` and `historyIndex` properties
      // on the page.
      if (key !== 'uiState' && key !== 'history' && key !== 'historyIndex') {
        mut.update('map', m => m.setIn([pageId, key], value));
      }
    }
  });
}

function setPageIndex(state, pageId, pageIndex) {
  return state.withMutations(mut => {
    const oldIndex = state.displayOrder.findIndex(id => id === pageId);
    mut.update('displayOrder', l => l.delete(oldIndex));
    mut.update('displayOrder', l => l.insert(pageIndex, pageId));
  });
}

function setPageDetails(state, pageId, pageDetails) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageDetails)) {
      if (key === 'id') {
        logger.warn('Skipping setting of `id` on page.');
        continue;
      }
      if (typeof value === 'object' && !Immutable.Iterable.isIterable(value)) {
        logger.warn(`Setting a non-immutable object \`${key}\` on page.`);
      }
      mut.update('map', m => m.setIn([pageId, key], value));
    }
  });
}

function setPageMeta(state, pageId, pageMeta) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageMeta)) {
      mut.update('map', m => m.setIn([pageId, 'meta', key], value));
    }
  });
}

function setPageState(state, pageId, pageState) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageState)) {
      const prevValue = state.getIn(['map', pageId, 'state', key]);
      let nextValue = value;

      // Don't update the page load state to "LOADED" if it's not "LOADING".
      // We're dong this to avoid overwriting failed load states.
      if (key === 'load' &&
          value === PageState.STATES.LOADED &&
          prevValue !== PageState.STATES.LOADING) {
        logger.warn('Skipping setting a `LOADED` page state.');
        continue;
      }

      if (key === 'certificate') {
        nextValue = new SSLCertificateModel(value);
      }

      mut.update('map', m => m.setIn([pageId, 'state', key], nextValue));
    }
  });
}

function setPageUIState(state, pageId, pageUIState) {
  return state.withMutations(mut => {
    for (const [key, value] of Object.entries(pageUIState)) {
      mut.update('map', m => m.setIn([pageId, 'uiState', key], value));
    }
  });
}

function setLocalPageHistory(state, pageId, history, historyIndex) {
  return state.withMutations(mut => {
    const records = history.map((location, index) => new PageLocalHistoryItem({
      url: location,
      active: index === historyIndex,
    }));
    mut.setIn(['map', pageId, 'history'], Immutable.List(records));
    mut.setIn(['map', pageId, 'historyIndex'], historyIndex);
  });
}
<|endoftext|>