<commit_before>/*! geotrigger-js - v0.1.2 - 2013-11-19
*   Copyright (c) 2013 Environmental Systems Research Institute, Inc.
*   Apache License*/

(function(e,t){"object"==typeof module&&"object"==typeof module.exports&&(XMLHttpRequest=require("xmlhttprequest").XMLHttpRequest,exports=module.exports=t()),"object"==typeof window&&(e.Geotrigger=t())})(this,function(){function e(e){this._queue=[],this._requestQueue=[],this._events={};var s={preferLocalStorage:!0,persistSession:"undefined"!=typeof module&&module.exports?!1:!0,geotriggersUrl:t,tokenUrl:i,registerDeviceUrl:r,automaticRegistation:!0,proxy:!1};if(!e||!e.clientId)throw Error("Geotrigger.Session requires an `clientId` or a `session` parameter.");if(!e.proxy&&!n)throw Error("This browser does not support CORS and a proxy has not been set.");o.merge(this,o.merge(s,e)),this.authenticatedAs=this.clientId&&this.clientSecret?"application":"device",this.key="geotriggers_"+this.authenticatedAs+"_"+this.clientId,this.persistSession&&(this.preferLocalStorage&&h?o.merge(this,c.get(this.key)):a&&o.merge(this,p.get(this.key))),(this.token&&Date.now()>new Date(this.expiresOn).getTime()||!this.token)&&this.refresh()}var t="https://geotrigger.arcgis.com/",i="https://arcgis.com/sharing/oauth2/token",r="https://arcgis.com/sharing/oauth2/registerDevice",s={},n=!0;"object"==typeof window&&(n=!!(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest)),Function.prototype.bind||(Function.prototype.bind=function(e){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var t=Array.prototype.slice.call(arguments,1),i=this,r=function(){},s=function(){return i.apply(this instanceof r&&e?this:e,t.concat(Array.prototype.slice.call(arguments)))};return r.prototype=this.prototype,s.prototype=new r,s}),e.prototype.authenticated=function(){return!!this.token},e.prototype.refresh=function(){if(!this.refreshing){this.refreshing=!0;var e=this.tokenUrl,t={client_id:this.clientId,f:"json"};this.clientSecret?(t.client_secret=this.clientSecret,t.grant_type="client_credentials"):this.refreshToken?(t.refresh_token=this.refreshToken,t.grant_type="refresh_token"):this.automaticRegistation&&(e=this.registerDeviceUrl),this.request(e,t,function(e,t){if(this.refreshing=!1,e)return this.emit("authentication:error",e),void 0;for(this.expiresOn=new Date((new Date).getTime()+1e3*(t.expires_in-300)),t.deviceToken?(this.refreshToken=t.deviceToken.refresh_token,this.token=t.deviceToken.access_token,this.deviceId=t.device.deviceId):(this.refreshToken=t.refresh_token,this.token=t.access_token),this.persistSession&&this.persist();this._queue.length;)this._queue.shift().apply(this);for(;this._requestQueue.length;)this.request.apply(this,this._requestQueue.shift());this.emit("authentication:success")}.bind(this))}},e.prototype.toJSON=function(){var e={};for(var t in this)this.hasOwnProperty(t)&&this[t]&&!t.match(/^_.+/)&&(e[t]=this[t]);return e},e.prototype.on=function(e,t){this._events[e]===void 0&&(this._events[e]=[]),this._events[e].push(t)},e.prototype.emit=function(e){var t=[].splice.call(arguments,1);if(this._events[e]instanceof Array)for(var i=this._events[e],r=0,s=i.length;s>r;r++)i[r].apply(this,t)},e.prototype.off=function(e,t){if(this._events[e]instanceof Array)for(var i=this._events[e],r=0,s=i.length;s>r;r++)if(i[r]===t){i.splice(r,1);break}},e.prototype.queue=function(e){return this.token?(e.apply(this),void 0):(this._queue.push(e),this.refresh(),void 0)},e.prototype.request=function(e,t,i){var r,s,n,h,a=Array.prototype.slice.apply(arguments),c=!e.match(/^https?:\/\//),p=c?this.geotriggersUrl+e:e;if(this.proxy&&(p=this.proxy+p),"function"==typeof t&&(i=t,t={}),c&&!this.token)return this._requestQueue.push(a),this.refresh(),void 0;var u=function(){try{r=JSON.parse(h.responseText),n=r.error?null:r,s=r.error?r.error:null}catch(e){n=null,s={type:"parse_error",message:"cound not parse response as JSON"}}if(s&&"invalidHeader"===s.type&&s.headers.Authorization)this._requestQueue.push(a),this.refresh();else if(s)if(s)i(s,null,h);else{var t={type:"unexpected_response",message:"the api returned a non JSON or unexpected data"};i(t,null,h)}else i(null,n,h)}.bind(this),l=function(){JSON.parse(h.responseText)}.bind(this),f=function(){4===h.readyState&&400>h.status?u():4===h.readyState&&h.status>=400&&l()}.bind(this);h=new XMLHttpRequest,h.onreadystatechange=f;var d;c?(t.token=this.token,d=JSON.stringify(t)):d=o.serialize(t),h.open("POST",p),h.setRequestHeader("Content-Type",c?"application/json":"application/x-www-form-urlencoded"),h.send(d)},e.prototype.persist=function(){var e={};this.clientId&&(e.clientId=this.clientId),this.clientSecret&&(e.clientSecret=this.clientSecret),this.token&&(e.token=this.token),this.refreshToken&&(e.refreshToken=this.refreshToken),this.deviceId&&(e.deviceId=this.deviceId),this.preferLocalStorage&&h?c.set(this.key,e):a&&p.set(this.key,e)},e.prototype.destroy=function(){this.preferLocalStorage&&h?c.erase(this.key):a&&p.erase(this.key)},s.Session=e;var o={merge:function(e,t){for(var i in t)t.hasOwnProperty(i)&&(e[i]=t[i]);return e},isObject:function(e){return"[object Object]"===Object.prototype.toString.call(e)},serialize:function(e,t){var i=encodeURIComponent,r=[];for(var s in e)if(e.hasOwnProperty(s)){var n,h=t?t+"["+s+"]":s,a=e[s];n=o.isObject(a)?o.serialize(a,h):i(h)+"="+i(a),r.push(n)}return r.join("&")}},h="object"==typeof window&&"object"==typeof window.localStorage?!0:!1,a="object"==typeof document&&"string"==typeof document.cookie?!0:!1,c={set:function(e,t){window.localStorage.setItem(e,JSON.stringify(t))},get:function(e){return JSON.parse(window.localStorage.getItem(e))},erase:function(e){window.localStorage.removeItem(e)}},p={get:function(e){var t=document.cookie.match(RegExp(e+"=[a-zA-Z0-9.()=|%/_]+($|;)","g"));return t&&t[0]?JSON.parse(t[0].substring(e.length+1,t[0].length).replace(";",""))||null:null},set:function(e,t,i){var r=[e+"="+JSON.stringify(t),"path=/","domain="+window.location.host],s=new Date;return s.setFullYear(s.getFullYear()+1),r.push(s.toGMTString()),i&&r.push("secure"),document.cookie=r.join("; ")},erase:function(e){document.cookie=e+"; "+new Date(0).toUTCString()}};return s});<commit_msg>rebuild new version<commit_after>/*! geotrigger-js - v0.1.2 - 2013-11-20
*   Copyright (c) 2013 Environmental Systems Research Institute, Inc.
*   Apache License*/

(function(e,t){"object"==typeof module&&"object"==typeof module.exports&&(XMLHttpRequest=require("xmlhttprequest").XMLHttpRequest,exports=module.exports=t()),"object"==typeof window&&(e.Geotrigger=t())})(this,function(){function e(e){this._queue=[],this._requestQueue=[],this._events={};var s={preferLocalStorage:!0,persistSession:"undefined"!=typeof module&&module.exports?!1:!0,geotriggersUrl:t,tokenUrl:i,registerDeviceUrl:r,automaticRegistation:!0,proxy:!1};if(!e||!e.clientId)throw Error("Geotrigger.Session requires an `clientId` or a `session` parameter.");if(!e.proxy&&!n)throw Error("This browser does not support CORS and a proxy has not been set.");o.merge(this,o.merge(s,e)),this.authenticatedAs=this.clientId&&this.clientSecret?"application":"device",this.key="geotriggers_"+this.authenticatedAs+"_"+this.clientId,this.persistSession&&(this.preferLocalStorage&&h?o.merge(this,c.get(this.key)):a&&o.merge(this,p.get(this.key))),(this.token&&Date.now()>new Date(this.expiresOn).getTime()||!this.token)&&this.refresh()}var t="https://geotrigger.arcgis.com/",i="https://arcgis.com/sharing/oauth2/token",r="https://arcgis.com/sharing/oauth2/registerDevice",s={},n=!0;"object"==typeof window&&(n=!!(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest)),Function.prototype.bind||(Function.prototype.bind=function(e){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var t=Array.prototype.slice.call(arguments,1),i=this,r=function(){},s=function(){return i.apply(this instanceof r&&e?this:e,t.concat(Array.prototype.slice.call(arguments)))};return r.prototype=this.prototype,s.prototype=new r,s}),e.prototype.authenticated=function(){return!!this.token},e.prototype.refresh=function(){if(!this.refreshing){this.refreshing=!0;var e=this.tokenUrl,t={client_id:this.clientId,f:"json"};this.clientSecret?(t.client_secret=this.clientSecret,t.grant_type="client_credentials"):this.refreshToken?(t.refresh_token=this.refreshToken,t.grant_type="refresh_token"):this.automaticRegistation&&(e=this.registerDeviceUrl),this.request(e,t,function(e,t){if(this.refreshing=!1,e)return this.emit("authentication:error",e),void 0;for(this.expiresOn=new Date((new Date).getTime()+1e3*(t.expires_in-300)),t.deviceToken?(this.refreshToken=t.deviceToken.refresh_token,this.token=t.deviceToken.access_token,this.deviceId=t.device.deviceId):(this.refreshToken=t.refresh_token,this.token=t.access_token),this.persistSession&&this.persist();this._queue.length;)this._queue.shift().apply(this);for(;this._requestQueue.length;)this.request.apply(this,this._requestQueue.shift());this.emit("authentication:success")}.bind(this))}},e.prototype.toJSON=function(){var e={};for(var t in this)this.hasOwnProperty(t)&&this[t]&&!t.match(/^_.+/)&&(e[t]=this[t]);return e},e.prototype.on=function(e,t){this._events[e]===void 0&&(this._events[e]=[]),this._events[e].push(t)},e.prototype.emit=function(e){var t=[].splice.call(arguments,1);if(this._events[e]instanceof Array)for(var i=this._events[e],r=0,s=i.length;s>r;r++)i[r].apply(this,t)},e.prototype.off=function(e,t){if(this._events[e]instanceof Array)for(var i=this._events[e],r=0,s=i.length;s>r;r++)if(i[r]===t){i.splice(r,1);break}},e.prototype.queue=function(e){return this.token?(e.apply(this),void 0):(this._queue.push(e),this.refresh(),void 0)},e.prototype.request=function(e,t,i){var r,s,n,h,a=Array.prototype.slice.apply(arguments),c=!e.match(/^https?:\/\//),p=c?this.geotriggersUrl+e:e;if(this.proxy&&(p=this.proxy+p),"function"==typeof t&&(i=t,t={}),c&&!this.token)return this._requestQueue.push(a),this.refresh(),void 0;var u=function(){try{r=JSON.parse(h.responseText),n=r.error?null:r,s=r.error?r.error:null}catch(e){n=null,s={type:"parse_error",message:"cound not parse response as JSON"}}if(s&&"invalidHeader"===s.type&&s.headers.Authorization)this._requestQueue.push(a),this.refresh();else if(s)if(s)i(s,null,h);else{var t={type:"unexpected_response",message:"the api returned a non JSON or unexpected data"};i(t,null,h)}else i(null,n,h)}.bind(this),l=function(){var e=JSON.parse(h.responseText),t={type:"http_error",message:e};i(t,null,h)}.bind(this),f=function(){4===h.readyState&&400>h.status?u():4===h.readyState&&h.status>=400&&l()}.bind(this);h=new XMLHttpRequest,h.onreadystatechange=f;var d;c?(t.token=this.token,d=JSON.stringify(t)):d=o.serialize(t),h.open("POST",p),h.setRequestHeader("Content-Type",c?"application/json":"application/x-www-form-urlencoded"),h.send(d)},e.prototype.persist=function(){var e={};this.clientId&&(e.clientId=this.clientId),this.clientSecret&&(e.clientSecret=this.clientSecret),this.token&&(e.token=this.token),this.refreshToken&&(e.refreshToken=this.refreshToken),this.deviceId&&(e.deviceId=this.deviceId),this.preferLocalStorage&&h?c.set(this.key,e):a&&p.set(this.key,e)},e.prototype.destroy=function(){this.preferLocalStorage&&h?c.erase(this.key):a&&p.erase(this.key)},s.Session=e;var o={merge:function(e,t){for(var i in t)t.hasOwnProperty(i)&&(e[i]=t[i]);return e},isObject:function(e){return"[object Object]"===Object.prototype.toString.call(e)},serialize:function(e,t){var i=encodeURIComponent,r=[];for(var s in e)if(e.hasOwnProperty(s)){var n,h=t?t+"["+s+"]":s,a=e[s];n=o.isObject(a)?o.serialize(a,h):i(h)+"="+i(a),r.push(n)}return r.join("&")}},h="object"==typeof window&&"object"==typeof window.localStorage?!0:!1,a="object"==typeof document&&"string"==typeof document.cookie?!0:!1,c={set:function(e,t){window.localStorage.setItem(e,JSON.stringify(t))},get:function(e){return JSON.parse(window.localStorage.getItem(e))},erase:function(e){window.localStorage.removeItem(e)}},p={get:function(e){var t=document.cookie.match(RegExp(e+"=[a-zA-Z0-9.()=|%/_]+($|;)","g"));return t&&t[0]?JSON.parse(t[0].substring(e.length+1,t[0].length).replace(";",""))||null:null},set:function(e,t,i){var r=[e+"="+JSON.stringify(t),"path=/","domain="+window.location.host],s=new Date;return s.setFullYear(s.getFullYear()+1),r.push(s.toGMTString()),i&&r.push("secure"),document.cookie=r.join("; ")},erase:function(e){document.cookie=e+"; "+new Date(0).toUTCString()}};return s});<|endoftext|>


<commit_before>/**
 *
 * GPS Geolocation with device orientation in real-time
 */

(function () {
    /**constructor function**/
    function GPSController() {
        this._liveTrackingActivated = false;
        this._timer = undefined;
        this._timerMiliseconds = 2000;
        this.createGPSButton();
    }

    Object.defineProperties(GPSController.prototype, {
        liveTrackingActivated: {
            get: function () {
                return this._liveTrackingActivated;
            },
            set: function (value) {
                this._liveTrackingActivated = value;
            }
        },
        timer: {
            get: function () {
                return this._timer;
            },
            set: function (value) {
                this._timer = value;
            }
        },
        timerMiliseconds: {
            get: function () {
                return this._timerMiliseconds;
            },
            set: function (value) {
                this._timerMiliseconds = value;
            }
        }
    });

    GPSController.prototype.createGPSButton = function () {
        var scope = this;

        var button = document.getElementById("gpsButton");
        button.className = "cesium-button cesium-toolbar-button tracking-deactivated";
        button.title = "View GPS (single-click: one time, double-click: real-time)";

        // replace the 3D/2D button with this GPS button
        var customCesiumViewerToolbar = document.getElementsByClassName("cesium-viewer-toolbar")[0];
        var customGlobeButton = customCesiumViewerToolbar.getElementsByClassName("cesium-sceneModePicker-wrapper cesium-toolbar-button")[0];
        customCesiumViewerToolbar.replaceChild(button, customGlobeButton);
    }

    GPSController.prototype.handleDclick = function () {
        var scope = this;
        if (scope._liveTrackingActivated) {
            scope._liveTrackingActivated = false;
            scope.stopTracking();
        } else {
            scope._liveTrackingActivated = true;
            // tracking in intervals of miliseconds
            scope.startTracking();
        }
    }

    GPSController.prototype.handleClick = function () {
        var scope = this;
        if (scope._liveTrackingActivated) {
            scope._liveTrackingActivated = false;
            scope.stopTracking();
        } else {
            // one time tracking
            scope.startTracking();
        }
    }

    GPSController.prototype.startTracking = function () {
        var scope = this;

        if (scope._liveTrackingActivated) {
            var button = document.getElementById("gpsButton");
            button.classList.remove("tracking-deactivated");
            button.classList.add("tracking-activated");
        }

        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(showPosition, showError);
        } else {
            alert("Geolocation is not supported by this browser.");
        }

        function showPosition(position) {
            getLocation();

            function getLocation() {
                if (window.DeviceOrientationEvent) {
                    window.addEventListener('deviceorientation', function auxOrientation(event) {
                        // one-time event
                        window.removeEventListener('deviceorientation', auxOrientation, false);
                        flyToLocationWithOrientation(position, event);
                    }, false);
                } else {
                    alert("Exact geolocation is not supported by this device.");
                    flyToLocationWithOrientation(position, event);
                }
            }

            function flyToLocationWithOrientation(position, ori) {
                var oriAlpha = 0;
                var oriBeta = 0;
                var oriGamma = 0;

                if (Cesium.defined(ori)) {
                    // ALPHA
                    if (ori.webkitCompassHeading) {
                        oriAlpha = ori.webkitCompassHeading;
                    } else if (Cesium.defined(ori.alpha)) {
                        oriAlpha = ori.alpha;
                    }
                    // alpha is in [0,360) degrees, while heading is [-pi,pi), where positive points eastward
                    if (oriAlpha < 180) {
                        oriAlpha = Cesium.Math.toRadians(-oriAlpha);
                    } else {
                        oriAlpha = Cesium.Math.toRadians(180 - (oriAlpha - 180));
                    }

                    // BETA
                    if (Cesium.defined(ori.beta)) {
                        oriBeta = Cesium.Math.toRadians(ori.beta - 90);
                    }
                }

                cesiumCamera.flyTo({
                    destination: Cesium.Cartesian3.fromDegrees(position.coords.longitude, position.coords.latitude, 2),
                    orientation: {
                        heading: oriAlpha,
                        pitch: oriBeta,
                        roll: oriGamma
                    },
                    complete: function () {
                        if (scope._liveTrackingActivated) {
                            // real-time tracking
                            scope._timer = setTimeout(function () {
                                // only check orientation in real-time
                                showPosition(position);
                                // also check position in real-time
                                // scope.startTracking();
                            }, scope._timerMiliseconds);
                        }
                    }
                });
            }
        }

        function showError(error) {
            switch (error.code) {
                case error.PERMISSION_DENIED:
                    showPopupInfoBoxWithTextContent("Error", "Geolocation denied by user.");
                    break;
                case error.POSITION_UNAVAILABLE:
                    showPopupInfoBoxWithTextContent("Error", "Location information is unavailable.");
                    break;
                case error.TIMEOUT:
                    showPopupInfoBoxWithTextContent("Error", "Location request has timed out.");
                    break;
                case error.UNKNOWN_ERROR:
                    showPopupInfoBoxWithTextContent("Error", "An unknown error has occurred while requesting location information.");
                    break;
            }
        }
    }

    GPSController.prototype.stopTracking = function () {
        var scope = this;

        var button = document.getElementById("gpsButton");
        button.classList.remove("tracking-activated");
        button.classList.add("tracking-deactivated");

        clearTimeout(scope._timer);
    }

    window.GPSController = GPSController;
})();
<commit_msg>Adjusted time interval between GPS calls.<commit_after>/**
 *
 * GPS Geolocation with device orientation in real-time
 */

(function () {
    /**constructor function**/
    function GPSController() {
        this._liveTrackingActivated = false;
        this._timer = undefined;
        this._timerMiliseconds = 1000;
        this.createGPSButton();
    }

    Object.defineProperties(GPSController.prototype, {
        liveTrackingActivated: {
            get: function () {
                return this._liveTrackingActivated;
            },
            set: function (value) {
                this._liveTrackingActivated = value;
            }
        },
        timer: {
            get: function () {
                return this._timer;
            },
            set: function (value) {
                this._timer = value;
            }
        },
        timerMiliseconds: {
            get: function () {
                return this._timerMiliseconds;
            },
            set: function (value) {
                this._timerMiliseconds = value;
            }
        }
    });

    GPSController.prototype.createGPSButton = function () {
        var scope = this;

        var button = document.getElementById("gpsButton");
        button.className = "cesium-button cesium-toolbar-button tracking-deactivated";
        button.title = "View GPS (single-click: one time, double-click: real-time)";

        // replace the 3D/2D button with this GPS button
        var customCesiumViewerToolbar = document.getElementsByClassName("cesium-viewer-toolbar")[0];
        var customGlobeButton = customCesiumViewerToolbar.getElementsByClassName("cesium-sceneModePicker-wrapper cesium-toolbar-button")[0];
        customCesiumViewerToolbar.replaceChild(button, customGlobeButton);
    }

    GPSController.prototype.handleDclick = function () {
        var scope = this;
        if (scope._liveTrackingActivated) {
            scope._liveTrackingActivated = false;
            scope.stopTracking();
        } else {
            scope._liveTrackingActivated = true;
            // tracking in intervals of miliseconds
            scope.startTracking();
        }
    }

    GPSController.prototype.handleClick = function () {
        var scope = this;
        if (scope._liveTrackingActivated) {
            scope._liveTrackingActivated = false;
            scope.stopTracking();
        } else {
            // one time tracking
            scope.startTracking();
        }
    }

    GPSController.prototype.startTracking = function () {
        var scope = this;

        if (scope._liveTrackingActivated) {
            var button = document.getElementById("gpsButton");
            button.classList.remove("tracking-deactivated");
            button.classList.add("tracking-activated");
        }

        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(showPosition, showError);
        } else {
            alert("Geolocation is not supported by this browser.");
        }

        function showPosition(position) {
            getLocation();

            function getLocation() {
                if (window.DeviceOrientationEvent) {
                    window.addEventListener('deviceorientation', function auxOrientation(event) {
                        // one-time event
                        window.removeEventListener('deviceorientation', auxOrientation, false);
                        flyToLocationWithOrientation(position, event);
                    }, false);
                } else {
                    alert("Exact geolocation is not supported by this device.");
                    flyToLocationWithOrientation(position, event);
                }
            }

            function flyToLocationWithOrientation(position, ori) {
                var oriAlpha = 0;
                var oriBeta = 0;
                var oriGamma = 0;

                if (Cesium.defined(ori)) {
                    // ALPHA
                    if (ori.webkitCompassHeading) {
                        oriAlpha = ori.webkitCompassHeading;
                    } else if (Cesium.defined(ori.alpha)) {
                        oriAlpha = ori.alpha;
                    }
                    // alpha is in [0,360) degrees, while heading is [-pi,pi), where positive points eastward
                    if (oriAlpha < 180) {
                        oriAlpha = Cesium.Math.toRadians(-oriAlpha);
                    } else {
                        oriAlpha = Cesium.Math.toRadians(180 - (oriAlpha - 180));
                    }

                    // BETA
                    if (Cesium.defined(ori.beta)) {
                        oriBeta = Cesium.Math.toRadians(ori.beta - 90);
                    }
                }

                cesiumCamera.flyTo({
                    destination: Cesium.Cartesian3.fromDegrees(position.coords.longitude, position.coords.latitude, 2),
                    orientation: {
                        heading: oriAlpha,
                        pitch: oriBeta,
                        roll: oriGamma
                    },
                    complete: function () {
                        if (scope._liveTrackingActivated) {
                            // real-time tracking
                            scope._timer = setTimeout(function () {
                                // only check orientation in real-time
                                showPosition(position);
                                // also check position in real-time
                                // scope.startTracking();
                            }, scope._timerMiliseconds);
                        }
                    }
                });
            }
        }

        function showError(error) {
            switch (error.code) {
                case error.PERMISSION_DENIED:
                    showPopupInfoBoxWithTextContent("Error", "Geolocation denied by user.");
                    break;
                case error.POSITION_UNAVAILABLE:
                    showPopupInfoBoxWithTextContent("Error", "Location information is unavailable.");
                    break;
                case error.TIMEOUT:
                    showPopupInfoBoxWithTextContent("Error", "Location request has timed out.");
                    break;
                case error.UNKNOWN_ERROR:
                    showPopupInfoBoxWithTextContent("Error", "An unknown error has occurred while requesting location information.");
                    break;
            }
        }
    }

    GPSController.prototype.stopTracking = function () {
        var scope = this;

        var button = document.getElementById("gpsButton");
        button.classList.remove("tracking-activated");
        button.classList.add("tracking-deactivated");

        clearTimeout(scope._timer);
    }

    window.GPSController = GPSController;
})();
<|endoftext|>


<commit_before>SC.initialize({
    client_id: "5a8edbed865ed2b31acf4d9720696e7f"
})

$(document).on('ready', function() {
	var id = Plugin.getConfig()['attr']['id']
	if (!id) return

	SC.get("/tracks/"+id+".json", null, function(track) {
		appendLi(track)
	})
})

function search(query, cb) {
	SC.get("/tracks", {q: query, limit: 5}, cb)
}

function appendLi(track) {
	var a = $('').text(track.title).append(''),
		li = $('
').data('id', track.id).append(a)

	$('ul').append(li)
}

$('input').on('keypress', function(e) {
	alert('pony')
	$('ul').html('')
	search($(this).val(), function(tracks) {
		tracks.forEach(function(track) {
			appendLi(track)
		})
	})
})

$('ul').on('tap', 'li', function() {
	Plugin.sendConfig({'id': parseInt($(this).data('id'))})
})<commit_msg>Small fix<commit_after>SC.initialize({
    client_id: "5a8edbed865ed2b31acf4d9720696e7f"
})

$(document).on('ready', function() {
	var id = Plugin.getConfig()['attr']['id']
	if (!id) return

	SC.get("/tracks/"+id+".json", null, function(track) {
		appendLi(track)
	})
})

function search(query, cb) {
	SC.get("/tracks", {q: query, limit: 5}, cb)
}

function appendLi(track) {
	var a = $('').text(track.title).append(''),
		li = $('
').data('id', track.id).append(a)

	$('ul').append(li)
}

$('input').on('keyup', function(e) {
	$('ul').html('')
	search($(this).val(), function(tracks) {
		tracks.forEach(function(track) {
			appendLi(track)
		})
	})
})

$('ul').on('tap', 'li', function() {
	Plugin.sendConfig({'id': parseInt($(this).data('id'))})
})<|endoftext|>


<commit_before>/**
 * Route Mappings
 * (sails.config.routes)
 *
 * Your routes map URLs to views and controllers.
 *
 * If Sails receives a URL that doesn't match any of the routes below,
 * it will check for matching files (images, scripts, stylesheets, etc.)
 * in your assets directory.  e.g. `http://localhost:1337/images/foo.jpg`
 * might match an image file: `/assets/images/foo.jpg`
 *
 * Finally, if those don't match either, the default 404 handler is triggered.
 * See `api/responses/notFound.js` to adjust your app's 404 logic.
 *
 * Note: Sails doesn't ACTUALLY serve stuff from `assets`-- the default Gruntfile in Sails copies
 * flat files from `assets` to `.tmp/public`.  This allows you to do things like compile LESS or
 * CoffeeScript for the front-end.
 *
 * For more information on configuring custom routes, check out:
 * http://sailsjs.org/#/documentation/concepts/Routes/RouteTargetSyntax.html
 */

module.exports.routes = {

  /***************************************************************************
  *                                                                          *
  * Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
  * etc. depending on your default view engine) your home page.              *
  *                                                                          *
  * (Alternatively, remove this and add an `index.html` file in your         *
  * `assets` directory)                                                      *
  *                                                                          *
  ***************************************************************************/

  '/': {
    view: 'homepage'
  },

  /***************************************************************************
  *                                                                          *
  * Custom routes here...                                                    *
  *                                                                          *
  *  If a request to a URL doesn't match any of the custom routes above, it  *
  * is matched against Sails route blueprints. See `config/blueprints.js`    *
  * for configuration options and examples.                                  *
  *                                                                          *
  ***************************************************************************/

  /***************************************************************************
   *                                                                         *
   * Passport Auth routes                                                    *
   *                                                                         *
   **************************************************************************/
  'get /login': 'AuthController.login',
  'get /logout': 'AuthController.logout',
  'get /register': 'AuthController.register',

  'post /auth/local': 'AuthController.callback',
  'post /auth/local/:action': 'AuthController.callback',

  'get /auth/:provider': 'AuthController.provider',
  'get /auth/:provider/callback': 'AuthController.callback',
  'get /auth/:provider/:action': 'AuthController.callback'

};
<commit_msg>Change home route to use controller not view.<commit_after>/**
 * Route Mappings
 * (sails.config.routes)
 *
 * Your routes map URLs to views and controllers.
 *
 * If Sails receives a URL that doesn't match any of the routes below,
 * it will check for matching files (images, scripts, stylesheets, etc.)
 * in your assets directory.  e.g. `http://localhost:1337/images/foo.jpg`
 * might match an image file: `/assets/images/foo.jpg`
 *
 * Finally, if those don't match either, the default 404 handler is triggered.
 * See `api/responses/notFound.js` to adjust your app's 404 logic.
 *
 * Note: Sails doesn't ACTUALLY serve stuff from `assets`-- the default Gruntfile in Sails copies
 * flat files from `assets` to `.tmp/public`.  This allows you to do things like compile LESS or
 * CoffeeScript for the front-end.
 *
 * For more information on configuring custom routes, check out:
 * http://sailsjs.org/#/documentation/concepts/Routes/RouteTargetSyntax.html
 */

module.exports.routes = {

  /***************************************************************************
  *                                                                          *
  * Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
  * etc. depending on your default view engine) your home page.              *
  *                                                                          *
  * (Alternatively, remove this and add an `index.html` file in your         *
  * `assets` directory)                                                      *
  *                                                                          *
  ***************************************************************************/

  // Use a route instead of a view so ew can override the title and HEAD info
  '/': 'PageController.home',

  //'/': {
  //  view: 'homepage'
  //},

  /***************************************************************************
  *                                                                          *
  * Custom routes here...                                                    *
  *                                                                          *
  *  If a request to a URL doesn't match any of the custom routes above, it  *
  * is matched against Sails route blueprints. See `config/blueprints.js`    *
  * for configuration options and examples.                                  *
  *                                                                          *
  ***************************************************************************/

  /***************************************************************************
   *                                                                         *
   * Passport Auth routes                                                    *
   *                                                                         *
   **************************************************************************/
  'get /login': 'AuthController.login',
  'get /logout': 'AuthController.logout',
  'get /register': 'AuthController.register',

  'post /auth/local': 'AuthController.callback',
  'post /auth/local/:action': 'AuthController.callback',

  'get /auth/:provider': 'AuthController.provider',
  'get /auth/:provider/callback': 'AuthController.callback',
  'get /auth/:provider/:action': 'AuthController.callback'

};
<|endoftext|>


<commit_before>var jws = require('jws')
  , fs = require('fs');

var payload = {
  iss: 'https://op.example.com/',
  aud: 'https://rp.example.com/',
  exp: Math.floor(new Date(2214, 01, 01).getTime() / 1000)
};

var data = jws.sign({
  header: { alg: 'RS256' },
  payload: payload,
  privateKey: fs.readFileSync('../../test/keys/rsa/private-key.pem')
});

console.log(data);
<commit_msg>Add subject to assertion.<commit_after>#!/usr/bin/env node

var jws = require('jws')
  , fs = require('fs');

var payload = {
  iss: 'https://op.example.com/',
  sub: 'mailto:bob@example.com',
  aud: 'https://rp.example.com/',
  exp: Math.floor(new Date(2214, 01, 01).getTime() / 1000)
};

var data = jws.sign({
  header: { alg: 'RS256' },
  payload: payload,
  privateKey: fs.readFileSync('../../test/keys/rsa/private-key.pem')
});

console.log(data);
<|endoftext|>


<commit_before>/**
 * Output widget for visualization of tree object (species trees and gene trees).
 * Roman Sutormin <rsutormin@lbl.gov>
 * @public
 */
'use strict';

define(['jquery',
        'kbwidget',
        'kbaseAuthenticatedWidget',
        'jquery-dataTables',
        'jquery-dataTables-bootstrap',
        'knhx',
        'widgetMaxWidthCorrection'],
        function($) {
    $.KBWidget({
        name: 'kbaseFeatureSet',
        parent: 'kbaseAuthenticatedWidget',
        version: '0.0.1',
        options: {
            featureset_name: null,
            workspaceName: null,
            wsURL: window.kbconfig.urls.workspace,
            loadingImage: "static/kbase/images/ajax-loader.gif"
        },

        loadingImage: "static/kbase/images/ajax-loader.gif",

        init: function(options) {
            this._super(options);

            this.$messagePane = $("
").addClass("kbwidget-message-pane kbwidget-hide-message");
            this.$elem.append(this.$messagePane);

            if (options.workspaceids && options.workspaceids.length > 0) {
                var id = options.workspaceids[0].split('/');
                this.options.treeID = id[1];
                this.options.workspaceID = id[0];
            }

            this.$mainPanel = $("
").addClass("").hide();
            this.$elem.append(this.$mainPanel);

            if (!this.options.featureset_name) {
                this.renderError("No FeatureSet to render!");
            } else if (!this.options.workspaceName) {
                this.renderError("No workspace given!");
            } else if (!this.options.kbCache && !this.authToken()) {
                this.renderError("No cache given, and not logged in!");
            } else {
                this.token = this.authToken();
                this.render();
            }

            return this;
        },

        render: function() {
            this.ws = new Workspace(this.options.wsURL, {token: this.token});
            this.loading(false);
            this.$mainPanel.hide();
            this.$mainPanel.empty();
            this.loadFeatureSet();
        },

        features: null, // genomeId : [{fid: x, data: x}]

        loadFeatureSet: function() {
            var self = this;
            self.features = {};
            self.ws.get_objects([{ref:self.options.workspaceName+"/"+self.options.featureset_name}],
                function(data) {
                    var fs = data[0].data;
                    if(fs.description) {
                        self.$mainPanel.append($('
')
                            .append("Description - ")
                            .append(fs.description));
                    }

                    for (var fid in fs.elements) {
                        if (fs.elements.hasOwnProperty(fid)) {

                            for (var k=0; k<fs.elements[fid].length; k++) {
                                var gid = fs.elements[fid][k];
                                if(self.features.hasOwnProperty(gid)) {
                                    self.features[gid].push({'fid':fid});
                                } else {
                                    self.features[gid] = [{'fid':fid}];
                                }
                            }
                        }
                    }
                    self.getGenomeData();
                    self.$mainPanel.show();
                },
                function(error) {
                    self.loading(true);
                    self.renderError(error);

                });
        },

        genomeLookupTable: null, // genomeId: { featureId: indexInFeatureList }
        genomeObjectInfo: null, //{},
        featureTableData: null, // list for datatables

        getGenomeData: function() {
            var self = this;
            self.genomeLookupTable = {};
            self.genomeObjectInfo = {};
            self.featureTableData = [];
            // first get subdata for each of the genomes to build up the Feature ID to index lookup table
            var subdata_query = [];
            for(var gid in self.features) {
                subdata_query.push({ref:gid, included:['features/[*]/id']});
            }
            self.ws.get_object_subset(subdata_query,
                function(data) {
                    for (var k=0; k<data.length; k++) {
                        self.genomeObjectInfo[subdata_query[k].ref] = data[k].info;
                        self.genomeLookupTable[subdata_query[k].ref] = {}
                        for (var f=0; f<data[k].data.features.length; f++) {
                            self.genomeLookupTable[subdata_query[k].ref][data[k].data.features[f].id] = f;
                        }
                    }

                    for(var gid in self.features) {
                        var included = [];
                        for(var f=0; f<self.features[gid].length; f++) {
                            var idx = self.genomeLookupTable[gid][self.features[gid][f].fid];
                            included.push('features/'+idx+'/id');
                            included.push('features/'+idx+'/type');
                            included.push('features/'+idx+'/function');
                            included.push('features/'+idx+'/aliases');
                        }

                        var subdata_query2 = [{ref:gid,included:included}];
                        self.ws.get_object_subset(subdata_query2,
                            function(featureData) {
                                var g = featureData[0].data;
                                // every feature we get back here is something in the list
                                for(var f=0; f<g.features.length; f++) {
                                    var aliases = "None";
                                    if(g.features[f].aliases) {
                                        if(g.features[f].aliases.length>0) {
                                            aliases= g.features[f].aliases.join(', ');
                                        }
                                    }

                                    self.featureTableData.push(
                                            {
                                                fid: ''+g.features[f].id+'',
                                                gid: ''+featureData[0].info[1]+"",
                                                ali: aliases,
                                                type: g.features[f].type,
                                                func: g.features[f].function
                                            }
                                        );
                                }
                                self.renderFeatureTable(); // just rerender each time
                                self.loading(true);
                            },
                            function(error) {
                                self.loading(true);
                                self.renderError(error);
                            });
                    }

                },
                function(error) {
                    self.loading(true);
                    self.renderError(error);
                });

        },

        $featureTableDiv : null,
        renderFeatureTable: function() {
            var self = this;

            if(!self.$featureTableDiv) {
                self.$featureTableDiv = $('
').css({'margin':'5px'});
                self.$mainPanel.append(self.$featureTableDiv);
            }

            self.$featureTableDiv.empty();

            var $tbl = $('
')
                            .addClass("table table-bordered table-striped");
            self.$featureTableDiv.append($tbl);

            var tblSettings = {
                "sPaginationType": "full_numbers",
                "iDisplayLength": 10,
                "sDom": "ft<ip>",
                "aaSorting": [[ 1, "asc" ], [2, "asc"]],
                "aoColumns": [
                                      {sTitle: "Feature ID", mData: "fid"},
                                      {sTitle: "Aliases", mData: "ali"},
                                      {sTitle: "Genome", mData: "gid"},
                                      {sTitle: "Type", mData: "type"},
                                      {sTitle: "Function", mData: "func"},
                                      ],
                                      "aaData": [],
                                      "oLanguage": {
                                          "sSearch": "Search features:",
                                          "sEmptyTable": "This FeatureSet is empty"
                                      }
                };
            var featuresTable = $tbl.dataTable(tblSettings);
            featuresTable.fnAddData(self.featureTableData);
        },

        renderError: function(error) {
            errString = "Sorry, an unknown error occurred";
            if (typeof error === "string")
                errString = error;
            else if (error.error && error.error.message)
                errString = error.error.message;

            var $errorDiv = $("
")
                            .addClass("alert alert-danger")
                            .append("Error:")
                            .append("
" + errString);
            this.$elem.empty();
            this.$elem.append($errorDiv);
        },

        buildObjectIdentity: function(workspaceID, objectID, objectVer, wsRef) {
            var obj = {};
            if (wsRef) {
                obj['ref'] = wsRef;
            } else {
                if (/^\d+$/.exec(workspaceID))
                    obj['wsid'] = workspaceID;
                else
                    obj['workspace'] = workspaceID;

                // same for the id
                if (/^\d+$/.exec(objectID))
                    obj['objid'] = objectID;
                else
                    obj['name'] = objectID;

                if (objectVer)
                    obj['ver'] = objectVer;
            }
            return obj;
        },

        loading: function(doneLoading) {
            if (doneLoading)
                this.hideMessage();
            else
                this.showMessage("");
        },

        showMessage: function(message) {
            var span = $("").append(message);

            this.$messagePane.append(span);
            this.$messagePane.show();
        },

        hideMessage: function() {
            this.$messagePane.hide();
            this.$messagePane.empty();
        },

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

        loggedInCallback: function(event, auth) {
            if (this.token == null) {
                this.token = auth.token;
                this.render();
            }
            return this;
        },

        loggedOutCallback: function(event, auth) {
            this.render();
            return this;
        }

    });
});<commit_msg>improved table display<commit_after>/**
 * Output widget for visualization of tree object (species trees and gene trees).
 * Roman Sutormin <rsutormin@lbl.gov>
 * @public
 */
'use strict';

define(['jquery',
        'kbwidget',
        'kbaseAuthenticatedWidget',
        'jquery-dataTables',
        'jquery-dataTables-bootstrap',
        'knhx',
        'widgetMaxWidthCorrection'],
        function($) {
    $.KBWidget({
        name: 'kbaseFeatureSet',
        parent: 'kbaseAuthenticatedWidget',
        version: '0.0.1',
        options: {
            featureset_name: null,
            workspaceName: null,
            wsURL: window.kbconfig.urls.workspace,
            loadingImage: "static/kbase/images/ajax-loader.gif"
        },

        loadingImage: "static/kbase/images/ajax-loader.gif",

        init: function(options) {
            this._super(options);

            this.$messagePane = $("
").addClass("kbwidget-message-pane kbwidget-hide-message");
            this.$elem.append(this.$messagePane);

            if (options.workspaceids && options.workspaceids.length > 0) {
                var id = options.workspaceids[0].split('/');
                this.options.treeID = id[1];
                this.options.workspaceID = id[0];
            }

            this.$mainPanel = $("
").addClass("").hide();
            this.$elem.append(this.$mainPanel);

            if (!this.options.featureset_name) {
                this.renderError("No FeatureSet to render!");
            } else if (!this.options.workspaceName) {
                this.renderError("No workspace given!");
            } else if (!this.options.kbCache && !this.authToken()) {
                this.renderError("No cache given, and not logged in!");
            } else {
                this.token = this.authToken();
                this.render();
            }

            return this;
        },

        render: function() {
            this.ws = new Workspace(this.options.wsURL, {token: this.token});
            this.loading(false);
            this.$mainPanel.hide();
            this.$mainPanel.empty();
            this.loadFeatureSet();
        },

        features: null, // genomeId : [{fid: x, data: x}]

        loadFeatureSet: function() {
            var self = this;
            self.features = {};
            self.ws.get_objects([{ref:self.options.workspaceName+"/"+self.options.featureset_name}],
                function(data) {
                    var fs = data[0].data;
                    if(fs.description) {
                        self.$mainPanel.append($('
')
                            .append("Description - ")
                            .append(fs.description));
                    }

                    for (var fid in fs.elements) {
                        if (fs.elements.hasOwnProperty(fid)) {

                            for (var k=0; k<fs.elements[fid].length; k++) {
                                var gid = fs.elements[fid][k];
                                if(self.features.hasOwnProperty(gid)) {
                                    self.features[gid].push({'fid':fid});
                                } else {
                                    self.features[gid] = [{'fid':fid}];
                                }
                            }
                        }
                    }
                    self.getGenomeData();
                    self.$mainPanel.show();
                },
                function(error) {
                    self.loading(true);
                    self.renderError(error);

                });
        },

        genomeLookupTable: null, // genomeId: { featureId: indexInFeatureList }
        genomeObjectInfo: null, //{},
        featureTableData: null, // list for datatables

        getGenomeData: function() {
            var self = this;
            self.genomeLookupTable = {};
            self.genomeObjectInfo = {};
            self.featureTableData = [];
            // first get subdata for each of the genomes to build up the Feature ID to index lookup table
            var subdata_query = [];
            for(var gid in self.features) {
                subdata_query.push({ref:gid, included:['features/[*]/id']});
            }
            self.ws.get_object_subset(subdata_query,
                function(data) {
                    for (var k=0; k<data.length; k++) {
                        self.genomeObjectInfo[subdata_query[k].ref] = data[k].info;
                        self.genomeLookupTable[subdata_query[k].ref] = {}
                        for (var f=0; f<data[k].data.features.length; f++) {
                            self.genomeLookupTable[subdata_query[k].ref][data[k].data.features[f].id] = f;
                        }
                    }

                    for(var gid in self.features) {
                        var included = [];
                        for(var f=0; f<self.features[gid].length; f++) {
                            var idx = self.genomeLookupTable[gid][self.features[gid][f].fid];
                            included.push('features/'+idx+'/id');
                            included.push('features/'+idx+'/type');
                            included.push('features/'+idx+'/function');
                            included.push('features/'+idx+'/aliases');
                        }

                        var subdata_query2 = [{ref:gid,included:included}];
                        self.ws.get_object_subset(subdata_query2,
                            function(featureData) {
                                var g = featureData[0].data;
                                // every feature we get back here is something in the list
                                for(var f=0; f<g.features.length; f++) {
                                    var aliases = "None";
                                    if(g.features[f].aliases) {
                                        if(g.features[f].aliases.length>0) {
                                            aliases= g.features[f].aliases.join(', ');
                                        }
                                    }

                                    self.featureTableData.push(
                                            {
                                                fid: ''+g.features[f].id+'',
                                                gid: ''+featureData[0].info[1]+"",
                                                ali: aliases,
                                                type: g.features[f].type,
                                                func: g.features[f].function
                                            }
                                        );
                                }
                                self.renderFeatureTable(); // just rerender each time
                                self.loading(true);
                            },
                            function(error) {
                                self.loading(true);
                                self.renderError(error);
                            });
                    }

                },
                function(error) {
                    self.loading(true);
                    self.renderError(error);
                });

        },

        $featureTableDiv : null,
        renderFeatureTable: function() {
            var self = this;

            if(!self.$featureTableDiv) {
                self.$featureTableDiv = $('
').css({'margin':'5px'});
                self.$mainPanel.append(self.$featureTableDiv);
            }

            self.$featureTableDiv.empty();

            var $tbl = $('
')
                            .addClass("table table-bordered table-striped");
            self.$featureTableDiv.append($tbl);

            var sDom = "ft<ip>";
            if(self.featureTableData.length<=10) sDom = "ft";

            var tblSettings = {
                "sPaginationType": "full_numbers",
                "iDisplayLength": 10,
                "sDom": sDom,
                "aaSorting": [[ 2, "asc" ], [0, "asc"]],
                "aoColumns": [
                                      {sTitle: "Feature ID", mData: "fid"},
                                      {sTitle: "Aliases", mData: "ali"},
                                      {sTitle: "Genome", mData: "gid"},
                                      {sTitle: "Type", mData: "type"},
                                      {sTitle: "Function", mData: "func"},
                                      ],
                                      "aaData": [],
                                      "oLanguage": {
                                          "sSearch": "Search features:",
                                          "sEmptyTable": "This FeatureSet is empty"
                                      }
                };
            var featuresTable = $tbl.dataTable(tblSettings);
            featuresTable.fnAddData(self.featureTableData);
        },

        renderError: function(error) {
            errString = "Sorry, an unknown error occurred";
            if (typeof error === "string")
                errString = error;
            else if (error.error && error.error.message)
                errString = error.error.message;

            var $errorDiv = $("
")
                            .addClass("alert alert-danger")
                            .append("Error:")
                            .append("
" + errString);
            this.$elem.empty();
            this.$elem.append($errorDiv);
        },

        buildObjectIdentity: function(workspaceID, objectID, objectVer, wsRef) {
            var obj = {};
            if (wsRef) {
                obj['ref'] = wsRef;
            } else {
                if (/^\d+$/.exec(workspaceID))
                    obj['wsid'] = workspaceID;
                else
                    obj['workspace'] = workspaceID;

                // same for the id
                if (/^\d+$/.exec(objectID))
                    obj['objid'] = objectID;
                else
                    obj['name'] = objectID;

                if (objectVer)
                    obj['ver'] = objectVer;
            }
            return obj;
        },

        loading: function(doneLoading) {
            if (doneLoading)
                this.hideMessage();
            else
                this.showMessage("");
        },

        showMessage: function(message) {
            var span = $("").append(message);

            this.$messagePane.append(span);
            this.$messagePane.show();
        },

        hideMessage: function() {
            this.$messagePane.hide();
            this.$messagePane.empty();
        },

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

        loggedInCallback: function(event, auth) {
            if (this.token == null) {
                this.token = auth.token;
                this.render();
            }
            return this;
        },

        loggedOutCallback: function(event, auth) {
            this.render();
            return this;
        }

    });
});<|endoftext|>


<commit_before>import { dispatch as d3_dispatch } from 'd3-dispatch';
import { event as d3_event } from 'd3-selection';
import deepEqual from 'fast-deep-equal';

import { presetManager } from '../presets';
import { t, localizer } from '../core/localizer';
import { actionChangeTags } from '../actions/change_tags';
import { modeBrowse } from '../modes/browse';
import { svgIcon } from '../svg/icon';
import { utilArrayIdentical } from '../util/array';
import { utilCleanTags, utilCombinedTags, utilRebind } from '../util';

import { uiSectionEntityIssues } from './sections/entity_issues';
import { uiSectionFeatureType } from './sections/feature_type';
import { uiSectionPresetFields } from './sections/preset_fields';
import { uiSectionRawMemberEditor } from './sections/raw_member_editor';
import { uiSectionRawMembershipEditor } from './sections/raw_membership_editor';
import { uiSectionRawTagEditor } from './sections/raw_tag_editor';
import { uiSectionSelectionList } from './sections/selection_list';

export function uiEntityEditor(context) {
    var dispatch = d3_dispatch('choose');
    var _state = 'select';
    var _coalesceChanges = false;
    var _modified = false;
    var _base;
    var _entityIDs;
    var _activePresets = [];
    var _newFeature;

    var _sections;

    function entityEditor(selection) {

        var combinedTags = utilCombinedTags(_entityIDs, context.graph());

        // Header
        var header = selection.selectAll('.header')
            .data([0]);

        // Enter
        var headerEnter = header.enter()
            .append('div')
            .attr('class', 'header fillL cf');

        headerEnter
            .append('button')
            .attr('class', 'preset-reset preset-choose')
            .call(svgIcon((localizer.textDirection() === 'rtl') ? '#iD-icon-forward' : '#iD-icon-backward'));

        headerEnter
            .append('button')
            .attr('class', 'close')
            .on('click', function() { context.enter(modeBrowse(context)); })
            .call(svgIcon(_modified ? '#iD-icon-apply' : '#iD-icon-close'));

        headerEnter
            .append('h3');

        // Update
        header = header
            .merge(headerEnter);

        header.selectAll('h3')
            .text(_entityIDs.length === 1 ? t('inspector.edit') : t('inspector.edit_features'));

        header.selectAll('.preset-reset')
            .on('click', function() {
                dispatch.call('choose', this, _activePresets);
            });

        // Body
        var body = selection.selectAll('.inspector-body')
            .data([0]);

        // Enter
        var bodyEnter = body.enter()
            .append('div')
            .attr('class', 'entity-editor inspector-body sep-top');

        // Update
        body = body
            .merge(bodyEnter);

        if (!_sections) {
            _sections = [
                uiSectionSelectionList(context),
                uiSectionFeatureType(context).on('choose', function(presets) {
                    dispatch.call('choose', this, presets);
                }),
                uiSectionEntityIssues(context),
                uiSectionPresetFields(context).on('change', changeTags).on('revert', revertTags),
                uiSectionRawTagEditor('raw-tag-editor', context).on('change', changeTags),
                uiSectionRawMemberEditor(context),
                uiSectionRawMembershipEditor(context)
            ];
        }

        _sections.forEach(function(section) {
            if (section.entityIDs) {
                section.entityIDs(_entityIDs);
            }
            if (section.presets) {
                section.presets(_activePresets);
            }
            if (section.tags) {
                section.tags(combinedTags);
            }
            if (section.state) {
                section.state(_state);
            }
            body.call(section.render);
        });

        body
            .selectAll('.key-trap-wrap')
            .data([0])
            .enter()
            .append('div')
            .attr('class', 'key-trap-wrap')
            .append('input')
            .attr('type', 'text')
            .attr('class', 'key-trap')
            .on('keydown.key-trap', function() {
                // On tabbing, send focus back to the first field on the inspector-body
                // (probably the `name` field) #4159
                if (d3_event.keyCode === 9 && !d3_event.shiftKey) {
                    d3_event.preventDefault();
                    body.select('input').node().focus();
                }
            });

        context.history()
            .on('change.entity-editor', historyChanged);

        function historyChanged(difference) {
            if (selection.selectAll('.entity-editor').empty()) return;
            if (_state === 'hide') return;
            var significant = !difference ||
                    difference.didChange.properties ||
                    difference.didChange.addition ||
                    difference.didChange.deletion;
            if (!significant) return;

            _entityIDs = _entityIDs.filter(context.hasEntity);
            if (!_entityIDs.length) return;

            var priorActivePreset = _activePresets.length === 1 && _activePresets[0];

            loadActivePresets();

            var graph = context.graph();
            entityEditor.modified(_base !== graph);
            entityEditor(selection);

            if (priorActivePreset && _activePresets.length === 1 && priorActivePreset !== _activePresets[0]) {
                // flash the button to indicate the preset changed
                context.container().selectAll('.entity-editor button.preset-reset .label')
                    .style('background-color', '#fff')
                    .transition()
                    .duration(750)
                    .style('background-color', null);
            }
        }
    }

    // Tag changes that fire on input can all get coalesced into a single
    // history operation when the user leaves the field.  #2342
    // Use explicit entityIDs in case the selection changes before the event is fired.
    function changeTags(entityIDs, changed, onInput) {

        var actions = [];
        for (var i in entityIDs) {
            var entityID = entityIDs[i];
            var entity = context.entity(entityID);

            var tags = Object.assign({}, entity.tags);   // shallow copy

            for (var k in changed) {
                if (!k) continue;
                var v = changed[k];
                if (v !== undefined || tags.hasOwnProperty(k)) {
                    tags[k] = v;
                }
            }

            if (!onInput) {
                tags = utilCleanTags(tags);
            }

            if (!deepEqual(entity.tags, tags)) {
                actions.push(actionChangeTags(entityID, tags));
            }
        }

        if (actions.length) {
            var combinedAction = function(graph) {
                actions.forEach(function(action) {
                    graph = action(graph);
                });
                return graph;
            };

            var annotation = t('operations.change_tags.annotation');

            if (_coalesceChanges) {
                context.overwrite(combinedAction, annotation);
            } else {
                context.perform(combinedAction, annotation);
                _coalesceChanges = !!onInput;
            }
        }

        // if leaving field (blur event), rerun validation
        if (!onInput) {
            context.validator().validate();
        }
    }

    function revertTags(keys) {

        var actions = [];
        for (var i in _entityIDs) {
            var entityID = _entityIDs[i];

            var original = context.graph().base().entities[entityID];
            var changed = {};
            for (var j in keys) {
                var key = keys[j];
                changed[key] = original ? original.tags[key] : undefined;
            }

            var entity = context.entity(entityID);
            var tags = Object.assign({}, entity.tags);   // shallow copy

            for (var k in changed) {
                if (!k) continue;
                var v = changed[k];
                if (v !== undefined || tags.hasOwnProperty(k)) {
                    tags[k] = v;
                }
            }

            tags = utilCleanTags(tags);

            if (!deepEqual(entity.tags, tags)) {
                actions.push(actionChangeTags(entityID, tags));
            }

        }

        if (actions.length) {
            var combinedAction = function(graph) {
                actions.forEach(function(action) {
                    graph = action(graph);
                });
                return graph;
            };

            var annotation = t('operations.change_tags.annotation');

            if (_coalesceChanges) {
                context.overwrite(combinedAction, annotation);
            } else {
                context.perform(combinedAction, annotation);
                _coalesceChanges = false;
            }
        }

        context.validator().validate();
    }

    entityEditor.modified = function(val) {
        if (!arguments.length) return _modified;
        _modified = val;
        return entityEditor;
    };

    entityEditor.state = function(val) {
        if (!arguments.length) return _state;
        _state = val;
        return entityEditor;
    };

    entityEditor.entityIDs = function(val) {
        if (!arguments.length) return _entityIDs;
        if (val && _entityIDs && utilArrayIdentical(_entityIDs, val)) return entityEditor;  // exit early if no change

        _entityIDs = val;
        _base = context.graph();
        _coalesceChanges = false;

        loadActivePresets();

        return entityEditor
            .modified(false);
    };

    entityEditor.newFeature = function(val) {
        if (!arguments.length) return _newFeature;
        _newFeature = val;
        return entityEditor;
    };

    function loadActivePresets() {

        var graph = context.graph();

        var counts = {};

        for (var i in _entityIDs) {
            var entity = graph.hasEntity(_entityIDs[i]);
            if (!entity) return;

            var match = presetManager.match(entity, graph);

            if (!counts[match.id]) counts[match.id] = 0;
            counts[match.id] += 1;
        }

        var matches = Object.keys(counts).sort(function(p1, p2) {
            return counts[p2] - counts[p1];
        }).map(function(pID) {
            return presetManager.item(pID);
        });

        // A "weak" preset doesn't set any tags. (e.g. "Address")
        var weakPreset = _activePresets.length === 1 &&
            Object.keys(_activePresets[0].addTags || {}).length === 0;
        // Don't replace a weak preset with a fallback preset (e.g. "Point")
        if (weakPreset && matches.length === 1 && matches[0].isFallback()) return;

        entityEditor.presets(matches);
    }

    entityEditor.presets = function(val) {
        if (!arguments.length) return _activePresets;

        // don't reload the same preset
        if (!utilArrayIdentical(val, _activePresets)) {
            _activePresets = val;
        }
        return entityEditor;
    };

    return utilRebind(entityEditor, dispatch, 'on');
}
<commit_msg>Fix issue where inspector may not update correctly when switching between weak and fallback presets (close #7827)<commit_after>import { dispatch as d3_dispatch } from 'd3-dispatch';
import { event as d3_event } from 'd3-selection';
import deepEqual from 'fast-deep-equal';

import { presetManager } from '../presets';
import { t, localizer } from '../core/localizer';
import { actionChangeTags } from '../actions/change_tags';
import { modeBrowse } from '../modes/browse';
import { svgIcon } from '../svg/icon';
import { utilArrayIdentical } from '../util/array';
import { utilCleanTags, utilCombinedTags, utilRebind } from '../util';

import { uiSectionEntityIssues } from './sections/entity_issues';
import { uiSectionFeatureType } from './sections/feature_type';
import { uiSectionPresetFields } from './sections/preset_fields';
import { uiSectionRawMemberEditor } from './sections/raw_member_editor';
import { uiSectionRawMembershipEditor } from './sections/raw_membership_editor';
import { uiSectionRawTagEditor } from './sections/raw_tag_editor';
import { uiSectionSelectionList } from './sections/selection_list';

export function uiEntityEditor(context) {
    var dispatch = d3_dispatch('choose');
    var _state = 'select';
    var _coalesceChanges = false;
    var _modified = false;
    var _base;
    var _entityIDs;
    var _activePresets = [];
    var _newFeature;

    var _sections;

    function entityEditor(selection) {

        var combinedTags = utilCombinedTags(_entityIDs, context.graph());

        // Header
        var header = selection.selectAll('.header')
            .data([0]);

        // Enter
        var headerEnter = header.enter()
            .append('div')
            .attr('class', 'header fillL cf');

        headerEnter
            .append('button')
            .attr('class', 'preset-reset preset-choose')
            .call(svgIcon((localizer.textDirection() === 'rtl') ? '#iD-icon-forward' : '#iD-icon-backward'));

        headerEnter
            .append('button')
            .attr('class', 'close')
            .on('click', function() { context.enter(modeBrowse(context)); })
            .call(svgIcon(_modified ? '#iD-icon-apply' : '#iD-icon-close'));

        headerEnter
            .append('h3');

        // Update
        header = header
            .merge(headerEnter);

        header.selectAll('h3')
            .text(_entityIDs.length === 1 ? t('inspector.edit') : t('inspector.edit_features'));

        header.selectAll('.preset-reset')
            .on('click', function() {
                dispatch.call('choose', this, _activePresets);
            });

        // Body
        var body = selection.selectAll('.inspector-body')
            .data([0]);

        // Enter
        var bodyEnter = body.enter()
            .append('div')
            .attr('class', 'entity-editor inspector-body sep-top');

        // Update
        body = body
            .merge(bodyEnter);

        if (!_sections) {
            _sections = [
                uiSectionSelectionList(context),
                uiSectionFeatureType(context).on('choose', function(presets) {
                    dispatch.call('choose', this, presets);
                }),
                uiSectionEntityIssues(context),
                uiSectionPresetFields(context).on('change', changeTags).on('revert', revertTags),
                uiSectionRawTagEditor('raw-tag-editor', context).on('change', changeTags),
                uiSectionRawMemberEditor(context),
                uiSectionRawMembershipEditor(context)
            ];
        }

        _sections.forEach(function(section) {
            if (section.entityIDs) {
                section.entityIDs(_entityIDs);
            }
            if (section.presets) {
                section.presets(_activePresets);
            }
            if (section.tags) {
                section.tags(combinedTags);
            }
            if (section.state) {
                section.state(_state);
            }
            body.call(section.render);
        });

        body
            .selectAll('.key-trap-wrap')
            .data([0])
            .enter()
            .append('div')
            .attr('class', 'key-trap-wrap')
            .append('input')
            .attr('type', 'text')
            .attr('class', 'key-trap')
            .on('keydown.key-trap', function() {
                // On tabbing, send focus back to the first field on the inspector-body
                // (probably the `name` field) #4159
                if (d3_event.keyCode === 9 && !d3_event.shiftKey) {
                    d3_event.preventDefault();
                    body.select('input').node().focus();
                }
            });

        context.history()
            .on('change.entity-editor', historyChanged);

        function historyChanged(difference) {
            if (selection.selectAll('.entity-editor').empty()) return;
            if (_state === 'hide') return;
            var significant = !difference ||
                    difference.didChange.properties ||
                    difference.didChange.addition ||
                    difference.didChange.deletion;
            if (!significant) return;

            _entityIDs = _entityIDs.filter(context.hasEntity);
            if (!_entityIDs.length) return;

            var priorActivePreset = _activePresets.length === 1 && _activePresets[0];

            loadActivePresets();

            var graph = context.graph();
            entityEditor.modified(_base !== graph);
            entityEditor(selection);

            if (priorActivePreset && _activePresets.length === 1 && priorActivePreset !== _activePresets[0]) {
                // flash the button to indicate the preset changed
                context.container().selectAll('.entity-editor button.preset-reset .label')
                    .style('background-color', '#fff')
                    .transition()
                    .duration(750)
                    .style('background-color', null);
            }
        }
    }

    // Tag changes that fire on input can all get coalesced into a single
    // history operation when the user leaves the field.  #2342
    // Use explicit entityIDs in case the selection changes before the event is fired.
    function changeTags(entityIDs, changed, onInput) {

        var actions = [];
        for (var i in entityIDs) {
            var entityID = entityIDs[i];
            var entity = context.entity(entityID);

            var tags = Object.assign({}, entity.tags);   // shallow copy

            for (var k in changed) {
                if (!k) continue;
                var v = changed[k];
                if (v !== undefined || tags.hasOwnProperty(k)) {
                    tags[k] = v;
                }
            }

            if (!onInput) {
                tags = utilCleanTags(tags);
            }

            if (!deepEqual(entity.tags, tags)) {
                actions.push(actionChangeTags(entityID, tags));
            }
        }

        if (actions.length) {
            var combinedAction = function(graph) {
                actions.forEach(function(action) {
                    graph = action(graph);
                });
                return graph;
            };

            var annotation = t('operations.change_tags.annotation');

            if (_coalesceChanges) {
                context.overwrite(combinedAction, annotation);
            } else {
                context.perform(combinedAction, annotation);
                _coalesceChanges = !!onInput;
            }
        }

        // if leaving field (blur event), rerun validation
        if (!onInput) {
            context.validator().validate();
        }
    }

    function revertTags(keys) {

        var actions = [];
        for (var i in _entityIDs) {
            var entityID = _entityIDs[i];

            var original = context.graph().base().entities[entityID];
            var changed = {};
            for (var j in keys) {
                var key = keys[j];
                changed[key] = original ? original.tags[key] : undefined;
            }

            var entity = context.entity(entityID);
            var tags = Object.assign({}, entity.tags);   // shallow copy

            for (var k in changed) {
                if (!k) continue;
                var v = changed[k];
                if (v !== undefined || tags.hasOwnProperty(k)) {
                    tags[k] = v;
                }
            }

            tags = utilCleanTags(tags);

            if (!deepEqual(entity.tags, tags)) {
                actions.push(actionChangeTags(entityID, tags));
            }

        }

        if (actions.length) {
            var combinedAction = function(graph) {
                actions.forEach(function(action) {
                    graph = action(graph);
                });
                return graph;
            };

            var annotation = t('operations.change_tags.annotation');

            if (_coalesceChanges) {
                context.overwrite(combinedAction, annotation);
            } else {
                context.perform(combinedAction, annotation);
                _coalesceChanges = false;
            }
        }

        context.validator().validate();
    }

    entityEditor.modified = function(val) {
        if (!arguments.length) return _modified;
        _modified = val;
        return entityEditor;
    };

    entityEditor.state = function(val) {
        if (!arguments.length) return _state;
        _state = val;
        return entityEditor;
    };

    entityEditor.entityIDs = function(val) {
        if (!arguments.length) return _entityIDs;
        if (val && _entityIDs && utilArrayIdentical(_entityIDs, val)) return entityEditor;  // exit early if no change

        _entityIDs = val;
        _base = context.graph();
        _coalesceChanges = false;

        loadActivePresets(true);

        return entityEditor
            .modified(false);
    };

    entityEditor.newFeature = function(val) {
        if (!arguments.length) return _newFeature;
        _newFeature = val;
        return entityEditor;
    };

    function loadActivePresets(isForNewSelection) {

        var graph = context.graph();

        var counts = {};

        for (var i in _entityIDs) {
            var entity = graph.hasEntity(_entityIDs[i]);
            if (!entity) return;

            var match = presetManager.match(entity, graph);

            if (!counts[match.id]) counts[match.id] = 0;
            counts[match.id] += 1;
        }

        var matches = Object.keys(counts).sort(function(p1, p2) {
            return counts[p2] - counts[p1];
        }).map(function(pID) {
            return presetManager.item(pID);
        });

        if (!isForNewSelection) {
            // A "weak" preset doesn't set any tags. (e.g. "Address")
            var weakPreset = _activePresets.length === 1 &&
                !_activePresets[0].isFallback() &&
                Object.keys(_activePresets[0].addTags || {}).length === 0;
            // Don't replace a weak preset with a fallback preset (e.g. "Point")
            if (weakPreset && matches.length === 1 && matches[0].isFallback()) return;
        }

        entityEditor.presets(matches);
    }

    entityEditor.presets = function(val) {
        if (!arguments.length) return _activePresets;

        // don't reload the same preset
        if (!utilArrayIdentical(val, _activePresets)) {
            _activePresets = val;
        }
        return entityEditor;
    };

    return utilRebind(entityEditor, dispatch, 'on');
}
<|endoftext|>


<commit_before>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.10.0',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

if (process.platform === 'darwin') {
  config.fileName = `Git-macOS-${config.version}-64-bit.zip`
  // TODO: swap this out for something more official, lol
  config.source = `https://www.dropbox.com/s/w2l51jsibl90jtd/${config.fileName}?dl=1`
  config.checksum = '5193a0923a7fc7cadc6d644d83bab184548987079f498cd77ee9df2a4509402e'
} else if (process.platform === 'win32') {
  config.upstreamVersion = `v${config.version}.windows.1`
  config.fileName = `MinGit-${config.version}-64-bit.zip`
  config.source = `https://github.com/git-for-windows/git/releases/download/${config.upstreamVersion}/${config.fileName}`
  config.checksum = '2e1101ec57da526728704c04792293613f3c5aa18e65f13a4129d00b54de2087'
} else if (process.platform === 'linux') {
  // TODO: these versions are out of sync, whatever
  config.fileName = `git-2.10.1-ubuntu.tgz`
  config.source = `https://www.dropbox.com/s/te0grj36xm9dkic/${config.fileName}?dl=0`
  config.checksum = '1e67dbd01de8d719a56d082c3ed42e52f2c38dc8ac8f65259b8660e028f85a30'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function unzip (path, callback) {
  const result = decompress(path, config.outputPath)

  result
    .then(() => {
      callback(null)
    })
    .catch(err => {
      callback(err)
    })
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  // console.log(`verifying checksum...`)

  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  unzip(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        // console.log('file valid. unpacking...')
        unpackFile(temporaryFile)
      } else {
        // console.log('file not valid. aborting...')
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    // console.log(`directory exists at ${config.outputPath}, removing...`)
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    // console.log(`cached file exists at ${temporaryFile}, verifying...`)
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        // console.log('cached file not valid. removing...')
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  // console.log(`file does not exist. downloading...`)

  downloadAndUnpack()
})
<commit_msg>download equals true<commit_after>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.10.0',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

if (process.platform === 'darwin') {
  config.fileName = `Git-macOS-${config.version}-64-bit.zip`
  // TODO: swap this out for something more official, lol
  config.source = `https://www.dropbox.com/s/w2l51jsibl90jtd/${config.fileName}?dl=1`
  config.checksum = '5193a0923a7fc7cadc6d644d83bab184548987079f498cd77ee9df2a4509402e'
} else if (process.platform === 'win32') {
  config.upstreamVersion = `v${config.version}.windows.1`
  config.fileName = `MinGit-${config.version}-64-bit.zip`
  config.source = `https://github.com/git-for-windows/git/releases/download/${config.upstreamVersion}/${config.fileName}`
  config.checksum = '2e1101ec57da526728704c04792293613f3c5aa18e65f13a4129d00b54de2087'
} else if (process.platform === 'linux') {
  // TODO: these versions are out of sync, whatever
  config.fileName = `git-2.10.1-ubuntu.tgz`
  config.source = `https://www.dropbox.com/s/te0grj36xm9dkic/${config.fileName}?dl=1`
  config.checksum = '1e67dbd01de8d719a56d082c3ed42e52f2c38dc8ac8f65259b8660e028f85a30'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function unzip (path, callback) {
  const result = decompress(path, config.outputPath)

  result
    .then(() => {
      callback(null)
    })
    .catch(err => {
      callback(err)
    })
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  // console.log(`verifying checksum...`)

  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  unzip(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        // console.log('file valid. unpacking...')
        unpackFile(temporaryFile)
      } else {
        // console.log('file not valid. aborting...')
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    // console.log(`directory exists at ${config.outputPath}, removing...`)
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    // console.log(`cached file exists at ${temporaryFile}, verifying...`)
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        // console.log('cached file not valid. removing...')
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  // console.log(`file does not exist. downloading...`)

  downloadAndUnpack()
})
<|endoftext|>


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

(function($) {
  $.futon = $.futon || {};
  $.extend($.futon, {
    escape: function(string) {
      return string.replace(/&/g, "&")
                   .replace(/</g, "<")
                   .replace(/>/g, ">")
                   .replace(/"/, """)
                   .replace(/'/, "';")
                   ;
    },

    // JSON pretty printing
    formatJSON: function(val, options) {
      options = $.extend({
        escapeStrings: true,
        indent: 4,
        linesep: "\n",
        quoteKeys: true
      }, options || {});
      var itemsep = options.linesep.length ? "," + options.linesep : ", ";

      function format(val, depth) {
        var tab = [];
        for (var i = 0; i < options.indent * depth; i++) tab.push("");
        tab = tab.join(" ");

        var type = typeof val;
        switch (type) {
          case "boolean":
          case "number":
          case "string":
            var retval = val;
            if (type == "string" && !options.escapeStrings) {
              retval = indentLines(retval.replace(/\r\n/g, "\n"), tab.substr(options.indent));
            } else {
              if (options.html) {
                retval = $.futon.escape(JSON.stringify(val));
              } else {
                retval = JSON.stringify(val);
              }
            }
            if (options.html) {
              retval = "" + retval + "";
            }
            return retval;

          case "object": {
            if (val === null) {
              if (options.html) {
                return "null";
              }
              return "null";
            }
            if (val.constructor == Date) {
              return JSON.stringify(val);
            }

            var buf = [];

            if (val.constructor == Array) {
              buf.push("[");
              for (var index = 0; index < val.length; index++) {
                buf.push(index > 0 ? itemsep : options.linesep);
                buf.push(tab, format(val[index], depth + 1));
              }
              if (index >= 0) {
                buf.push(options.linesep, tab.substr(options.indent));
              }
              buf.push("]");
              if (options.html) {
                return "" + buf.join("") + "";
              }

            } else {
              buf.push("{");
              var index = 0;
              for (var key in val) {
                buf.push(index > 0 ? itemsep : options.linesep);
                var keyDisplay = options.quoteKeys ? JSON.stringify(key) : key;
                if (options.html) {
                  if (options.quoteKeys) {
                    keyDisplay = keyDisplay.substr(1, keyDisplay.length - 2);
                  }
                  keyDisplay = "" + $.futon.escape(keyDisplay) + "";
                  if (options.quoteKeys) {
                    keyDisplay = '"' + keyDisplay + '"';
                  }
                }
                buf.push(tab, keyDisplay,
                  ": ", format(val[key], depth + 1));
                index++;
              }
              if (index >= 0) {
                buf.push(options.linesep, tab.substr(options.indent));
              }
              buf.push("}");
              if (options.html) {
                return "" + buf.join("") + "";
              }
            }

            return buf.join("");
          }
        }
      }

      function indentLines(text, tab) {
        var lines = text.split("\n");
        for (var i in lines) {
          lines[i] = (i > 0 ? tab : "") + $.futon.escape(lines[i]);
        }
        return lines.join("
");
      }

      return format(val, 1);
    },

    // File size pretty printing
    formatSize: function(size) {
      var jump = 512;
      if (size < jump) return size + " bytes";
      var units = ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
      var i = 0;
      while (size >= jump && i < units.length) {
        i += 1;
        size /= 1024
      }
      return size.toFixed(1) + ' ' + units[i - 1];
    }

  });

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

(function($) {
  $.futon = $.futon || {};
  $.extend($.futon, {
    escape: function(string) {
      return string.replace(/&/g, "&")
                   .replace(/</g, "<")
                   .replace(/>/g, ">")
                   .replace(/"/, """)
                   .replace(/'/, "'")
                   ;
    },

    // JSON pretty printing
    formatJSON: function(val, options) {
      options = $.extend({
        escapeStrings: true,
        indent: 4,
        linesep: "\n",
        quoteKeys: true
      }, options || {});
      var itemsep = options.linesep.length ? "," + options.linesep : ", ";

      function format(val, depth) {
        var tab = [];
        for (var i = 0; i < options.indent * depth; i++) tab.push("");
        tab = tab.join(" ");

        var type = typeof val;
        switch (type) {
          case "boolean":
          case "number":
          case "string":
            var retval = val;
            if (type == "string" && !options.escapeStrings) {
              retval = indentLines(retval.replace(/\r\n/g, "\n"), tab.substr(options.indent));
            } else {
              if (options.html) {
                retval = $.futon.escape(JSON.stringify(val));
              } else {
                retval = JSON.stringify(val);
              }
            }
            if (options.html) {
              retval = "" + retval + "";
            }
            return retval;

          case "object": {
            if (val === null) {
              if (options.html) {
                return "null";
              }
              return "null";
            }
            if (val.constructor == Date) {
              return JSON.stringify(val);
            }

            var buf = [];

            if (val.constructor == Array) {
              buf.push("[");
              for (var index = 0; index < val.length; index++) {
                buf.push(index > 0 ? itemsep : options.linesep);
                buf.push(tab, format(val[index], depth + 1));
              }
              if (index >= 0) {
                buf.push(options.linesep, tab.substr(options.indent));
              }
              buf.push("]");
              if (options.html) {
                return "" + buf.join("") + "";
              }

            } else {
              buf.push("{");
              var index = 0;
              for (var key in val) {
                buf.push(index > 0 ? itemsep : options.linesep);
                var keyDisplay = options.quoteKeys ? JSON.stringify(key) : key;
                if (options.html) {
                  if (options.quoteKeys) {
                    keyDisplay = keyDisplay.substr(1, keyDisplay.length - 2);
                  }
                  keyDisplay = "" + $.futon.escape(keyDisplay) + "";
                  if (options.quoteKeys) {
                    keyDisplay = '"' + keyDisplay + '"';
                  }
                }
                buf.push(tab, keyDisplay,
                  ": ", format(val[key], depth + 1));
                index++;
              }
              if (index >= 0) {
                buf.push(options.linesep, tab.substr(options.indent));
              }
              buf.push("}");
              if (options.html) {
                return "" + buf.join("") + "";
              }
            }

            return buf.join("");
          }
        }
      }

      function indentLines(text, tab) {
        var lines = text.split("\n");
        for (var i in lines) {
          lines[i] = (i > 0 ? tab : "") + $.futon.escape(lines[i]);
        }
        return lines.join("
");
      }

      return format(val, 1);
    },

    // File size pretty printing
    formatSize: function(size) {
      var jump = 512;
      if (size < jump) return size + " bytes";
      var units = ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
      var i = 0;
      while (size >= jump && i < units.length) {
        i += 1;
        size /= 1024
      }
      return size.toFixed(1) + ' ' + units[i - 1];
    }

  });

})(jQuery);
<|endoftext|>