<commit_before>'use strict';

var _         = require('lodash');
var d3        = require('d3');

var lineChart = require('./renderer/line');
var data      = require('util/data');

module.exports = {

	mixins: [
		require('./year-over-year')
	],

	computed: {
		colorScale : function() {
			var scale = d3.scale.ordinal()
				.range(['#2b8cbe', '#525b5e', '#82888e', '#98a0a8', '#b6c0cc'])
				.domain(_(this.series)
					.pluck('name')
					.sortBy()
					.reverse()
					.value());

			console.log(scale.domain());

			return scale;
		},

		renderer: function () {
			var x     = this.xScale;
			var y     = this.yScale;
			var color = this.colorScale;

			var renderer = lineChart()
				.x(function (d) {
					return x(d.month);
				})
				.y(function (d) {
					return y(d.value);
				})
				.values(function (d) {
					return d.values;
				})
				.color(function (d) {
					return color(d.name);
				});

			return renderer;
		},

		labels: function () {
			if (this.empty) {
				return [];
			}

			var x      = this.xScale;
			var y      = this.yScale;
			var series = this.series;
			var fmt    = this.yFmt;

			var labels = _(series)
				.map(function (d) {
					// lodash.max uses the accessor to find the comparison value, but
					// returns the entire object; d3.max returns the value returned
					// by the accessor
					var last = _.max(d.values, function (v) { return v.month; });

					return {
						text   : d.name + ' – ' + fmt(last.value),
						x      : x(last.month),
						y      : y(last.value),
						defined: data.defined(last.value)
					};
				})
				.filter('defined')
				.sortBy('y')
				.value();

			return labels;
		},

		series: function () {
			if (this.empty) {
				return [];
			}

			var series = {};
			var year   = null;
			var month  = 0;
			var total  = 0;

			_.forEach(_.sortBy(this.datapoints, function (d) {
					return d.campaign.start_date;
				}), function (d) {
					var y = d.campaign.start_date.getFullYear();

					if (year === null) {
						year         = y;
						series[year] = [];
					}

					// Fill in any missing years...
					while (year < y) {
						// Fill out entries for the rest of the year
						while (month < 11) {
							series[year].push({
								month : month,
								value : total,
								year  : year
							});
							month++;
						}

						// Happy New Year!
						year++;
						total        = 0;
						month        = 0;
						series[year] = [];
					}

					var m = d.campaign.start_date.getMonth();
					while (month < m) {
						series[year].push({
							month : month,
							value : total,
							year  : year
						});
						month++;
					}

					total += d.value;
					series[year].push({
						month : month,
						value : total,
						year  : year
					});
					month++;
				});

			return _.map(series, function (d, year) {
				return {
					name  : year,
					values: d
				};
			});
		},

		yScale: function () {
			function value (d) {
				return d.value;
			}

			var scale = d3.scale.linear()
				.range([this.contentHeight, 0]);

			if (!this.empty) {
				var s = _(this.series)
					.pluck('values')
					.flatten(true)
					.value();

				scale.domain([
					Math.min(d3.min(s, value)),
					d3.max(s, value)
				]);
			}

			return scale;
		}
	},

	methods: {
		diffX: function (a, b) {
			return a - b;
		},

		getSeriesName: function (d) {
			return d.year + ' –';
		},

		getX: function (d) {
			return d.month;
		}
	}
};
<commit_msg>Remove a log statement<commit_after>'use strict';

var _         = require('lodash');
var d3        = require('d3');

var lineChart = require('./renderer/line');
var data      = require('util/data');

module.exports = {

	mixins: [
		require('./year-over-year')
	],

	computed: {
		colorScale : function() {
			return d3.scale.ordinal()
				.range(['#2b8cbe', '#525b5e', '#82888e', '#98a0a8', '#b6c0cc'])
				.domain(_(this.series)
					.pluck('name')
					.sortBy()
					.reverse()
					.value());
		},

		renderer: function () {
			var x     = this.xScale;
			var y     = this.yScale;
			var color = this.colorScale;

			var renderer = lineChart()
				.x(function (d) {
					return x(d.month);
				})
				.y(function (d) {
					return y(d.value);
				})
				.values(function (d) {
					return d.values;
				})
				.color(function (d) {
					return color(d.name);
				});

			return renderer;
		},

		labels: function () {
			if (this.empty) {
				return [];
			}

			var x      = this.xScale;
			var y      = this.yScale;
			var series = this.series;
			var fmt    = this.yFmt;

			var labels = _(series)
				.map(function (d) {
					// lodash.max uses the accessor to find the comparison value, but
					// returns the entire object; d3.max returns the value returned
					// by the accessor
					var last = _.max(d.values, function (v) { return v.month; });

					return {
						text   : d.name + ' – ' + fmt(last.value),
						x      : x(last.month),
						y      : y(last.value),
						defined: data.defined(last.value)
					};
				})
				.filter('defined')
				.sortBy('y')
				.value();

			return labels;
		},

		series: function () {
			if (this.empty) {
				return [];
			}

			var series = {};
			var year   = null;
			var month  = 0;
			var total  = 0;

			_.forEach(_.sortBy(this.datapoints, function (d) {
					return d.campaign.start_date;
				}), function (d) {
					var y = d.campaign.start_date.getFullYear();

					if (year === null) {
						year         = y;
						series[year] = [];
					}

					// Fill in any missing years...
					while (year < y) {
						// Fill out entries for the rest of the year
						while (month < 11) {
							series[year].push({
								month : month,
								value : total,
								year  : year
							});
							month++;
						}

						// Happy New Year!
						year++;
						total        = 0;
						month        = 0;
						series[year] = [];
					}

					var m = d.campaign.start_date.getMonth();
					while (month < m) {
						series[year].push({
							month : month,
							value : total,
							year  : year
						});
						month++;
					}

					total += d.value;
					series[year].push({
						month : month,
						value : total,
						year  : year
					});
					month++;
				});

			return _.map(series, function (d, year) {
				return {
					name  : year,
					values: d
				};
			});
		},

		yScale: function () {
			function value (d) {
				return d.value;
			}

			var scale = d3.scale.linear()
				.range([this.contentHeight, 0]);

			if (!this.empty) {
				var s = _(this.series)
					.pluck('values')
					.flatten(true)
					.value();

				scale.domain([
					Math.min(d3.min(s, value)),
					d3.max(s, value)
				]);
			}

			return scale;
		}
	},

	methods: {
		diffX: function (a, b) {
			return a - b;
		},

		getSeriesName: function (d) {
			return d.year + ' –';
		},

		getX: function (d) {
			return d.month;
		}
	}
};
<|endoftext|>


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

/**
 * The "add a folder" dialog
 */
var FilterModal = Modal.extend({

    type: "filter",
    closeText: "Save",

    events: {
        //'submit form': 'save',
        'click .dialog_footer a' : 'call',
        'click .insert-member' : 'open_select_member_selector'
    },

    buttons: [
        { text: "OK", method: "save" },
        { text: "Cancel", method: "close" },
        { text: "Help", method: "help"}
    ],

    message: "",

    expression_text: function() {
        var c = "

";
        if (this.expressionType == "Order") {
            c += "
Sort Type <select class='form-control' id='fun'><option>ASC</option><option>BASC</option><option>DESC</option><option>BDESC</option> </select>
";
        }
        c += "
" + this.expressionType + " MDX Expression:
" +
             "

" +
             "
" +
            "Insert Member
";
        return c;
    },

    expression: " ",
    expressonType: "",

    initialize: function(args) {
        var self = this;
        this.id = _.uniqueId('filter-modal-');
        this.workspace = args.workspace;
        this.axis = args.axis;
        this.query = args.query;
        this.success = args.success;
        this.expression = args.expression;
        this.expressionType = args.expressionType;
        _.bindAll(this, "save", "expression_text");

        _.extend(this.options, {
            title: "Custom " + this.expressionType + " for " + this.axis
        });

        this.message = this.expression_text(this.expressionType);

        this.bind( 'open', function( ) {
            $(this.el).find('.sidebar').width(380);

            this.editor = ace.edit(this.id);
            this.editor.setValue(self.expression);
            this.editor.setShowPrintMargin(false);
            this.editor.setFontSize(11);
        });

        // fix event listening in IE < 9
        if(isIE && isIE < 9) {
            $(this.el).find('form').on('submit', this.save);
        }

    },

    save: function( event ) {
        event.preventDefault( );
        var self = this;
        this.expression = $(this.el).find('textarea').val();

        var alert_msg = "";
        if (typeof this.expression == "undefined" || !this.expression || this.expression === "") {
            alert_msg += "You have to enter a MDX expression for the " + this.expressionType + " function! ";
            alert(alert_msg);
        } else {
            if (self.expressionType == "Order") {
                var sortOrder = $('#fun').val();
                self.success(sortOrder, this.expression);
            } else {
                self.success(this.expression);
            }
            this.close();
        }

        return false;
    },

    error: function() {
        $(this.el).find('dialog_body')
            .html("Could not add new folder");
    },

    /**
     * Open the select member dialog
     * @param event
     */
    open_select_member_selector: function(event){
        event.preventDefault();
        var dimension = {
            val: this.$el.find('#cms-dimension option:selected').val(),
            txt: this.$el.find('#cms-dimension option:selected').text(),
            dataDimension: this.$el.find('#cms-dimension option:selected').data('dimension'),
            dataType: this.$el.find('#cms-dimension option:selected').data('type')
        };
        var editor = ace.edit(this.id);
        var that = this;

         (new ParentMemberSelectorModal({
                dialog: this,
                workspace: this.workspace,
                cube: this.workspace.selected_cube,
                dimensions: Saiku.session.sessionworkspace.cube[this.workspace.selected_cube].get('data').dimensions,
                selectDimension: dimension.val,
                dimension: dimension.dataDimension,
                hierarchy: dimension.txt,
                uniqueName: this.pmUniqueName,
                lastLevel: this.pmLevel,
                breadcrumbs: this.pmBreadcrumbs,
                select_type: "select_member",
                selected_member: this.selected_member,
                close_callback: function(args){
                    var e = editor;
                    that.close_select_modal(e, args);
                }
            })).render().open();

            this.$el.parents('.ui-dialog').find('.ui-dialog-title').text('Custom Filter');

    },

    /**
     * Callback to update the editor with the selected member.
     * @param editor
     * @param n
     */
    close_select_modal: function(editor, n){
        editor.insert(n);
    },

    help: function(){
        window.open("http://wiki.meteorite.bi/display/SAIK/Filtering");
    }

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

/**
 * The "add a folder" dialog
 */
var FilterModal = Modal.extend({

    type: "filter",
    closeText: "Save",

    events: {
        //'submit form': 'save',
        'click .dialog_footer a' : 'call',
        'click .insert-member' : 'open_select_member_selector'
    },

    buttons: [
        { text: "OK", method: "save" },
        { text: "Cancel", method: "close" },
        { text: "Help", method: "help"}
    ],

    message: "",

    expression_text: function() {
        var c = "

";
        if (this.expressionType == "Order") {
            c += "
Sort Type <select class='form-control' id='fun'><option>ASC</option><option>BASC</option><option>DESC</option><option>BDESC</option> </select>
";
        }
        c += "
" + this.expressionType + " MDX Expression:
" +
             "

" +
             "
" +
            "Insert Member
";
        return c;
    },

    expression: " ",
    expressonType: "",

    initialize: function(args) {
        var self = this;
        this.id = _.uniqueId('filter-modal-');
        this.workspace = args.workspace;
        this.axis = args.axis;
        this.query = args.query;
        this.success = args.success;
        this.expression = args.expression;
        this.expressionType = args.expressionType;
        _.bindAll(this, "save", "expression_text");

        _.extend(this.options, {
            title: "Custom " + this.expressionType + " for " + this.axis
        });

        this.message = this.expression_text(this.expressionType);

        this.bind( 'open', function( ) {
            $(this.el).find('.sidebar').width(380);

            this.editor = ace.edit(this.id);
            this.editor.setValue(self.expression);
            this.editor.setShowPrintMargin(false);
            this.editor.setFontSize(11);
        });

        // fix event listening in IE < 9
        if(isIE && isIE < 9) {
            $(this.el).find('form').on('submit', this.save);
        }

    },

    save: function( event ) {
        event.preventDefault( );
        var self = this;
        this.expression = this.editor.getValue();

        var alert_msg = "";
        if (typeof this.expression == "undefined" || !this.expression || this.expression === "") {
            alert_msg += "You have to enter a MDX expression for the " + this.expressionType + " function! ";
            alert(alert_msg);
        } else {
            if (self.expressionType == "Order") {
                var sortOrder = $('#fun').val();
                self.success(sortOrder, this.expression);
            } else {
                self.success(this.expression);
            }
            this.close();
        }

        return false;
    },

    error: function() {
        $(this.el).find('dialog_body')
            .html("Could not add new folder");
    },

    /**
     * Open the select member dialog
     * @param event
     */
    open_select_member_selector: function(event){
        event.preventDefault();
        var dimension = {
            val: this.$el.find('#cms-dimension option:selected').val(),
            txt: this.$el.find('#cms-dimension option:selected').text(),
            dataDimension: this.$el.find('#cms-dimension option:selected').data('dimension'),
            dataType: this.$el.find('#cms-dimension option:selected').data('type')
        };
        var editor = ace.edit(this.id);
        var that = this;

         (new ParentMemberSelectorModal({
                dialog: this,
                workspace: this.workspace,
                cube: this.workspace.selected_cube,
                dimensions: Saiku.session.sessionworkspace.cube[this.workspace.selected_cube].get('data').dimensions,
                selectDimension: dimension.val,
                dimension: dimension.dataDimension,
                hierarchy: dimension.txt,
                uniqueName: this.pmUniqueName,
                lastLevel: this.pmLevel,
                breadcrumbs: this.pmBreadcrumbs,
                select_type: "select_member",
                selected_member: this.selected_member,
                close_callback: function(args){
                    var e = editor;
                    that.close_select_modal(e, args);
                }
            })).render().open();

            this.$el.parents('.ui-dialog').find('.ui-dialog-title').text('Custom Filter');

    },

    /**
     * Callback to update the editor with the selected member.
     * @param editor
     * @param n
     */
    close_select_modal: function(editor, n){
        editor.insert(n);
    },

    help: function(){
        window.open("http://wiki.meteorite.bi/display/SAIK/Filtering");
    }

});
<|endoftext|>


<commit_before>var through = require('through');
var hyperglue = require('hyperglue');
var domify = require('domify');

module.exports = function (html, cb) {
    var className = classNameOf(html);

    var tr = through(function (line) {
        var row;
        if (isInt8Array(line)) {
            var s = '';
            for (var i = 0; i < line.length; i++) s += line[i];
            line = s;
        }
        if (typeof line === 'string') {
            try { row = JSON.parse(line) }
            catch (err) { this.emit('error', err) }
        }
        else row = line;

        var res = cb.call(this, row);
        if (res) {
            var elem = hyperglue(html, res);
            this.emit('element', elem);
            this.queue(elem.outerHTML);
        }
    });

    tr.prependTo = function (t) {
        var target = getTarget(t);

        tr.on('element', function (elem) {
            target.insertBefore(elem, target.childNodes[0]);
        });
        return tr;
    };

    tr.appendTo = function (t) {
        var target = getTarget(t);

        tr.on('element', function (elem) {
            target.appendChild(elem);
        });
        return tr;
    };

    tr.sortTo = function (t, cmp) {
        if (typeof cmp !== 'function') {
            throw new Error('comparison function not provided');
        }
        var target = getElem(t);

        tr.on('element', function (elem) {
            var nodes = target.getElementsByClassName(className);
            for (var i = 0; i < nodes.length; i++) {
                var n = cmp(elem, nodes[i]);
                if (n < 0) {
                    if (hasChild(target, elem)) {
                        target.removeChild(elem);
                    }
                    target.insertBefore(elem, nodes[i]);
                    return;
                }
            }
            target.appendChild(elem);
        });

        getTarget(t, target);
        return tr;
    };

    var emittedElements = false;
    return tr;

    function getTarget (t, target) {
        if (!target) target = getElem(t);
        tr.emit('parent', target);
        if (!className) return target;
        if (emittedElements) return target;
        emittedElements = true;

        var elems = target.getElementsByClassName(className);
        for (var i = 0; i < elems.length; i++) {
            tr.emit('element', elems[i]);
        }
        return target;
    }
};

function classNameOf (html) {
    var elems = domify(html);
    if (elems.length) return elems[0].getAttribute('class');
}

function hasChild (node, child) {
    var nodes = node.childNodes;
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i] === child) return true;
    }
    return false;
}

function getElem (target) {
    if (typeof target === 'string') {
        return document.querySelector(target);
    }
    return target;
}

function isInt8Array (line) {
    return line && typeof line === 'object'
        && line.constructor === 'function'
        && line.constructor.name === 'Int8Array'
    ;
}
<commit_msg>handle sub-stream properties<commit_after>var through = require('through');
var hyperglue = require('hyperglue');
var domify = require('domify');

module.exports = function (html, cb) {
    var className = classNameOf(html);

    var tr = through(function (line) {
        var row;
        if (isInt8Array(line)) {
            var s = '';
            for (var i = 0; i < line.length; i++) s += line[i];
            line = s;
        }
        if (typeof line === 'string') {
            try { row = JSON.parse(line) }
            catch (err) { this.emit('error', err) }
        }
        else row = line;

        var res = cb.call(this, row);
        if (!res) return;
        var keys = objectKeys(res);
        var streams = [];

        for (var i = 0; i < keys.length; i++) (function (key) {
            var x = res[key];
            if (!isStream(x)) return;
            delete res[key];
            streams.push([key, x ]);
            tr.emit('stream', x);
        })(keys[i]);

        var elem = hyperglue(html, res);

        for (var i = 0; i < streams.length; i++) (function (stream) {
            var cur = elem.querySelector(key);
            if (!cur) return;

            stream.on('element', function (elem) {
                cur.appendChild(elem);
                stream.removeListener('data', ondata);
            });
            stream.on('data', ondata);
            function ondata (e) { cur.innerHTML += e }
        })(streams[i]);

        this.emit('element', elem);
        this.queue(elem.outerHTML);
    });

    tr.prependTo = function (t) {
        var target = getTarget(t);

        tr.on('element', function (elem) {
            target.insertBefore(elem, target.childNodes[0]);
        });
        return tr;
    };

    tr.appendTo = function (t) {
        var target = getTarget(t);

        tr.on('element', function (elem) {
            target.appendChild(elem);
        });
        return tr;
    };

    tr.sortTo = function (t, cmp) {
        if (typeof cmp !== 'function') {
            throw new Error('comparison function not provided');
        }
        var target = getElem(t);

        tr.on('element', function (elem) {
            var nodes = target.getElementsByClassName(className);
            for (var i = 0; i < nodes.length; i++) {
                var n = cmp(elem, nodes[i]);
                if (n < 0) {
                    if (hasChild(target, elem)) {
                        target.removeChild(elem);
                    }
                    target.insertBefore(elem, nodes[i]);
                    return;
                }
            }
            target.appendChild(elem);
        });

        getTarget(t, target);
        return tr;
    };

    var emittedElements = false;
    return tr;

    function getTarget (t, target) {
        if (!target) target = getElem(t);
        tr.emit('parent', target);
        if (!className) return target;
        if (emittedElements) return target;
        emittedElements = true;

        var elems = target.getElementsByClassName(className);
        for (var i = 0; i < elems.length; i++) {
            tr.emit('element', elems[i]);
        }
        return target;
    }
};

function classNameOf (html) {
    var elems = domify(html);
    if (elems.length) return elems[0].getAttribute('class');
}

function hasChild (node, child) {
    var nodes = node.childNodes;
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i] === child) return true;
    }
    return false;
}

function getElem (target) {
    if (typeof target === 'string') {
        return document.querySelector(target);
    }
    return target;
}

function isInt8Array (line) {
    return line && typeof line === 'object'
        && line.constructor === 'function'
        && line.constructor.name === 'Int8Array'
    ;
}

function isStream (x) {
    return x && typeof x.pipe === 'function';
}

var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
};
<|endoftext|>


<commit_before>var dat = require('/dat');
var login = require('/ui/common/login');

exports.createManageWindow = function() {
	var Cloud = require('ti.cloud');
	Cloud.debug = true;
	var token = dat.getMyStoredAccessToken();
	// Create a user
	// ACS app must be configured to use 3-legged OAuth
	if (token) {

		Cloud.accessToken = token;
		// Ti.App.fireEvent('loggedIn',{});

	} else {

		login.createLoginWindow();

	}

	var win = Ti.UI.createWindow({
		title : 'Manage Jobs',
		backgroundColor : "white",
		layout : 'vertical'
	});

	var view = Ti.UI.createView({
		width : Ti.UI.FILL,
		height : '95%'
	});

	win.add(view);

	showEntries(view);

	win.open();

	var backBtn = Ti.UI.createButton({
		title : 'Back',
		width : Ti.UI.FILL,
		height : Ti.UI.FILL
	});

	backBtn.addEventListener('click', function() {
		win.close();
	});
	win.add(backBtn);

}
var showEntries = function(view) {
	var Cloud = require('ti.cloud');
	Cloud.debug = true;

	Cloud.Users.showMe(function(e) {
		var claimBtn = new Array();
		var delBtn = new Array();
		if (e.success) {
			var user = e.users[0];
			Ti.API.info('email ' + user.email);
			var myJobs = Cloud.Objects.query({
				classname : 'jobs',
				limit : 1000,

				where : {
					user_id : user.id
				}
			}, function(f) {
				if (f.success) {
					var table = Ti.UI.createTableView({
						width : Ti.UI.FILL,
						height : Ti.UI.FILL,
						layout : 'vertical'
					});
					var rows = new Array();
					for (var i = 0; i < f.jobs.length; i++) {
						var job = f.jobs[i];
						var row = Ti.UI.createTableViewRow({
							//layout : 'horizontal',
							//width : Ti.UI.FILL,
							height : Ti.UI.SIZE,
							id: job.id
						});
						delBtn[i] = Ti.UI.createButton({
							title : 'Delete',
							right : 0,
							width : '15%'
						});
						delBtn[i].addEventListener('click', function() {
							Cloud.Objects.remove({
								classname : 'jobs',
								id : this.parent.id,
							}, function(g) {
								if (g.success) {
									view.removeAllChildren();
									// table.close();
									showEntries(view);
								} else {
									alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
								}
							});
						});
						var label = Ti.UI.createLabel({
							height : Ti.UI.SIZE,
							width : '50%',
							left : 0,
							text : job.description + '  ' + job.wage + '  ' + job.time_estimate + "\n" + job.expiration
						});
						var claimButton;
						var claimColor;
						if (job.claimed == true) {
							claimButton = 'Unclaim';
							claimColor = 'red';
						} else {
							claimButton = 'Claim';
							claimColor = 'green';
						}
						claimBtn = Ti.UI.createButton({
							title : claimButton,
							width : '25%',
							right : '20%',
							backgroundColor : claimColor,
							color : claimColor
						});
						claimBtn[i].addEventListener('click', function() {
							var claimVal;
							if (claimBtn.title == 'Claim') {
								claimVal = true;
							} else {
								claimVal = false;
							}
							Ti.API.info("Job: " + this.parent.id);
							Cloud.Objects.update({
								classname : 'jobs',
								id : this.parent.id,
								fields : {
									claimed : claimVal
								}
							}, function(g) {
								if (g.success) {
									view.removeAllChildren();
									// table.close();
									showEntries(view);
								} else {
									alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
								}
							});
						});
						row.add(label);
						row.add(delBtn[i]);
						row.add(claimBtn[i]);
						Ti.API.info(row);
						Ti.API.info(label.text);
						Ti.API.info(jID[i]);
						rows.push(row);
					} // end of for each job loop for loop
				} else {//	end of if success loop funcrtion(f)

					alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
				}
				Ti.API.info(row);
				/*table.addEventListener('click', function(e) {
					if (e.source && e.source.objName !== 'table') {
						Ti.API.info('Row swiped: ' + e.source);
						Ti.API.info('Row swiped: ' + e.source.objName);
						Ti.API.info('Row ID : ' + e.source.rowID);
					}
				});*/
				table.data = rows;
				view.add(table);
				Ti.API.info(rows);
				Ti.API.info(table.data);
			});
			//end of function f

		}// end of if e success
		else {
			alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
		}
	});
	// end of function e
}// end of show entries function <commit_msg>Fixed errors<commit_after>var dat = require('/dat');
var login = require('/ui/common/login');

exports.createManageWindow = function() {
	var Cloud = require('ti.cloud');
	Cloud.debug = true;
	var token = dat.getMyStoredAccessToken();
	// Create a user
	// ACS app must be configured to use 3-legged OAuth
	if (token) {

		Cloud.accessToken = token;
		// Ti.App.fireEvent('loggedIn',{});

	} else {

		login.createLoginWindow();

	}

	var win = Ti.UI.createWindow({
		title : 'Manage Jobs',
		backgroundColor : "white",
		layout : 'vertical'
	});

	var view = Ti.UI.createView({
		width : Ti.UI.FILL,
		height : '95%'
	});

	win.add(view);

	showEntries(view);

	win.open();

	var backBtn = Ti.UI.createButton({
		title : 'Back',
		width : Ti.UI.FILL,
		height : Ti.UI.FILL
	});

	backBtn.addEventListener('click', function() {
		win.close();
	});
	win.add(backBtn);

}
var showEntries = function(view) {
	var Cloud = require('ti.cloud');
	Cloud.debug = true;

	Cloud.Users.showMe(function(e) {
		var claimBtn = new Array();
		var delBtn = new Array();
		if (e.success) {
			var user = e.users[0];
			Ti.API.info('email ' + user.email);
			var myJobs = Cloud.Objects.query({
				classname : 'jobs',
				limit : 1000,

				where : {
					user_id : user.id
				}
			}, function(f) {
				if (f.success) {
					var table = Ti.UI.createTableView({
						width : Ti.UI.FILL,
						height : Ti.UI.FILL,
						layout : 'vertical'
					});
					var rows = new Array();
					for (var i = 0; i < f.jobs.length; i++) {
						var job = f.jobs[i];
						var row = Ti.UI.createTableViewRow({
							//layout : 'horizontal',
							//width : Ti.UI.FILL,
							height : Ti.UI.SIZE,
							id: job.id
						});
						delBtn[i] = Ti.UI.createButton({
							title : 'Delete',
							right : 0,
							width : '15%'
						});
						delBtn[i].addEventListener('click', function() {
							Cloud.Objects.remove({
								classname : 'jobs',
								id : this.parent.id,
							}, function(g) {
								if (g.success) {
									view.removeAllChildren();
									// table.close();
									showEntries(view);
								} else {
									alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
								}
							});
						});
						var label = Ti.UI.createLabel({
							height : Ti.UI.SIZE,
							width : '50%',
							left : 0,
							text : job.description + '  ' + job.wage + '  ' + job.time_estimate + "\n" + job.expiration
						});
						var claimButton;
						var claimColor;
						if (job.claimed == true) {
							claimButton = 'Unclaim';
							claimColor = 'red';
						} else {
							claimButton = 'Claim';
							claimColor = 'green';
						}
						claimBtn[i] = Ti.UI.createButton({
							title : claimButton,
							width : '25%',
							right : '20%',
							backgroundColor : claimColor,
							color : claimColor
						});
						claimBtn[i].addEventListener('click', function() {
							var claimVal;
							if (claimBtn.title == 'Claim') {
								claimVal = true;
							} else {
								claimVal = false;
							}
							Ti.API.info("Job: " + this.parent.id);
							Cloud.Objects.update({
								classname : 'jobs',
								id : this.parent.id,
								fields : {
									claimed : claimVal
								}
							}, function(g) {
								if (g.success) {
									view.removeAllChildren();
									// table.close();
									showEntries(view);
								} else {
									alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
								}
							});
						});
						row.add(label);
						row.add(delBtn[i]);
						row.add(claimBtn[i]);
						Ti.API.info(row);
						Ti.API.info(label.text);
						rows.push(row);
					} // end of for each job loop for loop
				} else {//	end of if success loop funcrtion(f)

					alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
				}
				Ti.API.info(row);
				/*table.addEventListener('click', function(e) {
					if (e.source && e.source.objName !== 'table') {
						Ti.API.info('Row swiped: ' + e.source);
						Ti.API.info('Row swiped: ' + e.source.objName);
						Ti.API.info('Row ID : ' + e.source.rowID);
					}
				});*/
				table.data = rows;
				view.add(table);
				Ti.API.info(rows);
				Ti.API.info(table.data);
			});
			//end of function f

		}// end of if e success
		else {
			alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
		}
	});
	// end of function e
}// end of show entries function <|endoftext|>


<commit_before>"use strict";

var pg = require('pg');
var Q = require('q');

// TODO: Switch to connection pooling?
// Transactions with pooling is kind of difficult to get right. Must
// have an automatic api for it then, since you can't have all that
// code on the api consumer side.
// https://github.com/brianc/node-postgres/wiki/Transactions

function ProgresClient (postgresClient) {

	this.postgresClient = postgresClient;
}

ProgresClient.prototype.query = function (SQL, parameters) {

	return Q
		.nbind(this.postgresClient.query, this.postgresClient)(SQL, parameters)
		.catch(function (error) {

			// Add some useful info.
			error.SQL        = SQL;
			error.parameters = parameters;

			// Rethrow the error since it wasn't handled.
			throw error;

		})
		.then(function (result) {

			return result.rows;
		});
};

module.exports = {

	connect: function (connectionString, job) {

		// Wrap the job in Q().then(...) to catch exceptions.
		var wrappedJob = Q().then(function () {

			return job(new ProgresClient(postgresClient));
		});

		var postgresClient = new pg.Client(connectionString);

		return Q.nbind(postgresClient.connect, postgresClient)()
			.then(wrappedJob)
			.finally(function () {

				postgresClient.end();
			});
	},

	ProgresClient: ProgresClient
};
<commit_msg>Added comments.<commit_after>"use strict";

var pg = require('pg');
var Q = require('q');

// TODO: Switch to connection pooling?
// Transactions with pooling is kind of difficult to get right. Must
// have an automatic api for it then, since you can't have all that
// code on the api consumer side.
// https://github.com/brianc/node-postgres/wiki/Transactions

function ProgresClient (postgresClient) {

	this.postgresClient = postgresClient;
}

ProgresClient.prototype.query = function (SQL, parameters) {

	return Q
		.nbind(this.postgresClient.query, this.postgresClient)(SQL, parameters)
		.catch(function (error) {

			// Add some useful info.
			error.SQL        = SQL;
			error.parameters = parameters;

			// Rethrow the error since it wasn't handled.
			throw error;

		})
		.then(function (result) {

			return result.rows;
		});
};

module.exports = {

	connect: function (connectionString, job) {

		// Wrap the job in Q().then(...) to catch exceptions.
		var wrappedJob = Q().then(function () {

			return job(new ProgresClient(postgresClient));
		});

		var postgresClient = new pg.Client(connectionString);

		return (
			// Connect.
			Q.nbind(postgresClient.connect, postgresClient)()

			// Do the job.
			.then(wrappedJob)

			// Disconnect.
			.finally(function () {

				postgresClient.end();
			})
		);
	},

	ProgresClient: ProgresClient
};
<|endoftext|>


<commit_before>'use strict';

var mongoose = require('mongoose');
var config = require('../config');
require('../models/wallet');
require('../models/walletAddress');
require('../models/transaction');
require('../models/block');

var StorageService = function(){
};

StorageService.prototype.start = function(ready) {
  mongoose.connect('mongodb://' + config.dbHost + '/fullNodePlus?socketTimeoutMS=3600000&noDelay=true', {
    keepAlive: 15,
    poolSize: config.maxPoolSize
  }, ready);
};

StorageService.prototype.stop = function() {

};

module.exports = new StorageService();<commit_msg>use mongo client (get rid of deprecation warnings)<commit_after>'use strict';

var mongoose = require('mongoose');
var config = require('../config');
require('../models/wallet');
require('../models/walletAddress');
require('../models/transaction');
require('../models/block');

var StorageService = function(){
};

StorageService.prototype.start = function(ready) {
  mongoose.connect('mongodb://' + config.dbHost + '/fullNodePlus?socketTimeoutMS=3600000&noDelay=true', {
    useMongoClient: true,
    keepAlive: 15,
    poolSize: config.maxPoolSize
  }, ready);
};

StorageService.prototype.stop = function() {

};

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


<commit_before>// get URL parameters
// http://stackoverflow.com/a/979995
var Q = (function () {
    // This function is anonymous, is executed immediately and
    // the return value is assigned to Q!
    var i = 0;
    var query_string = {};
    var query = window.location.search.substring(1);
    var vars = query.split('&');
    while (i < vars.length) {
        var pair = vars[i].split('=');
        // If first entry with this name
        if (typeof query_string[pair[0]] === 'undefined') {
            query_string[pair[0]] = pair[1];
            // If second entry with this name
        } else if (typeof query_string[pair[0]] === 'string') {
            var arr = [ query_string[pair[0]], pair[1] ];
            query_string[pair[0]] = arr;
            // If third or later entry with this name
        } else {
            query_string[pair[0]].push(pair[1]);
        }
        i++;
    }
    return query_string;
}());

var MRHelpers = (function () {
    var constructJosmUri = function (bounds, features) {
        var nodes = [];
        var ways = [];
        var sw = bounds.getSouthWest();
        var ne = bounds.getNorthEast();
        var uri = 'http://127.0.0.1:8111/load_and_zoom?left=' + sw.lng + '&right=' + ne.lng + '&top=' + ne.lat + '&bottom=' + sw.lat + '&new_layer=0&select=';

        for (f in features) {
            var feature = features[f];
            switch (feature.geometry.type) {
                case 'Point':
                    url += 'node' + feature.properties.osmid;
                    break;
                case 'LineString':
                    url += 'way' + feature.properties.osmid;
                    break;
            }
        }
        return uri;
    };

    var mqResultToString = function (addr) {
        var out, county, town;
        if(!addr || !(addr.town || addr.county || addr.hamlet || addr.state || addr.country)) { return 'We are somewhere on earth..' };
        out = 'We are ';
        if(addr.city != null) { out += addr.city }
        else {
            if(addr.town != null) { town = 'in ' + addr.town }
            else if(addr.hamlet != null) { town = 'in ' + addr.hamlet }
            else { town = 'somewhere in ' };
            out += town;
            if(addr.county) {
                if(addr.county.toLowerCase().indexOf('county') > -1) { county = ', ' + addr.county + ', ' }
                else { county = ', ' + addr.county + ' County, ' };
            } else { county = '' };
            out += county;
        }
        if(addr.state) { out += addr.state + ', ' };
        if(addr.country) {
            if(addr.country.indexOf('United States') > -1) { out += 'the ' };
            out += addr.country;
        };
        out += '.';
        return out;
    };

    var openInJOSM = function (bounds, features) {
        var josmUri = constructJosmUri(bounds, features);
        console.log('opening in JOSM');
        // Use the .ajax JQ method to load the JOSM link unobtrusively and alert when the JOSM plugin is not running.
        $.ajax({
            url     : josmUri,
            success : function (t) {
                if (t.status!=200) {
                    notify.log('JOSM remote control did not respond. Do you have JOSM running with Remote Control enabled?');
                } else { setTimeout('confirmRemap(\'j\')', 4000); }
            }
        });
    };

    return {
        mqResultToString    : mqResultToString,
        openInJOSM          : openInJOSM
    }
}());

var MRConfig = (function () {
    // the UI strings
    return {
        strings:  {
            msgNextChallenge: 'Faites vos jeux...',
            msgMovingOnToNextChallenge: 'OK, moving right along...',
            msgZoomInForEdit: 'Please zoom in a little so we don\'t have to load a huge area from the API.'
        },

        // the default map options
        mapOptions: {
            center: new L.LatLng(40, -90),
            zoom: 17
        },

        // default tile URL
        tileUrl: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',

        // default tile attribution
        tileAttrib: '©  OpenStreetMap contributors',

        // minimum zoom level for enabling edit buttons
        minZoomLevelForEditing: 14
    };
}());

var MRManager = (function () {
    var map;
    var challenge;
    var task;
    var near = Q.near;
    var difficulty = Q.difficulty;
    var taskLayer;

    // define humane notification instance
    var notify = humane.create({ timeout: 1500 });

    /*
     * This function initializes the leaflet map.
     * identifier is the div id on the page
     */
    var createMap = function (identifier) {

        // map GeoJSON layer
        taskLayer = new L.geoJson(null, {
            onEachFeature   : function (feature, layer) {
                if(feature.properties && feature.properties.text) {
                    layer.bindPopup(feature.properties.text);
                    return layer.openPopup();
                }
            }
        });

        map = new L.Map(identifier, MRConfig.mapOptions);
        var tileLayer = new L.TileLayer(MRConfig.tileUrl, { attribution: MRConfig.tileAttrib });

        // Locate the user and define the event triggers
        map.locate({ setView: true, timeout: 1000, maximumAge: 0 });
        map.on('locationfound', function (e) {
            console.log('location found: ' + e);
        });
        map.on('locationerror', function (e) {
            console.log('location not found: ' + e.message);
        });

        map.addLayer(tileLayer);
        map.addLayer(taskLayer);
    };

    /*
     * get a random challenge with optional near and difficulty paramters
     */
    var selectChallenge = function () {

        var url = '/api/challenges/';

        if (near && difficulty) {
            console.log('we got near and difficulty');
            url += '?difficulty=' + difficulty + '&contains=' + near;
        } else if (near) {
            console.log('we got near');
            url += '?contains=' + near;
        } else if (difficulty) {
            console.log('we got difficulty');
            url += '?difficulty=' + difficulty;
        } else {
            console.log('we got neither near or difficulty');
        };

        // fire the request for a new challenge with the contructed URL
        $.ajax(
        {
            url     : url,
            async   : false,
            success : function (data) { challenge = data[0]; },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    };

    /*
     * get the selected challenge
     */
     var getChallengeDetails = function () {
        // check if we have a challenge, if not get one.
        if (typeof challenge === 'undefined') {
            selectChallenge();
        };

        // request the challenge details
        console.log('getting challenge details');
        url = '/api/challenge/' + challenge.slug;
        $.ajax({
            url     : url,
            success : function (data) {
                $.each(data, function(key, value) {
                    challenge[key] = value;
                });
                // update the challenge detail UI elements
                $('#challenge_title').text(challenge.title);
                $('#challenge_description').text(challenge.description);
                // and move on to get the stats
                getChallengeStats()
            },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    }

    var getChallengeStats = function () {
        // now get the challenge stats
        console.log('getting challenge stats');
        url = '/api/challenge/' + challenge.slug + '/stats';
        challenge.stats = {};
        $.ajax({
            url     : url,
            success : function (data) {
                $.each(data, function(key, value) {
                    challenge.stats[key] = value;
                });
                // update the stats UI elements
                $('#stats #total').text(challenge.stats.total);
                $('#stats #available').text(challenge.stats.available);
            },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    };

    /*
     * get a task for the current challenge
     */
    var getTask = function () {

        // check if we have a challenge, if not get one.
        if (typeof challenge === 'undefined') {
            selectChallenge();
        };

        // get a task
        $.ajax({
            url     : '/api/challenge/' + challenge.slug + '/task',
            async   : false,
            success: function (data) { task = data },
            error: function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });

        //...and its geometries
        $.ajax({
            url     : '/api/challenge/' + challenge.slug + '/task/' + task.id + '/geometries',
            async   : false,
            success : function (data) { task.features = data.features; },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    };

    /*
     * draw the task features onto the map canvas
     */
    var drawTask = function () {
        // clear the previous task from the layer
        taskLayer.clearLayers();

        // if we don't have a task, get one
        if (typeof task === 'undefined') {
            console.log('we don\'t have a task');
            return false;
        };

        // draw all features of this task on the task layer
        for(var i = 0; i < task.features.length; i++) {
            feature = task.features[i];
            taskLayer.addData(feature);
            console.log('geojson layer now has ' + taskLayer.getLayers().length + ' things.');
        }
        // fit the map snugly to the task features
        map.fitBounds(taskLayer.getBounds().pad(0.2));
        // show the task text as a notification
        notify.log(task.text, { timeout: 3000 });
        // let the user know where we are
        displayAdminArea();
    };

    var displayAdminArea = function() {
        var mqurl = 'http://open.mapquestapi.com/nominatim/v1/reverse?format=json&lat=' + map.getCenter().lat + ' &lon=' + map.getCenter().lng;
        $.ajax({
            url     : mqurl,
            success : function (data) { notify.log(MRHelpers.mqResultToString(data.address)); },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    }

    var initialize = function (identifier) {
        // create the map
        createMap(identifier);
        // and display the next task
        next();
        // get the challenge details
        getChallengeDetails();
    }

    var next = function () {
        getTask();
        drawTask();
    }

    var openTaskInEditor = function (editor) {
        if (map.getZoom() < MRConfig.minZoomLevelForEditing){
            notify.log(MRConfig.strings.msgZoomInForEdit, 3);
            return false;
        };
        console.log('opening in ' + editor);
        if (editor === 'j') { MRHelpers.openInJOSM(map.getBounds(), task.features) }
        else { // OSM default
            var editURL = 'http://www.openstreetmap.org/edit?bbox=' + map.getBounds().toBBoxString();
            window.open(editURL);
            setTimeout('confirmRemap(\'p\')', 4000)
        }
    }

    return {
        init            : initialize,
        nextTask        : next,
        openTaskInEditor: openTaskInEditor
    };
}());

// initialization
function init() {
    MRManager.init('map');
};
<commit_msg>unbreaking near functionality and improving rev geocode stringifying<commit_after>// get URL parameters
// http://stackoverflow.com/a/979995
var Q = (function () {
    // This function is anonymous, is executed immediately and
    // the return value is assigned to Q!
    var i = 0;
    var query_string = {};
    var query = window.location.search.substring(1);
    var vars = query.split('&');
    while (i < vars.length) {
        var pair = vars[i].split('=');
        // If first entry with this name
        if (typeof query_string[pair[0]] === 'undefined') {
            query_string[pair[0]] = pair[1];
            // If second entry with this name
        } else if (typeof query_string[pair[0]] === 'string') {
            var arr = [ query_string[pair[0]], pair[1] ];
            query_string[pair[0]] = arr;
            // If third or later entry with this name
        } else {
            query_string[pair[0]].push(pair[1]);
        }
        i++;
    }
    return query_string;
}());

var MRHelpers = (function () {
    var constructJosmUri = function (bounds, features) {
        var nodes = [];
        var ways = [];
        var sw = bounds.getSouthWest();
        var ne = bounds.getNorthEast();
        var uri = 'http://127.0.0.1:8111/load_and_zoom?left=' + sw.lng + '&right=' + ne.lng + '&top=' + ne.lat + '&bottom=' + sw.lat + '&new_layer=0&select=';

        for (f in features) {
            var feature = features[f];
            switch (feature.geometry.type) {
                case 'Point':
                    url += 'node' + feature.properties.osmid;
                    break;
                case 'LineString':
                    url += 'way' + feature.properties.osmid;
                    break;
            }
        }
        return uri;
    };

    var addComma = function(str) {
        return (str.match(/\,\s+$/) || str.match(/in\s+$/))?'':', ';
    }

    var mqResultToString = function (addr) {
        var out, county, town;
        if(!addr || !(addr.town || addr.county || addr.hamlet || addr.state || addr.country)) { return 'We are somewhere on earth..' };
        out = 'We are ';
        if(addr.city != null) { out += 'in ' + addr.city }
        else if (addr.town != null) { out += 'in ' + addr.town }
        else if (addr.hamlet != null) { out + 'in ' + addr.hamlet  }
        else { out += 'somewhere in ' };
        out += addComma(out);
        if(addr.county) {
            if(addr.county.toLowerCase().indexOf('county') > -1) { out += addr.county }
            else { out += addr.county + ' County' };
        };
        out += addComma(out);
        if(addr.state) { out += addr.state };
        out += addComma(out);
        if(addr.country) {
            if(addr.country.indexOf('United States') > -1) { out += 'the ' };
            out += addr.country;
        };
        out += '.';
        return out;
    };

    var openInJOSM = function (bounds, features) {
        var josmUri = constructJosmUri(bounds, features);
        console.log('opening in JOSM');
        // Use the .ajax JQ method to load the JOSM link unobtrusively and alert when the JOSM plugin is not running.
        $.ajax({
            url     : josmUri,
            success : function (t) {
                if (t.status!=200) {
                    notify.log('JOSM remote control did not respond. Do you have JOSM running with Remote Control enabled?');
                } else { setTimeout('confirmRemap(\'j\')', 4000); }
            }
        });
    };

    return {
        mqResultToString    : mqResultToString,
        openInJOSM          : openInJOSM
    }
}());

var MRConfig = (function () {
    // the UI strings
    return {
        strings:  {
            msgNextChallenge: 'Faites vos jeux...',
            msgMovingOnToNextChallenge: 'OK, moving right along...',
            msgZoomInForEdit: 'Please zoom in a little so we don\'t have to load a huge area from the API.'
        },

        // the default map options
        mapOptions: {
            center: new L.LatLng(40, -90),
            zoom: 17
        },

        // default tile URL
        tileUrl: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',

        // default tile attribution
        tileAttrib: '©  OpenStreetMap contributors',

        // minimum zoom level for enabling edit buttons
        minZoomLevelForEditing: 14
    };
}());

var MRManager = (function () {
    var map;
    var challenge;
    var task;
    var near = (Q.lon && Q.lat) ? { 'lon': parseFloat(Q.lon), 'lat': parseFloat(Q.lat) } : {};
    var difficulty = parseInt(Q.difficulty);
    var taskLayer;

    // define humane notification instance
    var notify = humane.create({ timeout: 1500 });

    /*
     * A helper function to construct the URL parameters for location and difficulty
     * if it is for a challenge, we need the difficulty as well as the location.
     */
    var constructUrlParameters = function (isChallenge) {
        var urlParams = '?';
        if (typeof near.lat === 'number' && typeof near.lon === 'number') { // this is not quite accurate but good enough for a casual check.
            urlParams += 'lon=' + near.lon + '&lat=' + near.lat + '&';
        };
        if ([1,2,3].indexOf(difficulty) > -1 && isChallenge) { // difficulty must be 1,2,3
            urlParams += 'difficulty=' + difficulty };
        return urlParams;
    }

    /*
     * This function initializes the leaflet map, gets the user location, and loads the first task.
     * A challenge is selected based on the user location, the URL parameter, or on the server side using the stored OSM home location.
     * identifier is the div id on the page
     */
    var init = function (identifier) {

        // a friendly welcome
        notify.log(['Welcome to MapRoulette!']);

        // map GeoJSON layer
        taskLayer = new L.geoJson(null, {
            onEachFeature   : function (feature, layer) {
                if(feature.properties && feature.properties.text) {
                    layer.bindPopup(feature.properties.text);
                    return layer.openPopup();
                }
            }
        });

        // initialize the map
        map = new L.Map(identifier, MRConfig.mapOptions);

        // and the tile layer
        var tileLayer = new L.TileLayer(MRConfig.tileUrl, { attribution: MRConfig.tileAttrib });

        // Locate the user and define the event triggers
        map.locate({ setView: false, timeout: 10000, maximumAge: 0 });
        // If the location is found, let the user know, and store.
        map.on('locationfound', function (e) {
            console.log('location found: ' + e.latlng);
            near.lat = parseFloat(e.latlng.lat);
            near.lon = parseFloat(e.latlng.lng);
            notify.log('We found your location. You next task will be closer to home!');
        });
        // If the location is not found, meh.
        map.on('locationerror', function (e) {
            console.log('location not found or not permitted: ' + e.message);
        });

        // Add both the tile layer and the task layer to the map
        map.addLayer(tileLayer);
        map.addLayer(taskLayer);

        // now load a task (this will select a challenge first)
        nextTask();

        // and request the challenge details and stats (slow)
        getChallengeDetails();
    };

    /*
     * get a random challenge with optional near and difficulty paramters
     */
    var selectChallenge = function () {

        var url = '/api/challenges/' + constructUrlParameters();

        // fire the request for a new challenge with the contructed URL
        $.ajax(
        {
            url     : url,
            async   : false,
            success : function (data) { challenge = data[0]; },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    };

    /*
     * get the selected challenge
     */
     var getChallengeDetails = function () {
        // check if we have a challenge, if not get one.
        if (typeof challenge === 'undefined') {
            selectChallenge();
        };

        // request the challenge details
        console.log('getting challenge details');
        url = '/api/challenge/' + challenge.slug;
        $.ajax({
            url     : url,
            success : function (data) {
                $.each(data, function(key, value) {
                    challenge[key] = value;
                });
                // update the challenge detail UI elements
                $('#challenge_title').text(challenge.title);
                $('#challenge_description').text(challenge.description);
                // and move on to get the stats
                getChallengeStats()
            },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    }

    var getChallengeStats = function () {
        // now get the challenge stats
        console.log('getting challenge stats');
        url = '/api/challenge/' + challenge.slug + '/stats';
        challenge.stats = {};
        $.ajax({
            url     : url,
            success : function (data) {
                $.each(data, function(key, value) {
                    challenge.stats[key] = value;
                });
                // update the stats UI elements
                $('#stats #total').text(challenge.stats.total);
                $('#stats #available').text(challenge.stats.available);
            },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    };

    /*
     * get a task for the current challenge
     */
    var getTask = function () {

        // check if we have a challenge, if not get one.
        if (typeof challenge === 'undefined') {
            selectChallenge();
        };

        // get a task
        $.ajax({
            url     : '/api/challenge/' + challenge.slug + '/task' + constructUrlParameters(),
            async   : false,
            success: function (data) { task = data },
            error: function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });

        //...and its geometries
        $.ajax({
            url     : '/api/challenge/' + challenge.slug + '/task/' + task.id + '/geometries',
            async   : false,
            success : function (data) { task.features = data.features; },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    };

    /*
     * draw the task features onto the map canvas
     */
    var drawTask = function () {
        // clear the previous task from the layer
        taskLayer.clearLayers();

        // if we don't have a task, get one
        if (typeof task === 'undefined') {
            console.log('we don\'t have a task');
            return false;
        };

        // draw all features of this task on the task layer
        for(var i = 0; i < task.features.length; i++) {
            feature = task.features[i];
            taskLayer.addData(feature);
            console.log('geojson layer now has ' + taskLayer.getLayers().length + ' things.');
        }
        // fit the map snugly to the task features
        map.fitBounds(taskLayer.getBounds().pad(0.2));
        // show the task text as a notification
        notify.log(task.text, { timeout: 3000 });
        // let the user know where we are
        displayAdminArea();
    };

    var displayAdminArea = function() {
        var mqurl = 'http://open.mapquestapi.com/nominatim/v1/reverse?format=json&lat=' + map.getCenter().lat + ' &lon=' + map.getCenter().lng;
        $.ajax({
            url     : mqurl,
            success : function (data) { notify.log(MRHelpers.mqResultToString(data.address)); },
            error   : function (jqXHR, textStatus, errorThrown) { console.log('ajax error'); }
        });
    }

    var nextTask = function () {
        getTask();
        drawTask();
    }

    var openTaskInEditor = function (editor) {
        if (map.getZoom() < MRConfig.minZoomLevelForEditing){
            notify.log(MRConfig.strings.msgZoomInForEdit, 3);
            return false;
        };
        console.log('opening in ' + editor);
        if (editor === 'j') { MRHelpers.openInJOSM(map.getBounds(), task.features) }
        else { // OSM default
            var editURL = 'http://www.openstreetmap.org/edit?bbox=' + map.getBounds().toBBoxString();
            window.open(editURL);
            setTimeout('confirmRemap(\'p\')', 4000)
        }
    }

    return {
        init            : init,
        nextTask        : nextTask,
        openTaskInEditor: openTaskInEditor
    };
}());

// initialization
function init() {
    MRManager.init('map');
};
<|endoftext|>


<commit_before>/*jshint maxlen:false */

define({
    ADVANCED_FEATURES_WARNING:          "This features are not recommended for basic Git users as they may cause you to lose code that has been already commited if used inproperly. Use with caution.",
    ADD_ENDLINE_TO_THE_END_OF_FILE:     "Add endline at the end of file",
    ADD_TO_GITIGNORE:                   "Add to .gitignore",
    AGREE_TO_STORE_PASSWORDS:           "I agree that password are stored in plain text on my computer",
    AMEND_COMMIT:                       "Amend last commit",
    AMEND_COMMIT_FORBIDDEN:             "Cannot amend commit when there are no unpushed commits",
    AUTHOR:                             "Author",
    AUTHORS_OF:                         "Authors of",
    AVATAR_TYPE:                        "Avatar type",
    BASH_NOT_AVAILABLE:                 "Bash is not available or properly configured",
    BASIC_CONFIGURATION:                "Basic configuration",
    BRACKETS_GIT_ERROR:                 "Brackets Git encountered an error\u2026",
    BRANCH_NAME:                        "Branch name",
    BUTTON_FIND_CONFLICTS:              "Find conflicts\u2026",
    BLACK_WHITE_AVATAR:                 "Black and white avatar",
    BUTTON_CANCEL:                      "Cancel",
    BUTTON_CHANGELOG:                   "Show changelog",
    BUTTON_CLOSE:                       "Close",
    BUTTON_DEFAULTS:                    "Restore defaults",
    BUTTON_OK:                          "OK",
    BUTTON_REPORT:                      "Report",
    BUTTON_SAVE:                        "Save",
    BUTTON_COMMIT:                      "Commit",
    BUTTON_INIT:                        "Init",
    BUTTON_CLONE:                       "Clone",
    BUTTON_CHECKOUT_COMMIT:             "Checkout",
    BUTTON_REBASE_CONTINUE:             "Continue rebase",
    BUTTON_REBASE_SKIP:                 "Skip",
    BUTTON_REBASE_ABORT:                "Abort",
    BUTTON_MERGE_ABORT:                 "Abort merge",
    BUTTON_RESET:                       "Reset index",
    BUTTON_RESET_HARD:                  "Reset to this commit and discard the changes that came after it. (reset --hard)",
    BUTTON_RESET_SOFT:                  "Reset to this commit and retain changes that came after it staged for a new commit. (reset --soft)",
    BUTTON_RESET_MIXED:                 "Reset to this commit and retain changes that came after it unstaged. (reset --mixed)",
    CANCEL:                             "Cancel",
    CHANGELOG:                          "Changelog",
    CHANGE_USER_NAME:                   "Change git username",
    CHANGE_USER_EMAIL:                  "Change git email",
    CHECK_GIT_SETTINGS:                 "Check Git settings",
    CODE_INSPECTION_PROBLEMS:           "Code inspection problems:",
    COMMAND_ARGUMENTS:                  "Command arguments",
    COMMIT:                             "Commit",
    COMMIT_ALL_SHORTCUT:                "Commit all files",
    COMMIT_CURRENT_SHORTCUT:            "Commit current file",
    COMMIT_MESSAGE_PLACEHOLDER:         "Enter commit message here\u2026",
    COLORED_AVATAR:                     "Colored avatar",
    CLONE_REPOSITORY:                   "Clone repository",
    CREATE_NEW_BRANCH:                  "Create new branch\u2026",
    CREATE_NEW_REMOTE:                  "Create new remote\u2026",
    CREATE_NEW_GITFTP_SCOPE:            "Create new Git-FTP remote\u2026",
    CUSTOM_TERMINAL_COMMAND:            "Custom terminal command (sample: gnome-terminal or complete path to executable)",
    CUSTOM_TERMINAL_COMMAND_HINT:       "Sample arguments: --window --working-directory=$1
$1 in arguments will be replaced by current project directory.",
    DATE_FORMAT:                        "YYYY-MM-DD HH:mm:ss",
    DATE_MODE_0:                        "Formatted using local date format",
    DATE_MODE_1:                        "Relative time",
    DATE_MODE_2:                        "Intelligent mode (relative/formatted)",
    DATE_MODE_3:                        "Formatted using your own format",
    DATE_MODE_4:                        "Original Git date",
    DEBUG:                              "Debug",
    DEBUG_MODE_SETTING:                 "DEBUG mode — Leave this OFF unless you need to find a problem with the extension. All Git communication will be forwarded to Brackets console!",
    DELETE_FILE:                        "Delete file",
    DELETE_REMOTE:                      "Delete remote",
    DELETE_REMOTE_NAME:                 "Do you really wish to delete remote \"{0}\"?",
    DELETE_LOCAL_BRANCH:                "Delete local branch",
    DELETE_LOCAL_BRANCH_NAME:           "Do you really wish to delete local branch \"{0}\"?",
    TITLE_CHECKOUT:                     "Do you really wish to checkout this commmit?",
    DIALOG_CHECKOUT:                    "When checking out a commit, the repo will go into a DETACHED HEAD state. You can't make any commits unless you create a branch based on this.",
    TITLE_RESET:                        "Do you really wish to reset?",
    DIALOG_RESET_HARD:                  "You will lose all changes after this commit!",
    DIALOG_RESET_MIXED:                 "Changes after this commit will be unstaged.",
    DIALOG_RESET_SOFT:                  "Changes after this commit will be staged for a new commmit.",
    DIALOG_PULL_TITLE:                  "Pull from remote",
    DIFF:                               "Diff",
    DIFF_FAILED_SEE_FILES:              "Git diff failed to provide diff results. This is the list of staged files to be commited:",
    ENTER_PASSWORD:                     "Enter password:",
    ENTER_USERNAME:                     "Enter username:",
    ENTER_REMOTE_GIT_URL:               "Enter Git URL of the repository you want to clone:",
    ENTER_REMOTE_NAME:                  "Enter name of the new remote:",
    ENTER_GITFTP_SCOPE_NAME:            "Enter name of the new Git-FTP remote:",
    ENTER_REMOTE_URL:                   "Enter URL of the new remote:",
    ENTER_GITFTP_SCOPE_URL:             "Enter FTP URL of the new Git-FTP remote specifing username and password:",
    ERROR_TERMINAL_NOT_FOUND:           "Terminal was not found for your OS, you can define a custom Terminal command in the settings",
    ERROR_CONNECT_NODEJS:               "Failed to connect to NodeJS. If you just updated the extension close all instances of Brackets and try starting again.",
    EXTENDED_COMMIT_MESSAGE:            "EXTENDED",
    EXTENSION_WAS_UPDATED_TITLE:        "The extension was updated to {0}",
    ENTER_NEW_USER_NAME:                "Enter username",
    ENTER_NEW_USER_EMAIL:               "Enter email",
    ENABLE_ADVANCED_FEATURES:           "Enable advanced features",
    FEATURES:                           "Features",
    FILE_STAGED:                        "Staged",
    FILE_UNMODIFIED:                    "Unmodified",
    FILE_IGNORED:                       "Ignored",
    FILE_UNTRACKED:                     "Untracked",
    FILE_MODIFIED:                      "Modified",
    FILE_ADDED:                         "New file",
    FILE_DELETED:                       "Deleted",
    FILE_RENAMED:                       "Renamed",
    FILE_COPIED:                        "Copied",
    FILE_UNMERGED:                      "Unmerged",
    FOR_MAC_LINUX_USERS:                "For Mac/Linux users",
    FOR_WINDOWS_USERS:                  "For Windows users",
    GIT_COMMIT:                         "Git commit\u2026",
    GIT_CONFIGURATION:                  "Git configuration",
    GIT_DIFF:                           "Git diff —",
    GIT_IS_IN_PATH:                     "Git can be called from anywhere (is in system path, might not work on Mac)",
    GIT_PULL_RESPONSE:                  "Git Pull response",
    GIT_PUSH_RESPONSE:                  "Git Push response",
    GITFTP_PUSH_RESPONSE:               "Git-FTP Push response",
    GIT_SETTINGS:                       "Git Settings\u2026",
    GIT_REMOTES:                        "Git remotes",
    GITFTP_SCOPES:                      "Git-FTP remotes",
    GOTO_PREVIOUS_GIT_CHANGE:           "Go to previous Git change",
    GOTO_NEXT_GIT_CHANGE:               "Go to next Git change",
    PICTURE:                            "Gravatar (www.avatars.io)",
    HIDE_UNTRACKED:                     "Hide untracked",
    HISTORY:                            "History",
    INIT_GITFTP_SCOPE:                  "Initialize Git-FTP remote",
    INIT_GITFTP_SCOPE_NAME:             "Initialize Git-FTP remote \"{0}\"?",
    IDENTICON:                          "Identicon (www.avatars.io)",
    LAUNCH_BASH_SHORTCUT:               "Bash/Terminal shortcut",
    LOADING:                            "Loading\u2026",
    LINES:                              "Lines",
    _LINES:                             "lines",
    LIST_MODIFIED_FILES:                "Modified files",
    MARK_MODIFIED_FILES_IN_TREE:        "Mark modified files in file tree",
    MERGE_BRANCH:                       "Merge branch",
    MERGE_RESULT:                       "Merge result",
    MERGE_MESSAGE:                      "Merge message",
    NORMALIZE_LINE_ENDINGS:             "Normalize line endings (to \\n)",
    NOTHING_TO_COMMIT:                  "Nothing to commit, working directory clean.",
    OK:                                 "OK",
    OPERATION_IN_PROGRESS_TITLE:        "Git operation in progress\u2026",
    ORIGIN_BRANCH:                      "Origin branch",
    PANEL_COMMAND:                      "Show Git panel",
    PANEL_SHORTCUT:                     "Toggle panel",
    PASSWORDS:                          "Passwords",
    PATH_TO_GIT_EXECUTABLE:             "Path to Git executable",
    PATH_TO_GIT_MSYSGIT:                "Path to msysgit folder",
    PULL_SHORTCUT:                      "Pull from remote repository",
    PUSH_SHORTCUT:                      "Push to remote repository",
    Q_DELETE_FILE:                      "Are you sure you wish to delete the file {0}?",
    Q_RESTART_BRACKETS:                 "Do you wish to restart Brackets to apply new settings?",
    Q_UNDO_CHANGES:                     "Reset changes to file {0}?",
    REBASE_RESULT:                      "Rebase result",
    REMOVE_BOM:                         "Remove BOM from files",
    REMOVE_FROM_GITIGNORE:              "Remove from .gitignore",
    RESTART:                            "Restart",
    RESET_LOCAL_REPO:                   "Discard all changes since last commit",
    RESET_LOCAL_REPO_CONFIRM:           "Do you wish to discard all changes done since last commit? This action can't be reverted.",
    REQ_INTERNET:                       "Requires internet connection",
    SAVE_PASSWORD_QUESTION:             "Save username/password?",
    SET_ORIGIN_URL:                     "Set origin URL",
    SHORTCUTS:                          "Shortcuts",
    SHORTCUTS_HINT:                     "Separate keys with dash, like this: Ctrl-Alt-G
You can use the english key identifiers Ctrl, Cmd (Mac), Alt and Shift.",
    SHOW_BASH_TERMINAL_BUTTON:          "Show Bash/Terminal button in the panel",
    SHOWN_DATE_FORMAT:                  "Format of commit dates in history",
    SHOW_REPORT_BUG_BUTTON:             "Show Report Bug button in the panel",
    SHOW_UNTRACKED:                     "Show untracked",
    STRIP_WHITESPACE_FROM_COMMITS:      "Strip trailing whitespace from commits",
    TARGET_BRANCH:                      "Target branch",
    TOOLTIP_FIND_CONFLICTS:             "Starts a search for Git merge/rebase conflicts in the project",
    TOOLTIP_BUG:                        "Report bug",
    TOOLTIP_OPEN_BASH:                  "Open Bash/Terminal console",
    TOOLTIP_PULL:                       "Git Pull",
    TOOLTIP_PUSH:                       "Git Push",
    TOOLTIP_GITPUSH:                    "Git-FTP Push",
    TOOLTIP_CLOSE_NOT_MODIFIED:         "Close files not modified in Git",
    TOOLTIP_INIT:                       "Initialize repository",
    TOOLTIP_CHECKOUT_COMMIT:            "Checkout a specific commit",
    TOOLTIP_CLONE:                      "Clone existing repository",
    TOOLTIP_COMMIT:                     "Commit the selected files",
    TOOLTIP_REFRESH_PANEL:              "Refresh panel",
    TOOLTIP_HIDE_HISTORY:               "Hide history",
    TOOLTIP_SHOW_HISTORY:               "Show history",
    TOOLTIP_HIDE_FILE_HISTORY:          "Hide file history",
    TOOLTIP_SHOW_FILE_HISTORY:          "Show file history",
    TOOLTIP_PICK_REMOTE:                "Pick preferred remote",
    TOOLTIP_MORE:                       "More actions\u2026",
    TOOLTIP_REBASE_CONTINUE:            "Restart the rebasing process after having resolved a merge conflict",
    TOOLTIP_REBASE_SKIP:                "Restart the rebasing process by skipping the current patch",
    TOOLTIP_REBASE_ABORT:               "Abort the rebase operation and reset HEAD to the original branch",
    TOOLTIP_MERGE_ABORT:                "Abort the merge operation and reset HEAD to the last local commit",
    USER_ABORTED:                       "User aborted!",
    UNDO_CHANGES:                       "Discard changes",
    UNDO_LAST_LOCAL_COMMIT:             "Undo last local (not pushed) commit",
    URL:                                "URL",
    USE_CODE_INSPECTION:                "Use Code inspection",
    USE_GIT_GUTTER:                     "Use Git gutter marks",
    USE_REBASE:                         "Use REBASE",
    USER_DATE_FORMAT:                   "Own date format (Syntax)",
    USE_GITFTP:                         "Use Git-FTP",
    USING_GIT_VERSION:                  "Git version",
    VIEW_AUTHORS_SELECTION:             "View authors of selection",
    VIEW_AUTHORS_FILE:                  "View authors of file"
});
<commit_msg>Fixed avatar provider URL<commit_after>/*jshint maxlen:false */

define({
    ADVANCED_FEATURES_WARNING:          "This features are not recommended for basic Git users as they may cause you to lose code that has been already commited if used inproperly. Use with caution.",
    ADD_ENDLINE_TO_THE_END_OF_FILE:     "Add endline at the end of file",
    ADD_TO_GITIGNORE:                   "Add to .gitignore",
    AGREE_TO_STORE_PASSWORDS:           "I agree that password are stored in plain text on my computer",
    AMEND_COMMIT:                       "Amend last commit",
    AMEND_COMMIT_FORBIDDEN:             "Cannot amend commit when there are no unpushed commits",
    AUTHOR:                             "Author",
    AUTHORS_OF:                         "Authors of",
    AVATAR_TYPE:                        "Avatar type",
    BASH_NOT_AVAILABLE:                 "Bash is not available or properly configured",
    BASIC_CONFIGURATION:                "Basic configuration",
    BRACKETS_GIT_ERROR:                 "Brackets Git encountered an error\u2026",
    BRANCH_NAME:                        "Branch name",
    BUTTON_FIND_CONFLICTS:              "Find conflicts\u2026",
    BLACK_WHITE_AVATAR:                 "Black and white avatar",
    BUTTON_CANCEL:                      "Cancel",
    BUTTON_CHANGELOG:                   "Show changelog",
    BUTTON_CLOSE:                       "Close",
    BUTTON_DEFAULTS:                    "Restore defaults",
    BUTTON_OK:                          "OK",
    BUTTON_REPORT:                      "Report",
    BUTTON_SAVE:                        "Save",
    BUTTON_COMMIT:                      "Commit",
    BUTTON_INIT:                        "Init",
    BUTTON_CLONE:                       "Clone",
    BUTTON_CHECKOUT_COMMIT:             "Checkout",
    BUTTON_REBASE_CONTINUE:             "Continue rebase",
    BUTTON_REBASE_SKIP:                 "Skip",
    BUTTON_REBASE_ABORT:                "Abort",
    BUTTON_MERGE_ABORT:                 "Abort merge",
    BUTTON_RESET:                       "Reset index",
    BUTTON_RESET_HARD:                  "Reset to this commit and discard the changes that came after it. (reset --hard)",
    BUTTON_RESET_SOFT:                  "Reset to this commit and retain changes that came after it staged for a new commit. (reset --soft)",
    BUTTON_RESET_MIXED:                 "Reset to this commit and retain changes that came after it unstaged. (reset --mixed)",
    CANCEL:                             "Cancel",
    CHANGELOG:                          "Changelog",
    CHANGE_USER_NAME:                   "Change git username",
    CHANGE_USER_EMAIL:                  "Change git email",
    CHECK_GIT_SETTINGS:                 "Check Git settings",
    CODE_INSPECTION_PROBLEMS:           "Code inspection problems:",
    COMMAND_ARGUMENTS:                  "Command arguments",
    COMMIT:                             "Commit",
    COMMIT_ALL_SHORTCUT:                "Commit all files",
    COMMIT_CURRENT_SHORTCUT:            "Commit current file",
    COMMIT_MESSAGE_PLACEHOLDER:         "Enter commit message here\u2026",
    COLORED_AVATAR:                     "Colored avatar",
    CLONE_REPOSITORY:                   "Clone repository",
    CREATE_NEW_BRANCH:                  "Create new branch\u2026",
    CREATE_NEW_REMOTE:                  "Create new remote\u2026",
    CREATE_NEW_GITFTP_SCOPE:            "Create new Git-FTP remote\u2026",
    CUSTOM_TERMINAL_COMMAND:            "Custom terminal command (sample: gnome-terminal or complete path to executable)",
    CUSTOM_TERMINAL_COMMAND_HINT:       "Sample arguments: --window --working-directory=$1
$1 in arguments will be replaced by current project directory.",
    DATE_FORMAT:                        "YYYY-MM-DD HH:mm:ss",
    DATE_MODE_0:                        "Formatted using local date format",
    DATE_MODE_1:                        "Relative time",
    DATE_MODE_2:                        "Intelligent mode (relative/formatted)",
    DATE_MODE_3:                        "Formatted using your own format",
    DATE_MODE_4:                        "Original Git date",
    DEBUG:                              "Debug",
    DEBUG_MODE_SETTING:                 "DEBUG mode — Leave this OFF unless you need to find a problem with the extension. All Git communication will be forwarded to Brackets console!",
    DELETE_FILE:                        "Delete file",
    DELETE_REMOTE:                      "Delete remote",
    DELETE_REMOTE_NAME:                 "Do you really wish to delete remote \"{0}\"?",
    DELETE_LOCAL_BRANCH:                "Delete local branch",
    DELETE_LOCAL_BRANCH_NAME:           "Do you really wish to delete local branch \"{0}\"?",
    TITLE_CHECKOUT:                     "Do you really wish to checkout this commmit?",
    DIALOG_CHECKOUT:                    "When checking out a commit, the repo will go into a DETACHED HEAD state. You can't make any commits unless you create a branch based on this.",
    TITLE_RESET:                        "Do you really wish to reset?",
    DIALOG_RESET_HARD:                  "You will lose all changes after this commit!",
    DIALOG_RESET_MIXED:                 "Changes after this commit will be unstaged.",
    DIALOG_RESET_SOFT:                  "Changes after this commit will be staged for a new commmit.",
    DIALOG_PULL_TITLE:                  "Pull from remote",
    DIFF:                               "Diff",
    DIFF_FAILED_SEE_FILES:              "Git diff failed to provide diff results. This is the list of staged files to be commited:",
    ENTER_PASSWORD:                     "Enter password:",
    ENTER_USERNAME:                     "Enter username:",
    ENTER_REMOTE_GIT_URL:               "Enter Git URL of the repository you want to clone:",
    ENTER_REMOTE_NAME:                  "Enter name of the new remote:",
    ENTER_GITFTP_SCOPE_NAME:            "Enter name of the new Git-FTP remote:",
    ENTER_REMOTE_URL:                   "Enter URL of the new remote:",
    ENTER_GITFTP_SCOPE_URL:             "Enter FTP URL of the new Git-FTP remote specifing username and password:",
    ERROR_TERMINAL_NOT_FOUND:           "Terminal was not found for your OS, you can define a custom Terminal command in the settings",
    ERROR_CONNECT_NODEJS:               "Failed to connect to NodeJS. If you just updated the extension close all instances of Brackets and try starting again.",
    EXTENDED_COMMIT_MESSAGE:            "EXTENDED",
    EXTENSION_WAS_UPDATED_TITLE:        "The extension was updated to {0}",
    ENTER_NEW_USER_NAME:                "Enter username",
    ENTER_NEW_USER_EMAIL:               "Enter email",
    ENABLE_ADVANCED_FEATURES:           "Enable advanced features",
    FEATURES:                           "Features",
    FILE_STAGED:                        "Staged",
    FILE_UNMODIFIED:                    "Unmodified",
    FILE_IGNORED:                       "Ignored",
    FILE_UNTRACKED:                     "Untracked",
    FILE_MODIFIED:                      "Modified",
    FILE_ADDED:                         "New file",
    FILE_DELETED:                       "Deleted",
    FILE_RENAMED:                       "Renamed",
    FILE_COPIED:                        "Copied",
    FILE_UNMERGED:                      "Unmerged",
    FOR_MAC_LINUX_USERS:                "For Mac/Linux users",
    FOR_WINDOWS_USERS:                  "For Windows users",
    GIT_COMMIT:                         "Git commit\u2026",
    GIT_CONFIGURATION:                  "Git configuration",
    GIT_DIFF:                           "Git diff —",
    GIT_IS_IN_PATH:                     "Git can be called from anywhere (is in system path, might not work on Mac)",
    GIT_PULL_RESPONSE:                  "Git Pull response",
    GIT_PUSH_RESPONSE:                  "Git Push response",
    GITFTP_PUSH_RESPONSE:               "Git-FTP Push response",
    GIT_SETTINGS:                       "Git Settings\u2026",
    GIT_REMOTES:                        "Git remotes",
    GITFTP_SCOPES:                      "Git-FTP remotes",
    GOTO_PREVIOUS_GIT_CHANGE:           "Go to previous Git change",
    GOTO_NEXT_GIT_CHANGE:               "Go to next Git change",
    PICTURE:                            "Gravatar (www.gravatar.com)",
    HIDE_UNTRACKED:                     "Hide untracked",
    HISTORY:                            "History",
    INIT_GITFTP_SCOPE:                  "Initialize Git-FTP remote",
    INIT_GITFTP_SCOPE_NAME:             "Initialize Git-FTP remote \"{0}\"?",
    IDENTICON:                          "Identicon (www.gravatar.com)",
    LAUNCH_BASH_SHORTCUT:               "Bash/Terminal shortcut",
    LOADING:                            "Loading\u2026",
    LINES:                              "Lines",
    _LINES:                             "lines",
    LIST_MODIFIED_FILES:                "Modified files",
    MARK_MODIFIED_FILES_IN_TREE:        "Mark modified files in file tree",
    MERGE_BRANCH:                       "Merge branch",
    MERGE_RESULT:                       "Merge result",
    MERGE_MESSAGE:                      "Merge message",
    NORMALIZE_LINE_ENDINGS:             "Normalize line endings (to \\n)",
    NOTHING_TO_COMMIT:                  "Nothing to commit, working directory clean.",
    OK:                                 "OK",
    OPERATION_IN_PROGRESS_TITLE:        "Git operation in progress\u2026",
    ORIGIN_BRANCH:                      "Origin branch",
    PANEL_COMMAND:                      "Show Git panel",
    PANEL_SHORTCUT:                     "Toggle panel",
    PASSWORDS:                          "Passwords",
    PATH_TO_GIT_EXECUTABLE:             "Path to Git executable",
    PATH_TO_GIT_MSYSGIT:                "Path to msysgit folder",
    PULL_SHORTCUT:                      "Pull from remote repository",
    PUSH_SHORTCUT:                      "Push to remote repository",
    Q_DELETE_FILE:                      "Are you sure you wish to delete the file {0}?",
    Q_RESTART_BRACKETS:                 "Do you wish to restart Brackets to apply new settings?",
    Q_UNDO_CHANGES:                     "Reset changes to file {0}?",
    REBASE_RESULT:                      "Rebase result",
    REMOVE_BOM:                         "Remove BOM from files",
    REMOVE_FROM_GITIGNORE:              "Remove from .gitignore",
    RESTART:                            "Restart",
    RESET_LOCAL_REPO:                   "Discard all changes since last commit",
    RESET_LOCAL_REPO_CONFIRM:           "Do you wish to discard all changes done since last commit? This action can't be reverted.",
    REQ_INTERNET:                       "Requires internet connection",
    SAVE_PASSWORD_QUESTION:             "Save username/password?",
    SET_ORIGIN_URL:                     "Set origin URL",
    SHORTCUTS:                          "Shortcuts",
    SHORTCUTS_HINT:                     "Separate keys with dash, like this: Ctrl-Alt-G
You can use the english key identifiers Ctrl, Cmd (Mac), Alt and Shift.",
    SHOW_BASH_TERMINAL_BUTTON:          "Show Bash/Terminal button in the panel",
    SHOWN_DATE_FORMAT:                  "Format of commit dates in history",
    SHOW_REPORT_BUG_BUTTON:             "Show Report Bug button in the panel",
    SHOW_UNTRACKED:                     "Show untracked",
    STRIP_WHITESPACE_FROM_COMMITS:      "Strip trailing whitespace from commits",
    TARGET_BRANCH:                      "Target branch",
    TOOLTIP_FIND_CONFLICTS:             "Starts a search for Git merge/rebase conflicts in the project",
    TOOLTIP_BUG:                        "Report bug",
    TOOLTIP_OPEN_BASH:                  "Open Bash/Terminal console",
    TOOLTIP_PULL:                       "Git Pull",
    TOOLTIP_PUSH:                       "Git Push",
    TOOLTIP_GITPUSH:                    "Git-FTP Push",
    TOOLTIP_CLOSE_NOT_MODIFIED:         "Close files not modified in Git",
    TOOLTIP_INIT:                       "Initialize repository",
    TOOLTIP_CHECKOUT_COMMIT:            "Checkout a specific commit",
    TOOLTIP_CLONE:                      "Clone existing repository",
    TOOLTIP_COMMIT:                     "Commit the selected files",
    TOOLTIP_REFRESH_PANEL:              "Refresh panel",
    TOOLTIP_HIDE_HISTORY:               "Hide history",
    TOOLTIP_SHOW_HISTORY:               "Show history",
    TOOLTIP_HIDE_FILE_HISTORY:          "Hide file history",
    TOOLTIP_SHOW_FILE_HISTORY:          "Show file history",
    TOOLTIP_PICK_REMOTE:                "Pick preferred remote",
    TOOLTIP_MORE:                       "More actions\u2026",
    TOOLTIP_REBASE_CONTINUE:            "Restart the rebasing process after having resolved a merge conflict",
    TOOLTIP_REBASE_SKIP:                "Restart the rebasing process by skipping the current patch",
    TOOLTIP_REBASE_ABORT:               "Abort the rebase operation and reset HEAD to the original branch",
    TOOLTIP_MERGE_ABORT:                "Abort the merge operation and reset HEAD to the last local commit",
    USER_ABORTED:                       "User aborted!",
    UNDO_CHANGES:                       "Discard changes",
    UNDO_LAST_LOCAL_COMMIT:             "Undo last local (not pushed) commit",
    URL:                                "URL",
    USE_CODE_INSPECTION:                "Use Code inspection",
    USE_GIT_GUTTER:                     "Use Git gutter marks",
    USE_REBASE:                         "Use REBASE",
    USER_DATE_FORMAT:                   "Own date format (Syntax)",
    USE_GITFTP:                         "Use Git-FTP",
    USING_GIT_VERSION:                  "Git version",
    VIEW_AUTHORS_SELECTION:             "View authors of selection",
    VIEW_AUTHORS_FILE:                  "View authors of file"
});
<|endoftext|>


<commit_before>/**
 * @fileOverview Helps bind and trigger events between views.
 * @author David Huynh
 * @author Ryan Lee
 */

/**
 * @constructor
 * @class
 * @param {Exhibit.UIContext} uiContext
 */
Exhibit.Coordinator = function(uiContext) {
    this._uiContext = uiContext;
    this._listeners = [];
};

/**
 * @static
 * @param {Object} configuration
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.Coordinator}
 */
Exhibit.Coordinator.create = function(configuration, uiContext) {
    return new Exhibit.Coordinator(uiContext);
};

/**
 * @static
 * @param {Element} div
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.Coordinator}
 */
Exhibit.Coordinator.createFromDOM = function(div, uiContext) {
    return new Exhibit.Coordinator(Exhibit.UIContext.createFromDOM(div, uiContext, false));
};

/**
 *
 */
Exhibit.Coordinator.prototype.dispose = function() {
    this._uiContext.dispose();
    this._uiContext = null;
};

/**
 * @param {Function} callback
 * @returns {Exhibit.Coordinator._Listener}
 */
Exhibit.Coordinator.prototype.addListener = function(callback) {
    var listener = new Exhibit.Coordinator._Listener(this, callback);
    this._listeners.push(listener);

    return listener;
};

/**
 * @param {Exhibit.Coordinator._Listener} listener
 */
Exhibit.Coordinator.prototype._removeListener = function(listener) {
    var i;
    for (i = 0; i < this._listeners.length; i++) {
        if (this._listeners[i] === listener) {
            this._listeners.splice(i, 1);
            return;
        }
    }
};

/**
 * @param {Exhibit.Coordinator._Listener} listener
 * @param {Object} o
 */
Exhibit.Coordinator.prototype._fire = function(listener, o) {
    var i, listener2;
    for (i = 0; i < this._listeners.length; i++) {
        listener2 = this._listeners[i];
        if (listener2 !== listener) {
            listener2._callback(o);
        }
    }
};

/**
 * @constructor
 * @class
 * @param {Exhibit.Coordinator} coordinator
 * @param {Function} callback
 */
Exhibit.Coordinator._Listener = function(coordinator, callback) {
    this._coordinator = coordinator;
    this._callback = callback;
};

/**
 */
Exhibit.Coordinator._Listener.prototype.dispose = function() {
    this._coordinator._removeListener(this);
};

/**
 * @param {Object} o
 */
Exhibit.Coordinator._Listener.prototype.fire = function(o) {
    this._coordinator._fire(this, o);
};
<commit_msg>Coordinators weren't registering themselves so didn't work. Fixed.<commit_after>/**
 * @fileOverview Helps bind and trigger events between views.
 * @author David Huynh
 * @author Ryan Lee
 */

/**
 * @constructor
 * @class
 * @param {Exhibit.UIContext} uiContext
 */
Exhibit.Coordinator = function(uiContext, div) {
    this._uiContext = uiContext;
    this._listeners = [];

    /**
     * Returns the programmatic identifier used for this view.
     * @public
     * @returns {String}
     */
    this.getID = function() {
        return _id;
    };

    /**
     * @private
     */
    _setIdentifier = function() {
        if (typeof div !== "undefined") {
            _id = Exhibit.jQuery(div).attr("id");
        }
        if (typeof _id === "undefined" || _id === null) {
            _id = self.getUIContext().getCollection().getID()
                + "-"
                + self.getUIContext().getMain().getRegistry().generateIdentifier(Exhibit.Coordinator.getRegistryKey());
        }
    };

    _setIdentifier();
    /**
     * Enter this view into the registry, making it easier to locate.
     */
    uiContext.getMain().getRegistry().register(
        Exhibit.Coordinator.getRegistryKey(),
        this.getID(),
        this
    );
    this._registered = true;
};

Exhibit.Coordinator._registryKey = "coordinator";
/**
 * @public
 * @static
 * @returns {String}
 */
Exhibit.Coordinator.getRegistryKey = function() {
    return Exhibit.Coordinator._registryKey;
};

Exhibit.Coordinator.registerComponent = function(evt, reg) {
    if (!reg.hasRegistry(Exhibit.Coordinator.getRegistryKey())) {
        reg.createRegistry(Exhibit.Coordinator.getRegistryKey());
    }
};

Exhibit.jQuery(document).one(
    "registerComponents.exhibit",
    Exhibit.Coordinator.registerComponent
);

/**
 * @static
 * @param {Object} configuration
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.Coordinator}
 */
Exhibit.Coordinator.create = function(configuration, uiContext) {
    return new Exhibit.Coordinator(uiContext);
};

/**
 * @static
 * @param {Element} div
 * @param {Exhibit.UIContext} uiContext
 * @returns {Exhibit.Coordinator}
 */
Exhibit.Coordinator.createFromDOM = function(div, uiContext) {
    return new Exhibit.Coordinator(Exhibit.UIContext.createFromDOM(div, uiContext, false), div);
};

/**
 *
 */
Exhibit.Coordinator.prototype.dispose = function() {
    this._uiContext.dispose();
    this._uiContext = null;
};

/**
 * @param {Function} callback
 * @returns {Exhibit.Coordinator._Listener}
 */
Exhibit.Coordinator.prototype.addListener = function(callback) {
    var listener = new Exhibit.Coordinator._Listener(this, callback);
    this._listeners.push(listener);

    return listener;
};

/**
 * @param {Exhibit.Coordinator._Listener} listener
 */
Exhibit.Coordinator.prototype._removeListener = function(listener) {
    var i;
    for (i = 0; i < this._listeners.length; i++) {
        if (this._listeners[i] === listener) {
            this._listeners.splice(i, 1);
            return;
        }
    }
};

/**
 * @param {Exhibit.Coordinator._Listener} listener
 * @param {Object} o
 */
Exhibit.Coordinator.prototype._fire = function(listener, o) {
    var i, listener2;
    for (i = 0; i < this._listeners.length; i++) {
        listener2 = this._listeners[i];
        if (listener2 !== listener) {
            listener2._callback(o);
        }
    }
};

/**
 * @constructor
 * @class
 * @param {Exhibit.Coordinator} coordinator
 * @param {Function} callback
 */
Exhibit.Coordinator._Listener = function(coordinator, callback) {
    this._coordinator = coordinator;
    this._callback = callback;
};

/**
 */
Exhibit.Coordinator._Listener.prototype.dispose = function() {
    this._coordinator._removeListener(this);
};

/**
 * @param {Object} o
 */
Exhibit.Coordinator._Listener.prototype.fire = function(o) {
    this._coordinator._fire(this, o);
};
<|endoftext|>


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