<commit_before>// Copyright (c) 2014 RazorFlow Technologies LLP

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

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

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

var TestHelper = function () {
	var self = this;
	var contextDiv = $("body");
	var oldContext = null;
	var doneFunc = null,
		continuations = [];

	var jqFilter = function (val, all) {
		if(contextDiv == null) {
			self.showError ("Context is null");
		}
		if(val === ".") {
			return contextDiv;
		}
		if(typeof(val) === "string") {
			if(!contextDiv) {
				debugger;
			}
			var contextFound = contextDiv.find(val);
			if(contextFound.length === 0) {
				self.showError("Cannot find selector " + val + " in context");
			}
			if(contextFound.length > 1) {
				log("the number of elements found for ", val, "is ", contextFound.length);
			}
			return all ? contextDiv.find(val) : $(contextDiv.find(val)[0]);
		}
		if(typeof(val) === "object") {
			if(val.length === 0) {
				self.showError("Empty jquery object passed");
			}
			if(val.length > 1) {
				log("the number of elements found for ", val, "is ", contextFound.length);
			}

			return val;
		}

		if(typeof(val) === "function") {
			return val(contextDiv);
		}
		throw "Unexpected type for jquery filter";
	}
	self.start = function (done) {
		log("Starting");
		doneFunc = done;
		contextDiv = $("body");
		continuations = [];

		self.wait(400);

		return self;
	};

	self.setContext = function (context, reset) {
		if(typeof(reset) == "undefined")
		{
			reset = true;
		}
		addSyncContinuation(function () {
			context = funcToValue(context);
			// First, reset the context div to body
			if(reset) {
				contextDiv = $("body");
			}
			contextDiv = jqFilter(context);
		});
		return self;
	};

	self.drillContext = function (context) {
		return self.setContext(context, false);
	};

	self.assertText = function (selector, expected, options) {
		options = options ? options : {};
		addSyncContinuation(function () {
			log("Asserting text is " + expected);
			var item = jqFilter(selector);
			var found = item.text();
			if(options.trim) {
				found = found.trim();
			}

			compareFoundToExpected(found, expected);
		});
		return self;
	};

	self.assert = function (callback) {
		addASyncContinuation(function (done) {
			var onErr = function (message) {
				self.showError(message);
				done();
			};

			callback(contextDiv, done, onErr);
		});
		return self;
	}

	self.assertClass = function (selector, expected, options) {
		options = options ? options : {};
		addSyncContinuation(function () {
			log("Asserting class exists:" + expected);
			var item = jqFilter(selector);
			if(!item.hasClass(expected)) {
				self.showError("Expected "+ selector + " to have class " + expected);
			}
		});
		return self;
	};

	self.count = function (selector, expectedNum, options) {
		options = options ? options : {op: '='};
		addSyncContinuation(function() {
			log('Asserting the number of dom elements found by the selector to be ' + expectedNum);
			var items = jqFilter(selector, true),
				found = items.length;
			compareFoundToExpectedWithOp(found, expectedNum, options.op);
		});
		return self;
	};

	self.svgMeasure = function (selector, attribute, expected, options) {
		options = options ? options : {};
		addSyncContinuation(function () {
			log("Measuring svg");
			var item = jqFilter(selector);

			// Get direct item
			item = item[0];
			if(!item[attribute]) {
				self.showError("Selector " + selector + " has no property " + attribute)
				return;
			}

			var baseVal = item[attribute].baseVal;
			var found;
			if(typeof(baseVal.value) == "number") {
				found = baseVal.value;
			}
			else if (baseVal[0]) {
				found = baseVal[0].value
			}
			else {
				self.showError("Cannot found a baseval");
			}
			compareFoundToExpected(found, expected);
		});

		return self;
	};

	self.svgTriggerEvent = function (selector, eventName) {
		addSyncContinuation(function () {
			log("Triggering event");
			var item = jqFilter(selector);

			// Get direct item
			item = item[0];
			var event; // The custom event that will be created

			if (document.createEvent) {
				event = document.createEvent("HTMLEvents");
				event.initEvent(eventName, true, true);
			} else {
				event = document.createEventObject();
				event.eventType = eventName;
			}

			event.eventName = eventName;

			if (document.createEvent) {
				item.dispatchEvent(event);
			} else {
				item.fireEvent("on" + event.eventType, event);
			}

		});

		return self;
	};

	self.wait = function (timeout) {
		addASyncContinuation(function (done) {
			log("Waiting for " + timeout);
			setTimeout(done, timeout);
		});
		return self;
	};

	self.click = function (selector, data) {
		return self.triggerEvent(selector, "click");
	};

	self.triggerEvent = function (selector, eventName, data) {
		addSyncContinuation(function () {
			log("clicking!!");
			var item = jqFilter(selector);
			item.trigger(eventName);
		});
		return self;
	}

	self.debug = function () {
		addSyncContinuation(function () {
			// console.log("Launching a debugger");
			// console.log("The current div is ", contextDiv)
			// DO NOT REMOVE THIS DEBUGGER. It's actually MEANT to be here.
			debugger;
		});
		return self;
	}

	self.finish = function () {
		runContinuations(continuations);
	};

	self.enterTempContext = function (selector) {
		addSyncContinuation (function () {
			oldContext = contextDiv;
			contextDiv = jqFilter(selector);
		})
		return self;
	};

	self.exitTempContext = function (selector) {
		addSyncContinuation(function () {
			contextDiv = oldContext;
			oldContext = null;
		})
		return self;
	};

	self.assertCSS = function (selector, propName, expected) {
		addSyncContinuation(function () {
			var item = jqFilter(selector);

			if(typeof(propName) == "string") {
				var found = item.css(propName);
				compareFoundToExpected(found, expected);
			}
			else if(typeof(propName) == "object") {
				for(var key in propName) {
					if(propName.hasOwnProperty(key)) {
						var expectedVal = propName[key];
						var found = item.css(key);

						compareFoundToExpected(found, expectedVal);
					}
				}
			}
		});

		return self;
	};

	self.assertAttrs = function (selector, propName, expected) {
		addSyncContinuation(function () {
			var item = jqFilter(selector);

			if(typeof(propName) == "string") {
				var found = item.attr(propName);
				compareFoundToExpected(found, expected);
			}
			else if(typeof(propName) == "object") {
				for(var key in propName) {
					if(propName.hasOwnProperty(key)) {
						var expectedVal = propName[key];
						var found = item.attr(key);

						compareFoundToExpected(found, expectedVal);
					}
				}
			}
		});

		return self;
	};

	self.doSync = function (func) {
		addSyncContinuation(function () {
			func(contextDiv);
		});
		return self;
	};

	self.doASync = function (func) {
		addASyncContinuation(function (done) {
			func(contextDiv, done)
		});
		return self;
	};

	self.assertElementExists = function (selector) {
		addSyncContinuation(function () {
			jqFilter(selector); // This will trigger
		});
	}

	var addSyncContinuation = function (func) {
		continuations.push(function (done) {
			func ();
			done();
		})
	};

	var addASyncContinuation = function (func) {
		continuations.push(function (done) {
			func(done);
		})
	};

	var funcToValue = function (value, found) {
		if(typeof(value) === "function") {
			return value(found);
		}
		else {
			return value;
		}
	};

	var compareFoundToExpected = function (found, expected) {
		if(typeof(expected) === "function") {
			var expectedResult = expected(found, contextDiv)
			if(expectedResult === true) {
				return;
			}
			else {
				if(expected(found, contextDiv, self.showError)) {
					self.showError("Custom check failed");
				}
			}
		}
		else {
			expect(found).toBe(expected);
		}

	};

	var compareFoundToExpectedWithOp = function(found, expected, op) {
		if(typeof(expected) === "function") {
			var expectedResult = expected(found, contextDiv)
			if(expectedResult === true) {
				return;
			}
			else {
				if(expected(found, contextDiv, self.showError)) {
					self.showError("Custom check failed");
				}
			}
		}
		else {
			if(op === '=') {
				expect(found).toEqual(expected);
			} else if(op === '<') {
				expect(found).toBeLessThan(expected);
			} else if(op === '>') {
				expect(found).toBeGreaterThan(expected);
			} else if(op === '~') {
				expected(found).toBeCloseTo(expected);
			}
		}
	}

	var runContinuations = function (cList) {
		if(cList.length == 0) {
			log("done everything");
			doneFunc();
			return;
		}
		var cont = cList.shift();

		cont(function () {
			runContinuations(cList);
		});
	};

	var log = function (msg) {
		if(console) {
			if(console.log) {
				console.log(msg);
			}
		}
	};

	self.showError = function (message) {
		expect("ERROR!!").toBe(message);
	};
};

var t3 = {
	start: function (done) {
		return new TestHelper().start(done);
	},
	between: function (start, end) {
		return function (val, context, showError) {
			if(typeof(val) === "string") {
				val = parseInt(val);
			}
			if(typeof(showError) === "function") {
				showError("Expected " + start + " < " + val + " < " + end + ". But it wasn't so.");
			}

			return (start <= val) && (val <= end);
		}
	},
	approximate: function (point, tolerance) {
		return t3.between(point - tolerance, point + tolerance);
	}
};

window.t3 = t3;
window.TestHelper = TestHelper;<commit_msg>fixed the safari and ie bug<commit_after>// Copyright (c) 2014 RazorFlow Technologies LLP

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

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

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

var TestHelper = function () {
	var self = this;
	var contextDiv = $("body");
	var oldContext = null;
	var doneFunc = null,
		continuations = [];

	var jqFilter = function (val, all) {
		if(contextDiv == null) {
			self.showError ("Context is null");
		}
		if(val === ".") {
			return contextDiv;
		}
		if(typeof(val) === "string") {
			if(!contextDiv) {
				debugger;
			}
			var contextFound = contextDiv.find(val);
			if(contextFound.length === 0) {
				self.showError("Cannot find selector " + val + " in context");
			}
			if(contextFound.length > 1) {
				log("the number of elements found for ", val, "is ", contextFound.length);
			}
			return all ? contextDiv.find(val) : $(contextDiv.find(val)[0]);
		}
		if(typeof(val) === "object") {
			if(val.length === 0) {
				self.showError("Empty jquery object passed");
			}
			if(val.length > 1) {
				log("the number of elements found for ", val, "is ", contextFound.length);
			}

			return val;
		}

		if(typeof(val) === "function") {
			return val(contextDiv);
		}
		throw "Unexpected type for jquery filter";
	}
	self.start = function (done) {
		log("Starting");
		doneFunc = done;
		contextDiv = $("body");
		continuations = [];

		self.wait(400);

		return self;
	};

	self.setContext = function (context, reset) {
		if(typeof(reset) == "undefined")
		{
			reset = true;
		}
		addSyncContinuation(function () {
			context = funcToValue(context);
			// First, reset the context div to body
			if(reset) {
				contextDiv = $("body");
			}
			contextDiv = jqFilter(context);
		});
		return self;
	};

	self.drillContext = function (context) {
		return self.setContext(context, false);
	};

	self.assertText = function (selector, expected, options) {
		options = options ? options : {};
		addSyncContinuation(function () {
			log("Asserting text is " + expected);
			var item = jqFilter(selector);
			var found = item.text();
			if(options.trim) {
				found = found.trim();
			}

			compareFoundToExpected(found, expected);
		});
		return self;
	};

	self.assert = function (callback) {
		addASyncContinuation(function (done) {
			var onErr = function (message) {
				self.showError(message);
				done();
			};

			callback(contextDiv, done, onErr);
		});
		return self;
	}

	self.assertClass = function (selector, expected, options) {
		options = options ? options : {};
		addSyncContinuation(function () {
			log("Asserting class exists:" + expected);
			var item = jqFilter(selector);
			if(!item.hasClass(expected)) {
				self.showError("Expected "+ selector + " to have class " + expected);
			}
		});
		return self;
	};

	self.count = function (selector, expectedNum, options) {
		options = options ? options : {op: '='};
		addSyncContinuation(function() {
			log('Asserting the number of dom elements found by the selector to be ' + expectedNum);
			var items = jqFilter(selector, true),
				found = items.length;
			compareFoundToExpectedWithOp(found, expectedNum, options.op);
		});
		return self;
	};

	self.svgMeasure = function (selector, attribute, expected, options) {
		options = options ? options : {};
		addSyncContinuation(function () {
			log("Measuring svg");
			var item = jqFilter(selector);

			// Get direct item
			item = item[0];
			if(!item[attribute]) {
				self.showError("Selector " + selector + " has no property " + attribute)
				return;
			}

			var baseVal = item[attribute].baseVal;
			var found;
			if(typeof(baseVal.value) == "number") {
				found = baseVal.value;
			}
			else if (baseVal[0]) {
				found = baseVal[0].value
			}
			else if (item.getAttribute(attribute) !== null) { // for Safari and ie
				found = +item.getAttribute(attribute);
			}
			else {
				self.showError("Cannot found a baseval");
			}
			compareFoundToExpected(found, expected);
		});

		return self;
	};

	self.svgTriggerEvent = function (selector, eventName) {
		addSyncContinuation(function () {
			log("Triggering event");
			var item = jqFilter(selector);

			// Get direct item
			item = item[0];
			var event; // The custom event that will be created

			if (document.createEvent) {
				event = document.createEvent("HTMLEvents");
				event.initEvent(eventName, true, true);
			} else {
				event = document.createEventObject();
				event.eventType = eventName;
			}

			event.eventName = eventName;

			if (document.createEvent) {
				item.dispatchEvent(event);
			} else {
				item.fireEvent("on" + event.eventType, event);
			}

		});

		return self;
	};

	self.wait = function (timeout) {
		addASyncContinuation(function (done) {
			log("Waiting for " + timeout);
			setTimeout(done, timeout);
		});
		return self;
	};

	self.click = function (selector, data) {
		return self.triggerEvent(selector, "click");
	};

	self.triggerEvent = function (selector, eventName, data) {
		addSyncContinuation(function () {
			log("clicking!!");
			var item = jqFilter(selector);
			item.trigger(eventName);
		});
		return self;
	}

	self.debug = function () {
		addSyncContinuation(function () {
			// console.log("Launching a debugger");
			// console.log("The current div is ", contextDiv)
			// DO NOT REMOVE THIS DEBUGGER. It's actually MEANT to be here.
			debugger;
		});
		return self;
	}

	self.finish = function () {
		runContinuations(continuations);
	};

	self.enterTempContext = function (selector) {
		addSyncContinuation (function () {
			oldContext = contextDiv;
			contextDiv = jqFilter(selector);
		})
		return self;
	};

	self.exitTempContext = function (selector) {
		addSyncContinuation(function () {
			contextDiv = oldContext;
			oldContext = null;
		})
		return self;
	};

	self.assertCSS = function (selector, propName, expected) {
		addSyncContinuation(function () {
			var item = jqFilter(selector);

			if(typeof(propName) == "string") {
				var found = item.css(propName);
				compareFoundToExpected(found, expected);
			}
			else if(typeof(propName) == "object") {
				for(var key in propName) {
					if(propName.hasOwnProperty(key)) {
						var expectedVal = propName[key];
						var found = item.css(key);

						compareFoundToExpected(found, expectedVal);
					}
				}
			}
		});

		return self;
	};

	self.assertAttrs = function (selector, propName, expected) {
		addSyncContinuation(function () {
			var item = jqFilter(selector);

			if(typeof(propName) == "string") {
				var found = item.attr(propName);
				compareFoundToExpected(found, expected);
			}
			else if(typeof(propName) == "object") {
				for(var key in propName) {
					if(propName.hasOwnProperty(key)) {
						var expectedVal = propName[key];
						var found = item.attr(key);

						compareFoundToExpected(found, expectedVal);
					}
				}
			}
		});

		return self;
	};

	self.doSync = function (func) {
		addSyncContinuation(function () {
			func(contextDiv);
		});
		return self;
	};

	self.doASync = function (func) {
		addASyncContinuation(function (done) {
			func(contextDiv, done)
		});
		return self;
	};

	self.assertElementExists = function (selector) {
		addSyncContinuation(function () {
			jqFilter(selector); // This will trigger
		});
	}

	var addSyncContinuation = function (func) {
		continuations.push(function (done) {
			func ();
			done();
		})
	};

	var addASyncContinuation = function (func) {
		continuations.push(function (done) {
			func(done);
		})
	};

	var funcToValue = function (value, found) {
		if(typeof(value) === "function") {
			return value(found);
		}
		else {
			return value;
		}
	};

	var compareFoundToExpected = function (found, expected) {
		if(typeof(expected) === "function") {
			var expectedResult = expected(found, contextDiv)
			if(expectedResult === true) {
				return;
			}
			else {
				if(expected(found, contextDiv, self.showError)) {
					self.showError("Custom check failed");
				}
			}
		}
		else {
			expect(found).toBe(expected);
		}

	};

	var compareFoundToExpectedWithOp = function(found, expected, op) {
		if(typeof(expected) === "function") {
			var expectedResult = expected(found, contextDiv)
			if(expectedResult === true) {
				return;
			}
			else {
				if(expected(found, contextDiv, self.showError)) {
					self.showError("Custom check failed");
				}
			}
		}
		else {
			if(op === '=') {
				expect(found).toEqual(expected);
			} else if(op === '<') {
				expect(found).toBeLessThan(expected);
			} else if(op === '>') {
				expect(found).toBeGreaterThan(expected);
			} else if(op === '~') {
				expected(found).toBeCloseTo(expected);
			}
		}
	}

	var runContinuations = function (cList) {
		if(cList.length == 0) {
			log("done everything");
			doneFunc();
			return;
		}
		var cont = cList.shift();

		cont(function () {
			runContinuations(cList);
		});
	};

	var log = function (msg) {
		if(console) {
			if(console.log) {
				console.log(msg);
			}
		}
	};

	self.showError = function (message) {
		expect("ERROR!!").toBe(message);
	};
};

var t3 = {
	start: function (done) {
		return new TestHelper().start(done);
	},
	between: function (start, end) {
		return function (val, context, showError) {
			if(typeof(val) === "string") {
				val = parseInt(val);
			}
			if(typeof(showError) === "function") {
				showError("Expected " + start + " < " + val + " < " + end + ". But it wasn't so.");
			}

			return (start <= val) && (val <= end);
		}
	},
	approximate: function (point, tolerance) {
		return t3.between(point - tolerance, point + tolerance);
	}
};

window.t3 = t3;
window.TestHelper = TestHelper;<|endoftext|>


<commit_before>function serialize_object(form_selector) {
    var formdata = $(form_selector).serializeArray();
    var data = {};
    _.each(formdata, function(element){
    // Return all of the values of the object's properties.
      var value = _.values(element);
    // name : value
      data[value[0]] = value[1];
    });
    return data;
}
function validate_item(json) {
    return _.every(_.values(json));
}

$(function() {
    var Item = Backbone.Model.extend({
        idAttribute: '_id',
        urlRoot: "",
        schema: {
            item_id: 'Text',
            buy_buyout: 'Text',
            buy_amount: 'Text',
            buy_additive: 'Text',

            sell_min_buyout: 'Text',
            sell_max_buyout: 'Text',
            sell_run_time: 'Text',
            sell_stack_size: 'Text',
            sell_ignore_stacks_below: 'Text',
            sell_amount: 'Text',
            sell_bid_percent: 'Text',
            sell_undercut_percent: 'Text'
        },
        validate: function(attrs, options) {
            //console.log(attrs);
            //console.log("validating b.addi: "+attrs.buy_additive);
            //console.log("validating b.addi: "+attrs.buy_additive);
        }
    });
    var Items = Backbone.Collection.extend({
        model: Item,
        url: ""
    });
    var ItemInfoView = Backbone.Marionette.ItemView.extend({
        initialize: function() {
            this.listenTo(this.model, 'destroy', this.remove);
        },
        template: "#item_info_template",
        tagName: "div",
        events: {
            'click button#btn_delete': 'delete_item',
        },
        delete_item: function(e) {
            this.model.destroy();
        }
    });
    var ItemsView = Backbone.Marionette.CompositeView.extend({
        tagName: "div",
        id: 'item_accordion',
        className: 'panel-group wat',
        attributes: {
            'role': 'tablist',
            'aria-multiselectable': 'true'
        },
        childView: ItemInfoView,
        template: "#item_data_template",
    });
    var CreateItemView = Backbone.Marionette.ItemView.extend({
        initialize: function(starting_items) {},
        template: "#item_add_template",
        tagName: "div",
        events: {
            'click button#add_item_submit': 'add_item'
        },
        validate_item: function(item) {

            return true;
        },
        add_item: function(e) {
            var form_data = serialize_object('form#item_add_form');

            if(form_data.buy_additive === 'on') {
                form_data.buy_additive = "True";
            } else {
                form_data.buy_additive = "False";
            }

            var cur_item = new Item(form_data);
            cur_item.isValid();
            if(this.validate_item(cur_item)) {
                items.push(cur_item);
            }
            e.preventDefault();
        }
    });

    var items = new Items([{
        item_id: 'item_id',
        buy_buyout: 'buy_buyout',
        buy_amount: 'buy_amount',
        buy_additive: 'True',

        sell_min_buyout: 'sell_min_buyout',
        sell_max_buyout: 'sell_max_buyout',
        sell_run_time: 'sell_run_time',
        sell_stack_size: 'sell_stack_size',
        sell_ignore_stacks_below: 'sell_ignore_stacks_below',
        sell_amount: 'sell_amount',
        sell_bid_percent: 'sell_bid_percent',
        sell_undercut_percent: 'sell_undercut_percent'
    }]);
    var MyApp = new Backbone.Marionette.Application();
    MyApp.addRegions({
      item_list: "#item_list_anchor",
      item_add_form: '#item_add_form_anchor'
    });

    MyApp.addInitializer(function(options){
      var itemsView = new ItemsView({
        collection: options.items
      });
      MyApp.item_list.show(itemsView);

      var createView = new CreateItemView();
      MyApp.item_add_form.show(createView);
    });

    MyApp.start({items: items});
});

/*
var base_template_info;
    $.ajax({
        url: 'static/base_template.js',
        method: 'GET',
        contentType: 'text',
        mimeType: 'text/plain; charset=x-user-defined',
        success: function (data) {
            base_template_info = data;
        }
    });

//*/
<commit_msg>removed unused per-item validate()<commit_after>function serialize_object(form_selector) {
    var formdata = $(form_selector).serializeArray();
    var data = {};
    _.each(formdata, function(element){
    // Return all of the values of the object's properties.
      var value = _.values(element);
    // name : value
      data[value[0]] = value[1];
    });
    return data;
}
function validate_item(json) {
    return _.every(_.values(json));
}

$(function() {
    var Item = Backbone.Model.extend({
        idAttribute: '_id',
        urlRoot: "",
        schema: {
            item_id: 'Text',
            buy_buyout: 'Text',
            buy_amount: 'Text',
            buy_additive: 'Text',

            sell_min_buyout: 'Text',
            sell_max_buyout: 'Text',
            sell_run_time: 'Text',
            sell_stack_size: 'Text',
            sell_ignore_stacks_below: 'Text',
            sell_amount: 'Text',
            sell_bid_percent: 'Text',
            sell_undercut_percent: 'Text'
        }
    });
    var Items = Backbone.Collection.extend({
        model: Item,
        url: ""
    });
    var ItemInfoView = Backbone.Marionette.ItemView.extend({
        initialize: function() {
            this.listenTo(this.model, 'destroy', this.remove);
        },
        template: "#item_info_template",
        tagName: "div",
        events: {
            'click button#btn_delete': 'delete_item',
        },
        delete_item: function(e) {
            this.model.destroy();
        }
    });
    var ItemsView = Backbone.Marionette.CompositeView.extend({
        tagName: "div",
        id: 'item_accordion',
        className: 'panel-group wat',
        attributes: {
            'role': 'tablist',
            'aria-multiselectable': 'true'
        },
        childView: ItemInfoView,
        template: "#item_data_template",
    });
    var CreateItemView = Backbone.Marionette.ItemView.extend({
        initialize: function(starting_items) {},
        template: "#item_add_template",
        tagName: "div",
        events: {
            'click button#add_item_submit': 'add_item'
        },
        validate_item: function(item) {

            return true;
        },
        add_item: function(e) {
            var form_data = serialize_object('form#item_add_form');

            if(form_data.buy_additive === 'on') {
                form_data.buy_additive = "True";
            } else {
                form_data.buy_additive = "False";
            }

            var cur_item = new Item(form_data);
            cur_item.isValid();
            if(this.validate_item(cur_item)) {
                items.push(cur_item);
            }
            e.preventDefault();
        }
    });

    var items = new Items([{
        item_id: 'item_id',
        buy_buyout: 'buy_buyout',
        buy_amount: 'buy_amount',
        buy_additive: 'True',

        sell_min_buyout: 'sell_min_buyout',
        sell_max_buyout: 'sell_max_buyout',
        sell_run_time: 'sell_run_time',
        sell_stack_size: 'sell_stack_size',
        sell_ignore_stacks_below: 'sell_ignore_stacks_below',
        sell_amount: 'sell_amount',
        sell_bid_percent: 'sell_bid_percent',
        sell_undercut_percent: 'sell_undercut_percent'
    }]);
    var MyApp = new Backbone.Marionette.Application();
    MyApp.addRegions({
      item_list: "#item_list_anchor",
      item_add_form: '#item_add_form_anchor'
    });

    MyApp.addInitializer(function(options){
      var itemsView = new ItemsView({
        collection: options.items
      });
      MyApp.item_list.show(itemsView);

      var createView = new CreateItemView();
      MyApp.item_add_form.show(createView);
    });

    MyApp.start({items: items});
});

/*
var base_template_info;
    $.ajax({
        url: 'static/base_template.js',
        method: 'GET',
        contentType: 'text',
        mimeType: 'text/plain; charset=x-user-defined',
        success: function (data) {
            base_template_info = data;
        }
    });

//*/
<|endoftext|>


<commit_before>  /*Application global vars*/
  var year            = 2003;
  var compare         = 'paro';
  var state           = "mapa";
  var global_url      = "http://ec2-50-16-13-57.compute-1.amazonaws.com/data";
  var tiles_version   = 0;
  var bubbles_version = 0;
  var graph_version   = 0;

  $(document).ready(function(){
    //Deep linking manage
    var route = window.location.hash.replace('#','').split('/');
    goToHash(route);
  });

  function initializeApp() {
    initializeGraph();       //initialize graph
    initializeHeader();      //initialize header options (selects and more) and graph/map menu
    initializeMap();         //initialize map and map modules
    initializeKeyBindings();
  }

  function initializeKeyBindings() {
    $(document).keyup(function(e) {
      if (e.keyCode == 27) {
        if (state == "grafico") {
          graphBubbleInfowindow.hide();
        } else {
          infowindow.hide();
        }
      }
    });
  }

  function goToHash(route) {
    //Check variable application state
    if (route[0]!="mapa" && route[0]!="grafico") {
      initializeApp();
      return false;
    }

    // //Check variable of compare
    if (!$('div.option_list ul li a.'+route[5]).length) {
      initializeApp();
      return false;
    }

    // Check length of the array
    if (route.length!=8) {
      initializeApp();
      return false;
    }

    // Check provincia-autonomia-municipio
    if (route[6]!="autonomias" && route[6]!="municipios" && route[6]!="provincias") {
      initializeApp();
      return false;
    }

    //check 1-num 2-num 3-num 4-year 5-string
    if (isNaN(route[1]) || isNaN(route[2]) || isNaN(route[3]) || isNaN(route[4]) || route[4].length!=4 || !isNaN(route[5])) {
      initializeApp();
      return false;
    }

    // Check zoom
    if (route[3]>12 || route[3]<6) {
      initializeApp();
      return false;
    }

    //All ok - change variables!
    start_center = new google.maps.LatLng(parseFloat(route[1]),parseFloat(route[2]));
    start_zoom = parseInt(route[3]);
    year = parseInt(route[4]);
    state = route[0];
    $("div.year_slider").slider("value",year);
    compare = route[5];
    deep = route[6];
    name = route[7];
    var value = $('div.option_list ul li a.'+compare).text();
    // Remove selected variable
    $('div.option_list ul li.selected').each(function(i,ele){$(ele).removeClass('selected');});
    $('div.select').each(function(i,ele){$(ele).removeClass('selected');});
    $('div.select span.inner_select a').each(function(i,ele){var text = $(ele).attr('title'); $(ele).text(text);});
    // Add new selected variable
    $('div.option_list ul li a.'+route[5]).closest('li').addClass('selected');
    $('div.option_list ul li a.'+route[5]).closest('div.select').addClass('selected');
    $('div.option_list ul li a.'+route[5]).closest('div.select').find('span.inner_select a').text(value);

    initializeApp();
  }

  function changeHash() {
    var latlng = peninsula.getCenter();
    var zoom = peninsula.getZoom();
    window.location.hash = "#"+ state + "/" + latlng.lat().toFixed(3)+"/"+latlng.lng().toFixed(3)+"/"+zoom+"/"+year+"/"+compare+"/"+deep+"/"+name;
  }
<commit_msg>added versioning for the gmaps too<commit_after>  /*Application global vars*/
  var year            = 2003;
  var compare         = 'paro';
  var state           = "mapa";
  var global_url      = "http://ec2-50-16-13-57.compute-1.amazonaws.com/data";
  var tiles_version   = 0;
  var bubbles_version = 3;
  var gmaps_version   = 1;
  var graph_version   = 0;

  $(document).ready(function(){
    //Deep linking manage
    var route = window.location.hash.replace('#','').split('/');
    goToHash(route);
  });

  function initializeApp() {
    initializeGraph();       //initialize graph
    initializeHeader();      //initialize header options (selects and more) and graph/map menu
    initializeMap();         //initialize map and map modules
    initializeKeyBindings();
  }

  function initializeKeyBindings() {
    $(document).keyup(function(e) {
      if (e.keyCode == 27) {
        if (state == "grafico") {
          graphBubbleInfowindow.hide();
        } else {
          infowindow.hide();
        }
      }
    });
  }

  function goToHash(route) {
    //Check variable application state
    if (route[0]!="mapa" && route[0]!="grafico") {
      initializeApp();
      return false;
    }

    // //Check variable of compare
    if (!$('div.option_list ul li a.'+route[5]).length) {
      initializeApp();
      return false;
    }

    // Check length of the array
    if (route.length!=8) {
      initializeApp();
      return false;
    }

    // Check provincia-autonomia-municipio
    if (route[6]!="autonomias" && route[6]!="municipios" && route[6]!="provincias") {
      initializeApp();
      return false;
    }

    //check 1-num 2-num 3-num 4-year 5-string
    if (isNaN(route[1]) || isNaN(route[2]) || isNaN(route[3]) || isNaN(route[4]) || route[4].length!=4 || !isNaN(route[5])) {
      initializeApp();
      return false;
    }

    // Check zoom
    if (route[3]>12 || route[3]<6) {
      initializeApp();
      return false;
    }

    //All ok - change variables!
    start_center = new google.maps.LatLng(parseFloat(route[1]),parseFloat(route[2]));
    start_zoom = parseInt(route[3]);
    year = parseInt(route[4]);
    state = route[0];
    $("div.year_slider").slider("value",year);
    compare = route[5];
    deep = route[6];
    name = route[7];
    var value = $('div.option_list ul li a.'+compare).text();
    // Remove selected variable
    $('div.option_list ul li.selected').each(function(i,ele){$(ele).removeClass('selected');});
    $('div.select').each(function(i,ele){$(ele).removeClass('selected');});
    $('div.select span.inner_select a').each(function(i,ele){var text = $(ele).attr('title'); $(ele).text(text);});
    // Add new selected variable
    $('div.option_list ul li a.'+route[5]).closest('li').addClass('selected');
    $('div.option_list ul li a.'+route[5]).closest('div.select').addClass('selected');
    $('div.option_list ul li a.'+route[5]).closest('div.select').find('span.inner_select a').text(value);

    initializeApp();
  }

  function changeHash() {
    var latlng = peninsula.getCenter();
    var zoom = peninsula.getZoom();
    window.location.hash = "#"+ state + "/" + latlng.lat().toFixed(3)+"/"+latlng.lng().toFixed(3)+"/"+zoom+"/"+year+"/"+compare+"/"+deep+"/"+name;
  }
<|endoftext|>


<commit_before>/** @flow */
import { PropTypes, PureComponent } from 'react'
import createCallbackMemoizer from '../utils/createCallbackMemoizer'

/**
 * Higher-order component that manages lazy-loading for "infinite" data.
 * This component decorates a virtual component and just-in-time prefetches rows as a user scrolls.
 * It is intended as a convenience component; fork it if you'd like finer-grained control over data-loading.
 */
export default class InfiniteLoader extends PureComponent {
  static propTypes = {
    /**
     * Function responsible for rendering a virtualized component.
     * This function should implement the following signature:
     * ({ onRowsRendered, registerChild }) => PropTypes.element
     *
     * The specified :onRowsRendered function should be passed through to the child's :onRowsRendered property.
     * The :registerChild callback should be set as the virtualized component's :ref.
     */
    children: PropTypes.func.isRequired,

    /**
     * Function responsible for tracking the loaded state of each row.
     * It should implement the following signature: ({ index: number }): boolean
     */
    isRowLoaded: PropTypes.func.isRequired,

    /**
     * Callback to be invoked when more rows must be loaded.
     * It should implement the following signature: ({ startIndex, stopIndex }): Promise
     * The returned Promise should be resolved once row data has finished loading.
     * It will be used to determine when to refresh the list with the newly-loaded data.
     * This callback may be called multiple times in reaction to a single scroll event.
     */
    loadMoreRows: PropTypes.func.isRequired,

    /**
     * Minimum number of rows to be loaded at a time.
     * This property can be used to batch requests to reduce HTTP requests.
     */
    minimumBatchSize: PropTypes.number.isRequired,

    /**
     * Number of rows in list; can be arbitrary high number if actual number is unknown.
     */
    rowCount: PropTypes.number.isRequired,

    /**
     * Threshold at which to pre-fetch data.
     * A threshold X means that data will start loading when a user scrolls within X rows.
     * This value defaults to 15.
     */
    threshold: PropTypes.number.isRequired
  };

  static defaultProps = {
    minimumBatchSize: 10,
    rowCount: 0,
    threshold: 15
  };

  constructor (props, context) {
    super(props, context)

    this._loadMoreRowsMemoizer = createCallbackMemoizer()

    this._onRowsRendered = this._onRowsRendered.bind(this)
    this._registerChild = this._registerChild.bind(this)
  }

  resetLoadMoreRowsCache() {
    this._loadMoreRowsMemoizer = createCallbackMemoizer()
  }

  render () {
    const { children } = this.props

    return children({
      onRowsRendered: this._onRowsRendered,
      registerChild: this._registerChild
    })
  }

  _loadUnloadedRanges (unloadedRanges) {
    const { loadMoreRows } = this.props

    unloadedRanges.forEach(unloadedRange => {
      let promise = loadMoreRows(unloadedRange)
      if (promise) {
        promise.then(() => {
          // Refresh the visible rows if any of them have just been loaded.
          // Otherwise they will remain in their unloaded visual state.
          if (
            isRangeVisible({
              lastRenderedStartIndex: this._lastRenderedStartIndex,
              lastRenderedStopIndex: this._lastRenderedStopIndex,
              startIndex: unloadedRange.startIndex,
              stopIndex: unloadedRange.stopIndex
            })
          ) {
            if (this._registeredChild) {
              forceUpdateReactVirtualizedComponent(this._registeredChild)
            }
          }
        })
      }
    })
  }

  _onRowsRendered ({ startIndex, stopIndex }) {
    const { isRowLoaded, minimumBatchSize, rowCount, threshold } = this.props

    this._lastRenderedStartIndex = startIndex
    this._lastRenderedStopIndex = stopIndex

    const unloadedRanges = scanForUnloadedRanges({
      isRowLoaded,
      minimumBatchSize,
      rowCount,
      startIndex: Math.max(0, startIndex - threshold),
      stopIndex: Math.min(rowCount - 1, stopIndex + threshold)
    })

    // For memoize comparison
    const squashedUnloadedRanges = unloadedRanges.reduce(
      (reduced, unloadedRange) => reduced.concat([unloadedRange.startIndex, unloadedRange.stopIndex]),
      []
    )

    this._loadMoreRowsMemoizer({
      callback: () => {
        this._loadUnloadedRanges(unloadedRanges)
      },
      indices: { squashedUnloadedRanges }
    })
  }

  _registerChild (registeredChild) {
    this._registeredChild = registeredChild
  }
}

/**
 * Determines if the specified start/stop range is visible based on the most recently rendered range.
 */
export function isRangeVisible ({
  lastRenderedStartIndex,
  lastRenderedStopIndex,
  startIndex,
  stopIndex
}) {
  return !(startIndex > lastRenderedStopIndex || stopIndex < lastRenderedStartIndex)
}

/**
 * Returns all of the ranges within a larger range that contain unloaded rows.
 */
export function scanForUnloadedRanges ({
  isRowLoaded,
  minimumBatchSize,
  rowCount,
  startIndex,
  stopIndex
}) {
  const unloadedRanges = []

  let rangeStartIndex = null
  let rangeStopIndex = null

  for (let index = startIndex; index <= stopIndex; index++) {
    let loaded = isRowLoaded({ index })

    if (!loaded) {
      rangeStopIndex = index
      if (rangeStartIndex === null) {
        rangeStartIndex = index
      }
    } else if (rangeStopIndex !== null) {
      unloadedRanges.push({
        startIndex: rangeStartIndex,
        stopIndex: rangeStopIndex
      })

      rangeStartIndex = rangeStopIndex = null
    }
  }

  // If :rangeStopIndex is not null it means we haven't ran out of unloaded rows.
  // Scan forward to try filling our :minimumBatchSize.
  if (rangeStopIndex !== null) {
    const potentialStopIndex = Math.min(
      Math.max(
        rangeStopIndex,
        rangeStartIndex + minimumBatchSize - 1
      ),
      rowCount - 1
    )

    for (let index = rangeStopIndex + 1; index <= potentialStopIndex; index++) {
      if (!isRowLoaded({ index })) {
        rangeStopIndex = index
      } else {
        break
      }
    }

    unloadedRanges.push({
      startIndex: rangeStartIndex,
      stopIndex: rangeStopIndex
    })
  }

  // Check to see if our first range ended prematurely.
  // In this case we should scan backwards to try filling our :minimumBatchSize.
  if (unloadedRanges.length) {
    const firstUnloadedRange = unloadedRanges[0]

    while (
      firstUnloadedRange.stopIndex - firstUnloadedRange.startIndex + 1 < minimumBatchSize &&
      firstUnloadedRange.startIndex > 0
    ) {
      let index = firstUnloadedRange.startIndex - 1

      if (!isRowLoaded({ index })) {
        firstUnloadedRange.startIndex = index
      } else {
        break
      }
    }
  }

  return unloadedRanges
}

/**
 * Since RV components use shallowCompare we need to force a render (even though props haven't changed).
 * However InfiniteLoader may wrap a Grid or it may wrap a Table or List.
 * In the first case the built-in React forceUpdate() method is sufficient to force a re-render,
 * But in the latter cases we need to use the RV-specific forceUpdateGrid() method.
 * Else the inner Grid will not be re-rendered and visuals may be stale.
 *
 * Additionally, while a Grid is scrolling the cells can be cached,
 * So it's important to invalidate that cache by recalculating sizes
 * before forcing a rerender.
 */
export function forceUpdateReactVirtualizedComponent (component) {
  const recomputeSize = typeof component.recomputeGridSize === 'function'
    ? component.recomputeGridSize
    : component.recomputeRowHeights

  if (recomputeSize) {
    recomputeSize.call(component)
  } else {
    component.forceUpdate()
  }
}
<commit_msg>Lint fix<commit_after>/** @flow */
import { PropTypes, PureComponent } from 'react'
import createCallbackMemoizer from '../utils/createCallbackMemoizer'

/**
 * Higher-order component that manages lazy-loading for "infinite" data.
 * This component decorates a virtual component and just-in-time prefetches rows as a user scrolls.
 * It is intended as a convenience component; fork it if you'd like finer-grained control over data-loading.
 */
export default class InfiniteLoader extends PureComponent {
  static propTypes = {
    /**
     * Function responsible for rendering a virtualized component.
     * This function should implement the following signature:
     * ({ onRowsRendered, registerChild }) => PropTypes.element
     *
     * The specified :onRowsRendered function should be passed through to the child's :onRowsRendered property.
     * The :registerChild callback should be set as the virtualized component's :ref.
     */
    children: PropTypes.func.isRequired,

    /**
     * Function responsible for tracking the loaded state of each row.
     * It should implement the following signature: ({ index: number }): boolean
     */
    isRowLoaded: PropTypes.func.isRequired,

    /**
     * Callback to be invoked when more rows must be loaded.
     * It should implement the following signature: ({ startIndex, stopIndex }): Promise
     * The returned Promise should be resolved once row data has finished loading.
     * It will be used to determine when to refresh the list with the newly-loaded data.
     * This callback may be called multiple times in reaction to a single scroll event.
     */
    loadMoreRows: PropTypes.func.isRequired,

    /**
     * Minimum number of rows to be loaded at a time.
     * This property can be used to batch requests to reduce HTTP requests.
     */
    minimumBatchSize: PropTypes.number.isRequired,

    /**
     * Number of rows in list; can be arbitrary high number if actual number is unknown.
     */
    rowCount: PropTypes.number.isRequired,

    /**
     * Threshold at which to pre-fetch data.
     * A threshold X means that data will start loading when a user scrolls within X rows.
     * This value defaults to 15.
     */
    threshold: PropTypes.number.isRequired
  };

  static defaultProps = {
    minimumBatchSize: 10,
    rowCount: 0,
    threshold: 15
  };

  constructor (props, context) {
    super(props, context)

    this._loadMoreRowsMemoizer = createCallbackMemoizer()

    this._onRowsRendered = this._onRowsRendered.bind(this)
    this._registerChild = this._registerChild.bind(this)
  }

  resetLoadMoreRowsCache () {
    this._loadMoreRowsMemoizer = createCallbackMemoizer()
  }

  render () {
    const { children } = this.props

    return children({
      onRowsRendered: this._onRowsRendered,
      registerChild: this._registerChild
    })
  }

  _loadUnloadedRanges (unloadedRanges) {
    const { loadMoreRows } = this.props

    unloadedRanges.forEach(unloadedRange => {
      let promise = loadMoreRows(unloadedRange)
      if (promise) {
        promise.then(() => {
          // Refresh the visible rows if any of them have just been loaded.
          // Otherwise they will remain in their unloaded visual state.
          if (
            isRangeVisible({
              lastRenderedStartIndex: this._lastRenderedStartIndex,
              lastRenderedStopIndex: this._lastRenderedStopIndex,
              startIndex: unloadedRange.startIndex,
              stopIndex: unloadedRange.stopIndex
            })
          ) {
            if (this._registeredChild) {
              forceUpdateReactVirtualizedComponent(this._registeredChild)
            }
          }
        })
      }
    })
  }

  _onRowsRendered ({ startIndex, stopIndex }) {
    const { isRowLoaded, minimumBatchSize, rowCount, threshold } = this.props

    this._lastRenderedStartIndex = startIndex
    this._lastRenderedStopIndex = stopIndex

    const unloadedRanges = scanForUnloadedRanges({
      isRowLoaded,
      minimumBatchSize,
      rowCount,
      startIndex: Math.max(0, startIndex - threshold),
      stopIndex: Math.min(rowCount - 1, stopIndex + threshold)
    })

    // For memoize comparison
    const squashedUnloadedRanges = unloadedRanges.reduce(
      (reduced, unloadedRange) => reduced.concat([unloadedRange.startIndex, unloadedRange.stopIndex]),
      []
    )

    this._loadMoreRowsMemoizer({
      callback: () => {
        this._loadUnloadedRanges(unloadedRanges)
      },
      indices: { squashedUnloadedRanges }
    })
  }

  _registerChild (registeredChild) {
    this._registeredChild = registeredChild
  }
}

/**
 * Determines if the specified start/stop range is visible based on the most recently rendered range.
 */
export function isRangeVisible ({
  lastRenderedStartIndex,
  lastRenderedStopIndex,
  startIndex,
  stopIndex
}) {
  return !(startIndex > lastRenderedStopIndex || stopIndex < lastRenderedStartIndex)
}

/**
 * Returns all of the ranges within a larger range that contain unloaded rows.
 */
export function scanForUnloadedRanges ({
  isRowLoaded,
  minimumBatchSize,
  rowCount,
  startIndex,
  stopIndex
}) {
  const unloadedRanges = []

  let rangeStartIndex = null
  let rangeStopIndex = null

  for (let index = startIndex; index <= stopIndex; index++) {
    let loaded = isRowLoaded({ index })

    if (!loaded) {
      rangeStopIndex = index
      if (rangeStartIndex === null) {
        rangeStartIndex = index
      }
    } else if (rangeStopIndex !== null) {
      unloadedRanges.push({
        startIndex: rangeStartIndex,
        stopIndex: rangeStopIndex
      })

      rangeStartIndex = rangeStopIndex = null
    }
  }

  // If :rangeStopIndex is not null it means we haven't ran out of unloaded rows.
  // Scan forward to try filling our :minimumBatchSize.
  if (rangeStopIndex !== null) {
    const potentialStopIndex = Math.min(
      Math.max(
        rangeStopIndex,
        rangeStartIndex + minimumBatchSize - 1
      ),
      rowCount - 1
    )

    for (let index = rangeStopIndex + 1; index <= potentialStopIndex; index++) {
      if (!isRowLoaded({ index })) {
        rangeStopIndex = index
      } else {
        break
      }
    }

    unloadedRanges.push({
      startIndex: rangeStartIndex,
      stopIndex: rangeStopIndex
    })
  }

  // Check to see if our first range ended prematurely.
  // In this case we should scan backwards to try filling our :minimumBatchSize.
  if (unloadedRanges.length) {
    const firstUnloadedRange = unloadedRanges[0]

    while (
      firstUnloadedRange.stopIndex - firstUnloadedRange.startIndex + 1 < minimumBatchSize &&
      firstUnloadedRange.startIndex > 0
    ) {
      let index = firstUnloadedRange.startIndex - 1

      if (!isRowLoaded({ index })) {
        firstUnloadedRange.startIndex = index
      } else {
        break
      }
    }
  }

  return unloadedRanges
}

/**
 * Since RV components use shallowCompare we need to force a render (even though props haven't changed).
 * However InfiniteLoader may wrap a Grid or it may wrap a Table or List.
 * In the first case the built-in React forceUpdate() method is sufficient to force a re-render,
 * But in the latter cases we need to use the RV-specific forceUpdateGrid() method.
 * Else the inner Grid will not be re-rendered and visuals may be stale.
 *
 * Additionally, while a Grid is scrolling the cells can be cached,
 * So it's important to invalidate that cache by recalculating sizes
 * before forcing a rerender.
 */
export function forceUpdateReactVirtualizedComponent (component) {
  const recomputeSize = typeof component.recomputeGridSize === 'function'
    ? component.recomputeGridSize
    : component.recomputeRowHeights

  if (recomputeSize) {
    recomputeSize.call(component)
  } else {
    component.forceUpdate()
  }
}
<|endoftext|>


<commit_before>var spawn = require('child_process').spawn;
var net = require('net');
var semaphore = require('semaphore')(1);

var conf = {
	bin: process.env.MELTED || "melted",
	root: process.env.MELTED_ROOT || process.env.PWD,
	host: process.env.MELTED_HOST || "localhost",
	port: process.env.MELTED_PORT || 5250,
	output: process.env.MELTED_OUTPUT || "sdl"
}

/**
 * _do
 *
 * Private function to connect to melted.
 *
 * @callback: Callback function to do to melted.
 */
_do = function(callback) {
	var pgrep = spawn('pgrep', ['-x', conf.bin]);
	var pid;

	pgrep.stdout.on('data', function (data) {
		pid = data;
	});

	pgrep.on('exit', function (code) {
		return callback(parseInt(pid));
	});
};

/**
 * update_config
 *
 * Setup following melted attributes:
 *
 *   - bin: path to binary file.
 *   - root: path to videos files.
 *   - host: host where melted is running.
 *   - port: port where melted is running.
 *   - output: output device.
 *
 * @conf: Map with melted basic configuration.
 */
exports.update_config = function(new_config) {
	conf.bin   = new_config.bin || conf.bin;
	conf.root  = new_config.root || conf.root;
	conf.host  = new_config.host || conf.host;
	conf.port  = new_config.port || conf.port;
	conf.output= new_config.output || conf.output;
};

/**
 * get_config
 *
 * Return config object.
 */
exports.get_config = function() {
	return conf;
};

/**
 * is_running
 *
 * @callback: callback function when known if running or not.
 */
exports.is_running = function(callback) {
	_do(function(pid) {
		return callback(!isNaN(pid));
	})
}

/**
 * stop
 *
 * Stop melted.
 *
 * @callback : callback function when process is stopped.
 */
exports.stop = function(callback) {
	_do(function(pid) {
		if (pid) {
			// exports.connect(function(conn){ exports.push(conn, ['SHUTDOWN'], undefined, undefined); });
			var kill = spawn('kill',[pid]);
			kill.on('close', function(state) { return callback(pid) });
		} else
			callback(pid);
	})
};

/**
 * start
 *
 * Start melted deamon.
 *
 * @callback : callback function when process is ready.
 */
exports.start = function(callback) {
	_do(function(pid) {
		if (pid) {
			callback(pid);
		} else {
			var melted_proc = spawn(conf.bin, [], {detached: true, stdio: [ 'ignore', 'ignore', 'ignore' ]});
			var pid = melted_proc.pid;
			melted_proc.unref()
			setTimeout(function() { callback(pid); }, 100);
		}
	})
};

/**
 * connect
 *
 * Connect to melted daemon.
 *
 * @callback : callback function when process is ready.
 */
exports.connect = function(callback) {
	var conn = net.createConnection(conf.port, conf.host);
	conn.setEncoding('ascii');
	callback(conn);
};

/**
 * push
 *
 * Push commands to melted daemon.
 *
 * @commands : list of commands to send.
 * @callback : callback function when process is ready.
 */
exports.push = function(conn, commands, command_callback, close_callback) {
	var s = 0;
	conn.on('connect', function() {
		conn.on('data', function(data) {
			if (command_callback) command_callback(data);
			if (s < commands.length && data.indexOf("\n") > -1) {
				conn.write(commands[s]+"\n");
				s = s + 1;
			};
		});
	});
	if (close_callback) conn.on('close', function(had_err) { close_callback(had_err); });
};

/**
 * setup
 *
 * Setup melted deamon.
 *
 * @callback : callback function when process is ready.
 */
exports.setup = function(root, output, callback) {
	root = root || conf.root;
	output = output || conf.output;
	_do(function(pid) {
		if (pid) {
			var commands = [ 'NLS', 'SET root='+root, 'UADD '+output, 'BYE' ];
			exports.connect(function(conn){ exports.push(conn, commands, undefined, callback)});
		} else {
			Err("Can't connect to server. Server is not running!")
		};
	})
};

/**
 * take
 *
 * Take melted and not leave execution to other melted taked.
 *
 * @callback: callback function to process while take melted.
 *
 */
exports.take = semaphore.take;

/**
 * leave
 *
 * Leave execution to other melted taked.
 *
 */
exports.leave = semaphore.leave;
<commit_msg>Checking process id of any melted binary.<commit_after>var spawn = require('child_process').spawn;
var net = require('net');
var semaphore = require('semaphore')(1);

var conf = {
	bin: process.env.MELTED || "melted",
	root: process.env.MELTED_ROOT || process.env.PWD,
	host: process.env.MELTED_HOST || "localhost",
	port: process.env.MELTED_PORT || 5250,
	output: process.env.MELTED_OUTPUT || "sdl"
}

/**
 * _do
 *
 * Private function to connect to melted.
 *
 * @callback: Callback function to do to melted.
 */
_do = function(callback) {
//	var pgrep = spawn('pgrep', ['-x', "melted"]);
    var pgrep = spawn('pgrep', ["melted"]);
	var pid;

	pgrep.stdout.on('data', function (data) {
		pid = data;
	});

	pgrep.on('exit', function (code) {
		return callback(parseInt(pid));
	});
};

/**
 * update_config
 *
 * Setup following melted attributes:
 *
 *   - bin: path to binary file.
 *   - root: path to videos files.
 *   - host: host where melted is running.
 *   - port: port where melted is running.
 *   - output: output device.
 *
 * @conf: Map with melted basic configuration.
 */
exports.update_config = function(new_config) {
	conf.bin   = new_config.bin || conf.bin;
	conf.root  = new_config.root || conf.root;
	conf.host  = new_config.host || conf.host;
	conf.port  = new_config.port || conf.port;
	conf.output= new_config.output || conf.output;
};

/**
 * get_config
 *
 * Return config object.
 */
exports.get_config = function() {
	return conf;
};

/**
 * is_running
 *
 * @callback: callback function when known if running or not.
 */
exports.is_running = function(callback) {
	_do(function(pid) {
		return callback(!isNaN(pid));
	})
}

/**
 * stop
 *
 * Stop melted.
 *
 * @callback : callback function when process is stopped.
 */
exports.stop = function(callback) {
	_do(function(pid) {
		if (pid) {
			// exports.connect(function(conn){ exports.push(conn, ['SHUTDOWN'], undefined, undefined); });
			var kill = spawn('kill',[pid]);
			kill.on('close', function(state) { return callback(pid) });
		} else
			callback(pid);
	})
};

/**
 * start
 *
 * Start melted deamon.
 *
 * @callback : callback function when process is ready.
 */
exports.start = function(callback) {
	_do(function(pid) {
		if (pid) {
			callback(pid);
		} else {
			var melted_proc = spawn(conf.bin, [], {detached: true, stdio: [ 'ignore', 'ignore', 'ignore' ]});
			var pid = melted_proc.pid;
			melted_proc.unref()
			setTimeout(function() { callback(pid); }, 100);
		}
	})
};

/**
 * connect
 *
 * Connect to melted daemon.
 *
 * @callback : callback function when process is ready.
 */
exports.connect = function(callback) {
	var conn = net.createConnection(conf.port, conf.host);
	conn.setEncoding('ascii');
	callback(conn);
};

/**
 * push
 *
 * Push commands to melted daemon.
 *
 * @commands : list of commands to send.
 * @callback : callback function when process is ready.
 */
exports.push = function(conn, commands, command_callback, close_callback) {
	var s = 0;
	conn.on('connect', function() {
		conn.on('data', function(data) {
			if (command_callback) command_callback(data);
			if (s < commands.length && data.indexOf("\n") > -1) {
				conn.write(commands[s]+"\n");
				s = s + 1;
			};
		});
	});
	if (close_callback) conn.on('close', function(had_err) { close_callback(had_err); });
};

/**
 * setup
 *
 * Setup melted deamon.
 *
 * @callback : callback function when process is ready.
 */
exports.setup = function(root, output, callback) {
	root = root || conf.root;
	output = output || conf.output;
	_do(function(pid) {
		if (pid) {
			var commands = [ 'NLS', 'SET root='+root, 'UADD '+output, 'BYE' ];
			exports.connect(function(conn){ exports.push(conn, commands, undefined, callback)});
		} else {
			Err("Can't connect to server. Server is not running!")
		};
	})
};

/**
 * take
 *
 * Take melted and not leave execution to other melted taked.
 *
 * @callback: callback function to process while take melted.
 *
 */
exports.take = semaphore.take;

/**
 * leave
 *
 * Leave execution to other melted taked.
 *
 */
exports.leave = semaphore.leave;
<|endoftext|>


<commit_before>(function (tree) {

    var parseCopyProperties = [
        'paths',            // option - unmodified - paths to search for imports on
        'optimization',     // option - optimization level (for the chunker)
        'files',            // list of files that have been imported, used for import-once
        'contents',         // browser-only, contents of all the files
        'relativeUrls',     // option - whether to adjust URL's to be relative
        'strictImports',    // option -
        'dumpLineNumbers',  // option - whether to dump line numbers
        'compress',         // option - whether to compress
        'processImports',   // option - whether to process imports. if false then imports will not be imported
        'syncImport',       // option - whether to import synchronously
        'mime',             // browser only - mime type for sheet import
        'currentFileInfo'   // information about the current file - for error reporting and importing and making urls relative etc.
    ];

    //currentFileInfo = {
    //  'relativeUrls' - option - whether to adjust URL's to be relative
    //  'filename' - full resolved filename of current file
    //  'rootpath' - path to append to normal URLs for this node
    //  'currentDirectory' - path to the current file, absolute
    //  'rootFilename' - filename of the base file
    //  'entryPath' = absolute path to the entry file

    tree.parseEnv = function(options) {
        copyFromOriginal(options, this, parseCopyProperties);

        if (!this.contents) { this.contents = {}; }
        if (!this.files) { this.files = {}; }

        if (!this.currentFileInfo) {
            var filename = (options && options.filename) || "input";
            var entryPath = filename.replace(/[^\/\\]*$/, "");
            if (options) {
                options.filename = null;
            }
            this.currentFileInfo = {
                filename: filename,
                relativeUrls: this.relativeUrls,
                rootpath: (options && options.rootpath) || "",
                currentDirectory: entryPath,
                entryPath: entryPath,
                rootFilename: filename
            };
        }
    };

    tree.parseEnv.prototype.toSheet = function (path) {
        var env = new tree.parseEnv(this);
        env.href = path;
        //env.title = path;
        env.type = this.mime;
        return env;
    };

    var evalCopyProperties = [
        'silent',      // whether to swallow errors and warnings
        'verbose',     // whether to log more activity
        'compress',    // whether to compress
        'ieCompat',    // whether to enforce IE compatibility (IE8 data-uri)
        'strictMath',  // whether math has to be within parenthesis
        'strictUnits'  // whether units need to evaluate correctly
        ];

    tree.evalEnv = function(options, frames) {
        copyFromOriginal(options, this, evalCopyProperties);

        this.frames = frames || [];
    };

    tree.evalEnv.prototype.inParenthesis = function () {
        if (!this.parensStack) {
            this.parensStack = [];
        }
        this.parensStack.push(true);
    };

    tree.evalEnv.prototype.outOfParenthesis = function () {
        this.parensStack.pop();
    };

    tree.evalEnv.prototype.isMathOn = function () {
        return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
    };

    tree.evalEnv.prototype.isPathRelative = function (path) {
        return !/^(?:[a-z-]+:|\/)/.test(path);
    };

    //todo - do the same for the toCSS env
    //tree.toCSSEnv = function (options) {
    //};

    var copyFromOriginal = function(original, destination, propertiesToCopy) {
        if (!original) { return; }

        for(var i = 0; i < propertiesToCopy.length; i++) {
            if (original.hasOwnProperty(propertiesToCopy[i])) {
                destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
            }
        }
    }
})(require('./tree'));<commit_msg>use yui-compress option<commit_after>(function (tree) {

    var parseCopyProperties = [
        'paths',            // option - unmodified - paths to search for imports on
        'optimization',     // option - optimization level (for the chunker)
        'files',            // list of files that have been imported, used for import-once
        'contents',         // browser-only, contents of all the files
        'relativeUrls',     // option - whether to adjust URL's to be relative
        'strictImports',    // option -
        'dumpLineNumbers',  // option - whether to dump line numbers
        'compress',         // option - whether to compress
        'processImports',   // option - whether to process imports. if false then imports will not be imported
        'syncImport',       // option - whether to import synchronously
        'mime',             // browser only - mime type for sheet import
        'currentFileInfo'   // information about the current file - for error reporting and importing and making urls relative etc.
    ];

    //currentFileInfo = {
    //  'relativeUrls' - option - whether to adjust URL's to be relative
    //  'filename' - full resolved filename of current file
    //  'rootpath' - path to append to normal URLs for this node
    //  'currentDirectory' - path to the current file, absolute
    //  'rootFilename' - filename of the base file
    //  'entryPath' = absolute path to the entry file

    tree.parseEnv = function(options) {
        copyFromOriginal(options, this, parseCopyProperties);

        if (!this.contents) { this.contents = {}; }
        if (!this.files) { this.files = {}; }

        if (!this.currentFileInfo) {
            var filename = (options && options.filename) || "input";
            var entryPath = filename.replace(/[^\/\\]*$/, "");
            if (options) {
                options.filename = null;
            }
            this.currentFileInfo = {
                filename: filename,
                relativeUrls: this.relativeUrls,
                rootpath: (options && options.rootpath) || "",
                currentDirectory: entryPath,
                entryPath: entryPath,
                rootFilename: filename
            };
        }
    };

    tree.parseEnv.prototype.toSheet = function (path) {
        var env = new tree.parseEnv(this);
        env.href = path;
        //env.title = path;
        env.type = this.mime;
        return env;
    };

    var evalCopyProperties = [
        'silent',      // whether to swallow errors and warnings
        'verbose',     // whether to log more activity
        'compress',    // whether to compress
        'yuicompress', // whether to compress with the outside tool yui compressor
        'ieCompat',    // whether to enforce IE compatibility (IE8 data-uri)
        'strictMath',  // whether math has to be within parenthesis
        'strictUnits'  // whether units need to evaluate correctly
        ];

    tree.evalEnv = function(options, frames) {
        copyFromOriginal(options, this, evalCopyProperties);

        this.frames = frames || [];
    };

    tree.evalEnv.prototype.inParenthesis = function () {
        if (!this.parensStack) {
            this.parensStack = [];
        }
        this.parensStack.push(true);
    };

    tree.evalEnv.prototype.outOfParenthesis = function () {
        this.parensStack.pop();
    };

    tree.evalEnv.prototype.isMathOn = function () {
        return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
    };

    tree.evalEnv.prototype.isPathRelative = function (path) {
        return !/^(?:[a-z-]+:|\/)/.test(path);
    };

    //todo - do the same for the toCSS env
    //tree.toCSSEnv = function (options) {
    //};

    var copyFromOriginal = function(original, destination, propertiesToCopy) {
        if (!original) { return; }

        for(var i = 0; i < propertiesToCopy.length; i++) {
            if (original.hasOwnProperty(propertiesToCopy[i])) {
                destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
            }
        }
    }
})(require('./tree'));<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import {
  View,
  StyleSheet,
  StatusBar,
  TouchableOpacity,
  Text,
} from 'react-native';
import { NavigationStyles } from '@expo/ex-navigation';
import colors from 'kolors';
import { Components, Location } from 'expo';
import ElevatedView from 'react-native-elevated-view';
import { maybeOpenURL } from 'react-native-app-link';
import connectDropdownAlert from '../utils/connectDropdownAlert';
import { phonecall } from 'react-native-communications';
import { observer } from 'mobx-react/native';
import { observable } from 'mobx';

@connectDropdownAlert
@observer
export default class MeetRiderScreen extends Component {
  static route = {
    navigationBar: {
      visible: false,
    },
    styles: {
      ...NavigationStyles.SlideHorizontal,
    },
  };

  static propTypes = {
    navigator: PropTypes.object.isRequired,
    navigation: PropTypes.object.isRequired,
    pickupLocation: PropTypes.object.isRequired,
    rider: PropTypes.object.isRequired,
    alertWithType: PropTypes.func.isRequired,
  };

  @observable region = null;
  @observable location = null;

  componentWillMount() {
    this.locationSub = Location.watchPositionAsync(
      {
        enableHighAccuracy: true,
        timeInterval: 1000,
        distanceInterval: 1,
      },
      data => {
        this.location = {
          latitude: data.coords.latitude,
          longitude: data.coords.longitude,
        };
      }
    );
  }

  componentWillUnmount() {
    this.locationSub.remove();
  }

  onRegionChange = region => this.region = region;

  render() {
    return (
      <View style={styles.container}>
        <Components.MapView
          ref={c => {
            this.map = c;
          }}
          style={StyleSheet.absoluteFillObject}
          initialRegion={{
            latitude: this.props.pickupLocation.lat,
            longitude: this.props.pickupLocation.lon,
            latitudeDelta: 0.0922,
            longitudeDelta: 0.0421,
          }}
          showsUserLocation
          followsUserLocation
          toolbarEnabled={false}
          loadingEnabled
          region={this.region}
          onRegionChange={this.onRegionChange}
        >
          <StatusBar hidden />
          <Components.MapView.Marker
            title={this.props.pickupLocation.name}
            coordinate={{
              latitude: this.props.pickupLocation.lat,
              longitude: this.props.pickupLocation.lon,
            }}
            onCalloutPress={() => {
              const wazeUrl = `waze://?ll=${this.props.pickupLocation.lat},` +
                `${this.props.pickupLocation.lon}&z=10&navigate=yes`;
              maybeOpenURL(wazeUrl, {
                appName: 'Waze',
                appStoreId: 'id323229106',
                playStoreId: 'com.waze',
              }).catch(err => {
                this.props.alertWithType('error', 'Error', err.toString());
              });
            }}
          >
            <ElevatedView style={styles.marker} elevation={6}>
              <View style={styles.markerInner} />
            </ElevatedView>
          </Components.MapView.Marker>
          <If condition={this.location}>
            <Components.MapView.Polyline
              strokeWidth={2}
              strokeColor={colors.black}
              geodesic
              lineDashPattern={[4, 8, 4, 8]}
              coordinates={[
                {
                  latitude: this.props.pickupLocation.lat,
                  longitude: this.props.pickupLocation.lon,
                },
                this.location,
              ]}
            />
          </If>
        </Components.MapView>
        <TouchableOpacity
          onPress={() => this.map.animateToCoordinate({
            latitude: this.props.pickupLocation.lat,
            longitude: this.props.pickupLocation.lon,
          })}
        >
          <ElevatedView style={styles.infoBox} elevation={4}>
            <Text style={styles.infoBoxText}>
              Pickup at the
              {' '}
              {this.props.pickupLocation.name.toLowerCase().trim()}
              .
            </Text>
          </ElevatedView>
        </TouchableOpacity>
        <View style={styles.actionContainer}>
          <View>
            <Text style={styles.driverName}>
              {this.props.rider.displayName.toUpperCase()}
            </Text>
          </View>
          <View style={styles.buttonRow}>
            <TouchableOpacity onPress={() => this.props.navigator.pop()}>
              <View style={[styles.button, styles.cancelButton]}>
                <Text style={styles.cancel}>CLOSE</Text>
              </View>
            </TouchableOpacity>
            <TouchableOpacity
              onPress={() => {
                phonecall(this.props.rider.phoneNumber, true);
              }}
            >
              <View style={styles.button}>
                <Text style={styles.contact}>CONTACT</Text>
              </View>
            </TouchableOpacity>
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  infoBox: {
    backgroundColor: colors.black,
    paddingVertical: 8,
    paddingHorizontal: 16,
    marginTop: 64,
    borderRadius: 4,
    justifyContent: 'center',
    alignItems: 'center',
  },
  infoBoxText: {
    fontFamily: 'open-sans',
    fontSize: 16,
    color: 'white',
  },
  marker: {
    height: 24,
    width: 24,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: colors.black,
    borderRadius: 12,
  },
  markerInner: {
    backgroundColor: 'white',
    height: 8,
    width: 8,
    borderRadius: 4,
  },
  actionContainer: {
    paddingVertical: 8,
    backgroundColor: 'white',
    justifyContent: 'center',
    alignItems: 'center',
  },
  driverName: {
    fontFamily: 'open-sans-bold',
    color: colors.black,
    fontSize: 14,
    paddingBottom: 8,
  },
  buttonRow: {
    paddingTop: 8,
    borderTopWidth: StyleSheet.hairlineWidth,
    borderColor: colors.lightGrey,
    alignItems: 'center',
    justifyContent: 'space-around',
    flexDirection: 'row',
  },
  button: {
    paddingHorizontal: 16,
    alignItems: 'center',
  },
  cancelButton: {
    borderRightWidth: StyleSheet.hairlineWidth,
    borderColor: colors.lightGrey,
  },
  cancel: {
    fontFamily: 'open-sans-bold',
    color: colors.hotPink,
    fontSize: 14,
  },
  contact: {
    fontFamily: 'open-sans-bold',
    color: colors.blue,
    fontSize: 14,
  },
});
<commit_msg>undefined is falsy<commit_after>import React, { Component, PropTypes } from 'react';
import {
  View,
  StyleSheet,
  StatusBar,
  TouchableOpacity,
  Text,
} from 'react-native';
import { NavigationStyles } from '@expo/ex-navigation';
import colors from 'kolors';
import { Components, Location } from 'expo';
import ElevatedView from 'react-native-elevated-view';
import { maybeOpenURL } from 'react-native-app-link';
import connectDropdownAlert from '../utils/connectDropdownAlert';
import { phonecall } from 'react-native-communications';
import { observer } from 'mobx-react/native';
import { observable } from 'mobx';

@connectDropdownAlert
@observer
export default class MeetRiderScreen extends Component {
  static route = {
    navigationBar: {
      visible: false,
    },
    styles: {
      ...NavigationStyles.SlideHorizontal,
    },
  };

  static propTypes = {
    navigator: PropTypes.object.isRequired,
    navigation: PropTypes.object.isRequired,
    pickupLocation: PropTypes.object.isRequired,
    rider: PropTypes.object.isRequired,
    alertWithType: PropTypes.func.isRequired,
  };

  @observable region;
  @observable location;

  componentWillMount() {
    this.locationSub = Location.watchPositionAsync(
      {
        enableHighAccuracy: true,
        timeInterval: 1000,
        distanceInterval: 1,
      },
      data => {
        this.location = {
          latitude: data.coords.latitude,
          longitude: data.coords.longitude,
        };
      }
    );
  }

  componentWillUnmount() {
    this.locationSub.remove();
  }

  onRegionChange = region => this.region = region;

  render() {
    return (
      <View style={styles.container}>
        <Components.MapView
          ref={c => {
            this.map = c;
          }}
          style={StyleSheet.absoluteFillObject}
          initialRegion={{
            latitude: this.props.pickupLocation.lat,
            longitude: this.props.pickupLocation.lon,
            latitudeDelta: 0.0922,
            longitudeDelta: 0.0421,
          }}
          showsUserLocation
          followsUserLocation
          toolbarEnabled={false}
          loadingEnabled
          region={this.region}
          onRegionChange={this.onRegionChange}
        >
          <StatusBar hidden />
          <Components.MapView.Marker
            title={this.props.pickupLocation.name}
            coordinate={{
              latitude: this.props.pickupLocation.lat,
              longitude: this.props.pickupLocation.lon,
            }}
            onCalloutPress={() => {
              const wazeUrl = `waze://?ll=${this.props.pickupLocation.lat},` +
                `${this.props.pickupLocation.lon}&z=10&navigate=yes`;
              maybeOpenURL(wazeUrl, {
                appName: 'Waze',
                appStoreId: 'id323229106',
                playStoreId: 'com.waze',
              }).catch(err => {
                this.props.alertWithType('error', 'Error', err.toString());
              });
            }}
          >
            <ElevatedView style={styles.marker} elevation={6}>
              <View style={styles.markerInner} />
            </ElevatedView>
          </Components.MapView.Marker>
          <If condition={this.location}>
            <Components.MapView.Polyline
              strokeWidth={2}
              strokeColor={colors.black}
              geodesic
              lineDashPattern={[4, 8, 4, 8]}
              coordinates={[
                {
                  latitude: this.props.pickupLocation.lat,
                  longitude: this.props.pickupLocation.lon,
                },
                this.location,
              ]}
            />
          </If>
        </Components.MapView>
        <TouchableOpacity
          onPress={() => this.map.animateToCoordinate({
            latitude: this.props.pickupLocation.lat,
            longitude: this.props.pickupLocation.lon,
          })}
        >
          <ElevatedView style={styles.infoBox} elevation={4}>
            <Text style={styles.infoBoxText}>
              Pickup at the
              {' '}
              {this.props.pickupLocation.name.toLowerCase().trim()}
              .
            </Text>
          </ElevatedView>
        </TouchableOpacity>
        <View style={styles.actionContainer}>
          <View>
            <Text style={styles.driverName}>
              {this.props.rider.displayName.toUpperCase()}
            </Text>
          </View>
          <View style={styles.buttonRow}>
            <TouchableOpacity onPress={() => this.props.navigator.pop()}>
              <View style={[styles.button, styles.cancelButton]}>
                <Text style={styles.cancel}>CLOSE</Text>
              </View>
            </TouchableOpacity>
            <TouchableOpacity
              onPress={() => {
                phonecall(this.props.rider.phoneNumber, true);
              }}
            >
              <View style={styles.button}>
                <Text style={styles.contact}>CONTACT</Text>
              </View>
            </TouchableOpacity>
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  infoBox: {
    backgroundColor: colors.black,
    paddingVertical: 8,
    paddingHorizontal: 16,
    marginTop: 64,
    borderRadius: 4,
    justifyContent: 'center',
    alignItems: 'center',
  },
  infoBoxText: {
    fontFamily: 'open-sans',
    fontSize: 16,
    color: 'white',
  },
  marker: {
    height: 24,
    width: 24,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: colors.black,
    borderRadius: 12,
  },
  markerInner: {
    backgroundColor: 'white',
    height: 8,
    width: 8,
    borderRadius: 4,
  },
  actionContainer: {
    paddingVertical: 8,
    backgroundColor: 'white',
    justifyContent: 'center',
    alignItems: 'center',
  },
  driverName: {
    fontFamily: 'open-sans-bold',
    color: colors.black,
    fontSize: 14,
    paddingBottom: 8,
  },
  buttonRow: {
    paddingTop: 8,
    borderTopWidth: StyleSheet.hairlineWidth,
    borderColor: colors.lightGrey,
    alignItems: 'center',
    justifyContent: 'space-around',
    flexDirection: 'row',
  },
  button: {
    paddingHorizontal: 16,
    alignItems: 'center',
  },
  cancelButton: {
    borderRightWidth: StyleSheet.hairlineWidth,
    borderColor: colors.lightGrey,
  },
  cancel: {
    fontFamily: 'open-sans-bold',
    color: colors.hotPink,
    fontSize: 14,
  },
  contact: {
    fontFamily: 'open-sans-bold',
    color: colors.blue,
    fontSize: 14,
  },
});
<|endoftext|>


<commit_before>/* Copyright 2016 Google Inc. All Rights Reserved.

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

var _ = require('underscore');

//
// Module Confguration
//
let DEFAULT_CONFIG = {
  codeServer: "http://localhost:3001"
};

const HIGHLIGHT_COLORS = ['#3cba54', '#f4c20d', '#db3236', '#4885ed'];

//
// Helper methods
//
function DefaultClientCode(client, text) {
  return `canvas.writeText(screen.width/2, screen.height/2-300, "Chicago Brick Live!", "#f4c20d", "140px Arial", {textAlign: "center"});
canvas.writeText(screen.width/2, screen.height/2-150, "${text}", "white", "100px Arial", {textAlign: "center"});
canvas.writeText(screen.width/2, screen.height/2+50, "${client.x}, ${client.y}", "white", "180px Arial", {textAlign: "center"});
canvas.draw.image(10, 10, "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", 0.5);`;
}

function ClientCodeError(message) {
  return `canvas.writeText(screen.width/2, screen.height/2-300, "Chicago Brick Live - Code Error", "#d50f25", "120px Arial", {textAlign: "center"});
canvas.writeText(screen.width/2, screen.height/2, "${message}", "white", "80px Arial", {textAlign: "center"});
canvas.draw.image(10, 10, "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", 0.5);`;
}

function getClientKey(client) {
  return `${client.x},${client.y}`;
}
//
// Server Module
//
class LiveClientServer extends ServerModuleInterface {
  constructor(config) {
    super();
    this.log = require('debug')('module:live_client');

    this.config = _.defaults(config, DEFAULT_CONFIG);
    this.log(`Attempting to use codeserver at ${this.config.codeServer}`);

    // All clients (x, y) that have ever connected.  Used to notify all clients
    // of global code changes (e.g., codeserver comes online) and cache code.
    this.clients = {};

    var inst = this;
    this.codeServer = require('socket.io-client')(this.config.codeServer);

    // Setup connection to code server.
    inst.codeServer.on('connect', function () {
      inst.log(`Connected to code server (${inst.config.codeServer}).`);

      // When code server connection is made re-request code for all clients
      // we know about.
      // #TODO Is there any client list provided by brick?
      for (var key in inst.clients) {
        inst.requestCode(inst.clients[key].client);
      }
    });

    inst.codeServer.on('disconnect', function () {
      inst.log('Disconnected from code server.');
    });

    inst.codeServer.on('code', function(data) {
      // Make a unique key of the form 'x,y' so we can use a dictionary for clients.
      var key = getClientKey(data.client);
      inst.log(`Received new info for client(${key}).`);

      // Override empty code
      data.code = data.code || DefaultClientCode(data.client, `Feed me code at ${inst.config.codeServer}`);

      // Cache the code in case the code server goes away.
      inst.clients[key] = data;

      // Forward code to clients.
      network.emit(`code(${key})`, data);
    });

    // Handle connections from clients.
    network.on('connection', function(socket) {
      socket.on('requestCode', function(data) {

        var key = getClientKey(data.client);
        inst.log(`Client(${key}) requested code.`);
        inst.log(`Code server connected: ${inst.codeServer.connected}`);

        // Track the client
        inst.clients[key] = _.extend(inst.clients[key] || {}, { client: data.client });
        inst.clients[key] = _.defaults(inst.clients[key], { code: undefined });

        var response;

        if (inst.clients[key].code || !inst.codeServer.connected) {
          inst.log(`Sending cached code to client(${key}).`);
          response = _.defaults(inst.clients[key], {
            client: data.client,
            code: DefaultClientCode(data.client, "No code server available")
          });

          network.emit(`code(${key})`, response);
        } else {
          // If there isn't any code yet, ask the code server. Any code
          // it sends back will be forwarded to clients automatically.
          inst.requestCode(data.client);
        }
      });
    });
  }

  dispose() {
    this.codeServer.close();
  }

  requestCode(client) {
    // Request code from code server
    var key = getClientKey(client);
    this.log(`Requesting code for client(${key}) from code server.`);
    this.codeServer.emit('requestCode', { client: client });
  }
}

//
// Client Module
//
class LiveClientClient extends ClientModuleInterface {
  finishFadeOut() {
    network.removeListener(this.newCodeEvent, this.newCodeHandler);

    if (this.surface) {
      this.surface.destroy();
    }
  }

  willBeShownSoon(container, deadline) {
    this.surface = new CanvasSurface(container, wallGeometry);
    this.canvas = this.extendCanvas(this.surface.context);
    this.screen = { x: 0, y: 0, width: this.canvas.canvas.width, height: this.canvas.canvas.height };

    // Basic client info.
    this.client = {
          x: this.surface.virtualOffset.x,
          y: this.surface.virtualOffset.y,
    };

    // Use the default code until told otherwise.
    this.setClientCode({ code: "", controlled: false });

    // The event we listen to for new code.
    this.newCodeEvent = `code(${getClientKey(this.client)})`;
    network.on(this.newCodeEvent, this.setClientCode.bind(this));

    // Ask for some code to run.
    network.emit('requestCode', { client: this.client });
  }

  extendCanvas(canvas) {
    canvas._imageCache = {};

    canvas.writeText = function(x, y, text, style, font, extraProps) {
      _.extend(this, {textAlign: "left"}, extraProps);

      this.font = font || "120px Arial";
      this.fillStyle = style || "white";
      this.baseBaseline = "bottom";
      this.fillText(text, x, y);
    };

    canvas.draw = {
      image: function(x, y, url, scale) {
        scale = scale || 1;

        // Only load each image once since everything is done in the draw loop.
        var image = canvas._imageCache[url];

        if (!image) {
          image = new Image();
          image.src = url;
          canvas._imageCache[url] = image;
        }

        canvas.drawImage(image, x, y, scale * image.width, scale * image.height);
      },
      rectangle: function(rect, style) {
        var l = rect.left || rect.x;
        var t = rect.top || rect.y;
        var w = rect.width || rect.w;
        var h = rect.height|| rect.h;

        canvas.fillStyle = style || "white";
        canvas.fillRect(l, t, w, h);
      },
      circle: function(x, y, radius, style) {
        canvas.fillStyle = style || "white";
        canvas.beginPath();
        canvas.arc(x, y, radius, 0, 2 * Math.PI);
        canvas.fill();
      }
    };

    return canvas;
  }

  setClientCode(clientCode) {
    // Merge the new client code with the existing.
    this.clientCode = _.extend(this.clientCode || {}, clientCode, { time0: undefined });

    try {
      this.clientCode.draw = new Function('canvas', 'time', 'globalTime', 'screen', this.clientCode.code);
    } catch (e) {
      // If there is a syntax error "new Function" will fail, replace code with
      // error message.
      this.setClientCode({ code: ClientCodeError(e.message) });
    }
  }

  draw(time, delta) {
    this.canvas.draw.rectangle(this.screen, 'black');

    this.clientCode.time0 = this.clientCode.time0 || time;

    try {
      this.clientCode.draw(this.canvas, time - this.clientCode.time0, time, this.screen);
    } catch (e) {
      // If there is a runtime error, replace code with error message.
      this.setClientCode({ code: ClientCodeError(e.message) });
    }

    // Draw client info.
    this.canvas.writeText(10, this.screen.height-20, getClientKey(this.client), "white", "40px Arial");
    if (this.clientCode.controlled) {
      this.canvas.save();
      this.canvas.strokeStyle = HIGHLIGHT_COLORS[(this.client.x + this.client.y) % HIGHLIGHT_COLORS.length];
      this.canvas.lineWidth   = 10;
      this.canvas.strokeRect(0,0, this.screen.width, this.screen.height);
      this.canvas.restore();
    }
  }
}

register(LiveClientServer, LiveClientClient);
<commit_msg>Update debug message naming for chicago-brick-live module.<commit_after>/* Copyright 2016 Google Inc. All Rights Reserved.

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

var _ = require('underscore');

//
// Module Confguration
//
let DEFAULT_CONFIG = {
  codeServer: "http://localhost:3001"
};

const HIGHLIGHT_COLORS = ['#3cba54', '#f4c20d', '#db3236', '#4885ed'];

//
// Helper methods
//
function DefaultClientCode(client, text) {
  return `canvas.writeText(screen.width/2, screen.height/2-300, "Chicago Brick Live!", "#f4c20d", "140px Arial", {textAlign: "center"});
canvas.writeText(screen.width/2, screen.height/2-150, "${text}", "white", "100px Arial", {textAlign: "center"});
canvas.writeText(screen.width/2, screen.height/2+50, "${client.x}, ${client.y}", "white", "180px Arial", {textAlign: "center"});
canvas.draw.image(10, 10, "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", 0.5);`;
}

function ClientCodeError(message) {
  return `canvas.writeText(screen.width/2, screen.height/2-300, "Chicago Brick Live - Code Error", "#d50f25", "120px Arial", {textAlign: "center"});
canvas.writeText(screen.width/2, screen.height/2, "${message}", "white", "80px Arial", {textAlign: "center"});
canvas.draw.image(10, 10, "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", 0.5);`;
}

function getClientKey(client) {
  return `${client.x},${client.y}`;
}
//
// Server Module
//
class LiveClientServer extends ServerModuleInterface {
  constructor(config) {
    super();
    this.log = require('debug')('chicago-brick-live');

    this.config = _.defaults(config, DEFAULT_CONFIG);
    this.log(`Attempting to use codeserver at ${this.config.codeServer}`);

    // All clients (x, y) that have ever connected.  Used to notify all clients
    // of global code changes (e.g., codeserver comes online) and cache code.
    this.clients = {};

    var inst = this;
    this.codeServer = require('socket.io-client')(this.config.codeServer);

    // Setup connection to code server.
    inst.codeServer.on('connect', function () {
      inst.log(`Connected to code server (${inst.config.codeServer}).`);

      // When code server connection is made re-request code for all clients
      // we know about.
      // #TODO Is there any client list provided by brick?
      for (var key in inst.clients) {
        inst.requestCode(inst.clients[key].client);
      }
    });

    inst.codeServer.on('disconnect', function () {
      inst.log('Disconnected from code server.');
    });

    inst.codeServer.on('code', function(data) {
      // Make a unique key of the form 'x,y' so we can use a dictionary for clients.
      var key = getClientKey(data.client);
      inst.log(`Received new info for client(${key}).`);

      // Override empty code
      data.code = data.code || DefaultClientCode(data.client, `Feed me code at ${inst.config.codeServer}`);

      // Cache the code in case the code server goes away.
      inst.clients[key] = data;

      // Forward code to clients.
      network.emit(`code(${key})`, data);
    });

    // Handle connections from clients.
    network.on('connection', function(socket) {
      socket.on('requestCode', function(data) {

        var key = getClientKey(data.client);
        inst.log(`Client(${key}) requested code.`);
        inst.log(`Code server connected: ${inst.codeServer.connected}`);

        // Track the client
        inst.clients[key] = _.extend(inst.clients[key] || {}, { client: data.client });
        inst.clients[key] = _.defaults(inst.clients[key], { code: undefined });

        var response;

        if (inst.clients[key].code || !inst.codeServer.connected) {
          inst.log(`Sending cached code to client(${key}).`);
          response = _.defaults(inst.clients[key], {
            client: data.client,
            code: DefaultClientCode(data.client, "No code server available")
          });

          network.emit(`code(${key})`, response);
        } else {
          // If there isn't any code yet, ask the code server. Any code
          // it sends back will be forwarded to clients automatically.
          inst.requestCode(data.client);
        }
      });
    });
  }

  dispose() {
    this.codeServer.close();
  }

  requestCode(client) {
    // Request code from code server
    var key = getClientKey(client);
    this.log(`Requesting code for client(${key}) from code server.`);
    this.codeServer.emit('requestCode', { client: client });
  }
}

//
// Client Module
//
class LiveClientClient extends ClientModuleInterface {
  finishFadeOut() {
    network.removeListener(this.newCodeEvent, this.newCodeHandler);

    if (this.surface) {
      this.surface.destroy();
    }
  }

  willBeShownSoon(container, deadline) {
    this.surface = new CanvasSurface(container, wallGeometry);
    this.canvas = this.extendCanvas(this.surface.context);
    this.screen = { x: 0, y: 0, width: this.canvas.canvas.width, height: this.canvas.canvas.height };

    // Basic client info.
    this.client = {
          x: this.surface.virtualOffset.x,
          y: this.surface.virtualOffset.y,
    };

    // Use the default code until told otherwise.
    this.setClientCode({ code: "", controlled: false });

    // The event we listen to for new code.
    this.newCodeEvent = `code(${getClientKey(this.client)})`;
    network.on(this.newCodeEvent, this.setClientCode.bind(this));

    // Ask for some code to run.
    network.emit('requestCode', { client: this.client });
  }

  extendCanvas(canvas) {
    canvas._imageCache = {};

    canvas.writeText = function(x, y, text, style, font, extraProps) {
      _.extend(this, {textAlign: "left"}, extraProps);

      this.font = font || "120px Arial";
      this.fillStyle = style || "white";
      this.baseBaseline = "bottom";
      this.fillText(text, x, y);
    };

    canvas.draw = {
      image: function(x, y, url, scale) {
        scale = scale || 1;

        // Only load each image once since everything is done in the draw loop.
        var image = canvas._imageCache[url];

        if (!image) {
          image = new Image();
          image.src = url;
          canvas._imageCache[url] = image;
        }

        canvas.drawImage(image, x, y, scale * image.width, scale * image.height);
      },
      rectangle: function(rect, style) {
        var l = rect.left || rect.x;
        var t = rect.top || rect.y;
        var w = rect.width || rect.w;
        var h = rect.height|| rect.h;

        canvas.fillStyle = style || "white";
        canvas.fillRect(l, t, w, h);
      },
      circle: function(x, y, radius, style) {
        canvas.fillStyle = style || "white";
        canvas.beginPath();
        canvas.arc(x, y, radius, 0, 2 * Math.PI);
        canvas.fill();
      }
    };

    return canvas;
  }

  setClientCode(clientCode) {
    // Merge the new client code with the existing.
    this.clientCode = _.extend(this.clientCode || {}, clientCode, { time0: undefined });

    try {
      this.clientCode.draw = new Function('canvas', 'time', 'globalTime', 'screen', this.clientCode.code);
    } catch (e) {
      // If there is a syntax error "new Function" will fail, replace code with
      // error message.
      this.setClientCode({ code: ClientCodeError(e.message) });
    }
  }

  draw(time, delta) {
    this.canvas.draw.rectangle(this.screen, 'black');

    this.clientCode.time0 = this.clientCode.time0 || time;

    try {
      this.clientCode.draw(this.canvas, time - this.clientCode.time0, time, this.screen);
    } catch (e) {
      // If there is a runtime error, replace code with error message.
      this.setClientCode({ code: ClientCodeError(e.message) });
    }

    // Draw client info.
    this.canvas.writeText(10, this.screen.height-20, getClientKey(this.client), "white", "40px Arial");
    if (this.clientCode.controlled) {
      this.canvas.save();
      this.canvas.strokeStyle = HIGHLIGHT_COLORS[(this.client.x + this.client.y) % HIGHLIGHT_COLORS.length];
      this.canvas.lineWidth   = 10;
      this.canvas.strokeRect(0,0, this.screen.width, this.screen.height);
      this.canvas.restore();
    }
  }
}

register(LiveClientServer, LiveClientClient);
<|endoftext|>


<commit_before>// ==UserScript==
// @name Douban Article Formater
// @namespace DAF
// @description 豆瓣文章格式化脚本，能够过滤段落中的手动缩进，自动调整段落间距。
// @include http://movie.douban.com/review/*
// @include http://www.douban.com/note/*
// @include http://book.douban.com/review/*
// @version 1.1.0
// @author tranch
// ==/UserScript==

(function() {
    function GM_wait() {
        if (typeof window.jQuery == 'undefined') {
            setTimeout(GM_wait, 100);
        } else {
            main(jQuery);
        }
    }

    function main($) {
        var article;
        article_container = $('div[property="v:description"]');
        article = article_container.html().replace(/( |\s|\n){2,}/g, '');
        article = '
' + article.replace(/(
(\s|( )*)+)+/g, '

') + '
';
        article_container.addClass('article_description').html(article);
        $('head').append($('