<commit_before>import html from "@web/rollup-plugin-html";
import copy from "rollup-plugin-copy";
import resolve from "@rollup/plugin-node-resolve";
import minifyHTML from "rollup-plugin-minify-html-literals";
import fs from "fs";
import path from "path";
import del from "rollup-plugin-delete";
import {babel} from "@rollup/plugin-babel";
import {terser} from "rollup-plugin-terser";
import {execSync} from "child_process";
import pkg from "./package.json";

const env = process.env || {};
const buildPath = path.join(__dirname, "build");
const sitesPath = path.join(__dirname, "src/sites");
const patternExt = /\.[0-9a-z]+$/i;
const patternConfig = /(config|settings|constants|tools)/gi;
const internalCss = /(global|magic-check|style|toggle-switch)/gi;

// Get target sites to build
// const sites = env.npm_config_sites ? env.npm_config_sites.split(",") : ["iva"];
const sites = ["iva", "api"];

const revision = () => {
    try {
        const jsorollaBranch = execSync("git rev-parse --abbrev-ref HEAD").toString();
        const jsorollaSha1 = execSync("git rev-parse HEAD").toString();
        return `
        Jsorolla Version: ${pkg.version} | Git: ${jsorollaBranch.trim()} - ${jsorollaSha1.trim()}
        Build generated on: ${new Date()}\n    `;
    } catch (error) {
        console.error(`
            Status: ${error.status}
            ${error.stderr.toString()}
        `);
    }
};

const isConfig = name => {
    return name.match(patternConfig) !== null;
};

const isInternalCss = name => {
    return name.match(internalCss) !== null;
};

const getCustomSitePath = (name, from, folder) => {
    if (env.npm_config_custom_site) {
        return `${from}custom-sites/${env.npm_config_custom_site}/${name}/${folder}`;
    }
    return folder; // Default path configuration
};

const transformHtmlContent = html => {
    const annihilator = /<!-- build:delete -->[\s\S]*?<!-- \/build -->/mg;
    let newHtml = html.replace("[build-signature]", revision()).replace(annihilator, "");
    sites.forEach(name => {
        const regex = new RegExp(`{{ ${name.toUpperCase()}_CONFIG_PATH }}`, "g");
        newHtml = newHtml.replace(regex, getCustomSitePath(name, "../../../", "conf")).replace(annihilator, "");
    });
    return newHtml;
};

const getSiteContent = name => {
    const content = fs.readFileSync(path.join(sitesPath, name, "index.html"), "utf8");
    return {
        name: "index.html",
        html: transformHtmlContent(content),
    };
};

const getCopyTargets = site => {
    const targets = [
        {src: `./src/sites/${site}/img`, dest: `${buildPath}/${site}/`},
        {src: "./styles/img", dest: `${buildPath}/${site}/`},
        // {src: `${ivaPath}/LICENSE`, dest: `${buildPath}`},
        // {src: `${ivaPath}/README.md`, dest: `${buildPath}`},
        {src: "./styles/fonts", dest: `${buildPath}/${site}/`},
        // {src: "./node_modules/bootstrap/dist/fonts/*.woff2", dest: `${buildPath}/${site}/vendors/fonts`},
        {src: "./node_modules/@fortawesome/fontawesome-free/webfonts/*.woff2", dest: `${buildPath}/${site}/vendors/webfonts`},
    ];
    if (env.npm_config_custom_site) {
        targets.push({
            src: getCustomSitePath(site, "", "img"),
            dest: `${buildPath}/${site}/`
        });
    }
    return targets;
};

export default sites.map(site => ({
    plugins: [
        del({
            targets: `build/${site}`,
        }),
        html({
            rootDir: `${sitesPath}/${site}/`,
            input: getSiteContent(site),
        }),
        resolve(),
        minifyHTML(),
        babel({
            exclude: "node_modules/**",
            babelHelpers: "runtime",
            presets: ["@babel/preset-env"],
            plugins: [
                "@babel/plugin-proposal-export-default-from",
                "@babel/plugin-proposal-nullish-coalescing-operator",
                "@babel/transform-runtime",
                ["@babel/plugin-proposal-class-properties", {"loose": false}]
            ]
        }),
        terser({
            ecma: 2020,
            module: true,
            warnings: true
        }),
        copy({
            targets: getCopyTargets(site),
        }),
    ],
    moduleContext: id => {
        // Avoid this Error: https://rollupjs.org/guide/en/#error-this-is-undefined
        /*
        * In order to match native module behaviour, Rollup sets `this`
        * as `undefined` at the top level of modules. Rollup also outputs
        * a warning if a module tries to access `this` at the top level.
        * The following modules use `this` at the top level and expect it
        * to be the global `window` object, so we tell Rollup to set
        *`this = window` for these modules.
        */
        const thisAsWindowForModules = [
            "node_modules/countup.js/dist/countUp.min.js"
        ];

        if (thisAsWindowForModules.some(id_ => id.trimRight().endsWith(id_))) {
            return "window";
        }
    },
    output: {
        dir: `${buildPath}/${site}`,
        manualChunks: id => { // It's only detect "import" from script type=module.. the others no.
            if (id.includes("node_modules")) {
                return "vendors/js/vendors";
            }
            if (id.includes("src/webcomponents")) {
                return "lib/webcomponents.min";
            }
            if (id.includes("src/core")) {
                return "lib/core.min";
            }
        },
        chunkFileNames: () => {
            return "[name]-[hash].js"; // configuration of manualChunks about name format and folder.
        },
        entryFileNames: () => {
            return "lib/[name].js"; // configuration for entry script module and inline script
        },
        assetFileNames: assetInfo => {
            // if (assetInfo.name.includes("genome-browser.config")) {
            //     return "genome-maps/conf/[name][extname]";
            // }

            if (isConfig(assetInfo.name)) {
                return "conf/[name][extname]";
            }

            if (isInternalCss(assetInfo.name)) {
                return "css/[name]-[hash][extname]";
            }

            if (assetInfo.name.endsWith(".js") && !isConfig(assetInfo.name)) {
                return "vendors/js/[name]-[hash][extname]";
            }

            if (assetInfo.name.endsWith(".css")) {
                return "vendors/css/[name]-[hash][extname]";
            }

            return "vendors/[name]-[hash][extname]";
        },
    },
}));
<commit_msg>Replace version from env variable in build #TASK-576<commit_after>import html from "@web/rollup-plugin-html";
import copy from "rollup-plugin-copy";
import resolve from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";
import minifyHTML from "rollup-plugin-minify-html-literals";
import fs from "fs";
import path from "path";
import del from "rollup-plugin-delete";
import {babel} from "@rollup/plugin-babel";
import {terser} from "rollup-plugin-terser";
import {execSync} from "child_process";
import pkg from "./package.json";

const env = process.env || {};
const buildPath = path.join(__dirname, "build");
const sitesPath = path.join(__dirname, "src/sites");
const patternExt = /\.[0-9a-z]+$/i;
const patternConfig = /(config|settings|constants|tools)/gi;
const internalCss = /(global|magic-check|style|toggle-switch)/gi;

// Get target sites to build
// const sites = env.npm_config_sites ? env.npm_config_sites.split(",") : ["iva"];
const sites = ["iva", "api"];

const revision = () => {
    try {
        const jsorollaBranch = execSync("git rev-parse --abbrev-ref HEAD").toString();
        const jsorollaSha1 = execSync("git rev-parse HEAD").toString();
        return `
        Jsorolla Version: ${pkg.version} | Git: ${jsorollaBranch.trim()} - ${jsorollaSha1.trim()}
        Build generated on: ${new Date()}\n    `;
    } catch (error) {
        console.error(`
            Status: ${error.status}
            ${error.stderr.toString()}
        `);
    }
};

const isConfig = name => {
    return name.match(patternConfig) !== null;
};

const isInternalCss = name => {
    return name.match(internalCss) !== null;
};

const getCustomSitePath = (name, from, folder) => {
    if (env.npm_config_custom_site) {
        return `${from}custom-sites/${env.npm_config_custom_site}/${name}/${folder}`;
    }
    return folder; // Default path configuration
};

const transformHtmlContent = html => {
    const annihilator = /<!-- build:delete -->[\s\S]*?<!-- \/build -->/mg;
    let newHtml = html.replace("[build-signature]", revision()).replace(annihilator, "");
    sites.forEach(name => {
        const regex = new RegExp(`{{ ${name.toUpperCase()}_CONFIG_PATH }}`, "g");
        newHtml = newHtml.replace(regex, getCustomSitePath(name, "../../../", "conf")).replace(annihilator, "");
    });
    return newHtml;
};

const getSiteContent = name => {
    const content = fs.readFileSync(path.join(sitesPath, name, "index.html"), "utf8");
    return {
        name: "index.html",
        html: transformHtmlContent(content),
    };
};

const getCopyTargets = site => {
    const targets = [
        {src: `./src/sites/${site}/img`, dest: `${buildPath}/${site}/`},
        {src: "./styles/img", dest: `${buildPath}/${site}/`},
        // {src: `${ivaPath}/LICENSE`, dest: `${buildPath}`},
        // {src: `${ivaPath}/README.md`, dest: `${buildPath}`},
        {src: "./styles/fonts", dest: `${buildPath}/${site}/`},
        // {src: "./node_modules/bootstrap/dist/fonts/*.woff2", dest: `${buildPath}/${site}/vendors/fonts`},
        {src: "./node_modules/@fortawesome/fontawesome-free/webfonts/*.woff2", dest: `${buildPath}/${site}/vendors/webfonts`},
    ];
    if (env.npm_config_custom_site) {
        targets.push({
            src: getCustomSitePath(site, "", "img"),
            dest: `${buildPath}/${site}/`
        });
    }
    return targets;
};

export default sites.map(site => ({
    plugins: [
        del({
            targets: `build/${site}`,
        }),
        replace({
            preventAssignment: true,
            values: {
                "process.env.VERSION": JSON.stringify(pkg.version),
            },
        }),
        html({
            rootDir: `${sitesPath}/${site}/`,
            input: getSiteContent(site),
        }),
        resolve(),
        minifyHTML(),
        babel({
            exclude: "node_modules/**",
            babelHelpers: "runtime",
            presets: ["@babel/preset-env"],
            plugins: [
                "@babel/plugin-proposal-export-default-from",
                "@babel/plugin-proposal-nullish-coalescing-operator",
                "@babel/transform-runtime",
                ["@babel/plugin-proposal-class-properties", {"loose": false}]
            ]
        }),
        terser({
            ecma: 2020,
            module: true,
            warnings: true
        }),
        copy({
            targets: getCopyTargets(site),
        }),
    ],
    moduleContext: id => {
        // Avoid this Error: https://rollupjs.org/guide/en/#error-this-is-undefined
        /*
        * In order to match native module behaviour, Rollup sets `this`
        * as `undefined` at the top level of modules. Rollup also outputs
        * a warning if a module tries to access `this` at the top level.
        * The following modules use `this` at the top level and expect it
        * to be the global `window` object, so we tell Rollup to set
        *`this = window` for these modules.
        */
        const thisAsWindowForModules = [
            "node_modules/countup.js/dist/countUp.min.js"
        ];

        if (thisAsWindowForModules.some(id_ => id.trimRight().endsWith(id_))) {
            return "window";
        }
    },
    output: {
        dir: `${buildPath}/${site}`,
        manualChunks: id => { // It's only detect "import" from script type=module.. the others no.
            if (id.includes("node_modules")) {
                return "vendors/js/vendors";
            }
            if (id.includes("src/webcomponents")) {
                return "lib/webcomponents.min";
            }
            if (id.includes("src/core")) {
                return "lib/core.min";
            }
        },
        chunkFileNames: () => {
            return "[name]-[hash].js"; // configuration of manualChunks about name format and folder.
        },
        entryFileNames: () => {
            return "lib/[name].js"; // configuration for entry script module and inline script
        },
        assetFileNames: assetInfo => {
            // if (assetInfo.name.includes("genome-browser.config")) {
            //     return "genome-maps/conf/[name][extname]";
            // }

            if (isConfig(assetInfo.name)) {
                return "conf/[name][extname]";
            }

            if (isInternalCss(assetInfo.name)) {
                return "css/[name]-[hash][extname]";
            }

            if (assetInfo.name.endsWith(".js") && !isConfig(assetInfo.name)) {
                return "vendors/js/[name]-[hash][extname]";
            }

            if (assetInfo.name.endsWith(".css")) {
                return "vendors/css/[name]-[hash][extname]";
            }

            return "vendors/[name]-[hash][extname]";
        },
    },
}));
<|endoftext|>


<commit_before>import nodeResolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import fs from 'fs';

var version = JSON.parse(fs.readFileSync('package.json')).version;

if (process.env.production)
  version += ' Production';
else
  version += ' Dev';

var name = `system${process.env.production ? '-production' : ''}`;

export default {
  input: `src/${name}.js`,

  output: {
    format: 'iife',
    file: `dist/${name}.src.js`,
    sourcemap: true,
    sourcemapFile: `dist/${name}.js.map`,
    banner: `/*
    * SystemJS v${version}
    */`
  },

  plugins: [
    nodeResolve({
      module: false,
      jsnext: false,
    }),
    replace({
      VERSION: JSON.stringify(version)
    })
  ],

  // skip rollup warnings (specifically the eval warning)
  onwarn: function() {}
};
<commit_msg>fix banner indentation<commit_after>import nodeResolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import fs from 'fs';

var version = JSON.parse(fs.readFileSync('package.json')).version;

if (process.env.production)
  version += ' Production';
else
  version += ' Dev';

var name = `system${process.env.production ? '-production' : ''}`;

export default {
  input: `src/${name}.js`,

  output: {
    format: 'iife',
    file: `dist/${name}.src.js`,
    sourcemap: true,
    sourcemapFile: `dist/${name}.js.map`,
    banner: `/*
* SystemJS v${version}
*/`
  },

  plugins: [
    nodeResolve({
      module: false,
      jsnext: false,
    }),
    replace({
      VERSION: JSON.stringify(version)
    })
  ],

  // skip rollup warnings (specifically the eval warning)
  onwarn: function() {}
};
<|endoftext|>


<commit_before>/* setup.js
* Created by:
* Date:
* Event listeners and main functions to run simulator
*
* Sources:
*
* TODO:
* - Add comments on functionality
* - Store last successful editor value
*   - in qromp, treat blank editor as okay
*
* DONE:
*
*/

$(document).ready(function() {
	// *** VARIABLE DECLARATION ***\\
	var // Keep track of qubit states and count
		userNum = 1,
		numQubits = 1,
		computedStates = [],
		defaultQubit = {up: {prob: 1, phase: 0}, down: {prob: 0, phase: 0}},
		// Instantiate editor and visualizer
		editor = ace.edit("code-area"),
		visualizer = new VisualizerObject("qubit-svg"),
		// Store often-used elements
		$guideMenu = $("#guide-menu"),
		$guideDetail = $("#guide-detail");

	// *** INITIALIZATION *** \\
	editor.getSession().setUseWrapMode(true);
	buildQubitArray();

	// *** EVENT LISTENERS ***\\

	$("#hidden-file-input").on('change.file',readSingleFile);

	$("#import").click(function(){
		$("#hidden-file-input").click();
	});

	$("#export").on('click', exportProgram);

	// --- Open guide content --- \\
	$(".guide-link").click(function() {
		var $this = $(this);
		$guideMenu.addClass("hidden");
		$guideDetail.removeClass("hidden");
		$("#guide-item-title").text($this.text());
		$($this.data("target")).addClass("current");
	});

	// --- Close guide content --- \\
	$("#guide-back").click(function() {
		$guideMenu.removeClass("hidden");
		var $current = $guideDetail.addClass("hidden").children(".current");
		setTimeout(function() {$current.removeClass("current");}, 450)
	});

	// --- Toggle visibility of reference drawer --- \\
	$("#reference-handle").click(function() {
		var $this = $(this);
		if (!$this.hasClass("flip-h")){
			$this.addClass("flip-h").parent().addClass("open").siblings().addClass("narrow");
		} else {
			$this.removeClass("flip-h").parent().removeClass("open").siblings().removeClass("narrow");
		}
		var animate = setInterval(function() {editor.resize();}, 20);
		setTimeout(function() {clearInterval(animate); editor.resize();}, 450);
	});

	// --- Handle dragging of reference item --- \\
	$(".reference-item").mousedown(function(){
		var $this = $(this),
			$document = $(document),
			offset = $this.offset(),
			diffX = event.pageX - offset.left,
			diffY = event.pageY - offset.top,
			$dragged = $this.clone()
				.attr("id", "dragged")
				.css({"top": event.pageY - diffY, "left": event.pageX - diffX})
				.appendTo("#scroller")
				// when released
				.mouseup(function(){
					$document.off("mousemove.track");
					$dragged.remove();
				});
			// while dragging
			$document.on("mousemove.track", function(){
				$dragged.css({"top": event.pageY - diffY, "left": event.pageX - diffX});
			})
	});

	// --- Set editor to example text --- \\
	$(".example").on("click", function (evt) {
		editor.getSession().setValue($(this).text());
	});

	// --- Add empty qubit to visualizer --- \\
	$("#add-qubit").click(function() {
		if (numQubits < 10) {
			userNum = ++numQubits;
			buildQubitArray();
		}
	});

	// --- Remove an empty qubit from visualizer --- \\
	$("#remove-qubit").click(function() {
		if (numQubits > 0 && numQubits > computedStates.length) {
			userNum = --numQubits;
			buildQubitArray();
		}
	});

	// --- Evaluate the editor contents on change --- \\
	editor.getSession().on('change', safeEvaluate);

	// *** FUNCTIONS ***\\

	function safeEvaluate() {
		try {
	    	evaluate(editor.getValue(), function(qubitStates) {
		    	buildQubitArray(qubitStates);
		    });
	    } catch (e) {
	    	//maybe put a little warning icon in the editor
	    }
	}

	function buildQubitArray(newStates) {
		if (newStates) {
			computedStates = newStates;
			numQubits = (computedStates.length < userNum) ? userNum : computedStates.length;
		}
		for (var fullStates = computedStates.slice(0), i = computedStates.length; i < numQubits; i++) {
			fullStates.push(defaultQubit);
		}
		numQubits = i;
		visualizer.render(fullStates);
	}

	function readSingleFile(evt) {
		if (window.File && window.FileReader && window.FileList) {
			var file = evt.target.files[0];
			if (file) {
				var reader = new FileReader();
				reader.onload = function(e) {
					var contents = e.target.result;
					editor.getSession().setValue(contents);
					$("#hidden-file-input").off('change.file').val("");
					$("#hidden-file-input").on('change.file',readSingleFile);
				}
				reader.readAsText(file);
			}
		} else {
			alert('The File APIs are not fully supported in this browser.');
		}
	}

	function exportProgram() {
		var textToWrite = editor.getValue(),
			textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}),
			fileNameToSaveAs = "qromp_program",
			downloadLink = document.createElement("a");

		downloadLink.download = fileNameToSaveAs;
		downloadLink.innerHTML = "Download File";
		if (window.webkitURL != null) {
			// Chrome allows the link to be clicked
			// without actually adding it to the DOM.
			downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
		} else {
			// Firefox requires the link to be added to the DOM
			// before it can be clicked.
			downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
			downloadLink.onclick = function(event) {
				document.body.removeChild(event.target);
			};
			downloadLink.style.display = "none";
			document.body.appendChild(downloadLink);
		}
		downloadLink.click();
	}

	// *** GUIDE DATA *** \\
	// One option:
	$("#l-start").html("Welcome to qromp, a quantum programming environment designed to help you learn all about stuff..."
		+ "\n
"
		+ "\nClick on an example (feature incomplete):"
		+ "\n
"
			+ "\n
u2 0 1 0.3 1.6 1
"
				+ "\n
hadamard 0
"
				+ "\n
utheta 0 0.6
"
				+ "\n
hadamard 2
"
+ "\nhadamard 1
"
+ "\nutheta 0 0.785398
"
+ "\nnand 0 2 1
"
+ "\nhadamard 2
"
+ "\ncnot 2 1
"
+ "\nhadamard 2
"
+ "\nutheta 1 1.570796
"
+ "\nutheta 2 1.570796
"
			+ "\n
"
		+ "\n
"
	);  // end #l-start.html

	$("#l-quant-comp").html();  // end #l-quant-comp.html
	$("#l-qubits").html(); // end #l-qubits.html
	$("#l-gates").html(); // end #l-gates.html
	$("#l-oracles").html(); // end #l-oracles.html
	$("#l-grovers").html(); // end #l-grovers.html
	$("#e-deutsch-jozsa").html(); // end #e-deutsch-jozsa.html
	$("#e-grovers").html(); // end #e-grovers.html
	$("#e-shors").html(); // end #e-shors.html
	$("#d-qnot").html(); // end #d-qnot.html
	$("#d-cnot").html(); // end #d-cnot.html
	$("#d-srn").html(); // end #d-srn.html
	$("#d-nand").html(); // end #d-nand.html
	$("#d-hadamard").html(); // end #d-hadamard.html
	$("#d-utheta").html(); // end #d-utheta.html
	$("#d-cphase").html(); // end #d-cphase.html
	$("#d-u2").html(); // end #d-u2.html
	$("#d-swap").html(); // end #d-swap.html
	$("#d-measure").html(); // end #d-measure.html
	$("#d-end").html(); // end #d-end.html
	$("#d-oracle").html(); // end #d-oracle.html
});
<commit_msg>Places placeholder text for guide items<commit_after>/* setup.js
* Created by:
* Date:
* Event listeners and main functions to run simulator
*
* Sources:
*
* TODO:
* - Add comments on functionality
* - Store last successful editor value
*   - in qromp, treat blank editor as okay
*
* DONE:
*
*/

$(document).ready(function() {
	// *** VARIABLE DECLARATION ***\\
	var // Keep track of qubit states and count
		userNum = 1,
		numQubits = 1,
		computedStates = [],
		defaultQubit = {up: {prob: 1, phase: 0}, down: {prob: 0, phase: 0}},
		// Instantiate editor and visualizer
		editor = ace.edit("code-area"),
		visualizer = new VisualizerObject("qubit-svg"),
		// Store often-used elements
		$guideMenu = $("#guide-menu"),
		$guideDetail = $("#guide-detail");

	// *** INITIALIZATION *** \\
	editor.getSession().setUseWrapMode(true);
	buildQubitArray();

	// *** EVENT LISTENERS ***\\

	$("#hidden-file-input").on('change.file',readSingleFile);

	$("#import").click(function(){
		$("#hidden-file-input").click();
	});

	$("#export").on('click', exportProgram);

	// --- Open guide content --- \\
	$(".guide-link").click(function() {
		var $this = $(this);
		$guideMenu.addClass("hidden");
		$guideDetail.removeClass("hidden");
		$("#guide-item-title").text($this.text());
		$($this.data("target")).addClass("current");
	});

	// --- Close guide content --- \\
	$("#guide-back").click(function() {
		$guideMenu.removeClass("hidden");
		var $current = $guideDetail.addClass("hidden").children(".current");
		setTimeout(function() {$current.removeClass("current");}, 450)
	});

	// --- Toggle visibility of reference drawer --- \\
	$("#reference-handle").click(function() {
		var $this = $(this);
		if (!$this.hasClass("flip-h")){
			$this.addClass("flip-h").parent().addClass("open").siblings().addClass("narrow");
		} else {
			$this.removeClass("flip-h").parent().removeClass("open").siblings().removeClass("narrow");
		}
		var animate = setInterval(function() {editor.resize();}, 20);
		setTimeout(function() {clearInterval(animate); editor.resize();}, 450);
	});

	// --- Handle dragging of reference item --- \\
	$(".reference-item").mousedown(function(){
		var $this = $(this),
			$document = $(document),
			offset = $this.offset(),
			diffX = event.pageX - offset.left,
			diffY = event.pageY - offset.top,
			$dragged = $this.clone()
				.attr("id", "dragged")
				.css({"top": event.pageY - diffY, "left": event.pageX - diffX})
				.appendTo("#scroller")
				// when released
				.mouseup(function(){
					$document.off("mousemove.track");
					$dragged.remove();
				});
			// while dragging
			$document.on("mousemove.track", function(){
				$dragged.css({"top": event.pageY - diffY, "left": event.pageX - diffX});
			})
	});

	// --- Set editor to example text --- \\
	$(".example").on("click", function (evt) {
		editor.getSession().setValue($(this).text());
	});

	// --- Add empty qubit to visualizer --- \\
	$("#add-qubit").click(function() {
		if (numQubits < 10) {
			userNum = ++numQubits;
			buildQubitArray();
		}
	});

	// --- Remove an empty qubit from visualizer --- \\
	$("#remove-qubit").click(function() {
		if (numQubits > 0 && numQubits > computedStates.length) {
			userNum = --numQubits;
			buildQubitArray();
		}
	});

	// --- Evaluate the editor contents on change --- \\
	editor.getSession().on('change', safeEvaluate);

	// *** FUNCTIONS ***\\

	function safeEvaluate() {
		try {
	    	evaluate(editor.getValue(), function(qubitStates) {
		    	buildQubitArray(qubitStates);
		    });
	    } catch (e) {
	    	//maybe put a little warning icon in the editor
	    }
	}

	function buildQubitArray(newStates) {
		if (newStates) {
			computedStates = newStates;
			numQubits = (computedStates.length < userNum) ? userNum : computedStates.length;
		}
		for (var fullStates = computedStates.slice(0), i = computedStates.length; i < numQubits; i++) {
			fullStates.push(defaultQubit);
		}
		numQubits = i;
		visualizer.render(fullStates);
	}

	function readSingleFile(evt) {
		if (window.File && window.FileReader && window.FileList) {
			var file = evt.target.files[0];
			if (file) {
				var reader = new FileReader();
				reader.onload = function(e) {
					var contents = e.target.result;
					editor.getSession().setValue(contents);
					$("#hidden-file-input").off('change.file').val("");
					$("#hidden-file-input").on('change.file',readSingleFile);
				}
				reader.readAsText(file);
			}
		} else {
			alert('The File APIs are not fully supported in this browser.');
		}
	}

	function exportProgram() {
		var textToWrite = editor.getValue(),
			textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}),
			fileNameToSaveAs = "qromp_program",
			downloadLink = document.createElement("a");

		downloadLink.download = fileNameToSaveAs;
		downloadLink.innerHTML = "Download File";
		if (window.webkitURL != null) {
			// Chrome allows the link to be clicked
			// without actually adding it to the DOM.
			downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
		} else {
			// Firefox requires the link to be added to the DOM
			// before it can be clicked.
			downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
			downloadLink.onclick = function(event) {
				document.body.removeChild(event.target);
			};
			downloadLink.style.display = "none";
			document.body.appendChild(downloadLink);
		}
		downloadLink.click();
	}

	// *** GUIDE DATA *** \\
	// One option:
	$("#l-start").html("Welcome to qromp, a quantum programming environment designed to help you learn all about stuff..."
		+ "\n
"
		+ "\nClick on an example (feature incomplete):"
		+ "\n
"
			+ "\n
u2 0 1 0.3 1.6 1
"
				+ "\n
hadamard 0
"
				+ "\n
utheta 0 0.6
"
				+ "\n
hadamard 2
"
+ "\nhadamard 1
"
+ "\nutheta 0 0.785398
"
+ "\nnand 0 2 1
"
+ "\nhadamard 2
"
+ "\ncnot 2 1
"
+ "\nhadamard 2
"
+ "\nutheta 1 1.570796
"
+ "\nutheta 2 1.570796
"
			+ "\n
"
		+ "\n
"
	);  // end #l-start.html

	$("#l-quant-comp").html("Stuff about quantum computers");  // end #l-quant-comp.html
	$("#l-qubits").html("Stuff about qubits"); // end #l-qubits.html
	$("#l-gates").html("Stuff about gates"); // end #l-gates.html
	$("#l-oracles").html("Stuff about oracles"); // end #l-oracles.html
	$("#l-grovers").html("Stuff about grovers"); // end #l-grovers.html
	$("#e-deutsch-jozsa").html("Stuff about deutsch-jozsa"); // end #e-deutsch-jozsa.html
	$("#e-grovers").html("Stuff about grovers"); // end #e-grovers.html
	$("#e-shors").html("Stuff about shors"); // end #e-shors.html
	$("#d-qnot").html("Stuff about qnot"); // end #d-qnot.html
	$("#d-cnot").html("Stuff about cnot"); // end #d-cnot.html
	$("#d-srn").html("Stuff about srn"); // end #d-srn.html
	$("#d-nand").html("Stuff about nand"); // end #d-nand.html
	$("#d-hadamard").html("Stuff about hadamard"); // end #d-hadamard.html
	$("#d-utheta").html("Stuff about utheta"); // end #d-utheta.html
	$("#d-cphase").html("Stuff about cphase"); // end #d-cphase.html
	$("#d-u2").html("Stuff about u2"); // end #d-u2.html
	$("#d-swap").html("Stuff about swap"); // end #d-swap.html
	$("#d-measure").html("Stuff about measure"); // end #d-measure.html
	$("#d-end").html("Stuff about end"); // end #d-end.html
	$("#d-oracle").html("Stuff about oracle"); // end #d-oracle.html
});
<|endoftext|>


<commit_before>import {terser} from "rollup-plugin-terser";
import * as meta from "./package.json";

const config = {
  input: "src/index.js",
  external: Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)),
  output: {
    file: `dist/${meta.name}.js`,
    name: "d3",
    format: "umd",
    indent: false,
    extend: true,
    banner: `// ${meta.homepage} v${meta.version} Copyright ${(new Date).getFullYear()} ${meta.author.name}`,
    globals: Object.assign({}, ...Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)).map(key => ({[key]: "d3"})))
  },
  plugins: []
};

export default [
  config,
  {
    ...config,
    output: {
      ...config.output,
      file: `dist/${meta.name}.min.js`
    },
    plugins: [
      ...config.plugins,
      terser({
        output: {
          preamble: config.output.banner
        }
      })
    ]
  }
];
<commit_msg>Squelch Rollup warning.<commit_after>import {terser} from "rollup-plugin-terser";
import * as meta from "./package.json";

const config = {
  input: "src/index.js",
  external: Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)),
  output: {
    file: `dist/${meta.name}.js`,
    name: "d3",
    format: "umd",
    indent: false,
    extend: true,
    banner: `// ${meta.homepage} v${meta.version} Copyright ${(new Date).getFullYear()} ${meta.author.name}`,
    globals: Object.assign({}, ...Object.keys(meta.dependencies || {}).filter(key => /^d3-/.test(key)).map(key => ({[key]: "d3"})))
  },
  plugins: [],
  onwarn(message, warn) {
    if (message.code === "CIRCULAR_DEPENDENCY") return;
    warn(message);
  }
};

export default [
  config,
  {
    ...config,
    output: {
      ...config.output,
      file: `dist/${meta.name}.min.js`
    },
    plugins: [
      ...config.plugins,
      terser({
        output: {
          preamble: config.output.banner
        }
      })
    ]
  }
];
<|endoftext|>


<commit_before>
'use strict';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

var ObjectId = mongoose.Schema.Types.ObjectId;

/** A schema for a venue where people can go to. It must have name and unique
 * ID.
 */
var VenueSchema = new Schema({

    appID: {
        unique: true,
        required: true,
        type: String,
    },

    name: {
        //required: true,
        type: String
    },

    location: {
        type: Object,
        //required: true,
        city: {
            type: String,
        },
    },

    url: {
        //TODO
    },

    img: {
        //TODO
    },

    going: [{type: ObjectId, ref: 'User'}],

},
{collection: 'nightlife_venues'}
);

/** Updates the object with a going user.*/
VenueSchema.methods.addGoing = function(userID, cb) {
    var going = this.going;
    var index = going.indexOf(userID);
    if (index < 0) {
        going.push(userID);
        var setVals = {$set: {going: going}};
        this.model('Venue').update({_id: this._id}, setVals, {}, cb);
    }
    else {
        var err = new Error("User already going to the venue. Cannot add.");
        cb(err);
    }
};

/** Removes one going user.*/
VenueSchema.methods.removeGoing = function(userID, cb) {
    var index = this.going.indexOf(userID);
    if (index >= 0) {
        console.log(JSON.stringify(this.going));
        this.going.splice(index, 1);
        console.log(JSON.stringify(this.going));
        var setVals = {$set: {going: this.going}};
        this.model('Venue').update({_id: this._id}, setVals, {}, cb);
    }
    else {
        var err = new Error("User is not going to the venue. Cannot remove.");
        cb(err);
    }

};

module.exports = mongoose.model('Venue', VenueSchema);
<commit_msg>Added descr to venue items which is shown at the client side.<commit_after>
'use strict';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

var ObjectId = mongoose.Schema.Types.ObjectId;

/** A schema for a venue where people can go to. It must have name and unique
 * ID.
 */
var VenueSchema = new Schema({

    appID: {
        unique: true,
        required: true,
        type: String,
    },

    name: {
        //required: true,
        type: String
    },

    location: {
        type: Object,
        //required: true,
        city: {
            type: String,
        },
    },

    descr: {},

    url: {
        //TODO
    },

    img: {
        //TODO
    },

    going: [{type: ObjectId, ref: 'User'}],

},
{collection: 'nightlife_venues'}
);

/** Updates the object with a going user.*/
VenueSchema.methods.addGoing = function(userID, cb) {
    var going = this.going;
    var index = going.indexOf(userID);
    if (index < 0) {
        going.push(userID);
        var setVals = {$set: {going: going}};
        this.model('Venue').update({_id: this._id}, setVals, {}, cb);
    }
    else {
        var err = new Error("User already going to the venue. Cannot add.");
        cb(err);
    }
};

/** Removes one going user.*/
VenueSchema.methods.removeGoing = function(userID, cb) {
    var index = this.going.indexOf(userID);
    if (index >= 0) {
        console.log(JSON.stringify(this.going));
        this.going.splice(index, 1);
        console.log(JSON.stringify(this.going));
        var setVals = {$set: {going: this.going}};
        this.model('Venue').update({_id: this._id}, setVals, {}, cb);
    }
    else {
        var err = new Error("User is not going to the venue. Cannot remove.");
        cb(err);
    }

};

module.exports = mongoose.model('Venue', VenueSchema);
<|endoftext|>


<commit_before>/*
MIT License

Copyright (c) 2017 Hasan Altan Birler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

function staticsearch(htmlnode,
	textelements=["a","span","link","nav","caption","thead",
		"#text","h1","h2","h3","h4","h5","h6",
		"abbr","address","b","bdi","bdo","blockquote",
		"cite","code","del","dfn","em","i","ins","kbd",
		"mark","meter","pre","progress","q","rp","rt",
		"ruby","s","samp","small","strong","sub","time",
		"u","var","wbr","label"]) {
	class VNode {
		constructor(htmlnode) {
			this.origdisplay = htmlnode.style.display;
			this.preactive = true;
			this.active = true;
			this.htmlnode = htmlnode;
			this.children = [];
			this.textchildren = [];
		}

		addChild(htmlnode) {
			const newnode = new VNode(htmlnode);
			this.children.push(newnode);
			return newnode;
		}
	}

	class TextVNode {
		constructor(htmlnode, parenthtmlnode) {
			this.preactive = true;
			this.active = true;
			this.markered = false;
			this.htmlnode = htmlnode;
			this.parenthtmlnode = parenthtmlnode;
			this.data = htmlnode.nodeValue;
		}
	}

	const treeroot = new VNode(htmlnode)

	function isTextNode(htmlnode) {
		return textelements.includes(htmlnode.nodeName.toLowerCase());
	}

	function createTraverse(vnode, htmlnode) {
		for (const cnode of htmlnode.childNodes) {
			if (isTextNode(cnode)) {
				if (cnode.nodeName === "#text") {
					vnode.textchildren.push(new TextVNode(cnode, htmlnode));
				}
				else {
					createTraverse(vnode, cnode);
				}
			}
			else {
				const childvnode = vnode.addChild(cnode);
				createTraverse(childvnode, cnode);
			}
		}
	}

	//build vnode tree
	createTraverse(treeroot, htmlnode);

	return {
		root: treeroot,
		filter: function(pattern) {
			class MarkerAction {
				constructor(parent, prenode, newnode) {
					this.parent = parent;
					this.prenode = prenode;
					this.newnode = newnode;
				}
			}

			class DisplayAction {
				constructor(vnode, newdisplay) {
					this.vnode = vnode;
					this.newdisplay = newdisplay;
				}
			}

			function getIndices(pattern, str) {
				const retval = [];
				const strtrans = str.toLowerCase();
				if (pattern == "") return retval;
				for (let i = strtrans.indexOf(pattern, 0); i >= 0; i = strtrans.indexOf(pattern, i+1))
					retval.push(i);
				return retval;
			}

			function createMarkedElement(text, pattern, indices) {
				if (pattern == "" || indices.length === 0)
					return document.createTextNode(text);

				const retval = document.createElement("span");

				let preind = 0;
				for (const ind of indices) {
					retval.appendChild(document.createTextNode(text.slice(preind, ind)));
					const markelement = document.createElement("mark");
					markelement.appendChild(document.createTextNode(text.slice(ind, ind + pattern.length)));
					retval.appendChild(markelement);
					preind = ind + pattern.length;
				}
				retval.appendChild(document.createTextNode(text.slice(preind, text.length)));

				return retval;
			}

			const markeractions = []
			function computeActive(pattern, mactions, vnode) {
				vnode.preactive = vnode.active;
				vnode.active = false;
				for (const tvnode of vnode.textchildren) {
					tvnode.preactive = tvnode.active;
					indices = getIndices(pattern, tvnode.data);
					tvnode.active = pattern === "" || indices.length > 0;

					if (tvnode.preactive === true || (tvnode.active === true && pattern !== "")) {
						const newnode = createMarkedElement(tvnode.data, pattern, indices);
						const myaction = new MarkerAction(tvnode.parenthtmlnode, tvnode.htmlnode, newnode);
						tvnode.htmlnode = newnode;
						mactions.push(myaction);
					}
					if (tvnode.active) vnode.active = true;
				}

				for (const cvnode of vnode.children) {
					computeActive(pattern, mactions, cvnode);
					if (cvnode.active) vnode.active = true;
				}
			}
			computeActive(pattern, markeractions, this.root);

			const displayactions = [];
			function computeActions(dactions, vnode) {
				if (vnode.preactive === true && vnode.active === false)
					dactions.push(new DisplayAction(vnode, vnode.active));

				for (const cvnode of vnode.children) {
					computeActions(dactions, cvnode);
				}

				if (vnode.preactive === false && vnode.active === true)
					dactions.push(new DisplayAction(vnode, vnode.active));
			}
			computeActions(displayactions, this.root);

			for (const dact of displayactions) {
				if (dact.newdisplay) {
					dact.vnode.htmlnode.style.display = dact.vnode.origdisplay;
				} else {
					dact.vnode.htmlnode.style.display = "none";
				}
			}

			for (const mact of markeractions) {
				mact.parent.replaceChild(mact.newnode, mact.prenode);
			}
		}
	};
}

/*
var replacementNode = document.createElement('span');
replacementNode.innerHTML = linkify(n.textContent);
n.parentNode.insertBefore(replacementNode, n);
n.parentNode.replaceChild(n);
*/<commit_msg>Cleaned up code<commit_after>/*
MIT License

Copyright (c) 2017 Hasan Altan Birler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

function staticsearch(htmlnode,
	textelements=["a","span","link","nav","caption","thead",
		"#text","h1","h2","h3","h4","h5","h6",
		"abbr","address","b","bdi","bdo","blockquote",
		"cite","code","del","dfn","em","i","ins","kbd",
		"mark","meter","pre","progress","q","rp","rt",
		"ruby","s","samp","small","strong","sub","time",
		"u","var","wbr","label"]) {
	class VNode {
		constructor(htmlnode) {
			this.origdisplay = htmlnode.style.display;
			this.preactive = true;
			this.active = true;
			this.htmlnode = htmlnode;
			this.children = [];
			this.textchildren = [];
		}

		addChild(htmlnode) {
			const newnode = new VNode(htmlnode);
			this.children.push(newnode);
			return newnode;
		}
	}

	class TextVNode {
		constructor(htmlnode, parenthtmlnode) {
			this.preactive = true;
			this.active = true;
			this.markered = false;
			this.htmlnode = htmlnode;
			this.parenthtmlnode = parenthtmlnode;
			this.data = htmlnode.nodeValue;
		}
	}

	const treeroot = new VNode(htmlnode)

	function isTextNode(htmlnode) {
		return textelements.includes(htmlnode.nodeName.toLowerCase());
	}

	//Creates the initial VNode tree by traversing DOM
	function createTraverse(vnode, htmlnode) {
		for (const cnode of htmlnode.childNodes) {
			if (isTextNode(cnode)) {
				if (cnode.nodeName === "#text") {
					vnode.textchildren.push(new TextVNode(cnode, htmlnode));
				}
				else {
					createTraverse(vnode, cnode);
				}
			}
			else {
				const childvnode = vnode.addChild(cnode);
				createTraverse(childvnode, cnode);
			}
		}
	}

	createTraverse(treeroot, htmlnode);

	return {
		root: treeroot,
		filter: function(pattern) {
			class MarkerAction {
				constructor(parent, prenode, newnode) {
					this.parent = parent;
					this.prenode = prenode;
					this.newnode = newnode;
				}
			}

			class DisplayAction {
				constructor(vnode, newdisplay) {
					this.vnode = vnode;
					this.newdisplay = newdisplay;
				}
			}

			function getIndices(pattern, str) {
				const retval = [];
				const strtrans = str.toLowerCase();
				if (pattern == "") return retval;
				for (let i = strtrans.indexOf(pattern, 0); i >= 0; i = strtrans.indexOf(pattern, i+1))
					retval.push(i);
				return retval;
			}

			//Creates a #text replacement element that replaces pattern with mark tags
			function createMarkedElement(text, pattern, indices) {
				if (pattern == "" || indices.length === 0)
					return document.createTextNode(text);

				const retval = document.createElement("span");

				let preind = 0;
				for (const ind of indices) {
					retval.appendChild(document.createTextNode(text.slice(preind, ind)));
					const markelement = document.createElement("mark");
					markelement.appendChild(document.createTextNode(text.slice(ind, ind + pattern.length)));
					retval.appendChild(markelement);
					preind = ind + pattern.length;
				}
				retval.appendChild(document.createTextNode(text.slice(preind, text.length)));

				return retval;
			}

			const markeractions = []
			//Checks for changes in #text elements and creates MarkerActions
			//Updates whether nodes should be displayed
			function computeActive(pattern, mactions, vnode) {
				vnode.preactive = vnode.active;
				vnode.active = false;
				for (const tvnode of vnode.textchildren) {
					tvnode.preactive = tvnode.active;
					indices = getIndices(pattern, tvnode.data);
					tvnode.active = pattern === "" || indices.length > 0;

					if (tvnode.preactive === true || (tvnode.active === true && pattern !== "")) {
						const newnode = createMarkedElement(tvnode.data, pattern, indices);
						const myaction = new MarkerAction(tvnode.parenthtmlnode, tvnode.htmlnode, newnode);
						tvnode.htmlnode = newnode;
						mactions.push(myaction);
					}
					if (tvnode.active) vnode.active = true;
				}

				for (const cvnode of vnode.children) {
					computeActive(pattern, mactions, cvnode);
					if (cvnode.active) vnode.active = true;
				}
			}
			computeActive(pattern, markeractions, this.root);

			const displayactions = [];
			//Computes the DisplayActions
			//Hide nodes higher in the tree with highest priority
			//Display nodes lower in the tree with high priority
			function computeActions(dactions, vnode) {
				if (vnode.preactive === true && vnode.active === false)
					dactions.push(new DisplayAction(vnode, vnode.active));

				for (const cvnode of vnode.children) {
					computeActions(dactions, cvnode);
				}

				if (vnode.preactive === false && vnode.active === true)
					dactions.push(new DisplayAction(vnode, vnode.active));
			}
			computeActions(displayactions, this.root);

			//Apply the DisplayActions (hide and display nodes)
			for (const dact of displayactions) {
				if (dact.newdisplay) {
					dact.vnode.htmlnode.style.display = dact.vnode.origdisplay;
				} else {
					dact.vnode.htmlnode.style.display = "none";
				}
			}

			//Apply the MarkerActions (add and remove mark tags)
			for (const mact of markeractions) {
				mact.parent.replaceChild(mact.newnode, mact.prenode);
			}
		}
	};
}<|endoftext|>


<commit_before>/*!
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements;
 * and to You under the Apache License, Version 2.0.
 */
'use strict';

/**
 * @ngdoc overview
 * @name playerApp
 * @description
 * # playerApp
 *
 * Main module of the application.
 */

var baseUrl = window.location.host;

// Angular templates (used to feed $templateCache)
//angular.module('templates', []);

angular.module('playerApp', ['ngResource','ngSanitize','ui.router','ngWebSocket','luegg.directives', 'hc.marked', 'templates'])
  .run(
  [          '$rootScope', '$state', '$stateParams',
    function ($rootScope,   $state,   $stateParams) {
      // make life easier
      $rootScope.$on("$stateChangeError", console.log.bind(console));

      // From https://github.com/angular-ui/ui-router/blob/gh-pages/sample/app/app.js
      $rootScope.$state = $state;
      $rootScope.$stateParams = $stateParams;
    }
  ])
  .constant("API", {
    "HOST": baseUrl,
    "PROFILE_URL": "https://"+baseUrl+"/players/v1/",
    "WS_URL": "wss://"+baseUrl+"/mediator/ws/",
    "CERT_URL": "https://"+baseUrl+"/auth/PublicCertificate",
    "GOOGLE": "https://"+baseUrl+"/auth/GoogleAuth",
    "TWITTER": "https://"+baseUrl+"/auth/TwitterAuth",
    "FACEBOOK": "https://"+baseUrl+"/auth/FacebookAuth",
    "GITHUB": "https://"+baseUrl+"/auth/GitHubAuth",
    "DUMMY": "https://"+baseUrl+"/auth/DummyAuth?dummyUserName=DevUser&callbackHost=https://"+baseUrl
  })
  .config(['markedProvider', function (markedProvider) {
    markedProvider.setOptions({sanitize: true});
  }])
  .config(['$locationProvider', function($locationProvider) {
    $locationProvider.hashPrefix('');
  }])
  .config(
  [          '$stateProvider','$urlRouterProvider',
    function ($stateProvider,  $urlRouterProvider) {

      // Use $urlRouterProvider to configure any redirects (when) and invalid urls (otherwise).
      // The `when` method says if the url is ever the 1st param, then redirect to the 2nd param
      $urlRouterProvider
        .otherwise('/');

      //////////////////////////
      // State Configurations

      $stateProvider
        .state('default', {
          url: '/',
          templateUrl: '/default.html',
          controller: 'DefaultCtrl as ctrl',
          onEnter: function(go_ga){
            console.info("state -> default");
            go_ga.hit('default');
          }
        })
        .state('default.terms', {
          url: '^/terms'
        })
        .state('default.login', {
          url: '^/login',
          onEnter: function(go_ga){
            console.info("state -> default.login");
            go_ga.hit('login');
            go_ga.report('send','event','GameOn','App','login');
          }
        })
        .state('default.auth', {
          url: '^/login/callback/{jwt:.*}',
      // State triggered by authentication callback (only).
          onEnter: function($state, $stateParams, auth) {
            console.info("state -> default.auth");
            auth.get_public_key(
            function(){
                console.log("got public cert.. proceeding to jwt validation.");

              auth.remember_jwt($stateParams.jwt);
              $state.go('default.validatejwt');
            },
            function(){
              //TODO: handle failure to obtain public key.
              //      can't do much without it.
              $state.go('default.yuk');
            });
           }
        })
        .state('default.validatejwt', {
          url: '^/login/getpubliccert',
      // State triggered by auth obtaining public key
          onEnter: function($state, $stateParams, auth, go_ga) {
            // this step has to read the token from the params passed ($stateParams.token)
            // and cause it to be stashed into the auth object so we can rely on it going forwards.

            console.info("state -> default.validatejwt");
            if(auth.validate_jwt()){
                console.log("token callback from auth service was valid");
                go_ga.report('send','event','GameOn','App','login-pass');
                $state.go('default.usersetup');
            }else{
                //TODO: goto a login failed page..
                go_ga.report('send','event','GameOn','App','login-fail');
                $state.go('default.login');
            }
          }
        })
        .state('default.usersetup', {
          url: '^/login/usersetup',
          // Triggered by default.auth state.
          onEnter: function($state, $stateParams,auth,user,go_ga) {
            console.info("state -> default.usersetup");
            go_ga.hit('usersetup');
            console.log("building user object");
            var jwt = auth.get_jwt();
            if (jwt !== null){
                // Verify the returned token...
                console.log("cached/recovered token was valid, token info object was");
                console.log(jwt);
                //user.load returns a promise that resolves to true if the user was found.. false otherwise.
                user.load(jwt.id, jwt.name).then(function(userKnownToDB){
                  if(userKnownToDB){
                    go_ga.report('send','event','GameOn','App','login-existing');
                    $state.go('play.room');
                  }else{
                    go_ga.report('send','event','GameOn','App','login-new');
                    $state.go('default.profile');
                  }
                });
              }else{
                //cached / recovered token was invalid.
                //TODO: goto a login failed page..
                $state.go('default.login');
              }
          }
        })
        .state('default.profile', { // initial profile creation
          url: '^/login/profile',
          onEnter: function($state, $stateParams, user, auth, go_ga) {
            console.info("state: default.profile");
            //if we're missing our auth token info.. user may have hit refresh here..
            //since we've just lost all our context, send them back to the start..
            //mebbe can make this nicer ;p
            if(typeof user.profile.name === 'undefined'){
              console.log("Missing auth info.. redirecting.. ");
              $state.go('default.login');
            }else{
              go_ga.hit('profile');
              console.log("default.profile.onEnter has this ", user.profile.name, auth);
            }
          }
        })
        .state('default.yuk', {
          url: '^/yuk',
        })
        .state('play', {
          // With abstract set to true, that means this state can not be explicitly activated.
          // It can only be implicitly activated by activating one of its children.
          abstract: true,
          url: '/play',
          templateUrl: '/play.html',
          controller: 'PlayCtrl as play',
          resolve: {
            // a fictional var that we'll have injected to onEntry and into the PlayCtrl.
            // resolve will make sure we don't create PlayCtrl or enter onEntry until
            // the promises below are all complete.
            "userAndAuth" : function(auth,user,$state) {
              return auth.getAuthenticationState().then(function(isAuthenticated){
                if(!isAuthenticated){
                  $state.go('default.login');
                }else{
                  if(typeof user.profile._id === 'undefined'){
                    $state.go('default.usersetup');
                  }
                }
              });
            }
          },
          onEnter: function($state, auth, user, userAndAuth){
            console.log("In play state", user, auth, userAndAuth);
          }
        })
        .state('play.room', {
          url: '',
          templateUrl: '/play.room.html',
          onEnter: function(go_ga){
            go_ga.hit('game_screen');
            go_ga.report('send','event','GameOn','App','play');
          }
        })
        .state('play.myrooms', {
          url: '/myrooms',
          templateUrl: '/play.myrooms.html',
          onEnter: function(go_ga){
            go_ga.hit('room_editor');
            go_ga.report('send','event','GameOn','App','edit_rooms');
          }
        })
        .state('play.me', {
          url: '/me',
          templateUrl: '/play.me.html',
          onEnter: function(go_ga, user){
            user.refresh();
            go_ga.hit('profile_editor');
            go_ga.report('send','event','GameOn','App','edit_profile');
          }
        });
    }
  ]);
<commit_msg>dummy auth for other environments<commit_after>/*!
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements;
 * and to You under the Apache License, Version 2.0.
 */
'use strict';

/**
 * @ngdoc overview
 * @name playerApp
 * @description
 * # playerApp
 *
 * Main module of the application.
 */

var baseUrl = window.location.host;

// Angular templates (used to feed $templateCache)
//angular.module('templates', []);

angular.module('playerApp', ['ngResource','ngSanitize','ui.router','ngWebSocket','luegg.directives', 'hc.marked', 'templates'])
  .run(
  [          '$rootScope', '$state', '$stateParams',
    function ($rootScope,   $state,   $stateParams) {
      // make life easier
      $rootScope.$on("$stateChangeError", console.log.bind(console));

      // From https://github.com/angular-ui/ui-router/blob/gh-pages/sample/app/app.js
      $rootScope.$state = $state;
      $rootScope.$stateParams = $stateParams;
    }
  ])
  .constant("API", {
    "HOST": baseUrl,
    "PROFILE_URL": "https://"+baseUrl+"/players/v1/",
    "WS_URL": "wss://"+baseUrl+"/mediator/ws/",
    "CERT_URL": "https://"+baseUrl+"/auth/PublicCertificate",
    "GOOGLE": "https://"+baseUrl+"/auth/GoogleAuth",
    "TWITTER": "https://"+baseUrl+"/auth/TwitterAuth",
    "FACEBOOK": "https://"+baseUrl+"/auth/FacebookAuth",
    "GITHUB": "https://"+baseUrl+"/auth/GitHubAuth",
    "DUMMY": "https://"+baseUrl+"/auth/DummyAuth?dummyUserName=DevUser&callbackHost=https://"+baseUrl,
    "showDummy": ( baseUrl.startsWith("testing.") || baseUrl.startsWith("staging.") || !baseUrl.endsWith(".org") )
  })
  .config(['markedProvider', function (markedProvider) {
    markedProvider.setOptions({sanitize: true});
  }])
  .config(['$locationProvider', function($locationProvider) {
    $locationProvider.hashPrefix('');
  }])
  .config(
  [          '$stateProvider','$urlRouterProvider',
    function ($stateProvider,  $urlRouterProvider) {

      // Use $urlRouterProvider to configure any redirects (when) and invalid urls (otherwise).
      // The `when` method says if the url is ever the 1st param, then redirect to the 2nd param
      $urlRouterProvider
        .otherwise('/');

      //////////////////////////
      // State Configurations

      $stateProvider
        .state('default', {
          url: '/',
          templateUrl: '/default.html',
          controller: 'DefaultCtrl as ctrl',
          onEnter: function(go_ga){
            console.info("state -> default");
            go_ga.hit('default');
          }
        })
        .state('default.terms', {
          url: '^/terms'
        })
        .state('default.login', {
          url: '^/login',
          onEnter: function(go_ga){
            console.info("state -> default.login");
            go_ga.hit('login');
            go_ga.report('send','event','GameOn','App','login');
          }
        })
        .state('default.auth', {
          url: '^/login/callback/{jwt:.*}',
      // State triggered by authentication callback (only).
          onEnter: function($state, $stateParams, auth) {
            console.info("state -> default.auth");
            auth.get_public_key(
            function(){
                console.log("got public cert.. proceeding to jwt validation.");

              auth.remember_jwt($stateParams.jwt);
              $state.go('default.validatejwt');
            },
            function(){
              //TODO: handle failure to obtain public key.
              //      can't do much without it.
              $state.go('default.yuk');
            });
           }
        })
        .state('default.validatejwt', {
          url: '^/login/getpubliccert',
      // State triggered by auth obtaining public key
          onEnter: function($state, $stateParams, auth, go_ga) {
            // this step has to read the token from the params passed ($stateParams.token)
            // and cause it to be stashed into the auth object so we can rely on it going forwards.

            console.info("state -> default.validatejwt");
            if(auth.validate_jwt()){
                console.log("token callback from auth service was valid");
                go_ga.report('send','event','GameOn','App','login-pass');
                $state.go('default.usersetup');
            }else{
                //TODO: goto a login failed page..
                go_ga.report('send','event','GameOn','App','login-fail');
                $state.go('default.login');
            }
          }
        })
        .state('default.usersetup', {
          url: '^/login/usersetup',
          // Triggered by default.auth state.
          onEnter: function($state, $stateParams,auth,user,go_ga) {
            console.info("state -> default.usersetup");
            go_ga.hit('usersetup');
            console.log("building user object");
            var jwt = auth.get_jwt();
            if (jwt !== null){
                // Verify the returned token...
                console.log("cached/recovered token was valid, token info object was");
                console.log(jwt);
                //user.load returns a promise that resolves to true if the user was found.. false otherwise.
                user.load(jwt.id, jwt.name).then(function(userKnownToDB){
                  if(userKnownToDB){
                    go_ga.report('send','event','GameOn','App','login-existing');
                    $state.go('play.room');
                  }else{
                    go_ga.report('send','event','GameOn','App','login-new');
                    $state.go('default.profile');
                  }
                });
              }else{
                //cached / recovered token was invalid.
                //TODO: goto a login failed page..
                $state.go('default.login');
              }
          }
        })
        .state('default.profile', { // initial profile creation
          url: '^/login/profile',
          onEnter: function($state, $stateParams, user, auth, go_ga) {
            console.info("state: default.profile");
            //if we're missing our auth token info.. user may have hit refresh here..
            //since we've just lost all our context, send them back to the start..
            //mebbe can make this nicer ;p
            if(typeof user.profile.name === 'undefined'){
              console.log("Missing auth info.. redirecting.. ");
              $state.go('default.login');
            }else{
              go_ga.hit('profile');
              console.log("default.profile.onEnter has this ", user.profile.name, auth);
            }
          }
        })
        .state('default.yuk', {
          url: '^/yuk',
        })
        .state('play', {
          // With abstract set to true, that means this state can not be explicitly activated.
          // It can only be implicitly activated by activating one of its children.
          abstract: true,
          url: '/play',
          templateUrl: '/play.html',
          controller: 'PlayCtrl as play',
          resolve: {
            // a fictional var that we'll have injected to onEntry and into the PlayCtrl.
            // resolve will make sure we don't create PlayCtrl or enter onEntry until
            // the promises below are all complete.
            "userAndAuth" : function(auth,user,$state) {
              return auth.getAuthenticationState().then(function(isAuthenticated){
                if(!isAuthenticated){
                  $state.go('default.login');
                }else{
                  if(typeof user.profile._id === 'undefined'){
                    $state.go('default.usersetup');
                  }
                }
              });
            }
          },
          onEnter: function($state, auth, user, userAndAuth){
            console.log("In play state", user, auth, userAndAuth);
          }
        })
        .state('play.room', {
          url: '',
          templateUrl: '/play.room.html',
          onEnter: function(go_ga){
            go_ga.hit('game_screen');
            go_ga.report('send','event','GameOn','App','play');
          }
        })
        .state('play.myrooms', {
          url: '/myrooms',
          templateUrl: '/play.myrooms.html',
          onEnter: function(go_ga){
            go_ga.hit('room_editor');
            go_ga.report('send','event','GameOn','App','edit_rooms');
          }
        })
        .state('play.me', {
          url: '/me',
          templateUrl: '/play.me.html',
          onEnter: function(go_ga, user){
            user.refresh();
            go_ga.hit('profile_editor');
            go_ga.report('send','event','GameOn','App','edit_profile');
          }
        });
    }
  ]);
<|endoftext|>


<commit_before>/**
 * 日期选择组添加方法:
 * <input type="text" name="xtime" data-toggle="hsDate" data-type="timestamp" data-fl="v || new Date().getTime() / 1000"/>
 * 可包裹在输入框组内,
 * 此输入框将被替换掉.
 *
 * 注: 2017/06/22 增加简单日期选择控件
 */

(function($) {

    function _addzero(num, len) {
        num = num ? num : "";
        num = num.toString();
        var gth = num.length;
        for (var i = gth; i < len; i ++) {
            num = "0" + num ;
        }
        return num;
    }

    function _setdate(box, dat) {
        box.find("[data-date]").each(function() {
            var flg = $( this ).data( "date" );
            switch (flg) {
                case 'La':
                case 'Sa':
                    $(this).val(dat.getHours() > 11 ? 1 : 0);
                    break;
                case 'LM':
                case 'SM':
                    $(this).val(dat.getMonth());
                    break;
                case 'M':
                    $(this).val(dat.getMonth() + 1);
                    break;
                case 'y':
                    $(this).val(dat.getFullYear() );
                    break;
                case 'Sy':
                    $(this).val(dat.getFullYear() - 2000);
                    break;
                case 'd':
                    $(this).val(dat.getDate( ));
                    break;
                case 'H':
                    $(this).val(dat.getHours());
                    break;
                case 'k':
                    $(this).val(dat.getHours() + 1 );
                    break;
                case 'K':
                    $(this).val(dat.getHours() % 12);
                    break;
                case 'h':
                    $(this).val(dat.getHours() % 12) + 1;
                    break;
                case 'm':
                    $(this).val(dat.getMinutes());
                    break;
                case 's':
                    $(this).val(dat.getSeconds());
                    break;
                case 'S':
                    $(this).val(dat.getMilliseconds());
                    break;
            }
        });
        return dat;
    }

    function _getdate(box, dat) {
        var pm = box.find("[data-date=La],[data-date=Sa]").val() == '1';
        box.find("[data-date]").each(function() {
            var flg = $( this ).data( "date" );
            var val = parseInt($(this).val( ));
            // 值被清空时则自动选中第一个日历项
            if (isNaN( val )) {
                var opt;
                opt = $(this).children().eq(0);
                val = parseInt(opt.val());
                opt.prop("selected",true);
            }
            switch (flg) {
                case 'LM':
                case 'SM':
                    dat.setMonth(val);
                    break;
                case 'M':
                    dat.setMonth(val - 1);
                    break;
                case 'y':
                    dat.setFullYear(val);
                    break;
                case 'Sy':
                    dat.setFullYear(val + 2000);
                    break;
                case 'd':
                    dat.setDate(val);
                    break;
                case 'H':
                    dat.setHours(val);
                    break;
                case 'k':
                    dat.setHours(val - 1);
                    break;
                case 'K':
                    dat.setHours(val + (pm ? 12 : 0));
                    break;
                case 'h':
                    dat.setHours(val + (pm ? 11 :-1));
                    break;
                case 'm':
                    dat.setMinutes(val);
                    break;
                case 's':
                    dat.setSeconds(val);
                    break;
                case 'S':
                    dat.setMilliseconds(val);
                    break;
            }
        });
        return dat;
    };

    function _makeGroups(grp) {
        var len = grp.length;
        var flg = grp.substring(0, 1);
        switch (flg) {
            case 'a':
                if (len >= 4) {
                    return _makeChoose("La", hsGetLang("date.La"));
                }
                else {
                    return _makeChoose("Sa", hsGetLang("date.Sa"));
                }
            case 'M':
                if (len >= 4) {
                    return _makeChoose("LM", hsGetLang("date.LM"));
                }
                if (len == 3) {
                    return _makeChoose("SM", hsGetLang("date.SM"));
                }
                else {
                    return _makeSelect( "M", 1, 12, len);
                }
            case 'y':
                if (len >= 4) {
                    return _makeSelect( "y", 1970, 2099, len);
                }
                else {
                    return _makeSelect("Sy", 0, 99, len);
                }
            case 'd':
                return _makeSelect(flg, 1, 31, len);
            case 'H':
                return _makeSelect(flg, 0, 23, len);
            case 'k':
                return _makeSelect(flg, 1, 24, len);
            case 'K':
                return _makeSelect(flg, 0, 11, len);
            case 'h':
                return _makeSelect(flg, 1, 12, len);
            case 'm':
                return _makeSelect(flg, 0, 59, len);
            case 's':
                return _makeSelect(flg, 0, 59, len);
            case 'S':
                return _makeSelect(flg, 0,999, len);
        }
    }

    function _makeChoose(flg, arr) {
        var s = '<select class="form-control datebox-'+flg+'" data-date="'+flg+'">';
        for(var j = arr.length, i = 0; i < j; i ++) {
            var v = arr[i];
            s += '<option value="'+ i +'">'+ v +'</option>';
        }
        s += '</select>';
        return $(s);
    }

    function _makeSelect(flg, min, max, len) {
        var s = '<select class="form-control datebox-'+flg+'" data-date="'+flg+'">';
        for(  ; min <= max  ; min ++  ) {
            var v  = _addzero(min, len);
            s += '<option value="'+min+'">'+ v +'</option>';
        }
        s += '</select>';
        return $(s);
    }

    function _makeAddons(txt) {
        var spn = $('');
        spn.text ( txt );
        return spn ;
    }

    function _makeInputs(fmt) {
        var box = $('

');
        var pat = /([MdyHkKhmsSa]+|[^MdyHkKhmsSa']+|'.*?')/g;
        var wrd = /^[MdyHkKhmsSa]+$/;
        var grp ;
        while ((grp = pat.exec(fmt))!= null) {
            grp = grp[0];
            if (wrd.test(grp)) {
                box.append(_makeGroups(grp));
            } else {
                box.append(_makeAddons(grp));
            }
        }
        box.append(_makeAddons("").css("width", "100%")); // 占位撑长
        return box;
    }

    /**
     * 日期时间选择, 用下拉列表构建
     */
    $.fn.hsDate = function() {
        if (this.data("linked")) {
            return; // 跳过已初始化
        }

        var fmt = this.data("format") || hsGetLang("datetime.format");
        var inp = this;
        var box ;

        do {
            /**
             * 如果有查找到组件标记
             * 说明用的是自定义选项
             * 就不需要再构建选项了
             */
            box = inp.siblings().filter("[data-widget=hsDate]");
            if (box.size() != 0) {
                break;
            }
            box = inp.parent(  ).filter("[data-widget=hsDate]");
            if (box.size() != 0) {
                break;
            }

            // 也可以指定对象的类型
            // 从当前语言配置中提取
            switch (fmt) {
                case "time":
                    fmt = hsGetLang("time.format");
                    break;
                case "date":
                    fmt = hsGetLang("date.format");
                    break;
                case "datetime" : case "" : case null :
                    fmt = hsGetLang("datetime.format");
            }

            inp.addClass("invisible");
            box = _makeInputs ( fmt );
            box.insertBefore  ( inp );

            /**
             * 非必填需增加取消按钮
             */
            if (!inp.attr("required")
            &&  !inp.data("required")) {
                box.find('.input-group-addon')
                   .last()
                   .css ("text-align","right")
                   .html('');
            }

            /**
             * 输入框组是不可嵌套的
             * 如果已经在输入框组里
             * 需要把选项向上提一层
             */
            if (inp.parent().is(".input-group")) {
                inp.before(box.contents());
                box.remove();
                box = inp.parent( );
                box.addClass ( "datebox" );
            }
        }
        while (false);

        box.addClass("datebox");
        box.attr("data-widget" , "hsDate");
        box.data("linked", inp);
        inp.attr("data-toggle" , "hsDate");
        inp.data("linked", box);

        inp.trigger ("change" );
    };

    /**
     * 日期时间输入, 用原生控件构建
     */
    $.fn.hsTime = function() {
        if (this.data("linked")) {
            return; // 跳过已初始化
        }

        var hide = $('<input type="hidden" class="form-ignored"/>');
        var type = this.attr("type"   );
        var kind = this.data("type"   );
        var frmt = this.data("format" );
        var patt = this.attr("pattern");
        var that = this;

        // 没指定则按类型的标准处理
        if (!frmt || !patt) {
            if (type == "time") {
                frmt = "HH:mm" ;
                patt = "\d{1,2}:\d{1,2}" ;
            } else
            if (type == "date") {
                frmt = "yyyy-MM-dd";
                patt = "\d{2,4}-\d{1,2}-\d{1,2}";
            } else
            {
                frmt = "yyyy-MM-ddTHH:mm";
                patt = "\d{2,4}-\d{1,2}-\d{1,2}T\d{1,2}:\d{1,2}";
            }
            this.data("format" , frmt);
            this.attr("pattern", patt);
        }

        hide.attr("name", this.attr("name"));
        this.attr("name", "" );
        this.data("linked", hide);
        hide.data("linked", this);
        this.after(hide);

        // 互相联动
        hide.on("change", function() {
            var v = $(this).val();
            if (v == "") {
                that.val("");
                return ;
            }

            var d = hsFmtDate(v, frmt);
            that.val(d);
        });
        this.on("change", function() {
            var v = $(this).val();
            if (v == "") {
                hide.val("");
                return ;
            }

            // 解析失败设为空
            var d = hsPrsDate(v, frmt);
            d = d.getTime( );
            if (isNaN(d)
            ||  0 === d) {
                hide.val("");
                return ;
            }

            // 可选择精确到秒
            if (kind == "timestamp"
            ||  kind == "datestamp") {
                d = Math.round(d/1000);
            }

            hide.val(d);
        });
    };

    // 处理大小月及闰年时日期的变化
    $(document).on("change", "[data-date=M],[data-date=SM],[data-date=LM]", function() {
        var y = $(this).closest(".input-group")
                .find("[data-date=y],[data-date=Sy]").val();
        var d = $(this).closest(".input-group")
                .find("[data-date=d]");
        var m = $(this).val( );
        if (y < 100) y += 2000;
        if (m == 2) {
            if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) {
                d.find("option:gt(28)")
                 .prop("selected", false)
                 .hide();
            } else {
                d.find("option:gt(27)")
                 .prop("selected", false)
                 .hide();
            }
        } else {
            if ((m < 7 && m % 2 == 0) || (m > 7 && m % 2 == 1)) {
                d.find("option:gt(29)")
                 .prop("selected", false)
                 .hide();
            } else {
                d.find("option:gt(27)")
                 .show();
            }
        }
    });

    // 控件组的值更新后联动日期输入
    $(document).on("change", "[data-widget=hsDate]", function(evt) {
        if ($(evt.target).data("toggle")=='hsDate') {
            return; // 跳过表单输入
        }
        if (! $(this).data("linked")) {
            return; // 跳过未初始化
        }

        var box = $(this);
        var inp = box.data("linked");
        var fmt = inp.data("format");
        var typ = inp.data( "type" );
        var dat = _getdate(box, new Date(0));
        var val ;

        switch (fmt) {
            case "time":
                fmt = hsGetLang("time.format");
                break;
            case "date":
                fmt = hsGetLang("date.format");
                break;
            case "datetime":
                fmt = hsGetLang("datetime.format");
                break;
            default : if (! fmt)
                fmt = hsGetLang("datetime.format");
        }

        switch (typ) {
            case "time":
                val = dat.getTime();
                break;
            case "timestamp":
                val = dat.getTime() / 1000;
                break;
            default:
                val = hsFmtDate(dat , fmt);
        }

        var evt = $.Event("change", {"date": dat});
        inp.val    (val);
        inp.trigger(evt);
    });

    // 表单项的值更改后联动日期控件
    $(document).on("change", "[data-toggle=hsDate]", function(evt) {
        if ($(evt.target).data("toggle")!='hsDate') {
            return; // 跳过非表单项
        }
        if (! $(this).data("linked")) {
            return; // 跳过未初始化
        }

        var inp = $(this);
        var box = inp.data("linked");
        var fmt = inp.data("format");
        var typ = inp.data( "type" );
        var val = inp.val (   );
        var num = parseInt(val);

        switch (fmt) {
            case "time":
                fmt = hsGetLang("time.format");
                break;
            case "date":
                fmt = hsGetLang("date.format");
                break;
            case "datetime":
                fmt = hsGetLang("datetime.format");
            default : if (! fmt)
                fmt = hsGetLang("datetime.format");
        }

        /**
         * 根据 type 确定精度
         * 缺失则将选项置为空
         */
        if (!isNaN(num)
        && (typ == "timestamp"
        ||  typ == "datestamp")) {
            val =  num * 1000  ;
        }
        if (! val ) {
            box.find( "select" )
               .val ( "" );
            inp.val ( "" );
            return;
        }

        _setdate(box, hsPrsDate(val, fmt));
    });

    // 清除已选中的
    $(document).on("click", ".datebox .clear", function() {
        $(this).closest(".datebox").find("select").val("");
    });

    // 加载就绪后自动初始化日期控件
    $(document).on("hsReady", function() {
        $(this).find("[data-toggle=hsDate]").each(function() {
            $(this).hsDate();
        });
        $(this).find("[data-toggle=hsTime]").each(function() {
            $(this).hsTime();
        });
    });

})(jQuery);
<commit_msg>为简单日历控件增加清空方法<commit_after>/**
 * 日期选择组添加方法:
 * <input type="text" name="xtime" data-toggle="hsDate" data-type="timestamp" data-fl="v || new Date().getTime() / 1000"/>
 * 可包裹在输入框组内,
 * 此输入框将被替换掉.
 *
 * 注: 2017/06/22 增加简单日期选择控件
 */

(function($) {

    function _addzero(num, len) {
        num = num ? num : "";
        num = num.toString();
        var gth = num.length;
        for (var i = gth; i < len; i ++) {
            num = "0" + num ;
        }
        return num;
    }

    function _setdate(box, dat) {
        box.find("[data-date]").each(function() {
            var flg = $( this ).data( "date" );
            switch (flg) {
                case 'La':
                case 'Sa':
                    $(this).val(dat.getHours() > 11 ? 1 : 0);
                    break;
                case 'LM':
                case 'SM':
                    $(this).val(dat.getMonth());
                    break;
                case 'M':
                    $(this).val(dat.getMonth() + 1);
                    break;
                case 'y':
                    $(this).val(dat.getFullYear() );
                    break;
                case 'Sy':
                    $(this).val(dat.getFullYear() - 2000);
                    break;
                case 'd':
                    $(this).val(dat.getDate( ));
                    break;
                case 'H':
                    $(this).val(dat.getHours());
                    break;
                case 'k':
                    $(this).val(dat.getHours() + 1 );
                    break;
                case 'K':
                    $(this).val(dat.getHours() % 12);
                    break;
                case 'h':
                    $(this).val(dat.getHours() % 12) + 1;
                    break;
                case 'm':
                    $(this).val(dat.getMinutes());
                    break;
                case 's':
                    $(this).val(dat.getSeconds());
                    break;
                case 'S':
                    $(this).val(dat.getMilliseconds());
                    break;
            }
        });
        return dat;
    }

    function _getdate(box, dat) {
        var pm = box.find("[data-date=La],[data-date=Sa]").val() == '1';
        box.find("[data-date]").each(function() {
            var flg = $( this ).data( "date" );
            var val = parseInt($(this).val( ));
            // 值被清空时则自动选中第一个日历项
            if (isNaN( val )) {
                var opt;
                opt = $(this).children().eq(0);
                val = parseInt(opt.val());
                opt.prop("selected",true);
            }
            switch (flg) {
                case 'LM':
                case 'SM':
                    dat.setMonth(val);
                    break;
                case 'M':
                    dat.setMonth(val - 1);
                    break;
                case 'y':
                    dat.setFullYear(val);
                    break;
                case 'Sy':
                    dat.setFullYear(val + 2000);
                    break;
                case 'd':
                    dat.setDate(val);
                    break;
                case 'H':
                    dat.setHours(val);
                    break;
                case 'k':
                    dat.setHours(val - 1);
                    break;
                case 'K':
                    dat.setHours(val + (pm ? 12 : 0));
                    break;
                case 'h':
                    dat.setHours(val + (pm ? 11 :-1));
                    break;
                case 'm':
                    dat.setMinutes(val);
                    break;
                case 's':
                    dat.setSeconds(val);
                    break;
                case 'S':
                    dat.setMilliseconds(val);
                    break;
            }
        });
        return dat;
    };

    function _makeGroups(grp) {
        var len = grp.length;
        var flg = grp.substring(0, 1);
        switch (flg) {
            case 'a':
                if (len >= 4) {
                    return _makeChoose("La", hsGetLang("date.La"));
                }
                else {
                    return _makeChoose("Sa", hsGetLang("date.Sa"));
                }
            case 'M':
                if (len >= 4) {
                    return _makeChoose("LM", hsGetLang("date.LM"));
                }
                if (len == 3) {
                    return _makeChoose("SM", hsGetLang("date.SM"));
                }
                else {
                    return _makeSelect( "M", 1, 12, len);
                }
            case 'y':
                if (len >= 4) {
                    return _makeSelect( "y", 1970, 2099, len);
                }
                else {
                    return _makeSelect("Sy", 0, 99, len);
                }
            case 'd':
                return _makeSelect(flg, 1, 31, len);
            case 'H':
                return _makeSelect(flg, 0, 23, len);
            case 'k':
                return _makeSelect(flg, 1, 24, len);
            case 'K':
                return _makeSelect(flg, 0, 11, len);
            case 'h':
                return _makeSelect(flg, 1, 12, len);
            case 'm':
                return _makeSelect(flg, 0, 59, len);
            case 's':
                return _makeSelect(flg, 0, 59, len);
            case 'S':
                return _makeSelect(flg, 0,999, len);
        }
    }

    function _makeChoose(flg, arr) {
        var s = '<select class="form-control datebox-'+flg+'" data-date="'+flg+'">';
        for(var j = arr.length, i = 0; i < j; i ++) {
            var v = arr[i];
            s += '<option value="'+ i +'">'+ v +'</option>';
        }
        s += '</select>';
        return $(s);
    }

    function _makeSelect(flg, min, max, len) {
        var s = '<select class="form-control datebox-'+flg+'" data-date="'+flg+'">';
        for(  ; min <= max  ; min ++  ) {
            var v  = _addzero(min, len);
            s += '<option value="'+min+'">'+ v +'</option>';
        }
        s += '</select>';
        return $(s);
    }

    function _makeAddons(txt) {
        var spn = $('');
        spn.text ( txt );
        return spn ;
    }

    function _makeInputs(fmt) {
        var box = $('

');
        var pat = /([MdyHkKhmsSa]+|[^MdyHkKhmsSa']+|'.*?')/g;
        var wrd = /^[MdyHkKhmsSa]+$/;
        var grp ;
        while ((grp = pat.exec(fmt))!= null) {
            grp = grp[0];
            if (wrd.test(grp)) {
                box.append(_makeGroups(grp));
            } else {
                box.append(_makeAddons(grp));
            }
        }
        box.append(_makeAddons("").css("width", "100%")); // 占位撑长
        return box;
    }

    /**
     * 日期时间选择, 用下拉列表构建
     */
    $.fn.hsDate = function() {
        if (this.data("linked")) {
            return; // 跳过已初始化
        }

        var fmt = this.data("format") || hsGetLang("datetime.format");
        var inp = this;
        var box ;

        do {
            /**
             * 如果有查找到组件标记
             * 说明用的是自定义选项
             * 就不需要再构建选项了
             */
            box = inp.siblings().filter("[data-widget=hsDate]");
            if (box.size() != 0) {
                break;
            }
            box = inp.parent(  ).filter("[data-widget=hsDate]");
            if (box.size() != 0) {
                break;
            }

            // 也可以指定对象的类型
            // 从当前语言配置中提取
            switch (fmt) {
                case "time":
                    fmt = hsGetLang("time.format");
                    break;
                case "date":
                    fmt = hsGetLang("date.format");
                    break;
                case "datetime" : case "" : case null :
                    fmt = hsGetLang("datetime.format");
            }

            inp.addClass("invisible");
            box = _makeInputs ( fmt );
            box.insertBefore  ( inp );

            /**
             * 非必填需增加取消按钮
             */
            if (!inp.attr("required")
            &&  !inp.data("required")) {
                box.find('.input-group-addon')
                   .last()
                   .css ("text-align","right")
                   .html('');
            }

            /**
             * 输入框组是不可嵌套的
             * 如果已经在输入框组里
             * 需要把选项向上提一层
             */
            if (inp.parent().is(".input-group")) {
                inp.before(box.contents());
                box.remove();
                box = inp.parent( );
                box.addClass ( "datebox" );
            }
        }
        while (false);

        box.addClass("datebox");
        box.attr("data-widget" , "hsDate");
        box.data("linked", inp);
        inp.attr("data-toggle" , "hsDate");
        inp.data("linked", box);

        inp.trigger ("change" );
    };

    /**
     * 日期时间输入, 用原生控件构建
     */
    $.fn.hsTime = function() {
        if (this.data("linked")) {
            return; // 跳过已初始化
        }

        var hide = $('<input type="hidden" class="form-ignored"/>');
        var type = this.attr("type"   );
        var kind = this.data("type"   );
        var frmt = this.data("format" );
        var patt = this.attr("pattern");
        var that = this;

        // 没指定则按类型的标准处理
        if (!frmt || !patt) {
            if (type == "time") {
                frmt = "HH:mm" ;
                patt = "\d{1,2}:\d{1,2}" ;
            } else
            if (type == "date") {
                frmt = "yyyy-MM-dd";
                patt = "\d{2,4}-\d{1,2}-\d{1,2}";
            } else
            {
                frmt = "yyyy-MM-ddTHH:mm";
                patt = "\d{2,4}-\d{1,2}-\d{1,2}T\d{1,2}:\d{1,2}";
            }
            this.data("format" , frmt);
            this.attr("pattern", patt);
        }

        hide.attr("name", this.attr("name"));
        this.attr("name", "" );
        this.data("linked", hide);
        hide.data("linked", this);
        this.after(hide);

        // 互相联动
        hide.on("change", function() {
            var v = $(this).val();
            if (v == "") {
                that.val("");
                return ;
            }

            var d = hsFmtDate(v, frmt);
            that.val(d);
        });
        this.on("change", function() {
            var v = $(this).val();
            if (v == "") {
                hide.val("");
                return ;
            }

            // 解析失败设为空
            var d = hsPrsDate(v, frmt);
            d = d.getTime( );
            if (isNaN(d)
            ||  0 === d) {
                hide.val("");
                return ;
            }

            // 可选择精确到秒
            if (kind == "timestamp"
            ||  kind == "datestamp") {
                d = Math.round(d/1000);
            }

            hide.val(d);
        });
    };

    // 处理大小月及闰年时日期的变化
    $(document).on("change", "[data-date=M],[data-date=SM],[data-date=LM]", function() {
        var y = $(this).closest(".input-group")
                .find("[data-date=y],[data-date=Sy]").val();
        var d = $(this).closest(".input-group")
                .find("[data-date=d]");
        var m = $(this).val( );
        if (y < 100) y += 2000;
        if (m == 2) {
            if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) {
                d.find("option:gt(28)")
                 .prop("selected", false)
                 .hide();
            } else {
                d.find("option:gt(27)")
                 .prop("selected", false)
                 .hide();
            }
        } else {
            if ((m < 7 && m % 2 == 0) || (m > 7 && m % 2 == 1)) {
                d.find("option:gt(29)")
                 .prop("selected", false)
                 .hide();
            } else {
                d.find("option:gt(27)")
                 .show();
            }
        }
    });

    // 控件组的值更新后联动日期输入
    $(document).on("change", "[data-widget=hsDate]", function(evt) {
        if ($(evt.target).data("toggle")=='hsDate') {
            return; // 跳过表单输入
        }
        if (! $(this).data("linked")) {
            return; // 跳过未初始化
        }

        var box = $(this);
        var inp = box.data("linked");
        var fmt = inp.data("format");
        var typ = inp.data( "type" );
        var dat = _getdate(box, new Date(0));
        var val ;

        switch (fmt) {
            case "time":
                fmt = hsGetLang("time.format");
                break;
            case "date":
                fmt = hsGetLang("date.format");
                break;
            case "datetime":
                fmt = hsGetLang("datetime.format");
                break;
            default : if (! fmt)
                fmt = hsGetLang("datetime.format");
        }

        switch (typ) {
            case "time":
                val = dat.getTime();
                break;
            case "timestamp":
                val = dat.getTime() / 1000;
                break;
            default:
                val = hsFmtDate(dat , fmt);
        }

        var evt = $.Event("change", {"date": dat});
        inp.val    (val);
        inp.trigger(evt);
    });

    // 表单项的值更改后联动日期控件
    $(document).on("change", "[data-toggle=hsDate]", function(evt) {
        if ($(evt.target).data("toggle")!='hsDate') {
            return; // 跳过非表单项
        }
        if (! $(this).data("linked")) {
            return; // 跳过未初始化
        }

        var inp = $(this);
        var box = inp.data("linked");
        var fmt = inp.data("format");
        var typ = inp.data( "type" );
        var val = inp.val (   );
        var num = parseInt(val);

        switch (fmt) {
            case "time":
                fmt = hsGetLang("time.format");
                break;
            case "date":
                fmt = hsGetLang("date.format");
                break;
            case "datetime":
                fmt = hsGetLang("datetime.format");
            default : if (! fmt)
                fmt = hsGetLang("datetime.format");
        }

        /**
         * 根据 type 确定精度
         * 缺失则将选项置为空
         */
        if (!isNaN(num)
        && (typ == "timestamp"
        ||  typ == "datestamp")) {
            val =  num * 1000  ;
        }
        if (! val ) {
            box.find( "select" )
               .val ( "" );
            inp.val ( "" );
            return;
        }

        _setdate(box, hsPrsDate(val, fmt));
    });

    // 清除已选中的
    $(document).on("click", ".datebox .clear", function() {
        $(this).closest(".datebox").find("select").val("");
    });

    // 加载就绪后自动初始化日期控件
    $(document).on("hsReady", function() {
        $(this).find("[data-toggle=hsDate]").each(function() {
            $(this).hsDate();
        });
        $(this).find("[data-toggle=hsTime]").each(function() {
            $(this).hsTime();
        });
    });

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

const storageManager = require('./../StorageManager'),
    ResponseHeader = require('./../model/ResponseHeader'),
    BlobTypes = require('./../Constants').BlobTypes,
    Blob = require('./../model/Blob');

class PutAppendBlock {
    constructor() {
    }

    process(req, res, containerName, blobName, body) {
        const blob = new Blob(blobName, req.headers, BlobTypes.AppendBlob);
        return storageManager.putAppendBlock(containerName, blob, body)
            .then((response) => {
                response['x-ms-request-server-encrypted'] = false;
                res.set(new ResponseHeader(response));
                res.status(201).send('Created');
            })
            .catch((e) => {
                res.status(e.statusCode || 500).send(e.message);
                if (!e.statusCode) throw e;
            });
    }
}

module.exports = new PutAppendBlock();<commit_msg>removed http return message<commit_after>'use strict';

const storageManager = require('./../StorageManager'),
    ResponseHeader = require('./../model/ResponseHeader'),
    BlobTypes = require('./../Constants').BlobTypes,
    Blob = require('./../model/Blob');

class PutAppendBlock {
    constructor() {
    }

    process(req, res, containerName, blobName, body) {
        const blob = new Blob(blobName, req.headers, BlobTypes.AppendBlob);
        return storageManager.putAppendBlock(containerName, blob, body)
            .then((response) => {
                response['x-ms-request-server-encrypted'] = false;
                res.set(new ResponseHeader(response));
                res.status(201).send();
            })
            .catch((e) => {
                res.status(e.statusCode || 500).send(e.message);
                if (!e.statusCode) throw e;
            });
    }
}

module.exports = new PutAppendBlock();<|endoftext|>