<commit_before>/**
Copyright (C) 2011 by Semmy Purewal

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

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

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

(function (window)  {
    //////////////// BUTTON /////////////////////
    var Button = new window.jermaine.Model(function () {
        this.hasA("name").which.isA("string");
        this.hasAn("imageURL").which.isA("string");
        this.hasA("handler").which.isA("function");

        this.hasA("view").which.validatesWith(function (v) {
            return v instanceof window.jermaine.BaseView;
        });

        this.isBuiltWith("name", "imageURL", "handler", function () {
            var that = this;
            this.view(new ButtonView(this));
        });
    });

    var ButtonView = new window.jermaine.View(function () {
        var buttonTemplate = Handlebars.compile($("#button-template").html());
        this.rendersWith(function (jsonRep) {
            return buttonTemplate(jsonRep);
        });
    });
    //////////////// BUTTON /////////////////////

    //////////////// PROJECT /////////////////////
    var Project = new window.jermaine.Model(function () {
        this.hasA("title").which.isA("string");
        this.hasA("source").which.isA("string").and.defaultsTo("//code goes here");
        this.hasA("url").which.isA("string");

        this.isBuiltWith("%url", function () {
            var that = this;
            if (this.url()) {
                $.getJSON(this.url(), function(result) {
                    if (!result.title || !result.source) {
                        throw new Error("invalid project object");
                    } else {
                        that.title(result.title);
                        that.source(result.source);
                    }
                });
            } else {
                that.title("default");
            }
        });
    });
    //////////////// PROJECT /////////////////////

    //////////////// IDE /////////////////////////
    var IDE = new window.jermaine.Model (function () {
        this.hasAn("editor").which.isImmutable();
        this.hasA("directory").which.isA("string");
        this.hasMany("projects");

        this.hasA("project").which.validatesWith(function (project) {
            return project instanceof Project;
        });

        this.hasMany("messages").eachOfWhich.isA("string");
        this.hasMany("buttons").which.validateWith(function (button) {
            return button instanceof Button;
        });

        this.hasA("view");

        this.isBuiltWith("%project", function () {
            //create new java mode
            var javaMode = require("ace/mode/java").Mode;

            //initialize editor as ace editor
            this.editor(ace.edit("IDE-editor"));
            this.editor().setTheme("ace/theme/eclipse");
            this.editor().getSession().setMode(new javaMode());
            this.editor().setHighlightActiveLine(false);
            this.editor().renderer.setShowPrintMargin(false);

            if (this.project() !== undefined) {
                this.editor().getSession().setValue(this.project().source());
            }

            this.view(new IDEView(this));
        });
    });

    var IDEView = new window.jermaine.View (function () {
        var messageTimer,
            messageTimeout = 5000,
            toggleEditorAndDirectory;

        this.initializesWith(function () {
            var that = this;

            toggleEditorAndDirectory = function () {
                var direction = $("#ide").is(":visible")?"lr":"rl";
                var elementA = $("#ide").is(":visible")?$("#ide"):$("#IDE-directory");
                var elementB = $("#ide").is(":visible")?$("#IDE-directory"):$("#ide");

                elementA.flip({
                    speed: 200,
                    direction:direction,
                    color:"#fff",
                    onBefore: function () {
                        elementA.hide();
                    },
                    onEnd: function () {
                        elementB.show();
                        console.log($("#ide").is(":visible"));

                        //this is a hack to force Ace to update when the editor
                        //becomes visible again
                        if ($("#ide").is(":visible")) {
                            that.instance().editor().setValue(that.instance().editor().getValue());
                            that.instance().editor().gotoLine(0,0);
                        }

                    }
                });

            };

            //add run button
            this.instance().buttons().add(new Button("run", "images/icons/run.png", function () {
                that.instance().messages().add("running program");
                that.instance().project().source(that.instance().editor().getSession().getValue());
                return false;
            }));

            var p;  //processing object
            var error;  //processing error

            $("#IDE-run_button").colorbox({
                'title' : that.instance().project().title(),
                'inline' : true,
                'scrolling' : false,
                'href':"#canvas",
                'onLoad' : function()  {
                    var width, height;
                    var code = that.instance().project().source();
                    var canvas = document.getElementById("processing_canvas");
                    error = null;

                    try  {
                        p = new Processing(canvas, code);
                        var dimensions = code.match(/\s+size\((\d+),(\d+)\)/);
                        if (dimensions !== null) {
                            width = parseInt(dimensions[1]);
                            height = parseInt(dimensions[2]);
                        } else {
                            width = 200;
                            height = 200;
                        }
                        $("#processing_canvas").css('width',width);
                        $("#processing_canvas").css('height',height);
                    }
                    catch(err)  {
                        error = err;
                        Processing.logger.log(err);
                        if(p)  {
                            p.exit();
                        }
                    }
                },

                'onComplete' : function()  {
                    if(error)  {
                        console.log(error);
                        $.colorbox.close();
                    } else  {
                        $("#processing_canvas").focus();
                    }
                },
                'onCleanup' : function()  {
                    if(p)  {
                        p.exit();
                    }
                }
            });

            //set up the click responder on the title
            $("#IDE-title").click(function () {
                toggleEditorAndDirectory();
            });
        });

        this.watches("messages", function (newMessage) {
            if (messageTimer !== null) {
                clearTimeout(messageTimer);
            }

            $("#IDE-message").css("display", "none");
            $("#IDE-message").text(newMessage);
            $("#IDE-message").fadeIn();

            messageTimer = setTimeout(function()  {
                $("#IDE-message").fadeOut();
            }, messageTimeout);
        });

        this.watches("project.title", function (newTitle) {
            $("#IDE-title").text(newTitle);
        });

        this.watches("project.source", function (newSource) {
            this.instance().editor().getSession().setValue(newSource);
        });

        this.watches("buttons", function (newButton) {
            var button = $($.parseHTML(newButton.view().render()));
            //add click function
            button.click(function () {
                newButton.handler()();
            });
            $("#IDE-buttons").append(button);
        });

        this.watches("directory", function (newDirectory) {
            var instance = this.instance();
            $.getJSON(newDirectory, function (result) {
                var directoryTemplate = Handlebars.compile($("#directory-template").html());
                for (i = 0; i < result.length; ++i) {
                    result[i]["directory"] = "sketches";
                    result[i]["name"] = result[i]["url"].match(/(.*).json/)[1];
                }
                $("#IDE-directory").append(directoryTemplate({project:result}));

                $("#IDE-directory #" + instance.project().url().match(/\/(.*)\.json/)[1]).addClass("active");

                $(".directory_listing").each(function (i, elt) {
                    $(elt).click(function () {
                        $("#"+instance.project().url().match(/\/(.*)\.json/)[1]).removeClass("active");
                        $("#"+$(elt).attr("href").match(/\/(.*)\.json/)[1]).addClass("active");
                        instance.project(new Project($(elt).attr("href")));
                        //toggleEditorAndDirectory();
                        return false;
                    });
                });
            });
        });
    });
    //////////////// IDE /////////////////////////

    window.IDE = IDE;
    window.Project = Project;
    window.Button = Button;
})(window);
<commit_msg>remove superfluous console.log statement<commit_after>/**
Copyright (C) 2011 by Semmy Purewal

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

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

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

(function (window)  {
    //////////////// BUTTON /////////////////////
    var Button = new window.jermaine.Model(function () {
        this.hasA("name").which.isA("string");
        this.hasAn("imageURL").which.isA("string");
        this.hasA("handler").which.isA("function");

        this.hasA("view").which.validatesWith(function (v) {
            return v instanceof window.jermaine.BaseView;
        });

        this.isBuiltWith("name", "imageURL", "handler", function () {
            var that = this;
            this.view(new ButtonView(this));
        });
    });

    var ButtonView = new window.jermaine.View(function () {
        var buttonTemplate = Handlebars.compile($("#button-template").html());
        this.rendersWith(function (jsonRep) {
            return buttonTemplate(jsonRep);
        });
    });
    //////////////// BUTTON /////////////////////

    //////////////// PROJECT /////////////////////
    var Project = new window.jermaine.Model(function () {
        this.hasA("title").which.isA("string");
        this.hasA("source").which.isA("string").and.defaultsTo("//code goes here");
        this.hasA("url").which.isA("string");

        this.isBuiltWith("%url", function () {
            var that = this;
            if (this.url()) {
                $.getJSON(this.url(), function(result) {
                    if (!result.title || !result.source) {
                        throw new Error("invalid project object");
                    } else {
                        that.title(result.title);
                        that.source(result.source);
                    }
                });
            } else {
                that.title("default");
            }
        });
    });
    //////////////// PROJECT /////////////////////

    //////////////// IDE /////////////////////////
    var IDE = new window.jermaine.Model (function () {
        this.hasAn("editor").which.isImmutable();
        this.hasA("directory").which.isA("string");
        this.hasMany("projects");

        this.hasA("project").which.validatesWith(function (project) {
            return project instanceof Project;
        });

        this.hasMany("messages").eachOfWhich.isA("string");
        this.hasMany("buttons").which.validateWith(function (button) {
            return button instanceof Button;
        });

        this.hasA("view");

        this.isBuiltWith("%project", function () {
            //create new java mode
            var javaMode = require("ace/mode/java").Mode;

            //initialize editor as ace editor
            this.editor(ace.edit("IDE-editor"));
            this.editor().setTheme("ace/theme/eclipse");
            this.editor().getSession().setMode(new javaMode());
            this.editor().setHighlightActiveLine(false);
            this.editor().renderer.setShowPrintMargin(false);

            if (this.project() !== undefined) {
                this.editor().getSession().setValue(this.project().source());
            }

            this.view(new IDEView(this));
        });
    });

    var IDEView = new window.jermaine.View (function () {
        var messageTimer,
            messageTimeout = 5000,
            toggleEditorAndDirectory;

        this.initializesWith(function () {
            var that = this;

            toggleEditorAndDirectory = function () {
                var direction = $("#ide").is(":visible")?"lr":"rl";
                var elementA = $("#ide").is(":visible")?$("#ide"):$("#IDE-directory");
                var elementB = $("#ide").is(":visible")?$("#IDE-directory"):$("#ide");

                elementA.flip({
                    speed: 200,
                    direction:direction,
                    color:"#fff",
                    onBefore: function () {
                        elementA.hide();
                    },
                    onEnd: function () {
                        elementB.show();

                        //this is a hack to force Ace to update when the editor
                        //becomes visible again
                        if ($("#ide").is(":visible")) {
                            that.instance().editor().setValue(that.instance().editor().getValue());
                            that.instance().editor().gotoLine(0,0);
                        }

                    }
                });

            };

            //add run button
            this.instance().buttons().add(new Button("run", "images/icons/run.png", function () {
                that.instance().messages().add("running program");
                that.instance().project().source(that.instance().editor().getSession().getValue());
                return false;
            }));

            var p;  //processing object
            var error;  //processing error

            $("#IDE-run_button").colorbox({
                'title' : that.instance().project().title(),
                'inline' : true,
                'scrolling' : false,
                'href':"#canvas",
                'onLoad' : function()  {
                    var width, height;
                    var code = that.instance().project().source();
                    var canvas = document.getElementById("processing_canvas");
                    error = null;

                    try  {
                        p = new Processing(canvas, code);
                        var dimensions = code.match(/\s+size\((\d+),(\d+)\)/);
                        if (dimensions !== null) {
                            width = parseInt(dimensions[1]);
                            height = parseInt(dimensions[2]);
                        } else {
                            width = 200;
                            height = 200;
                        }
                        $("#processing_canvas").css('width',width);
                        $("#processing_canvas").css('height',height);
                    }
                    catch(err)  {
                        error = err;
                        Processing.logger.log(err);
                        if(p)  {
                            p.exit();
                        }
                    }
                },

                'onComplete' : function()  {
                    if(error)  {
                        console.log(error);
                        $.colorbox.close();
                    } else  {
                        $("#processing_canvas").focus();
                    }
                },
                'onCleanup' : function()  {
                    if(p)  {
                        p.exit();
                    }
                }
            });

            //set up the click responder on the title
            $("#IDE-title").click(function () {
                toggleEditorAndDirectory();
            });
        });

        this.watches("messages", function (newMessage) {
            if (messageTimer !== null) {
                clearTimeout(messageTimer);
            }

            $("#IDE-message").css("display", "none");
            $("#IDE-message").text(newMessage);
            $("#IDE-message").fadeIn();

            messageTimer = setTimeout(function()  {
                $("#IDE-message").fadeOut();
            }, messageTimeout);
        });

        this.watches("project.title", function (newTitle) {
            $("#IDE-title").text(newTitle);
        });

        this.watches("project.source", function (newSource) {
            this.instance().editor().getSession().setValue(newSource);
        });

        this.watches("buttons", function (newButton) {
            var button = $($.parseHTML(newButton.view().render()));
            //add click function
            button.click(function () {
                newButton.handler()();
            });
            $("#IDE-buttons").append(button);
        });

        this.watches("directory", function (newDirectory) {
            var instance = this.instance();
            $.getJSON(newDirectory, function (result) {
                var directoryTemplate = Handlebars.compile($("#directory-template").html());
                for (i = 0; i < result.length; ++i) {
                    result[i]["directory"] = "sketches";
                    result[i]["name"] = result[i]["url"].match(/(.*).json/)[1];
                }
                $("#IDE-directory").append(directoryTemplate({project:result}));

                $("#IDE-directory #" + instance.project().url().match(/\/(.*)\.json/)[1]).addClass("active");

                $(".directory_listing").each(function (i, elt) {
                    $(elt).click(function () {
                        $("#"+instance.project().url().match(/\/(.*)\.json/)[1]).removeClass("active");
                        $("#"+$(elt).attr("href").match(/\/(.*)\.json/)[1]).addClass("active");
                        instance.project(new Project($(elt).attr("href")));
                        //toggleEditorAndDirectory();
                        return false;
                    });
                });
            });
        });
    });
    //////////////// IDE /////////////////////////

    window.IDE = IDE;
    window.Project = Project;
    window.Button = Button;
})(window);
<|endoftext|>


<commit_before>/*
1. Assume a sample large (50K items) JSON data set (e.g USA users for a site with location information)
2. Render a Google map, with pins shown for each state (e.g X users from California)
3. On zoom in, show the pins for each city (e.g X users from Palo Alto)
4. On zoom in further, show the pins for each zip code.
5. On zoom out, show the appropriate pins per the zoom level
 */

/*! @license
 *  Project: Buttons
 *  Description: Google Map Interface which extends to multi market
 *  Author: Sanyam Agrawal
 *  Date : 26/03/2015 (DD/MM/YYYY)
 *  License: Apache License v2.0
 */

(function($, window, document, undefined) {

    /**
     * map which is currently being rendered, Global to our app so that we can use it accross diffent objects.
     */
    var map,

        /**
         * [MapUtil description] Contains initialization method for map and event listners for map object.
         * @type {Object}
         */
        MapUtil = {

            /**
             * [ZOOM_LEVEL_MAP description]
             *     A hash map of the Zoom Level and the Information which needs to be rendered. i.e
             *     if Zoom Level is 5 then we need to render the Users States Information onto the Map.
             * @type {Object}
             */
            ZOOM_LEVEL_MAP: {
                "5": "state",
                "6": "city",
                "7": "zip"
            },

            /**
             * [DEFAULT_ZOOM_LEVEL description]
             *     The default zoom at whcich Google Map will be rendered.
             *     This should be avaliable in the above ZOOM_LEVEL_MAP
             * @type {Number}
             */
            DEFAULT_ZOOM_LEVEL: 5,

            /**
             * [initialize description] Renders the Google Map on to the element
             * @return {[type]} [description]
             */
            initialize: function() {
                var mapOptions = {
                    zoom: this.DEFAULT_ZOOM_LEVEL,
                    center: new google.maps.LatLng(20.593684, 78.962880)
                };

                map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

                //Add listners and callback on google map
                this.initListerners();

                StoreUtil.processJSON();
                MarkerUtil.initMarkers(this.ZOOM_LEVEL_MAP[this.DEFAULT_ZOOM_LEVEL], StoreUtil.getObjectBasedOnZoomLevel(this.DEFAULT_ZOOM_LEVEL));
            },

            /**
             * [initListerners description] Initializes all Map Related events here along with their call back funtion
             * @return {[type]} [description]
             */
            initListerners: function() {
                google.maps.event.addListener(map, "zoom_changed", this.zoomChangedCallback.bind(this));
            },

            /**
             * Callback for Zoom Event. It takes the type of zoom, int number and gets the type from ZOOM_LEVEL_MAP.
             * See ZOOM_LEVEL_MAP for possible zoom events.
             * @return {[type]} [description]
             */
            zoomChangedCallback: function() {
                var zoomLevel = map.getZoom(),
                    typeOfZoom = this.ZOOM_LEVEL_MAP[zoomLevel];

                //Clear all Markers rendered on the map
                MarkerUtil.clearMarkers();

                //If zoom level is not within the range we want to show (ZOOM_LEVEL_MAP) return from the function
                if (!typeOfZoom) {
                    return;
                }

                //Start rendering the markers based on the zoom level.
                MarkerUtil.initMarkers(typeOfZoom, StoreUtil.getObjectBasedOnType(typeOfZoom));
            }
        },

        /**
         * Marker Util defines all the functionality involved with showing a Marker on the screen,
         * hiding the marker, remomving the marker etc
         * @type {Object}
         */
        MarkerUtil = {

            /**
             * All markers during a particular zoom level are stored in this array.
             * @type {Array}
             */
            markers: [],

            /**
             * Bounds Google Map funtion reference
             * @type {google}
             */
            bounds: new google.maps.LatLngBounds(),

            /**
             * TO get the Long/Lat of an address from Google API
             * @type {google}
             */
            geocoder: new google.maps.Geocoder(),

            /**
             * To show the contect as a modal over a marker in google map
             * @type {google}
             */
            infowindow: new google.maps.InfoWindow(),

            /**
             * Initialize the data for the markers that need to be pased on the MAP
             * @param  {string} type The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {object} data The object which contains the data required to place the marker onto the MAP.
             * @return {} N/A
             */
            initMarkers: function(type, data) {
                this.processMarker(data, type);
            },

            /**
             * This function is responsible for iterating over the data and finding out if we have Longitute and
             * Latitude information of a particlar address .
             * If Present it will call the render function which will place the marker and if not present will
             * call the Google Map geoCoder API to get Long/Lat Information
             * @param  {object} interator The object which contains the data required to place the marker onto the MAP.
             * @param  {string} type The type of marker to be placed. ("State","City" or "Zip Code")
             */
            processMarker: function(interator, type) {
                var keys = Object.keys(interator);

                $(keys).each(function(index, key) {
                    /*jshint unused:true*/
                    var LatLng = interator[key].LatLng;

                    //If long/lat information is present then add the marker.
                    if (LatLng) {
                        this.addMarker(type, key, LatLng);
                    } else {
                        // else call geoLocator API to get long/lat information.
                        this.getLongLatInfo(key, type);
                    }
                }.bind(this));
            },
            /**
             * Get Log Lat Information based on address
             * @param  {String} query   The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             */
            getLongLatInfo: function(query, type) {
                var address = query;

                this.geocoder.geocode({
                    "address": address
                }, this.putMarker.bind(this, type, query));
            },

            /**
             * Function Caches the result from geocoder.geocode and calls the method to add the marker to map
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} query   The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {object} results google Location object. Result of geocoder.geocode
             * @param  {String} status  google.maps.GeocoderStatus ENUM status
             * @return {[type]}         NA
             */
            putMarker: function(type, query, results, status) {

                var position;

                if (status === google.maps.GeocoderStatus.OK) {

                    position = results[0].geometry.location;
                    StoreUtil.saveLongLatInfo(type, query, position);
                    this.addMarker(type, query, position);

                } else {
                    alert("Geocode was not successful for the following reason: " + status);
                }
            },

            /**
             * Place Marker on Google Map based on the result from GetLongLatInfo Function
             * @param  {string} type        The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} query       The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {Object} position    Object that contains the co-ordinates of the query string
             */
            addMarker: function(type, query, position) {
                var marker;

                marker = new google.maps.Marker({
                    map: map,
                    position: position
                });

                this.markers.push(marker);

                //Event Listerner to show Info tooltip when a marker is clicked.
                google.maps.event.addListener(marker, "click", this.markerClickCallback.bind(this, type, query, marker));
                //this.addBounds(marker);
            },

            /**
             * Shows a tooltip with Information above a marker in a map
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} query   The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {Object} marker  Google Marker Object which contains details of a address.
             */
            markerClickCallback: function(type, query, marker) {
                var count = StoreUtil.getObjectBasedOnType(type)[query].count + 1,
                    message = ["
", [count, "Users in this location."].join(" "), "
"].join("");

                this.infowindow.setContent(message);
                this.infowindow.open(map, marker);
            },

            /**
             * Removes the markers from the map, but keeps them in the array.
             */
            clearMarkers: function() {
                this.setAllMap(null);
                this.markers = [];
            },

            /**
             * Sets the map on all markers in the array.
             * @param {Object} map The map to be set
             */
            setAllMap: function(map) {
                var i = 0;
                for (i; i < this.markers.length; i++) {
                    this.markers[i].setMap(map);
                }
            },

            addBounds: function(marker) {
                this.bounds.extend(marker.position);
            },

            fitBound: function() {
                //map.fitBounds(this.bounds);
            }
        },

        /**
         * Store Util Contains Methods and API's to get the Users Details, Process the User's details based
         * Google map and some Utility Function.
         * @type {Object}
         */
        StoreUtil = {
            /**
             * JSON Formot required to render the Data in Google Maps.
             * @type {Object}
             */
            mappedJson: {},

            /**
             * Speical Character used to seperate different values for the address which needs to be parsed by
             * Google Map.
             * @type {String}
             */
            DELIMITOR: ",",

            /**
             * function returns a json of Users data.
             * @return {Object} JSON Object.
             */
            getJSON: function() {
                var response = [{
                    userId: 1,
                    locationDetails: {
                        state: {
                            value: "Karnataka"
                        },
                        city: {
                            value: "Bangalore"
                        },
                        zipCode: {
                            value: 560003
                        }
                    }

                }, {
                    userId: 2,
                    locationDetails: {
                        state: {
                            value: "Karnataka"
                        },
                        city: {
                            value: "Bangalore"
                        },
                        zipCode: {
                            value: 560101
                        }
                    }

                }, {
                    userId: 3,
                    locationDetails: {
                        state: {
                            value: "Karnataka"
                        },
                        city: {
                            value: "Hubli"
                        },
                        zipCode: {
                            value: 560003
                        }
                    }

                }, {
                    userId: 4,
                    locationDetails: {
                        state: {
                            value: "Delhi"
                        },
                        city: {
                            value: "Delhi"
                        },
                        zipCode: {
                            value: 110556
                        }
                    }

                }];
                return response;
            },

            /**
             * Iterates over the Json and converts it to an object that is easier to render to Google Maps.
             */
            processJSON: function() {
                var data = this.getJSON(),
                    stateInfo = {},
                    cityInfo = {},
                    zipInfo = {};

                $(data).each(function(index, user) {

                    /*jshint unused:true*/

                    var locationInfo = user.locationDetails,
                        state = locationInfo.state.value,
                        city = locationInfo.city.value,
                        zip = locationInfo.zipCode.value;

                    //Place State Inforamtion here.
                    this.put(stateInfo, state);

                    //Places State,City Information in cityInfo.
                    this.put(cityInfo, [state, city].join(this.DELIMITOR));

                    //Places State,City,ZipCode Information Here
                    this.put(zipInfo, [state, city, zip].join(this.DELIMITOR));
                    // cityInfo = put(stateInfo, state);
                    // zipInfo = put(cityInfo, city);
                    // put(zipInfo, zip);
                }.bind(this));

                //Finally add all the information to a single JSON as ECMA5 doesnt support sending multiple response.
                this.mappedJson = {
                    state: stateInfo,
                    city: cityInfo,
                    zip: zipInfo
                };
            },

            /**
             * A Utility Function which is useful to add infomration to a Object.
             * I tried adding it to Object.prototype.put but this somehow seems to break google API.
             * Still have to figure out why this is happening.
             * @param  {Object} obj     Object in which the value neeeds to be placed
             * @param  {[type]} value   The value which needs to be added to conunt key
             * @return {Object}         The Newely Created Object which might have or not ahve count as a property.
             */
            put: function(obj, value) {

                if (!obj[value]) {
                    obj[value] = {};
                    obj[value].count = 0;
                } else {
                    obj[value].count = obj[value].count + 1;
                }

                return obj[value];
            },

            /**
             * Get City, State or Zip Code Obejct to be processed based on the type.
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @return {object}         The type of marker to be placed
             */
            getObjectBasedOnType: function(type) {
                return this.mappedJson[type];
            },

            /**
             * Get City, State or Zip Code Object to be processed based on the Zoom Level.
             * @param  {string} level    The type of marker to be placed. ("State","City" or "Zip Code")
             * @return {object}         The type of marker to be placed
             */
            getObjectBasedOnZoomLevel: function(level) {
                return this.getObjectBasedOnType(MapUtil.ZOOM_LEVEL_MAP[level]);
            },

            /**
             * Utility Function to Cache the Longitute/Latitude information of a particlar address,
             * avaliable in the Object
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} key     The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {[type]} value   The value which needs to be put in LatLng value.
             */
            saveLongLatInfo: function(type, key, value) {
                var obj = this.getObjectBasedOnType(type);

                obj[key].LatLng = value;
            }
        };

    // Once The DOM Objet is avaliable start rendering our MAP.
    google.maps.event.addDomListener(window, "load", MapUtil.initialize.bind(MapUtil));

})(jQuery, window, document);
<commit_msg>Making Info Content More meaning ful<commit_after>/*
1. Assume a sample large (50K items) JSON data set (e.g USA users for a site with location information)
2. Render a Google map, with pins shown for each state (e.g X users from California)
3. On zoom in, show the pins for each city (e.g X users from Palo Alto)
4. On zoom in further, show the pins for each zip code.
5. On zoom out, show the appropriate pins per the zoom level
 */

/*! @license
 *  Project: Buttons
 *  Description: Google Map Interface which extends to multi market
 *  Author: Sanyam Agrawal
 *  Date : 26/03/2015 (DD/MM/YYYY)
 *  License: Apache License v2.0
 */

(function($, window, document, undefined) {

    /**
     * map which is currently being rendered, Global to our app so that we can use it accross diffent objects.
     */
    var map,

        /**
         * [MapUtil description] Contains initialization method for map and event listners for map object.
         * @type {Object}
         */
        MapUtil = {

            /**
             * [ZOOM_LEVEL_MAP description]
             *     A hash map of the Zoom Level and the Information which needs to be rendered. i.e
             *     if Zoom Level is 5 then we need to render the Users States Information onto the Map.
             * @type {Object}
             */
            ZOOM_LEVEL_MAP: {
                "5": "state",
                "6": "city",
                "7": "zip"
            },

            /**
             * [DEFAULT_ZOOM_LEVEL description]
             *     The default zoom at whcich Google Map will be rendered.
             *     This should be avaliable in the above ZOOM_LEVEL_MAP
             * @type {Number}
             */
            DEFAULT_ZOOM_LEVEL: 5,

            /**
             * [initialize description] Renders the Google Map on to the element
             * @return {[type]} [description]
             */
            initialize: function() {
                var mapOptions = {
                    zoom: this.DEFAULT_ZOOM_LEVEL,
                    center: new google.maps.LatLng(20.593684, 78.962880)
                };

                map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

                //Add listners and callback on google map
                this.initListerners();

                StoreUtil.processJSON();
                MarkerUtil.initMarkers(this.ZOOM_LEVEL_MAP[this.DEFAULT_ZOOM_LEVEL], StoreUtil.getObjectBasedOnZoomLevel(this.DEFAULT_ZOOM_LEVEL));
            },

            /**
             * [initListerners description] Initializes all Map Related events here along with their call back funtion
             * @return {[type]} [description]
             */
            initListerners: function() {
                google.maps.event.addListener(map, "zoom_changed", this.zoomChangedCallback.bind(this));
            },

            /**
             * Callback for Zoom Event. It takes the type of zoom, int number and gets the type from ZOOM_LEVEL_MAP.
             * See ZOOM_LEVEL_MAP for possible zoom events.
             * @return {[type]} [description]
             */
            zoomChangedCallback: function() {
                var zoomLevel = map.getZoom(),
                    typeOfZoom = this.ZOOM_LEVEL_MAP[zoomLevel];

                //Clear all Markers rendered on the map
                MarkerUtil.clearMarkers();

                //If zoom level is not within the range we want to show (ZOOM_LEVEL_MAP) return from the function
                if (!typeOfZoom) {
                    return;
                }

                //Start rendering the markers based on the zoom level.
                MarkerUtil.initMarkers(typeOfZoom, StoreUtil.getObjectBasedOnType(typeOfZoom));
            }
        },

        /**
         * Marker Util defines all the functionality involved with showing a Marker on the screen,
         * hiding the marker, remomving the marker etc
         * @type {Object}
         */
        MarkerUtil = {

            /**
             * All markers during a particular zoom level are stored in this array.
             * @type {Array}
             */
            markers: [],

            /**
             * Bounds Google Map funtion reference
             * @type {google}
             */
            bounds: new google.maps.LatLngBounds(),

            /**
             * TO get the Long/Lat of an address from Google API
             * @type {google}
             */
            geocoder: new google.maps.Geocoder(),

            /**
             * To show the contect as a modal over a marker in google map
             * @type {google}
             */
            infowindow: new google.maps.InfoWindow(),

            /**
             * Initialize the data for the markers that need to be pased on the MAP
             * @param  {string} type The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {object} data The object which contains the data required to place the marker onto the MAP.
             * @return {} N/A
             */
            initMarkers: function(type, data) {
                this.processMarker(data, type);
            },

            /**
             * This function is responsible for iterating over the data and finding out if we have Longitute and
             * Latitude information of a particlar address .
             * If Present it will call the render function which will place the marker and if not present will
             * call the Google Map geoCoder API to get Long/Lat Information
             * @param  {object} interator The object which contains the data required to place the marker onto the MAP.
             * @param  {string} type The type of marker to be placed. ("State","City" or "Zip Code")
             */
            processMarker: function(interator, type) {
                var keys = Object.keys(interator);

                $(keys).each(function(index, key) {
                    /*jshint unused:true*/
                    var LatLng = interator[key].LatLng;

                    //If long/lat information is present then add the marker.
                    if (LatLng) {
                        this.addMarker(type, key, LatLng);
                    } else {
                        // else call geoLocator API to get long/lat information.
                        this.getLongLatInfo(key, type);
                    }
                }.bind(this));
            },
            /**
             * Get Log Lat Information based on address
             * @param  {String} query   The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             */
            getLongLatInfo: function(query, type) {
                var address = query;

                this.geocoder.geocode({
                    "address": address
                }, this.putMarker.bind(this, type, query));
            },

            /**
             * Function Caches the result from geocoder.geocode and calls the method to add the marker to map
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} query   The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {object} results google Location object. Result of geocoder.geocode
             * @param  {String} status  google.maps.GeocoderStatus ENUM status
             * @return {[type]}         NA
             */
            putMarker: function(type, query, results, status) {

                var position;

                if (status === google.maps.GeocoderStatus.OK) {

                    position = results[0].geometry.location;
                    StoreUtil.saveLongLatInfo(type, query, position);
                    this.addMarker(type, query, position);

                } else {
                    alert("Geocode was not successful for the following reason: " + status);
                }
            },

            /**
             * Place Marker on Google Map based on the result from GetLongLatInfo Function
             * @param  {string} type        The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} query       The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {Object} position    Object that contains the co-ordinates of the query string
             */
            addMarker: function(type, query, position) {
                var marker;

                marker = new google.maps.Marker({
                    map: map,
                    position: position
                });

                this.markers.push(marker);

                //Event Listerner to show Info tooltip when a marker is clicked.
                google.maps.event.addListener(marker, "click", this.markerClickCallback.bind(this, type, query, marker));
                //this.addBounds(marker);
            },

            /**
             * Shows a tooltip with Information above a marker in a map
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} query   The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {Object} marker  Google Marker Object which contains details of a address.
             */
            markerClickCallback: function(type, query, marker) {
                var count = StoreUtil.getObjectBasedOnType(type)[query].count + 1,
                    message = ["
", [count, "Users in", query].join(" "), "
"].join("");

                this.infowindow.setContent(message);
                this.infowindow.open(map, marker);
            },

            /**
             * Removes the markers from the map, but keeps them in the array.
             */
            clearMarkers: function() {
                this.setAllMap(null);
                this.markers = [];
            },

            /**
             * Sets the map on all markers in the array.
             * @param {Object} map The map to be set
             */
            setAllMap: function(map) {
                var i = 0;
                for (i; i < this.markers.length; i++) {
                    this.markers[i].setMap(map);
                }
            },

            addBounds: function(marker) {
                this.bounds.extend(marker.position);
            },

            fitBound: function() {
                //map.fitBounds(this.bounds);
            }
        },

        /**
         * Store Util Contains Methods and API's to get the Users Details, Process the User's details based
         * Google map and some Utility Function.
         * @type {Object}
         */
        StoreUtil = {
            /**
             * JSON Formot required to render the Data in Google Maps.
             * @type {Object}
             */
            mappedJson: {},

            /**
             * Speical Character used to seperate different values for the address which needs to be parsed by
             * Google Map.
             * @type {String}
             */
            DELIMITOR: ",",

            /**
             * function returns a json of Users data.
             * @return {Object} JSON Object.
             */
            getJSON: function() {
                var response = [{
                    userId: 1,
                    locationDetails: {
                        state: {
                            value: "Karnataka"
                        },
                        city: {
                            value: "Bangalore"
                        },
                        zipCode: {
                            value: 560003
                        }
                    }

                }, {
                    userId: 2,
                    locationDetails: {
                        state: {
                            value: "Karnataka"
                        },
                        city: {
                            value: "Bangalore"
                        },
                        zipCode: {
                            value: 560101
                        }
                    }

                }, {
                    userId: 3,
                    locationDetails: {
                        state: {
                            value: "Karnataka"
                        },
                        city: {
                            value: "Hubli"
                        },
                        zipCode: {
                            value: 560003
                        }
                    }

                }, {
                    userId: 4,
                    locationDetails: {
                        state: {
                            value: "Delhi"
                        },
                        city: {
                            value: "Delhi"
                        },
                        zipCode: {
                            value: 110556
                        }
                    }

                }];
                return response;
            },

            /**
             * Iterates over the Json and converts it to an object that is easier to render to Google Maps.
             */
            processJSON: function() {
                var data = this.getJSON(),
                    stateInfo = {},
                    cityInfo = {},
                    zipInfo = {};

                $(data).each(function(index, user) {

                    /*jshint unused:true*/

                    var locationInfo = user.locationDetails,
                        state = locationInfo.state.value,
                        city = locationInfo.city.value,
                        zip = locationInfo.zipCode.value;

                    //Place State Inforamtion here.
                    this.put(stateInfo, state);

                    //Places State,City Information in cityInfo.
                    this.put(cityInfo, [state, city].join(this.DELIMITOR));

                    //Places State,City,ZipCode Information Here
                    this.put(zipInfo, [state, city, zip].join(this.DELIMITOR));
                    // cityInfo = put(stateInfo, state);
                    // zipInfo = put(cityInfo, city);
                    // put(zipInfo, zip);
                }.bind(this));

                //Finally add all the information to a single JSON as ECMA5 doesnt support sending multiple response.
                this.mappedJson = {
                    state: stateInfo,
                    city: cityInfo,
                    zip: zipInfo
                };
            },

            /**
             * A Utility Function which is useful to add infomration to a Object.
             * I tried adding it to Object.prototype.put but this somehow seems to break google API.
             * Still have to figure out why this is happening.
             * @param  {Object} obj     Object in which the value neeeds to be placed
             * @param  {[type]} value   The value which needs to be added to conunt key
             * @return {Object}         The Newely Created Object which might have or not ahve count as a property.
             */
            put: function(obj, value) {

                if (!obj[value]) {
                    obj[value] = {};
                    obj[value].count = 0;
                } else {
                    obj[value].count = obj[value].count + 1;
                }

                return obj[value];
            },

            /**
             * Get City, State or Zip Code Obejct to be processed based on the type.
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @return {object}         The type of marker to be placed
             */
            getObjectBasedOnType: function(type) {
                return this.mappedJson[type];
            },

            /**
             * Get City, State or Zip Code Object to be processed based on the Zoom Level.
             * @param  {string} level    The type of marker to be placed. ("State","City" or "Zip Code")
             * @return {object}         The type of marker to be placed
             */
            getObjectBasedOnZoomLevel: function(level) {
                return this.getObjectBasedOnType(MapUtil.ZOOM_LEVEL_MAP[level]);
            },

            /**
             * Utility Function to Cache the Longitute/Latitude information of a particlar address,
             * avaliable in the Object
             * @param  {string} type    The type of marker to be placed. ("State","City" or "Zip Code")
             * @param  {String} key     The address whose Co-oridnates needs to be found. (Karnataka Or Karnataka,Bangalore or Karnataka,Bangalore,560103)
             * @param  {[type]} value   The value which needs to be put in LatLng value.
             */
            saveLongLatInfo: function(type, key, value) {
                var obj = this.getObjectBasedOnType(type);

                obj[key].LatLng = value;
            }
        };

    // Once The DOM Objet is avaliable start rendering our MAP.
    google.maps.event.addDomListener(window, "load", MapUtil.initialize.bind(MapUtil));

})(jQuery, window, document);
<|endoftext|>


<commit_before>'use strict';

var isDate     = require('es5-ext/lib/Date/is-date')
  , d          = require('es5-ext/lib/Object/descriptor')
  , extend     = require('es5-ext/lib/Object/extend-properties')
  , Base       = require('./base')
  , NumberType = require('./number')

  , defineProperties = Object.defineProperties
  , getPrototypeOf = Object.getPrototypeOf

  , DateTime, proto;

module.exports = DateTime = Base.$$create('DateTime');
proto = DateTime.prototype;
extend(DateTime, Date);
DateTime.prototype = proto;

defineProperties(DateTime, {
	_serialize_: d('c', function (value) { return '4' + Number(value); }),
	compare: d('c', NumberType.compare)
});
DateTime._is.$$setValue(function (value) {
	return isDate(value) && !isNaN(value) &&
		(getPrototypeOf(value) === this.prototype);
});
DateTime._normalize.$$setValue(function (value) {
	if (!isDate(value)) value = new Date(value);
	if (isNaN(value)) return null;
	value.__proto__ = this.prototype;
	return value;
});

defineProperties(extend(proto, Date.prototype), {
	$create: d(function (value) {
		if (value == null) value = new Date();
		else value = new Date(value);
		value.__proto__ = this;
		value.$construct();
		return value;
	}),
	validateCreate: d(function (value) {
		if ((value != null) && isNaN(isDate(value) ? value : new Date(value))) {
			return new TypeError(value + " is invalid date value");
		}
		return null;
	})
});
proto._$construct.$$setValue(function (value) {});
delete proto.toString;
proto._toString.$$setValue(Date.prototype.toString);
<commit_msg>Reflect native Date constructor rules in DateTime<commit_after>'use strict';

var isDate     = require('es5-ext/lib/Date/is-date')
  , d          = require('es5-ext/lib/Object/descriptor')
  , extend     = require('es5-ext/lib/Object/extend-properties')
  , Base       = require('./base')
  , NumberType = require('./number')

  , defineProperties = Object.defineProperties
  , getPrototypeOf = Object.getPrototypeOf

  , DateTime, proto;

module.exports = DateTime = Base.$$create('DateTime');
proto = DateTime.prototype;
extend(DateTime, Date);
DateTime.prototype = proto;

defineProperties(DateTime, {
	_serialize_: d('c', function (value) { return '4' + Number(value); }),
	compare: d('c', NumberType.compare)
});
DateTime._is.$$setValue(function (value) {
	return isDate(value) && !isNaN(value) &&
		(getPrototypeOf(value) === this.prototype);
});
DateTime._normalize.$$setValue(function (value) {
	if (!isDate(value)) value = new Date(value);
	if (isNaN(value)) return null;
	value.__proto__ = this.prototype;
	return value;
});

defineProperties(extend(proto, Date.prototype), {
	$create: d(
		function (value/*[, month[, date[, hours[, minutes[, seconds[, ms]]]]]]*/) {
			var l = arguments.length;
			if (!l) {
				value = new Date();
			} else if (l > 1) {
				value = new Date(value, arguments[1], (l > 2) ? arguments[2] : 1,
					(l > 3) ? arguments[3] : 0, (l > 4) ? arguments[4] : 0,
					(l > 5) ? arguments[5] : 0, (l > 6) ? arguments[6] : 0);
			} else {
				value = new Date(value);
			}
			value.__proto__ = this;
			value.$construct();
			return value;
		}
	),
	validateCreate: d(
		function (value/*[, month[, date[, hours[, minutes[, seconds[, ms]]]]]]*/) {
			var l = arguments.length;
			if (!l) return null;
			if (l > 1) {
				value = new Date(value, arguments[1], (l > 2) ? arguments[2] : 1,
					(l > 3) ? arguments[3] : 0, (l > 4) ? arguments[4] : 0,
					(l > 5) ? arguments[5] : 0, (l > 6) ? arguments[6] : 0);
			} else {
				value = new Date(value);
			}
			if (isNaN(value)) return new TypeError(value + " is invalid date value");
			return null;
		}
	)
});
proto._$construct.$$setValue(function (value) {});
delete proto.toString;
proto._toString.$$setValue(Date.prototype.toString);
<|endoftext|>


<commit_before>/// <reference path='./../../typings/tsd.d.ts' />
'use strict';
var fs = require('fs');
var stream = fs.createWriteStream("./../typescript.pegjs");
stream.once('open', function (fd) {
    stream.write('// Typescript rules.');
    stream.end();
});
<commit_msg>Code for creating chapter en rules in the typescript.pegjs file<commit_after><|endoftext|>


<commit_before>//Reusable non plugin stuff goes in app
(function(win, doc) {
    'use strict';
    var app = app || {
        _isSafari: null,
        _isMobile: null,
        _bgImageLink: null,
        _searchedTag: null,
        _buttonLetter: null,
        _postHeaderImg: null
    };

    app.isSafari = function() {
      return parrot.device.browser.name.toLowerCase().indexOf('safari') !== -1
    }

    app.isMobile = function() {
      return parrot.device.type === 'mobile';
    }

    app.getBgImg = function(elem) {
        if (app._bgImageLink === null) {
            if (app.elemExists(elem)) {
                elem = $(elem);
                app._bgImageLink = elem.attr('src');
                elem.remove();
            }
        }

        return app._bgImageLink;
    }

    app.replaceAll = function(str, find, replace) {
        return str.replace(new RegExp(find, 'g'), replace);
    }

    app.elemExists = function(elem) {
        elem = $(elem);

        if (elem.length > 0) {
            return true;
        } else {
            return false;
        }
    }

    app.getTag = function(elem) {

        if (app._searchedTag === null) {
            if (app.elemExists(elem)) {
                var url = window.location.href;
                var splitURL = url.split('tag');
                var tag = app.replaceAll(splitURL[1], '/', '');
                var tagFirstChar;

                tag = app.replaceAll(tag, '-', ' ');
                tagFirstChar = tag.charAt(0).toUpperCase();
                tag = tagFirstChar + tag.substring(1, tag.length);

                app._searchedTag = tag;
            }
        }

        return app._searchedTag;
    }

    app.getFirstChar = function(elem, target) {
        if (app._buttonLetter === null) {
            if (app.elemExists(elem)) {
                var blogTitle = $(elem);
                var letter = blogTitle.val().charAt(0).toUpperCase();

                app._buttonLetter = letter;
            }
        }

        return app._buttonLetter;
    }

    app.aTagWrap = function(elem, elemClass) {
        if (app.elemExists(elem)) {
            var imgs = $(elem);
            if (imgs.length > 0) {
                imgs.each(function() {
                    var $this = $(this);
                    var imgLink = $this.attr('src');

                    var html = '';
                    html = "";

                    $this.wrap(html);
                });

            }
        }
    }

    app.getHeaderImg = function(elem) {
        if (app._postHeaderImg === null) {
            var post = $(elem);

            if (app.elemExists(elem)) {

                var postImg = $(elem + ' img')[0];
                if (typeof(postImg) !== 'undefined') {
                    $(postImg).remove();
                    $(postImg).attr('id', 'bg-img');
                    $('#post-container').append($(postImg));
                    app._postHeaderImg = postImg.src

                }
            }
        }

        return app._postHeaderImg;
    }

    window.app = app;

})(window, document);

var initImagesLoaded = function(container, elem) {

    var posts = document.querySelectorAll(elem);

    imagesLoaded(posts, function() {

        var postContainer = $(container);

        $('.post').fitVids();

        app.aTagWrap('.post-page-post .post-text img', 'fluid-popup');

        $('.fluid-popup').fluidbox();

        postContainer.addClass('show-post');
        postContainer.removeClass('hide-post');
    });
}

var bgImgLoaded = function(elem) {
    var posts = document.querySelectorAll(elem);

    imagesLoaded(posts, function() {

        //Set the bg image

        var bgImg = app.getBgImg('#bg-img') || app.getHeaderImg('.post-page-post .post-text');

        if (bgImg !== null) {
            var header = $('.main-header')
            $('.main-header').css('background-image', 'URL(' + bgImg + ')');
            if (app.isMobile()) {
                header.backstretch(bgImg);
            }
        }

    });
}

var initReadTime = function(elem) {
    elem = $(elem);
    readingTime = $('.post-reading-time');
    if (elem.length > 0 && readingTime.length > 0) {
        elem.readingTime({
            readingTimeTarget: '.post-reading-time',
        });
    }
}

var initSyntaxHighlight = function(elem) {
    var code = $(elem);
    if (code.length > 0) {
        code.each(function(i, e) {
            hljs.highlightBlock(e)
        });
    }
}

var initNavBar = function() {
    if (app.isSafari()) {
        $('#navbar').addClass('navbar-safari');
    }

    $('#openMenu').on('click', function(event) {
        event.preventDefault();
        var elems;

        // if (app.isSafari()){
        //    elems = $('#sidebar, .page-wrapper,#navbar');
        // }else{
        elems = $('#sidebar, .page-wrapper');
        //  }

        elems.toggleClass('opened');

        if (!app.isMobile()) {
            if (elems.hasClass('opened')) {
                disable_scroll();
            } else {
                enable_scroll();
            }
        } else {
            if (elems.hasClass('opened')) {
                document.ontouchmove = function(e) {
                    e.preventDefault();
                }
            } else {
                document.ontouchmove = function(e) {
                    return true;
                }
            }
        }
    });
}

var initInfiniteScroll = function(pageNumber, nextPage) {
    var maxPageNumber = $(pageNumber);
    var nextPageElem = $(nextPage);

    if (maxPageNumber.length > 0 && nextPageElem.length > 0) {
        var splitPageNumber = maxPageNumber.html().split('of');
        var getNextPage = nextPageElem.attr('href').slice(-2).replace('/', '');

        maxPageNumber = parseInt(splitPageNumber[1]);
        getNextPage = parseInt(getNextPage);

        $('#post-container .grid-container').infinitescroll({
            navSelector: ".pagination",
            // selector for the paged navigation (it will be hidden)
            nextSelector: ".pagination .older-posts",
            // selector for the NEXT link (to page 2)
            itemSelector: ".post"

        }, function(newElems) {

            var elem = $(newElems);
            var elemID = elem.attr('id');

            //elem.addClass('show-post');
            //elem.removeClass('hide-post');

            //update pagination
            getNextPage = getNextPage + 1;
            if (getNextPage > maxPageNumber) {
                $(window).unbind('.infscr');
                $('.pagination').remove();
            } else {
                nextPageElem.attr('href', '/page/' + getNextPage + '/');
            }

        });
    }
}

//Prevent scrolling
var keys = [37, 38, 39, 40];

function preventDefault(e) {
    e = e || window.event;
    if (e.preventDefault)
        e.preventDefault();
    e.returnValue = false;
}

function keydown(e) {
    for (var i = keys.length; i--;) {
        if (e.keyCode === keys[i]) {
            preventDefault(e);
            return;
        }
    }
}

function wheel(e) {
    preventDefault(e);
}

function disable_scroll() {
    if (window.addEventListener) {
        window.addEventListener('DOMMouseScroll', wheel, false);
    }
    window.onmousewheel = document.onmousewheel = wheel;
    document.onkeydown = keydown;
}

function enable_scroll() {
    if (window.removeEventListener) {
        window.removeEventListener('DOMMouseScroll', wheel, false);
    }
    window.onmousewheel = document.onmousewheel = document.onkeydown = null;
}

//END Prevent scrolling

$(function() {
    app = window.app;

    //Set the button letter
    var letterContainer = $('#letter');

    if (app.getFirstChar('#blog-title') !== null) {
        letterContainer.html(app.getFirstChar('#blog-title'));
    } else {
        letterContainer.html('');
    }

    if (app.getTag('#tag-search') !== null) {
        $('#tag-search').html(app.getTag('#tag-search'));
        $('.menu-btn').addClass('tags-menu-btn');
    }

    //Call Plugin Functions
    if (app.elemExists('.page-number', '.older-posts')) {
        initInfiniteScroll('.page-number', '.older-posts');
    }

    if (app.elemExists('.page-wrapper')) {
        initReadTime('.page-wrapper');
    }

    initImagesLoaded('#post-container', '.post');
    initSyntaxHighlight('pre code');
    initNavBar();
});
<commit_msg>Use first post blog image only if isn't be set yet<commit_after>//Reusable non plugin stuff goes in app
(function(win, doc) {
    'use strict';
    var app = app || {
        _isSafari: null,
        _isMobile: null,
        _bgImageLink: null,
        _searchedTag: null,
        _buttonLetter: null,
        _postHeaderImg: null
    };

    app.isSafari = function() {
      return parrot.device.browser.name.toLowerCase().indexOf('safari') !== -1
    }

    app.isMobile = function() {
      return parrot.device.type === 'mobile';
    }

    app.getBgImg = function(elem) {
        if (app._bgImageLink === null) {
            if (app.elemExists(elem)) {
                elem = $(elem);
                app._bgImageLink = elem.attr('src');
                elem.remove();
            }
        }

        return app._bgImageLink;
    }

    app.replaceAll = function(str, find, replace) {
        return str.replace(new RegExp(find, 'g'), replace);
    }

    app.elemExists = function(elem) {
        elem = $(elem);

        if (elem.length > 0) {
            return true;
        } else {
            return false;
        }
    }

    app.getTag = function(elem) {

        if (app._searchedTag === null) {
            if (app.elemExists(elem)) {
                var url = window.location.href;
                var splitURL = url.split('tag');
                var tag = app.replaceAll(splitURL[1], '/', '');
                var tagFirstChar;

                tag = app.replaceAll(tag, '-', ' ');
                tagFirstChar = tag.charAt(0).toUpperCase();
                tag = tagFirstChar + tag.substring(1, tag.length);

                app._searchedTag = tag;
            }
        }

        return app._searchedTag;
    }

    app.getFirstChar = function(elem, target) {
        if (app._buttonLetter === null) {
            if (app.elemExists(elem)) {
                var blogTitle = $(elem);
                var letter = blogTitle.val().charAt(0).toUpperCase();

                app._buttonLetter = letter;
            }
        }

        return app._buttonLetter;
    }

    app.aTagWrap = function(elem, elemClass) {
        if (app.elemExists(elem)) {
            var imgs = $(elem);
            if (imgs.length > 0) {
                imgs.each(function() {
                    var $this = $(this);
                    var imgLink = $this.attr('src');

                    var html = '';
                    html = "";

                    $this.wrap(html);
                });

            }
        }
    }

    app.getHeaderImg = function(elem) {
        if (app._postHeaderImg === null) {
            var post = $(elem);

            if (app.elemExists(elem)) {

                var postImg = $(elem + ' img')[0];
                if (typeof(postImg) !== 'undefined') {
                    $(postImg).remove();
                    $(postImg).attr('id', 'bg-img');
                    $('#post-container').append($(postImg));
                    app._postHeaderImg = postImg.src

                }
            }
        }

        return app._postHeaderImg;
    }

    window.app = app;

})(window, document);

var initImagesLoaded = function(container, elem) {

    var posts = document.querySelectorAll(elem);

    imagesLoaded(posts, function() {

        var postContainer = $(container);

        $('.post').fitVids();

        app.aTagWrap('.post-page-post .post-text img', 'fluid-popup');

        $('.fluid-popup').fluidbox();

        postContainer.addClass('show-post');
        postContainer.removeClass('hide-post');
    });
}

var bgImgLoaded = function(elem) {
    var posts = document.querySelectorAll(elem);

    imagesLoaded(posts, function() {

        //Set the bg image

        var bgImg = app.getBgImg('#bg-img') || app.getHeaderImg('.post-page-post .post-text');

        if (bgImg !== null) {
            var header = $('.main-header')
            $('.main-header').css('background-image', 'URL(' + bgImg + ')');
            if (app.isMobile()) {
                header.backstretch(bgImg);
            }
        }

    });
}

var initReadTime = function(elem) {
    elem = $(elem);
    readingTime = $('.post-reading-time');
    if (elem.length > 0 && readingTime.length > 0) {
        elem.readingTime({
            readingTimeTarget: '.post-reading-time',
        });
    }
}

var initSyntaxHighlight = function(elem) {
    var code = $(elem);
    if (code.length > 0) {
        code.each(function(i, e) {
            hljs.highlightBlock(e)
        });
    }
}

var initNavBar = function() {
    if (app.isSafari()) {
        $('#navbar').addClass('navbar-safari');
    }

    $('#openMenu').on('click', function(event) {
        event.preventDefault();
        var elems;

        // if (app.isSafari()){
        //    elems = $('#sidebar, .page-wrapper,#navbar');
        // }else{
        elems = $('#sidebar, .page-wrapper');
        //  }

        elems.toggleClass('opened');

        if (!app.isMobile()) {
            if (elems.hasClass('opened')) {
                disable_scroll();
            } else {
                enable_scroll();
            }
        } else {
            if (elems.hasClass('opened')) {
                document.ontouchmove = function(e) {
                    e.preventDefault();
                }
            } else {
                document.ontouchmove = function(e) {
                    return true;
                }
            }
        }
    });
}

var initInfiniteScroll = function(pageNumber, nextPage) {
    var maxPageNumber = $(pageNumber);
    var nextPageElem = $(nextPage);

    if (maxPageNumber.length > 0 && nextPageElem.length > 0) {
        var splitPageNumber = maxPageNumber.html().split('of');
        var getNextPage = nextPageElem.attr('href').slice(-2).replace('/', '');

        maxPageNumber = parseInt(splitPageNumber[1]);
        getNextPage = parseInt(getNextPage);

        $('#post-container .grid-container').infinitescroll({
            navSelector: ".pagination",
            // selector for the paged navigation (it will be hidden)
            nextSelector: ".pagination .older-posts",
            // selector for the NEXT link (to page 2)
            itemSelector: ".post"

        }, function(newElems) {

            var elem = $(newElems);
            var elemID = elem.attr('id');

            //elem.addClass('show-post');
            //elem.removeClass('hide-post');

            //update pagination
            getNextPage = getNextPage + 1;
            if (getNextPage > maxPageNumber) {
                $(window).unbind('.infscr');
                $('.pagination').remove();
            } else {
                nextPageElem.attr('href', '/page/' + getNextPage + '/');
            }

        });
    }
}

//Prevent scrolling
var keys = [37, 38, 39, 40];

function preventDefault(e) {
    e = e || window.event;
    if (e.preventDefault)
        e.preventDefault();
    e.returnValue = false;
}

function keydown(e) {
    for (var i = keys.length; i--;) {
        if (e.keyCode === keys[i]) {
            preventDefault(e);
            return;
        }
    }
}

function wheel(e) {
    preventDefault(e);
}

function disable_scroll() {
    if (window.addEventListener) {
        window.addEventListener('DOMMouseScroll', wheel, false);
    }
    window.onmousewheel = document.onmousewheel = wheel;
    document.onkeydown = keydown;
}

function enable_scroll() {
    if (window.removeEventListener) {
        window.removeEventListener('DOMMouseScroll', wheel, false);
    }
    window.onmousewheel = document.onmousewheel = document.onkeydown = null;
}

//END Prevent scrolling

$(function() {
    app = window.app;

    //Set the button letter
    var letterContainer = $('#letter');

    if (app.getFirstChar('#blog-title') !== null) {
        letterContainer.html(app.getFirstChar('#blog-title'));
    } else {
        letterContainer.html('');
    }

    if (app.getTag('#tag-search') !== null) {
        $('#tag-search').html(app.getTag('#tag-search'));
        $('.menu-btn').addClass('tags-menu-btn');
    }

    //Need to add id to header image on post page..

    // Only add heade button is not yet setted!

    PostHeaderImage = $('.main-header.post-page-header').css('background-image') !== 'none'

    if (!PostHeaderImage){
      app.getHeaderImg('.post-page-post .post-text')
    }

    if(app.elemExists('#bg-img')){
      bgImgLoaded('#bg-img');
    }

    //Call Plugin Functions
    if (app.elemExists('.page-number', '.older-posts')) {
        initInfiniteScroll('.page-number', '.older-posts');
    }

    if (app.elemExists('.page-wrapper')) {
        initReadTime('.page-wrapper');
    }

    initImagesLoaded('#post-container', '.post');
    initSyntaxHighlight('pre code');
    initNavBar();
});
<|endoftext|>


<commit_before>window.addEventListener("load", function () {
	var host = "ws://localhost:7681/";
	try {
		var socket = new WebSocket(host);

		socket.onopen = function (openEvent) {
			console.log("Connected to server");
			console.log(openEvent);
		};

		socket.onmessage = function (messageEvent) {
			var object = JSON.parse(messageEvent.data);
			console.log(object);
			graph.series[0].data = object;
			console.log("updated");
			window.requestAnimationFrame(function () {graph.render();});
		};

		 socket.onerror = function (errorEvent) {
		 	console.log('WebSocket Status:: Error was reported');
		 	console.log(errorEvent);
		 };

		 socket.onclose = function (closeEvent) {
		 	console.log( 'WebSocket Status:: Socket Closed');
		 	console.log(closeEvent);
		 };
	} catch (exception) { console.log(exception); }

	window.graph = new Rickshaw.Graph( {
		element: document.querySelector("#chart"),
		width: 1920,
		height: 1080,
		series: [{
			color: 'steelblue',
			data: [
			{ x: 0, y: 40 },
			{ x: 1, y: 49 },
			{ x: 2, y: 38 },
			{ x: 3, y: 30 },
			{ x: 4, y: 32 } ]
		}]
	});

	graph.render();
});

<commit_msg>Better layout<commit_after>window.addEventListener("load", function () {
	var host = "ws://localhost:7681/";
	try {
		var socket = new WebSocket(host);

		socket.onopen = function (openEvent) {
			console.log("Connected to server");
			console.log(openEvent);
		};

		socket.onmessage = function (messageEvent) {
			var object = JSON.parse(messageEvent.data);
			console.log(object);
			graph.series[0].data = object;
			console.log("updated");
			window.requestAnimationFrame(function () {graph.render();});
		};

		 socket.onerror = function (errorEvent) {
		 	console.log('WebSocket Status:: Error was reported');
		 	console.log(errorEvent);
		 };

		 socket.onclose = function (closeEvent) {
		 	console.log( 'WebSocket Status:: Socket Closed');
		 	console.log(closeEvent);
		 };
	} catch (exception) { console.log(exception); }

	window.graph = new Rickshaw.Graph( {
		element: document.querySelector("#chart"),
		width: 1800,
		height: 980,
		series: [{
			color: 'steelblue',
			data: [
			{ x: 0, y: 40 },
			{ x: 1, y: 49 },
			{ x: 2, y: 38 },
			{ x: 3, y: 30 },
			{ x: 4, y: 32 } ]
		}]
	});

	graph.render();
});

<|endoftext|>


<commit_before>const { readdir, readFile, writeFile } = require("fs").promises;
const fetch = require("node-fetch");

const forEachSource = async (path, cb) => {
	const entries = await readdir(path, {
		withFileTypes: true
	});
	for (const entry of entries) {
		if (entry.isFile() && entry.name === ".source.json") {
			const source = await readFile(`${path}/${entry.name}`, "utf8");
			await cb(path, JSON.parse(source));
		} else if (entry.isDirectory()) {
			await forEachSource(`${path}/${entry.name}`, cb);
		}
	}
};

const fetchBody = async (url, options) => {
	const res = await fetch(url, options);
	if (res.ok) {
		if (res.headers.get("content-type").includes("json")) {
			return res.json();
		} else {
			return res.text();
		}
	} else {
		throw new Error(`fetch ${url} -> ${res.status}: ${await res.text()}`);
	}
};

const github = async source => {
	const repoUrl = `https://api.github.com/repos/${source.repo}`;
	const repo = await fetchBody(repoUrl);
	const readme = await fetchBody(`${repoUrl}/readme`);
	const topics = await fetchBody(`${repoUrl}/topics`, {
		headers: {
			accept: "application/vnd.github.mercy-preview+json"
		}
	});
	const data = {
		date: repo.pushed_at,
		metadata: {
			title: repo.name,
			short_description: repo.description,
			tags: topics.names,
			homepage: repo.homepage,
			language: repo.language,
			license: repo.license.spdx_id
		}
	};

	return {
		readme: prepareGitHubReadme(readme),
		data
	};
};

const prepareGitHubReadme = readme =>
	Buffer.from(readme.content, readme.encoding)
		.toString()
		// Remove main heading
		.replace(/^# .+$/gm, "")
		// Make relative URLs absolute
		.replace(
			/\[([^\[\]]+)\]\(([^\)]+)\)/g,
			(_, p1, p2) => `[${p1}](${new URL(p2, readme.html_url)})`
		)
		// Replace language tags with PrismJS supported tags
		// https://prismjs.com/#supported-languages
		.replace(/```sh/g, "```shell-session")
		.replace(/```command/g, "```shell-session");

const sources = {
	github
};

const main = async () => {
	await forEachSource("src", async (path, source) => {
		if (sources[source.source]) {
			const { readme, data } = await sources[source.source](source);
			await writeFile(`${path}/index.md`, readme, "utf8");
			await writeFile(
				`${path}/index.11tydata.json`,
				JSON.stringify(data, null, "\t"),
				"utf8"
			);
		} else {
			console.warn(`Unknown source ${source.source} in ${path}`);
		}
	});
};

main().catch(err => {
	console.error(err);
	process.exitCode = 1;
});
<commit_msg>Make compatible with Node 10.8<commit_after>const { readdir, readFile, stat, writeFile } = require("fs").promises;
const fetch = require("node-fetch");

const forEachSource = async (path, cb) => {
	const entries = await readdir(path);
	for (const entry of entries) {
		const fullName = `${path}/${entry}`;
		const stats = await stat(fullName);
		if (stats.isFile() && entry === ".source.json") {
			const source = await readFile(fullName, "utf8");
			await cb(path, JSON.parse(source));
		} else if (stats.isDirectory()) {
			await forEachSource(fullName, cb);
		}
	}
};

const fetchBody = async (url, options) => {
	const res = await fetch(url, options);
	if (res.ok) {
		if (res.headers.get("content-type").includes("json")) {
			return res.json();
		} else {
			return res.text();
		}
	} else {
		throw new Error(`fetch ${url} -> ${res.status}: ${await res.text()}`);
	}
};

const github = async source => {
	const repoUrl = `https://api.github.com/repos/${source.repo}`;
	const repo = await fetchBody(repoUrl);
	const readme = await fetchBody(`${repoUrl}/readme`);
	const topics = await fetchBody(`${repoUrl}/topics`, {
		headers: {
			accept: "application/vnd.github.mercy-preview+json"
		}
	});
	const data = {
		date: repo.pushed_at,
		metadata: {
			title: repo.name,
			short_description: repo.description,
			tags: topics.names,
			homepage: repo.homepage,
			language: repo.language,
			license: repo.license.spdx_id
		}
	};

	return {
		readme: prepareGitHubReadme(readme),
		data
	};
};

const prepareGitHubReadme = readme =>
	Buffer.from(readme.content, readme.encoding)
		.toString()
		// Remove main heading
		.replace(/^# .+$/gm, "")
		// Make relative URLs absolute
		.replace(
			/\[([^\[\]]+)\]\(([^\)]+)\)/g,
			(_, p1, p2) => `[${p1}](${new URL(p2, readme.html_url)})`
		)
		// Replace language tags with PrismJS supported tags
		// https://prismjs.com/#supported-languages
		.replace(/```sh/g, "```shell-session")
		.replace(/```command/g, "```shell-session");

const sources = {
	github
};

const main = async () => {
	await forEachSource("src", async (path, source) => {
		if (sources[source.source]) {
			const { readme, data } = await sources[source.source](source);
			await writeFile(`${path}/index.md`, readme, "utf8");
			await writeFile(
				`${path}/index.11tydata.json`,
				JSON.stringify(data, null, "\t"),
				"utf8"
			);
		} else {
			console.warn(`Unknown source ${source.source} in ${path}`);
		}
	});
};

main().catch(err => {
	console.error(err);
	process.exitCode = 1;
});
<|endoftext|>