<commit_before>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, continue: true */
/*global require, exports */

(function () {
    "use strict";

    var async = require("async");
    var process_runner = require("./process_runner.js");
    var config = require("./config.js");
    var utils = require("./utils.js");
    var fs = require("fs");
    var os = require("os");

    var formatTempOutput = function (temp) {

        temp = temp / 1000;
        var out = {};

        if (!config.USE_CELCIUS) {
            temp = utils.celsiusToFarenheit(temp);
        }

        temp = Math.ceil(temp);

        out.cpuTemp = temp;
        out.tempScale = (config.USE_CELCIUS) ? "celcius" : "farenheit";

        return out;
    };

	var getCPUTemp = function (callback) {

        var out = {};
		var tmp;
		if (config.TEST) {
			tmp = 54072;

            out = formatTempOutput(tmp);
            callback(null, out);
			return;
		}

		fs.readFile("sys/class/thermal/thermal_zone0/temp", {encoding: "ascii"},
			function (err, data) {
				if (err) {
					callback(err);
					return;
                }

                //todo: this is wrong
				tmp = parseInt(data, 10); //convert to number
                out = formatTempOutput(tmp);

				callback(null, out);
			});

		//trip point
		//trip_point_0_temp

	};

	var getGPUTemp = function (callback) {
	};

    var restartUDHCPD = function (callback) {
        //service udhcpd restart 2>&1 >/dev/null
        process_runner.exec("service", ["udhcpd", "restart"], callback);
    };

    var restartAPD = function (callback) {
        //service hostapd restart 2>&1 >/dev/null
        process_runner.exec("service", ["hostapd", "restart"], callback);
    };

    var loadAPConfTemplate = function (callback) {
        fs.readFile(config.HOSTAPD_CONF_TEMPLATE_PATH, {encoding: "utf8"}, callback);
    };

    var createAPConf = function (ssid, template) {
        var out = template.replace(/\{\{SSID\}\}/g, ssid);
        return out;
    };

    var writeAPConfTemplate = function (data, callback) {
        fs.writeFile(config.HOSTAPD_CONF_PATH, data, callback);
    };

    //todo: we may want to cache the results of this, so we dont have to read a file
    //everytime this api is called. Might not be a big deal though, since there should only ever be
    //one person accessing the site
    var readRestrictedAccessList = function (callback) {
        fs.readFile(config.HOSTAPD_RESTRICTED_ADDRESSES_PATH,
                    {encoding: "utf8"},
            function (err, data) {
                var addresses = data.split(os.EOL);
                callback(null, addresses);
            }
            );
    };

    var saveRestrictedAccessList = function (addresses, callback) {
        var tmp = addresses.join(os.EOL);
        fs.writeFile(config.HOSTAPD_RESTRICTED_ADDRESSES_PATH, tmp, callback);
    };

    var updateRestrictedAccessList = function (addresses, callback) {
        //todo: confirm whether we need to restart service after updating access list
        async.series(
            [
                function (callback) {saveRestrictedAccessList(addresses, callback); },
                restartAPD
            ],
            function (err, out) {
                if (err) {
                    callback(err);
                    return;
                }
                callback(null, out);
            }
        );
    };

    var formatAsyncOutput = function (arr) {

        if (!arr) {
            return;
        }

        var out = [];

        var len = arr.length;

        var tmp, i;
        for (i = 0; i < len; i++) {
            tmp = arr[i];

            if (!tmp) {
                continue;
            }

            out.push(tmp.trim());
        }

        return out.join(os.EOL);
    };

    var updateAPConf = function (ssid, callback) {

        var _generateAPConf = function (data, callback) {
            var conf = createAPConf(ssid, data);
            callback(null, conf);
        };

        //todo: do we need to restart restartUDHCPD (it is slow)
        async.waterfall(
            [
                loadAPConfTemplate,
                _generateAPConf,
                writeAPConfTemplate
            ],
            function (err, out) {
                out = formatAsyncOutput(out);

                //note: if not an error, err will be null
                callback(err, out);
            }
        );
    };

    var updateAccessPoint = function (ssid, address, callback) {

        if (!utils.isValidMacAddress(address)) {
            callback("Invalid mac address");
            return;
        }

        if (!ssid || !ssid.length) {
            callback("Invalid SSID.");
            return;
        }

        //note, the arguments are not passed on the shell, so we don't have to worry
        //about injection (although the script being called does)
        //http://stackoverflow.com/questions/15168071/how-secure-is-using-execfile-for-bash-scripts
        async.series(
            [
                function (callback) {process_runner.exec("ifconfig", [config.ACCESS_POINT_INTERFACE, "down"], callback); },
                function (callback) {process_runner.exec("ifconfig", [config.ACCESS_POINT_INTERFACE, "hw", "ether", address], callback); },
                function (callback) {process_runner.exec("ifconfig", [config.ACCESS_POINT_INTERFACE, "up"], callback); },
                function (callback) {updateAPConf(ssid, callback); },
                restartAPD//,
                //restartUDHCPD

            ],
            function (err, out) {
                out = formatAsyncOutput(out);

                //note: if not an error, err will be null
                callback(err, out);
            }
        );
    };

    exports.getCPUTemp = getCPUTemp;
    exports.updateAccessPoint = updateAccessPoint;
}());<commit_msg>adding some error and debug info<commit_after>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, continue: true */
/*global require, exports */

(function () {
    "use strict";

    var async = require("async");
    var process_runner = require("./process_runner.js");
    var config = require("./config.js");
    var utils = require("./utils.js");
    var fs = require("fs");
    var os = require("os");
    var winston = require("./logger").winston;

    var formatTempOutput = function (temp) {

        temp = temp / 1000;
        var out = {};

        if (!config.USE_CELCIUS) {
            temp = utils.celsiusToFarenheit(temp);
        }

        temp = Math.ceil(temp);

        out.cpuTemp = temp;
        out.tempScale = (config.USE_CELCIUS) ? "celcius" : "farenheit";

        return out;
    };

	var getCPUTemp = function (callback) {

        var out = {};
		var tmp;
		if (config.TEST) {
			tmp = 54072;

            out = formatTempOutput(tmp);
            callback(null, out);
			return;
		}

		fs.readFile("sys/class/thermal/thermal_zone0/temp", {encoding: "ascii"},
			function (err, data) {
				if (err) {
                    winston.error("Error Reading System Temp");
					callback(err);
					return;
                }

                winston.info(data);

                //todo: this is wrong
				tmp = parseInt(data, 10); //convert to number
                out = formatTempOutput(tmp);

				callback(null, out);
			});

		//trip point
		//trip_point_0_temp

	};

	var getGPUTemp = function (callback) {
	};

    var restartUDHCPD = function (callback) {
        //service udhcpd restart 2>&1 >/dev/null
        process_runner.exec("service", ["udhcpd", "restart"], callback);
    };

    var restartAPD = function (callback) {
        //service hostapd restart 2>&1 >/dev/null
        process_runner.exec("service", ["hostapd", "restart"], callback);
    };

    var loadAPConfTemplate = function (callback) {
        fs.readFile(config.HOSTAPD_CONF_TEMPLATE_PATH, {encoding: "utf8"}, callback);
    };

    var createAPConf = function (ssid, template) {
        var out = template.replace(/\{\{SSID\}\}/g, ssid);
        return out;
    };

    var writeAPConfTemplate = function (data, callback) {
        fs.writeFile(config.HOSTAPD_CONF_PATH, data, callback);
    };

    //todo: we may want to cache the results of this, so we dont have to read a file
    //everytime this api is called. Might not be a big deal though, since there should only ever be
    //one person accessing the site
    var readRestrictedAccessList = function (callback) {
        fs.readFile(config.HOSTAPD_RESTRICTED_ADDRESSES_PATH,
                    {encoding: "utf8"},
            function (err, data) {
                var addresses = data.split(os.EOL);
                callback(null, addresses);
            }
            );
    };

    var saveRestrictedAccessList = function (addresses, callback) {
        var tmp = addresses.join(os.EOL);
        fs.writeFile(config.HOSTAPD_RESTRICTED_ADDRESSES_PATH, tmp, callback);
    };

    var updateRestrictedAccessList = function (addresses, callback) {
        //todo: confirm whether we need to restart service after updating access list
        async.series(
            [
                function (callback) {saveRestrictedAccessList(addresses, callback); },
                restartAPD
            ],
            function (err, out) {
                if (err) {
                    callback(err);
                    return;
                }
                callback(null, out);
            }
        );
    };

    var formatAsyncOutput = function (arr) {

        if (!arr) {
            return;
        }

        var out = [];

        var len = arr.length;

        var tmp, i;
        for (i = 0; i < len; i++) {
            tmp = arr[i];

            if (!tmp) {
                continue;
            }

            out.push(tmp.trim());
        }

        return out.join(os.EOL);
    };

    var updateAPConf = function (ssid, callback) {

        var _generateAPConf = function (data, callback) {
            var conf = createAPConf(ssid, data);
            callback(null, conf);
        };

        //todo: do we need to restart restartUDHCPD (it is slow)
        async.waterfall(
            [
                loadAPConfTemplate,
                _generateAPConf,
                writeAPConfTemplate
            ],
            function (err, out) {
                out = formatAsyncOutput(out);

                //note: if not an error, err will be null
                callback(err, out);
            }
        );
    };

    var updateAccessPoint = function (ssid, address, callback) {

        if (!utils.isValidMacAddress(address)) {
            callback("Invalid mac address");
            return;
        }

        if (!ssid || !ssid.length) {
            callback("Invalid SSID.");
            return;
        }

        //note, the arguments are not passed on the shell, so we don't have to worry
        //about injection (although the script being called does)
        //http://stackoverflow.com/questions/15168071/how-secure-is-using-execfile-for-bash-scripts
        async.series(
            [
                function (callback) {process_runner.exec("ifconfig", [config.ACCESS_POINT_INTERFACE, "down"], callback); },
                function (callback) {process_runner.exec("ifconfig", [config.ACCESS_POINT_INTERFACE, "hw", "ether", address], callback); },
                function (callback) {process_runner.exec("ifconfig", [config.ACCESS_POINT_INTERFACE, "up"], callback); },
                function (callback) {updateAPConf(ssid, callback); },
                restartAPD//,
                //restartUDHCPD

            ],
            function (err, out) {
                out = formatAsyncOutput(out);

                //note: if not an error, err will be null
                callback(err, out);
            }
        );
    };

    exports.getCPUTemp = getCPUTemp;
    exports.updateAccessPoint = updateAccessPoint;
}());<|endoftext|>


<commit_before>/*
   Copyright 2010 Dmitriy Khudorozhkov. All rights reserved.

   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.
*/

var barlesque = {

	// Shortcuts:
	Cc: Components.classes,
	Ci: Components.interfaces,

	// Preference branch for the extension:
	branch: null,

	// Preference listener:
	prefListener: null,

	// Initialization:
	init: function()
	{
		// Initialize preferences:
		var prefservice = this.Cc["@mozilla.org/preferences-service;1"].getService(this.Ci.nsIPrefService);
		this.branch = prefservice.getBranch("extensions.barlesque.");

		// Correct the preferences:
		if(!this.branch.getBoolPref("persist"))
		{
			this.branch.setBoolPref("collapsed", false);
		}

		// Initialize preference change listener:
		this.initPrefListener();

		// Initialize the keyboard shortcuts:
		this.rekeyHide();
		this.rekeyMove();

		// Update the gFindBar open and close methods:
		var methodstr = gFindBar.open.toString();
		if(methodstr.indexOf("barlesque") == -1)
		{
			methodstr = methodstr.substr(methodstr.indexOf("{") + 1);
			methodstr = "function(aMode) { document.getElementById('addon-bar').hidden = true; if(barlesque) { window.removeEventListener('resize', barlesque.doReset, false); barlesque.removeStyles(); } " + methodstr;

			new Function("gFindBar.open = " + methodstr)();
		}

		methodstr = gFindBar.close.toString();
		if(methodstr.indexOf("barlesque") == -1)
		{
			methodstr = methodstr.substring(0, methodstr.lastIndexOf("}") - 1);
			methodstr += "document.getElementById('addon-bar').hidden = false; if(barlesque) { barlesque.resetStyles(); window.addEventListener('resize', barlesque.doReset, false); } }";

			new Function("gFindBar.close = " + methodstr)();
		}

		// Update the onViewToolbarCommand method:
		methodstr = onViewToolbarCommand.toString();
		if(methodstr.indexOf("barlesque") == -1)
		{
			methodstr = methodstr.substring(0, methodstr.lastIndexOf("}") - 1);
			methodstr += "if(toolbarId == 'addon-bar') { if(barlesque) { barlesque.resetStyles(); } } }";

			new Function("onViewToolbarCommand = " + methodstr)();
		}

		// Initialize page load event:
		window.addEventListener("DOMContentLoaded", this.doReset, false);

		// Initialize resize event, deferred to reduce browser startup time:
		var self = this;
		setTimeout(function()
		{
			window.addEventListener("resize", self.doReset, false);
		},
		250);

		// Initialize tab selection event:
		gBrowser.tabContainer.addEventListener("TabSelect", this.doReset, false);

		// First round of style change:
		this.doReset();
	},

	// Startup of preference listener:
	initPrefListener: function()
	{
		var self = this;

		// Listener object:
		function prefChangedListener(branch, callback)
		{
			branch.QueryInterface(self.Ci.nsIPrefBranch2);
			branch.addObserver("", this, false);

			this.observe = function(subject, topic, data)
			{
				// Only track change events:
				if(topic == "nsPref:changed")
				{
					callback(branch, data);
				}
			};

			this.unregister = function()
			{
				if(branch)
				{
					branch.removeObserver("", this);
				}
			};
		}

		// Listener callback:
		function listenerCallback(branch, name)
		{
			switch(name)
			{
				case "mode":
					self.resetStyles();
					break;

				case "shorthide.key":
				case "shorthide.mod":
					self.rekeyHide();
					break;

				case "shortmove.key":
				case "shortmove.mod":
					self.rekeyMove();
					break;
			}
		}

		// Initialize:
		this.prefListener = new prefChangedListener(this.branch, listenerCallback);
	},

	// Shutdown:
	uninit: function()
	{
		this.prefListener.unregister();

		window.removeEventListener("DOMContentLoaded", this.doReset, false);
		window.removeEventListener("resize", this.doReset, false);

		gBrowser.tabContainer.removeEventListener("TabSelect", this.doReset, false);
	},

	// Wrapper for bottom bar style reset:
	doReset: function(event)
	{
		if(event && (event.type == "DOMContentLoaded"))
		{
			// Top-level document only:
			var doc = event.target;

			if(doc == gBrowser.selectedTab.linkedBrowser.contentDocument)
			{
				if(gFindBar.hidden)
				{
					barlesque.resetStyles();
				}
			}
		}
		else
		{
			if(gFindBar.hidden)
			{
				barlesque.resetStyles();
			}
		}
	},

	// Method that actually changes addon bar's class:
	resetStyles: function()
	{
		this.removeCollapser();

		var addonbar = document.getElementById("addon-bar");

		// Don't proceed if add-on bar is hidden:
		if(addonbar.collapsed == true)
		{
			return;
		}

		// Count the number of visible elements in add-on bar/status bar:
		var count = 0;
		var buttons = addonbar.childNodes;

		for(var i = 0, l = buttons.length; i < l; i++)
		{
			var button = buttons[i];

			if((button.tagName.toLowerCase() == "toolbarbutton") && (window.getComputedStyle(button).getPropertyValue("display") != "none"))
			{
				++count;
			}
		}

		var statusbar = document.getElementById("status-bar");

		if(statusbar)
		{
			var panels = statusbar.getElementsByTagName("statusbarpanel");

			for(i = 0, l = panels.length; i < l; i++)
			{
				var panel = panels[i];

				if((panel.className.indexOf("statusbar-resizerpanel") == -1) && (window.getComputedStyle(panel).getPropertyValue("display") != "none"))
				{
					++count;
				}
			}
		}

		// Don't proceed if there are no elements to show:
		if(count === 0)
		{
			addonbar.hidden = true;
			return;
		}

		var collapsed = this.branch.getBoolPref("collapsed");
		addonbar.hidden = collapsed;

		// Browser shortcut:
		var win = gBrowser.contentWindow;

		// Current rendering mode:
		var mode = this.branch.getBoolPref("mode");

		// Does currently shown browser have a vertical scroll bar?
		var vscroll = (win.scrollMaxY !== 0);

		// Does currently shown browser have a horizontal scroll bar?
		var hscroll = (win.scrollMaxX !== 0);

		// Current classes of bottom toolbar:
		var bottombox = document.getElementById("browser-bottombox");
		var classes = bottombox.className.length ? bottombox.className.split(" ") : [];

		// Remove old barlesque classes, if any:
		for(var i = 0; i < classes.length; i++)
		{
			if(classes[i].indexOf("barlesque-") == 0)
			{
				classes.splice(i--, 1);
			}
		}

		// New classes:
		classes.push("barlesque-bar");
		classes.push("barlesque-" + (mode ? "left" : "right"));

		if(!mode && vscroll)
		{
			classes.push("barlesque-vscroll");
		}

		if(hscroll)
		{
			classes.push("barlesque-hscroll");
		}

		if(collapsed)
		{
			classes.push("barlesque-collapsed");
		}

		// Assign new set of classes:
		bottombox.className = classes.join(" ");

		// Append the collapser:
		if(!document.getElementById("barlesque-collapser"))
		{
			let collapser = bottombox.appendChild(document.createElement("box"));
			collapser.id = "barlesque-collapser";
			collapser.setAttribute("tooltiptext", collapsed ? "Show the add-on bar" : "Collapse the add-on bar");

			// Attach event handler:
			collapser.addEventListener("click", function() { barlesque.branch.setBoolPref("collapsed", !barlesque.branch.getBoolPref("collapsed")); barlesque.resetStyles(); }, false);
		}
	},

	// Completely remove barlesque styles from bottom bar:
	removeStyles: function()
	{
		this.removeCollapser();

		// Current classes of bottom toolbar:
		var bar = document.getElementById("browser-bottombox");
		var classes = bar.className.length ? bar.className.split(" ") : [];

		// Remove old barlesque classes, if any:
		for(var i = 0; i < classes.length; i++)
		{
			if(classes[i].indexOf("barlesque-") == 0)
			{
				classes.splice(i--, 1);
			}
		}

		// Assign clean set of classes:
		bar.className = !classes.length ? "barlesque-empty-class" : classes.join(" ");
	},

	// Remove the collapser box:
	removeCollapser: function()
	{
		var collapser = document.getElementById("barlesque-collapser");
		if(collapser)
		{
			collapser.parentNode.removeChild(collapser);
		}
	},

	// Recreate shortcut elements:

	// - for add-on bar hiding/showing:
	rekeyHide: function()
	{
		var win = document.getElementById("main-window");
		var keyset = document.getElementById("barlesque-shorthide-keyset");

		if(keyset)
		{
			win.removeChild(keyset);
		}

		keyset = document.createElement("keyset");
		keyset.id = "barlesque-shorthide-keyset";
		win.appendChild(keyset);

		var shorthide = document.createElement("key");
		shorthide.id = "barlesque-shorthide";

		shorthide.setAttribute("key", this.branch.getCharPref("shorthide.key"));
		shorthide.setAttribute("modifiers", this.branch.getCharPref("shorthide.mod"));
		shorthide.setAttribute("command", "barlesque-command-shorthide");

		keyset.appendChild(shorthide);
	},

	// - for add-on bar re-aligning:
	rekeyMove: function()
	{
		var win = document.getElementById("main-window");

		var keyset = document.getElementById("barlesque-shortmove-keyset");

		if(keyset)
		{
			win.removeChild(keyset);
		}

		keyset = document.createElement("keyset");
		keyset.id = "barlesque-shortmove-keyset";
		win.appendChild(keyset);

		var shortmove = document.createElement("key");
		shortmove.id = "barlesque-shortmove";

		shortmove.setAttribute("key", this.branch.getCharPref("shortmove.key"));
		shortmove.setAttribute("modifiers", this.branch.getCharPref("shortmove.mod"));
		shortmove.setAttribute("command", "barlesque-command-shortmove");

		keyset.appendChild(shortmove);
	}
};

window.addEventListener("load",   function() { barlesque.init();   }, false);
window.addEventListener("unload", function() { barlesque.uninit(); }, false);<commit_msg>Lint.<commit_after>/*
   Copyright 2010 Dmitriy Khudorozhkov. All rights reserved.

   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.
*/

var barlesque = {

	// Shortcuts:
	Cc: Components.classes,
	Ci: Components.interfaces,

	// Preference branch for the extension:
	branch: null,

	// Preference listener:
	prefListener: null,

	// Initialization:
	init: function()
	{
		// Initialize preferences:
		var prefservice = this.Cc["@mozilla.org/preferences-service;1"].getService(this.Ci.nsIPrefService);
		this.branch = prefservice.getBranch("extensions.barlesque.");

		// Correct the preferences:
		if(!this.branch.getBoolPref("persist"))
		{
			this.branch.setBoolPref("collapsed", false);
		}

		// Initialize preference change listener:
		this.initPrefListener();

		// Initialize the keyboard shortcuts:
		this.rekeyHide();
		this.rekeyMove();

		// Update the gFindBar open and close methods:
		var methodstr = gFindBar.open.toString();
		if(methodstr.indexOf("barlesque") == -1)
		{
			methodstr = methodstr.substr(methodstr.indexOf("{") + 1);
			methodstr = "function(aMode) { document.getElementById('addon-bar').hidden = true; if(barlesque) { window.removeEventListener('resize', barlesque.doReset, false); barlesque.removeStyles(); } " + methodstr;

			new Function("gFindBar.open = " + methodstr)();
		}

		methodstr = gFindBar.close.toString();
		if(methodstr.indexOf("barlesque") == -1)
		{
			methodstr = methodstr.substring(0, methodstr.lastIndexOf("}") - 1);
			methodstr += "document.getElementById('addon-bar').hidden = false; if(barlesque) { barlesque.resetStyles(); window.addEventListener('resize', barlesque.doReset, false); } }";

			new Function("gFindBar.close = " + methodstr)();
		}

		// Update the onViewToolbarCommand method:
		methodstr = onViewToolbarCommand.toString();
		if(methodstr.indexOf("barlesque") == -1)
		{
			methodstr = methodstr.substring(0, methodstr.lastIndexOf("}") - 1);
			methodstr += "if(toolbarId == 'addon-bar') { if(barlesque) { barlesque.resetStyles(); } } }";

			new Function("onViewToolbarCommand = " + methodstr)();
		}

		// Initialize page load event:
		window.addEventListener("DOMContentLoaded", this.doReset, false);

		// Initialize resize event, deferred to reduce browser startup time:
		var self = this;
		setTimeout(function()
		{
			window.addEventListener("resize", self.doReset, false);
		},
		250);

		// Initialize tab selection event:
		gBrowser.tabContainer.addEventListener("TabSelect", this.doReset, false);

		// First round of style change:
		this.doReset();
	},

	// Startup of preference listener:
	initPrefListener: function()
	{
		var self = this;

		// Listener object:
		function prefChangedListener(branch, callback)
		{
			branch.QueryInterface(self.Ci.nsIPrefBranch2);
			branch.addObserver("", this, false);

			this.observe = function(subject, topic, data)
			{
				// Only track change events:
				if(topic == "nsPref:changed")
				{
					callback(branch, data);
				}
			};

			this.unregister = function()
			{
				if(branch)
				{
					branch.removeObserver("", this);
				}
			};
		}

		// Listener callback:
		function listenerCallback(branch, name)
		{
			switch(name)
			{
				case "mode":
					self.resetStyles();
					break;

				case "shorthide.key":
				case "shorthide.mod":
					self.rekeyHide();
					break;

				case "shortmove.key":
				case "shortmove.mod":
					self.rekeyMove();
					break;
			}
		}

		// Initialize:
		this.prefListener = new prefChangedListener(this.branch, listenerCallback);
	},

	// Shutdown:
	uninit: function()
	{
		this.prefListener.unregister();

		window.removeEventListener("DOMContentLoaded", this.doReset, false);
		window.removeEventListener("resize", this.doReset, false);

		gBrowser.tabContainer.removeEventListener("TabSelect", this.doReset, false);
	},

	// Wrapper for bottom bar style reset:
	doReset: function(event)
	{
		if(event && (event.type == "DOMContentLoaded"))
		{
			// Top-level document only:
			var doc = event.target;

			if(doc == gBrowser.selectedTab.linkedBrowser.contentDocument)
			{
				if(gFindBar.hidden)
				{
					barlesque.resetStyles();
				}
			}
		}
		else
		{
			if(gFindBar.hidden)
			{
				barlesque.resetStyles();
			}
		}
	},

	// Method that actually changes addon bar's class:
	resetStyles: function()
	{
		this.removeCollapser();

		var addonbar = document.getElementById("addon-bar");

		// Don't proceed if add-on bar is hidden:
		if(addonbar.collapsed === true)
		{
			return;
		}

		// Count the number of visible elements in add-on bar/status bar:
		var count = 0;
		var buttons = addonbar.childNodes;

		for(var i = 0, l = buttons.length; i < l; i++)
		{
			var button = buttons[i];

			if((button.tagName.toLowerCase() == "toolbarbutton") && (window.getComputedStyle(button).getPropertyValue("display") != "none"))
			{
				++count;
			}
		}

		var statusbar = document.getElementById("status-bar");

		if(statusbar)
		{
			var panels = statusbar.getElementsByTagName("statusbarpanel");

			for(i = 0, l = panels.length; i < l; i++)
			{
				var panel = panels[i];

				if((panel.className.indexOf("statusbar-resizerpanel") == -1) && (window.getComputedStyle(panel).getPropertyValue("display") != "none"))
				{
					++count;
				}
			}
		}

		// Don't proceed if there are no elements to show:
		if(count === 0)
		{
			addonbar.hidden = true;
			return;
		}

		var collapsed = this.branch.getBoolPref("collapsed");
		addonbar.hidden = collapsed;

		// Browser shortcut:
		var win = gBrowser.contentWindow;

		// Current rendering mode:
		var mode = this.branch.getBoolPref("mode");

		// Does currently shown browser have a vertical scroll bar?
		var vscroll = (win.scrollMaxY !== 0);

		// Does currently shown browser have a horizontal scroll bar?
		var hscroll = (win.scrollMaxX !== 0);

		// Current classes of bottom toolbar:
		var bottombox = document.getElementById("browser-bottombox");
		var classes = bottombox.className.length ? bottombox.className.split(" ") : [];

		// Remove old barlesque classes, if any:
		for(i = 0; i < classes.length; i++)
		{
			if(classes[i].indexOf("barlesque-") === 0)
			{
				classes.splice(i--, 1);
			}
		}

		// New classes:
		classes.push("barlesque-bar");
		classes.push("barlesque-" + (mode ? "left" : "right"));

		if(!mode && vscroll)
		{
			classes.push("barlesque-vscroll");
		}

		if(hscroll)
		{
			classes.push("barlesque-hscroll");
		}

		if(collapsed)
		{
			classes.push("barlesque-collapsed");
		}

		// Assign new set of classes:
		bottombox.className = classes.join(" ");

		// Append the collapser:
		if(!document.getElementById("barlesque-collapser"))
		{
			var collapser = bottombox.appendChild(document.createElement("box"));
			collapser.id = "barlesque-collapser";
			collapser.setAttribute("tooltiptext", collapsed ? "Show the add-on bar" : "Collapse the add-on bar");

			// Attach event handler:
			collapser.addEventListener("click", function() { barlesque.branch.setBoolPref("collapsed", !barlesque.branch.getBoolPref("collapsed")); barlesque.resetStyles(); }, false);
		}
	},

	// Completely remove barlesque styles from bottom bar:
	removeStyles: function()
	{
		this.removeCollapser();

		// Current classes of bottom toolbar:
		var bar = document.getElementById("browser-bottombox");
		var classes = bar.className.length ? bar.className.split(" ") : [];

		// Remove old barlesque classes, if any:
		for(var i = 0; i < classes.length; i++)
		{
			if(classes[i].indexOf("barlesque-") === 0)
			{
				classes.splice(i--, 1);
			}
		}

		// Assign clean set of classes:
		bar.className = !classes.length ? "barlesque-empty-class" : classes.join(" ");
	},

	// Remove the collapser box:
	removeCollapser: function()
	{
		var collapser = document.getElementById("barlesque-collapser");
		if(collapser)
		{
			collapser.parentNode.removeChild(collapser);
		}
	},

	// Recreate shortcut elements:

	// - for add-on bar hiding/showing:
	rekeyHide: function()
	{
		var win = document.getElementById("main-window");
		var keyset = document.getElementById("barlesque-shorthide-keyset");

		if(keyset)
		{
			win.removeChild(keyset);
		}

		keyset = document.createElement("keyset");
		keyset.id = "barlesque-shorthide-keyset";
		win.appendChild(keyset);

		var shorthide = document.createElement("key");
		shorthide.id = "barlesque-shorthide";

		shorthide.setAttribute("key", this.branch.getCharPref("shorthide.key"));
		shorthide.setAttribute("modifiers", this.branch.getCharPref("shorthide.mod"));
		shorthide.setAttribute("command", "barlesque-command-shorthide");

		keyset.appendChild(shorthide);
	},

	// - for add-on bar re-aligning:
	rekeyMove: function()
	{
		var win = document.getElementById("main-window");

		var keyset = document.getElementById("barlesque-shortmove-keyset");

		if(keyset)
		{
			win.removeChild(keyset);
		}

		keyset = document.createElement("keyset");
		keyset.id = "barlesque-shortmove-keyset";
		win.appendChild(keyset);

		var shortmove = document.createElement("key");
		shortmove.id = "barlesque-shortmove";

		shortmove.setAttribute("key", this.branch.getCharPref("shortmove.key"));
		shortmove.setAttribute("modifiers", this.branch.getCharPref("shortmove.mod"));
		shortmove.setAttribute("command", "barlesque-command-shortmove");

		keyset.appendChild(shortmove);
	}
};

window.addEventListener("load",   function() { barlesque.init();   }, false);
window.addEventListener("unload", function() { barlesque.uninit(); }, false);<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var path = require('path');
var Womb = require('child_process');
var CaptainsLog = require('captains-log');
var chalk = require('chalk');
var Sails = require('../lib/app');

/**
 * `sails debug`
 *
 * Attach the Node debugger and lift a Sails app.
 * You can then use Node inspector to debug your app as it runs.
 *
 * @stability 2
 * @see http://sailsjs.com/documentation/reference/command-line-interface/sails-debug
 */
module.exports = function(cmd) {

  var extraArgs = cmd.parent.rawArgs.slice(3);

  var log = CaptainsLog();

  // Use the app's local Sails in `node_modules` if one exists
  // But first make sure it'll work...
  var appPath = process.cwd();
  var pathToSails = path.resolve(appPath, '/node_modules/sails');
  if (!Sails.isLocalSailsValid(pathToSails, appPath)) {
    // otherwise, use the currently-running instance of Sails
    pathToSails = path.resolve(__dirname, './sails.js');
  }

  console.log();
  log.info('Running app in debug mode...');

  // Check whether node-inspector is running
  Womb.exec('ps', function(error, stdout, stderr) {

    // If not, suggest that they run it
    if (error || stderr || !stdout.toString().match(/node-inspector/)) {
      log.info('You probably want to install / run node-inspector to help with debugging!');
      log.info('https://github.com/node-inspector/node-inspector');
      console.log();
    }

    log.info(chalk.grey('( to exit, type ' + '<CTRL>+<C>' + ' )'));
    console.log();

    // Spin up child process for Sails
    Womb.spawn('node', ['--debug', pathToSails, 'lift'].concat(extraArgs), {
      stdio: 'inherit'
    });
  });

};
<commit_msg>Don't check for node-inspector anymore when running `sails debug`.<commit_after>/**
 * Module dependencies
 */

var path = require('path');
var Womb = require('child_process');
var CaptainsLog = require('captains-log');
var chalk = require('chalk');
var Sails = require('../lib/app');

/**
 * `sails debug`
 *
 * Attach the Node debugger and lift a Sails app.
 * You can then use Node inspector to debug your app as it runs.
 *
 * @stability 2
 * @see http://sailsjs.com/documentation/reference/command-line-interface/sails-debug
 */
module.exports = function(cmd) {

  var extraArgs = cmd.parent.rawArgs.slice(3);

  var log = CaptainsLog();

  // Use the app's local Sails in `node_modules` if one exists
  // But first make sure it'll work...
  var appPath = process.cwd();
  var pathToSails = path.resolve(appPath, '/node_modules/sails');
  if (!Sails.isLocalSailsValid(pathToSails, appPath)) {
    // otherwise, use the currently-running instance of Sails
    pathToSails = path.resolve(__dirname, './sails.js');
  }

  console.log();
  log.info('Running app in debug mode...');

  log.info(chalk.grey('( to exit, type ' + '<CTRL>+<C>' + ' )'));
  console.log();

  // Spin up child process for Sails
  Womb.spawn('node', ['--debug', pathToSails, 'lift'].concat(extraArgs), {
    stdio: 'inherit'
  });

};
<|endoftext|>


<commit_before>#!/usr/bin/env node
;(function() {
  'use strict';

  /** The Node filesystem, path, `zlib`, and child process modules */
  var fs = require('fs'),
      gzip = require('zlib').gzip,
      path = require('path'),
      spawn = require('child_process').spawn;

  /** The directory that is the base of the repository */
  var basePath = path.join(__dirname, '../');

  /** The directory where the Closure Compiler is located */
  var closurePath = path.join(basePath, 'vendor', 'closure-compiler', 'compiler.jar');

  /** The distribution directory */
  var distPath = path.join(basePath, 'dist');

  /** Load other modules */
  var preprocess = require(path.join(__dirname, 'pre-compile')),
      postprocess = require(path.join(__dirname, 'post-compile')),
      uglifyJS = require(path.join(basePath, 'vendor', 'uglifyjs', 'uglify-js'));

  /** Closure Compiler command-line options */
  var closureOptions = [
    '--compilation_level=ADVANCED_OPTIMIZATIONS',
    '--language_in=ECMASCRIPT5_STRICT',
    '--warning_level=QUIET'
  ];

  /*--------------------------------------------------------------------------*/

  /**
   * The exposed `minify` function minifies a given `source` and invokes the
   * `onComplete` callback when finished.
   *
   * @param {String} source The source to minify.
   * @param {String} workingName The name to give temporary files creates during the minification process.
   * @param {Function} onComplete A function called when minification has completed.
   */
  function minify(source, workingName, onComplete) {
    new Minify(source, workingName, onComplete);
  }

  /**
   * The Minify constructor used to keep state of each `minify` invocation.
   *
   * @private
   * @constructor
   * @param {String} source The source to minify.
   * @param {String} workingName The name to give temporary files creates during the minification process.
   * @param {Function} onComplete A function called when minification has completed.
   */
  function Minify(source, workingName, onComplete) {
    // create the destination directory if it doesn't exist
    if (!path.existsSync(distPath)) {
      fs.mkdirSync(distPath);
    }

    this.compiled = {};
    this.hybrid = {};
    this.uglified = {};
    this.onComplete = onComplete;
    this.source = source = preprocess(source);
    this.workingName = workingName;

    // begin the minification process
    closureCompile.call(this, source, onClosureCompile.bind(this));
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Compresses a `source` string using the Closure Compiler. Yields the
   * minified result, and any exceptions encountered, to a `callback` function.
   *
   * @private
   * @param {String} source The JavaScript source to minify.
   * @param {String} [message] The message to log.
   * @param {Function} callback The function to call once the process completes.
   */
  function closureCompile(source, message, callback) {
    // the standard error stream, standard output stream, and Closure Compiler process
    var error = '',
        output = '',
        compiler = spawn('java', ['-jar', closurePath].concat(closureOptions));

    // juggle arguments
    if (typeof message == 'function') {
      callback = message;
      message = null;
    }

    console.log(message == null
      ? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
      : message
    );

    compiler.stdout.on('data', function(data) {
      // append the data to the output stream
      output += data;
    });

    compiler.stderr.on('data', function(data) {
      // append the error message to the error stream
      error += data;
    });

    compiler.on('exit', function(status) {
      var exception = null;

      // `status` contains the process exit code
      if (status) {
        exception = new Error(error);
        exception.status = status;
      }
      callback(exception, output);
    });

    // proxy the standard input to the Closure Compiler
    compiler.stdin.end(source);
  }

  /**
   * Compresses a `source` string using UglifyJS. Yields the result to a
   * `callback` function. This function is synchronous; the `callback` is used
   * for symmetry.
   *
   * @private
   * @param {String} source The JavaScript source to minify.
   * @param {String} [message] The message to log.
   * @param {Function} callback The function to call once the process completes.
   */
  function uglify(source, message, callback) {
    var exception,
        result,
        ugly = uglifyJS.uglify;

    // juggle arguments
    if (typeof message == 'function') {
      callback = message;
      message = null;
    }

    console.log(message == null
      ? 'Compressing ' + this.workingName + ' using UglifyJS...'
      : message
    );

    try {
      result = ugly.gen_code(
        // enable unsafe transformations
        ugly.ast_squeeze_more(
          ugly.ast_squeeze(
            // munge variable and function names, excluding the special `define`
            // function exposed by AMD loaders
            ugly.ast_mangle(uglifyJS.parser.parse(source), {
              'except': ['define']
            }
        ))), {
        'ascii_only': true
      });
    } catch(e) {
      exception = e;
    }
    // lines are restricted to 500 characters for consistency with the Closure Compiler
    callback(exception, result && ugly.split_lines(result, 500));
  }

  /*--------------------------------------------------------------------------*/

  /**
   * The `closureCompile()` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {String} result The resulting minified source.
   */
  function onClosureCompile(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the post-processed Closure Compiler result and gzip it
    this.compiled.source = result = postprocess(result);
    gzip(result, onClosureGzip.bind(this));
  }

  /**
   * The Closure Compiler `gzip` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {Buffer} result The resulting gzipped source.
   */
  function onClosureGzip(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the gzipped result and report the size
    this.compiled.gzip = result;
    console.log('Done. Size: %d bytes.', result.length);

    // next, minify the source using only UglifyJS
    uglify.call(this, this.source, onUglify.bind(this));
  }

  /**
   * The `uglify()` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {String} result The resulting minified source.
   */
  function onUglify(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the post-processed Uglified result and gzip it
    this.uglified.source = result = postprocess(result);
    gzip(result, onUglifyGzip.bind(this));
  }

  /**
   * The UglifyJS `gzip` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {Buffer} result The resulting gzipped source.
   */
  function onUglifyGzip(exception, result) {
    if (exception) {
      throw exception;
    }
    var message = 'Compressing  ' + this.workingName + ' using hybrid minification...';

    // store the gzipped result and report the size
    this.uglified.gzip = result;
    console.log('Done. Size: %d bytes.', result.length);

    // next, minify the Closure Compiler minified source using UglifyJS
    uglify.call(this, this.compiled.source, message, onHybrid.bind(this));
  }

  /**
   * The hybrid `uglify()` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {String} result The resulting minified source.
   */
  function onHybrid(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the post-processed Uglified result and gzip it
    this.hybrid.source = result = postprocess(result);
    gzip(result, onHybridGzip.bind(this));
  }

  /**
   * The hybrid `gzip` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {Buffer} result The resulting gzipped source.
   */
  function onHybridGzip(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the gzipped result and report the size
    this.hybrid.gzip = result;
    console.log('Done. Size: %d bytes.', result.length);

    // finish by choosing the smallest compressed file
    onComplete.call(this);
  }

  /**
   * The callback executed after JavaScript source is minified and gzipped.
   *
   * @private
   */
  function onComplete() {
    var compiled = this.compiled,
        hybrid = this.hybrid,
        name = this.workingName,
        uglified = this.uglified;

    // save the Closure Compiled version to disk
    fs.writeFileSync(path.join(distPath, name + '.compiler.js'), compiled.source);
    fs.writeFileSync(path.join(distPath, name + '.compiler.js.gz'), compiled.gzip);

    // save the Uglified version to disk
    fs.writeFileSync(path.join(distPath, name + '.uglify.js'), uglified.source);
    fs.writeFileSync(path.join(distPath, name + '.uglify.js.gz'), uglified.gzip);

    // save the hybrid minified version to disk
    fs.writeFileSync(path.join(distPath, name + '.hybrid.js'), hybrid.source);
    fs.writeFileSync(path.join(distPath, name + '.hybrid.js.gz'), hybrid.gzip);

    // select the smallest gzipped file and use its minified counterpart as the
    // official minified release (ties go to Closure Compiler)
    var min = Math.min(compiled.gzip.length, hybrid.gzip.length, uglified.gzip.length);

    // pass the minified source to the minify instances "onComplete" callback
    this.onComplete(
      compiled.gzip.length == min
        ? compiled.source
        : uglified.gzip.length == min
          ? uglified.source
          : hybrid.source
    );
  }

  /*--------------------------------------------------------------------------*/

  // expose `minify`
  if (module != require.main) {
    module.exports = minify;
  }
  else {
    // read the JavaScript source file from the first argument if the script
    // was invoked directly (e.g. `node minify.js source.js`) and write to
    // the same file
    (function() {
      var filePath = process.argv[2],
          dirPath = path.dirname(filePath),
          source = fs.readFileSync(filePath, 'utf8'),
          workingName = path.basename(filePath, '.js') + '.min';

      minify(source, workingName, function(result) {
        fs.writeFileSync(path.join(dirPath, workingName + '.js'), result);
      });
    }());
  }
}());
<commit_msg>Switch to non-deprecated `fs.existsSync`.<commit_after>#!/usr/bin/env node
;(function() {
  'use strict';

  /** The Node filesystem, path, `zlib`, and child process modules */
  var fs = require('fs'),
      gzip = require('zlib').gzip,
      path = require('path'),
      spawn = require('child_process').spawn;

  /** The directory that is the base of the repository */
  var basePath = path.join(__dirname, '../');

  /** The directory where the Closure Compiler is located */
  var closurePath = path.join(basePath, 'vendor', 'closure-compiler', 'compiler.jar');

  /** The distribution directory */
  var distPath = path.join(basePath, 'dist');

  /** Load other modules */
  var preprocess = require(path.join(__dirname, 'pre-compile')),
      postprocess = require(path.join(__dirname, 'post-compile')),
      uglifyJS = require(path.join(basePath, 'vendor', 'uglifyjs', 'uglify-js'));

  /** Closure Compiler command-line options */
  var closureOptions = [
    '--compilation_level=ADVANCED_OPTIMIZATIONS',
    '--language_in=ECMASCRIPT5_STRICT',
    '--warning_level=QUIET'
  ];

  /*--------------------------------------------------------------------------*/

  /**
   * The exposed `minify` function minifies a given `source` and invokes the
   * `onComplete` callback when finished.
   *
   * @param {String} source The source to minify.
   * @param {String} workingName The name to give temporary files creates during the minification process.
   * @param {Function} onComplete A function called when minification has completed.
   */
  function minify(source, workingName, onComplete) {
    new Minify(source, workingName, onComplete);
  }

  /**
   * The Minify constructor used to keep state of each `minify` invocation.
   *
   * @private
   * @constructor
   * @param {String} source The source to minify.
   * @param {String} workingName The name to give temporary files creates during the minification process.
   * @param {Function} onComplete A function called when minification has completed.
   */
  function Minify(source, workingName, onComplete) {
    // create the destination directory if it doesn't exist
    if (!fs.existsSync(distPath)) {
      fs.mkdirSync(distPath);
    }

    this.compiled = {};
    this.hybrid = {};
    this.uglified = {};
    this.onComplete = onComplete;
    this.source = source = preprocess(source);
    this.workingName = workingName;

    // begin the minification process
    closureCompile.call(this, source, onClosureCompile.bind(this));
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Compresses a `source` string using the Closure Compiler. Yields the
   * minified result, and any exceptions encountered, to a `callback` function.
   *
   * @private
   * @param {String} source The JavaScript source to minify.
   * @param {String} [message] The message to log.
   * @param {Function} callback The function to call once the process completes.
   */
  function closureCompile(source, message, callback) {
    // the standard error stream, standard output stream, and Closure Compiler process
    var error = '',
        output = '',
        compiler = spawn('java', ['-jar', closurePath].concat(closureOptions));

    // juggle arguments
    if (typeof message == 'function') {
      callback = message;
      message = null;
    }

    console.log(message == null
      ? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
      : message
    );

    compiler.stdout.on('data', function(data) {
      // append the data to the output stream
      output += data;
    });

    compiler.stderr.on('data', function(data) {
      // append the error message to the error stream
      error += data;
    });

    compiler.on('exit', function(status) {
      var exception = null;

      // `status` contains the process exit code
      if (status) {
        exception = new Error(error);
        exception.status = status;
      }
      callback(exception, output);
    });

    // proxy the standard input to the Closure Compiler
    compiler.stdin.end(source);
  }

  /**
   * Compresses a `source` string using UglifyJS. Yields the result to a
   * `callback` function. This function is synchronous; the `callback` is used
   * for symmetry.
   *
   * @private
   * @param {String} source The JavaScript source to minify.
   * @param {String} [message] The message to log.
   * @param {Function} callback The function to call once the process completes.
   */
  function uglify(source, message, callback) {
    var exception,
        result,
        ugly = uglifyJS.uglify;

    // juggle arguments
    if (typeof message == 'function') {
      callback = message;
      message = null;
    }

    console.log(message == null
      ? 'Compressing ' + this.workingName + ' using UglifyJS...'
      : message
    );

    try {
      result = ugly.gen_code(
        // enable unsafe transformations
        ugly.ast_squeeze_more(
          ugly.ast_squeeze(
            // munge variable and function names, excluding the special `define`
            // function exposed by AMD loaders
            ugly.ast_mangle(uglifyJS.parser.parse(source), {
              'except': ['define']
            }
        ))), {
        'ascii_only': true
      });
    } catch(e) {
      exception = e;
    }
    // lines are restricted to 500 characters for consistency with the Closure Compiler
    callback(exception, result && ugly.split_lines(result, 500));
  }

  /*--------------------------------------------------------------------------*/

  /**
   * The `closureCompile()` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {String} result The resulting minified source.
   */
  function onClosureCompile(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the post-processed Closure Compiler result and gzip it
    this.compiled.source = result = postprocess(result);
    gzip(result, onClosureGzip.bind(this));
  }

  /**
   * The Closure Compiler `gzip` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {Buffer} result The resulting gzipped source.
   */
  function onClosureGzip(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the gzipped result and report the size
    this.compiled.gzip = result;
    console.log('Done. Size: %d bytes.', result.length);

    // next, minify the source using only UglifyJS
    uglify.call(this, this.source, onUglify.bind(this));
  }

  /**
   * The `uglify()` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {String} result The resulting minified source.
   */
  function onUglify(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the post-processed Uglified result and gzip it
    this.uglified.source = result = postprocess(result);
    gzip(result, onUglifyGzip.bind(this));
  }

  /**
   * The UglifyJS `gzip` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {Buffer} result The resulting gzipped source.
   */
  function onUglifyGzip(exception, result) {
    if (exception) {
      throw exception;
    }
    var message = 'Compressing  ' + this.workingName + ' using hybrid minification...';

    // store the gzipped result and report the size
    this.uglified.gzip = result;
    console.log('Done. Size: %d bytes.', result.length);

    // next, minify the Closure Compiler minified source using UglifyJS
    uglify.call(this, this.compiled.source, message, onHybrid.bind(this));
  }

  /**
   * The hybrid `uglify()` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {String} result The resulting minified source.
   */
  function onHybrid(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the post-processed Uglified result and gzip it
    this.hybrid.source = result = postprocess(result);
    gzip(result, onHybridGzip.bind(this));
  }

  /**
   * The hybrid `gzip` callback.
   *
   * @private
   * @param {Object|Undefined} exception The error object.
   * @param {Buffer} result The resulting gzipped source.
   */
  function onHybridGzip(exception, result) {
    if (exception) {
      throw exception;
    }
    // store the gzipped result and report the size
    this.hybrid.gzip = result;
    console.log('Done. Size: %d bytes.', result.length);

    // finish by choosing the smallest compressed file
    onComplete.call(this);
  }

  /**
   * The callback executed after JavaScript source is minified and gzipped.
   *
   * @private
   */
  function onComplete() {
    var compiled = this.compiled,
        hybrid = this.hybrid,
        name = this.workingName,
        uglified = this.uglified;

    // save the Closure Compiled version to disk
    fs.writeFileSync(path.join(distPath, name + '.compiler.js'), compiled.source);
    fs.writeFileSync(path.join(distPath, name + '.compiler.js.gz'), compiled.gzip);

    // save the Uglified version to disk
    fs.writeFileSync(path.join(distPath, name + '.uglify.js'), uglified.source);
    fs.writeFileSync(path.join(distPath, name + '.uglify.js.gz'), uglified.gzip);

    // save the hybrid minified version to disk
    fs.writeFileSync(path.join(distPath, name + '.hybrid.js'), hybrid.source);
    fs.writeFileSync(path.join(distPath, name + '.hybrid.js.gz'), hybrid.gzip);

    // select the smallest gzipped file and use its minified counterpart as the
    // official minified release (ties go to Closure Compiler)
    var min = Math.min(compiled.gzip.length, hybrid.gzip.length, uglified.gzip.length);

    // pass the minified source to the minify instances "onComplete" callback
    this.onComplete(
      compiled.gzip.length == min
        ? compiled.source
        : uglified.gzip.length == min
          ? uglified.source
          : hybrid.source
    );
  }

  /*--------------------------------------------------------------------------*/

  // expose `minify`
  if (module != require.main) {
    module.exports = minify;
  }
  else {
    // read the JavaScript source file from the first argument if the script
    // was invoked directly (e.g. `node minify.js source.js`) and write to
    // the same file
    (function() {
      var filePath = process.argv[2],
          dirPath = path.dirname(filePath),
          source = fs.readFileSync(filePath, 'utf8'),
          workingName = path.basename(filePath, '.js') + '.min';

      minify(source, workingName, function(result) {
        fs.writeFileSync(path.join(dirPath, workingName + '.js'), result);
      });
    }());
  }
}());
<|endoftext|>


<commit_before><commit_msg>fix test<commit_after><|endoftext|>


<commit_before>/*
This module contains a generic data browsing interface.
*/

CT.Browser = CT.Class({
	CLASSNAME: "CT.Browser",
	_: {
		nodes: {},
		edit: function(data) {
			var _ = this._, view = this.view;
			CT.db.put(data, function(dfull) {
				if (data.key)
					return view(dfull);
				_.items.push(dfull);
				_.tlist.postAdd(dfull, true);
			});
		},
		load: function(d) {
			var _ = this._, oz = this.opts, view = this.view;
			if (d.name)
				return view(d);
			CT.dom.setContent(_.nodes.content, CT.dom.div([
				CT.dom.div("what's this " + oz.modelName + " called?", "bigger centered"),
				CT.dom.smartField({
					classname: "w1",
					blurs: oz.blurs,
					cb: function(name) {
						d.name = name;
						view(d);
					}
				})
			], "margined padded bordered round"));
		},
		filter: function() {
			var _ = this._, refresher = function(val) {
				CT.dom.each(_.tlist, function(n, i) {
					CT.dom[(!val || n.firstChild.innerHTML.includes(val)) ? "show" : "hide"](n);
				});
				clearbutt.style.display = val ? "inline" : "none";
			}, sf = CT.dom.smartField({
				keyup: refresher
			}), clearbutt = CT.dom.span("X", "hidden pointer");
			clearbutt.onclick = function() {
				sf.value = "";
				refresher();
			}
			return CT.dom.span([sf, clearbutt]);
		},
		build: function(items) {
			var _ = this._, oz = this.opts, defs = {
					modelName: oz.modelName
				}, defz = this.defaults, ntxt = "new " + oz.modelName;
			if (oz.owner)
				defs.owner = user.core.get("key");
			_.items = items;
			_.tlist = CT.panel.triggerList([ntxt].concat(items), function(d) {
				_.load((d == ntxt) ? CT.merge(defs, defz()) : d);
			});
			CT.dom.setContent(_.nodes.list, _.tlist);
			var maker = CT.dom.id("tlnew" + oz.modelName);
			maker.trigger();
			if (oz.filter) {
				CT.dom.setContent(maker.firstChild,
					CT.dom.div("+", "biggest bold shiftup"));
				maker.style.float = "right";
				_.tlist.parentNode.insertBefore(CT.dom.div([
					_.filter(),
					maker
				], "browser_filter"), _.tlist);
			}
		},
		setup: function() {
			var _ = this._, nz = _.nodes, oz = this.opts;
			nz.list = CT.dom.div(null, "ctlist");
			nz.content = CT.dom.div(null, "ctcontent");
			CT.dom.setContent(oz.parent, [
				nz.list,
				nz.content
			]);
			CT.db.get(oz.modelName, _.build, null, null, null, oz.owner && {
				owner: user.core.get("key") // requires user module
			});
		}
	},
	namer: function(d, classes) {
		var n = CT.dom.div(d.name,
			"pointer " + (classes || "bigger centered"));
		n.onclick = function() {
			var sf = CT.dom.smartField({
				value: d.name,
				cb: function(name) {
					if (name == d.name) return;
					CT.db.put({
						key: d.key,
						name: name
					}, function(newd) {
						d.name = newd.name;
						d.label = newd.label;
						CT.dom.setContent(n, d.name);
						CT.dom.setContent(CT.dom.id("tl" + d.key).firstChild,
							d.label);
					});
				}
			});
			CT.dom.setContent(n, sf);
			sf.focus();
		};
		return n;
	},
	view: function(d) {
		// override!
		CT.dom.setContent(_.nodes.content, [
			this.namer(d),
			JSON.stringify(d)
		]);
	},
	defaults: function() {
		// override
	},
	init: function(opts) {
		this.opts = CT.merge(opts, {
			parent: "ctmain",
			modelName: null, // REQUIRED
			nopts: {},
			owner: true,
			filter: true,
			blurs: ["name please", "title", "what's it called?"]
		});
		setTimeout(this._.setup);
	}
});<commit_msg>Browser._.filter(): case insensitivity<commit_after>/*
This module contains a generic data browsing interface.
*/

CT.Browser = CT.Class({
	CLASSNAME: "CT.Browser",
	_: {
		nodes: {},
		edit: function(data) {
			var _ = this._, view = this.view;
			CT.db.put(data, function(dfull) {
				if (data.key)
					return view(dfull);
				_.items.push(dfull);
				_.tlist.postAdd(dfull, true);
			});
		},
		load: function(d) {
			var _ = this._, oz = this.opts, view = this.view;
			if (d.name)
				return view(d);
			CT.dom.setContent(_.nodes.content, CT.dom.div([
				CT.dom.div("what's this " + oz.modelName + " called?", "bigger centered"),
				CT.dom.smartField({
					classname: "w1",
					blurs: oz.blurs,
					cb: function(name) {
						d.name = name;
						view(d);
					}
				})
			], "margined padded bordered round"));
		},
		filter: function() {
			var _ = this._, refresher = function(val) {
				CT.dom.each(_.tlist, function(n, i) {
					CT.dom[(!val || n.firstChild.innerHTML.toLowerCase().includes(val.toLowerCase())) ? "show" : "hide"](n);
				});
				clearbutt.style.display = val ? "inline" : "none";
			}, sf = CT.dom.smartField({
				keyup: refresher
			}), clearbutt = CT.dom.span("X", "hidden pointer");
			clearbutt.onclick = function() {
				sf.value = "";
				refresher();
			}
			return CT.dom.span([sf, clearbutt]);
		},
		build: function(items) {
			var _ = this._, oz = this.opts, defs = {
					modelName: oz.modelName
				}, defz = this.defaults, ntxt = "new " + oz.modelName;
			if (oz.owner)
				defs.owner = user.core.get("key");
			_.items = items;
			_.tlist = CT.panel.triggerList([ntxt].concat(items), function(d) {
				_.load((d == ntxt) ? CT.merge(defs, defz()) : d);
			});
			CT.dom.setContent(_.nodes.list, _.tlist);
			var maker = CT.dom.id("tlnew" + oz.modelName);
			maker.trigger();
			if (oz.filter) {
				CT.dom.setContent(maker.firstChild,
					CT.dom.div("+", "biggest bold shiftup"));
				maker.style.float = "right";
				_.tlist.parentNode.insertBefore(CT.dom.div([
					_.filter(),
					maker
				], "browser_filter"), _.tlist);
			}
		},
		setup: function() {
			var _ = this._, nz = _.nodes, oz = this.opts;
			nz.list = CT.dom.div(null, "ctlist");
			nz.content = CT.dom.div(null, "ctcontent");
			CT.dom.setContent(oz.parent, [
				nz.list,
				nz.content
			]);
			CT.db.get(oz.modelName, _.build, null, null, null, oz.owner && {
				owner: user.core.get("key") // requires user module
			});
		}
	},
	namer: function(d, classes) {
		var n = CT.dom.div(d.name,
			"pointer " + (classes || "bigger centered"));
		n.onclick = function() {
			var sf = CT.dom.smartField({
				value: d.name,
				cb: function(name) {
					if (name == d.name) return;
					CT.db.put({
						key: d.key,
						name: name
					}, function(newd) {
						d.name = newd.name;
						d.label = newd.label;
						CT.dom.setContent(n, d.name);
						CT.dom.setContent(CT.dom.id("tl" + d.key).firstChild,
							d.label);
					});
				}
			});
			CT.dom.setContent(n, sf);
			sf.focus();
		};
		return n;
	},
	view: function(d) {
		// override!
		CT.dom.setContent(_.nodes.content, [
			this.namer(d),
			JSON.stringify(d)
		]);
	},
	defaults: function() {
		// override
	},
	init: function(opts) {
		this.opts = CT.merge(opts, {
			parent: "ctmain",
			modelName: null, // REQUIRED
			nopts: {},
			owner: true,
			filter: true,
			blurs: ["name please", "title", "what's it called?"]
		});
		setTimeout(this._.setup);
	}
});<|endoftext|>


<commit_before><commit_msg>feat: vulgar init shell script<commit_after>#!/usr/bin/env node

'use strict';

//# vulgar init

//** Import dependencies
var wizard = require('../lib/wizard'),
    program = require('commander');

program
  .description('Create a MEAN application in the current working directory')
  .option('-b, --branch <branch>', 'git branch')
  .option('-g, --git', 'clone using git:// instead of https://')
  .option('--repo <repo>', 'Specify which repository to install')
  .option('-f, --full', 'Clone the full project including all commit history')
  .option('-m, --mail <mail>', 'Assign/Create admin user to specified email')
  .option('-u, --username <username>', 'Assign/Create admin user to the '
    + 'specified username')
  .option('-q, --quick', 'Jump right into the project directory and run '
    + '`npm install`')
  .parse(process.argv);

var options = {
  name: program.args.length ? program.args[0] : 'mean',
  branch: program.branch || 'master',
  git: program.git,
  full: program.full,
  repo: program.repo,
  email: program.mail,
  username: program.username,
  quick: program.quick
};

// Pass the mighty wizard our options
wizard(options);
<|endoftext|>


<commit_before>(function () {
  var ns = $.namespace('pskl.utils.serialization');

  var areChunksValid = function (chunks) {
    return chunks.length && chunks.every(function (chunk) {
      return chunk.base64PNG;
    });
  };

  var createLineLayout = function (size, offset) {
    var layout = [];
    for (var i = 0 ; i < size ; i++) {
      layout.push([i + offset]);
    }

    return layout;
  };

  ns.Serializer = {
    serialize : function (piskel) {
      var serializedLayers = piskel.getLayers().map(function (l) {
        return pskl.utils.serialization.Serializer.serializeLayer(l);
      });
      return JSON.stringify({
        modelVersion : Constants.MODEL_VERSION,
        piskel : {
          name : piskel.getDescriptor().name,
          description : piskel.getDescriptor().description,
          fps : pskl.app.piskelController.getFPS(),
          height : piskel.getHeight(),
          width : piskel.getWidth(),
          layers : serializedLayers
        }
      });
    },

    serializeLayer : function (layer) {
      var frames = layer.getFrames();
      var layerToSerialize = {
        name : layer.getName(),
        opacity : layer.getOpacity(),
        frameCount : frames.length
      };

      // A layer spritesheet data can be chunked in case the spritesheet PNG is to big to be
      // converted to a dataURL.
      // Frames are divided equally amongst chunks and each chunk is converted to a spritesheet
      // PNG. If any chunk contains an invalid base64 PNG, we increase the number of chunks and
      // retry.
      var chunks = [];
      while (!areChunksValid(chunks)) {
        if (chunks.length > frames.length) {
          // Something went horribly wrong.
          chunks = [];
          break;
        }

        // Chunks are invalid, increase the number of chunks by one, and chunk the frames array.
        var frameChunks = pskl.utils.Array.chunk(frames, chunks.length + 1);

        // Reset chunks array.
        chunks = [];

        // After each chunk update the offset by te number of frames that have been processed.
        var offset = 0;
        for (var i = 0 ; i < frameChunks.length ; i++) {
          var chunkFrames = frameChunks[i];
          var renderer = new pskl.rendering.FramesheetRenderer(chunkFrames);
          chunks.push({
            base64PNG : renderer.renderAsCanvas().toDataURL(),
            // create a layout array, containing the indices of the frames extracted in this chunk
            layout : createLineLayout(chunkFrames.length, offset),
          });

          offset += chunkFrames.length;
        }
      }

      layerToSerialize.chunks = chunks;
      return JSON.stringify(layerToSerialize);
    }
  };
})();
<commit_msg>improve serialization error detection for firefox<commit_after>(function () {
  var ns = $.namespace('pskl.utils.serialization');

  var areChunksValid = function (chunks) {
    return chunks.length && chunks.every(function (chunk) {
      return chunk.base64PNG && chunk.base64PNG !== "data:,";
    });
  };

  var createLineLayout = function (size, offset) {
    var layout = [];
    for (var i = 0 ; i < size ; i++) {
      layout.push([i + offset]);
    }

    return layout;
  };

  ns.Serializer = {
    serialize : function (piskel) {
      var serializedLayers = piskel.getLayers().map(function (l) {
        return pskl.utils.serialization.Serializer.serializeLayer(l);
      });
      return JSON.stringify({
        modelVersion : Constants.MODEL_VERSION,
        piskel : {
          name : piskel.getDescriptor().name,
          description : piskel.getDescriptor().description,
          fps : pskl.app.piskelController.getFPS(),
          height : piskel.getHeight(),
          width : piskel.getWidth(),
          layers : serializedLayers
        }
      });
    },

    serializeLayer : function (layer) {
      var frames = layer.getFrames();
      var layerToSerialize = {
        name : layer.getName(),
        opacity : layer.getOpacity(),
        frameCount : frames.length
      };

      // A layer spritesheet data can be chunked in case the spritesheet PNG is to big to be
      // converted to a dataURL.
      // Frames are divided equally amongst chunks and each chunk is converted to a spritesheet
      // PNG. If any chunk contains an invalid base64 PNG, we increase the number of chunks and
      // retry.
      var chunks = [];
      while (!areChunksValid(chunks)) {
        if (chunks.length >= frames.length) {
          // Something went horribly wrong.
          chunks = [];
          break;
        }

        // Chunks are invalid, increase the number of chunks by one, and chunk the frames array.
        var frameChunks = pskl.utils.Array.chunk(frames, chunks.length + 1);

        // Reset chunks array.
        chunks = [];

        // After each chunk update the offset by te number of frames that have been processed.
        var offset = 0;
        for (var i = 0 ; i < frameChunks.length ; i++) {
          var chunkFrames = frameChunks[i];
          chunks.push({
            // create a layout array, containing the indices of the frames extracted in this chunk
            layout : createLineLayout(chunkFrames.length, offset),
            base64PNG : ns.Serializer.serializeFramesToBase64(chunkFrames),
          });

          offset += chunkFrames.length;
        }
      }

      layerToSerialize.chunks = chunks;
      return JSON.stringify(layerToSerialize);
    },

    serializeFramesToBase64 : function (frames) {
      try {
        var renderer = new pskl.rendering.FramesheetRenderer(frames);
        return renderer.renderAsCanvas().toDataURL();
      } catch (e) {
        return "";
      }
    }
  };
})();
<|endoftext|>


<commit_before>var roleRunner = require('role.runner');

module.exports = {
    run : function(creep){
        var mineral = creep.room.find(FIND_MINERALS)[0];
        var mineralType = mineral.mineralType;
        var mineralContainer = mineral.pos.findInRange(FIND_STRUCTURES,1,{filter:(s)=>s.structureType == STRUCTURE_CONTAINER})[0];
        if(!creep.memory.getting && _.sum(creep.carry) == 0){
            if(mineralContainer != undefined && creep.room.terminal != undefined && mineralContainer.store.mineralType >= creep.carryCapacity){
                creep.memory.getting = true;
                creep.memory.mytask = 'getMineral';
            }
            else if(creep.room.storage != undefined && creep.room.terminal != undefined && creep.room.storage.store.energy > 100000 && creep.terminal.store.energy < 50000){
                creep.memory.getting = true;
                creep.memory.mytask = 'getEnergy';
            }
            else{
                creep.memory.mytask = 'runner';
            }
        }
        else if(creep.memory.getting && _.sum(creep.carry) == creep.carryCapacity){
            creep.memory.getting = false;
            creep.memory.mytask = 'deliver';
        }

        if(creep.memory.mytask == 'runner'){
            roleRunner.run(creep);
        }
        else if(creep.memory.mytask = 'getMineral'){
            if(creep.withdraw(mineralContainer,mineralType) == ERR_NOT_IN_RANGE){
                creep.moveTo(mineralContainer);
            }
        }
        else if(creep.memory.mytask = 'getEnergy'){
            if(creep.withdraw(creep.room.storage,RESOURCE_ENERGY) == ERR_NOT_IN_RANGE){
                creep.moveTo(creep.room.storage);
            }
        }
        else if(creep.memory.mytask == 'deliver'){
            if(creep.transfer(creep.room.terminal,_.keys(creep.carry)[0]) == ERR_NOT_IN_RANGE){
                creep.moveTo(creep.room.terminal);
            }
        }

    }
}
<commit_msg>small fix<commit_after>var roleRunner = require('role.runner');

module.exports = {
    run : function(creep){
        var mineral = creep.room.find(FIND_MINERALS)[0];
        var mineralType = mineral.mineralType;
        var mineralContainer = mineral.pos.findInRange(FIND_STRUCTURES,1,{filter:(s)=>s.structureType == STRUCTURE_CONTAINER})[0];
        if(!creep.memory.getting && _.sum(creep.carry) == 0){
            if(mineralContainer != undefined && creep.room.terminal != undefined && mineralContainer.store.mineralType >= creep.carryCapacity){
                creep.memory.getting = true;
                creep.memory.mytask = 'getMineral';
            }
            else if(creep.room.storage != undefined && creep.room.terminal != undefined && creep.room.storage.store.energy > 100000 && creep.room.terminal.store.energy < 50000){
                creep.memory.getting = true;
                creep.memory.mytask = 'getEnergy';
            }
            else{
                creep.memory.mytask = 'runner';
            }
        }
        else if(creep.memory.getting && _.sum(creep.carry) == creep.carryCapacity){
            creep.memory.getting = false;
            creep.memory.mytask = 'deliver';
        }

        if(creep.memory.mytask == 'runner'){
            roleRunner.run(creep);
        }
        else if(creep.memory.mytask = 'getMineral'){
            if(creep.withdraw(mineralContainer,mineralType) == ERR_NOT_IN_RANGE){
                creep.moveTo(mineralContainer);
            }
        }
        else if(creep.memory.mytask = 'getEnergy'){
            if(creep.withdraw(creep.room.storage,RESOURCE_ENERGY) == ERR_NOT_IN_RANGE){
                creep.moveTo(creep.room.storage);
            }
        }
        else if(creep.memory.mytask == 'deliver'){
            if(creep.transfer(creep.room.terminal,_.keys(creep.carry)[0]) == ERR_NOT_IN_RANGE){
                creep.moveTo(creep.room.terminal);
            }
        }

    }
}
<|endoftext|>


<commit_before>angular
    .module('app', [
        'apiResponse',
        'unsavedNew',
        'uiHelpers',
        'ui.validate',
        'ui.if',
        'ui.bootstrap',
        'ngCookies',
        'angular-markdown',
        'mb.spinner',
        'ajoslin.promise-tracker',
        'angulartics',
        'angulartics.google.analytics',
        'google-maps',
        'truncate'
    ])

/**
 * Configure angular app
 *
 * @note we dont yet have access to $rootScope, and a few other things
 *
 */
.config([
    '$httpProvider',
    '$compileProvider',
    function(
        $httpProvider,
        $compileProvider,
        promiseTracker
    ) {

        /**
         * Standard CORS Configuration
         *
         */
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];

        /**
         * Configure ngSanitize directive
         * Here we add 'mailto' 'callto' etc. which prevents links with href='mailto:' from
         * being flagged as 'unsafe' by angular sanitizer
         *
         */
        $compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|callto):/);

    }
])

/**
 * Define constants using Angulars .constant() method
 *
 * @note you need to adjust base_url when developing locally. Don't commit any changes to this since
 *       master is setup alreay to work with heroku
 *
 */
.constant('MARLINAPI_CONFIG', {
    //base_url: 'http://marlinquoter.herokuapp.com/api/v1/'
    //base_url: 'http://localhost:3000/api/v1/'
    //base_url: 'http://0.0.0.0:3000/api/v1/'
    base_url: 'http://127.0.0.1:3000/api/v1/'
})

/**
 * Define routes
 *
 * @note for this app we set all routes here in the app file. An alternate (any maybe more modular)
 *       is to set routes in the controllers as needed.
 *
 */
.config(['$routeProvider',
    function($router) {

        $router

        // general routes
        .when('/', {
            controller: 'homeController',
            templateUrl: 'app/templates/home.html'
        })

        .when('/changelog', {
            controller: 'changelogController',
            templateUrl: 'app/templates/changelog.html'
        })

        // general routes
        .when('/login', {
            controller: 'loginController',
            templateUrl: 'app/templates/login.html'
        })

        // general routes
        .when('/logout', {
            controller: 'logoutController',
            templateUrl: 'app/templates/logout.html'
        })

        // Quoter tool!
        .when('/tools/quoter', {
            controller: 'quoterToolController',
            templateUrl: 'app/templates/tools/quoter/quoterTool.html'
        })
            .when('/tools/quoter/:id', {
                controller: 'quoterToolController',
                templateUrl: 'app/templates/tools/quoter/quoterTool.html'
            })
            .when('/tools/quoter/:id/print', {
                controller: 'quoterToolController',
                templateUrl: 'app/templates/tools/quoter/quoterTool.html'
            })

        // Application tool!
        .when('/tools/application', {
            controller: 'applicationToolController',
            templateUrl: 'app/templates/tools/application/applicationTool.html'
        })
            .when('/tools/application/:id', {
                controller: 'applicationToolController',
                templateUrl: 'app/templates/tools/application/applicationTool.html'
            })

        // Locator tool!
        .when('/tools/locator', {
            controller: 'locatorToolController',
            templateUrl: 'app/templates/tools/locator/locatorTool.html'
        })

        // Auth user dashboards
        .when('/dashboard', {
            controller: 'applicationController',
            templateUrl: 'app/templates/dashboard/index.html'
        })

        // vendor routes
        .when('/dashboard/vendors', {
            controller: 'vendorController',
            templateUrl: 'app/templates/vendors/vendorList.html'
        })
            .when('/dashboard/vendors/new', {
                controller: 'vendorEditController',
                templateUrl: 'app/templates/vendors/vendorEdit.html'
            })
            .when('/dashboard/vendors/:id', {
                controller: 'vendorEditController',
                templateUrl: 'app/templates/vendors/vendorEdit.html'
            })

        // program routes
        .when('/dashboard/programs', {
            controller: 'programListController',
            templateUrl: 'app/templates/programs/programList.html'
        })
            .when('/dashboard/programs/new', {
                controller: 'programEditController',
                templateUrl: 'app/templates/programs/programEdit.html'
            })
            .when('/dashboard/programs/:id', {
                controller: 'programEditController',
                templateUrl: 'app/templates/programs/programEdit.html'
            })

        // quote routes
        .when('/dashboard/quotes', {
            controller: 'quoteListController',
            templateUrl: 'app/templates/quotes/quoteList.html'
        })
            .when('/dashboard/quotes/new', {
                controller: 'quoteEditController',
                templateUrl: 'app/templates/quotes/quoteEdit.html'
            })
            .when('/dashboard/quotes/:id', {
                controller: 'quoteEditController',
                templateUrl: 'app/templates/quotes/quoteEdit.html'
            })

        // application routes
        .when('/dashboard/applications', {
            controller: 'applicationController',
            templateUrl: 'app/templates/applications/applicationList.html'
        })
            .when('/dashboard/applications/new', {
                controller: 'applicationController',
                templateUrl: 'app/templates/applications/applicationEdit.html'
            })
            .when('/dashboard/applications/:id', {
                controller: 'applicationController',
                templateUrl: 'app/templates/applications/applicationEdit.html'
            })

        // user routes
        .when('/dashboard/users', {
            controller: 'userListController',
            templateUrl: 'app/templates/users/userList.html'
        })
            .when('/dashboard/users/new', {
                controller: 'userEditController',
                templateUrl: 'app/templates/users/userEdit.html'
            })
            .when('/dashboard/users/:id', {
                controller: 'userEditController',
                templateUrl: 'app/templates/users/userEdit.html'
            })

        ;
    }
])

/**
 * Runs one time when our app is finally bootstrapped
 *
 * @note Now we have access to $rootScope.
 *
 * @note Functions defined here run only one time, unless they observe or bind to a variable
 *       in which case the funtions will run as expected when said variables updates.
 *
 * @todo Most of these should be added to our facultyUI repo, however is there an easier way
 *       to add them? IE instead of needing to put in .run() can we leave them in a seperate module
 *       but include them in our app?
 *
 */
.run(['$rootScope', '$location', 'authService', '$document', '$http', 'promiseTracker',
    function($rootScope, $location, Auth, $document, $http, promiseTracker) {

        // define our version
        // @todo this should be set in package.json, and an api call should be made
        //       to get the version number, rather then setting it here.
        $rootScope.version = '0.3.4';

        // @note this is related to experimental promisetracker module
        $rootScope.apiTracker = promiseTracker('api');

        /**
         * Helper functions, which are accessiable anywhere in our app using $rootScope.functionName()
         *
         */

        /**
         * goto a url. This allows us to easily change hash / no-hash method
         * without having to change many links site-wide
         *
         */
        $rootScope.goTo = function(urlToGoTo) {
            $location.url(urlToGoTo);
        };

        /**
         * Sets active class on a link based on current url / location
         *
         * @example Path // adds active class
         *
         */
        $rootScope.getClass = function(path) {
            var cur_path = $location.path();

            // do some counting
            var splitCurPath = cur_path.split('/').length;
            var splitPath = path.split('/').length;

            //console.log('$location.path() is: ' + cur_path + ', path is: ' + path);
            if (cur_path == path) {
                return "active";
            } else if ($location.path().indexOf(path) > -1 && path.split('/').length === 3) {
                // this check prevents 'dashboard' from being active when user is viewing quotes
                return "active active-trail";
            } else {
                return "";
            }
        };

        /**
         * Helper function that masks auth.showIfUserCanDoAction() method
         *
         * @todo refactor this, to remove from rootScope
         *
         */
        $rootScope.showIfUserCanDoAction = function(action) {
            return Auth.showIfUserCanDoAction(action);
        };

        /**
         * Generate a string of classes which are generally added to document.body
         * This allows us to target specific pages within css
         *
         * @note this will bound to all successful route changes
         *
         * @note it might be useful to expand this function to add prefixes to the class, ie: page-pageName
         *       Wordpress does this and its one of the more useful features
         *
         */
        $rootScope.$on('$routeChangeSuccess', function($event, $route, $previousRoute) {

            // variable we use on body, @example ng-class="{{pageSlug}}"
            $rootScope.pageSlug = "";

            // get the location and split into an array
            var pageSlug = $location.path().split('/');

            // remove the first element, which is always ""
            pageSlug.shift();

            // special case for home page
            if (pageSlug.length === 1 && pageSlug[0] === "") {

                $rootScope.pageSlug = 'home';

                // create string from each slug item
            } else {

                _.each(pageSlug, function(item) {
                    $rootScope.pageSlug += item + " ";
                });

            }

        });

    }
]);
<commit_msg>Add dependency on ui.utils<commit_after>angular
    .module('app', [
        'apiResponse',
        'unsavedNew',
        'uiHelpers',
        'ui.validate',
        'ui.if',
        'ui.bootstrap',
        'ngCookies',
        'angular-markdown',
        'mb.spinner',
        'ajoslin.promise-tracker',
        'angulartics',
        'angulartics.google.analytics',
        'google-maps',
        'truncate',
        'ui.utils'
    ])

/**
 * Configure angular app
 *
 * @note we dont yet have access to $rootScope, and a few other things
 *
 */
.config([
    '$httpProvider',
    '$compileProvider',
    function(
        $httpProvider,
        $compileProvider,
        promiseTracker
    ) {

        /**
         * Standard CORS Configuration
         *
         */
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];

        /**
         * Configure ngSanitize directive
         * Here we add 'mailto' 'callto' etc. which prevents links with href='mailto:' from
         * being flagged as 'unsafe' by angular sanitizer
         *
         */
        $compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|callto):/);

    }
])

/**
 * Define constants using Angulars .constant() method
 *
 * @note you need to adjust base_url when developing locally. Don't commit any changes to this since
 *       master is setup alreay to work with heroku
 *
 */
.constant('MARLINAPI_CONFIG', {
    //base_url: 'http://marlinquoter.herokuapp.com/api/v1/'
    //base_url: 'http://localhost:3000/api/v1/'
    //base_url: 'http://0.0.0.0:3000/api/v1/'
    base_url: 'http://127.0.0.1:3000/api/v1/'
})

/**
 * Define routes
 *
 * @note for this app we set all routes here in the app file. An alternate (any maybe more modular)
 *       is to set routes in the controllers as needed.
 *
 */
.config(['$routeProvider',
    function($router) {

        $router

        // general routes
        .when('/', {
            controller: 'homeController',
            templateUrl: 'app/templates/home.html'
        })

        .when('/changelog', {
            controller: 'changelogController',
            templateUrl: 'app/templates/changelog.html'
        })

        // general routes
        .when('/login', {
            controller: 'loginController',
            templateUrl: 'app/templates/login.html'
        })

        // general routes
        .when('/logout', {
            controller: 'logoutController',
            templateUrl: 'app/templates/logout.html'
        })

        // Quoter tool!
        .when('/tools/quoter', {
            controller: 'quoterToolController',
            templateUrl: 'app/templates/tools/quoter/quoterTool.html'
        })
            .when('/tools/quoter/:id', {
                controller: 'quoterToolController',
                templateUrl: 'app/templates/tools/quoter/quoterTool.html'
            })
            .when('/tools/quoter/:id/print', {
                controller: 'quoterToolController',
                templateUrl: 'app/templates/tools/quoter/quoterTool.html'
            })

        // Application tool!
        .when('/tools/application', {
            controller: 'applicationToolController',
            templateUrl: 'app/templates/tools/application/applicationTool.html'
        })
            .when('/tools/application/:id', {
                controller: 'applicationToolController',
                templateUrl: 'app/templates/tools/application/applicationTool.html'
            })

        // Locator tool!
        .when('/tools/locator', {
            controller: 'locatorToolController',
            templateUrl: 'app/templates/tools/locator/locatorTool.html'
        })

        // Auth user dashboards
        .when('/dashboard', {
            controller: 'applicationController',
            templateUrl: 'app/templates/dashboard/index.html'
        })

        // vendor routes
        .when('/dashboard/vendors', {
            controller: 'vendorController',
            templateUrl: 'app/templates/vendors/vendorList.html'
        })
            .when('/dashboard/vendors/new', {
                controller: 'vendorEditController',
                templateUrl: 'app/templates/vendors/vendorEdit.html'
            })
            .when('/dashboard/vendors/:id', {
                controller: 'vendorEditController',
                templateUrl: 'app/templates/vendors/vendorEdit.html'
            })

        // program routes
        .when('/dashboard/programs', {
            controller: 'programListController',
            templateUrl: 'app/templates/programs/programList.html'
        })
            .when('/dashboard/programs/new', {
                controller: 'programEditController',
                templateUrl: 'app/templates/programs/programEdit.html'
            })
            .when('/dashboard/programs/:id', {
                controller: 'programEditController',
                templateUrl: 'app/templates/programs/programEdit.html'
            })

        // quote routes
        .when('/dashboard/quotes', {
            controller: 'quoteListController',
            templateUrl: 'app/templates/quotes/quoteList.html'
        })
            .when('/dashboard/quotes/new', {
                controller: 'quoteEditController',
                templateUrl: 'app/templates/quotes/quoteEdit.html'
            })
            .when('/dashboard/quotes/:id', {
                controller: 'quoteEditController',
                templateUrl: 'app/templates/quotes/quoteEdit.html'
            })

        // application routes
        .when('/dashboard/applications', {
            controller: 'applicationController',
            templateUrl: 'app/templates/applications/applicationList.html'
        })
            .when('/dashboard/applications/new', {
                controller: 'applicationController',
                templateUrl: 'app/templates/applications/applicationEdit.html'
            })
            .when('/dashboard/applications/:id', {
                controller: 'applicationController',
                templateUrl: 'app/templates/applications/applicationEdit.html'
            })

        // user routes
        .when('/dashboard/users', {
            controller: 'userListController',
            templateUrl: 'app/templates/users/userList.html'
        })
            .when('/dashboard/users/new', {
                controller: 'userEditController',
                templateUrl: 'app/templates/users/userEdit.html'
            })
            .when('/dashboard/users/:id', {
                controller: 'userEditController',
                templateUrl: 'app/templates/users/userEdit.html'
            })

        ;
    }
])

/**
 * Runs one time when our app is finally bootstrapped
 *
 * @note Now we have access to $rootScope.
 *
 * @note Functions defined here run only one time, unless they observe or bind to a variable
 *       in which case the funtions will run as expected when said variables updates.
 *
 * @todo Most of these should be added to our facultyUI repo, however is there an easier way
 *       to add them? IE instead of needing to put in .run() can we leave them in a seperate module
 *       but include them in our app?
 *
 */
.run(['$rootScope', '$location', 'authService', '$document', '$http', 'promiseTracker',
    function($rootScope, $location, Auth, $document, $http, promiseTracker) {

        // define our version
        // @todo this should be set in package.json, and an api call should be made
        //       to get the version number, rather then setting it here.
        $rootScope.version = '0.3.4';

        // @note this is related to experimental promisetracker module
        $rootScope.apiTracker = promiseTracker('api');

        /**
         * Helper functions, which are accessiable anywhere in our app using $rootScope.functionName()
         *
         */

        /**
         * goto a url. This allows us to easily change hash / no-hash method
         * without having to change many links site-wide
         *
         */
        $rootScope.goTo = function(urlToGoTo) {
            $location.url(urlToGoTo);
        };

        /**
         * Sets active class on a link based on current url / location
         *
         * @example Path // adds active class
         *
         */
        $rootScope.getClass = function(path) {
            var cur_path = $location.path();

            // do some counting
            var splitCurPath = cur_path.split('/').length;
            var splitPath = path.split('/').length;

            //console.log('$location.path() is: ' + cur_path + ', path is: ' + path);
            if (cur_path == path) {
                return "active";
            } else if ($location.path().indexOf(path) > -1 && path.split('/').length === 3) {
                // this check prevents 'dashboard' from being active when user is viewing quotes
                return "active active-trail";
            } else {
                return "";
            }
        };

        /**
         * Helper function that masks auth.showIfUserCanDoAction() method
         *
         * @todo refactor this, to remove from rootScope
         *
         */
        $rootScope.showIfUserCanDoAction = function(action) {
            return Auth.showIfUserCanDoAction(action);
        };

        /**
         * Generate a string of classes which are generally added to document.body
         * This allows us to target specific pages within css
         *
         * @note this will bound to all successful route changes
         *
         * @note it might be useful to expand this function to add prefixes to the class, ie: page-pageName
         *       Wordpress does this and its one of the more useful features
         *
         */
        $rootScope.$on('$routeChangeSuccess', function($event, $route, $previousRoute) {

            // variable we use on body, @example ng-class="{{pageSlug}}"
            $rootScope.pageSlug = "";

            // get the location and split into an array
            var pageSlug = $location.path().split('/');

            // remove the first element, which is always ""
            pageSlug.shift();

            // special case for home page
            if (pageSlug.length === 1 && pageSlug[0] === "") {

                $rootScope.pageSlug = 'home';

                // create string from each slug item
            } else {

                _.each(pageSlug, function(item) {
                    $rootScope.pageSlug += item + " ";
                });

            }

        });

    }
]);
<|endoftext|>