<commit_before>odoo.define('website.editor', function (require) {
'use strict';

var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
var base = require('web_editor.base');
var editor = require('web_editor.editor');
var widget = require('web_editor.widget');
var website = require('website.website');

var qweb = core.qweb;
var _t = core._t;

ajax.loadXML('/website/static/src/xml/website.editor.xml', qweb);

/**
 * Object who contains all method and bind for the top bar, the template is create server side.
 */
website.TopBar.include({
    events: {
        'click [data-action="edit"]': 'edit',
    },
    start: function () {
        $("#wrapwrap").find("[data-oe-model] .oe_structure.oe_empty, [data-oe-model].oe_structure.oe_empty, [data-oe-type=html]:empty")
            .filter(".oe_not_editable")
            .filter(".oe_no_empty")
            .addClass("oe_empty");

        if (location.search.indexOf("enable_editor") >= 0 && $('html').attr('lang').match(/en[-_]US/)) {
            this.$el.addClass('editing_mode');
            this.delayed_hide();
        }

        return this._super.apply(this, arguments);
    },
    edit: function () {
        this.$('button[data-action=edit]').prop('disabled', true);
        this.$el.addClass('editing_mode');
        editor.editor_bar = new editor.Class(this);
        editor.editor_bar.prependTo(document.body);
        $('.o_homepage_editor_welcome_message').remove();

        this.delayed_hide();
    },
    delayed_hide: function () {
        _.delay((function () {
            this.do_hide();
        }).bind(this), 800);
    },
});

/* ----- Customize Template ---- */

website.TopBarCustomize = Widget.extend({
    events: {
        'mousedown a.dropdown-toggle': 'load_menu',
        'click ul a[data-view-id]': 'do_customize',
    },
    start: function () {
        var self = this;
        this.$menu = self.$el.find('ul');
        this.view_name = $(document.documentElement).data('view-xmlid');
        if (!this.view_name) {
            this.$el.hide();
        }
        this.loaded = false;
    },
    load_menu: function () {
        var self = this;
        if(this.loaded) {
            return;
        }
        ajax.jsonRpc('/website/customize_template_get', 'call', {
            key: this.view_name,
        }).then(function (result) {
            _.each(result, function (item) {
                if (item.key === "website.debugger" && !window.location.search.match(/[&?]debug(&|$)/)) return;
                if (item.header) {
                    self.$menu.append('
' + item.name + '
');
                } else {
                    var $li = $('
', {role: 'presentation'})
                                .append($('', {href: '#', 'data-view-id': item.id, role: 'menuitem'})
                                    .append(qweb.render('web_editor.components.switch', {id: 'switch-' + item.id, label: item.name})));
                    $li.find('input').prop('checked', !!item.active);
                    self.$menu.append($li);
                }
            });
            self.loaded = true;
        });
    },
    do_customize: function (e) {
        e.preventDefault();
        var view_id = $(e.currentTarget).data('view-id');
        return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
            model: 'ir.ui.view',
            method: 'toggle',
            args: [[parseInt(view_id, 10)]],
            kwargs: {context: base.get_context()}
        }).then(function () {
            window.location.reload();
        });
    },
});
website.TopBar.include({
    start: function () {
        this.customize_menu = new website.TopBarCustomize();
        var def = this.customize_menu.attachTo($('#customize-menu'));
        return $.when(this._super(), def);
    }
});

/* ----- EDITOR: LINK & MEDIA ---- */

widget.LinkDialog.include({
    bind_data: function () {
        var self = this;
        var href = this.data.url;
        var last;

        this.$('#link-page').select2({
            minimumInputLength: 1,
            placeholder: _t("New or existing page"),
            query: function (q) {
                if (q.term === last) return;
                last = q.term;
                $.when(
                    self.page_exists(q.term),
                    self.fetch_pages(q.term)
                ).then(function (exists, results) {
                    var rs = _.map(results, function (r) {
                        return { id: r.loc, text: r.loc, };
                    });
                    if (!exists) {
                        rs.push({
                            create: true,
                            id: q.term,
                            text: _.str.sprintf(_t("Create page '%s'"), q.term),
                        });
                    }
                    q.callback({
                        more: false,
                        results: rs
                    });
                }, function () {
                    q.callback({more: false, results: []});
                });
            },
        });

        if (href) {
            this.page_exists(href).then(function (exist) {
                if (exist) {
                    self.$('#link-page').select2('data', {'id': href, 'text': href}).change();
                } else {
                    self.$('input.url').val(href).change();
                    self.$('input.window-new').closest("div").show();
                }
            });
        }
        return this._super();
    },
    get_data_buy_url: function (def, $e, isNewWindow, label, classes, test) {
        var val = $e.val();
        if (val && val.length && $e.hasClass('page')) {
            var data = $e.select2('data');
            if (!data.create || test) {
                def.resolve(data.id, isNewWindow, label || data.text, classes);
            } else {
                // Create the page, get the URL back
                $.get(_.str.sprintf(
                        '/website/add/%s?noredirect=1', encodeURI(data.id)))
                    .then(function (response) {
                        def.resolve(response, isNewWindow, label, classes);
                    });
            }
        } else {
            return this._super.apply(this, arguments);
        }
    },
    changed: function (e) {
        this.$('.url-source').filter(':input').not($(e.target)).val('')
                .filter(function () { return !!$(this).data('select2'); })
                .select2('data', null);
        this._super(e);
    },
    call: function (method, args, kwargs) {
        var self = this;
        var req = method + '_req';
        if (this[req]) { this[req].abort(); }
        return this[req] = ajax.jsonRpc('/web/dataset/call_kw', 'call', {
            model: 'website',
            method: method,
            args: args,
            kwargs: kwargs,
        }).always(function () {
            self[req] = null;
        });
    },
    page_exists: function (term) {
        return this.call('page_exists', [null, term], {
            context: base.get_context(),
        });
    },
    fetch_pages: function (term) {
        return this.call('search_pages', [null, term], {
            limit: 9,
            context: base.get_context(),
        });
    },
});

/**
 * Display a welcome message on the homepage when it is empty and that the user is connected.
 */
base.ready().then(function () {
    if (location.search.indexOf("enable_editor") < 0 && $(".editor_enable").length === 0) {
        var $wrap = $("#wrapwrap.homepage #wrap");
        if ($wrap.length && $wrap.html().trim() === "") {
            $wrap.html(qweb.render("website.homepage_editor_welcome_message"));
        }
    }
});

});
<commit_msg>[IMP] website: make the welcome message fit the whole page height<commit_after>odoo.define('website.editor', function (require) {
'use strict';

var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
var base = require('web_editor.base');
var editor = require('web_editor.editor');
var widget = require('web_editor.widget');
var website = require('website.website');

var qweb = core.qweb;
var _t = core._t;

ajax.loadXML('/website/static/src/xml/website.editor.xml', qweb);

/**
 * Object who contains all method and bind for the top bar, the template is create server side.
 */
website.TopBar.include({
    events: {
        'click [data-action="edit"]': 'edit',
    },
    start: function () {
        $("#wrapwrap").find("[data-oe-model] .oe_structure.oe_empty, [data-oe-model].oe_structure.oe_empty, [data-oe-type=html]:empty")
            .filter(".oe_not_editable")
            .filter(".oe_no_empty")
            .addClass("oe_empty");

        if (location.search.indexOf("enable_editor") >= 0 && $('html').attr('lang').match(/en[-_]US/)) {
            this.$el.addClass('editing_mode');
            this.delayed_hide();
        }

        return this._super.apply(this, arguments);
    },
    edit: function () {
        this.$('button[data-action=edit]').prop('disabled', true);
        this.$el.addClass('editing_mode');
        editor.editor_bar = new editor.Class(this);
        editor.editor_bar.prependTo(document.body);
        $('.o_homepage_editor_welcome_message').remove();

        this.delayed_hide();
    },
    delayed_hide: function () {
        _.delay((function () {
            this.do_hide();
        }).bind(this), 800);
    },
});

/* ----- Customize Template ---- */

website.TopBarCustomize = Widget.extend({
    events: {
        'mousedown a.dropdown-toggle': 'load_menu',
        'click ul a[data-view-id]': 'do_customize',
    },
    start: function () {
        var self = this;
        this.$menu = self.$el.find('ul');
        this.view_name = $(document.documentElement).data('view-xmlid');
        if (!this.view_name) {
            this.$el.hide();
        }
        this.loaded = false;
    },
    load_menu: function () {
        var self = this;
        if(this.loaded) {
            return;
        }
        ajax.jsonRpc('/website/customize_template_get', 'call', {
            key: this.view_name,
        }).then(function (result) {
            _.each(result, function (item) {
                if (item.key === "website.debugger" && !window.location.search.match(/[&?]debug(&|$)/)) return;
                if (item.header) {
                    self.$menu.append('
' + item.name + '
');
                } else {
                    var $li = $('
', {role: 'presentation'})
                                .append($('', {href: '#', 'data-view-id': item.id, role: 'menuitem'})
                                    .append(qweb.render('web_editor.components.switch', {id: 'switch-' + item.id, label: item.name})));
                    $li.find('input').prop('checked', !!item.active);
                    self.$menu.append($li);
                }
            });
            self.loaded = true;
        });
    },
    do_customize: function (e) {
        e.preventDefault();
        var view_id = $(e.currentTarget).data('view-id');
        return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
            model: 'ir.ui.view',
            method: 'toggle',
            args: [[parseInt(view_id, 10)]],
            kwargs: {context: base.get_context()}
        }).then(function () {
            window.location.reload();
        });
    },
});
website.TopBar.include({
    start: function () {
        this.customize_menu = new website.TopBarCustomize();
        var def = this.customize_menu.attachTo($('#customize-menu'));
        return $.when(this._super(), def);
    }
});

/* ----- EDITOR: LINK & MEDIA ---- */

widget.LinkDialog.include({
    bind_data: function () {
        var self = this;
        var href = this.data.url;
        var last;

        this.$('#link-page').select2({
            minimumInputLength: 1,
            placeholder: _t("New or existing page"),
            query: function (q) {
                if (q.term === last) return;
                last = q.term;
                $.when(
                    self.page_exists(q.term),
                    self.fetch_pages(q.term)
                ).then(function (exists, results) {
                    var rs = _.map(results, function (r) {
                        return { id: r.loc, text: r.loc, };
                    });
                    if (!exists) {
                        rs.push({
                            create: true,
                            id: q.term,
                            text: _.str.sprintf(_t("Create page '%s'"), q.term),
                        });
                    }
                    q.callback({
                        more: false,
                        results: rs
                    });
                }, function () {
                    q.callback({more: false, results: []});
                });
            },
        });

        if (href) {
            this.page_exists(href).then(function (exist) {
                if (exist) {
                    self.$('#link-page').select2('data', {'id': href, 'text': href}).change();
                } else {
                    self.$('input.url').val(href).change();
                    self.$('input.window-new').closest("div").show();
                }
            });
        }
        return this._super();
    },
    get_data_buy_url: function (def, $e, isNewWindow, label, classes, test) {
        var val = $e.val();
        if (val && val.length && $e.hasClass('page')) {
            var data = $e.select2('data');
            if (!data.create || test) {
                def.resolve(data.id, isNewWindow, label || data.text, classes);
            } else {
                // Create the page, get the URL back
                $.get(_.str.sprintf(
                        '/website/add/%s?noredirect=1', encodeURI(data.id)))
                    .then(function (response) {
                        def.resolve(response, isNewWindow, label, classes);
                    });
            }
        } else {
            return this._super.apply(this, arguments);
        }
    },
    changed: function (e) {
        this.$('.url-source').filter(':input').not($(e.target)).val('')
                .filter(function () { return !!$(this).data('select2'); })
                .select2('data', null);
        this._super(e);
    },
    call: function (method, args, kwargs) {
        var self = this;
        var req = method + '_req';
        if (this[req]) { this[req].abort(); }
        return this[req] = ajax.jsonRpc('/web/dataset/call_kw', 'call', {
            model: 'website',
            method: method,
            args: args,
            kwargs: kwargs,
        }).always(function () {
            self[req] = null;
        });
    },
    page_exists: function (term) {
        return this.call('page_exists', [null, term], {
            context: base.get_context(),
        });
    },
    fetch_pages: function (term) {
        return this.call('search_pages', [null, term], {
            limit: 9,
            context: base.get_context(),
        });
    },
});

/**
 * Display a welcome message on the homepage when it is empty and that the user is connected.
 */
base.ready().then(function () {
    if (location.search.indexOf("enable_editor") < 0 && $(".editor_enable").length === 0) {
        var $wrap = $("#wrapwrap.homepage #wrap");
        if ($wrap.length && $wrap.html().trim() === "") {
            var $welcome_message = $(qweb.render("website.homepage_editor_welcome_message"));
            $welcome_message.css("height", $wrap.parent("main").height() - ($wrap.outerHeight(true) - $wrap.height()));
            $wrap.empty().append($welcome_message);
        }
    }
});

});
<|endoftext|>


<commit_before>// This class will encapsulate the grapher
function grapher() {

	this.scr = new screen();
	this.axes    = null;
	this.grid_dl = null;
	this.gl			 = null;
	this.wall		 = null;

	this.start   = null;
	this.moving  = false;

	// A framerate timer
	this.framerate	= null;
	this.framecount = 0;

	this.userClickFunction    = null;
	this.userKeyboardFunction = null;

	this.primitives = new Array();
	this.parameters = new Array();

	this.getContext = function() {
		var canvas = document.getElementById("glot");

		/* It seems there's not a lot of uniformly-accepted strings for
		 * fetching the context, and so we will try severl likely ones,
		 * and bail out when we find one.
		 */
		var strings = ["experimental-webgl", "moz-webgl", "webkit-3d", "webgl"];

		for (var i = 0; i < strings.length; ++i) {
			try {
				if (!this.gl) {
					this.gl = canvas.getContext(strings[i]);
				} else {
					break;
				}
			} catch (e) { }
		}

		return this.gl;
	}

	/* Where sx and sy are the screen x and y coordinates, this returns
	 * a point corresponding to world space at those screen coordinates.
	 */
	this.coordinates = function(sx, sy) {
		var point = new Array();
		point["x"] = this.scr.minx + (this.scr.maxx - this.scr.minx) * (sx / this.scr.width);
		point["y"] = this.scr.maxy + (this.scr.maxy + this.scr.miny) * (sy / this.scr.height);
		return point;
	}

	/* The mouse-click handler
	 */
	this.mousedown = function(x, y) {
		this.start = this.coordinates(x, y);
		this.moving = true;
	}

	/* And the mouse-up handler
	 */
	this.mouseup = function(x, y) {
		try {
			var end = this.coordinates(x, y);

			var dx = this.start["x"] - end["x"];
			var dy = this.start["y"] - end["y"];

			if (dx != 0 || dy != 0) {
				this.scr.minx -= dx;
				this.scr.maxx -= dx;
				this.scr.miny -= dy;
				this.scr.maxy -= dy;
				this.refresh_dls();
			}
			this.moving = false;

			if (this.userClickFunction) {
				this.userClickFunction(end.x, end.y);
			}

		} catch (e) {}
	}

	/* The mouse-movement handler
	 */
	this.mousemove = function(x, y) {
		if (this.moving) {
			var end = this.coordinates(x, y);

			var dx = this.start["x"] - end["x"];
			var dy = this.start["y"] - end["y"];

			if (dx != 0 || dy != 0) {
				this.gl.projectionMatrix = new CanvasMatrix4();
				this.gl.projectionMatrix.ortho(this.scr.minx + dx, this.scr.maxx + dx, this.scr.miny + dy, this.scr.maxy + dy, -10, 0);
			}
		}
	}

	/* The keyboard handler
	 */
	this.keyboard = function(key) {
		this.gl.console.log("Key (" + key + ") pressed.");
		if (key == 189) {
			this.zoom(1.15);
		} else if (key == 187) {
			this.zoom(1.0 / 1.15);
		}
	}

	this.zoom = function(scale) {

		var diff = (this.scr.maxx - this.scr.minx) * scale / 2.0;
		var midx = (this.scr.maxx + this.scr.minx) / 2.0;
		this.scr.minx = midx - diff;
		this.scr.maxx = midx + diff;

		diff = (this.scr.maxy - this.scr.miny) * scale / 2.0;
		midy = (this.scr.maxy + this.scr.miny) / 2.0;
		this.scr.miny = midy - diff;
		this.scr.maxy = midy + diff;

		midx *= 2;
		midy *= 2;

		/*
		this.gl.projectionMatrix = new CanvasMatrix4();
		this.gl.projectionMatrix.ortho(this.scr.minx - midx, this.scr.maxx - midx, this.scr.miny - midy, this.scr.maxy - midy, -10, 0);
		*/

		this.scr.recalc();

		if (scale > 1) {
			this.refresh_dls();
		}
	}

	this.setClickFunction = function(myfunction) {
		this.userClickFunction = myfunction;
	}

	this.initialize = function() {
		// First things first, get the WebGL rendering context.
		this.gl = this.getContext();

		var canvas = document.getElementById("glot");
		// This was included in the webkit examples, but my JavaScript
		// is weak, and I'm not quite sure what exactly this means.
		// Add a console
		this.gl.console = ("console" in window) ? window.console : { log: function() { } };

		// This is for easier callback handling
		canvas.glot = this;
		document.glot = this;

		/* Register various callback handlers */
		var f = function(event) { this.glot.mousedown(event.clientX, event.clientY) };
		canvas.onmousedown = f;

		f = function(event) { this.glot.mouseup(event.clientX, event.clientY) };
		document.onmouseup = f;

		f = function(event) { this.glot.mousemove(event.clientX, event.clientY) };
		document.onmousemove = f;

		f = function(event) { this.getElementById("glot").glot.keyboard(Number(event.keyCode)) };
		document.onkeydown = f;

		if (!this.gl) {
			alert("Can't find a WebGL context; is it enabled?");
			return null;
		}

		/* There is a slight, but unititive syntactic change between OpenGL
		 * and WebGL.	 glEnable becomes gl.enable, uncapitalizig the first
		 * character of the function call, and "gl." referes to the context
		 * provided by getContext()
		 */
		this.gl.enable(this.gl.LINE_SMOOTH);
		this.gl.enable(this.gl.POINT_SMOOTH);
		this.gl.enable(this.gl.BLEND);
		this.gl.enable(this.gl.VERTEX_ARRAY);
		this.gl.enable(this.gl.DEPTH_TEST);

		// Other smoothness and blending options
		this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
		this.gl.hint(this.gl.LINE_SMOOTH_HINT, this.gl.DONT_CARE);

		// Set the line width and point size
		this.gl.lineWidth(1.5);

		/* WebGL doesn't support this, it seems.  OpenGL ES 2.0 elliminated
		 * it to obviate the need for dedicated hardware for this task,
		 * which is a luxury in some sense.
		 *
		 * gl.pointSize(7);
		 */

		// Default color is white
		this.gl.clearColor(1.0, 1.0, 1.0, 1.0);

		/*
		 * WARNING! Some primitives depend on screen having the properly-
		 * filled values in screen for determination of vertex positions.
		 * Thus, it is CRITICAL that this be dynamically queried at run-
		 * time so that this data can be accurate.
		 */
		this.scr.width = this.scr.height = 500;

		this.framerate = new stopwatch();
		this.framerate.start();
		this.framecount = 0;

		this.wall = new stopwatch();
		this.wall.start();

		// Determine the axes and grid
		this.axes = new axes(this.gl, this.scr);
		//this.grid_dl = this.grid_dl_gen();

		// In the future, this ought to return some encoded value of success or failure.
		return 0;
	}

	this.grid_dl_gen = function() {
		var gl = this.getContext();
		var dl = gl.genLists(1);

		glNewList(dl, GL_COMPILE);

			glColor4d(0.0, 0.0, 0.0, 0.14);

			glBegin(GL_LINES);

				// How does typecasting work in JavaScript?
				for( var i = this.scr.miny; i <= this.scr.maxy; ++i) {
					glVertex3d(this.scr.minx, i, 1);
					glVertex3d(this.scr.maxx, i, 1);
				}

				for( var i = this.scr.minx; i <= this.scr.maxx; ++i) {
					glVertex3d(i, this.scr.miny, 1);
					glVertex3d(i, this.scr.maxy, 1);
				}

			glEnd();

		glEndList();

		return dl;
	}

	this.display = function() {

		this.reshape();
		this.scr.recalc();

		var gl = this.gl;

		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

		var program				 = null;
		var mvMat_location = null;
		var prMat_location = null;
		var time_location	 = null;
		var param_loc      = null;

		this.scr.time = this.wall.time();

		for (var i in this.primitives) {
			//*
			program = this.primitives[i].program;
			gl.useProgram(program);
			this.scr.set_uniforms(gl, program);
			//*/

			//*
			for (var j in this.parameters) {
				param_loc = gl.getUniformLocation(program, j);
				gl.uniform1f(param_loc, this.parameters[j]);
			}
			//*/

			this.primitives[i].draw(this.scr);
		}

		// Draw axes and grid
		/*
		program = this.axes.program;
		gl.useProgram(program);
		this.scr.set_uniforms(gl, program);
		this.axes.draw(this.scr);
		//*/

		gl.flush();

		this.framecount = this.framecount + 1;
		if (this.framecount == 150) {
			document.getElementById("framerate").innerHTML = "Framerate: " + 150 / this.framerate.time();
			this.framecount = 0;
			this.framerate = new stopwatch();
			this.framerate.start();
		}

		gl.finish();
	}

	this.refresh_dls = function() {
		for (var i = 0; i < this.primitives.length; ++i) {
			this.primitives[i].refresh(this.scr);
		}
		this.axes.refresh(this.scr);
		//this.grid_dl = grid_dl_gen();
	}

	this.reshape = function() {
		var canvas = document.getElementById("glot");
		var context = this.getContext();

		var w = canvas.clientWidth;
		var h = canvas.clientHeight;

		/* If the width and height of the resized canvas are already
		 * the stored sizes, return and do nothing.
		 */
		if (w == this.scr.width && h == this.scr.height) {
			return;
		}

		context.viewport(0, 0, w, h);

		/** Determine the new max x and y based on the
			* current scale.	This does not shrink or expand
			* the plot - only changes what's visible.
			*/
		this.scr.maxx = this.scr.minx + (this.scr.maxx - this.scr.minx) * w / this.scr.width;
		this.scr.maxy = this.scr.miny + (this.scr.maxy - this.scr.miny) * h / this.scr.height;

		var xw = this.scr.maxx - this.scr.minx;
		var yh = this.scr.maxy - this.scr.miny;

		this.scr.recalc();

		// Re-calculate the draw lists if we've expanded the view
		if (w > this.scr.width || h > this.scr.height) {
			this.refresh_dls();
		}

		this.scr.width = w;
		this.scr.height = h;

		//glutPostRedisplay();
	}

	this.add = function(primitive) {
		this.primitives.push(primitive);
		primitive.initialize(this.gl, this.scr, this.parameters);
	}

	this.set = function(parameter, value) {
		this.parameters[parameter] = value;
	}

	this.get = function(parameter) {
		return this.parameters[parameter];
	}

	this.run = function() {
		window.glot = this;
		window.setInterval(function() { this.glot.display(); }, 10);
	}

	this.initialize();
}<commit_msg>Corrected the screen width and height initialization.  It turns out, this was to blame for the screen zooming out to initialize craziness.<commit_after>// This class will encapsulate the grapher
function grapher() {

	this.scr = new screen();
	this.axes    = null;
	this.grid_dl = null;
	this.gl			 = null;
	this.wall		 = null;

	this.start   = null;
	this.moving  = false;

	// A framerate timer
	this.framerate	= null;
	this.framecount = 0;

	this.userClickFunction    = null;
	this.userKeyboardFunction = null;

	this.primitives = new Array();
	this.parameters = new Array();

	this.getContext = function() {
		var canvas = document.getElementById("glot");

		/* It seems there's not a lot of uniformly-accepted strings for
		 * fetching the context, and so we will try severl likely ones,
		 * and bail out when we find one.
		 */
		var strings = ["experimental-webgl", "moz-webgl", "webkit-3d", "webgl"];

		for (var i = 0; i < strings.length; ++i) {
			try {
				if (!this.gl) {
					this.gl = canvas.getContext(strings[i]);
				} else {
					break;
				}
			} catch (e) { }
		}

		return this.gl;
	}

	/* Where sx and sy are the screen x and y coordinates, this returns
	 * a point corresponding to world space at those screen coordinates.
	 */
	this.coordinates = function(sx, sy) {
		var point = new Array();
		point["x"] = this.scr.minx + (this.scr.maxx - this.scr.minx) * (sx / this.scr.width);
		point["y"] = this.scr.maxy + (this.scr.maxy + this.scr.miny) * (sy / this.scr.height);
		return point;
	}

	/* The mouse-click handler
	 */
	this.mousedown = function(x, y) {
		this.start = this.coordinates(x, y);
		this.moving = true;
	}

	/* And the mouse-up handler
	 */
	this.mouseup = function(x, y) {
		try {
			var end = this.coordinates(x, y);

			var dx = this.start["x"] - end["x"];
			var dy = this.start["y"] - end["y"];

			if (dx != 0 || dy != 0) {
				this.scr.minx -= dx;
				this.scr.maxx -= dx;
				this.scr.miny -= dy;
				this.scr.maxy -= dy;
				this.refresh_dls();
			}
			this.moving = false;

			if (this.userClickFunction) {
				this.userClickFunction(end.x, end.y);
			}

		} catch (e) {}
	}

	/* The mouse-movement handler
	 */
	this.mousemove = function(x, y) {
		if (this.moving) {
			var end = this.coordinates(x, y);

			var dx = this.start["x"] - end["x"];
			var dy = this.start["y"] - end["y"];

			if (dx != 0 || dy != 0) {
				this.gl.projectionMatrix = new CanvasMatrix4();
				this.gl.projectionMatrix.ortho(this.scr.minx + dx, this.scr.maxx + dx, this.scr.miny + dy, this.scr.maxy + dy, -10, 0);
			}
		}
	}

	/* The keyboard handler
	 */
	this.keyboard = function(key) {
		this.gl.console.log("Key (" + key + ") pressed.");
		if (key == 189) {
			this.zoom(1.15);
		} else if (key == 187) {
			this.zoom(1.0 / 1.15);
		}
	}

	this.zoom = function(scale) {

		var diff = (this.scr.maxx - this.scr.minx) * scale / 2.0;
		var midx = (this.scr.maxx + this.scr.minx) / 2.0;
		this.scr.minx = midx - diff;
		this.scr.maxx = midx + diff;

		diff = (this.scr.maxy - this.scr.miny) * scale / 2.0;
		midy = (this.scr.maxy + this.scr.miny) / 2.0;
		this.scr.miny = midy - diff;
		this.scr.maxy = midy + diff;

		midx *= 2;
		midy *= 2;

		/*
		this.gl.projectionMatrix = new CanvasMatrix4();
		this.gl.projectionMatrix.ortho(this.scr.minx - midx, this.scr.maxx - midx, this.scr.miny - midy, this.scr.maxy - midy, -10, 0);
		*/

		this.scr.recalc();

		if (scale > 1) {
			this.refresh_dls();
		}
	}

	this.setClickFunction = function(myfunction) {
		this.userClickFunction = myfunction;
	}

	this.initialize = function() {
		// First things first, get the WebGL rendering context.
		this.gl = this.getContext();

		var canvas = document.getElementById("glot");

		/* Initialize the screen's stored width and height */
		this.scr.width  = canvas.clientWidth;
		this.scr.height = canvas.clientHeight;

		// This was included in the webkit examples, but my JavaScript
		// is weak, and I'm not quite sure what exactly this means.
		// Add a console
		this.gl.console = ("console" in window) ? window.console : { log: function() { } };

		// This is for easier callback handling
		canvas.glot = this;
		document.glot = this;

		/* Register various callback handlers */
		var f = function(event) { this.glot.mousedown(event.clientX, event.clientY) };
		canvas.onmousedown = f;

		f = function(event) { this.glot.mouseup(event.clientX, event.clientY) };
		document.onmouseup = f;

		f = function(event) { this.glot.mousemove(event.clientX, event.clientY) };
		document.onmousemove = f;

		f = function(event) { this.getElementById("glot").glot.keyboard(Number(event.keyCode)) };
		document.onkeydown = f;

		if (!this.gl) {
			alert("Can't find a WebGL context; is it enabled?");
			return null;
		}

		/* There is a slight, but unititive syntactic change between OpenGL
		 * and WebGL.	 glEnable becomes gl.enable, uncapitalizig the first
		 * character of the function call, and "gl." referes to the context
		 * provided by getContext()
		 */
		this.gl.enable(this.gl.LINE_SMOOTH);
		this.gl.enable(this.gl.POINT_SMOOTH);
		this.gl.enable(this.gl.BLEND);
		this.gl.enable(this.gl.VERTEX_ARRAY);
		this.gl.enable(this.gl.DEPTH_TEST);

		// Other smoothness and blending options
		this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
		this.gl.hint(this.gl.LINE_SMOOTH_HINT, this.gl.DONT_CARE);

		// Set the line width and point size
		this.gl.lineWidth(1.5);

		/* WebGL doesn't support this, it seems.  OpenGL ES 2.0 elliminated
		 * it to obviate the need for dedicated hardware for this task,
		 * which is a luxury in some sense.
		 *
		 * gl.pointSize(7);
		 */

		// Default color is white
		this.gl.clearColor(1.0, 1.0, 1.0, 1.0);

		this.framerate = new stopwatch();
		this.framerate.start();
		this.framecount = 0;

		this.wall = new stopwatch();
		this.wall.start();

		// Determine the axes and grid
		this.axes = new axes(this.gl, this.scr);
		//this.grid_dl = this.grid_dl_gen();

		// In the future, this ought to return some encoded value of success or failure.
		return 0;
	}

	this.grid_dl_gen = function() {
		var gl = this.getContext();
		var dl = gl.genLists(1);

		glNewList(dl, GL_COMPILE);

			glColor4d(0.0, 0.0, 0.0, 0.14);

			glBegin(GL_LINES);

				// How does typecasting work in JavaScript?
				for( var i = this.scr.miny; i <= this.scr.maxy; ++i) {
					glVertex3d(this.scr.minx, i, 1);
					glVertex3d(this.scr.maxx, i, 1);
				}

				for( var i = this.scr.minx; i <= this.scr.maxx; ++i) {
					glVertex3d(i, this.scr.miny, 1);
					glVertex3d(i, this.scr.maxy, 1);
				}

			glEnd();

		glEndList();

		return dl;
	}

	this.display = function() {

		this.reshape();
		this.scr.recalc();

		var gl = this.gl;

		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

		var program				 = null;
		var mvMat_location = null;
		var prMat_location = null;
		var time_location	 = null;
		var param_loc      = null;

		this.scr.time = this.wall.time();

		for (var i in this.primitives) {
			//*
			program = this.primitives[i].program;
			gl.useProgram(program);
			this.scr.set_uniforms(gl, program);
			//*/

			//*
			for (var j in this.parameters) {
				param_loc = gl.getUniformLocation(program, j);
				gl.uniform1f(param_loc, this.parameters[j]);
			}
			//*/

			this.primitives[i].draw(this.scr);
		}

		// Draw axes and grid
		/*
		program = this.axes.program;
		gl.useProgram(program);
		this.scr.set_uniforms(gl, program);
		this.axes.draw(this.scr);
		//*/

		gl.flush();

		this.framecount = this.framecount + 1;
		if (this.framecount == 150) {
			document.getElementById("framerate").innerHTML = "Framerate: " + 150 / this.framerate.time();
			this.framecount = 0;
			this.framerate = new stopwatch();
			this.framerate.start();
		}

		gl.finish();
	}

	this.refresh_dls = function() {
		for (var i = 0; i < this.primitives.length; ++i) {
			this.primitives[i].refresh(this.scr);
		}
		this.axes.refresh(this.scr);
		//this.grid_dl = grid_dl_gen();
	}

	this.reshape = function() {
		var canvas = document.getElementById("glot");
		var context = this.getContext();

		var w = canvas.clientWidth;
		var h = canvas.clientHeight;

		/* If the width and height of the resized canvas are already
		 * the stored sizes, return and do nothing.
		 */
		if (w == this.scr.width && h == this.scr.height) {
			return;
		}

		context.viewport(0, 0, w, h);

		/** Determine the new max x and y based on the
			* current scale.	This does not shrink or expand
			* the plot - only changes what's visible.
			*/
		this.scr.maxx = this.scr.minx + (this.scr.maxx - this.scr.minx) * w / this.scr.width;
		this.scr.maxy = this.scr.miny + (this.scr.maxy - this.scr.miny) * h / this.scr.height;

		var xw = this.scr.maxx - this.scr.minx;
		var yh = this.scr.maxy - this.scr.miny;

		this.scr.recalc();

		// Re-calculate the draw lists if we've expanded the view
		if (w > this.scr.width || h > this.scr.height) {
			this.refresh_dls();
		}

		this.scr.width = w;
		this.scr.height = h;

		//glutPostRedisplay();
	}

	this.add = function(primitive) {
		this.primitives.push(primitive);
		primitive.initialize(this.gl, this.scr, this.parameters);
	}

	this.set = function(parameter, value) {
		this.parameters[parameter] = value;
	}

	this.get = function(parameter) {
		return this.parameters[parameter];
	}

	this.run = function() {
		window.glot = this;
		window.setInterval(function() { this.glot.display(); }, 10);
	}

	this.initialize();
}<|endoftext|>


<commit_before>'use strict'

const { resolve } = require('path')
const HandlerRunner = require('./handler-runner/index.js')
const LambdaContext = require('./LambdaContext.js')
const serverlessLog = require('./serverlessLog.js')
const {
  DEFAULT_LAMBDA_MEMORY_SIZE,
  DEFAULT_LAMBDA_RUNTIME,
  DEFAULT_LAMBDA_TIMEOUT,
  supportedRuntimes,
} = require('./config/index.js')
const { createUniqueId, splitHandlerPathAndName } = require('./utils/index.js')

const { now } = Date

module.exports = class LambdaFunction {
  constructor(functionName, functionObj, provider, config, options) {
    // TEMP options.location, for compatibility with serverless-webpack:
    // https://github.com/dherault/serverless-offline/issues/787
    // TODO FIXME look into better way to work with serverless-webpack
    const servicePath = resolve(config.servicePath, options.location || '')
    const { /* servicePath, */ serverlessPath } = config

    const { name, handler } = functionObj
    const [handlerPath, handlerName] = splitHandlerPathAndName(handler)

    const memorySize =
      functionObj.memorySize ||
      provider.memorySize ||
      DEFAULT_LAMBDA_MEMORY_SIZE

    const runtime =
      functionObj.runtime || provider.runtime || DEFAULT_LAMBDA_RUNTIME

    const timeout =
      (functionObj.timeout || provider.timeout || DEFAULT_LAMBDA_TIMEOUT) * 1000

    // TEMP
    const funOptions = {
      functionName,
      handlerName,
      handlerPath: resolve(servicePath, handlerPath),
      runtime,
      serverlessPath,
      servicePath,
    }

    this._awsRequestId = null
    this._executionTimeEnded = null
    this._executionTimeStarted = null
    this._executionTimeout = null
    this._functionName = functionName

    const env = this._getEnv(
      provider.environment,
      functionObj.environment,
      handler,
    )

    this._handlerRunner = new HandlerRunner(
      funOptions,
      options,
      env,
      this._stage,
    )
    this._lambdaName = name
    this._memorySize = memorySize
    this._region = provider.region
    this._runtime = runtime
    this._serverlessPath = serverlessPath
    this._servicePath = servicePath
    this._stage = provider.stage
    this._timeout = timeout

    this._verifySupportedRuntime()
  }

  _startExecutionTimer() {
    this._executionTimeStarted = now()
    this._executionTimeout = this._executionTimeStarted + this._timeout * 1000
  }

  _stopExecutionTimer() {
    this._executionTimeEnded = now()
  }

  _verifySupportedRuntime() {
    // print message but keep working (don't error out or exit process)
    if (!supportedRuntimes.has(this._runtime)) {
      // this.printBlankLine(); // TODO
      console.log('')
      serverlessLog(
        `Warning: found unsupported runtime '${this._runtime}' for function '${this._functionName}'`,
      )
    }
  }

  // based on:
  // https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/invokeLocal/index.js#L108
  _getAwsEnvVars() {
    return {
      AWS_DEFAULT_REGION: this._region,
      AWS_LAMBDA_FUNCTION_MEMORY_SIZE: this._memorySize,
      AWS_LAMBDA_FUNCTION_NAME: this._lambdaName,
      AWS_LAMBDA_FUNCTION_VERSION: '$LATEST',
      // https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/lib/naming.js#L123
      AWS_LAMBDA_LOG_GROUP_NAME: `/aws/lambda/${this._lambdaName}`,
      AWS_LAMBDA_LOG_STREAM_NAME:
        '2016/12/02/[$LATEST]f77ff5e4026c45bda9a9ebcec6bc9cad',
      AWS_REGION: this._region,
      LANG: 'en_US.UTF-8',
      LAMBDA_RUNTIME_DIR: '/var/runtime',
      LAMBDA_TASK_ROOT: '/var/task',
      LD_LIBRARY_PATH:
        '/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib',
      NODE_PATH: '/var/runtime:/var/task:/var/runtime/node_modules',
    }
  }

  _getEnv(providerEnv, functionObjEnv, handler) {
    return {
      ...this._getAwsEnvVars(),
      ...providerEnv,
      ...functionObjEnv,
      _HANDLER: handler, // TODO is this available in AWS?
    }
  }

  addEvent(event) {
    this._event = event
  }

  getExecutionTimeInMillis() {
    return this._executionTimeEnded - this._executionTimeStarted
  }

  getAwsRequestId() {
    return this._awsRequestId
  }

  // () => Promise<void>
  cleanup() {
    // TODO console.log('lambda cleanup')
    return this._handlerRunner.cleanup()
  }

  async runHandler() {
    this._awsRequestId = createUniqueId()

    const lambdaContext = new LambdaContext({
      awsRequestId: this._awsRequestId,
      getRemainingTimeInMillis: () => {
        const time = this._executionTimeout - now()

        // just return 0 for now if we are beyond alotted time (timeout)
        return time > 0 ? time : 0
      },
      lambdaName: this._lambdaName,
      memorySize: this._memorySize,
    })

    let callback

    const callbackCalled = new Promise((resolve, reject) => {
      callback = (err, data) => {
        if (err) {
          reject(err)
        }
        resolve(data)
      }

      lambdaContext.once('contextCalled', callback)
    })

    const context = lambdaContext.create()

    this._startExecutionTimer()

    let result

    // execute (run) handler
    try {
      result = this._handlerRunner.run(this._event, context, callback)
    } catch (err) {
      // this only executes when we have an exception caused by synchronous code
      // TODO logging
      console.log(err)
      throw new Error(`Uncaught error in '${this._functionName}' handler.`)
    }

    // // not a Promise, which is not supported by aws
    // if (result == null || typeof result.then !== 'function') {
    //   throw new Error(`Synchronous function execution is not supported.`);
    // }

    const callbacks = [callbackCalled]

    // Promise was returned
    if (result != null && typeof result.then === 'function') {
      callbacks.push(result)
    }

    let callbackResult

    try {
      callbackResult = await Promise.race(callbacks)
    } catch (err) {
      // TODO logging
      console.log(err)
      throw err
    }

    this._stopExecutionTimer()

    return callbackResult
  }
}
<commit_msg>Fix env population (some items missings)<commit_after>'use strict'

const { resolve } = require('path')
const HandlerRunner = require('./handler-runner/index.js')
const LambdaContext = require('./LambdaContext.js')
const serverlessLog = require('./serverlessLog.js')
const {
  DEFAULT_LAMBDA_MEMORY_SIZE,
  DEFAULT_LAMBDA_RUNTIME,
  DEFAULT_LAMBDA_TIMEOUT,
  supportedRuntimes,
} = require('./config/index.js')
const { createUniqueId, splitHandlerPathAndName } = require('./utils/index.js')

const { now } = Date

module.exports = class LambdaFunction {
  constructor(functionName, functionObj, provider, config, options) {
    // TEMP options.location, for compatibility with serverless-webpack:
    // https://github.com/dherault/serverless-offline/issues/787
    // TODO FIXME look into better way to work with serverless-webpack
    const servicePath = resolve(config.servicePath, options.location || '')
    const { /* servicePath, */ serverlessPath } = config

    const { name, handler } = functionObj
    const [handlerPath, handlerName] = splitHandlerPathAndName(handler)

    const memorySize =
      functionObj.memorySize ||
      provider.memorySize ||
      DEFAULT_LAMBDA_MEMORY_SIZE

    const runtime =
      functionObj.runtime || provider.runtime || DEFAULT_LAMBDA_RUNTIME

    const timeout =
      (functionObj.timeout || provider.timeout || DEFAULT_LAMBDA_TIMEOUT) * 1000

    this._awsRequestId = null
    this._executionTimeEnded = null
    this._executionTimeStarted = null
    this._executionTimeout = null
    this._functionName = functionName
    this._lambdaName = name
    this._memorySize = memorySize
    this._region = provider.region
    this._runtime = runtime
    this._serverlessPath = serverlessPath
    this._servicePath = servicePath
    this._stage = provider.stage
    this._timeout = timeout

    this._verifySupportedRuntime()

    const env = this._getEnv(
      provider.environment,
      functionObj.environment,
      handler,
    )

    // TEMP
    const funOptions = {
      functionName,
      handlerName,
      handlerPath: resolve(servicePath, handlerPath),
      runtime,
      serverlessPath,
      servicePath,
    }

    this._handlerRunner = new HandlerRunner(
      funOptions,
      options,
      env,
      this._stage,
    )
  }

  _startExecutionTimer() {
    this._executionTimeStarted = now()
    this._executionTimeout = this._executionTimeStarted + this._timeout * 1000
  }

  _stopExecutionTimer() {
    this._executionTimeEnded = now()
  }

  _verifySupportedRuntime() {
    // print message but keep working (don't error out or exit process)
    if (!supportedRuntimes.has(this._runtime)) {
      // this.printBlankLine(); // TODO
      console.log('')
      serverlessLog(
        `Warning: found unsupported runtime '${this._runtime}' for function '${this._functionName}'`,
      )
    }
  }

  // based on:
  // https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/invokeLocal/index.js#L108
  _getAwsEnvVars() {
    return {
      AWS_DEFAULT_REGION: this._region,
      AWS_LAMBDA_FUNCTION_MEMORY_SIZE: this._memorySize,
      AWS_LAMBDA_FUNCTION_NAME: this._lambdaName,
      AWS_LAMBDA_FUNCTION_VERSION: '$LATEST',
      // https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/lib/naming.js#L123
      AWS_LAMBDA_LOG_GROUP_NAME: `/aws/lambda/${this._lambdaName}`,
      AWS_LAMBDA_LOG_STREAM_NAME:
        '2016/12/02/[$LATEST]f77ff5e4026c45bda9a9ebcec6bc9cad',
      AWS_REGION: this._region,
      LANG: 'en_US.UTF-8',
      LAMBDA_RUNTIME_DIR: '/var/runtime',
      LAMBDA_TASK_ROOT: '/var/task',
      LD_LIBRARY_PATH:
        '/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib',
      NODE_PATH: '/var/runtime:/var/task:/var/runtime/node_modules',
    }
  }

  _getEnv(providerEnv, functionObjEnv, handler) {
    return {
      ...this._getAwsEnvVars(),
      ...providerEnv,
      ...functionObjEnv,
      _HANDLER: handler, // TODO is this available in AWS?
    }
  }

  addEvent(event) {
    this._event = event
  }

  getExecutionTimeInMillis() {
    return this._executionTimeEnded - this._executionTimeStarted
  }

  getAwsRequestId() {
    return this._awsRequestId
  }

  // () => Promise<void>
  cleanup() {
    // TODO console.log('lambda cleanup')
    return this._handlerRunner.cleanup()
  }

  async runHandler() {
    this._awsRequestId = createUniqueId()

    const lambdaContext = new LambdaContext({
      awsRequestId: this._awsRequestId,
      getRemainingTimeInMillis: () => {
        const time = this._executionTimeout - now()

        // just return 0 for now if we are beyond alotted time (timeout)
        return time > 0 ? time : 0
      },
      lambdaName: this._lambdaName,
      memorySize: this._memorySize,
    })

    let callback

    const callbackCalled = new Promise((resolve, reject) => {
      callback = (err, data) => {
        if (err) {
          reject(err)
        }
        resolve(data)
      }

      lambdaContext.once('contextCalled', callback)
    })

    const context = lambdaContext.create()

    this._startExecutionTimer()

    let result

    // execute (run) handler
    try {
      result = this._handlerRunner.run(this._event, context, callback)
    } catch (err) {
      // this only executes when we have an exception caused by synchronous code
      // TODO logging
      console.log(err)
      throw new Error(`Uncaught error in '${this._functionName}' handler.`)
    }

    // // not a Promise, which is not supported by aws
    // if (result == null || typeof result.then !== 'function') {
    //   throw new Error(`Synchronous function execution is not supported.`);
    // }

    const callbacks = [callbackCalled]

    // Promise was returned
    if (result != null && typeof result.then === 'function') {
      callbacks.push(result)
    }

    let callbackResult

    try {
      callbackResult = await Promise.race(callbacks)
    } catch (err) {
      // TODO logging
      console.log(err)
      throw err
    }

    this._stopExecutionTimer()

    return callbackResult
  }
}
<|endoftext|>


<commit_before>// https://gist.github.com/mojodna/1251812

var models = require("../../models");
var log = require('../utils/logger');
var toJson = require('../utils/to_json');
var async = require('async');

var airbrake = null;
if(process.env.AIRBRAKE_PROJECT_ID) {
  airbrake = require('../utils/airbrake');
}

var generatePostNotification = require('../engine/notifications/generate_post_notifications.js');
var generatePointNotification = require('../engine/notifications/generate_point_notifications.js');
var generateRecommendationEvent = require('../engine/recommendations/events_manager').generateRecommendationEvent;
var generatePostStatusChangeNotification = require('../engine/notifications/generate_post_status_change_notifications.js');

var ActivityWorker = function () {};

ActivityWorker.prototype.process = function (activityJson, callback) {
  var activity;
  log.info('Processing activity Started');
  async.series([
    function (seriesCallback) {
      models.AcActivity.find({
        where: { id: activityJson.id },
        include: [
          {
            model: models.User,
            attributes: ['id','notifications_settings','email','name','created_at'],
            required: false
          },
          {
            model: models.Domain,
            required: false
          },
          {
            model: models.Community,
            required: false
          },
          {
            model: models.Group,
            required: false
          },
          {
            model: models.Post,
            required: false
          },
          {
            model: models.Point,
            required: false,
            include: [
              {
                model: models.Post,
                required: false
              }
            ]
          }
        ]
      }).then(function (results) {
        if (results) {
          activity = results;
          seriesCallback();
        } else {
          seriesCallback('Activity not found');
        }
      }).catch(function (error) {
        seriesCallback(error);
      });
    },
    function (seriesCallback) {
      log.info('Processing Activity Started', {type: activity.type});
      try {
        switch (activity.type) {
          case "activity.user.invite":
            models.AcNotification.createNotificationFromActivity(activity.actor.user_id, activity, "notification.user.invite", "priority", 70, function (error) {
              log.info('Processing activity.user.invite Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.password.recovery":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.password.recovery", "priority", 100, function (error) {
              log.info('Processing activity.password.recovery Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.password.changed":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.password.changed", "priority", 100, function (error) {
              log.info('Processing activity.password.changed Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.system.generalUserNotification":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.generalUserNotification", "priority", 100, function (error) {
              log.info('Processing activity.system.generalUserNotification', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.report.content":
            models.AcNotification.createReportNotifications(activity.actor.user, activity, function (error) {
              log.info('Processing activity.report.content Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.bulk.status.update":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.bulk.status.update", "priority", 100, function (error) {
              log.info('Processing activity.bulk.status.update Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.post.new":
          case "activity.post.opposition.new":
          case "activity.post.endorsement.new":
            generatePostNotification(activity, activity.User, function (error) {
              if (error) {
                log.error('Processing activity.post.* Error', {type: activity.type, err: error});
                seriesCallback(error);
              } else {
                log.info('Processing activity.post.* Completed', {type: activity.type});
                seriesCallback();
              }
            });
            break;
          case "activity.point.new":
          case "activity.point.helpful.new":
          case "activity.point.unhelpful.new":
          case "activity.point.newsStory.new":
          case "activity.point.comment.new":
            generatePointNotification(activity, activity.User, function (error) {
              if (error) {
                log.error('Processing activity.point.* Completed', {type: activity.type, err: error});
                seriesCallback(error);
              } else {
                log.info('Processing activity.point.* Completed', {type: activity.type});
                seriesCallback();
              }
            });
            break;
          case "activity.post.status.change":
            if (activity.object && activity.object.bulkStatusUpdate) {
              log.info('Processing activity.post.status.change not creating notifications', {type: activity.type});
              seriesCallback();
            } else {
              generatePostStatusChangeNotification(activity, activity.User, function (error) {
                if (error) {
                  log.error('Processing activity.post.status.change Completed', {type: activity.type, err: error});
                  seriesCallback(error);
                } else {
                  log.info('Processing activity.post.status.change Completed', {type: activity.type});
                  seriesCallback();
                }
              });
            }
            break;
          default:
            seriesCallback();
        }
      } catch (error) {
        log.error("Processing Activity Error", {err: error});
        seriesCallback(error);
      }
    },
    function (seriesCallback) {
      generateRecommendationEvent(activity, seriesCallback);
    }
  ], function (error) {
    if (error) {
      log.error("Processing Activity Error", {err: error});
      if(airbrake) {
        airbrake.notify(error, function(airbrakeErr, url) {
          if (airbrakeErr) {
            log.error("AirBrake Error", { context: 'airbrake', err: airbrakeErr, errorStatus: 500 });
          }
          callback(error);
        });
      } else {
        callback(error);
      }
    } else {
      log.info('Processing Activity and Recommendation Completed', {type: activity.type});
      callback();
    }
  });
};

module.exports = new ActivityWorker();
<commit_msg>Fix for notification<commit_after>// https://gist.github.com/mojodna/1251812

var models = require("../../models");
var log = require('../utils/logger');
var toJson = require('../utils/to_json');
var async = require('async');

var airbrake = null;
if(process.env.AIRBRAKE_PROJECT_ID) {
  airbrake = require('../utils/airbrake');
}

var generatePostNotification = require('../engine/notifications/generate_post_notifications.js');
var generatePointNotification = require('../engine/notifications/generate_point_notifications.js');
var generateRecommendationEvent = require('../engine/recommendations/events_manager').generateRecommendationEvent;
var generatePostStatusChangeNotification = require('../engine/notifications/generate_post_status_change_notifications.js');

var ActivityWorker = function () {};

ActivityWorker.prototype.process = function (activityJson, callback) {
  var activity;
  log.info('Processing activity Started');
  async.series([
    function (seriesCallback) {
      models.AcActivity.find({
        where: { id: activityJson.id },
        include: [
          {
            model: models.User,
            attributes: ['id','notifications_settings','email','name','created_at'],
            required: false
          },
          {
            model: models.Domain,
            required: false
          },
          {
            model: models.Community,
            required: false
          },
          {
            model: models.Group,
            required: false
          },
          {
            model: models.Post,
            required: false
          },
          {
            model: models.Point,
            required: false,
            include: [
              {
                model: models.Post,
                required: false
              }
            ]
          }
        ]
      }).then(function (results) {
        if (results) {
          activity = results;
          seriesCallback();
        } else {
          seriesCallback('Activity not found');
        }
      }).catch(function (error) {
        seriesCallback(error);
      });
    },
    function (seriesCallback) {
      log.info('Processing Activity Started', {type: activity.type});
      try {
        switch (activity.type) {
          case "activity.user.invite":
            models.AcNotification.createNotificationFromActivity(activity.actor.user_id, activity, "notification.user.invite", "priority", 70, function (error) {
              log.info('Processing activity.user.invite Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.password.recovery":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.password.recovery", "priority", 100, function (error) {
              log.info('Processing activity.password.recovery Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.password.changed":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.password.changed", "priority", 100, function (error) {
              log.info('Processing activity.password.changed Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.system.generalUserNotification":
            models.AcNotification.createNotificationFromActivity(activity.actor.userId, activity, "notification.generalUserNotification", "priority", 100, function (error) {
              log.info('Processing activity.system.generalUserNotification', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.report.content":
            models.AcNotification.createReportNotifications(activity.actor.user, activity, function (error) {
              log.info('Processing activity.report.content Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.bulk.status.update":
            models.AcNotification.createNotificationFromActivity(activity.actor.user, activity, "notification.bulk.status.update", "priority", 100, function (error) {
              log.info('Processing activity.bulk.status.update Completed', {type: activity.type, err: error});
              seriesCallback(error);
            });
            break;
          case "activity.post.new":
          case "activity.post.opposition.new":
          case "activity.post.endorsement.new":
            generatePostNotification(activity, activity.User, function (error) {
              if (error) {
                log.error('Processing activity.post.* Error', {type: activity.type, err: error});
                seriesCallback(error);
              } else {
                log.info('Processing activity.post.* Completed', {type: activity.type});
                seriesCallback();
              }
            });
            break;
          case "activity.point.new":
          case "activity.point.helpful.new":
          case "activity.point.unhelpful.new":
          case "activity.point.newsStory.new":
          case "activity.point.comment.new":
            generatePointNotification(activity, activity.User, function (error) {
              if (error) {
                log.error('Processing activity.point.* Completed', {type: activity.type, err: error});
                seriesCallback(error);
              } else {
                log.info('Processing activity.point.* Completed', {type: activity.type});
                seriesCallback();
              }
            });
            break;
          case "activity.post.status.change":
            if (activity.object && activity.object.bulkStatusUpdate) {
              log.info('Processing activity.post.status.change not creating notifications', {type: activity.type});
              seriesCallback();
            } else {
              generatePostStatusChangeNotification(activity, activity.User, function (error) {
                if (error) {
                  log.error('Processing activity.post.status.change Completed', {type: activity.type, err: error});
                  seriesCallback(error);
                } else {
                  log.info('Processing activity.post.status.change Completed', {type: activity.type});
                  seriesCallback();
                }
              });
            }
            break;
          default:
            seriesCallback();
        }
      } catch (error) {
        log.error("Processing Activity Error", {err: error});
        seriesCallback(error);
      }
    },
    function (seriesCallback) {
      generateRecommendationEvent(activity, seriesCallback);
    }
  ], function (error) {
    if (error) {
      log.error("Processing Activity Error", {err: error});
      if(airbrake) {
        airbrake.notify(error, function(airbrakeErr, url) {
          if (airbrakeErr) {
            log.error("AirBrake Error", { context: 'airbrake', err: airbrakeErr, errorStatus: 500 });
          }
          callback(error);
        });
      } else {
        callback(error);
      }
    } else {
      log.info('Processing Activity and Recommendation Completed', {type: activity.type});
      callback();
    }
  });
};

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


<commit_before>function getParam(name) {
  return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
}

// set default amount based on param donation_amount in url
var name = 'donation_amount';
var da = getParam(name);
if (da > 0) {
  da = da.replace('.', '\\.');
  jQuery(".price-set-row input[data-amount="+da+"]").prop("checked", true).click();
}

//Show / hide other amount input
jQuery('.price-set-row input').on('change', function(e) {
  var $other = jQuery('.crm-container .crm-section.other_amount-section');
  var val = jQuery(this).val();
  if (val == 0) {
    $other.show();
  } else {
    $other.hide();
  }
});

/* Convert daily/weekly donations to monthly donations */

function isConvertedToMonthly() {
  return getParam('id') == 24;
}

function getMonthlyValue() {
  var $montlyInfo = jQuery('#monthlyInfo');
  var amount = jQuery('.price-set-row input').filter(':checked').attr('data-amount');
  if (amount) {
    amount = parseFloat(amount);
  } else {
    amount = parseFloat(jQuery('.other_amount-section input').val());
  }
  if (isNaN(amount)) {
    var monthlyValue = '';
  } else {
    var monthlyValue = (amount * 4.3).toFixed(2);
  }
  return monthlyValue;
}

function updateMonthlyValue() {
  var monthlyValue = getMonthlyValue();
  jQuery('#monthlyValue').text(monthlyValue);
}

if (isConvertedToMonthly()) {
  var $monthlyInfo = jQuery('

You will contribute €  per month

');
  jQuery('.other_amount-section').after($monthlyInfo);
  jQuery('.price-set-row input').on('change', function(e) {
    updateMonthlyValue();
  });
  jQuery('.other_amount-section input').on('keyup', function(e) {
    updateMonthlyValue();
  });
  updateMonthlyValue();

  jQuery('form#Main').on('submit', function(e) {
    jQuery('.other_amount-section input').val(getMonthlyValue());
    jQuery('.price-set-row input[value=0]').prop('checked', 'checked');
  });
}

/* Converting comma to dot in other amount field */
jQuery(".other_amount-content input[name*=price]").change(function(e) {
  jQuery(this).val(jQuery(this).val().replace(/,/g,"."));
});

/* IBAN magic */

var natFields = {
  ES: {
    'bank_code': "Bank code",
    'branch_code': "Branch code",
    'check_digits': "Check digits",
    'account': "Account number"
  },
  DE: {
    'bank_code': "Bank code",
    'account': "Account number"
  }
}

function isIBANConverted(formId) {
  var toConvert = ['19'];
  return toConvert.indexOf(formId) >= 0;
}

var switch_section = '

 <input id="SEPA_scheme" name="transfer_scheme" value="SEPA" type="radio" checked> SEPA <input id="National_scheme" name="transfer_scheme" value="national" type="radio"> National

';

var field_tpl = '

@@label@@*

<input size="34" maxlength="34" autocomplete="off" name="@@name@@" id="@@name@@" class="crm-form-text" type="text">

'

function addField(name, label) {
  var $iban = jQuery('.bank_account_number-section');
  var field = field_tpl.split('@@name@@').join(name);
  field = field.replace('@@label@@', label);
  $iban.before(field);
}

function replaceLetters(bban) {
  var value = '';
  var a = 'a'.charCodeAt(0) - 10;
  bban = bban.toLowerCase();
  for (var i = 0; i < bban.length; ++i) {
    var c = bban.charAt(i);
    var n = parseInt(c);
    if (isNaN(n)) n = bban.charCodeAt(i) - a;
    value = value + n;
  }
  return value;
}

function mod97(digits) {
  var value = 0;
  for (var i = 0; i < digits.length; ++i) {
    value = (10 * value + parseInt(digits.charAt(i))) % 97;
  }
  return value;
}

function getBBAN(country) {
  var bban = '';
  for (field_id in natFields[country]) {
    bban += jQuery('#' + field_id).val();
  }
  return bban;
}

function genIBAN(country) {
  var bban = getBBAN(country);
  var checkInput = replaceLetters(bban + country + '00');
  var checksum = (98 - mod97(checkInput)).toString();
  while (checksum.length < 2) checksum = '0' + checksum;
  return country + checksum + bban;
}

function enableNationalForm(country) {
  jQuery('.account_holder-section').before(switch_section);
  var fieldSelect = '';
  for (field_id in natFields[country]) {
    addField(field_id, natFields[country][field_id]);
    fieldSelect += '.' + field_id + '-section, ';
  }

  var $iban = jQuery('#bank_account_number');
  jQuery('input[name=transfer_scheme]').on('change', function (e) {
    jQuery(fieldSelect + '.bank_account_number-section, .bank_identification_number-section').toggle();
    $iban.focus();
  });

  jQuery('#bank_code, #branch_code, #check_digits, #account').on('change', function(e) {
    $iban.val(genIBAN(country));
  });
}

var formId = getParam('id');
if (isIBANConverted(formId)) {
  var country = 'DE';
  var $payProc = jQuery('input[name=payment_processor]');
  if (jQuery('.direct_debit_info-group').length) {
    enableNationalForm(country);
  } else {
    $payProc.on('change', function(e) {
      if ($payProc.filter(':checked').val() == '3') {
	enableNationalForm(country);
      }
    });
  }
}
<commit_msg>Adapt magic to germany<commit_after>function getParam(name) {
  return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
}

// set default amount based on param donation_amount in url
var name = 'donation_amount';
var da = getParam(name);
if (da > 0) {
  da = da.replace('.', '\\.');
  jQuery(".price-set-row input[data-amount="+da+"]").prop("checked", true).click();
}

//Show / hide other amount input
jQuery('.price-set-row input').on('change', function(e) {
  var $other = jQuery('.crm-container .crm-section.other_amount-section');
  var val = jQuery(this).val();
  if (val == 0) {
    $other.show();
  } else {
    $other.hide();
  }
});

/* Convert daily/weekly donations to monthly donations */

function isConvertedToMonthly() {
  return getParam('id') == 24;
}

function getMonthlyValue() {
  var $montlyInfo = jQuery('#monthlyInfo');
  var amount = jQuery('.price-set-row input').filter(':checked').attr('data-amount');
  if (amount) {
    amount = parseFloat(amount);
  } else {
    amount = parseFloat(jQuery('.other_amount-section input').val());
  }
  if (isNaN(amount)) {
    var monthlyValue = '';
  } else {
    var monthlyValue = (amount * 4.3).toFixed(2);
  }
  return monthlyValue;
}

function updateMonthlyValue() {
  var monthlyValue = getMonthlyValue();
  jQuery('#monthlyValue').text(monthlyValue);
}

if (isConvertedToMonthly()) {
  var $monthlyInfo = jQuery('

You will contribute €  per month

');
  jQuery('.other_amount-section').after($monthlyInfo);
  jQuery('.price-set-row input').on('change', function(e) {
    updateMonthlyValue();
  });
  jQuery('.other_amount-section input').on('keyup', function(e) {
    updateMonthlyValue();
  });
  updateMonthlyValue();

  jQuery('form#Main').on('submit', function(e) {
    jQuery('.other_amount-section input').val(getMonthlyValue());
    jQuery('.price-set-row input[value=0]').prop('checked', 'checked');
  });
}

/* Converting comma to dot in other amount field */
jQuery(".other_amount-content input[name*=price]").change(function(e) {
  jQuery(this).val(jQuery(this).val().replace(/,/g,"."));
});

/* IBAN magic */

var natFields = {
  ES: {
    'bank_code': "Bank code",
    'branch_code': "Branch code",
    'check_digits': "Check digits",
    'account': "Account number"
  },
  DE: {
    'bank_code': "Bank code",
    'account': "Account number"
  }
}

function isIBANConverted(formId) {
  var toConvert = ['19'];
  return toConvert.indexOf(formId) >= 0;
}

var switch_section = '

 <input id="SEPA_scheme" name="transfer_scheme" value="SEPA" type="radio" checked> SEPA <input id="National_scheme" name="transfer_scheme" value="national" type="radio"> National

';

var field_tpl = '

@@label@@*

<input size="34" maxlength="34" autocomplete="off" name="@@name@@" id="@@name@@" class="crm-form-text" type="text">

'

function addField(name, label) {
  var $iban = jQuery('.bank_account_number-section');
  var field = field_tpl.split('@@name@@').join(name);
  field = field.replace('@@label@@', label);
  $iban.before(field);
}

function replaceLetters(bban) {
  var value = '';
  var a = 'a'.charCodeAt(0) - 10;
  bban = bban.toLowerCase();
  for (var i = 0; i < bban.length; ++i) {
    var c = bban.charAt(i);
    var n = parseInt(c);
    if (isNaN(n)) n = bban.charCodeAt(i) - a;
    value = value + n;
  }
  return value;
}

function mod97(digits) {
  var value = 0;
  for (var i = 0; i < digits.length; ++i) {
    value = (10 * value + parseInt(digits.charAt(i))) % 97;
  }
  return value;
}

function getBBAN(country) {
  var bban = '';
  for (field_id in natFields[country]) {
    bban += jQuery('#' + field_id).val();
  }
  return bban;
}

function genIBAN(country) {
  var bban = getBBAN(country);
  var checkInput = replaceLetters(bban + country + '00');
  var checksum = (98 - mod97(checkInput)).toString();
  while (checksum.length < 2) checksum = '0' + checksum;
  return country + checksum + bban;
}

function enableNationalForm(country) {
  jQuery('.account_holder-section').before(switch_section);
  var fieldSelect = '';
  for (field_id in natFields[country]) {
    addField(field_id, natFields[country][field_id]);
    fieldSelect += '.' + field_id + '-section, ';
  }

  var $iban = jQuery('#bank_account_number');
  jQuery('input[name=transfer_scheme]').on('change', function (e) {
    jQuery(fieldSelect + '.bank_account_number-section, .bank_identification_number-section').toggle();
    $iban.click();
  });

  jQuery('#bank_code, #branch_code, #check_digits, #account').on('change', function(e) {
    $iban.val(genIBAN(country));
  });
}

var formId = getParam('id');
if (isIBANConverted(formId)) {
  var country = 'DE';
  var $payProc = jQuery('input[name=payment_processor]');
  if (jQuery('.direct_debit_info-group').length) {
    enableNationalForm(country);
  } else {
    $payProc.on('change', function(e) {
      if ($payProc.filter(':checked').val() == '3') {
	enableNationalForm(country);
      }
    });
  }
}
<|endoftext|>


<commit_before>(function(){
    var teleport;
    var portalDestination;
    var thisEntityID;

    function playSound() {
        var properties = Entities.getEntityProperties(thisEntityID, 'position');
        if (properties) {
            Audio.playSound(teleport, { position: properties.position, volume: 0.40, localOnly: true });
        }
    };

    this.preload = function(entityID) {
        thisEntityID = entityID;
        teleport = SoundCache.getSound("atp:/sounds/teleport.raw");

        var properties = Entities.getEntityProperties(entityID, 'userData');
        if (properties) {
            portalDestination = properties.userData;
            print("portal.js | The portal destination is " + portalDestination);
        }
    }

    this.enterEntity = function(entityID) {
        print("portal.js | enterEntity");

        var properties = Entities.getEntityProperties(entityID, 'userData'); // in case the userData/portalURL has changed
        if (properties) {
            portalDestination = properties.userData;

            print("portal.js | enterEntity() .... The portal destination is " + portalDestination);

            if (portalDestination.length > 0) {
                if (portalDestination[0] == '/') {
                    print("Teleporting to " + portalDestination);
                    Window.location = portalDestination;
                } else {
                    print("Teleporting to hifi://" + portalDestination);
                    Window.location = "hifi://" + portalDestination;
                }
            } else {
                location.goToEntry(); // going forward: no data means go to appropriate entry point
            }
        }
    };

    this.leaveEntity = function(entityID) {
        print("portal.js | leaveEntity");

        playSound();
    };
})
<commit_msg>Final merge pull request #4 from FlameSoulis/fix/teleporter<commit_after>(function () {
    var teleportSound;
    var portalDestination;
    var animationURL;
    var position;
    var canTeleport;

    function playSound(entityID) {
        print("playing teleport sound");
        if (teleportSound.downloaded) {
            if (!position) {
                getProps(entityID);
            }
            Audio.playSound(teleportSound, { position: position, volume: 0.40, localOnly: true });
        }
    }

    function getProps(entityID) {
        var properties = Entities.getEntityProperties(entityID);
        if (properties) {
            animationURL = properties.modelURL;
            position = properties.position;
            portalDestination = properties.userData;
        }
    }

    function isPositionInsideBox(position, boxProperties) {
        var localPosition = Vec3.multiplyQbyV(Quat.inverse(boxProperties.rotation),
            Vec3.subtract(MyAvatar.position, boxProperties.position));
        var halfDimensions = Vec3.multiply(boxProperties.dimensions, 0.5);
        return -halfDimensions.x <= localPosition.x &&
            halfDimensions.x >= localPosition.x &&
            -halfDimensions.y <= localPosition.y &&
            halfDimensions.y >= localPosition.y &&
            -halfDimensions.z <= localPosition.z &&
            halfDimensions.z >= localPosition.z;
    }

    this.preload = function (entityID) {
        print("loading teleport script");
        teleportSound = SoundCache.getSound("http://s3.amazonaws.com/hifi-public/birarda/teleport.raw");
        getProps(entityID);
        // check if we are already in the object
        canTeleport = !isPositionInsideBox(MyAvatar.position, Entities.getEntityProperties(entityID));
    };

    this.enterEntity = function (entityID) {
        // check if we should teleport
        if (canTeleport === false) {
            // if we have not passed enough time, do not teleport the user
            return;
        }
        // get latest props in case we changed the destination
        getProps(entityID);
        print("enterEntity() .... The portal destination is " + portalDestination);

        if (portalDestination.length > 0) {
            print("Teleporting to hifi://" + portalDestination);
            Window.location = "hifi://" + portalDestination;
        }

    };

    this.leaveEntity = function (entityID) {
        print("leaveEntity() called ....");
        if (!animationURL) {
            getProps(entityID);
        }
        Entities.editEntity(entityID, {
            animation: { url: animationURL, currentFrame: 1, running: false }
        });

        if (canTeleport === true) {
            // only play the sound if we can teleport
            playSound(entityID);
        }
        canTeleport = true;
    };

    this.hoverEnterEntity = function (entityID) {
        print("hoverEnterEntity() called ....");
        if (!animationURL) {
            getProps(entityID);
        }
        Entities.editEntity(entityID, {
            animation: { url: animationURL, fps: 24, firstFrame: 1, lastFrame: 25, currentFrame: 1, running: true, hold: true }
        });
    };

    this.unload = function () {
        print("unloading teleport script");
    };
});
<|endoftext|>


<commit_before>/*
 * L.TileLayer is used for standard xyz-numbered tile layers.
 */

L.TileLayer = L.Class.extend({
	includes: L.Mixin.Events,

	options: {
		minZoom: 0,
		maxZoom: 18,
		tileSize: 256,
		subdomains: 'abc',
		errorTileUrl: '',
		attribution: '',
		opacity: 1,
		scheme: 'xyz',
		continuousWorld: false,
		noWrap: false,

		unloadInvisibleTiles: L.Browser.mobile,
		updateWhenIdle: L.Browser.mobile
	},

	initialize: function(url, options) {
		L.Util.setOptions(this, options);

		this._url = url;

		if (typeof this.options.subdomains == 'string') {
			this.options.subdomains = this.options.subdomains.split('');
		}
	},

	onAdd: function(map, insertAtTheBottom) {
		this._map = map;
		this._insertAtTheBottom = insertAtTheBottom;

		// create a container div for tiles
		this._initContainer();

		// create an image to clone for tiles
		this._createTileProto();

		// set up events
		map.on('viewreset',
			function(e) {
				this._reset(e.hard);
			},
			this);

		if (this.options.updateWhenIdle) {
			map.on('moveend', this._update, this);
		} else {
			this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
			map.on('move', this._limitedUpdate, this);
		}

		this._reset();
		this._update();
	},

	onRemove: function(map) {
		this._map.getPanes().tilePane.removeChild(this._container);
		this._container = null;

		this._map.off('viewreset', this._reset, this);

		if (this.options.updateWhenIdle) {
			this._map.off('moveend', this._update, this);
		} else {
			this._map.off('move', this._limitedUpdate, this);
		}
	},

	getAttribution: function() {
		return this.options.attribution;
	},

	setOpacity: function(opacity) {
		this.options.opacity = opacity;

		this._setOpacity(opacity);

		// stupid webkit hack to force redrawing of tiles
		if (L.Browser.webkit) {
			for (i in this._tiles) {
				this._tiles[i].style.webkitTransform += ' translate(0,0)';
			}
		}
	},

	_setOpacity: function(opacity) {
		if (opacity < 1) {
			L.DomUtil.setOpacity(this._container, opacity);
		}
	},

	_initContainer: function() {
		var tilePane = this._map.getPanes().tilePane,
			first = tilePane.firstChild;

		if (!this._container || tilePane.empty) {
			this._container = L.DomUtil.create('div', 'leaflet-layer');

			if (this._insertAtTheBottom && first) {
				tilePane.insertBefore(this._container, first);
			} else {
				tilePane.appendChild(this._container);
			}

			this._setOpacity(this.options.opacity);
		}
	},

	_reset: function(clearOldContainer) {
		this._tiles = {};
		if (clearOldContainer && this._container)
			this._container.innerHTML = "";
		this._initContainer();
		this._container.innerHTML = '';
	},

	_update: function() {
		var bounds = this._map.getPixelBounds(),
			tileSize = this.options.tileSize;

		var nwTilePoint = new L.Point(
				Math.floor(bounds.min.x / tileSize),
				Math.floor(bounds.min.y / tileSize)),
			seTilePoint = new L.Point(
				Math.floor(bounds.max.x / tileSize),
				Math.floor(bounds.max.y / tileSize)),
			tileBounds = new L.Bounds(nwTilePoint, seTilePoint);

		this._addTilesFromCenterOut(tileBounds);

		if (this.options.unloadInvisibleTiles) {
			this._removeOtherTiles(tileBounds);
		}
	},

	_addTilesFromCenterOut: function(bounds) {
		var queue = [],
			center = bounds.getCenter();

		for (var j = bounds.min.y; j <= bounds.max.y; j++) {
			for (var i = bounds.min.x; i <= bounds.max.x; i++) {
				if ((i + ':' + j) in this._tiles) { continue; }
				queue.push(new L.Point(i, j));
			}
		}

		// load tiles in order of their distance to center
		queue.sort(function(a, b) {
			return a.distanceTo(center) - b.distanceTo(center);
		});

		var fragment = document.createDocumentFragment();

		this._tilesToLoad = queue.length;
		for (var k = 0, len = this._tilesToLoad; k < len; k++) {
			this._addTile(queue[k], fragment);
		}

		this._container.appendChild(fragment);
	},

	_removeOtherTiles: function(bounds) {
		var kArr, x, y, key;

		for (key in this._tiles) {
			if (this._tiles.hasOwnProperty(key)) {
				kArr = key.split(':');
				x = parseInt(kArr[0], 10);
				y = parseInt(kArr[1], 10);

				// remove tile if it's out of bounds
				if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {

					this.fire("tileunload",this._tiles[key]);

					// evil, don't do this! crashes Android 3, produces load errors, doesn't solve memory leaks
					// this._tiles[key].src = '';

					if (this._tiles[key].parentNode == this._container) {
						this._container.removeChild(this._tiles[key]);
					}
					delete this._tiles[key];
				}
			}
		}
	},

	_addTile: function(tilePoint, container) {
		var tilePos = this._getTilePos(tilePoint),
			zoom = this._map.getZoom(),
			key = tilePoint.x + ':' + tilePoint.y,
			tileLimit = (1 << zoom);

		// wrap tile coordinates
		if (!this.options.continuousWorld) {
			if (!this.options.noWrap) {
				tilePoint.x = ((tilePoint.x % tileLimit) + tileLimit) % tileLimit;
			} else if (tilePoint.x < 0 || tilePoint.x >= tileLimit) {
				this._tilesToLoad--;
				return;
			}

			if (tilePoint.y < 0 || tilePoint.y >= tileLimit) {
				this._tilesToLoad--;
				return;
			}
		}

		// create tile
		var tile = this._createTile();
		L.DomUtil.setPosition(tile, tilePos);

		this._tiles[key] = tile;

		if (this.options.scheme == 'tms') {
			tilePoint.y = tileLimit - tilePoint.y - 1;
		}

		this._loadTile(tile, tilePoint, zoom);

		container.appendChild(tile);
	},

	_getTilePos: function(tilePoint) {
		var origin = this._map.getPixelOrigin(),
			tileSize = this.options.tileSize;

		return tilePoint.multiplyBy(tileSize).subtract(origin);
	},

	// image-specific code (override to implement e.g. Canvas or SVG tile layer)

	getTileUrl: function(tilePoint, zoom) {
		var subdomains = this.options.subdomains,
			s = this.options.subdomains[(tilePoint.x + tilePoint.y) % subdomains.length];

		return this._url
				.replace('{s}', s)
				.replace('{z}', zoom)
				.replace('{x}', tilePoint.x)
				.replace('{y}', tilePoint.y);
	},

	_createTileProto: function() {
		this._tileImg = L.DomUtil.create('img', 'leaflet-tile');
		this._tileImg.galleryimg = 'no';

		var tileSize = this.options.tileSize;
		this._tileImg.style.width = tileSize + 'px';
		this._tileImg.style.height = tileSize + 'px';
	},

	_createTile: function() {
		var tile = this._tileImg.cloneNode(false);
		tile.onselectstart = tile.onmousemove = L.Util.falseFn;
		return tile;
	},

	_loadTile: function(tile, tilePoint, zoom) {
		tile._layer = this;
		tile.onload = this._tileOnLoad;
		tile.onerror = this._tileOnError;
		tile.src = this.getTileUrl(tilePoint, zoom);
	},

	_tileOnLoad: function(e) {
		var layer = this._layer;

		this.className += ' leaflet-tile-loaded';

		layer.fire('tileload', {tile: this, url: this.src});

		layer._tilesToLoad--;
		if (!layer._tilesToLoad) {
			layer.fire('load');
		}
	},

	_tileOnError: function(e) {
		var layer = this._layer;

		layer.fire('tileerror', {tile: this, url: this.src});

		var newUrl = layer.options.errorTileUrl;
		if (newUrl) {
			this.src = newUrl;
		}
	}
});
<commit_msg>Pass object<commit_after>/*
 * L.TileLayer is used for standard xyz-numbered tile layers.
 */

L.TileLayer = L.Class.extend({
	includes: L.Mixin.Events,

	options: {
		minZoom: 0,
		maxZoom: 18,
		tileSize: 256,
		subdomains: 'abc',
		errorTileUrl: '',
		attribution: '',
		opacity: 1,
		scheme: 'xyz',
		continuousWorld: false,
		noWrap: false,

		unloadInvisibleTiles: L.Browser.mobile,
		updateWhenIdle: L.Browser.mobile
	},

	initialize: function(url, options) {
		L.Util.setOptions(this, options);

		this._url = url;

		if (typeof this.options.subdomains == 'string') {
			this.options.subdomains = this.options.subdomains.split('');
		}
	},

	onAdd: function(map, insertAtTheBottom) {
		this._map = map;
		this._insertAtTheBottom = insertAtTheBottom;

		// create a container div for tiles
		this._initContainer();

		// create an image to clone for tiles
		this._createTileProto();

		// set up events
		map.on('viewreset',
			function(e) {
				this._reset(e.hard);
			},
			this);

		if (this.options.updateWhenIdle) {
			map.on('moveend', this._update, this);
		} else {
			this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
			map.on('move', this._limitedUpdate, this);
		}

		this._reset();
		this._update();
	},

	onRemove: function(map) {
		this._map.getPanes().tilePane.removeChild(this._container);
		this._container = null;

		this._map.off('viewreset', this._reset, this);

		if (this.options.updateWhenIdle) {
			this._map.off('moveend', this._update, this);
		} else {
			this._map.off('move', this._limitedUpdate, this);
		}
	},

	getAttribution: function() {
		return this.options.attribution;
	},

	setOpacity: function(opacity) {
		this.options.opacity = opacity;

		this._setOpacity(opacity);

		// stupid webkit hack to force redrawing of tiles
		if (L.Browser.webkit) {
			for (i in this._tiles) {
				this._tiles[i].style.webkitTransform += ' translate(0,0)';
			}
		}
	},

	_setOpacity: function(opacity) {
		if (opacity < 1) {
			L.DomUtil.setOpacity(this._container, opacity);
		}
	},

	_initContainer: function() {
		var tilePane = this._map.getPanes().tilePane,
			first = tilePane.firstChild;

		if (!this._container || tilePane.empty) {
			this._container = L.DomUtil.create('div', 'leaflet-layer');

			if (this._insertAtTheBottom && first) {
				tilePane.insertBefore(this._container, first);
			} else {
				tilePane.appendChild(this._container);
			}

			this._setOpacity(this.options.opacity);
		}
	},

	_reset: function(clearOldContainer) {
		this._tiles = {};
		if (clearOldContainer && this._container)
			this._container.innerHTML = "";
		this._initContainer();
		this._container.innerHTML = '';
	},

	_update: function() {
		var bounds = this._map.getPixelBounds(),
			tileSize = this.options.tileSize;

		var nwTilePoint = new L.Point(
				Math.floor(bounds.min.x / tileSize),
				Math.floor(bounds.min.y / tileSize)),
			seTilePoint = new L.Point(
				Math.floor(bounds.max.x / tileSize),
				Math.floor(bounds.max.y / tileSize)),
			tileBounds = new L.Bounds(nwTilePoint, seTilePoint);

		this._addTilesFromCenterOut(tileBounds);

		if (this.options.unloadInvisibleTiles) {
			this._removeOtherTiles(tileBounds);
		}
	},

	_addTilesFromCenterOut: function(bounds) {
		var queue = [],
			center = bounds.getCenter();

		for (var j = bounds.min.y; j <= bounds.max.y; j++) {
			for (var i = bounds.min.x; i <= bounds.max.x; i++) {
				if ((i + ':' + j) in this._tiles) { continue; }
				queue.push(new L.Point(i, j));
			}
		}

		// load tiles in order of their distance to center
		queue.sort(function(a, b) {
			return a.distanceTo(center) - b.distanceTo(center);
		});

		var fragment = document.createDocumentFragment();

		this._tilesToLoad = queue.length;
		for (var k = 0, len = this._tilesToLoad; k < len; k++) {
			this._addTile(queue[k], fragment);
		}

		this._container.appendChild(fragment);
	},

	_removeOtherTiles: function(bounds) {
		var kArr, x, y, key;

		for (key in this._tiles) {
			if (this._tiles.hasOwnProperty(key)) {
				kArr = key.split(':');
				x = parseInt(kArr[0], 10);
				y = parseInt(kArr[1], 10);

				// remove tile if it's out of bounds
				if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {

					this.fire("tileunload", {tile: this._tiles[key], url: this._tiles[key].src});

					// evil, don't do this! crashes Android 3, produces load errors, doesn't solve memory leaks
					// this._tiles[key].src = '';

					if (this._tiles[key].parentNode == this._container) {
						this._container.removeChild(this._tiles[key]);
					}
					delete this._tiles[key];
				}
			}
		}
	},

	_addTile: function(tilePoint, container) {
		var tilePos = this._getTilePos(tilePoint),
			zoom = this._map.getZoom(),
			key = tilePoint.x + ':' + tilePoint.y,
			tileLimit = (1 << zoom);

		// wrap tile coordinates
		if (!this.options.continuousWorld) {
			if (!this.options.noWrap) {
				tilePoint.x = ((tilePoint.x % tileLimit) + tileLimit) % tileLimit;
			} else if (tilePoint.x < 0 || tilePoint.x >= tileLimit) {
				this._tilesToLoad--;
				return;
			}

			if (tilePoint.y < 0 || tilePoint.y >= tileLimit) {
				this._tilesToLoad--;
				return;
			}
		}

		// create tile
		var tile = this._createTile();
		L.DomUtil.setPosition(tile, tilePos);

		this._tiles[key] = tile;

		if (this.options.scheme == 'tms') {
			tilePoint.y = tileLimit - tilePoint.y - 1;
		}

		this._loadTile(tile, tilePoint, zoom);

		container.appendChild(tile);
	},

	_getTilePos: function(tilePoint) {
		var origin = this._map.getPixelOrigin(),
			tileSize = this.options.tileSize;

		return tilePoint.multiplyBy(tileSize).subtract(origin);
	},

	// image-specific code (override to implement e.g. Canvas or SVG tile layer)

	getTileUrl: function(tilePoint, zoom) {
		var subdomains = this.options.subdomains,
			s = this.options.subdomains[(tilePoint.x + tilePoint.y) % subdomains.length];

		return this._url
				.replace('{s}', s)
				.replace('{z}', zoom)
				.replace('{x}', tilePoint.x)
				.replace('{y}', tilePoint.y);
	},

	_createTileProto: function() {
		this._tileImg = L.DomUtil.create('img', 'leaflet-tile');
		this._tileImg.galleryimg = 'no';

		var tileSize = this.options.tileSize;
		this._tileImg.style.width = tileSize + 'px';
		this._tileImg.style.height = tileSize + 'px';
	},

	_createTile: function() {
		var tile = this._tileImg.cloneNode(false);
		tile.onselectstart = tile.onmousemove = L.Util.falseFn;
		return tile;
	},

	_loadTile: function(tile, tilePoint, zoom) {
		tile._layer = this;
		tile.onload = this._tileOnLoad;
		tile.onerror = this._tileOnError;
		tile.src = this.getTileUrl(tilePoint, zoom);
	},

	_tileOnLoad: function(e) {
		var layer = this._layer;

		this.className += ' leaflet-tile-loaded';

		layer.fire('tileload', {tile: this, url: this.src});

		layer._tilesToLoad--;
		if (!layer._tilesToLoad) {
			layer.fire('load');
		}
	},

	_tileOnError: function(e) {
		var layer = this._layer;

		layer.fire('tileerror', {tile: this, url: this.src});

		var newUrl = layer.options.errorTileUrl;
		if (newUrl) {
			this.src = newUrl;
		}
	}
});
<|endoftext|>


<commit_before>eecQaPlugin.getControl = function(controlId) {
  return $('#' + cw.LayoutManagers.WOGeneral.Controls.get(controlId));
};

eecQaPlugin.tests = {  //TODO: Dynamically specify which tests in init params so they can be assigned per user group through XML?
  tasks: {
    description: 'Tasks Complete',
    update: function() {
      //TODO: Is this going to run async?
      eecQaPlugin.callApi('Tasks', 'ByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        var complete = 0;
        var total = data.length;
        for (var i= 0; i<total; i++) {
          var task = data[i];
          if (task['Status'] == 'COMPLETE') { complete++; }
        }
        if (complete == total) {
          status = 'pass'
        } else {
          status = 'fail'
        }
        eecQaPlugin.setTestResults('tasks', status, complete, total);
      });
    }
  },
  inspections: {
    description: 'Inspections Complete',
    update: function() {
      debugger;
      var inspIds = eecQaPlugin.getControl('grdInspections').find('.rgRow td:eq(1) a, .rgAltRow td:eq(1) a');
      inspIds.each(function() {
        var inspId = $(this).text();
        console.log(inspId);
      });
      //TODO: Write.  It doesn't look like there's going to be an easy way to get "Related Inspections" through the API.
      //We'll probably have to write our own API to retrieve the relationships.  But getting the status can use the
      //official one.
      //OR... we can rely on the work order form to list the related inspections for us (and even their statuses too!)
    }
  },
  customFields: {
    description: 'Required Custom Fields Filled In',
    update: function() {
      //TODO: Write.  Note we'll have to write our own custom fields API because Cityworks doesn't have one (or do it totally cosmetically).
    }
  },
  requiredFields: {
    description: 'Other Required Fields Filled In',
    update: function() {
      //TODO: Write.  This should be able to be done completely cosmetically without any network traffic.  But what about required fields on other pages (i.e. arrived on site)?
    }
  },
  asset: {
    description: 'Attached to an Asset',
    update: function() {
      eecQaPlugin.callApi('WorkOrder', 'Entities', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length == 0) {  //TODO: More sophisticated check?
          status = 'fail';
        } else if (data.length == 1) {
          if (data[0].IsBlank) {
            status = 'fail';
          } else {
            status = 'pass';
          }
        } else {
          status = 'pass';
        }
        eecQaPlugin.setTestResults('asset', status);
      });
    }
  },
  labor: {
    description: 'Labor Entered',
    update: function() {
      eecQaPlugin.callApi('LaborCost', 'WorkOrderCostsByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length > 0) {  //TODO: More sophisticated check?
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('labor', status);
      });
    }
  },
  equipment: {
    description: 'Equipment Entered',
    update: function() {
      eecQaPlugin.callApi('EquipmentCost', 'WorkOrderCostsByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length > 0) {  //TODO: More sophisticated check?
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('equipment', status);
      });
    }
  },
  materials: {
    description: 'Materials Entered',
    update: function() {
      eecQaPlugin.callApi('MaterialCost', 'WorkOrderCostsByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length > 0) {  //TODO: More sophisticated check?
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('materials', status);
      });
    }
  }
};

eecQaPlugin.recordId = eecQaPlugin.getControl('cboWorkOrderId').val();
<commit_msg>Writing WO inspection test<commit_after>eecQaPlugin.getControl = function(controlId) {
  return $('#' + cw.LayoutManagers.WOGeneral.Controls.get(controlId));
};

eecQaPlugin.tests = {  //TODO: Dynamically specify which tests in init params so they can be assigned per user group through XML?
  tasks: {
    description: 'Tasks Complete',
    update: function() {
      //TODO: Is this going to run async?
      eecQaPlugin.callApi('Tasks', 'ByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        var complete = 0;
        var total = data.length;
        for (var i= 0; i<total; i++) {
          var task = data[i];
          if (task['Status'] == 'COMPLETE') { complete++; }
        }
        if (complete == total) {
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('tasks', status, complete, total);
      });
    }
  },
  inspections: {
    description: 'Inspections Complete',
    update: function() {
      var inspIdEls = eecQaPlugin.getControl('grdInspections').find('.rgRow td:eq(1) a, .rgAltRow td:eq(1) a');
      var inspIds = [];
      inspIdEls.each(function() {
        inspIds.push(Number($(this).text()));
      });
      if (inspIds.length == 0) {
        eecQaPlugin.setTestResults('inspections', 'pass', 0, 0);
      } else {
        eecQaPlugin.callApi('Inspection', 'ByIds', {InspectionIds: inspIds}, function(data) {
          var status = '';
          var complete = 0;
          var total = data.length;
          for (var i=0; i<total; i++) {
            var insp = data[i];
            if (insp['IsClosed']) { complete++; }
          }
          if (complete == total) {
            status = 'pass';
          } else {
            status = 'fail';
          }
          eecQaPlugin.setTestResults('inspections', status, complete, total);
        });
      }
    }
  },
  customFields: {
    description: 'Required Custom Fields Filled In',
    update: function() {
      //TODO: Write.  Note we'll have to write our own custom fields API because Cityworks doesn't have one (or do it totally cosmetically).
    }
  },
  requiredFields: {
    description: 'Other Required Fields Filled In',
    update: function() {
      //TODO: Write.  This should be able to be done completely cosmetically without any network traffic.  But what about required fields on other pages (i.e. arrived on site)?
    }
  },
  asset: {
    description: 'Attached to an Asset',
    update: function() {
      eecQaPlugin.callApi('WorkOrder', 'Entities', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length == 0) {  //TODO: More sophisticated check?
          status = 'fail';
        } else if (data.length == 1) {
          if (data[0].IsBlank) {
            status = 'fail';
          } else {
            status = 'pass';
          }
        } else {
          status = 'pass';
        }
        eecQaPlugin.setTestResults('asset', status);
      });
    }
  },
  labor: {
    description: 'Labor Entered',
    update: function() {
      eecQaPlugin.callApi('LaborCost', 'WorkOrderCostsByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length > 0) {  //TODO: More sophisticated check?
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('labor', status);
      });
    }
  },
  equipment: {
    description: 'Equipment Entered',
    update: function() {
      eecQaPlugin.callApi('EquipmentCost', 'WorkOrderCostsByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length > 0) {  //TODO: More sophisticated check?
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('equipment', status);
      });
    }
  },
  materials: {
    description: 'Materials Entered',
    update: function() {
      eecQaPlugin.callApi('MaterialCost', 'WorkOrderCostsByWorkOrder', {WorkOrderIds: [eecQaPlugin.recordId]}, function(data) {
        var status = '';
        if (data.length > 0) {  //TODO: More sophisticated check?
          status = 'pass';
        } else {
          status = 'fail';
        }
        eecQaPlugin.setTestResults('materials', status);
      });
    }
  }
};

eecQaPlugin.recordId = eecQaPlugin.getControl('cboWorkOrderId').val();
<|endoftext|>