<commit_before>Com['Tooltip'] = function(o){
    var that = this,
        config = cm.merge({
            'target' : cm.Node('div'),
            'targetEvent' : 'hover',        // hover | click | none
            'hideOnReClick' : false,        // Hide tooltip when re-clicking on the target, requires setting value 'targetEvent' : 'click'
            'preventClickEvent' : false,    // Prevent default click event on the target, requires setting value 'targetEvent' : 'click'
            'top' : 0,                      // Supported properties: targetHeight, selfWidth
            'left' : 0,                     // Supported properties: targetWidth, selfWidth
            'width' : 'auto',               // Supported properties: targetWidth | auto
            'className' : '',
            'adaptive' : true,
            'title' : '',
            'titleTag' : 'h3',
            'content' : cm.Node('div'),
            'container' : document.body,
            'events' : {}
        }, o),
        API = {
            'onShowStart' : [],
            'onShow' : [],
            'onHideStart' : [],
            'onHide' : []
        },
        checkInt,
        anim,
        isHide = true,
        nodes = {};

    var init = function(){
        // Convert events to API Events
        convertEvents(config['events']);
        // Render structure
        render();
        setMiscEvents();
    };

    var render = function(){
        // Structure
        nodes['container'] = cm.Node('div', {'class' : 'com-tooltip'},
            nodes['inner'] = cm.Node('div', {'class' : 'inner'},
                nodes['content'] = cm.Node('div', {'class' : 'scroll'})
            )
        );
        // Add css class
        !cm.isEmpty(config['className']) && cm.addClass(nodes['container'], config['className']);
        // Set title
        renderTitle(config['title']);
        // Embed content
        renderContent(config['content']);
    };

    var renderTitle = function(title){
        cm.remove(nodes['title']);
        if(!cm.isEmpty(title)){
            nodes['title'] = cm.Node('div', {'class' : 'title'},
                cm.Node(config['titleTag'], title)
            );
            cm.insertFirst(nodes['title'], nodes['inner']);
        }
    };

    var renderContent = function(node){
        cm.clearNode(nodes['content']);
        if(node){
            nodes['content'].appendChild(node);
        }
    };

    var setMiscEvents = function(){
        // Init animation
        anim = new cm.Animation(nodes['container']);
        // Add target event
        if(config['preventClickEvent']){
            config['target'].onclick = function(e){
                e = cm.getEvent(e);
                cm.preventDefault(e);
            };
        }
        setTargetEvent();
    };

    var targetEvent = function(){
        if(!isHide && config['targetEvent'] == 'click' && config['hideOnReClick']){
            hide(false);
        }else{
            show();
        }
    };

    var setTargetEvent = function(){
        switch(config['targetEvent']){
            case 'hover' :
                cm.addEvent(config['target'], 'mouseover', targetEvent);
                break;
            case 'click' :
                cm.addEvent(config['target'], 'click', targetEvent);
                break;
        }
    };

    var removeTargetEvent = function(){
        switch(config['targetEvent']){
            case 'hover' :
                cm.removeEvent(config['target'], 'mouseover', targetEvent);
                break;
            case 'click' :
                cm.removeEvent(config['target'], 'click', targetEvent);
                break;
        }
    };

    var show = function(){
        if(isHide){
            isHide = false;
            // Append child tooltip into body and set position
            config['container'].appendChild(nodes['container']);
            getPosition();
            // Show tooltip
            nodes['container'].style.display = 'block';
            // Check position
            checkInt = setInterval(getPosition, 5);
            // Animate
            anim.go({'style' : {'opacity' : 1}, 'duration' : 100, 'onStop' : function(){
                /* *** EXECUTE API EVENTS *** */
                executeEvent('onShow');
            }});
            // Add document target event
            switch(config['targetEvent']){
                case 'hover' :
                    cm.addEvent(document, 'mouseover', bodyEvent);
                    break;
                case 'click' :
                    cm.addEvent(document, 'mousedown', bodyEvent);
                    break;
            }
            /* *** EXECUTE API EVENTS *** */
            executeEvent('onShowStart');
        }
    };

    var hide = function(immediately){
        if(!isHide){
            isHide = true;
            // Remove event - Check position
            checkInt && clearInterval(checkInt);
            // Remove document target event
            switch(config['targetEvent']){
                case 'hover' :
                    cm.removeEvent(document, 'mouseover', bodyEvent);
                    break;
                case 'click' :
                    cm.removeEvent(document, 'mousedown', bodyEvent);
                    break;
            }
            // Animate
            anim.go({'style' : {'opacity' : 0}, 'duration' : immediately? 0 : 100, 'onStop' : function(){
                nodes['container'].style.display = 'none';
                cm.remove(nodes['container']);
                /* *** EXECUTE API EVENTS *** */
                executeEvent('onHide');
            }});
            /* *** EXECUTE API EVENTS *** */
            executeEvent('onHideStart');
        }
    };

    var getPosition = function(){
        var targetWidth =  config['target'].offsetWidth,
            targetHeight = config['target'].offsetHeight,
            selfHeight = nodes['container'].offsetHeight,
            selfWidth = nodes['container'].offsetWidth,
            pageSize = cm.getPageSize();
        // Calculate size
        (function(){
            if(config['width'] != 'auto'){
                var width = eval(config['width'].toString().replace('targetWidth', targetWidth));

                if(width != selfWidth){
                    nodes['container'].style.width =  [width, 'px'].join('');
                }
            }
        })();
        // Calculate position
        (function(){
            var top = cm.getRealY(config['target']),
                topAdd = eval(
                    config['top']
                        .toString()
                        .replace('targetHeight', targetHeight)
                        .replace('selfHeight', selfHeight)
                ),
                left =  cm.getRealX(config['target']),
                leftAdd = eval(
                    config['left']
                        .toString()
                        .replace('targetWidth', targetWidth)
                        .replace('selfWidth', selfWidth)
                ),
                positionTop = (config['adaptive'] && top + topAdd + selfHeight > pageSize['winHeight']?
                    (top - topAdd - selfHeight + targetHeight) : top + topAdd
                ),
                positionLeft = (config['adaptive'] && left + leftAdd + selfWidth > pageSize['winWidth']?
                    (left - leftAdd - selfWidth + targetWidth) : left + leftAdd
                );

            if(positionTop != nodes['container'].offsetTop){
                nodes['container'].style.top =  [positionTop, 'px'].join('');
            }
            if(positionLeft != nodes['container'].offsetLeft){
                nodes['container'].style.left = [positionLeft, 'px'].join('');
            }
        })();
    };

    var bodyEvent = function(e){
        if(!isHide){
            e = cm.getEvent(e);
            var target = cm.getEventTarget(e);
            if(!cm.isParent(nodes['container'], target, true) && !cm.isParent(config['target'], target, true)){
                hide(false);
            }
        }
    };

    var executeEvent = function(event){
        var handler = function(){
            cm.forEach(API[event], function(item){
                item(that);
            });
        };

        switch(event){
            default:
                handler();
                break;
        }
    };

    var convertEvents = function(o){
        cm.forEach(o, function(item, key){
            if(API[key] && typeof item == 'function'){
                API[key].push(item);
            }
        });
    };

    /* Main */

    that.setTitle = function(title){
        renderTitle(title);
        return that;
    };

    that.setContent = function(node){
        renderContent(node);
        return that;
    };

    that.setTarget = function(node){
        removeTargetEvent();
        config['target'] = node || cm.Node('div');
        setTargetEvent();
        return that;
    };

    that.show = function(){
        show();
        return that;
    };

    that.hide = function(immediately){
        hide(immediately);
        return that;
    };

    that.isHide = function(){
        return isHide;
    };

    that.addEvent = function(event, handler){
        if(API[event] && typeof handler == 'function'){
            API[event].push(handler);
        }
        return that;
    };

    that.removeEvent = function(event, handler){
        if(API[event] && typeof handler == 'function'){
            API[event] = API[event].filter(function(item){
                return item != handler;
            });
        }
        return that;
    };

    that.getNodes = function(key){
        return nodes[key] || nodes;
    };

    that.remove = function(){
        hide(true);
        removeTargetEvent();
        return that;
    };

    init();
};<commit_msg>* JS. Fix with position of Com.Tooltip.<commit_after>Com['Tooltip'] = function(o){
    var that = this,
        config = cm.merge({
            'target' : cm.Node('div'),
            'targetEvent' : 'hover',        // hover | click | none
            'hideOnReClick' : false,        // Hide tooltip when re-clicking on the target, requires setting value 'targetEvent' : 'click'
            'preventClickEvent' : false,    // Prevent default click event on the target, requires setting value 'targetEvent' : 'click'
            'top' : 0,                      // Supported properties: targetHeight, selfWidth
            'left' : 0,                     // Supported properties: targetWidth, selfWidth
            'width' : 'auto',               // Supported properties: targetWidth | auto
            'className' : '',
            'adaptive' : true,
            'title' : '',
            'titleTag' : 'h3',
            'content' : cm.Node('div'),
            'container' : document.body,
            'events' : {}
        }, o),
        API = {
            'onShowStart' : [],
            'onShow' : [],
            'onHideStart' : [],
            'onHide' : []
        },
        checkInt,
        anim,
        isHide = true,
        nodes = {};

    var init = function(){
        // Convert events to API Events
        convertEvents(config['events']);
        // Render structure
        render();
        setMiscEvents();
    };

    var render = function(){
        // Structure
        nodes['container'] = cm.Node('div', {'class' : 'com-tooltip'},
            nodes['inner'] = cm.Node('div', {'class' : 'inner'},
                nodes['content'] = cm.Node('div', {'class' : 'scroll'})
            )
        );
        // Add css class
        !cm.isEmpty(config['className']) && cm.addClass(nodes['container'], config['className']);
        // Set title
        renderTitle(config['title']);
        // Embed content
        renderContent(config['content']);
    };

    var renderTitle = function(title){
        cm.remove(nodes['title']);
        if(!cm.isEmpty(title)){
            nodes['title'] = cm.Node('div', {'class' : 'title'},
                cm.Node(config['titleTag'], title)
            );
            cm.insertFirst(nodes['title'], nodes['inner']);
        }
    };

    var renderContent = function(node){
        cm.clearNode(nodes['content']);
        if(node){
            nodes['content'].appendChild(node);
        }
    };

    var setMiscEvents = function(){
        // Init animation
        anim = new cm.Animation(nodes['container']);
        // Add target event
        if(config['preventClickEvent']){
            config['target'].onclick = function(e){
                e = cm.getEvent(e);
                cm.preventDefault(e);
            };
        }
        setTargetEvent();
    };

    var targetEvent = function(){
        if(!isHide && config['targetEvent'] == 'click' && config['hideOnReClick']){
            hide(false);
        }else{
            show();
        }
    };

    var setTargetEvent = function(){
        switch(config['targetEvent']){
            case 'hover' :
                cm.addEvent(config['target'], 'mouseover', targetEvent);
                break;
            case 'click' :
                cm.addEvent(config['target'], 'click', targetEvent);
                break;
        }
    };

    var removeTargetEvent = function(){
        switch(config['targetEvent']){
            case 'hover' :
                cm.removeEvent(config['target'], 'mouseover', targetEvent);
                break;
            case 'click' :
                cm.removeEvent(config['target'], 'click', targetEvent);
                break;
        }
    };

    var show = function(){
        if(isHide){
            isHide = false;
            // Append child tooltip into body and set position
            config['container'].appendChild(nodes['container']);
            getPosition();
            // Show tooltip
            nodes['container'].style.display = 'block';
            // Check position
            checkInt = setInterval(getPosition, 5);
            // Animate
            anim.go({'style' : {'opacity' : 1}, 'duration' : 100, 'onStop' : function(){
                /* *** EXECUTE API EVENTS *** */
                executeEvent('onShow');
            }});
            // Add document target event
            switch(config['targetEvent']){
                case 'hover' :
                    cm.addEvent(document, 'mouseover', bodyEvent);
                    break;
                case 'click' :
                    cm.addEvent(document, 'mousedown', bodyEvent);
                    break;
            }
            /* *** EXECUTE API EVENTS *** */
            executeEvent('onShowStart');
        }
    };

    var hide = function(immediately){
        if(!isHide){
            isHide = true;
            // Remove event - Check position
            checkInt && clearInterval(checkInt);
            // Remove document target event
            switch(config['targetEvent']){
                case 'hover' :
                    cm.removeEvent(document, 'mouseover', bodyEvent);
                    break;
                case 'click' :
                    cm.removeEvent(document, 'mousedown', bodyEvent);
                    break;
            }
            // Animate
            anim.go({'style' : {'opacity' : 0}, 'duration' : immediately? 0 : 100, 'onStop' : function(){
                nodes['container'].style.display = 'none';
                cm.remove(nodes['container']);
                /* *** EXECUTE API EVENTS *** */
                executeEvent('onHide');
            }});
            /* *** EXECUTE API EVENTS *** */
            executeEvent('onHideStart');
        }
    };

    var getPosition = function(){
        var targetWidth =  config['target'].offsetWidth,
            targetHeight = config['target'].offsetHeight,
            selfHeight = nodes['container'].offsetHeight,
            selfWidth = nodes['container'].offsetWidth,
            pageSize = cm.getPageSize();
        // Calculate size
        (function(){
            if(config['width'] != 'auto'){
                var width = eval(config['width'].toString().replace('targetWidth', targetWidth));

                if(width != selfWidth){
                    nodes['container'].style.width =  [width, 'px'].join('');
                }
            }
        })();
        // Calculate position
        (function(){
            var top = cm.getRealY(config['target']),
                topAdd = eval(
                    config['top']
                        .toString()
                        .replace('targetHeight', targetHeight)
                        .replace('selfHeight', selfHeight)
                ),
                left =  cm.getRealX(config['target']),
                leftAdd = eval(
                    config['left']
                        .toString()
                        .replace('targetWidth', targetWidth)
                        .replace('selfWidth', selfWidth)
                ),
                positionTop = (config['adaptive'] && top + topAdd + selfHeight > pageSize['winHeight']?
                    (top - topAdd - selfHeight + targetHeight) : top + topAdd
                ),
                positionLeft = (config['adaptive'] && left + leftAdd + selfWidth > pageSize['winWidth']?
                    (left - leftAdd - selfWidth + targetWidth) : left + leftAdd
                );

            if(positionTop != nodes['container'].offsetTop){
                nodes['container'].style.top =  [Math.max(positionTop, 0), 'px'].join('');
            }
            if(positionLeft != nodes['container'].offsetLeft){
                nodes['container'].style.left = [Math.max(positionLeft, 0), 'px'].join('');
            }
        })();
    };

    var bodyEvent = function(e){
        if(!isHide){
            e = cm.getEvent(e);
            var target = cm.getEventTarget(e);
            if(!cm.isParent(nodes['container'], target, true) && !cm.isParent(config['target'], target, true)){
                hide(false);
            }
        }
    };

    var executeEvent = function(event){
        var handler = function(){
            cm.forEach(API[event], function(item){
                item(that);
            });
        };

        switch(event){
            default:
                handler();
                break;
        }
    };

    var convertEvents = function(o){
        cm.forEach(o, function(item, key){
            if(API[key] && typeof item == 'function'){
                API[key].push(item);
            }
        });
    };

    /* Main */

    that.setTitle = function(title){
        renderTitle(title);
        return that;
    };

    that.setContent = function(node){
        renderContent(node);
        return that;
    };

    that.setTarget = function(node){
        removeTargetEvent();
        config['target'] = node || cm.Node('div');
        setTargetEvent();
        return that;
    };

    that.show = function(){
        show();
        return that;
    };

    that.hide = function(immediately){
        hide(immediately);
        return that;
    };

    that.isHide = function(){
        return isHide;
    };

    that.addEvent = function(event, handler){
        if(API[event] && typeof handler == 'function'){
            API[event].push(handler);
        }
        return that;
    };

    that.removeEvent = function(event, handler){
        if(API[event] && typeof handler == 'function'){
            API[event] = API[event].filter(function(item){
                return item != handler;
            });
        }
        return that;
    };

    that.getNodes = function(key){
        return nodes[key] || nodes;
    };

    that.remove = function(){
        hide(true);
        removeTargetEvent();
        return that;
    };

    init();
};<|endoftext|>


<commit_before>(function(app) {
  'use strict';

  var FileSaver = require('file-saver');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var Component = app.Component || require('./component.js');
  var ContentHeader = app.ContentHeader || require('./content-header.js');
  var ModuleContainer = app.ModuleContainer || require('./module-container.js');

  var Content = helper.inherits(function(props) {
    Content.super_.call(this, props);

    this.header = new ContentHeader({
      element: this.headerElement(),
      sidebarCollapser: props.sidebarCollapser,
      sidebarExpander: props.sidebarExpander,
      fileLoader: Content.prototype.fileLoader.bind(this),
      fileSaver: Content.prototype.fileSaver.bind(this),
    });

    this.moduleContainer = new ModuleContainer({
      element: this.moduleContainerElement(),
      moduleDragStarter: props.moduleDragStarter,
      moduleDragEnder: props.moduleDragEnder,
    });
  }, Component);

  Content.prototype.headerElement = function() {
    return dom.child(this.element(), 0);
  };

  Content.prototype.moduleContainerElement = function() {
    return dom.child(this.element(), 1);
  };

  Content.prototype.disabled = function(value) {
    this.header.disabled(value);
    this.moduleContainer.disabled(value);
  };

  Content.prototype.loadModuleByClientPosition = function(props, visiblePortNames) {
    return this.moduleContainer.loadModuleByClientPosition(props, visiblePortNames).catch(function(e) {
      if (!(e instanceof RangeError)) {
        throw e;
      }
    });
  };

  Content.prototype.redraw = function() {
    this.header.redraw();
    this.moduleContainer.redraw();
  };

  Content.prototype.fileLoader = function(file) {
    this.disabled(true);
    dom.load(file).then(function(text) {
      var data = JSON.parse(text);
      this.moduleContainer.clear();
      this.moduleContainer.load(data);
    }.bind(this)).catch(function(e) {
      alert(e);
    }).then(function() {
      this.disabled(false);
    }.bind(this));
  };

  Content.prototype.fileSaver = function() {
    var text = JSON.stringify(this.moduleContainer.toData());
    var blob = new Blob([text], { type: 'application/json' });
    FileSaver.saveAs(blob, 'download.json');
  };

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = Content;
  } else {
    app.Content = Content;
  }
})(this.app || (this.app = {}));
<commit_msg>Fix code to wait for completion of file loading<commit_after>(function(app) {
  'use strict';

  var FileSaver = require('file-saver');
  var helper = app.helper || require('../helper.js');
  var dom = app.dom || require('../dom.js');
  var Component = app.Component || require('./component.js');
  var ContentHeader = app.ContentHeader || require('./content-header.js');
  var ModuleContainer = app.ModuleContainer || require('./module-container.js');

  var Content = helper.inherits(function(props) {
    Content.super_.call(this, props);

    this.header = new ContentHeader({
      element: this.headerElement(),
      sidebarCollapser: props.sidebarCollapser,
      sidebarExpander: props.sidebarExpander,
      fileLoader: Content.prototype.fileLoader.bind(this),
      fileSaver: Content.prototype.fileSaver.bind(this),
    });

    this.moduleContainer = new ModuleContainer({
      element: this.moduleContainerElement(),
      moduleDragStarter: props.moduleDragStarter,
      moduleDragEnder: props.moduleDragEnder,
    });
  }, Component);

  Content.prototype.headerElement = function() {
    return dom.child(this.element(), 0);
  };

  Content.prototype.moduleContainerElement = function() {
    return dom.child(this.element(), 1);
  };

  Content.prototype.disabled = function(value) {
    this.header.disabled(value);
    this.moduleContainer.disabled(value);
  };

  Content.prototype.loadModuleByClientPosition = function(props, visiblePortNames) {
    return this.moduleContainer.loadModuleByClientPosition(props, visiblePortNames).catch(function(e) {
      if (!(e instanceof RangeError)) {
        throw e;
      }
    });
  };

  Content.prototype.redraw = function() {
    this.header.redraw();
    this.moduleContainer.redraw();
  };

  Content.prototype.fileLoader = function(file) {
    this.disabled(true);
    dom.load(file).then(function(text) {
      var data = JSON.parse(text);
      this.moduleContainer.clear();
      return this.moduleContainer.load(data);
    }.bind(this)).catch(function(e) {
      alert(e);
    }).then(function() {
      this.disabled(false);
    }.bind(this));
  };

  Content.prototype.fileSaver = function() {
    var text = JSON.stringify(this.moduleContainer.toData());
    var blob = new Blob([text], { type: 'application/json' });
    FileSaver.saveAs(blob, 'download.json');
  };

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = Content;
  } else {
    app.Content = Content;
  }
})(this.app || (this.app = {}));
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014-2015 Broad Institute
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

import igvxhr from "../igvxhr.js";
import Zlib from "../vendor/zlib_and_gzip.js";
import {buildOptions} from "../util/igvUtils.js";

const google = {

        fileInfoCache: {},

        // Crude test, this is conservative, nothing bad happens for a false positive
        isGoogleURL: function (url) {
            return (url.includes("googleapis") && !url.includes("urlshortener")) ||
                this.isGoogleCloudURL(url) ||
                this.isGoogleStorageURL(url) ||
                this.isGoogleDrive(url)
        },

        isGoogleStorageURL: function (url) {
            return url.startsWith("https://www.googleapis.com/storage") ||
                url.startsWith("https://storage.cloud.google.com")
        },

        isGoogleCloudURL: function (url) {
            return url.startsWith("gs://")
        },

        isGoogleDrive: function (url) {
            return url.indexOf("drive.google.com") >= 0 || url.indexOf("www.googleapis.com/drive") > 0
        },

        setApiKey: function (key) {
            this.apiKey = key;
        },

        translateGoogleCloudURL: function (gsUrl) {

            var i, bucket, object, qIdx, objectString, paramString;

            i = gsUrl.indexOf('/', 5);
            qIdx = gsUrl.indexOf('?');

            if (i < 0) {
                console.log("Invalid gs url: " + gsUrl);
                return gsUrl;
            }

            bucket = gsUrl.substring(5, i);

            objectString = (qIdx < 0) ? gsUrl.substring(i + 1) : gsUrl.substring(i + 1, qIdx);
            object = encodeURIComponent(objectString);

            if (qIdx > 0) {
                paramString = gsUrl.substring(qIdx);
            }

            return "https://www.googleapis.com/storage/v1/b/" + bucket + "/o/" + object +
                (paramString ? paramString + "&alt=media" : "?alt=media");

        },

        addApiKey: function (url) {
            const apiKey = this.apiKey
            if (apiKey !== undefined && !url.includes("key=")) {
                const paramSeparator = url.includes("?") ? "&" : "?"
                url = url + paramSeparator + "key=" + apiKey;
            }
            return url;
        },

        driveDownloadURL: function (link) {
            // Return a google drive download url for the sharable link
            //https://drive.google.com/open?id=0B-lleX9c2pZFbDJ4VVRxakJzVGM
            //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing

            var id = getGoogleDriveFileID(link);

            return id ? "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media&supportsTeamDrives=true" : link;
        },

        getDriveFileInfo: function (googleDriveURL) {

            var id = getGoogleDriveFileID(googleDriveURL),
                endPoint = "https://www.googleapis.com/drive/v3/files/" + id + "?supportsTeamDrives=true";

            return igvxhr.loadJson(endPoint, buildOptions({}));
        },

        loadGoogleProperties: function (propertiesURL) {

            const self = this;

            return igvxhr.loadArrayBuffer(propertiesURL)

                .then(function (arrayBuffer) {
                    var inflate, plain, str;

                    inflate = new Zlib.Gunzip(new Uint8Array(arrayBuffer));
                    plain = inflate.decompress();
                    str = String.fromCharCode.apply(null, plain);

                    const properties = JSON.parse(str);
                    self.setApiKey(properties["api_key"]);

                    self.properties = properties;
                    return properties;

                })
        }
    }

    function getGoogleDriveFileID(link) {

        //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing
        var i1, i2;

        if (link.includes("/open?id=")) {
            i1 = link.indexOf("/open?id=") + 9;
            i2 = link.indexOf("&");
            if (i1 > 0 && i2 > i1) {
                return link.substring(i1, i2)
            } else if (i1 > 0) {
                return link.substring(i1);
            }

        } else if (link.includes("/file/d/")) {
            i1 = link.indexOf("/file/d/") + 8;
            i2 = link.lastIndexOf("/");
            return link.substring(i1, i2);
        }
    }

export default google;

<commit_msg>refine google storage test<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014-2015 Broad Institute
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

import igvxhr from "../igvxhr.js";
import Zlib from "../vendor/zlib_and_gzip.js";
import {buildOptions} from "../util/igvUtils.js";

const google = {

        fileInfoCache: {},

        // Crude test, this is conservative, nothing bad happens for a false positive
        isGoogleURL: function (url) {
            return (url.includes("googleapis") && !url.includes("urlshortener")) ||
                this.isGoogleCloudURL(url) ||
                this.isGoogleStorageURL(url) ||
                this.isGoogleDrive(url)
        },

        isGoogleStorageURL: function (url) {
            return url.startsWith("https://www.googleapis.com/storage") ||
                url.startsWith("https://storage.cloud.google.com")  ||
                url.startsWith("https://storage.googleapis.com");
        },

        isGoogleCloudURL: function (url) {
            return url.startsWith("gs://")
        },

        isGoogleDrive: function (url) {
            return url.indexOf("drive.google.com") >= 0 || url.indexOf("www.googleapis.com/drive") > 0
        },

        setApiKey: function (key) {
            this.apiKey = key;
        },

        translateGoogleCloudURL: function (gsUrl) {

            var i, bucket, object, qIdx, objectString, paramString;

            i = gsUrl.indexOf('/', 5);
            qIdx = gsUrl.indexOf('?');

            if (i < 0) {
                console.log("Invalid gs url: " + gsUrl);
                return gsUrl;
            }

            bucket = gsUrl.substring(5, i);

            objectString = (qIdx < 0) ? gsUrl.substring(i + 1) : gsUrl.substring(i + 1, qIdx);
            object = encodeURIComponent(objectString);

            if (qIdx > 0) {
                paramString = gsUrl.substring(qIdx);
            }

            return "https://www.googleapis.com/storage/v1/b/" + bucket + "/o/" + object +
                (paramString ? paramString + "&alt=media" : "?alt=media");

        },

        addApiKey: function (url) {
            const apiKey = this.apiKey
            if (apiKey !== undefined && !url.includes("key=")) {
                const paramSeparator = url.includes("?") ? "&" : "?"
                url = url + paramSeparator + "key=" + apiKey;
            }
            return url;
        },

        driveDownloadURL: function (link) {
            // Return a google drive download url for the sharable link
            //https://drive.google.com/open?id=0B-lleX9c2pZFbDJ4VVRxakJzVGM
            //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing

            var id = getGoogleDriveFileID(link);

            return id ? "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media&supportsTeamDrives=true" : link;
        },

        getDriveFileInfo: function (googleDriveURL) {

            var id = getGoogleDriveFileID(googleDriveURL),
                endPoint = "https://www.googleapis.com/drive/v3/files/" + id + "?supportsTeamDrives=true";

            return igvxhr.loadJson(endPoint, buildOptions({}));
        },

        loadGoogleProperties: function (propertiesURL) {

            const self = this;

            return igvxhr.loadArrayBuffer(propertiesURL)

                .then(function (arrayBuffer) {
                    var inflate, plain, str;

                    inflate = new Zlib.Gunzip(new Uint8Array(arrayBuffer));
                    plain = inflate.decompress();
                    str = String.fromCharCode.apply(null, plain);

                    const properties = JSON.parse(str);
                    self.setApiKey(properties["api_key"]);

                    self.properties = properties;
                    return properties;

                })
        }
    }

    function getGoogleDriveFileID(link) {

        //https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing
        var i1, i2;

        if (link.includes("/open?id=")) {
            i1 = link.indexOf("/open?id=") + 9;
            i2 = link.indexOf("&");
            if (i1 > 0 && i2 > i1) {
                return link.substring(i1, i2)
            } else if (i1 > 0) {
                return link.substring(i1);
            }

        } else if (link.includes("/file/d/")) {
            i1 = link.indexOf("/file/d/") + 8;
            i2 = link.lastIndexOf("/");
            return link.substring(i1, i2);
        }
    }

export default google;

<|endoftext|>


<commit_before>iD.behavior.Select = function(context) {
    function keydown() {
        if (d3.event && d3.event.shiftKey) {
            context.surface()
                .classed('behavior-multiselect', true);
        }
    }

    function keyup() {
        if (!d3.event || !d3.event.shiftKey) {
            context.surface()
                .classed('behavior-multiselect', false);
        }
    }

    function click() {
        var datum = d3.event.target.__data__;
        if (!(datum instanceof iD.Entity)) {
            if (!d3.event.shiftKey)
                context.enter(iD.modes.Browse(context));

        } else if (!d3.event.shiftKey) {
            // Avoid re-entering Select mode with same entity.
            if (context.selection().length !== 1 || context.selection()[0] !== datum.id) {
                context.enter(iD.modes.Select(context, [datum.id]));
            } else {
                context.mode().reselect();
            }
        } else if (context.selection().indexOf(datum.id) >= 0) {
            var selection = _.without(context.selection(), datum.id);
            context.enter(selection.length ?
                iD.modes.Select(context, selection) :
                iD.modes.Browse(context));

        } else {
            context.enter(iD.modes.Select(context, context.selection().concat([datum.id])));
        }
    }

    var behavior = function(selection) {
        d3.select(window)
            .on('keydown.select', keydown)
            .on('keyup.select', keyup);

        selection.on('click.select', click);

        keydown();
    };

    behavior.off = function(selection) {
        d3.select(window)
            .on('keydown.select', null)
            .on('keyup.select', null);

        selection.on('click.select', null);

        keyup();
    };

    return behavior;
};
<commit_msg>lasso works if shift is released before mouseup<commit_after>iD.behavior.Select = function(context) {
    function keydown() {
        if (d3.event && d3.event.shiftKey) {
            context.surface()
                .classed('behavior-multiselect', true);
        }
    }

    function keyup() {
        if (!d3.event || !d3.event.shiftKey) {
            context.surface()
                .classed('behavior-multiselect', false);
        }
    }

    function click() {
        var datum = d3.event.target.__data__;
        var lasso = d3.select('#surface .lasso').node();
        if (!(datum instanceof iD.Entity)) {
            if (!d3.event.shiftKey && !lasso)
                context.enter(iD.modes.Browse(context));

        } else if (!d3.event.shiftKey && !lasso) {
            // Avoid re-entering Select mode with same entity.
            if (context.selection().length !== 1 || context.selection()[0] !== datum.id) {
                context.enter(iD.modes.Select(context, [datum.id]));
            } else {
                context.mode().reselect();
            }
        } else if (context.selection().indexOf(datum.id) >= 0) {
            var selection = _.without(context.selection(), datum.id);
            context.enter(selection.length ?
                iD.modes.Select(context, selection) :
                iD.modes.Browse(context));

        } else {
            context.enter(iD.modes.Select(context, context.selection().concat([datum.id])));
        }
    }

    var behavior = function(selection) {
        d3.select(window)
            .on('keydown.select', keydown)
            .on('keyup.select', keyup);

        selection.on('click.select', click);

        keydown();
    };

    behavior.off = function(selection) {
        d3.select(window)
            .on('keydown.select', null)
            .on('keyup.select', null);

        selection.on('click.select', null);

        keyup();
    };

    return behavior;
};
<|endoftext|>


<commit_before>iD.ui.preset.radio = function(field) {

    var event = d3.dispatch('change'),
        buttons;

    function radio(selection) {
        selection.classed('preset-radio', true);

        var wrap = selection.selectAll('.preset-input-wrap')
            .data([0]);

        var buttonWrap = wrap.enter().append('div')
            .attr('class', 'preset-input-wrap toggle-list radio-wrap');

        buttons = wrap.selectAll('button')
            .data(field.options || field.keys);

        buttons.enter().append('button')
            .text(function(d) { return field.t('options.' + d, { 'default': d }); });

        buttons
            .on('click', function(d) {
                buttons.classed('active', function(e) { return d === e; });
                change();
            });

        buttonWrap.append('span')
            .attr('class','placeholder')
            .text(field.placeholder());

        var remove = wrap.selectAll('button.remove')
            .data([0]);

        remove.enter().append('button')
            .attr('class', 'remove')
            .text(t('inspector.remove'))
            .append('span')
            .attr('class', 'icon remove');

        remove
            .on('click', function() {
                buttons.classed('active', false);
                change();
            });

    }

    function change() {
        var t = {};
        if (field.key) t[field.key] = undefined;
        buttons.each(function(d) {
            var active = d3.select(this).classed('active');
            if (field.key) {
                if (active) t[field.key] = d;
            } else {
                t[d] = active ? 'yes' : undefined;
            }
        });
        event.change(t);
    }

    radio.tags = function(tags) {
        buttons.classed('active', function(d) {
            if (field.key) {
                return tags[field.key] === d;
            } else {
                return tags[d] && tags[d] !== 'no';
            }
        });
    };

    radio.focus = function() {
        buttons.node().focus();
    };

    return d3.rebind(radio, event, 'on');
};
<commit_msg>Fix radio field click behavior<commit_after>iD.ui.preset.radio = function(field) {

    var event = d3.dispatch('change'),
        buttons;

    function radio(selection) {
        selection.classed('preset-radio', true);

        var wrap = selection.selectAll('.preset-input-wrap')
            .data([0]);

        var buttonWrap = wrap.enter().append('div')
            .attr('class', 'preset-input-wrap toggle-list radio-wrap');

        buttons = wrap.selectAll('button')
            .data(field.options || field.keys);

        buttons.enter().append('button')
            .text(function(d) { return field.t('options.' + d, { 'default': d }); });

        buttons
            .on('click', function(d) {
                d3.event.preventDefault();
                buttons.classed('active', function(e) { return d === e; });
                change();
            });

        buttonWrap.append('span')
            .attr('class','placeholder')
            .text(field.placeholder());

        var remove = wrap.selectAll('button.remove')
            .data([0]);

        remove.enter().append('button')
            .attr('class', 'remove')
            .text(t('inspector.remove'))
            .append('span')
            .attr('class', 'icon remove');

        remove
            .on('click', function() {
                d3.event.preventDefault();
                buttons.classed('active', false);
                change();
            });

    }

    function change() {
        var t = {};
        if (field.key) t[field.key] = undefined;
        buttons.each(function(d) {
            var active = d3.select(this).classed('active');
            if (field.key) {
                if (active) t[field.key] = d;
            } else {
                t[d] = active ? 'yes' : undefined;
            }
        });
        event.change(t);
    }

    radio.tags = function(tags) {
        buttons.classed('active', function(d) {
            if (field.key) {
                return tags[field.key] === d;
            } else {
                return tags[d] && tags[d] !== 'no';
            }
        });
    };

    radio.focus = function() {
        buttons.node().focus();
    };

    return d3.rebind(radio, event, 'on');
};
<|endoftext|>


<commit_before>iD.ui.preset.radio = function(field) {

    var event = d3.dispatch('change'),
        buttons;

    function radio(selection) {
        selection.classed('preset-radio', true);

        var wrap = selection.selectAll('.preset-input-wrap')
            .data([0]);

        var buttonWrap = wrap.enter().append('div')
            .attr('class', 'preset-input-wrap toggle-list');

        buttons = wrap.selectAll('button')
            .data(field.options || field.keys);

        buttons.enter().append('button')
                .text(function(d) { return field.t('options.' + d, { 'default': d }); });

        buttons
            .on('click', function(d) {
                d3.event.preventDefault();
                buttons.classed('active', function(e) { return d === e; });
                change();
            });

        buttonWrap.append('span')
            .attr('class','placeholder')
            .text(field.placeholder());

        var remove = wrap.selectAll('button.remove')
            .data([0]);

        remove.enter().append('button')
            .attr('class', 'remove')
            .text(t('inspector.remove'))
            .append('span')
            .attr('class', 'icon remove');

        remove
            .on('click', function() {
                d3.event.preventDefault();
                buttons.classed('active', false);
                change();
            });

    }

    function change() {
        var t = {};
        if (field.key) t[field.key] = undefined;
        buttons.each(function(d) {
            var active = d3.select(this).classed('active');
            if (field.key) {
                if (active) t[field.key] = d;
            } else {
                t[d] = active ? 'yes' : undefined;
            }
        });
        event.change(t);
    }

    radio.tags = function(tags) {
        buttons.classed('active', function(d) {
            if (field.key) {
                return tags[field.key] === d;
            } else {
                return tags[d] && tags[d] !== 'no';
            }
        });
    };

    radio.focus = function() {
        buttons.node().focus();
    };

    return d3.rebind(radio, event, 'on');
};
<commit_msg>fix whitespace.<commit_after>iD.ui.preset.radio = function(field) {

    var event = d3.dispatch('change'),
        buttons;

    function radio(selection) {
        selection.classed('preset-radio', true);

        var wrap = selection.selectAll('.preset-input-wrap')
            .data([0]);

        var buttonWrap = wrap.enter().append('div')
            .attr('class', 'preset-input-wrap toggle-list');

        buttons = wrap.selectAll('button')
            .data(field.options || field.keys);

        buttons.enter().append('button')
            .text(function(d) { return field.t('options.' + d, { 'default': d }); });

        buttons
            .on('click', function(d) {
                d3.event.preventDefault();
                buttons.classed('active', function(e) { return d === e; });
                change();
            });

        buttonWrap.append('span')
            .attr('class','placeholder')
            .text(field.placeholder());

        var remove = wrap.selectAll('button.remove')
            .data([0]);

        remove.enter().append('button')
            .attr('class', 'remove')
            .text(t('inspector.remove'))
            .append('span')
            .attr('class', 'icon remove');

        remove
            .on('click', function() {
                d3.event.preventDefault();
                buttons.classed('active', false);
                change();
            });

    }

    function change() {
        var t = {};
        if (field.key) t[field.key] = undefined;
        buttons.each(function(d) {
            var active = d3.select(this).classed('active');
            if (field.key) {
                if (active) t[field.key] = d;
            } else {
                t[d] = active ? 'yes' : undefined;
            }
        });
        event.change(t);
    }

    radio.tags = function(tags) {
        buttons.classed('active', function(d) {
            if (field.key) {
                return tags[field.key] === d;
            } else {
                return tags[d] && tags[d] !== 'no';
            }
        });
    };

    radio.focus = function() {
        buttons.node().focus();
    };

    return d3.rebind(radio, event, 'on');
};
<|endoftext|>


<commit_before>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Global initialization of the library.
//>>label: Init
//>>group: Core

define( [ "jquery", "./jquery.mobile.core", "./jquery.mobile.support", "./jquery.mobile.navigation",
	"./jquery.mobile.navigation.pushstate", "../external/requirejs/depend!./jquery.hashchange[jquery]" ], function( $ ) {
//>>excludeEnd("jqmBuildExclude");
( function( $, window, undefined ) {
	var	$html = $( "html" ),
			$head = $( "head" ),
			$window = $( window );

 	// trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
	$( window.document ).trigger( "mobileinit" );

	// support conditions
	// if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
	// otherwise, proceed with the enhancements
	if ( !$.mobile.gradeA() ) {
		return;
	}

	// override ajaxEnabled on platforms that have known conflicts with hash history updates
	// or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)
	if ( $.mobile.ajaxBlacklist ) {
		$.mobile.ajaxEnabled = false;
	}

	// Add mobile, initial load "rendering" classes to docEl
	$html.addClass( "ui-mobile ui-mobile-rendering" );

	// This is a fallback. If anything goes wrong (JS errors, etc), or events don't fire,
	// this ensures the rendering class is removed after 5 seconds, so content is visible and accessible
	setTimeout( hideRenderingClass, 5000 );

	//remove initial build class (only present on first pageshow)
	function hideRenderingClass(){
		$html.removeClass( "ui-mobile-rendering" );
	}

	$.extend($.mobile, {
		// find and enhance the pages in the dom and transition to the first page.
		initializePage: function() {
			// find present pages
			var $pages = $( ":jqmData(role='page'), :jqmData(role='dialog')" );

			// if no pages are found, create one with body's inner html
			if ( !$pages.length ) {
				$pages = $( "body" ).wrapInner( "

" ).children( 0 );
			}

			// add dialogs, set data-url attrs
			$pages.each(function() {
				var $this = $(this);

				// unless the data url is already set set it to the pathname
				if ( !$this.jqmData("url") ) {
					$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || location.pathname + location.search );
				}
			});

			// define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
			$.mobile.firstPage = $pages.first();

			// define page container
			$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );

			// alert listeners that the pagecontainer has been determined for binding
			// to events triggered on it
			$window.trigger( "pagecontainercreate" );

			// cue page loading message
			$.mobile.showPageLoadingMsg();

			//remove initial build class (only present on first pageshow)
			hideRenderingClass();

			// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
			if ( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ) {
				$.mobile.changePage( $.mobile.firstPage, { transition: "none", reverse: true, changeHash: false, fromHashChange: true } );
			}
			// otherwise, trigger a hashchange to load a deeplink
			else {
				$window.trigger( "hashchange", [ true ] );
			}
		}
	});

	// initialize events now, after mobileinit has occurred
	$.mobile._registerInternalEvents();

	// check which scrollTop value should be used by scrolling to 1 immediately at domready
	// then check what the scroll top is. Android will report 0... others 1
	// note that this initial scroll won't hide the address bar. It's just for the check.
	$(function() {
		window.scrollTo( 0, 1 );

		// if defaultHomeScroll hasn't been set yet, see if scrollTop is 1
		// it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)
		// so if it's 1, use 0 from now on
		$.mobile.defaultHomeScroll = ( !$.support.scrollTop || $(window).scrollTop() === 1 ) ? 0 : 1;

		// TODO: Implement a proper registration mechanism with dependency handling in order to not have exceptions like the one below
		//auto self-init widgets for those widgets that have a soft dependency on others
		if ( $.fn.controlgroup ) {
			$( document ).bind( "pagecreate create", function( e ){
				$( ":jqmData(role='controlgroup')", e.target )
					.jqmEnhanceable()
					.controlgroup({ excludeInvisible: false });
			});
		}

		//dom-ready inits
		if( $.mobile.autoInitializePage ){
			$.mobile.initializePage();
		}

		// window load event
		// hide iOS browser chrome on load
		$window.load( $.mobile.silentScroll );
	});
}( jQuery, this ));
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<commit_msg>[init] Needs to depend on loader, because it calls $.mobile.showPageLoadingMsg()<commit_after>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Global initialization of the library.
//>>label: Init
//>>group: Core

define( [ "jquery", "./jquery.mobile.core", "./jquery.mobile.support", "./jquery.mobile.navigation",
	"./jquery.mobile.navigation.pushstate", "./jquery.mobile.loader", "../external/requirejs/depend!./jquery.hashchange[jquery]" ], function( $ ) {
//>>excludeEnd("jqmBuildExclude");
( function( $, window, undefined ) {
	var	$html = $( "html" ),
			$head = $( "head" ),
			$window = $( window );

 	// trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
	$( window.document ).trigger( "mobileinit" );

	// support conditions
	// if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
	// otherwise, proceed with the enhancements
	if ( !$.mobile.gradeA() ) {
		return;
	}

	// override ajaxEnabled on platforms that have known conflicts with hash history updates
	// or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)
	if ( $.mobile.ajaxBlacklist ) {
		$.mobile.ajaxEnabled = false;
	}

	// Add mobile, initial load "rendering" classes to docEl
	$html.addClass( "ui-mobile ui-mobile-rendering" );

	// This is a fallback. If anything goes wrong (JS errors, etc), or events don't fire,
	// this ensures the rendering class is removed after 5 seconds, so content is visible and accessible
	setTimeout( hideRenderingClass, 5000 );

	//remove initial build class (only present on first pageshow)
	function hideRenderingClass(){
		$html.removeClass( "ui-mobile-rendering" );
	}

	$.extend($.mobile, {
		// find and enhance the pages in the dom and transition to the first page.
		initializePage: function() {
			// find present pages
			var $pages = $( ":jqmData(role='page'), :jqmData(role='dialog')" );

			// if no pages are found, create one with body's inner html
			if ( !$pages.length ) {
				$pages = $( "body" ).wrapInner( "

" ).children( 0 );
			}

			// add dialogs, set data-url attrs
			$pages.each(function() {
				var $this = $(this);

				// unless the data url is already set set it to the pathname
				if ( !$this.jqmData("url") ) {
					$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || location.pathname + location.search );
				}
			});

			// define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
			$.mobile.firstPage = $pages.first();

			// define page container
			$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );

			// alert listeners that the pagecontainer has been determined for binding
			// to events triggered on it
			$window.trigger( "pagecontainercreate" );

			// cue page loading message
			$.mobile.showPageLoadingMsg();

			//remove initial build class (only present on first pageshow)
			hideRenderingClass();

			// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
			if ( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ) {
				$.mobile.changePage( $.mobile.firstPage, { transition: "none", reverse: true, changeHash: false, fromHashChange: true } );
			}
			// otherwise, trigger a hashchange to load a deeplink
			else {
				$window.trigger( "hashchange", [ true ] );
			}
		}
	});

	// initialize events now, after mobileinit has occurred
	$.mobile._registerInternalEvents();

	// check which scrollTop value should be used by scrolling to 1 immediately at domready
	// then check what the scroll top is. Android will report 0... others 1
	// note that this initial scroll won't hide the address bar. It's just for the check.
	$(function() {
		window.scrollTo( 0, 1 );

		// if defaultHomeScroll hasn't been set yet, see if scrollTop is 1
		// it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)
		// so if it's 1, use 0 from now on
		$.mobile.defaultHomeScroll = ( !$.support.scrollTop || $(window).scrollTop() === 1 ) ? 0 : 1;

		// TODO: Implement a proper registration mechanism with dependency handling in order to not have exceptions like the one below
		//auto self-init widgets for those widgets that have a soft dependency on others
		if ( $.fn.controlgroup ) {
			$( document ).bind( "pagecreate create", function( e ){
				$( ":jqmData(role='controlgroup')", e.target )
					.jqmEnhanceable()
					.controlgroup({ excludeInvisible: false });
			});
		}

		//dom-ready inits
		if( $.mobile.autoInitializePage ){
			$.mobile.initializePage();
		}

		// window load event
		// hide iOS browser chrome on load
		$window.load( $.mobile.silentScroll );
	});
}( jQuery, this ));
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<|endoftext|>


<commit_before>/*
* "page" plugin
*/

//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
define( [ "jquery.mobile.widget" ], function() {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

$.widget( "mobile.page", $.mobile.widget, {
	options: {
		theme: "c",
		domCache: false,
		keepNativeDefault: ":jqmData(role='none'), :jqmData(role='nojs')"
	},

	_create: function() {

		this._trigger( "beforecreate" );

		this.element
			.attr( "tabindex", "0" )
			.addClass( "ui-page ui-body-" + this.options.theme );
	},

	keepNativeSelector: function() {
		var options = this.options,
			keepNativeDefined = options.keepNative && $.trim(options.keepNative);

		if( keepNativeDefined && options.keepNative !== options.keepNativeDefault ){
			return [options.keepNative, options.keepNativeDefault].join(", ");
		}

		return options.keepNativeDefault;
	}
});
})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<commit_msg>fix bug to allow pagebeforecreate bindings to prevent enhancement<commit_after>/*
* "page" plugin
*/

//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
define( [ "jquery.mobile.widget" ], function() {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

$.widget( "mobile.page", $.mobile.widget, {
	options: {
		theme: "c",
		domCache: false,
		keepNativeDefault: ":jqmData(role='none'), :jqmData(role='nojs')"
	},

	_create: function() {

		// if false is returned by the callbacks do not create the page
		if( !this._trigger( "beforecreate" ) ){
			return false;
		}

		this.element
			.attr( "tabindex", "0" )
			.addClass( "ui-page ui-body-" + this.options.theme );
	},

	keepNativeSelector: function() {
		var options = this.options,
			keepNativeDefined = options.keepNative && $.trim(options.keepNative);

		if( keepNativeDefined && options.keepNative !== options.keepNativeDefault ){
			return [options.keepNative, options.keepNativeDefault].join(", ");
		}

		return options.keepNativeDefault;
	}
});
})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<|endoftext|>


<commit_before>$(document).ready(function() {
    //Initialize a loader
    if (loader == undefined) {
        var loader = '

';
    }
    $('body').prepend(loader);

    /**
     * The clicked link or button is tagged with data-trigger=true. When a form is submitted,
     * we find the tagged element in case it has some data to submit.
     */
    $(document).on('click', 'form[data-toggle="ajax"] *[type="submit"]', function (event) {
        $(this).parents('form[data-toggle="ajax"]').first().children('*[type="submit"]').each(function () {
            $(this).attr('data-trigger', false);
        });
        $(this).attr('data-trigger', true);
    });

    $(document).trigger('ajax_button_listener_initialized');
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});

/**
 * Keep scroll position after replacing content
 */
$(document).ajaxStart(function() {
    scrollTop = $(document).scrollTop();
});
$(document).ajaxSuccess(function() {
    $(document).scrollTop(scrollTop);
});

$(document).ajaxComplete(function() {
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});
    $(document).on('submit', 'form[data-toggle="ajax"]', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        $('#canvasloader-container--overlay').fadeIn();
        event.preventDefault();
        $(this).trigger('ajax.form.initialize');
        //Guess what is the target to update
        if ($(this).attr('data-target')) {
            var update = $(this).attr('data-target');
        } else if ($(this).data('update')) {
            console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
            var update = $(this).data('update');
        }
        var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
        var form = $(this);
        var effect = guessEffect(this, "#" + update);
        ajaxFormSubmit(form, $(form).attr('action'), update, updateStrategy, effect);

        return false;
    }).on('click', 'a[data-toggle="ajax"]', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        $('#canvasloader-container--overlay').fadeIn();
        event.preventDefault();

        //is the link linked ot a form
        var formSelector = $(this).data('form');

        $(this).trigger('ajax.link.initialize');
        //Guess what is the target to update
        if ($(this).attr('data-target')) {
            var update = $(this).attr('data-target');
        } else if ($(this).data('update')) {
            console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
            var update = $(this).data('update');
        }
        var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
        var link = $(this).attr('href');
        var effect = guessEffect(this, "#" + update);

        //if there is a form we submit this one with the href of the link
        if (formSelector === undefined) {
            ajaxLink(link, update, updateStrategy);
        } else {
            var form = $(formSelector);
            ajaxFormSubmit(form, link, update, updateStrategy, effect);
        }

        return false;
    });

function ajaxFormSubmit(form, action, update, updateStrategy, effect) {
    $(form).trigger('ajax.ajaxFormSubmit.before');
    var button = $('[type="submit"][data-trigger=true]');
    //grab all form data
    var formData = $(form).serializeArray();
    var formCache = $(form).attr('data-cache') != 'undefined' ? true : false;
    if (button.length) {
        formData.push({ name: button.attr('name'), value: button.attr('value') });
    }
    formData = $.param(formData);
    var contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
    if ($(form).attr('enctype') == 'multipart/form-data') {
        var formData = new FormData($(form)[0]);
        formData.append(button.attr('name'), button.val());
        var contentType = false;
    }

    $.ajax({
        url         : action,
        context     : document.body,
        data        : formData,
        type        : $(form).attr('method'),
        contentType : contentType,
        processData : false,
        async       : true,
        cache       : formCache,
        success     : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        }
    });

    $(form).trigger('ajax.ajaxFormSubmit.after');
}

function ajaxLink(link,update, updateStrategy, effect) {
    $.ajax({
        url     : link,
        context : document.body,
        type    : "GET",
        success : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        },
        error: function(jsonResponse) {
            if (typeof toastr === 'undefined') {
                alert("Il semble s'être produit une erreur");
            } else {
                toastr.options = {
                  "positionClass": "toast-bottom-left",
                }
                toastr.error("Il semble s'être produit une erreur");
            }
            $('#canvasloader-container').fadeOut();
            $('#canvasloader-container--overlay').fadeOut();
        }
    });
}

function ajaxify(jsonResponse, update, updateStrategy, effect) {
    $(document).trigger('ajax.success.before', jsonResponse);

    if (typeof jsonResponse === 'object') {
        handleJson(jsonResponse, update, updateStrategy);
    } else {
        if (effect != undefined && effect != null){
            $("#" + update).hide();
        }
        //By default, the updateStrategy is html (a simple replace) but you can set your own function
        //for example, append, after etc or even a custom one.
        eval('$("#" + update).' + updateStrategy + '(jsonResponse)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).' + effect + '()');
        }
    }

    $('#canvasloader-container').fadeOut();
    $('#canvasloader-container--overlay').fadeOut();
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });

    $(document).trigger('ajax.success.after', jsonResponse);
}

function handleJson(json, update, updateStrategy, effect) {

    if (json.hasOwnProperty("update")) {
        update = json.update;
    }

    if (effect != undefined && effect != null){
        $("#" + update).hide();
    }

    // check if an ajax callback is given in the response, execute it
    if (json.hasOwnProperty("ajax-callback")) {
        $.post(json.callback,
        {
            params : json.data
        },
        function(data){
            eval('$("#" + update).' + updateStrategy + '(data)');
        });
    }
    // a callback is javascript code
    if (json.hasOwnProperty("callback")) {
        eval(json.callback);
    }
    // html is the html part to be inserted in the "update"
    if (json.hasOwnProperty("html")) {
        eval('$("#" + update).' + updateStrategy + '(json.html)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).'+effect+'()');
        }
    }
    // redirect is an url
    if (json.hasOwnProperty("redirect")) {
        window.location = json.redirect;
        location.reload();
    }
}

function guessEffect(link, targetId) {
    var effect = "show";
    if ($(targetId).html() != undefined) {
        if ($(targetId).html() == "") {
            effect = "slideDown";
            if ($(link).attr('data-new-effect') != undefined && $(link).attr('data-new-effect') != "") {
                effect = $(link).attr('data-new-effect');
            } else if ($(targetId).attr('data-new-effect') != undefined && $(targetId).attr('data-new-effect') != "") {
                effect = $(targetId).attr('data-new-effect');
            }
        } else {
            effect = "fadeIn";
            if ($(link).attr('data-update-effect') != undefined && $(link).attr('data-update-effect') != "") {
                effect = $(link).attr('data-update-effect');
            } else if ($(targetId).attr('data-update-effect') != undefined && $(targetId).attr('data-update-effect') != "") {
                effect = $(targetId).attr('data-update-effect');
            }
        }
    } else if ($(link).data('no-effect')) {
        effect = null;
    }

    return effect;
}
<commit_msg>change the way to write on events ajaxStart and ajaxSuccess to be sure all browsers catch them<commit_after>$(document).ready(function() {
    //Initialize a loader
    if (loader == undefined) {
        var loader = '

';
    }
    $('body').prepend(loader);

    /**
     * The clicked link or button is tagged with data-trigger=true. When a form is submitted,
     * we find the tagged element in case it has some data to submit.
     */
    $(document).on('click', 'form[data-toggle="ajax"] *[type="submit"]', function (event) {
        $(this).parents('form[data-toggle="ajax"]').first().children('*[type="submit"]').each(function () {
            $(this).attr('data-trigger', false);
        });
        $(this).attr('data-trigger', true);
    });

    $(document).trigger('ajax_button_listener_initialized');
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});

/**
 * Keep scroll position after replacing content
 */
$(document).on({
    ajaxStart: function() {
        scrollTop = $(document).scrollTop();
    },
    ajaxSuccess: function() {
        $(document).scrollTop(scrollTop);
    }
});

$(document).ajaxComplete(function() {
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});
    $(document).on('submit', 'form[data-toggle="ajax"]', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        $('#canvasloader-container--overlay').fadeIn();
        event.preventDefault();
        $(this).trigger('ajax.form.initialize');
        //Guess what is the target to update
        if ($(this).attr('data-target')) {
            var update = $(this).attr('data-target');
        } else if ($(this).data('update')) {
            console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
            var update = $(this).data('update');
        }
        var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
        var form = $(this);
        var effect = guessEffect(this, "#" + update);
        ajaxFormSubmit(form, $(form).attr('action'), update, updateStrategy, effect);

        return false;
    }).on('click', 'a[data-toggle="ajax"]', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        $('#canvasloader-container--overlay').fadeIn();
        event.preventDefault();

        //is the link linked ot a form
        var formSelector = $(this).data('form');

        $(this).trigger('ajax.link.initialize');
        //Guess what is the target to update
        if ($(this).attr('data-target')) {
            var update = $(this).attr('data-target');
        } else if ($(this).data('update')) {
            console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
            var update = $(this).data('update');
        }
        var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
        var link = $(this).attr('href');
        var effect = guessEffect(this, "#" + update);

        //if there is a form we submit this one with the href of the link
        if (formSelector === undefined) {
            ajaxLink(link, update, updateStrategy);
        } else {
            var form = $(formSelector);
            ajaxFormSubmit(form, link, update, updateStrategy, effect);
        }

        return false;
    });

function ajaxFormSubmit(form, action, update, updateStrategy, effect) {
    $(form).trigger('ajax.ajaxFormSubmit.before');
    var button = $('[type="submit"][data-trigger=true]');
    //grab all form data
    var formData = $(form).serializeArray();
    var formCache = $(form).attr('data-cache') != 'undefined' ? true : false;
    if (button.length) {
        formData.push({ name: button.attr('name'), value: button.attr('value') });
    }
    formData = $.param(formData);
    var contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
    if ($(form).attr('enctype') == 'multipart/form-data') {
        var formData = new FormData($(form)[0]);
        formData.append(button.attr('name'), button.val());
        var contentType = false;
    }

    $.ajax({
        url         : action,
        context     : document.body,
        data        : formData,
        type        : $(form).attr('method'),
        contentType : contentType,
        processData : false,
        async       : true,
        cache       : formCache,
        success     : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        }
    });

    $(form).trigger('ajax.ajaxFormSubmit.after');
}

function ajaxLink(link,update, updateStrategy, effect) {
    $.ajax({
        url     : link,
        context : document.body,
        type    : "GET",
        success : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        },
        error: function(jsonResponse) {
            if (typeof toastr === 'undefined') {
                alert("Il semble s'être produit une erreur");
            } else {
                toastr.options = {
                  "positionClass": "toast-bottom-left",
                }
                toastr.error("Il semble s'être produit une erreur");
            }
            $('#canvasloader-container').fadeOut();
            $('#canvasloader-container--overlay').fadeOut();
        }
    });
}

function ajaxify(jsonResponse, update, updateStrategy, effect) {
    $(document).trigger('ajax.success.before', jsonResponse);

    if (typeof jsonResponse === 'object') {
        handleJson(jsonResponse, update, updateStrategy);
    } else {
        if (effect != undefined && effect != null){
            $("#" + update).hide();
        }
        //By default, the updateStrategy is html (a simple replace) but you can set your own function
        //for example, append, after etc or even a custom one.
        eval('$("#" + update).' + updateStrategy + '(jsonResponse)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).' + effect + '()');
        }
    }

    $('#canvasloader-container').fadeOut();
    $('#canvasloader-container--overlay').fadeOut();
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });

    $(document).trigger('ajax.success.after', jsonResponse);
}

function handleJson(json, update, updateStrategy, effect) {

    if (json.hasOwnProperty("update")) {
        update = json.update;
    }

    if (effect != undefined && effect != null){
        $("#" + update).hide();
    }

    // check if an ajax callback is given in the response, execute it
    if (json.hasOwnProperty("ajax-callback")) {
        $.post(json.callback,
        {
            params : json.data
        },
        function(data){
            eval('$("#" + update).' + updateStrategy + '(data)');
        });
    }
    // a callback is javascript code
    if (json.hasOwnProperty("callback")) {
        eval(json.callback);
    }
    // html is the html part to be inserted in the "update"
    if (json.hasOwnProperty("html")) {
        eval('$("#" + update).' + updateStrategy + '(json.html)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).'+effect+'()');
        }
    }
    // redirect is an url
    if (json.hasOwnProperty("redirect")) {
        window.location = json.redirect;
        location.reload();
    }
}

function guessEffect(link, targetId) {
    var effect = "show";
    if ($(targetId).html() != undefined) {
        if ($(targetId).html() == "") {
            effect = "slideDown";
            if ($(link).attr('data-new-effect') != undefined && $(link).attr('data-new-effect') != "") {
                effect = $(link).attr('data-new-effect');
            } else if ($(targetId).attr('data-new-effect') != undefined && $(targetId).attr('data-new-effect') != "") {
                effect = $(targetId).attr('data-new-effect');
            }
        } else {
            effect = "fadeIn";
            if ($(link).attr('data-update-effect') != undefined && $(link).attr('data-update-effect') != "") {
                effect = $(link).attr('data-update-effect');
            } else if ($(targetId).attr('data-update-effect') != undefined && $(targetId).attr('data-update-effect') != "") {
                effect = $(targetId).attr('data-update-effect');
            }
        }
    } else if ($(link).data('no-effect')) {
        effect = null;
    }

    return effect;
}
<|endoftext|>


<commit_before>"use strict";

var $ = require('jquery'),
    _ = require('lodash'),
    L = require('leaflet'),
    U = require('treemap/utility'),
    addMapFeature = require('treemap/addMapFeature');

require('leafletEditablePolyline');

var activateMode = _.identity,
    deactivateMode = _.identity,
    STEP_CHOOSE_TYPE = 0,
    STEP_LOCATE = 1,
    STEP_OUTLINE_AREA = 2,
    STEP_DETAILS = 3,
    STEP_FINAL = 4;

function init(options) {
    options.onSaveBefore = onSaveBefore;
    var manager = addMapFeature.init(options),
        config = options.config,
        $sidebar = $(options.sidebar),
        $footerStepCounts = U.$find('.footer-total-steps', $sidebar),
        $resourceType = U.$find('input[name="addResourceType"]', $sidebar),
        $form = U.$find(options.formSelector, $sidebar),
        $summaryHead = U.$find('.summaryHead', $sidebar),
        $summarySubhead = U.$find('.summarySubhead', $sidebar),
        mapManager = options.mapManager,
        plotMarker = options.plotMarker,
        areaFieldIdentifier,
        areaPolygon;

    $resourceType.on('change', onResourceTypeChosen);

    manager.addFeatureStream.onValue(initSteps);
    manager.deactivateStream.onValue(initSteps);

    activateMode = function() {
        manager.activate();
        manager.stepControls.enableNext(STEP_CHOOSE_TYPE, false);
        plotMarker.useTreeIcon(false);
        areaPolygon = null;
    };

    deactivateMode = function () {
        removeAreaPolygon();
        manager.deactivate();
    }

    function onResourceTypeChosen() {
        var $option = $resourceType.filter(':checked'),
            type = $option.val(),
            typeName = $option.next().text().trim(),
            areaFieldName = $option.data('area-field-name'),
            addFeatureUrl = config.instance.url + 'features/' + type + '/';
        if (type) {
            manager.setAddFeatureUrl(addFeatureUrl);
            manager.stepControls.enableNext(STEP_CHOOSE_TYPE, true);
            manager.stepControls.enableNext(STEP_OUTLINE_AREA, true);
            manager.stepControls.enableNext(STEP_DETAILS, false);
            $summaryHead.text(typeName);
            $summarySubhead.text("Watershed Solution");

            var hasAreaStep = !!areaFieldName;
            activateAreaStep(hasAreaStep);
            if (hasAreaStep) {
                var objectName = type.slice(0, 1).toLowerCase() + type.slice(1);
                areaFieldIdentifier = objectName + '.' + areaFieldName;
            } else {
                areaFieldIdentifier = null;
            }

            $.ajax({
                url: config.instance.url + "features/" + type + '/',
                type: 'GET',
                dataType: 'html',
                success: onResourceFormLoaded
            });
        }
    }

    function activateAreaStep(hasAreaStep) {
        var stepCount = manager.stepControls.maxStepNumber + 1;
        if (!hasAreaStep) {
            stepCount--;
        }
        $footerStepCounts.each(function () {
            $(this).text(stepCount);
        });
        manager.stepControls.activateStep(STEP_OUTLINE_AREA, hasAreaStep);
    }

    function onResourceFormLoaded(html) {
        $form.html(html);
        U.$find('[data-class="edit"]', $form).show();
        U.$find('[data-class="display"]', $form).hide();
        hideSubquestions();

        U.$find('input[type="radio"]', $form).on('change', onQuestionAnswered);
        U.$find('input[type="text"]', $form).on('keyup', enableFinalStep);
        U.$find('select', $form).on('change', enableFinalStep);
    }

    function initSteps() {
        $resourceType.prop('checked', false);
        manager.stepControls.enableNext(STEP_CHOOSE_TYPE, false);
        hideSubquestions();
    }

    function hideSubquestions() {
        U.$find('.resource-subquestion', $form).hide();
    }

    manager.stepControls.stepChangeCompleteStream.onValue(function (stepNumber) {
        if (stepNumber === STEP_LOCATE) {
            if (plotMarker.wasMoved()) {
                plotMarker.enableMoving({needsFirstMove: false});
            } else {
                // Let user start creating a feature (by clicking the map)
                plotMarker.enablePlacing();
            }
        } else {
            plotMarker.disableMoving();
        }

        if (stepNumber === STEP_OUTLINE_AREA) {
            enableAreaPolygon();
        } else {
            disableAreaPolygon();
        }
    });

    function initAreaPolygon() {
        var p1 = plotMarker.getLatLng(),
            p2 = U.offsetLatLngByMeters(p1, -20, -20),
            points = [
                [p1.lat, p1.lng],
                [p2.lat, p1.lng],
                [p2.lat, p2.lng],
                [p1.lat, p2.lng]
            ],
            pointIcon = L.icon({
                iconUrl: config.staticUrl + 'img/polygon-point.png',
                iconSize: [11, 11],
                iconAnchor: [6, 6]
            }),
            newPointIcon = L.icon({
                iconUrl: config.staticUrl + 'img/polygon-point-new.png',
                iconSize: [11, 11],
                iconAnchor: [6, 6]
            });
        areaPolygon = L.Polyline.PolylineEditor(points, {
            pointIcon: pointIcon,
            newPointIcon: newPointIcon
        });
        areaPolygon.addTo(mapManager.map);
    }

    function removeAreaPolygon() {
        if (areaPolygon) {
            mapManager.map.removeLayer(areaPolygon);
        }
    }

    function enableAreaPolygon() {
        if (!areaPolygon) {
            initAreaPolygon();
        }
        mapManager.map.setEditablePolylinesEnabled(true);
    }

    function disableAreaPolygon() {
        if (areaPolygon) {
            mapManager.map.setEditablePolylinesEnabled(false);
        }
    }

    function onQuestionAnswered(e) {
        var $radioButton = $(e.target),
            onOrOff = $radioButton.val() === 'True',
            $container = $radioButton.closest('.resource-question, .resource-subquestion'),
            $subquestions = $container.children('.resource-subquestion');
        $subquestions.toggle(onOrOff);
        enableFinalStep();
    }

    function enableFinalStep() {
        var $questions = $form.find('.resource-question, .resource-subquestion:visible'),
            $fieldGroups = $questions.children('.field-edit'),
            values = $fieldGroups
                .find('input[type!=radio],select')
                .serializeArray(),
            answered = _.map(values, function (value) {
                return value.value.trim().length > 0;
            }),
            $fieldGroupsRadio = $fieldGroups.filter(':has(input[type=radio])'),
            $checked = $fieldGroupsRadio.find(':checked'),
            allAnswered = _.every(answered) && $fieldGroupsRadio.length === $checked.length;

        manager.stepControls.enableNext(STEP_DETAILS, allAnswered);
    }

    function onSaveBefore(formData) {
        if (areaFieldIdentifier) {
            var points = _.map(areaPolygon.getPoints(), function (point) {
                var latLng = point.getLatLng();
                return [latLng.lng, latLng.lat];
            });
            points.push(points[0]);
            formData[areaFieldIdentifier] = {polygon: points};
        }
    }
}

function activate() {
    activateMode();
}

function deactivate() {
    deactivateMode();
}

module.exports = {
    name: 'addResource',
    init: init,
    activate: activate,
    deactivate: deactivate,
    lockOnActivate: true
};
<commit_msg>Better cleanup of area polygon.<commit_after>"use strict";

var $ = require('jquery'),
    _ = require('lodash'),
    L = require('leaflet'),
    U = require('treemap/utility'),
    addMapFeature = require('treemap/addMapFeature');

require('leafletEditablePolyline');

var activateMode = _.identity,
    deactivateMode = _.identity,
    STEP_CHOOSE_TYPE = 0,
    STEP_LOCATE = 1,
    STEP_OUTLINE_AREA = 2,
    STEP_DETAILS = 3,
    STEP_FINAL = 4;

function init(options) {
    options.onSaveBefore = onSaveBefore;
    var manager = addMapFeature.init(options),
        config = options.config,
        $sidebar = $(options.sidebar),
        $footerStepCounts = U.$find('.footer-total-steps', $sidebar),
        $resourceType = U.$find('input[name="addResourceType"]', $sidebar),
        $form = U.$find(options.formSelector, $sidebar),
        $summaryHead = U.$find('.summaryHead', $sidebar),
        $summarySubhead = U.$find('.summarySubhead', $sidebar),
        mapManager = options.mapManager,
        plotMarker = options.plotMarker,
        areaFieldIdentifier,
        areaPolygon;

    $resourceType.on('change', onResourceTypeChosen);

    manager.addFeatureStream.onValue(initSteps);
    manager.deactivateStream.onValue(initSteps);

    activateMode = function() {
        manager.activate();
        plotMarker.useTreeIcon(false);
        initSteps();
    };

    deactivateMode = function () {
        removeAreaPolygon();
        manager.deactivate();
    }

    function onResourceTypeChosen() {
        var $option = $resourceType.filter(':checked'),
            type = $option.val(),
            typeName = $option.next().text().trim(),
            areaFieldName = $option.data('area-field-name'),
            addFeatureUrl = config.instance.url + 'features/' + type + '/';
        if (type) {
            manager.setAddFeatureUrl(addFeatureUrl);
            manager.stepControls.enableNext(STEP_CHOOSE_TYPE, true);
            manager.stepControls.enableNext(STEP_OUTLINE_AREA, true);
            manager.stepControls.enableNext(STEP_DETAILS, false);
            $summaryHead.text(typeName);
            $summarySubhead.text("Watershed Solution");

            var hasAreaStep = !!areaFieldName;
            activateAreaStep(hasAreaStep);
            if (hasAreaStep) {
                var objectName = type.slice(0, 1).toLowerCase() + type.slice(1);
                areaFieldIdentifier = objectName + '.' + areaFieldName;
            } else {
                areaFieldIdentifier = null;
            }
            removeAreaPolygon(); // in case user backed up and changed type

            $.ajax({
                url: config.instance.url + "features/" + type + '/',
                type: 'GET',
                dataType: 'html',
                success: onResourceFormLoaded
            });
        }
    }

    function activateAreaStep(hasAreaStep) {
        var stepCount = manager.stepControls.maxStepNumber + 1;
        if (!hasAreaStep) {
            stepCount--;
        }
        $footerStepCounts.each(function () {
            $(this).text(stepCount);
        });
        manager.stepControls.activateStep(STEP_OUTLINE_AREA, hasAreaStep);
    }

    function onResourceFormLoaded(html) {
        $form.html(html);
        U.$find('[data-class="edit"]', $form).show();
        U.$find('[data-class="display"]', $form).hide();
        hideSubquestions();

        U.$find('input[type="radio"]', $form).on('change', onQuestionAnswered);
        U.$find('input[type="text"]', $form).on('keyup', enableFinalStep);
        U.$find('select', $form).on('change', enableFinalStep);
    }

    function initSteps() {
        $resourceType.prop('checked', false);
        manager.stepControls.enableNext(STEP_CHOOSE_TYPE, false);
        removeAreaPolygon();
        hideSubquestions();
    }

    function hideSubquestions() {
        U.$find('.resource-subquestion', $form).hide();
    }

    manager.stepControls.stepChangeCompleteStream.onValue(function (stepNumber) {
        if (stepNumber === STEP_LOCATE) {
            if (plotMarker.wasMoved()) {
                plotMarker.enableMoving({needsFirstMove: false});
            } else {
                // Let user start creating a feature (by clicking the map)
                plotMarker.enablePlacing();
            }
        } else {
            plotMarker.disableMoving();
        }

        if (stepNumber === STEP_OUTLINE_AREA) {
            enableAreaPolygon();
        } else {
            disableAreaPolygon();
        }
    });

    function initAreaPolygon() {
        var p1 = plotMarker.getLatLng(),
            p2 = U.offsetLatLngByMeters(p1, -20, -20),
            points = [
                [p1.lat, p1.lng],
                [p2.lat, p1.lng],
                [p2.lat, p2.lng],
                [p1.lat, p2.lng]
            ],
            pointIcon = L.icon({
                iconUrl: config.staticUrl + 'img/polygon-point.png',
                iconSize: [11, 11],
                iconAnchor: [6, 6]
            }),
            newPointIcon = L.icon({
                iconUrl: config.staticUrl + 'img/polygon-point-new.png',
                iconSize: [11, 11],
                iconAnchor: [6, 6]
            });
        areaPolygon = L.Polyline.PolylineEditor(points, {
            pointIcon: pointIcon,
            newPointIcon: newPointIcon
        });
        areaPolygon.addTo(mapManager.map);
    }

    function removeAreaPolygon() {
        if (areaPolygon) {
            disableAreaPolygon();
            mapManager.map.removeLayer(areaPolygon);
            areaPolygon = null;
        }
    }

    function enableAreaPolygon() {
        if (!areaPolygon) {
            initAreaPolygon();
        }
        mapManager.map.setEditablePolylinesEnabled(true);
    }

    function disableAreaPolygon() {
        if (areaPolygon) {
            mapManager.map.setEditablePolylinesEnabled(false);
        }
    }

    function onQuestionAnswered(e) {
        var $radioButton = $(e.target),
            onOrOff = $radioButton.val() === 'True',
            $container = $radioButton.closest('.resource-question, .resource-subquestion'),
            $subquestions = $container.children('.resource-subquestion');
        $subquestions.toggle(onOrOff);
        enableFinalStep();
    }

    function enableFinalStep() {
        var $questions = $form.find('.resource-question, .resource-subquestion:visible'),
            $fieldGroups = $questions.children('.field-edit'),
            values = $fieldGroups
                .find('input[type!=radio],select')
                .serializeArray(),
            answered = _.map(values, function (value) {
                return value.value.trim().length > 0;
            }),
            $fieldGroupsRadio = $fieldGroups.filter(':has(input[type=radio])'),
            $checked = $fieldGroupsRadio.find(':checked'),
            allAnswered = _.every(answered) && $fieldGroupsRadio.length === $checked.length;

        manager.stepControls.enableNext(STEP_DETAILS, allAnswered);
    }

    function onSaveBefore(formData) {
        if (areaFieldIdentifier) {
            var points = _.map(areaPolygon.getPoints(), function (point) {
                var latLng = point.getLatLng();
                return [latLng.lng, latLng.lat];
            });
            points.push(points[0]);
            formData[areaFieldIdentifier] = {polygon: points};
        }
    }
}

function activate() {
    activateMode();
}

function deactivate() {
    deactivateMode();
}

module.exports = {
    name: 'addResource',
    init: init,
    activate: activate,
    deactivate: deactivate,
    lockOnActivate: true
};
<|endoftext|>


<commit_before>(function($) {
  $(function () {
    // Only act on the new study admin page, just in case
    if ($('body.admin_studies.new').length > 0) {
      var $referenceNumberField = $('#study_reference_number');
      if ($referenceNumberField.val() === '') {
        var prefix = 'OCA' + window.ReMIT.currentReferenceNumberYear + '-';
        var nextNumber = window.ReMIT.currentReferenceNumber + 1;
        $referenceNumberField.val(prefix + nextNumber);
      }
    }
  });
})(window.jQuery);<commit_msg>Prefix single digit reference numbers with a zero.<commit_after>(function($) {
  $(function () {
    // Only act on the new study admin page, just in case
    if ($('body.admin_studies.new').length > 0) {
      var $referenceNumberField = $('#study_reference_number');
      if ($referenceNumberField.val() === '') {
        var prefix = 'OCA' + window.ReMIT.currentReferenceNumberYear + '-';
        var nextNumber = window.ReMIT.currentReferenceNumber + 1;
        if(nextNumber < 10) {
          nextNumber = '0' + nextNumber.toString();
        }
        $referenceNumberField.val(prefix + nextNumber);
      }
    }
  });
})(window.jQuery);<|endoftext|>