<commit_before>// ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\
// │ Taitale - JavaScript Taitale Library - TOOLS - loader                                │ \\
// │ Use Raphael.js                                                                       │ \\
// │ -------------------------------------------------------------------------------------│ \\
// │ Taitale - provide an infrastructure mapping graph engine                             │ \\
// │ Copyright (C) 2013  Mathilde Ffrench												  │ \\
// │ 																					  │ \\
// │ This program is free software: you can redistribute it and/or modify                 │ \\
// │ it under the terms of the GNU Affero General Public License as                       │ \\
// │ published by the Free Software Foundation, either version 3 of the                   │ \\
// │ License, or (at your option) any later version.									  │ \\
// │																					  │ \\
// │ This program is distributed in the hope that it will be useful,					  │ \\
// │ but WITHOUT ANY WARRANTY; without even the implied warranty of						  │ \\
// │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the						  │ \\
// │ GNU Affero General Public License for more details.								  │ \\
// │																					  │ \\
// │ You should have received a copy of the GNU Affero General Public License			  │ \\
// │ along with this program.  If not, see <http://www.gnu.org/licenses/>.				  │ \\
// └──────────────────────────────────────────────────────────────────────────────────────┘ \\

define(
    [
        'jquery',
        'raphael',
        'raphael-zpd',
        'raphael-svg-export',
        'taitale-params',
        'taitale-map',
        'taitale-helper',
        'taitale-ext-raphael'
    ],
    function($,Raphael,RaphelZPD,RaphaelSVGExport,params,map,helper) {

        function loader () {

            // SAMPLE PURPOSE => when ajax sync we display a map whatever the httpd server state.
            //jQuery.ajaxSetup({async:false});
            //jQuery.ajaxSetup({timeout:8000});

            var helper_  = new helper(),
                loader   = this,
                r        = null,
                zpd      = null,
                mappy    = null;

            var menu              = null,
                menuSet           = null,
                menuFillColor     = params.map_menuFillColor,
                menuStrokeColor   = params.map_menuStrokeColor,
                menuOpacity       = params.map_menuOpacity,
                menuStrokeWidth   = params.map_menuStrokeWidth,
                menuHided         = true;

            var refreshZPDOffset = null;

            var mainMouseDown = function(e) {

                var offsets = r.getHTMLOffsets();

                var posx = 0;
                var posy = 0;
                if (!e) e = window.event;
                if (e.clientX || e.clientY) {
                    posx = e.clientX + document.body.scrollLeft
                        + document.documentElement.scrollLeft - offsets.left;
                    posy = e.clientY + document.body.scrollTop
                        + document.documentElement.scrollTop - offsets.top;
                }

                if (e.which == 3) {
                    if (r.getDisplayMainMenu() && posx > 0 && posy > 0) {
                        for (var i = 0, ii = menuSet.length ; i < ii ; i++) {
                            if (i==0)
                                menuSet[i].attr({"x": posx, "y": posy+10});
                            else if (i==1)
                                menuSet[i].attr({"x": posx, "y": posy+30});
                            else
                                menuSet[i].attr({"x": posx, "y": posy+30+(i-1)*15});
                        }
                        if (menuHided) {
                            menu = r.menu(posx,posy,menuSet).attr({fill: menuFillColor, stroke: menuStrokeColor, "stroke-width": menuStrokeWidth, "fill-opacity": menuOpacity});
                            menu.toFront();
                            menu.show();
                            menuSet.toFront();
                            menuSet.show();
                            menuHided=false;
                        } else {
                            menu.remove();
                            menuSet.toBack();
                            menuSet.hide();
                            menuHided=true;
                        }
                    }
                    r.setDisplayMainMenu(true);
                }
            };

            this.normalSize = function() {
                var mapLayoutDivHeight = helper_.getMappyLayoutDivSize().height,
                    mapCanvasWidth     = helper_.getMappyCanvasDivSize().width,
                    mapCanvasHeight    = mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height,
                    mapCanvasCenterX   = mapCanvasWidth/ 2,
                    mapCanvasCenterY   = mapCanvasHeight/2;

                mappy.updateMapSize();

                var mappyWidth    = mappy.getMapSize().width,
                    mappyHeight   = mappy.getMapSize().height,
                    mappyTopLeftX = mappy.getTopLeftCoords().topLeftX,
                    mappyTopLeftY = mappy.getTopLeftCoords().topLeftY,
                    mappyCenterX  = (mappyTopLeftX + mappyWidth)/2,
                    mappyCenterY  = (mappyTopLeftY + mappyHeight)/2;

                //helper_.debug("=>normal size");
                r.ZPDNormalSize(mapCanvasCenterX, mapCanvasCenterY);

                //helper_.debug("=>pan");
                var transX = mapCanvasCenterX-mappyCenterX,
                    transY = mapCanvasCenterY-mappyCenterY;
                r.ZPDPanTo(transX,transY);
            };

            this.centerMappy = function() {
                var mapLayoutDivHeight = helper_.getMappyLayoutDivSize().height,
                    mapCanvasWidth     = helper_.getMappyCanvasDivSize().width,
                    mapCanvasHeight    = mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height,
                    mapCanvasCenterX   = mapCanvasWidth/ 2,
                    mapCanvasCenterY   = mapCanvasHeight/2;

                /**
                 * normale size and center
                 */
                this.normalSize();

                var mappyWidth    = mappy.getMapSize().width,
                    mappyHeight   = mappy.getMapSize().height;

                /**
                 * scale
                 */
                //helper_.debug("=>scale to center");
                var deltaX = mapCanvasWidth/mappyWidth,
                    deltaY = mapCanvasHeight/mappyHeight;
                if (deltaX < 1 || deltaY < 1) {
                    var delta = Math.min(deltaX,deltaY) - 1;
                    //helper_.debug(deltaX + "," + deltaY + "," + delta);
                    r.ZPDScaleTo(delta, mapCanvasCenterX, mapCanvasCenterY);
                }
            };

            var rrect,
                mapCanvasWidth,
                mapCanvasHeight;

            this.loadMappy = function() {
                var mapSize = mappy.getMapSize();
                var mapLayoutDivHeight = helper_.getMappyLayoutDivSize().height;
                if (helper_.getMappyCanvasDivSize().width > mapSize.width)
                    mapCanvasWidth     = helper_.getMappyCanvasDivSize().width;
                else
                    mapCanvasWidth     = mapSize.width;
                if (mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height > mapSize.height)
                    mapCanvasHeight    = mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height;
                else
                    mapCanvasHeight    = mapSize.height;
                    //mapCanvasHeight     = mapSize.height;

                document.getElementById("mappyCanvas").innerHTML = "";
                r = Raphael("mappyCanvas", mapCanvasWidth, mapCanvasHeight);

                /**
                 * Init raphael JS object outside ZPD
                 */
                r.setMainMenuSet();
                //r.setEndpointMenuSet();
                //r.raphael.mousedown(mainMouseDown);
                r.raphael.getColor.reset();

                menuSet = r.getMainMenuSet();
                zpd = new RaphaelZPD(r, { zoom: true, pan: true, drag: false }, mappy);
                mappy.print(r);

                rrect = r.rect(0, 0, mapCanvasWidth, mapCanvasHeight);
                rrect.attr("fill", "#555");
                rrect.attr("stroke", "#555");
                rrect.toBack();

                if (refreshZPDOffset!=null) {
                    zpd.ZPDRefreshLastOffset(refreshZPDOffset.x,refreshZPDOffset.y);
                }

                this.centerMappy();
            };

            var httpJSONmap = null;

            this.buildMappy = function(options) {
                mappy       = new map(options);
                mappy.parseJSON(httpJSONmap);
                mappy.buildMap();

                this.loadMappy();

                helper_.growlMsgs(
                    {
                        severity: 'info',
                        summary: 'Map successfully loaded ',
                        detail: 'Layout: '+options.getLayout() +"
Mode: "+options.getMode()
                    }
                );
            };

            this.loadMap = function(options) {
                document.getElementById('mappyLoading').style.display = "";
                document.getElementById('mappyCanvas').style.display = "none";
                $.ajax({
                        url: options.getURI(),
                        success:
                            function(data)	{
                                if( !data || data === ""){
                                    // error
                                    return;
                                }

                                document.getElementById('mappyLoading').style.display = "none";
                                document.getElementById('mappyCanvas').style.display = "";

                                var json = null;
                                try {
                                    json = JSON.parse(data);
                                } catch (e) {
                                    throw   {
                                        stack: new Error("JSON parse error").stack,
                                        severity: 'error',
                                        summary: 'JSON parse error',
                                        detail: 'Unable to parse JSON from following url : '.concat(options.getURI()).concat('
 error raised: ').concat(e.message),
                                        sticky: true
                                    };
                                }

                                httpJSONmap=json;
                                loader.buildMappy(options);
                            },
                        error:
                            function (xhr, ajaxOptions, thrownError){
                                document.getElementById('mappyLoading').style.display = "none";
                                document.getElementById('mappyCanvas').style.display = "";
                                throw   {
                                    stack: new Error("JSON parse error").stack,
                                    severity: 'error',
                                    summary: 'JSON parse error',
                                    detail: 'Unable to parse JSON from following url : '.concat(options.getURI()).concat('
 error raised: ').concat(thrownError),
                                    sticky: true
                                };
                            },
                        dataType: "text"});
            };

            this.reloadMap = function(options) {
                if (zpd!=null)
                    zpd.ZPDClearEvents();
                if (r!=null) {
                    //r.raphael.unmousedown(mainMouseDown);
                    r.clear();
                }
                refreshZPDOffset=null;
                this.loadMap(options);
            };

            this.rebuildMap = function(options) {
                if (zpd!=null)
                    zpd.ZPDClearEvents();
                if (r!=null) {
                    //r.raphael.unmousedown(mainMouseDown);
                    r.clear();
                }
                refreshZPDOffset=null;
                this.buildMappy(options);
            };

            this.refreshMap = function(options) {
                if (zpd!=null) {
                    if (r!=null) {
                        refreshZPDOffset = r.getZPDoffsets();
                    }
                    zpd.ZPDClearEvents();
                }
                if (r!=null) {
                    //r.raphael.unmousedown(mainMouseDown);
                    r.clear();
                }
                loader.loadMappy();

                helper_.growlMsgs(
                    {
                        severity: 'info',
                        summary: 'Map successfully refreshed ',
                        detail: '
Layout: '+options.getLayout()+"
Mode: "+options.getMode()
                    }
                );
            };

            this.editionMode = function(options) {
                if (mappy!=null) mappy.editionMode(options);
            };

            this.displayDC = function(display) {
                if (mappy!=null && display!=null) mappy.displayDC(display);
            };

            this.displayArea = function(display) {
                if (mappy!=null && display!=null) mappy.displayArea(display);
            };

            this.displayLan = function(display) {
                if (mappy!=null && display!=null) mappy.displayLan(display);
            };

            this.sortRootTree = function(sort) {
                if (mappy!=null && sort!=null) mappy.sortRootTree(sort);
            };

            this.sortSubTrees = function(sort) {
                if (mappy!=null && sort!=null) mappy.sortSubTrees(sort);
            };

            this.rebuildMapTreeLayout = function()  {
                if (mappy!=null) mappy.rebuildMapTreeLayout();
            };

            this.exportToSVG = function() {
                var svg = null;
                if (r!=null && mappy !=null) {
                    rrect.remove();
                    mappy.updateMapSize();
                    var mapSize         = mappy.getMapSize();
                    r.setSize(mapSize.width, mapSize.height);
                    mappy.rePozTo0Canvas();

                    rrect = r.rect(0, 0, mapSize.width, mapSize.height);
                    rrect.attr("fill", "#fff");
                    rrect.attr("stroke", "#fff");
                    rrect.toBack();
                    svg = r.toSVG();
                    mappy.reInitToInitalPoz();

                    rrect.attr("fill", "#555");
                }
                return svg;
            };
        }

        return loader;
});<commit_msg>[ACC-35] export network layout to SVG<commit_after>// ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\
// │ Taitale - JavaScript Taitale Library - TOOLS - loader                                │ \\
// │ Use Raphael.js                                                                       │ \\
// │ -------------------------------------------------------------------------------------│ \\
// │ Taitale - provide an infrastructure mapping graph engine                             │ \\
// │ Copyright (C) 2013  Mathilde Ffrench												  │ \\
// │ 																					  │ \\
// │ This program is free software: you can redistribute it and/or modify                 │ \\
// │ it under the terms of the GNU Affero General Public License as                       │ \\
// │ published by the Free Software Foundation, either version 3 of the                   │ \\
// │ License, or (at your option) any later version.									  │ \\
// │																					  │ \\
// │ This program is distributed in the hope that it will be useful,					  │ \\
// │ but WITHOUT ANY WARRANTY; without even the implied warranty of						  │ \\
// │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the						  │ \\
// │ GNU Affero General Public License for more details.								  │ \\
// │																					  │ \\
// │ You should have received a copy of the GNU Affero General Public License			  │ \\
// │ along with this program.  If not, see <http://www.gnu.org/licenses/>.				  │ \\
// └──────────────────────────────────────────────────────────────────────────────────────┘ \\

define(
    [
        'jquery',
        'raphael',
        'raphael-zpd',
        'raphael-svg-export',
        'taitale-params',
        'taitale-map',
        'taitale-helper',
        'taitale-ext-raphael'
    ],
    function($,Raphael,RaphelZPD,RaphaelSVGExport,params,map,helper) {

        function loader () {

            // SAMPLE PURPOSE => when ajax sync we display a map whatever the httpd server state.
            //jQuery.ajaxSetup({async:false});
            //jQuery.ajaxSetup({timeout:8000});

            var helper_  = new helper(),
                loader   = this,
                r        = null,
                zpd      = null,
                mappy    = null;

            var menu              = null,
                menuSet           = null,
                menuFillColor     = params.map_menuFillColor,
                menuStrokeColor   = params.map_menuStrokeColor,
                menuOpacity       = params.map_menuOpacity,
                menuStrokeWidth   = params.map_menuStrokeWidth,
                menuHided         = true;

            var refreshZPDOffset = null;

            var mainMouseDown = function(e) {

                var offsets = r.getHTMLOffsets();

                var posx = 0;
                var posy = 0;
                if (!e) e = window.event;
                if (e.clientX || e.clientY) {
                    posx = e.clientX + document.body.scrollLeft
                        + document.documentElement.scrollLeft - offsets.left;
                    posy = e.clientY + document.body.scrollTop
                        + document.documentElement.scrollTop - offsets.top;
                }

                if (e.which == 3) {
                    if (r.getDisplayMainMenu() && posx > 0 && posy > 0) {
                        for (var i = 0, ii = menuSet.length ; i < ii ; i++) {
                            if (i==0)
                                menuSet[i].attr({"x": posx, "y": posy+10});
                            else if (i==1)
                                menuSet[i].attr({"x": posx, "y": posy+30});
                            else
                                menuSet[i].attr({"x": posx, "y": posy+30+(i-1)*15});
                        }
                        if (menuHided) {
                            menu = r.menu(posx,posy,menuSet).attr({fill: menuFillColor, stroke: menuStrokeColor, "stroke-width": menuStrokeWidth, "fill-opacity": menuOpacity});
                            menu.toFront();
                            menu.show();
                            menuSet.toFront();
                            menuSet.show();
                            menuHided=false;
                        } else {
                            menu.remove();
                            menuSet.toBack();
                            menuSet.hide();
                            menuHided=true;
                        }
                    }
                    r.setDisplayMainMenu(true);
                }
            };

            this.normalSize = function() {
                var mapLayoutDivHeight = helper_.getMappyLayoutDivSize().height,
                    mapCanvasWidth     = helper_.getMappyCanvasDivSize().width,
                    mapCanvasHeight    = mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height,
                    mapCanvasCenterX   = mapCanvasWidth/ 2,
                    mapCanvasCenterY   = mapCanvasHeight/2;

                mappy.updateMapSize();

                var mappyWidth    = mappy.getMapSize().width,
                    mappyHeight   = mappy.getMapSize().height,
                    mappyTopLeftX = mappy.getTopLeftCoords().topLeftX,
                    mappyTopLeftY = mappy.getTopLeftCoords().topLeftY,
                    mappyCenterX  = (mappyTopLeftX + mappyWidth)/2,
                    mappyCenterY  = (mappyTopLeftY + mappyHeight)/2;

                //helper_.debug("=>normal size");
                r.ZPDNormalSize(mapCanvasCenterX, mapCanvasCenterY);

                //helper_.debug("=>pan");
                var transX = mapCanvasCenterX-mappyCenterX,
                    transY = mapCanvasCenterY-mappyCenterY;
                r.ZPDPanTo(transX,transY);
            };

            this.centerMappy = function() {
                var mapLayoutDivHeight = helper_.getMappyLayoutDivSize().height,
                    mapCanvasWidth     = helper_.getMappyCanvasDivSize().width,
                    mapCanvasHeight    = mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height,
                    mapCanvasCenterX   = mapCanvasWidth/ 2,
                    mapCanvasCenterY   = mapCanvasHeight/2;

                /**
                 * normale size and center
                 */
                this.normalSize();

                var mappyWidth    = mappy.getMapSize().width,
                    mappyHeight   = mappy.getMapSize().height;

                /**
                 * scale
                 */
                //helper_.debug("=>scale to center");
                var deltaX = mapCanvasWidth/mappyWidth,
                    deltaY = mapCanvasHeight/mappyHeight;
                if (deltaX < 1 || deltaY < 1) {
                    var delta = Math.min(deltaX,deltaY) - 1;
                    //helper_.debug(deltaX + "," + deltaY + "," + delta);
                    r.ZPDScaleTo(delta, mapCanvasCenterX, mapCanvasCenterY);
                }
            };

            var rrect,
                mapCanvasWidth,
                mapCanvasHeight;

            this.loadMappy = function() {
                var mapSize = mappy.getMapSize();
                var mapLayoutDivHeight = helper_.getMappyLayoutDivSize().height;
                if (helper_.getMappyCanvasDivSize().width > mapSize.width)
                    mapCanvasWidth     = helper_.getMappyCanvasDivSize().width;
                else
                    mapCanvasWidth     = mapSize.width;
                if (mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height > mapSize.height)
                    mapCanvasHeight    = mapLayoutDivHeight + helper_.getMappyCanvasDivSize().height;
                else
                    mapCanvasHeight    = mapSize.height;
                    //mapCanvasHeight     = mapSize.height;

                document.getElementById("mappyCanvas").innerHTML = "";
                r = Raphael("mappyCanvas", mapCanvasWidth, mapCanvasHeight);

                /**
                 * Init raphael JS object outside ZPD
                 */
                r.setMainMenuSet();
                //r.setEndpointMenuSet();
                //r.raphael.mousedown(mainMouseDown);
                r.raphael.getColor.reset();

                menuSet = r.getMainMenuSet();
                zpd = new RaphaelZPD(r, { zoom: true, pan: true, drag: false }, mappy);
                mappy.print(r);

                //rrect = r.rect(0, 0, mapCanvasWidth, mapCanvasHeight);
                //rrect.attr("fill", "#555");
                //rrect.attr("stroke", "#555");
                //rrect.toBack();

                if (refreshZPDOffset!=null) {
                    zpd.ZPDRefreshLastOffset(refreshZPDOffset.x,refreshZPDOffset.y);
                }

                this.centerMappy();
            };

            var httpJSONmap = null;

            this.buildMappy = function(options) {
                mappy       = new map(options);
                mappy.parseJSON(httpJSONmap);
                mappy.buildMap();

                this.loadMappy();

                helper_.growlMsgs(
                    {
                        severity: 'info',
                        summary: 'Map successfully loaded ',
                        detail: 'Layout: '+options.getLayout() +"
Mode: "+options.getMode()
                    }
                );
            };

            this.loadMap = function(options) {
                document.getElementById('mappyLoading').style.display = "";
                document.getElementById('mappyCanvas').style.display = "none";
                $.ajax({
                        url: options.getURI(),
                        success:
                            function(data)	{
                                if( !data || data === ""){
                                    // error
                                    return;
                                }

                                document.getElementById('mappyLoading').style.display = "none";
                                document.getElementById('mappyCanvas').style.display = "";

                                var json = null;
                                try {
                                    json = JSON.parse(data);
                                } catch (e) {
                                    throw   {
                                        stack: new Error("JSON parse error").stack,
                                        severity: 'error',
                                        summary: 'JSON parse error',
                                        detail: 'Unable to parse JSON from following url : '.concat(options.getURI()).concat('
 error raised: ').concat(e.message),
                                        sticky: true
                                    };
                                }

                                httpJSONmap=json;
                                loader.buildMappy(options);
                            },
                        error:
                            function (xhr, ajaxOptions, thrownError){
                                document.getElementById('mappyLoading').style.display = "none";
                                document.getElementById('mappyCanvas').style.display = "";
                                throw   {
                                    stack: new Error("JSON parse error").stack,
                                    severity: 'error',
                                    summary: 'JSON parse error',
                                    detail: 'Unable to parse JSON from following url : '.concat(options.getURI()).concat('
 error raised: ').concat(thrownError),
                                    sticky: true
                                };
                            },
                        dataType: "text"});
            };

            this.reloadMap = function(options) {
                if (zpd!=null)
                    zpd.ZPDClearEvents();
                if (r!=null) {
                    //r.raphael.unmousedown(mainMouseDown);
                    r.clear();
                }
                refreshZPDOffset=null;
                this.loadMap(options);
            };

            this.rebuildMap = function(options) {
                if (zpd!=null)
                    zpd.ZPDClearEvents();
                if (r!=null) {
                    //r.raphael.unmousedown(mainMouseDown);
                    r.clear();
                }
                refreshZPDOffset=null;
                this.buildMappy(options);
            };

            this.refreshMap = function(options) {
                if (zpd!=null) {
                    if (r!=null) {
                        refreshZPDOffset = r.getZPDoffsets();
                    }
                    zpd.ZPDClearEvents();
                }
                if (r!=null) {
                    //r.raphael.unmousedown(mainMouseDown);
                    r.clear();
                }
                loader.loadMappy();

                helper_.growlMsgs(
                    {
                        severity: 'info',
                        summary: 'Map successfully refreshed ',
                        detail: '
Layout: '+options.getLayout()+"
Mode: "+options.getMode()
                    }
                );
            };

            this.editionMode = function(options) {
                if (mappy!=null) mappy.editionMode(options);
            };

            this.displayDC = function(display) {
                if (mappy!=null && display!=null) mappy.displayDC(display);
            };

            this.displayArea = function(display) {
                if (mappy!=null && display!=null) mappy.displayArea(display);
            };

            this.displayLan = function(display) {
                if (mappy!=null && display!=null) mappy.displayLan(display);
            };

            this.sortRootTree = function(sort) {
                if (mappy!=null && sort!=null) mappy.sortRootTree(sort);
            };

            this.sortSubTrees = function(sort) {
                if (mappy!=null && sort!=null) mappy.sortSubTrees(sort);
            };

            this.rebuildMapTreeLayout = function()  {
                if (mappy!=null) mappy.rebuildMapTreeLayout();
            };

            this.exportToSVG = function() {
                var svg = null;
                if (r!=null && mappy !=null) {
                    //rrect.remove();
                    mappy.updateMapSize();
                    var mapSize         = mappy.getMapSize();
                    r.setSize(mapSize.width, mapSize.height);
                    mappy.rePozTo0Canvas();

                    rrect = r.rect(0, 0, mapSize.width, mapSize.height);
                    rrect.attr("fill", "#fff");
                    rrect.attr("stroke", "#fff");
                    rrect.toBack();
                    svg = r.toSVG();
                    mappy.reInitToInitalPoz();

                    rrect.remove();
                    //rrect.attr("fill", "#555");
                }
                return svg;
            };
        }

        return loader;
});<|endoftext|>


<commit_before>var Referential=function(isNumber,isObject,objectAssign,observable){"use strict";isNumber="default"in isNumber?isNumber["default"]:isNumber;isObject="default"in isObject?isObject["default"]:isObject;objectAssign="default"in objectAssign?objectAssign["default"]:objectAssign;observable="default"in observable?observable["default"]:observable;var Ref;var nextId;var indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i<l;i++){if(i in this&&this[i]===item)return i}return-1};nextId=function(){var ids;ids=0;return function(){return ids++}}();var Ref$1=Ref=function(){function Ref(_value,parent,key1){this._value=_value;this.parent=parent;this.key=key1;this._cache={};this._children={};this._numChildren=0;this._id=nextId();if(this.parent!=null){this.parent._children[this._id]=this;this.parent._numChildren++}observable(this);this}Ref.prototype._mutate=function(key){var child,id,ref;this._cache={};ref=this._children;for(id in ref){child=ref[id];child._mutate()}return this};Ref.prototype.destroy=function(){var child,id,ref;ref=this._children;for(id in ref){child=ref[id];child.destroy()}delete this._cache;delete this._children;this.off("*");if(this.parent){delete this.parent._children[this._id];this.parent._numChildren--}return this};Ref.prototype.value=function(state){if(!this.parent){if(state!=null){this._value=state}return this._value}if(state!=null){return this.parent.set(this.key,state)}else{return this.parent.get(this.key)}};Ref.prototype.ref=function(key){if(!key){return this}return new Ref(null,this,key)};Ref.prototype.get=function(key){if(!key){return this.value()}else{if(this._cache[key]){return this._cache[key]}return this._cache[key]=this.index(key)}};Ref.prototype.set=function(key,value){var k,oldValue,v;if(isObject(key)){for(k in key){v=key[k];this.set(k,v)}return this}oldValue=this.get(key);this._mutate(key);if(value==null){this.value(objectAssign(this.value(),key))}else{this.index(key,value)}this._triggerSet(key,value,oldValue);this._triggerSetChildren(key,value,oldValue);return this};Ref.prototype._triggerSetChildren=function(key,value,oldValue){var child,childKeys,childRemainderKey,i,id,keyPart,keyParts,partialKey,ref,ref1,regExps,results;if(this._numChildren===0){return this}key=key+"";keyParts=key.split(".");partialKey="";childKeys=[];regExps={};for(i in keyParts){keyPart=keyParts[i];if(partialKey===""){partialKey=keyPart}else{partialKey+="."+keyPart}childKeys[i]=partialKey;regExps[partialKey]=new RegExp("^"+partialKey+".?")}ref=this._children;results=[];for(id in ref){child=ref[id];if(ref1=child.key,indexOf.call(childKeys,ref1)>=0){childRemainderKey=key.replace(regExps[child.key],"");child.trigger("set",childRemainderKey,value,oldValue);results.push(child._triggerSetChildren(childRemainderKey,value,oldValue))}else{results.push(void 0)}}return results};Ref.prototype._triggerSet=function(key,value,oldValue){var parentKey;this.trigger("set",key,value,oldValue);if(this.parent){parentKey=this.key+"."+key;return this.parent._triggerSet(parentKey,value,oldValue)}};Ref.prototype.extend=function(key,value){var clone;this._mutate(key);if(value==null){this.value(objectAssign(this.value(),key))}else{if(isObject(value)){this.value(objectAssign(this.ref(key).get(),value))}else{clone=this.clone();this.set(key,value);this.value(objectAssign(clone.get(),this.value()))}}return this};Ref.prototype.clone=function(key){return new Ref(objectAssign({},this.get(key)))};Ref.prototype.index=function(key,value,obj,prev){var next,prop,props;if(obj==null){obj=this.value()}if(this.parent){return this.parent.index(this.key+"."+key,value)}if(isNumber(key)){key=String(key)}props=key.split(".");if(value==null){while(prop=props.shift()){if(!props.length){return obj!=null?obj[prop]:void 0}obj=obj!=null?obj[prop]:void 0}return}while(prop=props.shift()){if(!props.length){return obj[prop]=value}else{next=props[0];if(obj[prop]==null){if(isNaN(Number(next))){if(obj[prop]==null){obj[prop]={}}}else{if(obj[prop]==null){obj[prop]=[]}}}}obj=obj[prop]}};return Ref}();var methods;var refer;methods=["extend","get","index","ref","set","value","on","off","one","trigger"];refer=function(state,ref){var fn,i,len,method,wrapper;if(ref==null){ref=null}if(ref==null){ref=new Ref$1(state)}wrapper=function(key){return ref.get(key)};fn=function(method){return wrapper[method]=function(){return ref[method].apply(ref,arguments)}};for(i=0,len=methods.length;i<len;i++){method=methods[i];fn(method)}wrapper.refer=function(key){return refer(null,ref.ref(key))};wrapper.clone=function(key){return refer(null,ref.clone(key))};return wrapper};refer.Ref=Ref$1;var refer$1=refer;return refer$1}(isNumber,isObject,objectAssign,observable);<commit_msg>Recompile<commit_after>var Referential=function(){"use strict";var toString=function(obj){return Object.prototype.toString.call(obj)};var isNumber;var isNumber$1=isNumber=function(value){return toString(value)==="[object Number]"};var isObject;var isObject$1=isObject=function(value){return toString(value)==="[object Object]"};var getOwnSymbols;var objectAssign;var shouldUseNative;var toObject;var slice=[].slice;getOwnSymbols=Object.getOwnPropertySymbols;toObject=function(val){if(val===null||val===void 0){throw new TypeError("Object.assign cannot be called with null or undefined")}return Object(val)};shouldUseNative=function(){var err,i,j,k,len,letter,order2,ref,test1,test2,test3;try{if(!Object.assign){return false}test1=new String("abc");test1[5]="de";if(Object.getOwnPropertyNames(test1)[0]==="5"){return false}test2={};for(i=j=0;j<=9;i=++j){test2["_"+String.fromCharCode(i)]=i}order2=Object.getOwnPropertyNames(test2).map(function(n){return test2[n]});if(order2.join("")!=="0123456789"){return false}test3={};ref="abcdefghijklmnopqrst".split("");for(k=0,len=ref.length;k<len;k++){letter=ref[k];test3[letter]=letter}if(Object.keys(Object.assign({},test3)).join("")!=="abcdefghijklmnopqrst"){return false}return true}catch(error){err=error;return false}};var index=objectAssign=function(){if(shouldUseNative()){return Object.assign}return function(){var from,j,k,key,len,len1,ref,source,sources,symbol,target,to;target=arguments[0],sources=2<=arguments.length?slice.call(arguments,1):[];to=toObject(target);for(j=0,len=sources.length;j<len;j++){source=sources[j];from=Object(source);for(key in from){if(Object.prototype.hasOwnProperty.call(from,key)){to[key]=from[key]}}if(getOwnSymbols){ref=getOwnSymbols(from);for(k=0,len1=ref.length;k<len1;k++){symbol=ref[k];if(Object.prototype.propIsEnumerable.call(from,symbol)){to[symbol]=from[symbol]}}}}return to}}();var observable=function(el){el=el||{};var callbacks={},slice=Array.prototype.slice;Object.defineProperties(el,{on:{value:function(event,fn){if(typeof fn=="function")(callbacks[event]=callbacks[event]||[]).push(fn);return el},enumerable:false,writable:false,configurable:false},off:{value:function(event,fn){if(event=="*"&&!fn)callbacks={};else{if(fn){var arr=callbacks[event];for(var i=0,cb;cb=arr&&arr[i];++i){if(cb==fn)arr.splice(i--,1)}}else delete callbacks[event]}return el},enumerable:false,writable:false,configurable:false},one:{value:function(event,fn){function on(){el.off(event,on);fn.apply(el,arguments)}return el.on(event,on)},enumerable:false,writable:false,configurable:false},trigger:{value:function(event){var arglen=arguments.length-1,args=new Array(arglen),fns,fn,i;for(i=0;i<arglen;i++){args[i]=arguments[i+1]}fns=slice.call(callbacks[event]||[],0);for(i=0;fn=fns[i];++i){fn.apply(el,args)}if(callbacks["*"]&&event!="*")el.trigger.apply(el,["*",event].concat(args));return el},enumerable:false,writable:false,configurable:false}});return el};var Ref;var nextId;var indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i<l;i++){if(i in this&&this[i]===item)return i}return-1};nextId=function(){var ids;ids=0;return function(){return ids++}}();var Ref$1=Ref=function(){function Ref(_value,parent,key1){this._value=_value;this.parent=parent;this.key=key1;this._cache={};this._children={};this._numChildren=0;this._id=nextId();if(this.parent!=null){this.parent._children[this._id]=this;this.parent._numChildren++}observable(this);this}Ref.prototype._mutate=function(key){var child,id,ref;this._cache={};ref=this._children;for(id in ref){child=ref[id];child._mutate()}return this};Ref.prototype.destroy=function(){var child,id,ref;ref=this._children;for(id in ref){child=ref[id];child.destroy()}delete this._cache;delete this._children;this.off("*");if(this.parent){delete this.parent._children[this._id];this.parent._numChildren--}return this};Ref.prototype.value=function(state){if(!this.parent){if(state!=null){this._value=state}return this._value}if(state!=null){return this.parent.set(this.key,state)}else{return this.parent.get(this.key)}};Ref.prototype.ref=function(key){if(!key){return this}return new Ref(null,this,key)};Ref.prototype.get=function(key){if(!key){return this.value()}else{if(this._cache[key]){return this._cache[key]}return this._cache[key]=this.index(key)}};Ref.prototype.set=function(key,value){var k,oldValue,v;if(isObject$1(key)){for(k in key){v=key[k];this.set(k,v)}return this}oldValue=this.get(key);this._mutate(key);if(value==null){this.value(index(this.value(),key))}else{this.index(key,value)}this._triggerSet(key,value,oldValue);this._triggerSetChildren(key,value,oldValue);return this};Ref.prototype._triggerSetChildren=function(key,value,oldValue){var child,childKeys,childRemainderKey,i,id,keyPart,keyParts,partialKey,ref,ref1,regExps,results;if(this._numChildren===0){return this}key=key+"";keyParts=key.split(".");partialKey="";childKeys=[];regExps={};for(i in keyParts){keyPart=keyParts[i];if(partialKey===""){partialKey=keyPart}else{partialKey+="."+keyPart}childKeys[i]=partialKey;regExps[partialKey]=new RegExp("^"+partialKey+".?")}ref=this._children;results=[];for(id in ref){child=ref[id];if(ref1=child.key,indexOf.call(childKeys,ref1)>=0){childRemainderKey=key.replace(regExps[child.key],"");child.trigger("set",childRemainderKey,value,oldValue);results.push(child._triggerSetChildren(childRemainderKey,value,oldValue))}else{results.push(void 0)}}return results};Ref.prototype._triggerSet=function(key,value,oldValue){var parentKey;this.trigger("set",key,value,oldValue);if(this.parent){parentKey=this.key+"."+key;return this.parent._triggerSet(parentKey,value,oldValue)}};Ref.prototype.extend=function(key,value){var clone;this._mutate(key);if(value==null){this.value(index(this.value(),key))}else{if(isObject$1(value)){this.value(index(this.ref(key).get(),value))}else{clone=this.clone();this.set(key,value);this.value(index(clone.get(),this.value()))}}return this};Ref.prototype.clone=function(key){return new Ref(index({},this.get(key)))};Ref.prototype.index=function(key,value,obj,prev){var next,prop,props;if(obj==null){obj=this.value()}if(this.parent){return this.parent.index(this.key+"."+key,value)}if(isNumber$1(key)){key=String(key)}props=key.split(".");if(value==null){while(prop=props.shift()){if(!props.length){return obj!=null?obj[prop]:void 0}obj=obj!=null?obj[prop]:void 0}return}while(prop=props.shift()){if(!props.length){return obj[prop]=value}else{next=props[0];if(obj[prop]==null){if(isNaN(Number(next))){if(obj[prop]==null){obj[prop]={}}}else{if(obj[prop]==null){obj[prop]=[]}}}}obj=obj[prop]}};return Ref}();var methods;var refer;methods=["extend","get","index","ref","set","value","on","off","one","trigger"];refer=function(state,ref){var fn,i,len,method,wrapper;if(ref==null){ref=null}if(ref==null){ref=new Ref$1(state)}wrapper=function(key){return ref.get(key)};fn=function(method){return wrapper[method]=function(){return ref[method].apply(ref,arguments)}};for(i=0,len=methods.length;i<len;i++){method=methods[i];fn(method)}wrapper.refer=function(key){return refer(null,ref.ref(key))};wrapper.clone=function(key){return refer(null,ref.clone(key))};return wrapper};refer.Ref=Ref$1;var refer$1=refer;return refer$1}();<|endoftext|>


<commit_before>/* jshint esversion: 6 */
(function($) {
    "use strict";

    let $tilkeeModal = $("#tilkee-modal .modal-content");
    function updateModal(html) {
        $tilkeeModal.html(html);
    }

    function showIntro() {
        let lastDisplay = localStorage.getItem("lastTilkeeIntroDisplay");
        let now = new Date().getTime();
        // Display Tilkee intro once per user and per month
        if (!lastDisplay || now-parseFloat(lastDisplay) > 30*24*60*60*1000) {
            localStorage.setItem("lastTilkeeIntroDisplay", now);
            showModal("#tilkee-modal");
        }
    }

    function initTilkeeModal(siret) {
        // Display modal with spinner
        showModal("#tilkee-modal");
        updateModal('

');
        ga('send', 'event', 'Tilkee', 'show', siret);
    }

    function initUploadForm(siret) {
        // Handle file selection
        let files = [];
        $tilkeeModal.find('.tilkee-file-select').on("click", function(e){
            e.preventDefault();
            $tilkeeModal.find("[name='files']").click();
            ga('send', 'event', 'Tilkee', 'browse-files', siret);
        });
        $tilkeeModal.find("[name='files']").on("change", function(e){
            let newfiles = $(this).prop("files");
            for (let f = 0; f < newfiles.length; f++) {
                files.push(newfiles[f]);
            }
            drawFileList(files, siret);
        });

        $tilkeeModal.find(".tilkee-upload-form").on("submit", function(evt) {
            evt.preventDefault();
            uploadDocuments($(this), siret, files);
        });
    }

    function initUploadedButtons() {
        $tilkeeModal.find(".tilkee-copy-text button").click(function() {
            copyToClipboard('tilkee-email-body');
            $(this).html("");
        });
    }

    function drawFileList(files, siret) {
        let $fileList = $tilkeeModal.find(".tilkee-files");
        $fileList.html("");
        for (let f = 0; f < files.length; f++) {
            let filename = files[f].name;
            $fileList.append("" + filename + "
\n");
        }
        if (files.length) {
            $tilkeeModal.find("[type='submit']").removeClass("hidden");
            ga('send', 'event', 'Tilkee', 'select-files', siret);
        } else {
            $tilkeeModal.find("[type='submit']").addClass("hidden");
            ga('send', 'event', 'Tilkee', 'select-no-file', siret);
        }
        $fileList.find(".tilkee-remove-file").click(function(){
            ga('send', 'event', 'Tilkee', 'remove-file');
            let f = $(this).attr("data-file-index");
            files.splice(parseInt(f), 1);
            drawFileList(files, siret);
        });
    }

    function uploadDocuments($form, siret, files) {
        let formData = new FormData();
        formData.set("csrf_token", $form.find("[name='csrf_token']")[0].value);
        for (let f = 0; f < files.length; f++) {
            formData.append('files', files[f], files[f].name);
        }

        $form.find("[type='submit']").prop("disabled", true);
        $.ajax({
            url: $form.attr("action"),
            type: 'POST',
            data: formData,
            cache: false,
            contentType: false,
            processData: false,
            success: function(html) {
                updateModal(html);
                initUploadedButtons();
                ga('send', 'event', 'Tilkee', 'upload', siret);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                if (jqXHR.status === 413) {
                    updateModal("Vos documents sont de trop grande taille : veuillez sélectionner des documents dont la taille totale est inférieure à 10 Mo.");
                } else if (jqXHR.status >= 500) {
                    updateModal("Une erreur inattendue s'est produite : nos équipes ont été prévenues et vont essayer de résoudre le problème très rapidement. Merci de réessayer plus tard.");
                } else {
                    updateModal("Erreur " + String(jqXHR.status) + " : est-ce que par hasard vous n'auriez pas essayé de faire quelque chose de fourbe ?");
                }
                ga('send', 'event', 'Tilkee', 'upload-error', siret);
            },
            complete: function() {
                $form.find("[type='submit']").prop("disabled", false);
            },
            xhr: function() {
                // Monitor upload progress
                let $messageElt = $tilkeeModal.find(".upload-progress-message");

                $tilkeeModal.find(".progressbar").removeClass("hidden");
                $messageElt.removeClass("hidden");
                let xhr = $.ajaxSettings.xhr();
                if (xhr.upload) {
                    xhr.upload.addEventListener('progress', function(e) {
                        if (e.lengthComputable) {
                            let percentage = e.loaded * 100/e.total;
                            $tilkeeModal.find(".progressbar span").css("width", String(percentage) + "%");
                            if (percentage < 100) {
                                $messageElt.html("1/2 Envoi de vos fichiers...");
                            } else {
                                $messageElt.html("2/2 Création de votre dossier...");
                            }
                        }
                    } , false);
                }
                return xhr;
            },
        });
    }

    $(document).on('lbbready', function() {
        showIntro();

        $(".tilkee-button").on("click", function(e) {
            e.preventDefault();
            $(this).tooltip("hide");
            let siret = $(this).attr("data-siret");
            initTilkeeModal(siret);

            // Load modal content
            $.get($(this).attr("href"), function(data) {
                updateModal(data);
                initUploadForm(siret);
            }).fail(function(e) {
                updateModal("Une erreur a eu lieu. Veuillez réessayer plus tard.");
            });

        });
    });
})(jQuery);
<commit_msg>Make Tilkee PoC compatible with Firefox 38<commit_after>/* jshint esversion: 6 */
(function($) {
    "use strict";

    var $tilkeeModal = $("#tilkee-modal .modal-content");
    function updateModal(html) {
        $tilkeeModal.html(html);
    }

    function showIntro() {
        var lastDisplay = localStorage.getItem("lastTilkeeIntroDisplay");
        var now = new Date().getTime();
        // Display Tilkee intro once per user and per month
        if (!lastDisplay || now-parseFloat(lastDisplay) > 30*24*60*60*1000) {
            localStorage.setItem("lastTilkeeIntroDisplay", now);
            showModal("#tilkee-modal");
        }
    }

    function initTilkeeModal(siret) {
        // Display modal with spinner
        showModal("#tilkee-modal");
        updateModal('

');
        ga('send', 'event', 'Tilkee', 'show', siret);
    }

    function initUploadForm(siret) {
        // Handle file selection
        var files = [];
        $tilkeeModal.find('.tilkee-file-select').on("click", function(e){
            e.preventDefault();
            $tilkeeModal.find("[name='files']").click();
            ga('send', 'event', 'Tilkee', 'browse-files', siret);
        });
        $tilkeeModal.find("[name='files']").on("change", function(e){
            var newfiles = $(this).prop("files");
            for (var f = 0; f < newfiles.length; f++) {
                files.push(newfiles[f]);
            }
            drawFileList(files, siret);
        });

        $tilkeeModal.find(".tilkee-upload-form").on("submit", function(evt) {
            evt.preventDefault();
            uploadDocuments($(this), siret, files);
        });
    }

    function initUploadedButtons() {
        $tilkeeModal.find(".tilkee-copy-text button").click(function() {
            copyToClipboard('tilkee-email-body');
            $(this).html("");
        });
    }

    function drawFileList(files, siret) {
        var $fileList = $tilkeeModal.find(".tilkee-files");
        $fileList.html("");
        for (var f = 0; f < files.length; f++) {
            var filename = files[f].name;
            $fileList.append("" + filename + "
\n");
        }
        if (files.length) {
            $tilkeeModal.find("[type='submit']").removeClass("hidden");
            ga('send', 'event', 'Tilkee', 'select-files', siret);
        } else {
            $tilkeeModal.find("[type='submit']").addClass("hidden");
            ga('send', 'event', 'Tilkee', 'select-no-file', siret);
        }
        $fileList.find(".tilkee-remove-file").click(function(){
            ga('send', 'event', 'Tilkee', 'remove-file');
            var f = $(this).attr("data-file-index");
            files.splice(parseInt(f), 1);
            drawFileList(files, siret);
        });
    }

    function uploadDocuments($form, siret, files) {
        var formData = new FormData();
        formData.set("csrf_token", $form.find("[name='csrf_token']")[0].value);
        for (var f = 0; f < files.length; f++) {
            formData.append('files', files[f], files[f].name);
        }

        $form.find("[type='submit']").prop("disabled", true);
        $.ajax({
            url: $form.attr("action"),
            type: 'POST',
            data: formData,
            cache: false,
            contentType: false,
            processData: false,
            success: function(html) {
                updateModal(html);
                initUploadedButtons();
                ga('send', 'event', 'Tilkee', 'upload', siret);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                if (jqXHR.status === 413) {
                    updateModal("Vos documents sont de trop grande taille : veuillez sélectionner des documents dont la taille totale est inférieure à 10 Mo.");
                } else if (jqXHR.status >= 500) {
                    updateModal("Une erreur inattendue s'est produite : nos équipes ont été prévenues et vont essayer de résoudre le problème très rapidement. Merci de réessayer plus tard.");
                } else {
                    updateModal("Erreur " + String(jqXHR.status) + " : est-ce que par hasard vous n'auriez pas essayé de faire quelque chose de fourbe ?");
                }
                ga('send', 'event', 'Tilkee', 'upload-error', siret);
            },
            complete: function() {
                $form.find("[type='submit']").prop("disabled", false);
            },
            xhr: function() {
                // Monitor upload progress
                var $messageElt = $tilkeeModal.find(".upload-progress-message");

                $tilkeeModal.find(".progressbar").removeClass("hidden");
                $messageElt.removeClass("hidden");
                var xhr = $.ajaxSettings.xhr();
                if (xhr.upload) {
                    xhr.upload.addEventListener('progress', function(e) {
                        if (e.lengthComputable) {
                            var percentage = e.loaded * 100/e.total;
                            $tilkeeModal.find(".progressbar span").css("width", String(percentage) + "%");
                            if (percentage < 100) {
                                $messageElt.html("1/2 Envoi de vos fichiers...");
                            } else {
                                $messageElt.html("2/2 Création de votre dossier...");
                            }
                        }
                    } , false);
                }
                return xhr;
            },
        });
    }

    $(document).on('lbbready', function() {
        showIntro();

        $(".tilkee-button").on("click", function(e) {
            e.preventDefault();
            $(this).tooltip("hide");
            var siret = $(this).attr("data-siret");
            initTilkeeModal(siret);

            // Load modal content
            $.get($(this).attr("href"), function(data) {
                updateModal(data);
                initUploadForm(siret);
            }).fail(function(e) {
                updateModal("Une erreur a eu lieu. Veuillez réessayer plus tard.");
            });

        });
    });
})(jQuery);
<|endoftext|>


<commit_before>/* globals XMLHttpRequest: true */
'use strict';

var React = require('react-native');
var {StyleSheet, TextInput, View, ListView, Image, Text, Dimensions, TouchableHighlight, Platform, ActivityIndicatorIOS, ProgressBarAndroid} = React;
var Qs = require('qs');

var defaultStyles = {
  container: {
  },
  textInputContainer: {
    backgroundColor: '#C9C9CE',
    height: 44,
    borderTopColor: '#7e7e7e',
    borderBottomColor: '#b5b5b5',
    borderTopWidth: 0.5,
    borderBottomWidth: 0.5,
  },
  textInput: {
    backgroundColor: '#FFFFFF',
    height: 28,
    borderRadius: 5,
    paddingTop: 4.5,
    paddingBottom: 4.5,
    paddingLeft: 10,
    paddingRight: 10,
    marginTop: 7.5,
    marginLeft: 8,
    marginRight: 8,
    fontSize: 15,
  },
  poweredContainer: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  powered: {
    marginTop: 15,
  },
  listView: {
    height: Dimensions.get('window').height - 44,
  },
  row: {
    padding: 13,
    height: 44,
    flexDirection: 'row',
  },
  separator: {
    height: 1,
    backgroundColor: '#c8c7cc',
  },
  description: {
  },
  loader: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    height: 20,
  },
  androidLoader: {
    marginRight: -15
  },
};

var GooglePlacesAutocomplete = React.createClass({

  propTypes: {
    placeholder: React.PropTypes.string,
    onPress: React.PropTypes.func,
    minLength: React.PropTypes.number,
    fetchDetails: React.PropTypes.bool,
    autoFocus: React.PropTypes.bool,
    getDefaultValue: React.PropTypes.func,
    timeout: React.PropTypes.number,
    onTimeout: React.PropTypes.func,
    query: React.PropTypes.object,
    styles: React.PropTypes.object,
  },

  getDefaultProps() {
    return {
      placeholder: 'Search',
      onPress: () => {},
      minLength: 0,
      fetchDetails: false,
      autoFocus: false,
      getDefaultValue: () => '',
      timeout: 20000,
      onTimeout: () => console.warn('google places autocomplete: request timeout'),
      query: {
        key: 'missing api key',
        language: 'en',
        types: 'geocode',
      },
      styles: {
      },
    };
  },

  getInitialState() {
    var ds = new ListView.DataSource({rowHasChanged: function(r1, r2) {
      if (typeof r1.isLoading !== 'undefined') {
        return true;
      }
      return r1 !== r2;
    }});
    return {
      text: this.props.getDefaultValue(),
      dataSource: ds.cloneWithRows([]),
      listViewDisplayed: false,
    };
  },
  _abortRequests() {
    for (let i = 0; i < this._requests.length; i++) {
      this._requests[i].abort();
    }
    this._requests = [];
  },
  componentWillUnmount() {
    this._abortRequests();
  },
  _enableRowLoader(rowData) {
    for (let i = 0; i < this._results.length; i++) {
      if (this._results[i].place_id === rowData.place_id) {
        this._results[i].isLoading = true;
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(this._results),
        });
        break;
      }
    }
  },
  _disableRowLoaders() {
    if (this.isMounted()) {
      for (let i = 0; i < this._results.length; i++) {
        if (this._results[i].isLoading === true) {
          this._results[i].isLoading = false;
        }
      }
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this._results),
      });
    }
  },
  _onPress(rowData) {
    if (this.props.fetchDetails === true) {
      if (rowData.isLoading === true) {
        // already requesting
        return;
      } else {
        this._abortRequests();
      }

      // display loader
      this._enableRowLoader(rowData);

      // fetch details
      var request = new XMLHttpRequest();
      this._requests.push(request);
      request.timeout = this.props.timeout;
      request.ontimeout = this.props.onTimeout;
      request.onreadystatechange = (e) => {
        if (request.readyState !== 4) {
          return;
        }
        if (request.status === 200) {
          var responseJSON = JSON.parse(request.responseText);
          if (responseJSON.status === 'OK') {
            if (this.isMounted()) {
              var details = responseJSON.result;
              this._disableRowLoaders();
              if (typeof this.refs.textInput.blur === 'function') {
                this.refs.textInput.blur();
              }

              this.setState({
                text: rowData.description,
                listViewDisplayed: false,
              });

              delete rowData.isLoading;
              this.props.onPress(rowData, details);
            }
          } else {
            this._disableRowLoaders();
            console.warn('google places autocomplete: '+responseJSON.status);
          }
        } else {
          this._disableRowLoaders();
          console.warn("google places autocomplete: request could not be completed or has been aborted");
        }
      };
      request.open('GET', 'https://maps.googleapis.com/maps/api/place/details/json?'+Qs.stringify({
        key: this.props.query.key,
        placeid: rowData.place_id,
        language: this.props.query.language,
      }));
      request.send();
    } else {
      this.setState({
        text: rowData.description,
        listViewDisplayed: false,
      });

      if (typeof this.refs.textInput.blur === 'function') {
        this.refs.textInput.blur();
      }
      delete rowData.isLoading;
      this.props.onPress(rowData);
    }
  },
  _results: [],
  _requests: [],
  _request(text) {
    this._abortRequests();
    if (text.length >= this.props.minLength) {
      var request = new XMLHttpRequest();
      this._requests.push(request);
      request.timeout = this.props.timeout;
      request.ontimeout = this.props.onTimeout;
      request.onreadystatechange = (e) => {
        if (request.readyState !== 4) {
          return;
        }
        if (request.status === 200) {
          var responseJSON = JSON.parse(request.responseText);
          if (typeof responseJSON.predictions !== 'undefined') {
            if (this.isMounted()) {
              this._results = responseJSON.predictions;
              this.setState({
                dataSource: this.state.dataSource.cloneWithRows(responseJSON.predictions),
              });
            }
          }
          if (typeof responseJSON.error_message !== 'undefined') {
            console.warn('google places autocomplete: '+responseJSON.error_message);
          }
        } else {
          // console.warn("google places autocomplete: request could not be completed or has been aborted");
        }
      };
      request.open('GET', 'https://maps.googleapis.com/maps/api/place/autocomplete/json?&input='+encodeURI(text)+'&'+Qs.stringify(this.props.query));
      request.send();
    } else {
      this._results = [];
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows([]),
      });
    }
  },
  _onChangeText(text) {
    this._request(text);
    this.setState({
      text: text,
      listViewDisplayed: true,
    });
  },
  _getRowLoader() {
    if (Platform.OS === 'android') {
      /* jshint ignore:start */
      return (
        <ProgressBarAndroid
          style={[defaultStyles.androidLoader, this.props.styles.androidLoader]}
          styleAttr="Inverse"
        />
      );
    } else {
      return (
        <ActivityIndicatorIOS
          animating={true}
          size="small"
        />
      );
      /* jshint ignore:end */
    }
  },

  _renderRow(rowData = {}) {
    rowData.description = rowData.description || 'Unknown';
    /* jshint ignore:start */
    return (
      <TouchableHighlight
        onPress={() =>
          this._onPress(rowData)
        }
        underlayColor="#c8c7cc"
      >
        <View>
          <View style={[defaultStyles.row, this.props.styles.row]}>
            <Text
              style={[defaultStyles.description, this.props.styles.description]}
              numberOfLines={1}
            >{rowData.description}</Text>
            <View
              style={[defaultStyles.loader, this.props.styles.loader]}
            >
              {rowData.isLoading === true ? this._getRowLoader() : null}
            </View>
          </View>
          <View style={[defaultStyles.separator, this.props.styles.separator]} />
        </View>
      </TouchableHighlight>
    );
    /* jshint ignore:end */
  },

  // _onBlur() {
  //   this.setState({listViewDisplayed: false});
  // },

  _onFocus() {
    this.setState({listViewDisplayed: true});
  },

  _getListView() {
    if (this.state.text !== '' && this.state.listViewDisplayed === true) {
      /* jshint ignore:start */
      return (
        <ListView
          keyboardShouldPersistTaps={true}
          keyboardDismissMode='none'
          style={[defaultStyles.listView, this.props.styles.listView]}
          dataSource={this.state.dataSource}
          renderRow={this._renderRow}
          automaticallyAdjustContentInsets={false}
        />
      );
    } else {
      return (
        <View
          style={[defaultStyles.poweredContainer, this.props.styles.poweredContainer]}
        >
          <Image
            style={[defaultStyles.powered, this.props.styles.powered]}
            resizeMode={Image.resizeMode.contain}
            source={require('./images/powered_by_google_on_white.png')}
          />
        </View>
      );
      /* jshint ignore:end */
    }
  },
  render() {
    /* jshint ignore:start */
    return (
      <View
        style={[defaultStyles.container, this.props.styles.container]}
      >
        <View
          style={[defaultStyles.textInputContainer, this.props.styles.textInputContainer]}
        >
          <TextInput
            ref='textInput'
            autoFocus={this.props.autoFocus}
            style={[defaultStyles.textInput, this.props.styles.textInput]}
            onChangeText={this._onChangeText}
            value={this.state.text}
            placeholder={this.props.placeholder}
            // onBlur={this._onBlur}
            onFocus={this._onFocus}
            clearButtonMode="while-editing"
          />
        </View>
        {this._getListView()}
      </View>
    );
    /* jshint ignore:end */
  },
});

// this function is still present in the library to be retrocompatible with version < 1.1.0
var create = function(options = {}) {
  return React.createClass({
    render() {
      return (
        <GooglePlacesAutocomplete ref='GooglePlacesAutocomplete'
          {...options}
        />
      );
    }
  });
};

module.exports = {GooglePlacesAutocomplete, create};<commit_msg>exposed triggerFocus method to parent components<commit_after>/* globals XMLHttpRequest: true */
'use strict';

var React = require('react-native');
var {StyleSheet, TextInput, View, ListView, Image, Text, Dimensions, TouchableHighlight, Platform, ActivityIndicatorIOS, ProgressBarAndroid} = React;
var Qs = require('qs');

var defaultStyles = {
  container: {
  },
  textInputContainer: {
    backgroundColor: '#C9C9CE',
    height: 44,
    borderTopColor: '#7e7e7e',
    borderBottomColor: '#b5b5b5',
    borderTopWidth: 0.5,
    borderBottomWidth: 0.5,
  },
  textInput: {
    backgroundColor: '#FFFFFF',
    height: 28,
    borderRadius: 5,
    paddingTop: 4.5,
    paddingBottom: 4.5,
    paddingLeft: 10,
    paddingRight: 10,
    marginTop: 7.5,
    marginLeft: 8,
    marginRight: 8,
    fontSize: 15,
  },
  poweredContainer: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  powered: {
    marginTop: 15,
  },
  listView: {
    height: Dimensions.get('window').height - 44,
  },
  row: {
    padding: 13,
    height: 44,
    flexDirection: 'row',
  },
  separator: {
    height: 1,
    backgroundColor: '#c8c7cc',
  },
  description: {
  },
  loader: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    height: 20,
  },
  androidLoader: {
    marginRight: -15
  },
};

var GooglePlacesAutocomplete = React.createClass({

  propTypes: {
    placeholder: React.PropTypes.string,
    onPress: React.PropTypes.func,
    minLength: React.PropTypes.number,
    fetchDetails: React.PropTypes.bool,
    autoFocus: React.PropTypes.bool,
    getDefaultValue: React.PropTypes.func,
    timeout: React.PropTypes.number,
    onTimeout: React.PropTypes.func,
    query: React.PropTypes.object,
    styles: React.PropTypes.object,
  },

  getDefaultProps() {
    return {
      placeholder: 'Search',
      onPress: () => {},
      minLength: 0,
      fetchDetails: false,
      autoFocus: false,
      getDefaultValue: () => '',
      timeout: 20000,
      onTimeout: () => console.warn('google places autocomplete: request timeout'),
      query: {
        key: 'missing api key',
        language: 'en',
        types: 'geocode',
      },
      styles: {
      },
    };
  },

  /**
   * This method is exposed to parent components to focus on textInput manually.
   * @public
   */
  triggerFocus: function() {
    this.refs.textInput.focus();
  },

  getInitialState() {
    var ds = new ListView.DataSource({rowHasChanged: function(r1, r2) {
      if (typeof r1.isLoading !== 'undefined') {
        return true;
      }
      return r1 !== r2;
    }});
    return {
      text: this.props.getDefaultValue(),
      dataSource: ds.cloneWithRows([]),
      listViewDisplayed: false,
    };
  },
  _abortRequests() {
    for (let i = 0; i < this._requests.length; i++) {
      this._requests[i].abort();
    }
    this._requests = [];
  },
  componentWillUnmount() {
    this._abortRequests();
  },
  _enableRowLoader(rowData) {
    for (let i = 0; i < this._results.length; i++) {
      if (this._results[i].place_id === rowData.place_id) {
        this._results[i].isLoading = true;
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(this._results),
        });
        break;
      }
    }
  },
  _disableRowLoaders() {
    if (this.isMounted()) {
      for (let i = 0; i < this._results.length; i++) {
        if (this._results[i].isLoading === true) {
          this._results[i].isLoading = false;
        }
      }
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this._results),
      });
    }
  },
  _onPress(rowData) {
    if (this.props.fetchDetails === true) {
      if (rowData.isLoading === true) {
        // already requesting
        return;
      } else {
        this._abortRequests();
      }

      // display loader
      this._enableRowLoader(rowData);

      // fetch details
      var request = new XMLHttpRequest();
      this._requests.push(request);
      request.timeout = this.props.timeout;
      request.ontimeout = this.props.onTimeout;
      request.onreadystatechange = (e) => {
        if (request.readyState !== 4) {
          return;
        }
        if (request.status === 200) {
          var responseJSON = JSON.parse(request.responseText);
          if (responseJSON.status === 'OK') {
            if (this.isMounted()) {
              var details = responseJSON.result;
              this._disableRowLoaders();
              if (typeof this.refs.textInput.blur === 'function') {
                this.refs.textInput.blur();
              }

              this.setState({
                text: rowData.description,
                listViewDisplayed: false,
              });

              delete rowData.isLoading;
              this.props.onPress(rowData, details);
            }
          } else {
            this._disableRowLoaders();
            console.warn('google places autocomplete: '+responseJSON.status);
          }
        } else {
          this._disableRowLoaders();
          console.warn("google places autocomplete: request could not be completed or has been aborted");
        }
      };
      request.open('GET', 'https://maps.googleapis.com/maps/api/place/details/json?'+Qs.stringify({
        key: this.props.query.key,
        placeid: rowData.place_id,
        language: this.props.query.language,
      }));
      request.send();
    } else {
      this.setState({
        text: rowData.description,
        listViewDisplayed: false,
      });

      if (typeof this.refs.textInput.blur === 'function') {
        this.refs.textInput.blur();
      }
      delete rowData.isLoading;
      this.props.onPress(rowData);
    }
  },
  _results: [],
  _requests: [],
  _request(text) {
    this._abortRequests();
    if (text.length >= this.props.minLength) {
      var request = new XMLHttpRequest();
      this._requests.push(request);
      request.timeout = this.props.timeout;
      request.ontimeout = this.props.onTimeout;
      request.onreadystatechange = (e) => {
        if (request.readyState !== 4) {
          return;
        }
        if (request.status === 200) {
          var responseJSON = JSON.parse(request.responseText);
          if (typeof responseJSON.predictions !== 'undefined') {
            if (this.isMounted()) {
              this._results = responseJSON.predictions;
              this.setState({
                dataSource: this.state.dataSource.cloneWithRows(responseJSON.predictions),
              });
            }
          }
          if (typeof responseJSON.error_message !== 'undefined') {
            console.warn('google places autocomplete: '+responseJSON.error_message);
          }
        } else {
          // console.warn("google places autocomplete: request could not be completed or has been aborted");
        }
      };
      request.open('GET', 'https://maps.googleapis.com/maps/api/place/autocomplete/json?&input='+encodeURI(text)+'&'+Qs.stringify(this.props.query));
      request.send();
    } else {
      this._results = [];
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows([]),
      });
    }
  },
  _onChangeText(text) {
    this._request(text);
    this.setState({
      text: text,
      listViewDisplayed: true,
    });
  },
  _getRowLoader() {
    if (Platform.OS === 'android') {
      /* jshint ignore:start */
      return (
        <ProgressBarAndroid
          style={[defaultStyles.androidLoader, this.props.styles.androidLoader]}
          styleAttr="Inverse"
        />
      );
    } else {
      return (
        <ActivityIndicatorIOS
          animating={true}
          size="small"
        />
      );
      /* jshint ignore:end */
    }
  },

  _renderRow(rowData = {}) {
    rowData.description = rowData.description || 'Unknown';
    /* jshint ignore:start */
    return (
      <TouchableHighlight
        onPress={() =>
          this._onPress(rowData)
        }
        underlayColor="#c8c7cc"
      >
        <View>
          <View style={[defaultStyles.row, this.props.styles.row]}>
            <Text
              style={[defaultStyles.description, this.props.styles.description]}
              numberOfLines={1}
            >{rowData.description}</Text>
            <View
              style={[defaultStyles.loader, this.props.styles.loader]}
            >
              {rowData.isLoading === true ? this._getRowLoader() : null}
            </View>
          </View>
          <View style={[defaultStyles.separator, this.props.styles.separator]} />
        </View>
      </TouchableHighlight>
    );
    /* jshint ignore:end */
  },

  // _onBlur() {
  //   this.setState({listViewDisplayed: false});
  // },

  _onFocus() {
    this.setState({listViewDisplayed: true});
  },

  _getListView() {
    if (this.state.text !== '' && this.state.listViewDisplayed === true) {
      /* jshint ignore:start */
      return (
        <ListView
          keyboardShouldPersistTaps={true}
          keyboardDismissMode='none'
          style={[defaultStyles.listView, this.props.styles.listView]}
          dataSource={this.state.dataSource}
          renderRow={this._renderRow}
          automaticallyAdjustContentInsets={false}
        />
      );
    } else {
      return (
        <View
          style={[defaultStyles.poweredContainer, this.props.styles.poweredContainer]}
        >
          <Image
            style={[defaultStyles.powered, this.props.styles.powered]}
            resizeMode={Image.resizeMode.contain}
            source={require('./images/powered_by_google_on_white.png')}
          />
        </View>
      );
      /* jshint ignore:end */
    }
  },
  render() {
    /* jshint ignore:start */
    return (
      <View
        style={[defaultStyles.container, this.props.styles.container]}
      >
        <View
          style={[defaultStyles.textInputContainer, this.props.styles.textInputContainer]}
        >
          <TextInput
            ref='textInput'
            autoFocus={this.props.autoFocus}
            style={[defaultStyles.textInput, this.props.styles.textInput]}
            onChangeText={this._onChangeText}
            value={this.state.text}
            placeholder={this.props.placeholder}
            // onBlur={this._onBlur}
            onFocus={this._onFocus}
            clearButtonMode="while-editing"
          />
        </View>
        {this._getListView()}
      </View>
    );
    /* jshint ignore:end */
  },
});

// this function is still present in the library to be retrocompatible with version < 1.1.0
var create = function(options = {}) {
  return React.createClass({
    render() {
      return (
        <GooglePlacesAutocomplete ref='GooglePlacesAutocomplete'
          {...options}
        />
      );
    }
  });
};

module.exports = {GooglePlacesAutocomplete, create};<|endoftext|>