<commit_before>function carGaugeDefaultSettings() {
    return {
        minValue: 0,
        maxValue: 100,
        startValue: 50,
        textVertPosition: 0.5,
        textSize: 1,
        displayPercent: true
    };
}

function loadCarGauge(elementClass, value, config) {
    if (config === null) {
        config = carGaugeDefaultSettings();
    }

    var width = 1;
    var height = 1;
    var offset = 0;
    var gaugeValue = value;
    var padding = 20;

    //////// canvas dimensions
    width = document.getElementsByClassName(elementClass)[0].offsetWidth;
    height = width;

    //////// fuel gauge
    // point coordinates for triangle shape
    var leftPointX = padding;
    var leftPointY = padding;
    var rightPointX = width - padding;
    var rightPointY = padding;
    var bottomPointX = width / 2;
    var bottomPointY = height - padding;

    // fuel gauge path
    var path = "M " + leftPointX + " " + leftPointY + " L " + bottomPointX + " " + bottomPointY + " L " + rightPointX + " " + rightPointY + " L " + leftPointX + " " + leftPointY;

    //////// empty bar path
    // empty bar points
    var emptyBarLeft = width * 0.35;
    var emptyBarRight = width - width * 0.35;

    //empty bar path
    var emptyBarPath = "M " + emptyBarLeft + " " + bottomPointY + " L " + emptyBarRight + " " + bottomPointY;

    // create canvas
    var svg = d3.select("." + elementClass)
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    // create gradient
    var grad = svg.append("defs")
        .append("linearGradient")
        .attr({
            "id": "grad",
            "x1": "0%",
            "x2": "0%",
            "y1": "100%",
            "y2": "50%"
        });

    var clip = svg.append("defs");
    var clipPath = clip.append("clipPath")
        .attr("id", "polygon-mask");
    var polygon = clipPath
        .append("polygon")
        .attr("points", leftPointX + "," + rightPointY + " " + bottomPointX + "," + bottomPointY + " " + rightPointX + "," + rightPointY);

    grad.append("stop")
        .attr("offset", "100%")
        .style("stop-color", "#006600");

    // add gauge outline
    svg.append('svg:path')
        .attr("d", path)
        .attr("stroke", "#006600")
        .attr("fill", "none");

    // add gauge with fill
    var gauge = svg.append('svg:path')
        .attr("d", path)
        .attr("stroke", "none")
        .attr("fill", "url(#grad)")
        .attr("opacity", ".8")
        .attr("clip-path", "url(#polygon-mask)");

    // add empty bar
    var emptyBar = svg.append('svg:path')
        .attr("d", emptyBarPath)
        .attr("stroke", "#006600")
        .attr("stroke-width", "3px");

    //////// fuel gauge text
    var emptyBarText = svg.selectAll("text")
                            .data(emptyBar)
                            .enter();

    // empty bar text "E"
    emptyBarText.append("text")
                    .attr("x", emptyBarLeft - 15)
                    .attr("y", bottomPointY + 5)
                    .text("E")
                    .attr("font-size", "20px")
                    .attr("fill", "#006600");

    var changeGauge = function(percent) {
        offset = height - padding * 2 - ((height - padding * 2) * percent / 100);
        leftPointY = padding + offset;
        rightPointY = padding + offset;
        path = getNewPath();
        polygon.attr("points", updatePolygon());
    };

    var getNewPath = function() {
        return "M " + leftPointX + " " + leftPointY + " L " + bottomPointX + " " + bottomPointY + " L " + rightPointX + " " + rightPointY + " L " + leftPointX + " " + leftPointY;
    };

    var updatePolygon = function() {
         return "points", leftPointX + "," + rightPointY + " " + bottomPointX + "," + bottomPointY + " " + rightPointX + "," + rightPointY;
    };

    return {
        updateGauge:  function(percent) {
            changeGauge(percent);

            gauge.attr("clip-path", "url(#polygon-mask)")
                .attr("transform", null)
                .transition()
                .attr("transform", "translate(" + 0 + "," + 0 + ")");

            gaugeValue = percent;
        },

        getGaugeValue: function() {
            return gaugeValue;
        },

        getRecommendedRefuelValue: function() {
            return 25;
        }
    };
}
<commit_msg>add 1/3 line<commit_after>function carGaugeDefaultSettings() {
    return {
        minValue: 0,
        maxValue: 100,
        startValue: 50,
        textVertPosition: 0.5,
        textSize: 1,
        displayPercent: true
    };
}

function loadCarGauge(elementClass, value, config) {
    if (config === null) {
        config = carGaugeDefaultSettings();
    }

    var width = 1;
    var height = 1;
    var offset = 0;
    var gaugeValue = value;
    var padding = 20;

    //////// canvas dimensions
    width = document.getElementsByClassName(elementClass)[0].offsetWidth;
    height = width;

    //////// fuel gauge
    // point coordinates for triangle shape
    var leftPointX = padding;
    var leftPointY = padding;
    var rightPointX = width - padding;
    var rightPointY = padding;
    var bottomPointX = width / 2;
    var bottomPointY = height - padding;

    // fuel gauge path
    var path = "M " + leftPointX + " " + leftPointY + " L " + bottomPointX + " " + bottomPointY + " L " + rightPointX + " " + rightPointY + " L " + leftPointX + " " + leftPointY;

    //////// empty bar
    // empty bar points
    var emptyBarLeft = width * 0.35;
    var emptyBarRight = width - width * 0.35;

    // empty bar path
    var emptyBarPath = "M " + emptyBarLeft + " " + bottomPointY + " L " + emptyBarRight + " " + bottomPointY;

    //////// third bar
    // third bar points
    var thirdBarLeft = width * 0.27;
    var thirdBarRight = width * 0.33;

    // third bar heigh
    var thirdBarHeight = (bottomPointY - padding) * (2 / 3) + padding;

    // third bar path
    var thirdBarPath = "M " + thirdBarLeft + " " + thirdBarHeight + " L " + thirdBarRight + " " + thirdBarHeight;

    // create canvas
    var svg = d3.select("." + elementClass)
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    // create gradient
    var grad = svg.append("defs")
        .append("linearGradient")
        .attr({
            "id": "grad",
            "x1": "0%",
            "x2": "0%",
            "y1": "100%",
            "y2": "50%"
        });

    var clip = svg.append("defs");
    var clipPath = clip.append("clipPath")
        .attr("id", "polygon-mask");
    var polygon = clipPath
        .append("polygon")
        .attr("points", leftPointX + "," + rightPointY + " " + bottomPointX + "," + bottomPointY + " " + rightPointX + "," + rightPointY);

    grad.append("stop")
        .attr("offset", "100%")
        .style("stop-color", "#006600");

    // add gauge outline
    svg.append('svg:path')
        .attr("d", path)
        .attr("stroke", "#006600")
        .attr("fill", "none");

    // add gauge with fill
    var gauge = svg.append('svg:path')
        .attr("d", path)
        .attr("stroke", "none")
        .attr("fill", "url(#grad)")
        .attr("opacity", ".8")
        .attr("clip-path", "url(#polygon-mask)");

    // add empty bar
    var emptyBar = svg.append('svg:path')
        .attr("d", emptyBarPath)
        .attr("stroke", "#006600")
        .attr("stroke-width", "3px");

    // add third bar
    var thirdBar = svg.append('svg:path')
        .attr("d", thirdBarPath)
        .attr("stroke", "#006600")
        .attr("stroke-width", "3px");

    //////// fuel gauge text
    var emptyBarText = svg.selectAll("text")
                            .data(emptyBar)
                            .enter();

    // empty bar text "E"
    emptyBarText.append("text")
                    .attr("x", emptyBarLeft - 15)
                    .attr("y", bottomPointY + 5)
                    .text("E")
                    .attr("font-size", "20px")
                    .attr("fill", "#006600");

    // third bar text "1/3"
    emptyBarText.append("text")
                    .attr("x", thirdBarLeft - 25)
                    .attr("y", thirdBarHeight + 5)
                    .text("1/3")
                    .attr("font-size", "20px")
                    .attr("fill", "#006600");

    //emptyBarText.append()

    var changeGauge = function(percent) {
        offset = height - padding * 2 - ((height - padding * 2) * percent / 100);
        leftPointY = padding + offset;
        rightPointY = padding + offset;
        path = getNewPath();
        polygon.attr("points", updatePolygon());
    };

    var getNewPath = function() {
        return "M " + leftPointX + " " + leftPointY + " L " + bottomPointX + " " + bottomPointY + " L " + rightPointX + " " + rightPointY + " L " + leftPointX + " " + leftPointY;
    };

    var updatePolygon = function() {
         return "points", leftPointX + "," + rightPointY + " " + bottomPointX + "," + bottomPointY + " " + rightPointX + "," + rightPointY;
    };

    return {
        updateGauge:  function(percent) {
            changeGauge(percent);

            gauge.attr("clip-path", "url(#polygon-mask)")
                .attr("transform", null)
                .transition()
                .attr("transform", "translate(" + 0 + "," + 0 + ")");

            gaugeValue = percent;
        },

        changeGaugeColor: function() {

        },

        getGaugeValue: function() {
            return gaugeValue;
        },

        getRecommendedRefuelValue: function() {
            return 25;
        }
    };
}
<|endoftext|>


<commit_before>requirejs.config({
  baseDir: "/js",
  paths: {
    "analytics": "/bower_components/webmaker-analytics/analytics",
    "jquery": "/bower_components/jquery/jquery.min",
    "intl-tel-input": "/bower_components/intl-tel-input/build/js/intlTelInput.min",
    "ua-parser-js": "/bower_components/ua-parser-js/dist/ua-parser.min"
  }
});

require(["jquery", "analytics", "intl-tel-input", "ua-parser-js"], function ($, analytics, UA) {
  "use strict";
  var downloadButtons = $(".download-app-btn"),
    sendInstallAppButtonContainer = $(".desktop-install-app-btn-wrapper"),
    sendInstallLinkContainer = $(".send-install-link-container"),
    smsPrivacyMessageContainer = $(".sms-privacy-message"),
    phoneNumberLabel = $(".phone-number-label"),
    getAppBtn = $("#get-app"),
    mobileFooter = $(".download-app"),
    phoneNumberInput = $(".phone-num-input"),
    phoneNumberInputError = $(".phone-error"),
    sendSmsButton = $(".send-sms-btn"),
    messageSent = $("#message-sent"),
    messageSentError = $(".message-sent-error-container"),
    csrfToken = $("meta[name='csrf-token']").attr("content"),
    smsForm = $("#sms-form");
  var parser = new UAParser();
  var ua = parser.getResult();
  var isMobile = ua.device.type === "mobile";
  if (isMobile) {
    $(".mobile-only").removeClass("mobile-only");
  } else {
    $(".desktop-only").removeClass("desktop-only");
  }

  function sendSMS() {
    sendSmsButton.attr("disabled", true);
    var phoneNumber = phoneNumberInput.intlTelInput("getNumber", window.intlTelInputUtils.numberFormat.INTERNATIONAL);

    analytics.event("Click Send SMS Link for Beta App", {
      label: phoneNumberInput.intlTelInput("getSelectedCountryData").iso2
    });

    $.ajax({
      type: "POST",
      url: "/app/send-download-link",
      dataType: "json",
      data: {
        to: phoneNumber
      },
      headers: {
        "X-CSRF-Token": csrfToken
      },
      error: function () {
        smsForm.addClass("hidden");
        messageSentError.removeClass("hidden");
      },
      success: function () {
        smsForm.addClass("hidden");
        messageSent.removeClass("hidden");
        analytics.event("SMS Send Success", {
          nonInteraction: true
        });
      }
    });
  }

  sendSmsButton.attr("disabled", true);

  downloadButtons.click(function () {
    analytics.event("Download Beta App");
  });

  getAppBtn.click(function () {
    analytics.event("Click Get App Button");
    smsForm.removeClass("hidden");
    getAppBtn.addClass("hidden");
  });

  phoneNumberInput.intlTelInput();

  phoneNumberInput.intlTelInput("loadUtils", "/bower_components/intl-tel-input/lib/libphonenumber/build/utils.js");

  phoneNumberInput.keyup(function () {
    sendSmsButton.attr("disabled", !phoneNumberInput.intlTelInput("isValidNumber"));
  });

  phoneNumberInput.focus(function () {
    phoneNumberInput.removeClass("invalid");
    phoneNumberInputError.addClass("hidden");
  });

  phoneNumberInput.blur(function () {
    if (phoneNumberInput.intlTelInput("isValidNumber")) {
      phoneNumberInput.removeClass("invalid");
      phoneNumberInputError.addClass("hidden");
    } else if (phoneNumberInput.val().trim().length > 0) {
      phoneNumberInput.addClass("invalid");
      phoneNumberInputError.removeClass("hidden");
    }
  });

  sendSmsButton.click(sendSMS);

  sendSmsButton.keypress(function (evt) {
    if (evt.keycode === 13 && phoneNumberInput.intlTelInput("isValidNumber")) {
      sendSMS();
    }
  });
});
<commit_msg>fixes<commit_after>requirejs.config({
  baseDir: "/js",
  paths: {
    "analytics": "/bower_components/webmaker-analytics/analytics",
    "jquery": "/bower_components/jquery/jquery.min",
    "intl-tel-input": "/bower_components/intl-tel-input/build/js/intlTelInput.min",
    "ua-parser-js": "/bower_components/ua-parser-js/dist/ua-parser.min"
  }
});

require(["jquery", "analytics", "intl-tel-input", "ua-parser-js"], function ($, analytics, UA) {
  "use strict";
  var downloadButtons = $(".download-app-btn"),
    getAppBtn = $("#get-app"),
    phoneNumberInput = $(".phone-num-input"),
    phoneNumberInputError = $(".phone-error"),
    sendSmsButton = $(".send-sms-btn"),
    messageSent = $("#message-sent"),
    messageSentError = $(".message-sent-error-container"),
    csrfToken = $("meta[name='csrf-token']").attr("content"),
    smsForm = $("#sms-form");
  var parser = new window.UAParser();
  var ua = parser.getResult();
  var isMobile = ua.device.type === "mobile";
  if (isMobile) {
    $(".mobile-only").removeClass("mobile-only");
  } else {
    $(".desktop-only").removeClass("desktop-only");
  }

  function sendSMS() {
    sendSmsButton.attr("disabled", true);
    var phoneNumber = phoneNumberInput.intlTelInput("getNumber", window.intlTelInputUtils.numberFormat.INTERNATIONAL);

    analytics.event("Click Send SMS Link for Beta App", {
      label: phoneNumberInput.intlTelInput("getSelectedCountryData").iso2
    });

    $.ajax({
      type: "POST",
      url: "/app/send-download-link",
      dataType: "json",
      data: {
        to: phoneNumber
      },
      headers: {
        "X-CSRF-Token": csrfToken
      },
      error: function () {
        smsForm.addClass("hidden");
        messageSentError.removeClass("hidden");
      },
      success: function () {
        smsForm.addClass("hidden");
        messageSent.removeClass("hidden");
        analytics.event("SMS Send Success", {
          nonInteraction: true
        });
      }
    });
  }

  sendSmsButton.attr("disabled", true);

  downloadButtons.click(function () {
    analytics.event("Download Beta App");
  });

  getAppBtn.click(function () {
    analytics.event("Click Get App Button");
    smsForm.removeClass("hidden");
    getAppBtn.addClass("hidden");
  });

  phoneNumberInput.intlTelInput();

  phoneNumberInput.intlTelInput("loadUtils", "/bower_components/intl-tel-input/lib/libphonenumber/build/utils.js");

  phoneNumberInput.keyup(function () {
    sendSmsButton.attr("disabled", !phoneNumberInput.intlTelInput("isValidNumber"));
  });

  phoneNumberInput.focus(function () {
    phoneNumberInput.removeClass("invalid");
    phoneNumberInputError.addClass("hidden");
  });

  phoneNumberInput.blur(function () {
    if (phoneNumberInput.intlTelInput("isValidNumber")) {
      phoneNumberInput.removeClass("invalid");
      phoneNumberInputError.addClass("hidden");
    } else if (phoneNumberInput.val().trim().length > 0) {
      phoneNumberInput.addClass("invalid");
      phoneNumberInputError.removeClass("hidden");
    }
  });

  sendSmsButton.click(sendSMS);

  sendSmsButton.keypress(function (evt) {
    if (evt.keycode === 13 && phoneNumberInput.intlTelInput("isValidNumber")) {
      sendSMS();
    }
  });
});
<|endoftext|>


<commit_before>const ansi = module.exports = {
	black: ["\x1b[30m", "\x1b[39m"],
	red: ["\x1b[31m", "\x1b[39m"],
	green: ["\x1b[32m", "\x1b[39m"],
	yellow: ["\x1b[33m", "\x1b[39m"],
	blue: ["\x1b[34m", "\x1b[39m"],
	magenta: ["\x1b[35m", "\x1b[39m"],
	cyan: ["\x1b[36m", "\x1b[39m"],
	white: ["\x1b[37m", "\x1b[39m"],
	gray: ["\x1B[90m", "\x1b[39m"],

	bgBlack: ["\x1b[40m", "\x1b[49m"],
	bgRed: ["\x1b[41m", "\x1b[49m"],
	bgGreen: ["\x1b[42m", "\x1b[49m"],
	bgYellow: ["\x1b[43m", "\x1b[49m"],
	bgBlue: ["\x1b[44m", "\x1b[49m"],
	bgMagenta: ["\x1b[45m", "\x1b[49m"],
	bgCyan: ["\x1b[46m", "\x1b[49m"],
	bgWhite: ["\x1b[47m", "\x1b[49m"],

	dim: ["\x1b[2m", "\x1b[22m"],
	bold: ["\x1b[1m", "\x1b[22m"],
	hidden: ["\x1b[8m", "\x1b[28m"],
	italic: ["\x1b[3m", "\x1b[23m"],
	underline: ["\x1b[4m", "\x1b[24m"],
	inverse: ["\x1b[7m", "\x1b[27m"],
	strikethrough: ["\x1b[9m", "\x1b[29m"],

	newLine: ["\n", "\x1b[0m"],
	tab: ["\t", "\x1b[0m"],
	reset: ["\x1b[0m"]
}

const hasColor = _ =>
	process.platform === "win32" ||
	process.stdout.isTTY &&
	process.env.TERM &&
	process.env.TERM !== "dumb"

Object.keys(ansi).forEach(k => ansi[k] = hasColor() ? ansi[k] : ["", ""])

<commit_msg>Support FORCE_COLOR environment variable<commit_after>const ansi = module.exports = {
	black: ["\x1b[30m", "\x1b[39m"],
	red: ["\x1b[31m", "\x1b[39m"],
	green: ["\x1b[32m", "\x1b[39m"],
	yellow: ["\x1b[33m", "\x1b[39m"],
	blue: ["\x1b[34m", "\x1b[39m"],
	magenta: ["\x1b[35m", "\x1b[39m"],
	cyan: ["\x1b[36m", "\x1b[39m"],
	white: ["\x1b[37m", "\x1b[39m"],
	gray: ["\x1B[90m", "\x1b[39m"],

	bgBlack: ["\x1b[40m", "\x1b[49m"],
	bgRed: ["\x1b[41m", "\x1b[49m"],
	bgGreen: ["\x1b[42m", "\x1b[49m"],
	bgYellow: ["\x1b[43m", "\x1b[49m"],
	bgBlue: ["\x1b[44m", "\x1b[49m"],
	bgMagenta: ["\x1b[45m", "\x1b[49m"],
	bgCyan: ["\x1b[46m", "\x1b[49m"],
	bgWhite: ["\x1b[47m", "\x1b[49m"],

	dim: ["\x1b[2m", "\x1b[22m"],
	bold: ["\x1b[1m", "\x1b[22m"],
	hidden: ["\x1b[8m", "\x1b[28m"],
	italic: ["\x1b[3m", "\x1b[23m"],
	underline: ["\x1b[4m", "\x1b[24m"],
	inverse: ["\x1b[7m", "\x1b[27m"],
	strikethrough: ["\x1b[9m", "\x1b[29m"],

	newLine: ["\n", "\x1b[0m"],
	tab: ["\t", "\x1b[0m"],
	reset: ["\x1b[0m"]
}

const hasColor = _ =>
	process.env.FORCE_COLOR ||
	process.platform === "win32" ||
	process.stdout.isTTY &&
	process.env.TERM &&
	process.env.TERM !== "dumb"

Object.keys(ansi).forEach(k => ansi[k] = hasColor() ? ansi[k] : ["", ""])

<|endoftext|>


<commit_before>define([
	'./lang', // lang.delegate
	'./debug', // debug.error
	'./properties'
], function (lang, debug, properties) {
	'use strict';

	function isInMethodChain(method, name, prototypes) {
		// summary:
		//		Searches for a method in the given prototype hierarchy
		// returns: Boolean

		return prototypes.some(function (prototype) {
			return prototype[name] === method;
		});
	}

	function getBases(args, prototypeFlag) {
		// summary:
		//		Registers a set of constructors for a class, eliminating duplicate constructors that may result from
		//		diamond construction for classes (e.g. B->A, C->A, D->B&C, then D() should only call A() once)
		// args: Array
		//		An array of constructors to utilise to return
		// prototypeFlag: Boolean
		//		Used to identify if the bases being collected are for the construction of a prototype.
		// returns: Array
		//		An array of constructors for a class

		var bases = [];

		function iterate(args, checkChildren) {
			outer:
			for (var i = 0; i < args.length; i++) {
				var arg = args[i],
					target = prototypeFlag && typeof arg === 'function' ? arg.prototype : arg;
				if (prototypeFlag || typeof arg === 'function') {
					var argGetBases = checkChildren && arg._getBases;
					if (argGetBases) {
						iterate(argGetBases(prototypeFlag));	// don't need to check children for these, they should
																// be pre-flattened
					}
					else {
						for (var j = 0; j < bases.length; j++) {
							if (target === bases[j]) {
								continue outer;
							}
						}
						bases.push(target);
					}
				}
			}
		}

		iterate(args, true);
		return bases;
	}

	function validArg(/* Mixed */ arg) {
		// summary:
		//		Checks to see if a valid argument is being passed and throws an error if it isn't, otherwise returns
		//		the argument

		if (!arg) {
			throw new Error('compose arguments must be functions or objects');
		}
		return arg; // Mixed
	}

	function required() {
		// summary:
		//		A "stub" function used to identify properties that are required in descendent objects.  Throws an
		//		error if called without the property being implemented.

		throw new Error('This method is required and no implementation has been provided');
	}

	function extend() {
		// summary:
		//		A shortcut function to quickly extend an Object via compose

		var args = [this];
		args.push.apply(args, arguments);
		return compose.apply(0, args);
	}

	function mixin(dest, sources) {
		// summary:
		//		A specialised mixin function that handles hierarchial prototypes
		// dest: Object|Function
		//		The base of which the `sources` will be mixed into
		// sources: Array
		//		The source (or sources) that should be mixed into the Object from left to right.
		// returns: Object
		//		The composite of the sources mixed in

		function set(dest, key, value, propertyDescriptor) {
			// summary:
			//		Either sets a value to a property if the property already exists in the target, otherwise defines
			//		a new property using the supplied property descriptor.

			if (key in dest && dest.hasOwnProperty(key)) {
				dest[key] = value;
			}
			else {
				Object.defineProperty(dest, key, propertyDescriptor);
			}
		}

		function mixinPrototype(dest, proto) {
			// summary:
			//		Take a prototype and mix it into a destination, looking for specifically decorated values

			var key, value, own, propertyDescriptor;
			for (key in proto) {
				propertyDescriptor = properties.getDescriptor(proto, key);
				value = proto[key];
				own = proto.hasOwnProperty(key);
				if (typeof value === 'function' && key in dest && value !== dest[key]) {
					if (value === required) {
						// this is a required value, which is now supplied, so fulfilled
						propertyDescriptor = properties.getDescriptor(dest, key);
						value = dest[key];
					}
					else if (!own) {
						if (isInMethodChain(value, key,
								getBases(Array.prototype.slice.call(sources, 0, i + 1), true))) {
							// this value is in the existing method's override chain, we can use the existing method
							propertyDescriptor = properties.getDescriptor(dest, key);
							value = dest[key];
						}
						else if (!isInMethodChain(dest[key], key, getBases([arg], true))) {
							// The existing method is in the current override chain, so we are left with a conflict
							console.error('Conflicted method ' + key + ', final composer must explicitly override' +
									'with correct method.');
						}
					}
				}
				if (value && value.install && own && !isInMethodChain(dest[key], key, getBases([arg], true))) {
					// apply decorator
					value.install.call(dest, key);
				}
				else {
					set(dest, key, value, propertyDescriptor);
				}
			}
		}

		function mixinObject(dest, obj) {
			// summary:
			//		Take an object and mix it into a destination, looking for specifically decorated values

			var key, value, propertyDescriptor;
			for (key in obj) {
				propertyDescriptor = properties.getDescriptor(obj, key);
				value = obj[key];
				if (typeof value === 'function') {
					if (value.install) {
						// apply decorator
						value.install.call(dest, key);
						continue;
					}
					if (key in dest) {
						if (value === required) {
							// requirement met
							continue;
						}
					}
				}
				set(dest, key, value, propertyDescriptor);
			}
		}

		var i, arg;

		for (i = 0; i < sources.length; i++) {
			arg = sources[i];
			if (typeof arg === 'function') {
				mixinPrototype(dest, arg.prototype);
			}
			else {
				mixinObject(dest, validArg(arg));
			}
		}
		return dest;
	}

	function compose(base, extensions) {
		// summary:
		//		Object compositor for JavaScript, featuring JavaScript-style prototype inheritance and composition,
		//		multiple inheritance, mixin and traits-inspired conflict resolution and composition.
		// base: Object|Function
		//		The object or constructor function that is used for the base to be composited upon
		// extensions: Object|Function...
		//		Additional constructor functions or objects to be composited into the base
		// returns: Object
		//		The composited object class, which can be instantiated with `new`

		var args = arguments,
			proto = (args.length < 2 && typeof args[0] !== 'function') ? args[0] :
				mixin(lang.delegate(validArg(base)), Array.prototype.slice.call(arguments, 1));

		var constructors = getBases(args),
			constructorsLength = constructors.length;

		if (typeof args[args.length - 1] === 'object') {
			args[args.length - 1] = proto;
		}

		var prototypes = getBases(args, true);

		function Constructor() {
			// summary:
			//		The base constructor function for compose generated classes.  Will return a new instance, even if
			//		called directly, without the `new` keyword.
			// returns: Object
			//		The constructed object

			var instance = this instanceof Constructor ? this : Object.create(proto);
			for (var i = 0; i < constructorsLength; i++) {
				var constructor = constructors[i],
					result = constructor.apply(instance, arguments);
				if (typeof result === 'object') {
					if (result instanceof Constructor) {
						instance = result;
					}
					else {
						Object.keys(result).forEach(function (key) {
							if (key in instance) {
								instance[key] = result[key];
							}
							else {
								Object.defineProperty(instance, key, Object.getOwnPropertyDescriptor(result, key));
							}
						});
					}
				}
			}
			// accessor properties are not copied as own from prototype, which is desired, therefore they are defined
			// on the target instance
			var propertyDescriptor;
			for (var name in instance) {
				if (!instance.hasOwnProperty(name)) {
					propertyDescriptor = properties.getDescriptor(instance, name);
					if (properties.isAccessorDescriptor(propertyDescriptor)) {
						Object.defineProperty(instance, name, propertyDescriptor);
					}
				}
			}
			return instance;
		}

		// returns "pre-calculated" bases for a Constructor class
		Object.defineProperty(Constructor, '_getBases', {
			value: function (prototypeFlag) {
				return prototypeFlag ? prototypes : constructors;
			}
		});

		// provides an extend function on the Constructor class
		Object.defineProperty(Constructor, 'extend', {
			value: extend,
			writable: true,
			enumerable: true,
			configurable: true
		});

		// if compose not operating in a secure mode, provides a constructor property
		if (!compose.secure) {
			Object.defineProperty(proto, 'constructor', {
				value: Constructor,
				configurable: true
			});
		}

		// sets the prototype for the Constructor
		Constructor.prototype = proto;

		return Constructor;
	}

	Object.defineProperty(compose, 'required', {
		value: required,
		enumerable: true,
		configurable: true
	});

	function decorator(install, direct) {
		function Decorator() {
			if (direct) {
				return direct.apply(this, arguments);
			}
			throw new Error('Decorator not applied');
		}
		Object.defineProperty(Decorator, 'install', {
			value: install,
			enumerable: true,
			configurable: true
		});
		return Decorator;
	}

	Object.defineProperty(compose, 'Decorator', {
		value: decorator,
		enumerable: true,
		configurable: true
	});

	// TODO: convert to `dojo/aspect`
	function aspect(handler) {
		return function (advice) {
			return decorator(function install(name) {
				var baseMethod = this[name];
				(advice = this[name] = baseMethod ? handler(this, baseMethod, advice) : advice).install = install;
			}, advice);
		};
	}

	var stop = {};
	Object.defineProperty(compose, 'stop', {
		value: stop,
		enumerable: true,
		configurable: true
	});

	Object.defineProperty(compose, 'around', {
		value: aspect(function (target, base, advice) {
			return advice.call(target, base);
		}),
		enumerable: true
	});

	Object.defineProperty(compose, 'before', {
		value: aspect(function (target, base, advice) {
			return function () {
				var results = advice.apply(this, arguments);
				if (results !== stop) {
					return base.apply(this, results || arguments);
				}
			};
		}),
		enumerable: true
	});

	Object.defineProperty(compose, 'after', {
		value: aspect(function (target, base, advice) {
			return function () {
				var results = base.apply(this, arguments),
					adviceResults = advice.apply(this, arguments);
				return adviceResults === undefined ? results : adviceResults;
			};
		}),
		enumerable: true
	});

	Object.defineProperty(compose, 'property', {
		value: function (descriptor) {
			return decorator(function (key) {
				var inheritedDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), key);
				if (inheritedDescriptor) {
					mixin(inheritedDescriptor, [descriptor]);
				}
				Object.defineProperty(this, key, inheritedDescriptor || descriptor);
			});
		},
		enumerable: true
	});

	Object.defineProperty(compose, 'from', {
		value: function (trait, fromKey) {
			var descriptor = fromKey ? Object.getOwnPropertyDescriptor((typeof trait === 'function' ?
				trait.prototype : trait), fromKey) : null;
			return decorator(function (key) {
				descriptor = descriptor || (typeof trait === 'string' ? Object.getOwnPropertyDescriptor(this, trait) :
					Object.getOwnPropertyDescriptor((typeof trait === 'function' ? trait.prototype : trait),
						fromKey || key));
				if (descriptor) {
					Object.defineProperty(this, key, descriptor);
				}
				else {
					throw new Error('Source method ' + fromKey + ' was not available to be renamed to ' + key);
				}
			});
		},
		enumerable: true
	});

	Object.defineProperty(compose, 'create', {
		value: function (base) {
			var instance = mixin(lang.delegate(base), Array.prototype.slice.call(arguments, 1)),
				arg;
			for (var i = 0, l = arguments.length; i < l; i++) {
				arg = arguments[i];
				if (typeof arg === 'function') {
					instance = arg.call(instance) || instance;
				}
			}
			return instance;
		},
		enumerable: true
	});

	Object.defineProperty(compose, 'apply', {
		value: function (self, args) {
			return self ? mixin(self, args) :
				extend.apply.call(compose, 0, args);
		}
	});

	Object.defineProperty(compose, 'call', {
		value: function (self) {
			return mixin(self, Array.prototype.slice.call(arguments, 1));
		}
	});

	Object.defineProperty(compose, 'secure', {
		value: false,
		writable: true,
		enumerable: true
	});

	return compose;

});<commit_msg>compose comments and more efficient code<commit_after>define([
	'./lang', // lang.delegate
	'./debug', // debug.error
	'./properties'
], function (lang, debug, properties) {
	'use strict';

	function isInMethodChain(method, name, prototypes) {
		// summary:
		//		Searches for a method in the given prototype hierarchy
		// returns: Boolean

		return prototypes.some(function (prototype) {
			return prototype[name] === method;
		});
	}

	function getBases(args, prototypeFlag) {
		// summary:
		//		Registers a set of constructors for a class, eliminating duplicate constructors that may result from
		//		diamond construction for classes (e.g. B->A, C->A, D->B&C, then D() should only call A() once)
		// args: Array
		//		An array of constructors to utilise to return
		// prototypeFlag: Boolean
		//		Used to identify if the bases being collected are for the construction of a prototype.
		// returns: Array
		//		An array of constructors for a class

		var bases = [];

		function iterate(args, checkChildren) {
			outer:
			for (var i = 0; i < args.length; i++) {
				var arg = args[i],
					target = prototypeFlag && typeof arg === 'function' ? arg.prototype : arg;
				if (prototypeFlag || typeof arg === 'function') {
					var argGetBases = checkChildren && arg._getBases;
					if (argGetBases) {
						iterate(argGetBases(prototypeFlag));	// don't need to check children for these, they should
																// be pre-flattened
					}
					else {
						for (var j = 0; j < bases.length; j++) {
							if (target === bases[j]) {
								continue outer;
							}
						}
						bases.push(target);
					}
				}
			}
		}

		iterate(args, true);
		return bases;
	}

	function validArg(/* Mixed */ arg) {
		// summary:
		//		Checks to see if a valid argument is being passed and throws an error if it isn't, otherwise returns
		//		the argument

		if (!arg) {
			throw new Error('compose arguments must be functions or objects');
		}
		return arg; // Mixed
	}

	function required() {
		// summary:
		//		A "stub" function used to identify properties that are required in descendent objects.  Throws an
		//		error if called without the property being implemented.

		throw new Error('This method is required and no implementation has been provided');
	}

	function extend() {
		// summary:
		//		A shortcut function to quickly extend an Object via compose

		var args = [this];
		args.push.apply(args, arguments);
		return compose.apply(0, args);
	}

	function mixin(dest, sources) {
		// summary:
		//		A specialised mixin function that handles hierarchial prototypes
		// dest: Object|Function
		//		The base of which the `sources` will be mixed into
		// sources: Array
		//		The source (or sources) that should be mixed into the Object from left to right.
		// returns: Object
		//		The composite of the sources mixed in

		function set(dest, key, value, propertyDescriptor) {
			// summary:
			//		Either sets a value to a property if the property already exists in the target, otherwise defines
			//		a new property using the supplied property descriptor.

			if (key in dest && dest.hasOwnProperty(key)) {
				dest[key] = value;
			}
			else {
				Object.defineProperty(dest, key, propertyDescriptor);
			}
		}

		function mixinPrototype(dest, proto) {
			// summary:
			//		Take a prototype and mix it into a destination, looking for specifically decorated values

			var key, value, own, propertyDescriptor;
			for (key in proto) {
				propertyDescriptor = properties.getDescriptor(proto, key);
				value = proto[key];
				own = proto.hasOwnProperty(key);
				if (typeof value === 'function' && key in dest && value !== dest[key]) {
					if (value === required) {
						// this is a required value, which is now supplied, so fulfilled
						propertyDescriptor = properties.getDescriptor(dest, key);
						value = dest[key];
					}
					else if (!own) {
						if (isInMethodChain(value, key,
								getBases(Array.prototype.slice.call(sources, 0, i + 1), true))) {
							// this value is in the existing method's override chain, we can use the existing method
							propertyDescriptor = properties.getDescriptor(dest, key);
							value = dest[key];
						}
						else if (!isInMethodChain(dest[key], key, getBases([arg], true))) {
							// The existing method is in the current override chain, so we are left with a conflict
							console.error('Conflicted method ' + key + ', final composer must explicitly override' +
									'with correct method.');
						}
					}
				}
				if (value && value.install && own && !isInMethodChain(dest[key], key, getBases([arg], true))) {
					// apply decorator
					value.install.call(dest, key);
				}
				else {
					set(dest, key, value, propertyDescriptor);
				}
			}
		}

		function mixinObject(dest, obj) {
			// summary:
			//		Take an object and mix it into a destination, looking for specifically decorated values

			var key, value, propertyDescriptor;
			for (key in obj) {
				propertyDescriptor = properties.getDescriptor(obj, key);
				value = obj[key];
				if (typeof value === 'function') {
					if (value.install) {
						// apply decorator
						value.install.call(dest, key);
						continue;
					}
					if (key in dest) {
						if (value === required) {
							// requirement met
							continue;
						}
					}
				}
				set(dest, key, value, propertyDescriptor);
			}
		}

		var i, arg;

		for (i = 0; i < sources.length; i++) {
			arg = sources[i];
			if (typeof arg === 'function') {
				mixinPrototype(dest, arg.prototype);
			}
			else {
				mixinObject(dest, validArg(arg));
			}
		}
		return dest;
	}

	function compose(base /*=====, extensions =====*/) {
		// summary:
		//		Object compositor for JavaScript, featuring JavaScript-style prototype inheritance and composition,
		//		multiple inheritance, mixin and traits-inspired conflict resolution and composition.
		// base: Object|Function
		//		The object or constructor function that is used for the base to be composited upon
		// extensions: Object|Function...
		//		Additional constructor functions or objects to be composited into the base
		// returns: Object
		//		The composited object class, which can be instantiated with `new`

		var args = arguments,
			proto = (args.length < 2 && typeof args[0] !== 'function') ? args[0] :
				mixin(lang.delegate(validArg(base)), Array.prototype.slice.call(arguments, 1));

		var constructors = getBases(args),
			constructorsLength = constructors.length;

		if (typeof args[args.length - 1] === 'object') {
			args[args.length - 1] = proto;
		}

		var prototypes = getBases(args, true);

		function Constructor() {
			// summary:
			//		The base constructor function for compose generated classes.  Will return a new instance, even if
			//		called directly, without the `new` keyword.
			// returns: Object
			//		The constructed object

			var instance = this instanceof Constructor ? this : Object.create(proto);
			for (var i = 0; i < constructorsLength; i++) {
				var constructor = constructors[i],
					result = constructor.apply(instance, arguments);
				if (typeof result === 'object') {
					if (result instanceof Constructor) {
						instance = result;
					}
					else {
						Object.keys(result).forEach(function (key) {
							if (key in instance) {
								instance[key] = result[key];
							}
							else {
								Object.defineProperty(instance, key, Object.getOwnPropertyDescriptor(result, key));
							}
						});
					}
				}
			}
			// accessor properties are not copied as own from prototype, which is desired, therefore they are defined
			// on the target instance
			var propertyDescriptor;
			for (var name in instance) {
				if (!instance.hasOwnProperty(name)) {
					propertyDescriptor = properties.getDescriptor(instance, name);
					if (properties.isAccessorDescriptor(propertyDescriptor)) {
						Object.defineProperty(instance, name, propertyDescriptor);
					}
				}
			}
			return instance;
		}

		Object.defineProperties(Constructor, {
			// returns "pre-calculated" bases for a Constructor class
			_getBases: {
				value: function (prototypeFlag) {
					return prototypeFlag ? prototypes : constructors;
				}
			},
			// provides an extend function on the Constructor class
			extend: {
				value: extend,
				enumerable: true,
				configurable: true
			}
		});

		// if compose not operating in a secure mode, provides a constructor property
		if (!compose.secure) {
			Object.defineProperty(proto, 'constructor', {
				value: Constructor,
				configurable: true
			});
		}

		// sets the prototype for the Constructor
		Constructor.prototype = proto;

		return Constructor;
	}

	function decorator(install, direct) {
		// summary:
		//		Generates a Decorator function that can be used to special special properties that are required to
		//		be installed via a specific installer.
		function Decorator() {
			if (direct) {
				return direct.apply(this, arguments);
			}
			throw new Error('Decorator not applied');
		}
		Object.defineProperty(Decorator, 'install', {
			value: install,
			enumerable: true,
			configurable: true
		});
		return Decorator;
	}

	// TODO: convert to `dojo/aspect`
	function aspect(handler) {
		return function (advice) {
			return decorator(function install(name) {
				var baseMethod = this[name];
				(advice = this[name] = baseMethod ? handler(this, baseMethod, advice) : advice).install = install;
			}, advice);
		};
	}

	var stop = {};

	Object.defineProperties(compose, {

		// required: Function
		//		A "placeholder" for a property that is required to be defined in a descendent
		required: {
			value: required,
			enumerable: true,
			configurable: true
		},

		// Decorator: Function
		//		A constructor function that generates a decorator function that installs properties with a custom
		//		installer.
		Decorator: {
			value: decorator,
			enumerable: true,
			configurable: true
		},

		// stop: Object
		//		Used to determine the end of a "dependency chain" of functions that are being used for aspect advice
		stop: {
			value: stop,
			enumerable: true,
			configurable: true
		},

		// around: Function
		//		Used to generate a property that gives around aspect advice for the ancestor's property
		around: {
			value: aspect(function (target, base, advice) {
				return advice.call(target, base);
			}),
			enumerable: true
		},

		// before: Function
		//		Used to generate a property that gives before aspect advice for the ancestor's property
		before: {
			value: aspect(function (target, base, advice) {
				return function () {
					var results = advice.apply(this, arguments);
					if (results !== stop) {
						return base.apply(this, results || arguments);
					}
				};
			}),
			enumerable: true
		},

		// after: Function
		//		Used to generate a property that gives after advice for the ancestor's property
		after: {
			value: aspect(function (target, base, advice) {
				return function () {
					var results = base.apply(this, arguments),
						adviceResults = advice.apply(this, arguments);
					return adviceResults === undefined ? results : adviceResults;
				};
			}),
			enumerable: true
		},

		// property: Function
		//		Used to generate a property defined by an ES5 descriptor (which can also understand the aspect advice
		//		for the get and set functions)
		property: {
			value: function (descriptor) {
				return decorator(function (key) {
					var inheritedDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), key);
					if (inheritedDescriptor) {
						mixin(inheritedDescriptor, [descriptor]);
					}
					Object.defineProperty(this, key, inheritedDescriptor || descriptor);
				});
			},
			enumerable: true
		},

		// from: Function
		//		"Copy" a property from a specific ancestor
		from: {
			value: function (trait, fromKey) {
				var descriptor = fromKey ? Object.getOwnPropertyDescriptor((typeof trait === 'function' ?
					trait.prototype : trait), fromKey) : null;
				return decorator(function (key) {
					descriptor = descriptor || (typeof trait === 'string' ? Object.getOwnPropertyDescriptor(this, trait) :
						Object.getOwnPropertyDescriptor((typeof trait === 'function' ? trait.prototype : trait),
							fromKey || key));
					if (descriptor) {
						Object.defineProperty(this, key, descriptor);
					}
					else {
						throw new Error('Source method ' + fromKey + ' was not available to be renamed to ' + key);
					}
				});
			},
			enumerable: true
		},

		// create: Function
		//		A convenience function to create a new instance of a composed object
		create: {
			value: function (base) {
				var instance = mixin(lang.delegate(base), Array.prototype.slice.call(arguments, 1)),
					arg;
				for (var i = 0, l = arguments.length; i < l; i++) {
					arg = arguments[i];
					if (typeof arg === 'function') {
						instance = arg.call(instance) || instance;
					}
				}
				return instance;
			},
			enumerable: true
		},

		apply: {
			value: function (self, args) {
				return self ? mixin(self, args) :
					extend.apply.call(compose, 0, args);
			}
		},
		call: {
			value: function (self) {
				return mixin(self, Array.prototype.slice.call(arguments, 1));
			}
		},

		// secure: Boolean
		//		If operating in secure mode, the constructor property will not be added to generated Constructors,
		//		thereby ensuring that the constructor cannot be manipulated by other code.
		secure: {
			value: false,
			writable: true,
			enumerable: true
		}
	});

	return compose;

});<|endoftext|>


<commit_before>/**
 * Athena Core Javascript Library
 *
 * JSLint Settings:
 * jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true,
 * plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true,
 * immed: true, devel: true
 */

/*****************************************************************************
  Internet Information Superhighway 2.0 v5
*****************************************************************************/

// 'use strict';

( function( window, document, undefined ) {

/**
 * Module namespace
 * @property li
 * @type Object
 */
  var li = {},
  /**
   * List of JS files
   * @property modules
   * @type Array
   */
    modules = [],

  /**
   * Object containing meta data for each module
   * @property packages
   * @type Object
   */
  packages = {},
  /**
   * A hash-map of Resource Loaders
   * @property loaders
   * @type Object
   */
  loaders = {};

  //Allow resource sharing across *.linkedin.com,
  //This should be factored out via proxy.
  if( document.domain.match( 'linkedin.com' ) ) {
    document.domain = 'linkedin.com';
  }

  /**
   * Global configuration object
   * @property ENV_CONFIG
   * @type Object
   */
  window.ENV_CONFIG = ENV_CONFIG || {};

  // merge external and local global configs
  li.environment = _.extend( {
    debug: false,
    baseUri: ''
  }, ENV_CONFIG );

  /**
   * Stores packages in Local Storage if available
   * @method cacheScript
   * @private
   * @param {String} id The package id
   */
  function cacheScript( id ) {
    var pckg,
      key;

    if( Modernizr.localstorage && li.environment.debug === false ) {
      pckg = packages[id];
      key = pckg.id + pckg.version;
      localStorage[key] = pckg.__script;
    }
  }

  /**
   * Executes/evals code.
   * @method evalScript
   * @private
   * @param {String} code The code to evaluate
   */
  function evalScript( code ) {

    if ( window.execScript ) {
      window.execScript( code );
    } else {
      /*
        window.eval.call compresses the JS code into a single line,
        making it hard to debug.  Normal eval seems to work OK though.
      */
      if (li.environment.debug) {
        eval(code);
      }
      else {
        window.eval.call( window, code );
      }
    }

  }

  /**
   * Class to manage javascript dependencies
   * @class Require
   * @constructor
   * @param {Array} ids The list of package ids to load.
   * @param {Function} callback The callback function to execute after loading is complete.
   */
  function Require( ids, callback ) {
    var required = [],
      interfaces = ids,
      request;

    /**
     * Dynamically loads a script file
     * @method getScript
     * @private
     * @param {String} id The identity key for the script
     */
    function getScript( id ) {
      var pckg = packages[id],
        key,
        loader = new ResourceLoader();

      /**
       * Loads an external resource
       * @class ResourceLoader
       * @constructor
       * @for Require
       */
      function ResourceLoader(){
        var ResourceLoader = this;

        /**
         * Generates a globally-unique identifer
         * @method guid
         * @private
         * @return {String} The id
         */
        function guid() {
          function S4() {
            return ( ( ( 1 + Math.random() ) * 0x10000 ) | 0 ).toString( 16 ).substring( 1 );
          }
          return ( S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4() );
        }

        /**
         * The id of the resource loader instance
         * @property id
         * @type String
         */
        ResourceLoader.id = guid();

        // Add this instance into the map of loaders
        loaders[ResourceLoader.id] = ResourceLoader;

        /**
         * Caches and evaluates the loaded script file.
         * @method proxyEventHandler
         * @private
         * @param {Object} response The data returned from loading the script via XHR
         */
        ResourceLoader.proxyEventHandler = function( response ) {
          pckg.__script = response;
          cacheScript( pckg.id );
          resolve( pckg.id );
        };

        /**
         * Description
         * @method Name
         * @public|private
         * @param {Type} Name Description
         */

        ResourceLoader.load = function( url ){
          ( function recurse() {
            if( window.getResource ) {
              window.getResource( ResourceLoader.id, url );
            } else {
              window.setTimeout( recurse, 1 );
            }
          }() );
        };

      }

      function resolve( id ) {
        var i,
          code;

        for( i in packages ) {
          packages[i].requires = _.reject( packages[i].requires, function ( item ) {
            return ( item === id );
          } );
        }

        required = _.reject( required, function( item, index ) {
          if( packages[item].requires.length === 0 && packages[item].__script ) {
            if( li.environment.debug ) {
              // The @ sourceURL forces Firebug to display the filename instead of a generic sequence number on the eval'd code.
              code = ( '( function () {\n' + packages[item].__script + '\nconsole.log(\'Module "' + item + '" ready.\' );\n}() );//@ sourceURL=' + packages[item].path );
            } else {
              code = ( '( function () {\n' + packages[item].__script + '\n}() );' );
            }

            try {
              evalScript( code );
            } catch ( e ) {
              console.error( 'Module ', item, ' could not be loaded.\n', e );
              return false;
            }

            if( module.exports !== true ) {
              eval( packages[item].__namespace + ' = module.exports;' );
              module.exports = true;
            }

            return true;

          } else {
            return false;
          }
        } );

        if( required.length === 0 ) {
          applyCallback( callback );
        }

      }

      if( Modernizr.localstorage && li.environment.debug === false ) {
        key = pckg.id + pckg.version;
        if( localStorage[key] ) {
          pckg.__script = localStorage[key];
          resolve( pckg.id );
          return;
        }
      }

      loader.load( pckg.path );

      return;

    }
    function require( ids ) {
      _.each( ids, function( item, index ) {

        var pckg = packages[item],
          requirements,
          namespaces = item.split( '/' ),
          namespace = 'li',
          context = li;

        _.each( namespaces, function( item, index ) {

          if( context[namespaces[index]] === undefined ) {
            context[namespaces[index]] = {};
          }

          context = context[namespaces[index]];
          namespace += '[\'' + namespaces[index] + '\']';

        } );

        if( !pckg ) {
          console.error( 'The Module with id ' + item + ' is not defined.' );
          return;
        }

        if( !pckg.__required ) {
          pckg.__required = true;
          pckg.__namespace = namespace;
          requirements = pckg.requires;

          ( function recurse( requirements ) {
            if( requirements.length > 0 ) {
              _.each( requirements, function( item, index ) {
                recurse( packages[item].requires );
                if( _.indexOf( pckg.requires, item ) === -1 ) {
                  pckg.requires.push( item );
                }
              } );
            }
          }( requirements ) );

          getScript( pckg.id );

        }

      } );
    }
    function applyCallback( callback ) {
      _.each( interfaces, function( item, index ) {
        interfaces[ index ] = eval( packages[item].__namespace );
      } );
      callback.apply( this, interfaces );
    }

    this.execute = function() {
      ( function gather( ids ) {
        _.each( ids, function( item, index ) {
          if (packages[item]) {
            gather( packages[ item ].requires );
          }

          if( _.indexOf( modules, item ) === -1 ) {
            required.push( item );
            modules.push( item );
          }
        } );
      }( ids ) );

      if( required.length > 0 ) {
        require( required );
      }
    };

  }

  li.define = function( definitions ){
    _.each( definitions, function( item, index ) {
      packages[item.id] = {
        id: item.id,
        version: item.version,
        requires: item.requires || [],
        path: item.path || li.environment.baseUri + item.id + '.js'
      };
    } );
  };

  li.require = function( ids, callback ){
    var pckg;
    if( typeof ids === 'string' ){
      pckg = packages[ids];
      return eval( pckg.__namespace );
    }
    new Require( ids, callback ).execute();
    return false;
  };

  li.proxyEventHandler = function ( event ) {
    var parameters = event.data.split( '&response=' ),
      response,
      key;

    response = parameters[1];
    key = parameters[0].split( '?key=' )[1];

    loaders[key].proxyEventHandler( response );

  };

  //CommonJS
  window.module = { exports: true };

  //Expose li, module to global scope
  window.li = li;

}( this, this.document ) );

( function DependancyTree(){

  li.define( [
    {
      id: 'libraries/ptclass',
      version: '1.0',
      path: '/scripts/libraries/ptclass.js'
    }, {
      id: 'libraries/athena',
      version: '0.0.1',
      path: '/scripts/libraries/athena-0.0.1.js',
      requires: ['libraries/ptclass']
    }, {
      id: 'providers/Event',
      version: '0.0.1',
      path: '/scripts/packages/providers/Event.js',
      requires: ['libraries/ptclass']
    }, {
      id: 'ui/Abstract',
      version: '0.0.1',
      path: '/scripts/packages/ui/Abstract.js',
      requires: ['libraries/ptclass']
    }, {
      id: 'ui/Button',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button.js',
      requires: [ 'libraries/ptclass', 'ui/Abstract' ]
    }, {
      id: 'ui/List',
      version: '0.0.1',
      path: '/scripts/packages/ui/List.js',
      requires: ['ui/Abstract']
    }, {
      id: 'ui/Carousel',
      version: '0.0.1',
      path: '/scripts/packages/ui/Carousel.js',
      requires: ['ui/Abstract', 'ui/List']
    }, {
      id: 'ui/Button/Next',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Next.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Previous',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Previous.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Select',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Select.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Play',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Play.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Pause',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Pause.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Tabs',
      version: '0.0.1',
      path: '/scripts/packages/ui/Tabs.js',
      requires: ['ui/Abstract']
    }
  ] );

}() );
<commit_msg>Updated with ptclass inclusion<commit_after>/**
 * Athena Core Javascript Library
 *
 * JSLint Settings:
 * jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true,
 * plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true,
 * immed: true, devel: true
 */

/*****************************************************************************
  Internet Information Superhighway 2.0 v5
*****************************************************************************/

// 'use strict';

( function( window, document, undefined ) {

/**
 * Module namespace
 * @property li
 * @type Object
 */
  var li = {},
  /**
   * List of JS files
   * @property modules
   * @type Array
   */
    modules = [],

  /**
   * Object containing meta data for each module
   * @property packages
   * @type Object
   */
  packages = {},
  /**
   * A hash-map of Resource Loaders
   * @property loaders
   * @type Object
   */
  loaders = {};

  //Allow resource sharing across *.linkedin.com,
  //This should be factored out via proxy.
  if( document.domain.match( 'linkedin.com' ) ) {
    document.domain = 'linkedin.com';
  }

  /**
   * Global configuration object
   * @property ENV_CONFIG
   * @type Object
   */
  window.ENV_CONFIG = ENV_CONFIG || {};

  // merge external and local global configs
  li.environment = _.extend( {
    debug: false,
    baseUri: ''
  }, ENV_CONFIG );

  /**
   * Stores packages in Local Storage if available
   * @method cacheScript
   * @private
   * @param {String} id The package id
   */
  function cacheScript( id ) {
    var pckg,
      key;

    if( Modernizr.localstorage && li.environment.debug === false ) {
      pckg = packages[id];
      key = pckg.id + pckg.version;
      localStorage[key] = pckg.__script;
    }
  }

  /**
   * Executes/evals code.
   * @method evalScript
   * @private
   * @param {String} code The code to evaluate
   */
  function evalScript( code ) {

    if ( window.execScript ) {
      window.execScript( code );
    } else {
      /*
        window.eval.call compresses the JS code into a single line,
        making it hard to debug.  Normal eval seems to work OK though.
      */
      if (li.environment.debug) {
        eval(code);
      }
      else {
        window.eval.call( window, code );
      }
    }

  }

  /**
   * Class to manage javascript dependencies
   * @class Require
   * @constructor
   * @param {Array} ids The list of package ids to load.
   * @param {Function} callback The callback function to execute after loading is complete.
   */
  function Require( ids, callback ) {
    var required = [],
      interfaces = ids,
      request;

    /**
     * Dynamically loads a script file
     * @method getScript
     * @private
     * @param {String} id The identity key for the script
     */
    function getScript( id ) {
      var pckg = packages[id],
        key,
        loader = new ResourceLoader();

      /**
       * Loads an external resource
       * @class ResourceLoader
       * @constructor
       * @for Require
       */
      function ResourceLoader(){
        var ResourceLoader = this;

        /**
         * Generates a globally-unique identifer
         * @method guid
         * @private
         * @return {String} The id
         */
        function guid() {
          function S4() {
            return ( ( ( 1 + Math.random() ) * 0x10000 ) | 0 ).toString( 16 ).substring( 1 );
          }
          return ( S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4() );
        }

        /**
         * The id of the resource loader instance
         * @property id
         * @type String
         */
        ResourceLoader.id = guid();

        // Add this instance into the map of loaders
        loaders[ResourceLoader.id] = ResourceLoader;

        /**
         * Caches and evaluates the loaded script file.
         * @method proxyEventHandler
         * @private
         * @param {Object} response The data returned from loading the script via XHR
         */
        ResourceLoader.proxyEventHandler = function( response ) {
          pckg.__script = response;
          cacheScript( pckg.id );
          resolve( pckg.id );
        };

        /**
         * Description
         * @method Name
         * @public|private
         * @param {Type} Name Description
         */

        ResourceLoader.load = function( url ){
          ( function recurse() {
            if( window.getResource ) {
              window.getResource( ResourceLoader.id, url );
            } else {
              window.setTimeout( recurse, 1 );
            }
          }() );
        };

      }

      function resolve( id ) {
        var i,
          code;

        for( i in packages ) {
          packages[i].requires = _.reject( packages[i].requires, function ( item ) {
            return ( item === id );
          } );
        }

        required = _.reject( required, function( item, index ) {
          if( packages[item].requires.length === 0 && packages[item].__script ) {
            if( li.environment.debug ) {
              // The @ sourceURL forces Firebug to display the filename instead of a generic sequence number on the eval'd code.
              code = ( '( function () {\n' + packages[item].__script + '\nconsole.log(\'Module "' + item + '" ready.\' );\n}() );//@ sourceURL=' + packages[item].path );
            } else {
              code = ( '( function () {\n' + packages[item].__script + '\n}() );' );
            }

            try {
              evalScript( code );
            } catch ( e ) {
              console.error( 'Module ', item, ' could not be loaded.\n', e );
              return false;
            }

            if( module.exports !== true ) {
              eval( packages[item].__namespace + ' = module.exports;' );
              module.exports = true;
            }

            return true;

          } else {
            return false;
          }
        } );

        if( required.length === 0 ) {
          applyCallback( callback );
        }

      }

      if( Modernizr.localstorage && li.environment.debug === false ) {
        key = pckg.id + pckg.version;
        if( localStorage[key] ) {
          pckg.__script = localStorage[key];
          resolve( pckg.id );
          return;
        }
      }

      loader.load( pckg.path );

      return;

    }
    function require( ids ) {
      _.each( ids, function( item, index ) {

        var pckg = packages[item],
          requirements,
          namespaces = item.split( '/' ),
          namespace = 'li',
          context = li;

        _.each( namespaces, function( item, index ) {

          if( context[namespaces[index]] === undefined ) {
            context[namespaces[index]] = {};
          }

          context = context[namespaces[index]];
          namespace += '[\'' + namespaces[index] + '\']';

        } );

        if( !pckg ) {
          console.error( 'The Module with id ' + item + ' is not defined.' );
          return;
        }

        if( !pckg.__required ) {
          pckg.__required = true;
          pckg.__namespace = namespace;
          requirements = pckg.requires;

          ( function recurse( requirements ) {
            if( requirements.length > 0 ) {
              _.each( requirements, function( item, index ) {
                recurse( packages[item].requires );
                if( _.indexOf( pckg.requires, item ) === -1 ) {
                  pckg.requires.push( item );
                }
              } );
            }
          }( requirements ) );

          getScript( pckg.id );

        }

      } );
    }
    function applyCallback( callback ) {
      _.each( interfaces, function( item, index ) {
        interfaces[ index ] = eval( packages[item].__namespace );
      } );
      callback.apply( this, interfaces );
    }

    this.execute = function() {
      ( function gather( ids ) {
        _.each( ids, function( item, index ) {
          if (packages[item]) {
            gather( packages[ item ].requires );
          }

          if( _.indexOf( modules, item ) === -1 ) {
            required.push( item );
            modules.push( item );
          }
        } );
      }( ids ) );

      if( required.length > 0 ) {
        require( required );
      }
    };

  }

  li.define = function( definitions ){
    _.each( definitions, function( item, index ) {
      packages[item.id] = {
        id: item.id,
        version: item.version,
        requires: item.requires || [],
        path: item.path || li.environment.baseUri + item.id + '.js'
      };
    } );
  };

  li.require = function( ids, callback ){
    var pckg;
    if( typeof ids === 'string' ){
      pckg = packages[ids];
      return eval( pckg.__namespace );
    }
    new Require( ids, callback ).execute();
    return false;
  };

  li.proxyEventHandler = function ( event ) {
    var parameters = event.data.split( '&response=' ),
      response,
      key;

    response = parameters[1];
    key = parameters[0].split( '?key=' )[1];

    loaders[key].proxyEventHandler( response );

  };

  //CommonJS
  window.module = { exports: true };

  //Expose li, module to global scope
  window.li = li;

}( this, this.document ) );

( function DependancyTree(){

  li.define( [
    {
      id: 'libraries/ptclass',
      version: '1.0',
      path: '/scripts/libraries/ptclass.js'
    }, {
      id: 'libraries/athena',
      version: '0.0.1',
      path: '/scripts/libraries/athena-0.0.1.js',
      requires: ['libraries/ptclass']
    }, {
      id: 'providers/Event',
      version: '0.0.1',
      path: '/scripts/packages/providers/Event.js',
      requires: ['libraries/ptclass']
    }, {
      id: 'ui/Abstract',
      version: '0.0.1',
      path: '/scripts/packages/ui/Abstract.js',
      requires: ['libraries/ptclass']
    }, {
      id: 'ui/Button',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button.js',
      requires: [ 'libraries/ptclass', 'ui/Abstract' ]
    }, {
      id: 'ui/List',
      version: '0.0.1',
      path: '/scripts/packages/ui/List.js',
      requires: ['ui/Abstract']
    }, {
      id: 'ui/Carousel',
      version: '0.0.1',
      path: '/scripts/packages/ui/Carousel.js',
      requires: ['ui/Abstract', 'ui/List']
    }, {
      id: 'ui/Button/Next',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Next.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Previous',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Previous.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Select',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Select.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Play',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Play.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Button/Pause',
      version: '0.0.1',
      path: '/scripts/packages/ui/Button/Pause.js',
      requires: [ 'libraries/ptclass', 'ui/Button' ]
    }, {
      id: 'ui/Tabs',
      version: '0.0.1',
      path: '/scripts/packages/ui/Tabs.js',
      requires: ['libraries/ptclass', 'ui/Abstract']
    }
  ] );

}() );
<|endoftext|>


<commit_before>/*
 * Copyright (c) $year, Den Norske Turistforening (DNT)
 *
 * https://github.com/Turistforeningen/turadmin
 */

define(function (require, exports, module) {
    "use strict";

    // Dependencies
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        L = require('leaflet'),
        NtbModel = require('models/ntb');

    // Module
    return NtbModel.extend({

        idAttribute: '_id',

        defaults: {
            // navn: '', // Not set as default, because of validation
            // beskrivelse: '', // Not set as default, because of validation
            lenker: [],
            tidsbrukDager: '1',
            tidsbrukTimer: '0',
            tidsbrukMinutter: '0',
            tidsbruk: {normal: {dager: 1, timer: 0, minutter: 0}},
            retning: 'ABA',
            lisens: 'CC BY-NC 4.0',
            status: 'Kladd',
            tags: [],
            // gradering: '', // Not set as default, because of validation
            privat: {}
        },

        serverAttrs: [
            // '_id', 'tilbyder', 'endret', 'checksum' // Legges automatisk inn av Nasjonal Turbase
            'lisens',
            'navngiving',
            'status',
            'navn',
            'geojson',
            'distanse',
            'retning',
            'områder',
            'kommuner',
            'fylker',
            'beskrivelse',
            'adkomst',
            'kollektiv', // NOTE: Will this be a private field?
            'lenker',
            'gradering',
            'passer_for',
            'tilrettelagt_for',
            'sesong',
            'tidsbruk',
            'tags',
            'privat',
            'grupper',
            'bilder',
            'steder',
            'url'
        ],

        validation: {
            'geojson.coordinates': function (value) {
                if (!this.hasRoute()) {
                    return 'Turforslaget må inneholde en inntegning av turen.';
                }
            },
            navn: {
                required: true,
                msg: 'Dette feltet er påkrevd.'
            },
            beskrivelse:  {
                required: true,
                msg: 'Dette feltet er påkrevd.'
            },
            gradering: {
                required: true,
                msg: 'Dette feltet er påkrevd.'
            },
            sesong: {
                // arrayMinLength: 1,
                required: true,
                msg: 'Velg minst én måned det normalt er mulig å gjennomføre turen.'
            },
            turtype: {
                required: true,
                msg: 'Minst én turtype må velges'
            }
        },

        initialize: function (options) {

            if (!!this.idAttribute && !!this.get(this.idAttribute)) {
                this.set('id', this.get(this.idAttribute));
            }

            this.on('change:turtype', this.updateTurtypeInTags);
            this.on('change:flereTurtyper', this.updateFlereTurtyperInTags);

            var duration = this.get('tidsbruk');

            if (!!duration.normal) {
                this.set('tidsbrukDager', (!!duration.normal.dager) ? '' + duration.normal.dager : '0');
                this.set('tidsbrukTimer', (!!duration.normal.timer) ? '' + duration.normal.timer: '0');
                this.set('tidsbrukMinutter', (!!duration.normal.minutter) ? '' + duration.normal.minutter: '0');
            }

            this.set('turtype', this.getRouteType());
            this.set('flereTurtyper', this.getAdditionalRouteTypes());

            NtbModel.prototype.initialize.call(this, options);

        },

        urlRoot: function () {
            return '/restProxy/turer';
        },

        setPoiIds: function (ids) {
            this.set('steder', ids);
        },

        setPictureIds: function (ids) {
            this.set('bilder', ids);
        },

        updateStartpunkt: function () {
            var geojson = this.get('geojson'),
                privat = this.get('privat') || {},
                startpunkt;

            if (geojson && geojson.coordinates && geojson.coordinates.length) {
                startpunkt = geojson.coordinates[0];
                privat.startpunkt = {type: 'Point', coordinates: startpunkt};
            } else {
                if (privat.startpunkt) {
                    delete privat.startpunkt;
                }
            }
        },

        updateTurtypeInTags: function () {
            var tags = this.get('tags');
            var turtype = this.get('turtype');
            tags[0] = turtype;
            this.set('tags', tags);
        },

        updateFlereTurtyperInTags: function () {
            var tags = this.get('tags');
            var turtype = tags[0];
            var flereTurtyper = this.get('flereTurtyper');
            tags = [turtype].concat(flereTurtyper);
            this.set('tags', tags);
        },

        getRouteType: function () {
            var tags = this.get('tags');
            return (tags.length) ? tags[0] : '';
        },

        getAdditionalRouteTypes: function () {
            var tags = this.get('tags');
            var additionalRouteTypes = _.rest(tags, 1);
            return additionalRouteTypes;
        },

        hasRoute: function () {
            var geojson = this.get('geojson');
            return (geojson && geojson.coordinates.length) ? true : false;
        },

        // Season months must be saved as integers
        updateSeason: function () {
            var season = this.get('sesong');
            if (!!season && season.length) {
                for (var i = 0; i < season.length; i++) {
                    season[i] = parseInt(season[i], 10);
                }
                this.set('sesong', season);
            }
        },

        save: function (attrs, options) {

            this.updateStartpunkt();
            this.updateSeason();
            this.updateTidsbruk();

            attrs = attrs || this.toJSON();
            options = options || {};

            // Remove geojson if empty
            if (!this.hasRoute()) {
                delete attrs.geojson;
            }

            // Call super with attrs moved to options
            return NtbModel.prototype.save.call(this, attrs, options);
        },

        updateTidsbruk: function () {
            var days = parseInt(this.get('tidsbrukDager'), 10);
            var hours = parseInt(this.get('tidsbrukTimer'), 10);
            var minutes = parseInt(this.get('tidsbrukMinutter'), 10);
            var tidsbruk = {normal:{}};

            if (days === 1) {
                tidsbruk.normal = {
                    dager: days,
                    timer: hours,
                    minutter: minutes
                };

            } else {
                tidsbruk.normal = {
                    dager: days,
                    timer: 0,
                    minutter: 0
                };
            }

            this.set('tidsbruk', tidsbruk);
        }

    });

});
<commit_msg>Update defaults in model to reflect ui (days == 1 && hours == 0 is not possible)<commit_after>/*
 * Copyright (c) $year, Den Norske Turistforening (DNT)
 *
 * https://github.com/Turistforeningen/turadmin
 */

define(function (require, exports, module) {
    "use strict";

    // Dependencies
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        L = require('leaflet'),
        NtbModel = require('models/ntb');

    // Module
    return NtbModel.extend({

        idAttribute: '_id',

        defaults: {
            // navn: '', // Not set as default, because of validation
            // beskrivelse: '', // Not set as default, because of validation
            lenker: [],
            tidsbrukDager: '1',
            tidsbrukTimer: '1',
            tidsbrukMinutter: '0',
            tidsbruk: {normal: {dager: 1, timer: 1, minutter: 0}},
            retning: 'ABA',
            lisens: 'CC BY-NC 4.0',
            status: 'Kladd',
            tags: [],
            // gradering: '', // Not set as default, because of validation
            privat: {}
        },

        serverAttrs: [
            // '_id', 'tilbyder', 'endret', 'checksum' // Legges automatisk inn av Nasjonal Turbase
            'lisens',
            'navngiving',
            'status',
            'navn',
            'geojson',
            'distanse',
            'retning',
            'områder',
            'kommuner',
            'fylker',
            'beskrivelse',
            'adkomst',
            'kollektiv', // NOTE: Will this be a private field?
            'lenker',
            'gradering',
            'passer_for',
            'tilrettelagt_for',
            'sesong',
            'tidsbruk',
            'tags',
            'privat',
            'grupper',
            'bilder',
            'steder',
            'url'
        ],

        validation: {
            'geojson.coordinates': function (value) {
                if (!this.hasRoute()) {
                    return 'Turforslaget må inneholde en inntegning av turen.';
                }
            },
            navn: {
                required: true,
                msg: 'Dette feltet er påkrevd.'
            },
            beskrivelse:  {
                required: true,
                msg: 'Dette feltet er påkrevd.'
            },
            gradering: {
                required: true,
                msg: 'Dette feltet er påkrevd.'
            },
            sesong: {
                // arrayMinLength: 1,
                required: true,
                msg: 'Velg minst én måned det normalt er mulig å gjennomføre turen.'
            },
            turtype: {
                required: true,
                msg: 'Minst én turtype må velges'
            }
        },

        initialize: function (options) {

            if (!!this.idAttribute && !!this.get(this.idAttribute)) {
                this.set('id', this.get(this.idAttribute));
            }

            this.on('change:turtype', this.updateTurtypeInTags);
            this.on('change:flereTurtyper', this.updateFlereTurtyperInTags);

            var duration = this.get('tidsbruk');

            if (!!duration.normal) {
                this.set('tidsbrukDager', (!!duration.normal.dager) ? '' + duration.normal.dager : '0');
                this.set('tidsbrukTimer', (!!duration.normal.timer) ? '' + duration.normal.timer: '0');
                this.set('tidsbrukMinutter', (!!duration.normal.minutter) ? '' + duration.normal.minutter: '0');
            }

            this.set('turtype', this.getRouteType());
            this.set('flereTurtyper', this.getAdditionalRouteTypes());

            NtbModel.prototype.initialize.call(this, options);

        },

        urlRoot: function () {
            return '/restProxy/turer';
        },

        setPoiIds: function (ids) {
            this.set('steder', ids);
        },

        setPictureIds: function (ids) {
            this.set('bilder', ids);
        },

        updateStartpunkt: function () {
            var geojson = this.get('geojson'),
                privat = this.get('privat') || {},
                startpunkt;

            if (geojson && geojson.coordinates && geojson.coordinates.length) {
                startpunkt = geojson.coordinates[0];
                privat.startpunkt = {type: 'Point', coordinates: startpunkt};
            } else {
                if (privat.startpunkt) {
                    delete privat.startpunkt;
                }
            }
        },

        updateTurtypeInTags: function () {
            var tags = this.get('tags');
            var turtype = this.get('turtype');
            tags[0] = turtype;
            this.set('tags', tags);
        },

        updateFlereTurtyperInTags: function () {
            var tags = this.get('tags');
            var turtype = tags[0];
            var flereTurtyper = this.get('flereTurtyper');
            tags = [turtype].concat(flereTurtyper);
            this.set('tags', tags);
        },

        getRouteType: function () {
            var tags = this.get('tags');
            return (tags.length) ? tags[0] : '';
        },

        getAdditionalRouteTypes: function () {
            var tags = this.get('tags');
            var additionalRouteTypes = _.rest(tags, 1);
            return additionalRouteTypes;
        },

        hasRoute: function () {
            var geojson = this.get('geojson');
            return (geojson && geojson.coordinates.length) ? true : false;
        },

        // Season months must be saved as integers
        updateSeason: function () {
            var season = this.get('sesong');
            if (!!season && season.length) {
                for (var i = 0; i < season.length; i++) {
                    season[i] = parseInt(season[i], 10);
                }
                this.set('sesong', season);
            }
        },

        save: function (attrs, options) {

            this.updateStartpunkt();
            this.updateSeason();
            this.updateTidsbruk();

            attrs = attrs || this.toJSON();
            options = options || {};

            // Remove geojson if empty
            if (!this.hasRoute()) {
                delete attrs.geojson;
            }

            // Call super with attrs moved to options
            return NtbModel.prototype.save.call(this, attrs, options);
        },

        updateTidsbruk: function () {
            var days = parseInt(this.get('tidsbrukDager'), 10);
            var hours = parseInt(this.get('tidsbrukTimer'), 10);
            var minutes = parseInt(this.get('tidsbrukMinutter'), 10);
            var tidsbruk = {normal:{}};

            if (days === 1) {
                tidsbruk.normal = {
                    dager: days,
                    timer: hours,
                    minutter: minutes
                };

            } else {
                tidsbruk.normal = {
                    dager: days,
                    timer: 0,
                    minutter: 0
                };
            }

            this.set('tidsbruk', tidsbruk);
        }

    });

});
<|endoftext|>


<commit_before>(function() {
  require(["jquery"], function($) {
    var projects = document.querySelectorAll("tr.bramble-user-project");
    var queryString = window.location.search;
    // We do this to deal with the weird Firefox caching issue
    // that does not allow a click on the project name to reach the
    // `/projects/:projectID` route and instead just loads a cached
    // vaersion of `/`
    var cacheBust = "cacheBust=" + Date.now();
    queryString = queryString === "" ? "?" + cacheBust : queryString + "&" + cacheBust;

    function getElapsedTime(lastEdited) {
      var now = Date.now();
      lastEdited = new Date(lastEdited);
      var elapsedTime, unit = "";
      var secondsElapsed = (now - lastEdited) / 1000;
      var minutesElapsed = secondsElapsed / 60;
      var hoursElapsed = minutesElapsed / 60;
      var daysElapsed = hoursElapsed / 24;

      if(daysElapsed > 31) {
        elapsedTime = "over a month";
      } else if(daysElapsed >= 1) {
        elapsedTime = Math.round(daysElapsed);
        unit = elapsedTime === 1 ? " day" : " days";
      } else if(hoursElapsed >= 1) {
        elapsedTime = Math.round(hoursElapsed);
        unit = elapsedTime === 1 ? " hour" : " hours";
      } else if(minutesElapsed >= 1) {
        elapsedTime = Math.round(minutesElapsed);
        unit = elapsedTime === 1 ? " minute" : " minutes";
      } else {
        elapsedTime = Math.round(secondsElapsed);
        unit = elapsedTime === 1 ? " second" : " seconds";
      }

      return "Last Edited " + elapsedTime + unit + " ago";
    }

    Array.prototype.forEach.call(projects, function(project) {
      var projectSelector = "#" + project.getAttribute("id");
      var lastEdited = project.getAttribute("data-project-date_updated");

      $(projectSelector + " > .project-title").on("click", function() {
        window.location.href = "/project/" + project.getAttribute("data-project-id") + queryString;
      });
      $(projectSelector + " .project-information").text(getElapsedTime(lastEdited));
    });

    $("#project-0").on("click", function() {
      window.location.href = "/newProject" + queryString + "&now=" + (new Date()).toISOString();
    });

    $("td.project-delete").click(function() {
      var project = $(this).parent();
      $(this).text("Deleting...");

      var projectId = project.attr("data-project-id");
      var projectElementId = project.attr("id");
      $("#" + projectElementId + " > .project-title").off("click");

      var request = $.ajax({
        headers: {
          "X-Csrf-Token": $("meta[name='csrf-token']").attr("content")
        },
        type: "DELETE",
        url: "/deleteProject/" + projectId
      });
      request.done(function() {
        if(request.status !== 204) {
          console.error("Error sending delete request");
          return;
        }

        project.hide({
          duration: 1000,
          easing: "linear",
          done: function() {
            project.remove();
          }
        });
      });
      request.fail(function(jqXHR, status, err) {
        console.error(err);
      });
    });
  });
}());
<commit_msg>Add separate requirejs config for open-projects.js<commit_after>require.config({
  paths: {
    "jquery": "/bower/jquery/index"
  },
  shim: {
    "jquery": {
      exports: "$"
    }
  }
});

require(["jquery"], function($) {
  var projects = document.querySelectorAll("tr.bramble-user-project");
  var queryString = window.location.search;
  // We do this to deal with the weird Firefox caching issue
  // that does not allow a click on the project name to reach the
  // `/projects/:projectID` route and instead just loads a cached
  // vaersion of `/`
  var cacheBust = "cacheBust=" + Date.now();
  queryString = queryString === "" ? "?" + cacheBust : queryString + "&" + cacheBust;

  function getElapsedTime(lastEdited) {
    var now = Date.now();
    lastEdited = new Date(lastEdited);
    var elapsedTime, unit = "";
    var secondsElapsed = (now - lastEdited) / 1000;
    var minutesElapsed = secondsElapsed / 60;
    var hoursElapsed = minutesElapsed / 60;
    var daysElapsed = hoursElapsed / 24;

    if(daysElapsed > 31) {
      elapsedTime = "over a month";
    } else if(daysElapsed >= 1) {
      elapsedTime = Math.round(daysElapsed);
      unit = elapsedTime === 1 ? " day" : " days";
    } else if(hoursElapsed >= 1) {
      elapsedTime = Math.round(hoursElapsed);
      unit = elapsedTime === 1 ? " hour" : " hours";
    } else if(minutesElapsed >= 1) {
      elapsedTime = Math.round(minutesElapsed);
      unit = elapsedTime === 1 ? " minute" : " minutes";
    } else {
      elapsedTime = Math.round(secondsElapsed);
      unit = elapsedTime === 1 ? " second" : " seconds";
    }

    return "Last Edited " + elapsedTime + unit + " ago";
  }

  Array.prototype.forEach.call(projects, function(project) {
    var projectSelector = "#" + project.getAttribute("id");
    var lastEdited = project.getAttribute("data-project-date_updated");

    $(projectSelector + " > .project-title").on("click", function() {
      window.location.href = "/project/" + project.getAttribute("data-project-id") + queryString;
    });
    $(projectSelector + " .project-information").text(getElapsedTime(lastEdited));
  });

  $("#project-0").on("click", function() {
    window.location.href = "/newProject" + queryString + "&now=" + (new Date()).toISOString();
  });

  $("td.project-delete").click(function() {
    var project = $(this).parent();
    $(this).text("Deleting...");

    var projectId = project.attr("data-project-id");
    var projectElementId = project.attr("id");
    $("#" + projectElementId + " > .project-title").off("click");

    var request = $.ajax({
      headers: {
        "X-Csrf-Token": $("meta[name='csrf-token']").attr("content")
      },
      type: "DELETE",
      url: "/deleteProject/" + projectId
    });
    request.done(function() {
      if(request.status !== 204) {
        console.error("Error sending delete request");
        return;
      }

      project.hide({
        duration: 1000,
        easing: "linear",
        done: function() {
          project.remove();
        }
      });
    });
    request.fail(function(jqXHR, status, err) {
      console.error(err);
    });
  });
});
<|endoftext|>


<commit_before>import ReactGA from 'react-ga';
import { setAppName, setVersion, APP_TOOLS } from './config';
import { setAppColors } from './styles/colors';
import routes from './routes/toolsRoutes';
import initializeApp from './index';

/**
 * This serves as the primary entry point to the Media Cloud Topic Mapper app.
 */

ReactGA.initialize('UA-60744513-9');

setVersion('3.4.2');

setAppName(APP_TOOLS);

setAppColors({
  light: '#BDBDBD',
  dark: '#616161',
  darker: '#1F1F1F',
  main: '#616161',
});

initializeApp(routes);
<commit_msg>version bump for release<commit_after>import ReactGA from 'react-ga';
import { setAppName, setVersion, APP_TOOLS } from './config';
import { setAppColors } from './styles/colors';
import routes from './routes/toolsRoutes';
import initializeApp from './index';

/**
 * This serves as the primary entry point to the Media Cloud Topic Mapper app.
 */

ReactGA.initialize('UA-60744513-9');

setVersion('3.5.0');

setAppName(APP_TOOLS);

setAppColors({
  light: '#BDBDBD',
  dark: '#616161',
  darker: '#1F1F1F',
  main: '#616161',
});

initializeApp(routes);
<|endoftext|>