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

define("ace/mode/vyper_highlight_rules", function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var VyperHighlightRules = function() {

	var keywords = (
		"and|as|assert|break|continue|def|del|elif|else|" +
		"for|from|if|import|in|is|not|or|pass|raise|return|while|" +
		"with|int128|int256|uint256|decimal|real|address|contract|bool|bytes32|" +
		"bytes|timestamp|wei_value|currency_value|indexed|real128x128|until|push|" +
		"dup|swap|stop|throw|event|public|private|payable|constant"
	);

	var builtinConstants = (
		"true|false|None|NotImplemented|Ellipsis|ERC20|ether|wei|finney|" +
		"szabo|shannon|lovelace|ada|babbage|gwei|kwei|mwei|twei|pwei"
	);

	var builtinFunctions = (
		"send|call|selfdestruct|convert|floor|ceil|uint256_add|uint256_sub|" +
		"uint256_mul|uint256_div|uint256_mod|uint256_mulmod|uint256_addmod|" +
		"uint256_exp|uint256_gt|uint256_ge|uint256_lt|uint256_le|shift|" +
		"create_with_code_of|RLPList|min|max|keccak256|slice|as_unitless_number|" +
		"concat|len|sha3|method_id|ecrecover|avo|ecadd|ecmul|extract32|" +
		"as_wei_value|raw_call|blockhash|raw_log|bitwise_and|bitwise_or|" +
		"bitwise_xor|bitwise_not"
	);

	//var futureReserved = "";
	var keywordMapper = this.createKeywordMapper({
		"invalid.deprecated": "internal|__log__|num|num256",
		"support.function": builtinFunctions,
		"variable.language": "self|cls|msg|block",
		"constant.language": builtinConstants,
		"keyword": keywords
	}, "identifier");

	var strPre = "(?:r|u|ur|R|U|UR|Ur|uR)?";

	var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
	var octInteger = "(?:0[oO]?[0-7]+)";
	var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
	var binInteger = "(?:0[bB][01]+)";
	var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";

	var exponent = "(?:[eE][+-]?\\d+)";
	var fraction = "(?:\\.\\d+)";
	var intPart = "(?:\\d+)";
	var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
	var exponentFloat = "(?:(?:" + pointFloat + "|" +  intPart + ")" + exponent + ")";
	var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";

	var stringEscape =  "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";

	this.$rules = {
		"start" : [ {
			token : "comment",
			regex : "#.*$"
		}, {
			token : "string",           // multi line """ string start
			regex : strPre + '"{3}',
			next : "qqstring3"
		}, {
			token : "string",           // " string
			regex : strPre + '"(?=.)',
			next : "qqstring"
		}, {
			token : "string",           // multi line ''' string start
			regex : strPre + "'{3}",
			next : "qstring3"
		}, {
			token : "string",           // ' string
			regex : strPre + "'(?=.)",
			next : "qstring"
		}, {
			token : "constant.numeric", // imaginary
			regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
		}, {
			token : "constant.numeric", // float
			regex : floatNumber
		}, {
			token : "constant.numeric", // long integer
			regex : integer + "[lL]\\b"
		}, {
			token : "constant.numeric", // integer
			regex : integer + "\\b"
		}, {
			token : keywordMapper,
			regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
		}, {
			token : "keyword.operator",
			regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
		}, {
			token : "paren.lparen",
			regex : "[\\[\\(\\{]"
		}, {
			token : "paren.rparen",
			regex : "[\\]\\)\\}]"
		}, {
			token : "text",
			regex : "\\s+"
		} ],
		"qqstring3" : [ {
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string", // multi line """ string end
			regex : '"{3}',
			next : "start"
		}, {
			defaultToken : "string"
		} ],
		"qstring3" : [ {
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string",  // multi line ''' string end
			regex : "'{3}",
			next : "start"
		}, {
			defaultToken : "string"
		} ],
		"qqstring" : [{
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string",
			regex : "\\\\$",
			next  : "qqstring"
		}, {
			token : "string",
			regex : '"|$',
			next  : "start"
		}, {
			defaultToken: "string"
		}],
		"qstring" : [{
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string",
			regex : "\\\\$",
			next  : "qstring"
		}, {
			token : "string",
			regex : "'|$",
			next  : "start"
		}, {
			defaultToken: "string"
		}]
	};
};

oop.inherits(VyperHighlightRules, TextHighlightRules);

exports.VyperHighlightRules = VyperHighlightRules;
});

define("ace/mode/folding/pythonic", function(require, exports, module) {
"use strict";

var oop = require("../../lib/oop");
var BaseFoldMode = require("./fold_mode").FoldMode;

var FoldMode = exports.FoldMode = function(markers) {
	this.foldingStartMarker = new RegExp("([\\[{])(?:\\s*)$|(" + markers + ")(?:\\s*)(?:#.*)?$");
};
oop.inherits(FoldMode, BaseFoldMode);

(function() {

	this.getFoldWidgetRange = function(session, foldStyle, row) {
		var line = session.getLine(row);
		var match = line.match(this.foldingStartMarker);
		if (match) {
			if (match[1])
				return this.openingBracketBlock(session, match[1], row, match.index);
			if (match[2])
				return this.indentationBlock(session, row, match.index + match[2].length);
			return this.indentationBlock(session, row);
		}
	};

}).call(FoldMode.prototype);

});

define("ace/mode/vyper", function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var VyperHighlightRules = require("./vyper_highlight_rules").VyperHighlightRules;
var PythonFoldMode = require("./folding/pythonic").FoldMode;
var Range = require("../range").Range;

var Mode = function() {
	this.HighlightRules = VyperHighlightRules;
	this.foldingRules = new PythonFoldMode("\\:");
	this.$behaviour = this.$defaultBehaviour;
};
oop.inherits(Mode, TextMode);

(function() {

	this.lineCommentStart = "#";

	this.getNextLineIndent = function(state, line, tab) {
		var indent = this.$getIndent(line);

		var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
		var tokens = tokenizedLine.tokens;

		if (tokens.length && tokens[tokens.length-1].type == "comment") {
			return indent;
		}

		if (state == "start") {
			var match = line.match(/^.*[\{\(\[:]\s*$/);
			if (match) {
				indent += tab;
			}
		}

		return indent;
	};

	var outdents = {
		"pass": 1,
		"return": 1,
		"raise": 1,
		"break": 1,
		"continue": 1
	};

	this.checkOutdent = function(state, line, input) {
		if (input !== "\r\n" && input !== "\r" && input !== "\n")
			return false;

		var tokens = this.getTokenizer().getLineTokens(line.trim(), state).tokens;

		if (!tokens)
			return false;

		// ignore trailing comments
		do {
			var last = tokens.pop();
		} while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));

		if (!last)
			return false;

		return (last.type == "keyword" && outdents[last.value]);
	};

	this.autoOutdent = function(state, doc, row) {
		// outdenting in python is slightly different because it always applies
		// to the next line and only of a new line is inserted

		row += 1;
		var indent = this.$getIndent(doc.getLine(row));
		var tab = doc.getTabString();
		if (indent.slice(-tab.length) == tab)
			doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
	};

	this.$id = "ace/mode/vyper";
}).call(Mode.prototype);

exports.Mode = Mode;
});
<commit_msg>Added True False highlighting and deprecated while<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

define("ace/mode/vyper_highlight_rules", function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var VyperHighlightRules = function() {

	var keywords = (
		"and|as|assert|break|continue|def|del|elif|else|" +
		"for|from|if|import|in|is|not|or|pass|raise|return|while|" +
		"with|int128|int256|uint256|decimal|real|address|contract|bool|bytes32|" +
		"bytes|timestamp|wei_value|currency_value|indexed|real128x128|until|push|" +
		"dup|swap|stop|throw|event|public|private|payable|constant"
	);

	var builtinConstants = (
		"true|false|True|False|None|NotImplemented|Ellipsis|ERC20|ether|wei|finney|" +
		"szabo|shannon|lovelace|ada|babbage|gwei|kwei|mwei|twei|pwei"
	);

	var builtinFunctions = (
		"send|call|selfdestruct|convert|floor|ceil|uint256_add|uint256_sub|" +
		"uint256_mul|uint256_div|uint256_mod|uint256_mulmod|uint256_addmod|" +
		"uint256_exp|uint256_gt|uint256_ge|uint256_lt|uint256_le|shift|" +
		"create_with_code_of|RLPList|min|max|keccak256|slice|as_unitless_number|" +
		"concat|len|sha3|method_id|ecrecover|avo|ecadd|ecmul|extract32|" +
		"as_wei_value|raw_call|blockhash|raw_log|bitwise_and|bitwise_or|" +
		"bitwise_xor|bitwise_not"
	);

	//var futureReserved = "";
	var keywordMapper = this.createKeywordMapper({
		"invalid.deprecated": "internal|__log__|num|num256|while",
		"support.function": builtinFunctions,
		"variable.language": "self|cls|msg|block",
		"constant.language": builtinConstants,
		"keyword": keywords
	}, "identifier");

	var strPre = "(?:r|u|ur|R|U|UR|Ur|uR)?";

	var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
	var octInteger = "(?:0[oO]?[0-7]+)";
	var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
	var binInteger = "(?:0[bB][01]+)";
	var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";

	var exponent = "(?:[eE][+-]?\\d+)";
	var fraction = "(?:\\.\\d+)";
	var intPart = "(?:\\d+)";
	var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
	var exponentFloat = "(?:(?:" + pointFloat + "|" +  intPart + ")" + exponent + ")";
	var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";

	var stringEscape =  "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";

	this.$rules = {
		"start" : [ {
			token : "comment",
			regex : "#.*$"
		}, {
			token : "string",           // multi line """ string start
			regex : strPre + '"{3}',
			next : "qqstring3"
		}, {
			token : "string",           // " string
			regex : strPre + '"(?=.)',
			next : "qqstring"
		}, {
			token : "string",           // multi line ''' string start
			regex : strPre + "'{3}",
			next : "qstring3"
		}, {
			token : "string",           // ' string
			regex : strPre + "'(?=.)",
			next : "qstring"
		}, {
			token : "constant.numeric", // imaginary
			regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
		}, {
			token : "constant.numeric", // float
			regex : floatNumber
		}, {
			token : "constant.numeric", // long integer
			regex : integer + "[lL]\\b"
		}, {
			token : "constant.numeric", // integer
			regex : integer + "\\b"
		}, {
			token : keywordMapper,
			regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
		}, {
			token : "keyword.operator",
			regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
		}, {
			token : "paren.lparen",
			regex : "[\\[\\(\\{]"
		}, {
			token : "paren.rparen",
			regex : "[\\]\\)\\}]"
		}, {
			token : "text",
			regex : "\\s+"
		} ],
		"qqstring3" : [ {
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string", // multi line """ string end
			regex : '"{3}',
			next : "start"
		}, {
			defaultToken : "string"
		} ],
		"qstring3" : [ {
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string",  // multi line ''' string end
			regex : "'{3}",
			next : "start"
		}, {
			defaultToken : "string"
		} ],
		"qqstring" : [{
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string",
			regex : "\\\\$",
			next  : "qqstring"
		}, {
			token : "string",
			regex : '"|$',
			next  : "start"
		}, {
			defaultToken: "string"
		}],
		"qstring" : [{
			token : "constant.language.escape",
			regex : stringEscape
		}, {
			token : "string",
			regex : "\\\\$",
			next  : "qstring"
		}, {
			token : "string",
			regex : "'|$",
			next  : "start"
		}, {
			defaultToken: "string"
		}]
	};
};

oop.inherits(VyperHighlightRules, TextHighlightRules);

exports.VyperHighlightRules = VyperHighlightRules;
});

define("ace/mode/folding/pythonic", function(require, exports, module) {
"use strict";

var oop = require("../../lib/oop");
var BaseFoldMode = require("./fold_mode").FoldMode;

var FoldMode = exports.FoldMode = function(markers) {
	this.foldingStartMarker = new RegExp("([\\[{])(?:\\s*)$|(" + markers + ")(?:\\s*)(?:#.*)?$");
};
oop.inherits(FoldMode, BaseFoldMode);

(function() {

	this.getFoldWidgetRange = function(session, foldStyle, row) {
		var line = session.getLine(row);
		var match = line.match(this.foldingStartMarker);
		if (match) {
			if (match[1])
				return this.openingBracketBlock(session, match[1], row, match.index);
			if (match[2])
				return this.indentationBlock(session, row, match.index + match[2].length);
			return this.indentationBlock(session, row);
		}
	};

}).call(FoldMode.prototype);

});

define("ace/mode/vyper", function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var VyperHighlightRules = require("./vyper_highlight_rules").VyperHighlightRules;
var PythonFoldMode = require("./folding/pythonic").FoldMode;
var Range = require("../range").Range;

var Mode = function() {
	this.HighlightRules = VyperHighlightRules;
	this.foldingRules = new PythonFoldMode("\\:");
	this.$behaviour = this.$defaultBehaviour;
};
oop.inherits(Mode, TextMode);

(function() {

	this.lineCommentStart = "#";

	this.getNextLineIndent = function(state, line, tab) {
		var indent = this.$getIndent(line);

		var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
		var tokens = tokenizedLine.tokens;

		if (tokens.length && tokens[tokens.length-1].type == "comment") {
			return indent;
		}

		if (state == "start") {
			var match = line.match(/^.*[\{\(\[:]\s*$/);
			if (match) {
				indent += tab;
			}
		}

		return indent;
	};

	var outdents = {
		"pass": 1,
		"return": 1,
		"raise": 1,
		"break": 1,
		"continue": 1
	};

	this.checkOutdent = function(state, line, input) {
		if (input !== "\r\n" && input !== "\r" && input !== "\n")
			return false;

		var tokens = this.getTokenizer().getLineTokens(line.trim(), state).tokens;

		if (!tokens)
			return false;

		// ignore trailing comments
		do {
			var last = tokens.pop();
		} while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));

		if (!last)
			return false;

		return (last.type == "keyword" && outdents[last.value]);
	};

	this.autoOutdent = function(state, doc, row) {
		// outdenting in python is slightly different because it always applies
		// to the next line and only of a new line is inserted

		row += 1;
		var indent = this.$getIndent(doc.getLine(row));
		var tab = doc.getTabString();
		if (indent.slice(-tab.length) == tab)
			doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
	};

	this.$id = "ace/mode/vyper";
}).call(Mode.prototype);

exports.Mode = Mode;
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

const config = require('./../../../config.js');

/**
 * https://www.npmjs.com/package/tabtab#3-parsing-env
 *
 * @param {string} env.lastPartial - the characters entered in the current
 *                               argument before hitting tabtab
 * @param {string} env.prev - last given argument value, or previously
 *                            completed value
 * @param {string} env.words - the number of argument currently active
 * @param {string} env.line - the current complete input line in the cli
 * @returns {Promise<Array<string>>}
 */
module.exports = async ({ words, prev }) => {
  switch(words) {
    case 2: {
      return ['set', 'get', 'list'];
    }
    case 3: {
      const configKeys = Object.keys(config.get());
      // @TODO add name / description combinations for config variables
      // for better explanation
      delete configKeys.type;
      return configKeys;
    }
    case 4: {
      const value = config.get(prev);
      return [value];
    }
  }
};
<commit_msg>fix(config): prevent setting of undefined variable<commit_after>#!/usr/bin/env node
'use strict';

const config = require('./../../../config.js');

/**
 * https://www.npmjs.com/package/tabtab#3-parsing-env
 *
 * @param {string} env.lastPartial - the characters entered in the current
 *                               argument before hitting tabtab
 * @param {string} env.prev - last given argument value, or previously
 *                            completed value
 * @param {string} env.words - the number of argument currently active
 * @param {string} env.line - the current complete input line in the cli
 * @returns {Promise<Array<string>>}
 */
module.exports = async ({ words, prev }) => {
  switch(words) {
    case 2: {
      return [
        {
          name: 'set',
          description: 'set a config variable'
        },
        { name: 'get',
          description: 'get a config variable'
        },
        { name: 'list',
          description: 'show all variables and their values'
        },
        {
          name: '--help',
          description: 'show help message'
        }
      ];
    }
    case 3: {
      const configKeys = Object.keys(config.get());
      // @TODO add name / description combinations for config variables
      // for better explanation
      delete configKeys.type;
      return configKeys;
    }
    case 4: {
      const value = config.get(prev);
      return [value];
    }
  }
};
<|endoftext|>


<commit_before>/**
 * @fileoverview Contains code defining the TrafficMap class.
 * @requires GoogleMaps
 * @requires jQuery
 */

if (typeof google !== 'undefined' && typeof google.maps !== 'undefined')
  google.maps['visualRefresh'] = true;

/**
 * Creates a new traffic map.
 * @class Represents a traffic map.
 * @this TrafficMap
 * @param {String} elementId An ID to load the map into.
 * @param {IncidentList} incidents An IncidentList to link to the map.
 */
var TrafficMap = function (elementId, incidents) {
  var self = this;

  this._live_cams = [];
  this._traffic_overlay = null;
  this._incidents = incidents;
  this._markers = {};
  this._icons = {};
  this._globalInfoWindow = new google.maps.InfoWindow();
  this._map_has_been_moved = false;

  var mapOptions = {
    zoom: 11,
    center: new google.maps.LatLng(38.56, -121.40),
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    scrollwheel: false,
    disableDefaultUI: true
  };

  this.gmap = new google.maps.Map(document.getElementById(elementId), mapOptions);

  // Setup the map buttons.
  this.make_traffic_button();
  this.make_camera_button();
  var recenter_btn = document.getElementById('recenter_btn');
  recenter_btn.onclick = function () {
    this.style.display = 'none';
    self._map_has_been_moved = false;
    self.fitIncidents();
  };

  this.gmap.controls[google.maps.ControlPosition.TOP_RIGHT].push(document.getElementById('mapcontrol'));
  this.gmap.controls[google.maps.ControlPosition.TOP_LEFT].push(document.getElementById('incident_container'));

  // Set initial map state
  if (this.getState('live_cams')) {
    this.show_live_cams();
  }

  if (this.getState('traffic')) {
    this.show_gtraffic();
  }

  // Events...
  google.maps.event.addListener(this.gmap, 'dragend', function() {
    recenter_btn.style.display = 'block';
    self._map_has_been_moved = true;
  });
  google.maps.event.addListener(this.gmap, 'dblclick', function() {
    recenter_btn.style.display = 'block';
    self._map_has_been_moved = true;
  });
  google.maps.event.addListener(this.gmap, 'resize', function() {
    self.fitIncidents();
  });
  google.maps.event.addListener(this.gmap, 'tilesloaded', function() {
    $('#incident_container').slideDown(function () {
      $('#incident_container .header .closebox').click(function () {
        $('#incident_container').toggleClass('closed');
      });
    });
  });
  google.maps.event.addListener(this._globalInfoWindow, 'closeclick', function() {
    self.resize();
  });

  $(this._incidents).on('st_new_incident', function (evt, incident) {
    self.addIncident(incident);
  });
  $(this._incidents).on('st_update_incident', function (evt, incident) {
    self.addIncident(incident);
  });
  $(this._incidents).on('st_delete_incident', function (evt, id) {
    self.removeIncident(id);
  });
}

/**
 * Makes a show/hide traffic button to enable/disable the traffic overlay
 * on the map.
 */
TrafficMap.prototype.make_traffic_button = function () {
  var self = this;

  this.traffic_button = document.getElementById('traffic_btn');
  this.traffic_button.onclick = function () {
    if (self.getState('traffic')) {
      self.hide_gtraffic();
    } else {
      self.show_gtraffic();
    }
  };
};

/**
 * Makes a show/hide camera button to enable/disable the live camera markers
 * on the map.
 */
TrafficMap.prototype.make_camera_button = function () {
  var self = this;

  this.camera_button = document.getElementById('camera_btn');
  this.camera_button.onclick = function () {
    if (self.getState('live_cams')) {
      self.hide_live_cams();
    } else {
      self.show_live_cams();
    }
  };
};

/**
 * Moves the map to cover the all the incidents.
 */
TrafficMap.prototype.fitIncidents = function () {
  if (this._incidents.size() > 0 && !this._map_has_been_moved) {
    var bounds = this._incidents.getBounds();
    this.gmap.fitBounds(new google.maps.LatLngBounds(
      new google.maps.LatLng (bounds.sw.lat, bounds.sw.lon),
      new google.maps.LatLng (bounds.ne.lat, bounds.ne.lon)
    ));
  }
};

/**
 * Tells Google to resize.
 */
TrafficMap.prototype.resize = function () {
  google.maps.event.trigger(this.gmap, 'resize');
};

/**
 * Shows the live cams.
 */
TrafficMap.prototype.show_live_cams = function () {
  if (this._live_cams.length === 0) {
    var self = this;

    jQuery.ajax({
      url: "/data/cameras.txt",
      dataType: "text",
      success: function (cameras) {
        var rows = cameras.split(/\n/);
        for (var x = 1, xl = rows.length; x < xl; x++) {
          if (rows[x] === '' || rows[x].match(/^#/)) {
            continue;
          }

          var fields = rows[x].split(/,/);
          var camera = {
            name: fields[0],
            url: fields[1],
            location: {
              lat: fields[2],
              lon: fields[3]
            }
          };

          self._live_cams.push(make_camera_marker(camera));
        }

        function make_camera_marker (camera) {
          var marker = new google.maps.Marker({
            position: new google.maps.LatLng(camera.location.lat, camera.location.lon),
            icon: self.getMapIcon('camera'),
            title: camera.name,
            map: self.gmap
          });

          google.maps.event.addListener(marker, 'click', function() {
            self._globalInfoWindow.setContent('

Live Video: ' + camera.name + '

Show
');
            self._globalInfoWindow.open(self.gmap, marker);
          });

          return marker;
        }

      }
    });
  } else {
    for (var x = 0, xl = this._live_cams.length; x < xl; x++) {
      var cam_marker = this._live_cams[x];
      cam_marker.setMap(this.gmap);
    }
  }

  this.camera_button.innerHTML = 'Hide Cameras';
  this.setState('live_cams', true);
};

/**
 * Hides the live cams.
 */
TrafficMap.prototype.hide_live_cams = function () {
  for (var x = 0, xl = this._live_cams.length; x < xl; x++) {
    var cam_marker = this._live_cams[x];
    cam_marker.setMap(null);
  }

  this.camera_button.innerHTML = 'Show Cameras';
  this.setState('live_cams', false);
};

/**
 * Shows Google traffic info.
 */
TrafficMap.prototype.show_gtraffic = function () {
  this._traffic_overlay = new google.maps.TrafficLayer();
  this._traffic_overlay.setMap(this.gmap);

  this.traffic_button.innerHTML = 'Hide Traffic';
  this.setState('traffic', true);
};

/**
 * Hides Google traffic info.
 */
TrafficMap.prototype.hide_gtraffic = function () {
  if (this._traffic_overlay) {
    this._traffic_overlay.setMap(null);
  }

  this.traffic_button.innerHTML = 'Show Traffic';
  this.setState('traffic', false);
};

/**
 * Centers the map on the given latitude and longitude.
 * @param {Number} lat The latitude.
 * @param {Number} lon The longitude.
 */
TrafficMap.prototype.centerOnGeo = function (lat, lon) {
  this.gmap.panTo(new google.maps.LatLng(lat, lon));
};

/**
 * Getter for map state.
 * @param {String} key The key to get.
 * @return {Any} The value.
 */
TrafficMap.prototype.getState = function (key) {
  if (typeof(this._mapstate) === 'undefined') {
    if ('localStorage' in window && window['localStorage'] !== null) {
      this._mapstate = JSON.parse(localStorage.getItem('trafficmap_state')) || {};
    }
  }

  return this._mapstate[key] || false;
};

/**
 * Setter for map state. Also saved to localStorage if possible.
 * @param {String} key The key to set.
 * @param {Any} value The value to set.
 */
TrafficMap.prototype.setState = function (key, value) {
  this._mapstate[key] = value;
  if ('localStorage' in window && window['localStorage'] !== null) {
    localStorage.setItem('trafficmap_state', JSON.stringify(this._mapstate));
  }
};

/**
 * Adds a Marker for a given incident.  Also supports updating existing markers.
 * @param {Incident} incident The incident.
 */
TrafficMap.prototype.addIncident = function (incident) {
  var self = this;

  if (!incident.geolocation) return;

  var icon = this.getMapIcon(incident.getIcon().name);
  var marker = this._markers[incident.ID];
  if (typeof(marker) === 'undefined') {
    marker = new google.maps.Marker({
      position: new google.maps.LatLng(incident.geolocation.lat, incident.geolocation.lon),
      icon: icon,
      shadow: this.getMapIcon('shadow'),
      title: incident.LogType,
      map: this.gmap
    });

    this._markers[incident.ID] = marker;
    this.fitIncidents();
  } else {
    // Update the icon, incase it's changed.
    marker.setIcon(icon);
    marker.setTitle(incident.LogType);
    google.maps.event.clearListeners(marker, 'click');
  }

  google.maps.event.addListener(marker, 'click', function() {
    var logtime = new Date(incident.LogTime * 1000);
    self._globalInfoWindow.setContent('

' + incident.LogType + '

' + incident.Location + '

' + logtime.getPrettyDateTime() + '

');
    self._globalInfoWindow.open(self.gmap, marker);
  });
};

/**
 * Removes a Marker for a given incident.
 * @param {String} id The incident ID to remove.
 */
TrafficMap.prototype.removeIncident = function (id) {
  this._markers[id].setMap(null);
  delete this._markers[id];
  this.fitIncidents();
};

/**
 * Icon generator for the traffic map.
 * @param {String} type The type of icon to return.
 */
TrafficMap.prototype.getMapIcon = function (type) {
  if (typeof(type) === 'undefined') {
    type = 'generic';
  }

  if (typeof(this._icons[type]) === 'undefined') {
    var url = '/images/map_markers.png?v=3';
    var size = new google.maps.Size(32, 37);
    var origin = new google.maps.Point(0, 0);
    var anchor = new google.maps.Point(16, 37);
    var scaledSize = null;

    switch (type) {
      case 'Maintenance':
        origin = new google.maps.Point(32, 0);
        break;
      case 'Collision-serious':
        origin = new google.maps.Point(64, 0);
        break;
      case 'Collision':
        origin = new google.maps.Point(96, 0);
        break;
      case 'Fire':
        origin = new google.maps.Point(128, 0);
        break;
      case 'camera':
        origin = new google.maps.Point(160, 0);
        break;
      case 'shadow':
        size = new google.maps.Size(51, 37);
        origin = new google.maps.Point(0, 37);
        anchor = new google.maps.Point(26, 37);
        break;
    }

    this._icons[type] = {
      anchor: anchor,
      origin: origin,
      scaledSize: scaledSize,
      size: size,
      url: url
    };
  }

  return this._icons[type];
}
<commit_msg>Add click tracking to the map.<commit_after>/**
 * @fileoverview Contains code defining the TrafficMap class.
 * @requires GoogleMaps
 * @requires jQuery
 */

if (typeof google !== 'undefined' && typeof google.maps !== 'undefined')
  google.maps['visualRefresh'] = true;

/**
 * Creates a new traffic map.
 * @class Represents a traffic map.
 * @this TrafficMap
 * @param {String} elementId An ID to load the map into.
 * @param {IncidentList} incidents An IncidentList to link to the map.
 */
var TrafficMap = function (elementId, incidents) {
  var self = this;

  this._live_cams = [];
  this._traffic_overlay = null;
  this._incidents = incidents;
  this._markers = {};
  this._icons = {};
  this._globalInfoWindow = new google.maps.InfoWindow();
  this._map_has_been_moved = false;

  var mapOptions = {
    zoom: 11,
    center: new google.maps.LatLng(38.56, -121.40),
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    scrollwheel: false,
    disableDefaultUI: true
  };

  this.gmap = new google.maps.Map(document.getElementById(elementId), mapOptions);

  // Setup the map buttons.
  this.make_traffic_button();
  this.make_camera_button();
  var recenter_btn = document.getElementById('recenter_btn');
  recenter_btn.onclick = function () {
    this.style.display = 'none';
    self._map_has_been_moved = false;
    self.fitIncidents();
  };

  this.gmap.controls[google.maps.ControlPosition.TOP_RIGHT].push(document.getElementById('mapcontrol'));
  this.gmap.controls[google.maps.ControlPosition.TOP_LEFT].push(document.getElementById('incident_container'));

  // Set initial map state
  if (this.getState('live_cams')) {
    this.show_live_cams();
  }

  if (this.getState('traffic')) {
    this.show_gtraffic();
  }

  // Events...
  google.maps.event.addListener(this.gmap, 'dragend', function() {
    recenter_btn.style.display = 'block';
    self._map_has_been_moved = true;
  });
  google.maps.event.addListener(this.gmap, 'dblclick', function() {
    recenter_btn.style.display = 'block';
    self._map_has_been_moved = true;
  });
  google.maps.event.addListener(this.gmap, 'resize', function() {
    self.fitIncidents();
  });
  google.maps.event.addListener(this.gmap, 'tilesloaded', function() {
    $('#incident_container').slideDown(function () {
      $('#incident_container .header .closebox').click(function () {
        if (window._gaq) {
          var action = ($('#incident_container').hasClass('closed')) ? 'to_open' : 'to_close';
          _gaq.push(['_trackEvent', 'Container Closebox', action]);
        }

        $('#incident_container').toggleClass('closed');
      });
    });
  });
  google.maps.event.addListener(this._globalInfoWindow, 'closeclick', function() {
    self.resize();
  });

  $(this._incidents).on('st_new_incident', function (evt, incident) {
    self.addIncident(incident);
  });
  $(this._incidents).on('st_update_incident', function (evt, incident) {
    self.addIncident(incident);
  });
  $(this._incidents).on('st_delete_incident', function (evt, id) {
    self.removeIncident(id);
  });
}

/**
 * Makes a show/hide traffic button to enable/disable the traffic overlay
 * on the map.
 */
TrafficMap.prototype.make_traffic_button = function () {
  var self = this;

  this.traffic_button = document.getElementById('traffic_btn');
  this.traffic_button.onclick = function () {
    if (self.getState('traffic')) {
      self.hide_gtraffic();
    } else {
      self.show_gtraffic();
    }
  };
};

/**
 * Makes a show/hide camera button to enable/disable the live camera markers
 * on the map.
 */
TrafficMap.prototype.make_camera_button = function () {
  var self = this;

  this.camera_button = document.getElementById('camera_btn');
  this.camera_button.onclick = function () {
    if (self.getState('live_cams')) {
      self.hide_live_cams();
    } else {
      self.show_live_cams();
    }
  };
};

/**
 * Moves the map to cover the all the incidents.
 */
TrafficMap.prototype.fitIncidents = function () {
  if (this._incidents.size() > 0 && !this._map_has_been_moved) {
    var bounds = this._incidents.getBounds();
    this.gmap.fitBounds(new google.maps.LatLngBounds(
      new google.maps.LatLng (bounds.sw.lat, bounds.sw.lon),
      new google.maps.LatLng (bounds.ne.lat, bounds.ne.lon)
    ));
  }
};

/**
 * Tells Google to resize.
 */
TrafficMap.prototype.resize = function () {
  google.maps.event.trigger(this.gmap, 'resize');
};

/**
 * Shows the live cams.
 */
TrafficMap.prototype.show_live_cams = function () {
  if (this._live_cams.length === 0) {
    var self = this;

    jQuery.ajax({
      url: "/data/cameras.txt",
      dataType: "text",
      success: function (cameras) {
        var rows = cameras.split(/\n/);
        for (var x = 1, xl = rows.length; x < xl; x++) {
          if (rows[x] === '' || rows[x].match(/^#/)) {
            continue;
          }

          var fields = rows[x].split(/,/);
          var camera = {
            name: fields[0],
            url: fields[1],
            location: {
              lat: fields[2],
              lon: fields[3]
            }
          };

          self._live_cams.push(make_camera_marker(camera));
        }

        function make_camera_marker (camera) {
          var marker = new google.maps.Marker({
            position: new google.maps.LatLng(camera.location.lat, camera.location.lon),
            icon: self.getMapIcon('camera'),
            title: camera.name,
            map: self.gmap
          });

          google.maps.event.addListener(marker, 'click', function() {
            if (window._gaq)
              _gaq.push(['_trackEvent', 'Show Camera', 'clicked', camera.name]);

            self._globalInfoWindow.setContent('

Live Video: ' + camera.name + '

Show
');
            self._globalInfoWindow.open(self.gmap, marker);
          });

          return marker;
        }

      }
    });
  } else {
    for (var x = 0, xl = this._live_cams.length; x < xl; x++) {
      var cam_marker = this._live_cams[x];
      cam_marker.setMap(this.gmap);
    }
  }

  this.camera_button.innerHTML = 'Hide Cameras';
  this.setState('live_cams', true);
};

/**
 * Hides the live cams.
 */
TrafficMap.prototype.hide_live_cams = function () {
  for (var x = 0, xl = this._live_cams.length; x < xl; x++) {
    var cam_marker = this._live_cams[x];
    cam_marker.setMap(null);
  }

  this.camera_button.innerHTML = 'Show Cameras';
  this.setState('live_cams', false);
};

/**
 * Shows Google traffic info.
 */
TrafficMap.prototype.show_gtraffic = function () {
  this._traffic_overlay = new google.maps.TrafficLayer();
  this._traffic_overlay.setMap(this.gmap);

  this.traffic_button.innerHTML = 'Hide Traffic';
  this.setState('traffic', true);
};

/**
 * Hides Google traffic info.
 */
TrafficMap.prototype.hide_gtraffic = function () {
  if (this._traffic_overlay) {
    this._traffic_overlay.setMap(null);
  }

  this.traffic_button.innerHTML = 'Show Traffic';
  this.setState('traffic', false);
};

/**
 * Centers the map on the given latitude and longitude.
 * @param {Number} lat The latitude.
 * @param {Number} lon The longitude.
 */
TrafficMap.prototype.centerOnGeo = function (lat, lon) {
  this.gmap.panTo(new google.maps.LatLng(lat, lon));
};

/**
 * Getter for map state.
 * @param {String} key The key to get.
 * @return {Any} The value.
 */
TrafficMap.prototype.getState = function (key) {
  if (typeof(this._mapstate) === 'undefined') {
    if ('localStorage' in window && window['localStorage'] !== null) {
      this._mapstate = JSON.parse(localStorage.getItem('trafficmap_state')) || {};
    }
  }

  return this._mapstate[key] || false;
};

/**
 * Setter for map state. Also saved to localStorage if possible.
 * @param {String} key The key to set.
 * @param {Any} value The value to set.
 */
TrafficMap.prototype.setState = function (key, value) {
  this._mapstate[key] = value;
  if ('localStorage' in window && window['localStorage'] !== null) {
    localStorage.setItem('trafficmap_state', JSON.stringify(this._mapstate));
  }
};

/**
 * Adds a Marker for a given incident.  Also supports updating existing markers.
 * @param {Incident} incident The incident.
 */
TrafficMap.prototype.addIncident = function (incident) {
  var self = this;

  if (!incident.geolocation) return;

  var icon = this.getMapIcon(incident.getIcon().name);
  var marker = this._markers[incident.ID];
  if (typeof(marker) === 'undefined') {
    marker = new google.maps.Marker({
      position: new google.maps.LatLng(incident.geolocation.lat, incident.geolocation.lon),
      icon: icon,
      shadow: this.getMapIcon('shadow'),
      title: incident.LogType,
      map: this.gmap
    });

    this._markers[incident.ID] = marker;
    this.fitIncidents();
  } else {
    // Update the icon, incase it's changed.
    marker.setIcon(icon);
    marker.setTitle(incident.LogType);
    google.maps.event.clearListeners(marker, 'click');
  }

  google.maps.event.addListener(marker, 'click', function() {
    if (window._gaq)
      _gaq.push(['_trackEvent', 'Show Incident', 'clicked', incident.LogType]);

    var logtime = new Date(incident.LogTime * 1000);
    self._globalInfoWindow.setContent('

' + incident.LogType + '

' + incident.Location + '

' + logtime.getPrettyDateTime() + '

');
    self._globalInfoWindow.open(self.gmap, marker);
  });
};

/**
 * Removes a Marker for a given incident.
 * @param {String} id The incident ID to remove.
 */
TrafficMap.prototype.removeIncident = function (id) {
  this._markers[id].setMap(null);
  delete this._markers[id];
  this.fitIncidents();
};

/**
 * Icon generator for the traffic map.
 * @param {String} type The type of icon to return.
 */
TrafficMap.prototype.getMapIcon = function (type) {
  if (typeof(type) === 'undefined') {
    type = 'generic';
  }

  if (typeof(this._icons[type]) === 'undefined') {
    var url = '/images/map_markers.png?v=3';
    var size = new google.maps.Size(32, 37);
    var origin = new google.maps.Point(0, 0);
    var anchor = new google.maps.Point(16, 37);
    var scaledSize = null;

    switch (type) {
      case 'Maintenance':
        origin = new google.maps.Point(32, 0);
        break;
      case 'Collision-serious':
        origin = new google.maps.Point(64, 0);
        break;
      case 'Collision':
        origin = new google.maps.Point(96, 0);
        break;
      case 'Fire':
        origin = new google.maps.Point(128, 0);
        break;
      case 'camera':
        origin = new google.maps.Point(160, 0);
        break;
      case 'shadow':
        size = new google.maps.Size(51, 37);
        origin = new google.maps.Point(0, 37);
        anchor = new google.maps.Point(26, 37);
        break;
    }

    this._icons[type] = {
      anchor: anchor,
      origin: origin,
      scaledSize: scaledSize,
      size: size,
      url: url
    };
  }

  return this._icons[type];
}
<|endoftext|>


<commit_before>/**
 * @namespace hs.status_creator
 * @memberOf hs
 */
define(['angular', 'ol', 'map', 'ngcookies'],

    function(angular, ol) {
        var module = angular.module('hs.status_creator', ['hs.map', 'hs.core', 'ngCookies'])
            .directive('hs.statusCreator.directive', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/dialog.html',
                    link: function(scope, element) {
                        $('#stc-save, #stc-saveas').hide();
                    }
                };
            })
            .directive('hs.statusCreator.directiveForm', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/form.html',
                    link: function(scope, element) {

                    }
                };
            })
            .directive('hs.statusCreator.directivePanel', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/panel.html',
                    link: function(scope, element) {

                    }
                };
            })
            .directive('hs.statusCreator.resultDialogDirective', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/dialog_result.html',
                    link: function(scope, element, attrs) {
                        $('#status-creator-result-dialog').modal('show');
                    }
                };
            })

        .service('hs.status_creator.service', ['hs.map.service', 'Core', function(OlMap, Core) {
            var me = {
                map2json: function(map, $scope, saveAll) {
                    var groups = {};
                    angular.forEach($scope.groups, function(g) {
                        if (g.r || g.w) {
                            groups[g.roleName] = (g.r ? 'r' : '') + (g.w ? 'w' : '');
                        }
                    });
                    var json = {
                        abstract: $scope.abstract,
                        title: $scope.title,
                        keywords: $scope.keywords,
                        extent: $scope.bbox,
                        user: {
                            address: $scope.address,
                            city: $scope.city,
                            country: $scope.country,
                            email: $scope.email,
                            name: $scope.name,
                            organization: $scope.organization,
                            phone: $scope.phone,
                            position: $scope.position,
                            postalcode: $scope.postalcode,
                            state: $scope.state,
                            url: $scope.url
                        },
                        groups: groups
                    };

                    // Map properties
                    json.scale = map.getView().getProjection().getMetersPerUnit();
                    json.projection = map.getView().getProjection().getCode().toLowerCase();
                    var center = map.getView().getCenter();
                    if (center) {
                        json.center = [center[0], center[1]];
                    }
                    json.units = map.getView().getProjection().getUnits();

                    if (map.maxExtent) {
                        json.maxExtent = {};
                        json.maxExtent.left = map.maxExtent.left;
                        json.maxExtent.bottom = map.maxExtent.bottom;
                        json.maxExtent.right = map.maxExtent.right;
                        json.maxExtent.top = map.maxExtent.top;
                    }

                    //json.minResolution = map.minResolution;
                    //json.maxResolution = map.maxResolution;
                    //json.numZoomLevels = map.numZoomLevels;

                    //json.resolutions = map.resolutions;
                    //json.scales = map.scales;
                    //json.sphericalMercator = map.sphericalMercator;

                    // Layers properties
                    json.layers = me.layers2json(map.getLayers(), saveAll);

                    return json;
                },

                /**
                 * Converts map layers into a JSON object.
                 * Uses layer2json().
                 *
                 * @param {Array} layers Map layers that should be converted
                 * @param {Boolean} saveAll Whether all the layer attributes should be saved
                 * @returns {Array} JSON object representing the layers
                 */
                layers2json: function(layers, saveAll) {

                    var i, ilen;
                    var json = [];
                    layers.forEach(function(lyr) {
                        var l = me.layer2json(lyr, saveAll);
                        if (l) {
                            json.push(l);
                        }
                    });

                    return json;
                },

                /**
                 * Converts map layer from Layer object to text in JSON notation.
                 *
                 * Syntactic sugar for layer2json()
                 *
                 * @param {Object} layer Layer to be converted
                 * @param {Boolean} Whether to use pretty notation
                 * @param {Boolean} saveAll Whether all the layer attributes should be saved
                 * @returns {String} Text in JSON notation representing the layer
                 */
                layer2string: function(layer, pretty, saveAll) {
                    var json = me.layer2json(layer, saveAll);
                    var text = JSON.stringify(json, pretty);
                    return text;
                },

                /**
                 * Converts map layer into a JSON object.
                 *
                 * Layer properties covered:  CLASS_NAME, name, url, params,
                 *                            group, displayInLayerSwitcher, visibility,
                 *                            attribution, transitionEffect,
                 *                             isBaseLayer, minResolution,
                 *                            maxResolution, minScale, maxScale, metadata,
                 *                            abstract, opacity, singleTile, removable,
                 *                            queryable, legend, projections,
                 *                            wmsMinScale, wmsMaxScale
                 *
                 * The layer index is not covered, as we assume
                 * that it is corresponding to the layers order.
                 *
                 * @param {Object} layer Map layer that should be converted
                 * @param {Boolean} saveAll Whether all the layer attributes should be saved. Sometimes we want to save network traffic and save completely only the foreign layers, in such a case set saveAll to false.
                 * @returns {Object} JSON object representing the layer
                 */
                layer2json: function(layer, saveAll) {
                    var json = {
                        metadata: {}
                    };
                    if (!layer instanceof ol.layer.Layer) {
                        return;
                    }

                    // Check if the layer is foreigner
                    if (layer.get('saveState')) {
                        saveAll = true; // If so, make sure we save all the attributes
                    } else {
                        return; //RB. Dont process not foreign layers
                    }

                    // Common stuff

                    // type
                    //json.className = layer.CLASS_NAME;
                    //json.origClassName = layer.CLASS_NAME; // the original type

                    // options
                    json.visibility = layer.getVisible();
                    json.opacity = layer.getOpacity();
                    json.title = layer.get('title');
                    //json.index = layer.map.getLayerIndex(layer);
                    json.path = layer.get('path');

                    if (saveAll) {
                        if (layer.getExtent()) {
                            var ex = layer.getExtent();
                            json.maxExtent = {
                                left: ex[0],
                                bottom: ex[3],
                                right: ex[2],
                                top: ex[1]
                            };
                        }

                        // HTTPRequest
                        if (layer instanceof ol.layer.Tile || layer instanceof ol.layer.Image) {
                            var src = layer.getSource();
                            if (src instanceof ol.source.ImageWMS || src instanceof ol.source.TileWMS) {
                                json.className = "HSLayers.Layer.WMS";
                                json.wmsMinScale = layer.get('minScale');
                                json.wmsMaxScale = layer.get('maxScale');
                                json.maxResolution = layer.getMaxResolution();
                                json.minResolution = layer.getMinResolution();
                                if (src.getUrl) json.url = src.getUrl();
                                if (src.getUrls) json.url = src.getUrls()[0];
                                if (src.getProjection()) json.projection = src.getProjection().getCode().toLowerCase();
                                json.params = src.getParams();
                                json.ratio = src.get('ratio');
                                json.displayInLayerSwitcher = layer.get('show_in_manager');
                                json.metadata.styles = src.get('styles');
                            }
                        }

                        // Vector
                        if (layer instanceof ol.layer.Vector) {
                            /* RB. Will be implemented later
                             *this._saveVectorLayer(json, layer);
                             */
                        }

                        // image
                        if (layer instanceof ol.layer.Image) {
                            /* RB. Will be implemented later
                             * this._saveImageLayer(json, layer);
                             */
                        }
                    }

                    return json;
                }
            };
            return me;
        }])

        .controller('hs.status_creator.controller', ['$scope', '$rootScope', 'hs.map.service', 'Core', 'hs.status_creator.service', 'config', '$compile', '$cookies',
            function($scope, $rootScope, OlMap, Core, status_creator, config, $compile, $cookies) {
                $scope.layers = [];
                $scope.id = '';
                $scope.panel_name = 'status_creator';

                $scope.getCurrentExtent = function() {
                    var b = OlMap.map.getView().calculateExtent(OlMap.map.getSize());
                    var pair1 = [b[0], b[1]]
                    var pair2 = [b[2], b[3]];
                    var cur_proj = OlMap.map.getView().getProjection().getCode();
                    pair1 = ol.proj.transform(pair1, cur_proj, 'EPSG:4326');
                    pair2 = ol.proj.transform(pair2, cur_proj, 'EPSG:4326');
                    $scope.bbox = [pair1[0].toFixed(8), pair1[1].toFixed(8), pair2[0].toFixed(8), pair2[1].toFixed(8)];
                }

                $scope.next = function() {
                    if ($('a[href=#author]').parent().hasClass('active')) {
                        var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(status_creator.map2json(OlMap.map, $scope, false)));
                        $('#stc-download').remove();
                        $('Download').insertAfter('#stc-next');
                        $('#stc-save, #stc-saveas').show();
                    } else {
                        if ($('a[href=#context]').parent().hasClass('active'))
                            $('.stc-tabs li:eq(1) a').tab('show');
                        else
                            if ($('a[href=#access]').parent().hasClass('active'))
                                $('.stc-tabs li:eq(2) a').tab('show');
                    }
                }

                var generateUuid = function() {
                    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                        var r = Math.random() * 16 | 0,
                            v = c == 'x' ? r : r & 0x3 | 0x8;
                        return v.toString(16);
                    });
                };

                $scope.showResultDialog = function() {
                    if ($("#hs-dialog-area #status-creator-result-dialog").length == 0) {
                        var el = angular.element('
');
                        $("#hs-dialog-area").append(el)
                        $compile(el)($scope);
                    } else {
                        $('#status-creator-result-dialog').modal('show');
                    }
                    if (!$scope.$$phase) $scope.$digest();
                }

                $scope.save = function(save_as_new) {
                    if (save_as_new || $scope.id == '') $scope.id = generateUuid();
                    $.ajax({
                        url: "/wwwlibs/statusmanager2/index.php",
                        cache: false,
                        method: 'POST',
                        dataType: "json",
                        data: JSON.stringify({
                            data: status_creator.map2json(OlMap.map, $scope, false),
                            permanent: true,
                            id: $scope.id,
                            project: config.project_name,
                            request: "save"
                        }),
                        success: function(j) {
                            $scope.success = j.saved !== false;
                            $scope.showResultDialog();
                            Core.setMainPanel('layermanager', true);
                            $('.composition-info').html($('').html($('
').html($scope.title)).click(function() {
                                $('.composition-abstract').toggle();
                            }));
                            $('.composition-info').append($('
').html($scope.abstract).addClass('well composition-abstract'));
                        },
                        error: function() {
                            $scope.success = false;
                            $scope.showResultDialog()
                        }
                    })
                }

                $scope.open = function() {
                    $scope.layers = [];
                    $scope.getCurrentExtent();
                    OlMap.map.getLayers().forEach(function(lyr) {
                        $scope.layers.push({
                            title: lyr.get('title'),
                            checked: lyr.get('saveState')
                        });
                    });
                    $scope.fillGroups();
                    Core.setMainPanel('status_creator', true);
                    //$('#status-creator-dialog').modal('show');
                    $scope.loadUserDetails();
                }

                $scope.fillGroups = function() {
                    $scope.groups = [];
                    $.ajax({
                        url: '/wwwlibs/statusmanager2/index.php',
                        cache: false,
                        method: 'GET',
                        dataType: 'json',
                        data: {
                            request: 'getGroups'
                        },
                        success: function(j) {
                            if (j.success) {
                                $scope.groups = j.result;
                                angular.forEach($scope.groups, function(g) {
                                    g.w = false;
                                    g.r = false;
                                });
                            }
                        }
                    });
                    $scope.groups.unshift({
                        roleTitle: 'Public',
                        roleName: 'guest',
                        w: false,
                        r: false
                    });
                }

                $scope.loadUserDetails = function() {
                    var jsessionid = $cookies.get("JSESSIONID");
                    if (jsessionid) {
                        $.ajax({
                            url: "/g4i-portlet/service/sso/validate/" + jsessionid,
                            success: $scope.setUserDetails
                        });
                    }
                };

                $scope.setUserDetails = function(user) {
                    if (user && user.resultCode == "0") {
                        // set the values
                        if (user.userInfo) {
                            $scope.email = user.userInfo.email;
                            $scope.phone = user.userInfo.phone;
                            $scope.name = user.userInfo.firstName + " " + user.userInfo.lastName;
                        }
                        if (user.userInfo && user.userInfo.org) {
                            $scope.address = user.userInfo.org.street;
                            $scope.country = user.userInfo.org.state;
                            $scope.postalcode = user.userInfo.org.zip;
                            $scope.city = user.userInfo.org.city;
                            $scope.organization = user.userInfo.org.name;
                        }
                    }
                };

                $scope.$on('compositions.composition_loaded', function(event, data) {
                    if (console) console.log('compositions.composition_loaded', data);
                    $scope.id = data.id;
                    $scope.abstract = data.abstract;
                    $scope.title = data.title;
                    $scope.keywords = data.keywords;
                });

                $scope.getCurrentExtent();
                $scope.$emit('scope_loaded', "StatusCreator");
            }
        ]);

    })
<commit_msg>async false for getting groups<commit_after>/**
 * @namespace hs.status_creator
 * @memberOf hs
 */
define(['angular', 'ol', 'map', 'ngcookies'],

    function(angular, ol) {
        var module = angular.module('hs.status_creator', ['hs.map', 'hs.core', 'ngCookies'])
            .directive('hs.statusCreator.directive', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/dialog.html',
                    link: function(scope, element) {
                        $('#stc-save, #stc-saveas').hide();
                    }
                };
            })
            .directive('hs.statusCreator.directiveForm', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/form.html',
                    link: function(scope, element) {

                    }
                };
            })
            .directive('hs.statusCreator.directivePanel', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/panel.html',
                    link: function(scope, element) {

                    }
                };
            })
            .directive('hs.statusCreator.resultDialogDirective', function() {
                return {
                    templateUrl: hsl_path + 'components/status_creator/partials/dialog_result.html',
                    link: function(scope, element, attrs) {
                        $('#status-creator-result-dialog').modal('show');
                    }
                };
            })

        .service('hs.status_creator.service', ['hs.map.service', 'Core', function(OlMap, Core) {
            var me = {
                map2json: function(map, $scope, saveAll) {
                    var groups = {};
                    angular.forEach($scope.groups, function(g) {
                        if (g.r || g.w) {
                            groups[g.roleName] = (g.r ? 'r' : '') + (g.w ? 'w' : '');
                        }
                    });
                    var json = {
                        abstract: $scope.abstract,
                        title: $scope.title,
                        keywords: $scope.keywords,
                        extent: $scope.bbox,
                        user: {
                            address: $scope.address,
                            city: $scope.city,
                            country: $scope.country,
                            email: $scope.email,
                            name: $scope.name,
                            organization: $scope.organization,
                            phone: $scope.phone,
                            position: $scope.position,
                            postalcode: $scope.postalcode,
                            state: $scope.state,
                            url: $scope.url
                        },
                        groups: groups
                    };

                    // Map properties
                    json.scale = map.getView().getProjection().getMetersPerUnit();
                    json.projection = map.getView().getProjection().getCode().toLowerCase();
                    var center = map.getView().getCenter();
                    if (center) {
                        json.center = [center[0], center[1]];
                    }
                    json.units = map.getView().getProjection().getUnits();

                    if (map.maxExtent) {
                        json.maxExtent = {};
                        json.maxExtent.left = map.maxExtent.left;
                        json.maxExtent.bottom = map.maxExtent.bottom;
                        json.maxExtent.right = map.maxExtent.right;
                        json.maxExtent.top = map.maxExtent.top;
                    }

                    //json.minResolution = map.minResolution;
                    //json.maxResolution = map.maxResolution;
                    //json.numZoomLevels = map.numZoomLevels;

                    //json.resolutions = map.resolutions;
                    //json.scales = map.scales;
                    //json.sphericalMercator = map.sphericalMercator;

                    // Layers properties
                    json.layers = me.layers2json(map.getLayers(), saveAll);

                    return json;
                },

                /**
                 * Converts map layers into a JSON object.
                 * Uses layer2json().
                 *
                 * @param {Array} layers Map layers that should be converted
                 * @param {Boolean} saveAll Whether all the layer attributes should be saved
                 * @returns {Array} JSON object representing the layers
                 */
                layers2json: function(layers, saveAll) {

                    var i, ilen;
                    var json = [];
                    layers.forEach(function(lyr) {
                        var l = me.layer2json(lyr, saveAll);
                        if (l) {
                            json.push(l);
                        }
                    });

                    return json;
                },

                /**
                 * Converts map layer from Layer object to text in JSON notation.
                 *
                 * Syntactic sugar for layer2json()
                 *
                 * @param {Object} layer Layer to be converted
                 * @param {Boolean} Whether to use pretty notation
                 * @param {Boolean} saveAll Whether all the layer attributes should be saved
                 * @returns {String} Text in JSON notation representing the layer
                 */
                layer2string: function(layer, pretty, saveAll) {
                    var json = me.layer2json(layer, saveAll);
                    var text = JSON.stringify(json, pretty);
                    return text;
                },

                /**
                 * Converts map layer into a JSON object.
                 *
                 * Layer properties covered:  CLASS_NAME, name, url, params,
                 *                            group, displayInLayerSwitcher, visibility,
                 *                            attribution, transitionEffect,
                 *                             isBaseLayer, minResolution,
                 *                            maxResolution, minScale, maxScale, metadata,
                 *                            abstract, opacity, singleTile, removable,
                 *                            queryable, legend, projections,
                 *                            wmsMinScale, wmsMaxScale
                 *
                 * The layer index is not covered, as we assume
                 * that it is corresponding to the layers order.
                 *
                 * @param {Object} layer Map layer that should be converted
                 * @param {Boolean} saveAll Whether all the layer attributes should be saved. Sometimes we want to save network traffic and save completely only the foreign layers, in such a case set saveAll to false.
                 * @returns {Object} JSON object representing the layer
                 */
                layer2json: function(layer, saveAll) {
                    var json = {
                        metadata: {}
                    };
                    if (!layer instanceof ol.layer.Layer) {
                        return;
                    }

                    // Check if the layer is foreigner
                    if (layer.get('saveState')) {
                        saveAll = true; // If so, make sure we save all the attributes
                    } else {
                        return; //RB. Dont process not foreign layers
                    }

                    // Common stuff

                    // type
                    //json.className = layer.CLASS_NAME;
                    //json.origClassName = layer.CLASS_NAME; // the original type

                    // options
                    json.visibility = layer.getVisible();
                    json.opacity = layer.getOpacity();
                    json.title = layer.get('title');
                    //json.index = layer.map.getLayerIndex(layer);
                    json.path = layer.get('path');

                    if (saveAll) {
                        if (layer.getExtent()) {
                            var ex = layer.getExtent();
                            json.maxExtent = {
                                left: ex[0],
                                bottom: ex[3],
                                right: ex[2],
                                top: ex[1]
                            };
                        }

                        // HTTPRequest
                        if (layer instanceof ol.layer.Tile || layer instanceof ol.layer.Image) {
                            var src = layer.getSource();
                            if (src instanceof ol.source.ImageWMS || src instanceof ol.source.TileWMS) {
                                json.className = "HSLayers.Layer.WMS";
                                json.wmsMinScale = layer.get('minScale');
                                json.wmsMaxScale = layer.get('maxScale');
                                json.maxResolution = layer.getMaxResolution();
                                json.minResolution = layer.getMinResolution();
                                if (src.getUrl) json.url = src.getUrl();
                                if (src.getUrls) json.url = src.getUrls()[0];
                                if (src.getProjection()) json.projection = src.getProjection().getCode().toLowerCase();
                                json.params = src.getParams();
                                json.ratio = src.get('ratio');
                                json.displayInLayerSwitcher = layer.get('show_in_manager');
                                json.metadata.styles = src.get('styles');
                            }
                        }

                        // Vector
                        if (layer instanceof ol.layer.Vector) {
                            /* RB. Will be implemented later
                             *this._saveVectorLayer(json, layer);
                             */
                        }

                        // image
                        if (layer instanceof ol.layer.Image) {
                            /* RB. Will be implemented later
                             * this._saveImageLayer(json, layer);
                             */
                        }
                    }

                    return json;
                }
            };
            return me;
        }])

        .controller('hs.status_creator.controller', ['$scope', '$rootScope', 'hs.map.service', 'Core', 'hs.status_creator.service', 'config', '$compile', '$cookies',
            function($scope, $rootScope, OlMap, Core, status_creator, config, $compile, $cookies) {
                $scope.layers = [];
                $scope.id = '';
                $scope.panel_name = 'status_creator';

                $scope.getCurrentExtent = function() {
                    var b = OlMap.map.getView().calculateExtent(OlMap.map.getSize());
                    var pair1 = [b[0], b[1]]
                    var pair2 = [b[2], b[3]];
                    var cur_proj = OlMap.map.getView().getProjection().getCode();
                    pair1 = ol.proj.transform(pair1, cur_proj, 'EPSG:4326');
                    pair2 = ol.proj.transform(pair2, cur_proj, 'EPSG:4326');
                    $scope.bbox = [pair1[0].toFixed(8), pair1[1].toFixed(8), pair2[0].toFixed(8), pair2[1].toFixed(8)];
                }

                $scope.next = function() {
                    if ($('a[href=#author]').parent().hasClass('active')) {
                        var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(status_creator.map2json(OlMap.map, $scope, false)));
                        $('#stc-download').remove();
                        $('Download').insertAfter('#stc-next');
                        $('#stc-save, #stc-saveas').show();
                    } else {
                        if ($('a[href=#context]').parent().hasClass('active'))
                            $('.stc-tabs li:eq(1) a').tab('show');
                        else
                            if ($('a[href=#access]').parent().hasClass('active'))
                                $('.stc-tabs li:eq(2) a').tab('show');
                    }
                }

                var generateUuid = function() {
                    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                        var r = Math.random() * 16 | 0,
                            v = c == 'x' ? r : r & 0x3 | 0x8;
                        return v.toString(16);
                    });
                };

                $scope.showResultDialog = function() {
                    if ($("#hs-dialog-area #status-creator-result-dialog").length == 0) {
                        var el = angular.element('
');
                        $("#hs-dialog-area").append(el)
                        $compile(el)($scope);
                    } else {
                        $('#status-creator-result-dialog').modal('show');
                    }
                    if (!$scope.$$phase) $scope.$digest();
                }

                $scope.save = function(save_as_new) {
                    if (save_as_new || $scope.id == '') $scope.id = generateUuid();
                    $.ajax({
                        url: "/wwwlibs/statusmanager2/index.php",
                        cache: false,
                        method: 'POST',
                        dataType: "json",
                        data: JSON.stringify({
                            data: status_creator.map2json(OlMap.map, $scope, false),
                            permanent: true,
                            id: $scope.id,
                            project: config.project_name,
                            request: "save"
                        }),
                        success: function(j) {
                            $scope.success = j.saved !== false;
                            $scope.showResultDialog();
                            Core.setMainPanel('layermanager', true);
                            $('.composition-info').html($('').html($('
').html($scope.title)).click(function() {
                                $('.composition-abstract').toggle();
                            }));
                            $('.composition-info').append($('
').html($scope.abstract).addClass('well composition-abstract'));
                        },
                        error: function() {
                            $scope.success = false;
                            $scope.showResultDialog()
                        }
                    })
                }

                $scope.open = function() {
                    $scope.layers = [];
                    $scope.getCurrentExtent();
                    OlMap.map.getLayers().forEach(function(lyr) {
                        $scope.layers.push({
                            title: lyr.get('title'),
                            checked: lyr.get('saveState')
                        });
                    });
                    $scope.fillGroups();
                    Core.setMainPanel('status_creator', true);
                    //$('#status-creator-dialog').modal('show');
                    $scope.loadUserDetails();
                }

                $scope.fillGroups = function() {
                    $scope.groups = [];
                    $.ajax({
                        url: '/wwwlibs/statusmanager2/index.php',
                        cache: false,
                        method: 'GET',
                        async: false,
                        dataType: 'json',
                        data: {
                            request: 'getGroups'
                        },
                        success: function(j) {
                            if (j.success) {
                                $scope.groups = j.result;
                                angular.forEach($scope.groups, function(g) {
                                    g.w = false;
                                    g.r = false;
                                });
                            }
                        }
                    });
                    $scope.groups.unshift({
                        roleTitle: 'Public',
                        roleName: 'guest',
                        w: false,
                        r: false
                    });
                }

                $scope.loadUserDetails = function() {
                    var jsessionid = $cookies.get("JSESSIONID");
                    if (jsessionid) {
                        $.ajax({
                            url: "/g4i-portlet/service/sso/validate/" + jsessionid,
                            success: $scope.setUserDetails
                        });
                    }
                };

                $scope.setUserDetails = function(user) {
                    if (user && user.resultCode == "0") {
                        // set the values
                        if (user.userInfo) {
                            $scope.email = user.userInfo.email;
                            $scope.phone = user.userInfo.phone;
                            $scope.name = user.userInfo.firstName + " " + user.userInfo.lastName;
                        }
                        if (user.userInfo && user.userInfo.org) {
                            $scope.address = user.userInfo.org.street;
                            $scope.country = user.userInfo.org.state;
                            $scope.postalcode = user.userInfo.org.zip;
                            $scope.city = user.userInfo.org.city;
                            $scope.organization = user.userInfo.org.name;
                        }
                    }
                };

                $scope.$on('compositions.composition_loaded', function(event, data) {
                    if (console) console.log('compositions.composition_loaded', data);
                    $scope.id = data.id;
                    $scope.abstract = data.abstract;
                    $scope.title = data.title;
                    $scope.keywords = data.keywords;
                });

                $scope.getCurrentExtent();
                $scope.$emit('scope_loaded', "StatusCreator");
            }
        ]);

    })
<|endoftext|>