<commit_before>import React, { Component } from 'react'
import { Redirect } from 'react-router-dom'
import PropTypes from 'prop-types'
import { Meteor } from 'meteor/meteor'
import { EventsSchema } from '/imports/both/collections/events'
import { Modal, ModalHeader, ModalBody, ModalFooter, Button, Alert } from 'reactstrap'
import FormWizard from './FormWizard'
import i18n from '/imports/both/i18n/en'
import qs from 'query-string'
import cloneDeep from 'clone-deep'
import './styles.scss'
import { dcs } from "/imports/client/utils/dcs-master"

const { NewEventModal: i18n_ } = i18n // Strings from i18n

class NewEventModal extends Component {
  constructor () {
    super()
    this.state = {
      currentStep: 0,
      editMode: false,
      form: null,
      googleLoaded: false,
      hasErrors: false,
      isRedirect: false,
      isConfirmBtn: false
    }

    if (window.google) {
      this.state.googleLoaded = true
    }
  }

  static getDerivedStateFromProps (nextProps, prevState) {
    if (window.__editData) {
      return {
        ...nextProps,
        editMode: true,
        isRedirect: false,
        isConfirmBtn: false
      }
    }
    return {
      ...nextProps,
      editMode: false,
      isRedirect: false,
      isConfirmBtn: false,
    }
  }

  componentDidMount () {
    // ensure google maps is loaded
    this.interval = setInterval(() => {
      if (window.google) {
        clearInterval(this.interval)
        this.setState({ googleLoaded: true })
      }
    }, 1000) // 1 second
  }

  componentDidUpdate(prevProps){
    if(prevProps.location.pathname !== this.props.location.pathname){
      delete window.__unfinishedNewEvent
    }
  }

  componentWillUnmount () {
    clearInterval(this.interval)
    this.interval = null
  }

  render () {
    if (this.state.isRedirect === true) {
      return <Redirect to='/map' />
    }
    const {
      currentStep,
      editMode,
      googleLoaded,
      hasErrors,
      isOpen
    } = this.state

    const hasGoogleMapsLoaded = window.google || googleLoaded

    const header = i18n_.modal_header
    const isConfirmBtn = this.state.isConfirmBtn
    const deleteBtn = editMode && currentStep + 1 <= 1 ? <Button color='danger' onClick={() => this.setState({ isConfirmBtn: true })}>Delete Page</Button> : null

    return hasGoogleMapsLoaded && (
      <Modal id='new-event-modal' isOpen={isOpen} toggle={this.toggleModal} size='lg'>
        <ModalHeader toggle={this.toggleModal}>
          {editMode ? header.replace('New', 'Edit') : header}
        </ModalHeader>
        <ModalBody>
          <FormWizard
            currentStep={currentStep}
            passFormRefToParent={this.getRef}
            editMode={editMode} />
        </ModalBody>
        <Alert color='danger' isOpen={hasErrors} toggle={this.toggleErrors} className='error-general'>
          Please check that all necessary fields (outlined in red)
           are filled out.
        </Alert>
        {isConfirmBtn ?
          <ModalFooter>
            <Button color='primary' onClick={() => this.setState({ isConfirmBtn: false })}>Cancel</Button>
            <Button color='danger' onClick={this.deletePage}>CONFIRM DELETE</Button>

          </ModalFooter>
          :
          <ModalFooter>
            {currentStep + 1 <= 1 &&
              <Button color='primary' onClick={this.moveNext}>Next</Button>
            }
            {deleteBtn}
            {currentStep === 1 &&
              <Button color='primary' onClick={this.submit} className='submit'>Submit</Button>
            }
            {currentStep > 0 &&
              <Button color='primary' onClick={this.moveBack}>Back</Button>
            }
          </ModalFooter>
        }
      </Modal>
    )
  }

  moveNext = () => {
    this.setState(prevState => ({ currentStep: prevState.currentStep + 1 }))
  };

  moveBack = () => {
    this.setState(prevState => ({ currentStep: prevState.currentStep - 1, hasErrors: false }))
  };

  submit = () => {

    this.state.form.validate({ clean: true })
      .then(() => {
        window.NProgress.set(0.4)

        let model = EventsSchema.clean(this.state.form.getModel())
        if (this.state.editMode) {
          model._id = this.state.form.getModel()._id
          this.callEditEvent(model)
        } else {
          this.callNewEvent(model)
        }
      })
      .catch(err => {
        this.setState({ hasErrors: true })

        if (Meteor.isDevelopment) { console.log(err.details, err) }
      })

      // get rid of any previously unfinished New Event
      delete window.__unfinishedNewEvent
  }

  deletePage = () => {
    let model = EventsSchema.clean(this.state.form.getModel())
    model._id = this.state.form.getModel()._id

    this.callDeleteEvent(model);
  }

  callNewEvent = model => {
    Meteor.call('Events.newEvent', model, (err, res) => {
      if (!err) {
        this.setState({ currentStep: 0 }) // return to first step
        window.__recentEvent = { ...model, _id: res }
        this.props.history.push('/thank-you')
        dcs.postCreateDcsTags({
          pageName: 'lastev',
          triggerIds: ['photos', 'videos', 'stories'],
          notificationLevel: 3
        })
      }

      window.NProgress.done()
      if (Meteor.isDevelopment) { console.log(err) }
    })
  }

  callEditEvent = (model) => {
    console.log('model', model);
    Meteor.call('Events.editEvent', model, (err, res) => {
      if (!err) {
        window.__updatedData = model // update event page.
        this.setState({ currentStep: 0 })
        this.props.history.push('/page/' + model._id)
      }

      window.NProgress.done()
      if (Meteor.isDevelopment) { console.log(err, model) }
    })
  }

  callDeleteEvent = (model) => {
    Meteor.call('Events.deleteEvent', model, (err, res) => {
      if (!err) {
        this.setState({ isRedirect: true })
      }

      if (Meteor.isDevelopment) { console.log(err, model) }
    })

  }

  toggleModal = () => {
    const { pathname, search } = this.props.location
    const queryStrings = qs.parse(search)

    delete queryStrings.edit
    delete queryStrings.new

    const url = pathname + '?' + qs.stringify(queryStrings)
    this.props.history.push(url)

    // toggleModal() closes modal, but it is not called after form submits
    // copy unfinished form to global window and check for it inside FormWizard
    window.__unfinishedNewEvent = cloneDeep(this.state.form.getModel())
  }

  toggleErrors = () => this.setState({ hasErrors: false })

  getRef = (form) => {
    this.setState({ form: form })
  }
}

NewEventModal.propTypes = {
  isOpen: PropTypes.bool.isRequired,
  location: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
}

export default NewEventModal
<commit_msg>Update index.js<commit_after>import React, { Component } from 'react'
import { Redirect } from 'react-router-dom'
import PropTypes from 'prop-types'
import { Meteor } from 'meteor/meteor'
import { EventsSchema } from '/imports/both/collections/events'
import { Modal, ModalHeader, ModalBody, ModalFooter, Button, Alert } from 'reactstrap'
import FormWizard from './FormWizard'
import i18n from '/imports/both/i18n/en'
import qs from 'query-string'
import cloneDeep from 'clone-deep'
import './styles.scss'
import { comToPlugin } from 'dcs-client'

const { NewEventModal: i18n_ } = i18n // Strings from i18n

class NewEventModal extends Component {
  constructor () {
    super()
    this.state = {
      currentStep: 0,
      editMode: false,
      form: null,
      googleLoaded: false,
      hasErrors: false,
      isRedirect: false,
      isConfirmBtn: false
    }

    if (window.google) {
      this.state.googleLoaded = true
    }
  }

  static getDerivedStateFromProps (nextProps, prevState) {
    if (window.__editData) {
      return {
        ...nextProps,
        editMode: true,
        isRedirect: false,
        isConfirmBtn: false
      }
    }
    return {
      ...nextProps,
      editMode: false,
      isRedirect: false,
      isConfirmBtn: false,
    }
  }

  componentDidMount () {
    // ensure google maps is loaded
    this.interval = setInterval(() => {
      if (window.google) {
        clearInterval(this.interval)
        this.setState({ googleLoaded: true })
      }
    }, 1000) // 1 second
  }

  componentDidUpdate(prevProps){
    if(prevProps.location.pathname !== this.props.location.pathname){
      delete window.__unfinishedNewEvent
    }
  }

  componentWillUnmount () {
    clearInterval(this.interval)
    this.interval = null
  }

  render () {
    if (this.state.isRedirect === true) {
      return <Redirect to='/map' />
    }
    const {
      currentStep,
      editMode,
      googleLoaded,
      hasErrors,
      isOpen
    } = this.state

    const hasGoogleMapsLoaded = window.google || googleLoaded

    const header = i18n_.modal_header
    const isConfirmBtn = this.state.isConfirmBtn
    const deleteBtn = editMode && currentStep + 1 <= 1 ? <Button color='danger' onClick={() => this.setState({ isConfirmBtn: true })}>Delete Page</Button> : null

    return hasGoogleMapsLoaded && (
      <Modal id='new-event-modal' isOpen={isOpen} toggle={this.toggleModal} size='lg'>
        <ModalHeader toggle={this.toggleModal}>
          {editMode ? header.replace('New', 'Edit') : header}
        </ModalHeader>
        <ModalBody>
          <FormWizard
            currentStep={currentStep}
            passFormRefToParent={this.getRef}
            editMode={editMode} />
        </ModalBody>
        <Alert color='danger' isOpen={hasErrors} toggle={this.toggleErrors} className='error-general'>
          Please check that all necessary fields (outlined in red)
           are filled out.
        </Alert>
        {isConfirmBtn ?
          <ModalFooter>
            <Button color='primary' onClick={() => this.setState({ isConfirmBtn: false })}>Cancel</Button>
            <Button color='danger' onClick={this.deletePage}>CONFIRM DELETE</Button>

          </ModalFooter>
          :
          <ModalFooter>
            {currentStep + 1 <= 1 &&
              <Button color='primary' onClick={this.moveNext}>Next</Button>
            }
            {deleteBtn}
            {currentStep === 1 &&
              <Button color='primary' onClick={this.submit} className='submit'>Submit</Button>
            }
            {currentStep > 0 &&
              <Button color='primary' onClick={this.moveBack}>Back</Button>
            }
          </ModalFooter>
        }
      </Modal>
    )
  }

  moveNext = () => {
    this.setState(prevState => ({ currentStep: prevState.currentStep + 1 }))
  };

  moveBack = () => {
    this.setState(prevState => ({ currentStep: prevState.currentStep - 1, hasErrors: false }))
  };

  submit = () => {

    this.state.form.validate({ clean: true })
      .then(() => {
        window.NProgress.set(0.4)

        let model = EventsSchema.clean(this.state.form.getModel())
        if (this.state.editMode) {
          model._id = this.state.form.getModel()._id
          this.callEditEvent(model)
        } else {
          this.callNewEvent(model)
        }
      })
      .catch(err => {
        this.setState({ hasErrors: true })

        if (Meteor.isDevelopment) { console.log(err.details, err) }
      })

      // get rid of any previously unfinished New Event
      delete window.__unfinishedNewEvent
  }

  deletePage = () => {
    let model = EventsSchema.clean(this.state.form.getModel())
    model._id = this.state.form.getModel()._id

    this.callDeleteEvent(model);
  }

  callNewEvent = model => {
    Meteor.call('Events.newEvent', model, (err, res) => {
      if (!err) {
        this.setState({ currentStep: 0 }) // return to first step
        window.__recentEvent = { ...model, _id: res }
        this.props.history.push('/thank-you')
        comToPlugin.postCreateDcsTags({
          pageName: 'lastev',
          triggerIds: ['photos', 'videos', 'stories'],
          notificationLevel: 3
        })
      }

      window.NProgress.done()
      if (Meteor.isDevelopment) { console.log(err) }
    })
  }

  callEditEvent = (model) => {
    console.log('model', model);
    Meteor.call('Events.editEvent', model, (err, res) => {
      if (!err) {
        window.__updatedData = model // update event page.
        this.setState({ currentStep: 0 })
        this.props.history.push('/page/' + model._id)
      }

      window.NProgress.done()
      if (Meteor.isDevelopment) { console.log(err, model) }
    })
  }

  callDeleteEvent = (model) => {
    Meteor.call('Events.deleteEvent', model, (err, res) => {
      if (!err) {
        this.setState({ isRedirect: true })
      }

      if (Meteor.isDevelopment) { console.log(err, model) }
    })

  }

  toggleModal = () => {
    const { pathname, search } = this.props.location
    const queryStrings = qs.parse(search)

    delete queryStrings.edit
    delete queryStrings.new

    const url = pathname + '?' + qs.stringify(queryStrings)
    this.props.history.push(url)

    // toggleModal() closes modal, but it is not called after form submits
    // copy unfinished form to global window and check for it inside FormWizard
    window.__unfinishedNewEvent = cloneDeep(this.state.form.getModel())
  }

  toggleErrors = () => this.setState({ hasErrors: false })

  getRef = (form) => {
    this.setState({ form: form })
  }
}

NewEventModal.propTypes = {
  isOpen: PropTypes.bool.isRequired,
  location: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
}

export default NewEventModal
<|endoftext|>


<commit_before>function getError(url, option, xhr) {
    var msg;
    if (xhr.response) {
        msg = xhr.status + ' ' + (xhr.response.error || xhr.response);
    } else if (xhr.responseText) {
        msg = xhr.status + ' ' + xhr.responseText;
    } else {
        msg = 'fail to post ' + url + ' ' + xhr.status;
    }

    var err = new Error(msg);
    err.status = xhr.status;
    err.method = 'post';
    err.url = url;
    return err;
}

function getBody(xhr) {
    var text = xhr.responseText || xhr.response;
    if (!text) {
        return text;
    }

    try {
        return JSON.parse(text);
    } catch (e) {
        return text;
    }
}

module.exports = function upload(option) {
    if (typeof XMLHttpRequest === 'undefined') {
        return;
    }

    var xhr = new XMLHttpRequest();
    var url = option.url;

    if (xhr.upload) {
        xhr.upload.onprogress = function progress(e) {
            if (e.total > 0) {
                e.percent = e.loaded / e.total * 100;
            }
            option.onProgress && option.onProgress(e);
        };
    }

    var formData = new FormData();

    if (option.data) {
        Object.keys(option.data).forEach(function (key) {
            formData.append(key, option.data[key]);
        });
    }

    formData.append(option.fileFieldName, option.file);

    xhr.onerror = function error(e) {
        option.onError(e);
    };

    xhr.onload = function onload() {
        if (xhr.status < 200 || xhr.status >= 300) {
            return option.onError(getError(url, option, xhr));
        }

        option.onSuccess(getBody(xhr));
    };

    xhr.open('post', url, true);

    if (option.withCredentials && 'withCredentials' in xhr) {
        xhr.withCredentials = true;
    }

    var headers = option.headers || {};

    for (var item in headers) {
        if (headers.hasOwnProperty(item) && headers[item] !== null) {
            xhr.setRequestHeader(item, headers[item]);
        }
    }
    xhr.send(formData);
    return xhr;
}<commit_msg>优化弹出框<commit_after>function getError(url, option, xhr) {
    var msg;
    if (xhr.response) {
        msg = xhr.status + ' ' + (xhr.response.message || xhr.response);
    } else if (xhr.responseText) {
        msg = xhr.status + ' ' + xhr.responseText;
    } else {
        msg = 'fail to post ' + url + ' ' + xhr.status;
    }

    var err = new Error(msg);
    err.status = xhr.status;
    err.method = 'post';
    err.url = url;
    return err;
}

function getBody(xhr) {
    var text = xhr.responseText || xhr.response;
    if (!text) {
        return text;
    }

    try {
        return JSON.parse(text);
    } catch (e) {
        return text;
    }
}

module.exports = function upload(option) {
    if (typeof XMLHttpRequest === 'undefined') {
        return;
    }

    var xhr = new XMLHttpRequest();
    var url = option.url;

    if (xhr.upload) {
        xhr.upload.onprogress = function progress(e) {
            if (e.total > 0) {
                e.percent = e.loaded / e.total * 100;
            }
            option.onProgress && option.onProgress(e);
        };
    }

    var formData = new FormData();

    if (option.data) {
        Object.keys(option.data).forEach(function (key) {
            formData.append(key, option.data[key]);
        });
    }

    formData.append(option.fileFieldName, option.file);

    xhr.onerror = function error(e) {
        option.onError(e);
    };

    xhr.onload = function onload() {
        if (xhr.status < 200 || xhr.status >= 300) {
            return option.onError(getError(url, option, xhr));
        }

        option.onSuccess(getBody(xhr));
    };

    xhr.open('post', url, true);

    if (option.withCredentials && 'withCredentials' in xhr) {
        xhr.withCredentials = true;
    }

    var headers = option.headers || {};

    for (var item in headers) {
        if (headers.hasOwnProperty(item) && headers[item] !== null) {
            xhr.setRequestHeader(item, headers[item]);
        }
    }
    xhr.send(formData);
    return xhr;
}<|endoftext|>


<commit_before>define([
    'dojo/request/xhr',
    'dojo/store/Memory',
    'dojo/_base/lang',
    'dojo/store/util/QueryResults',
    'dojo/_base/declare'
], function (xhr, Memory, lang, QueryResults, declare) {

    var memory = new Memory(),
        xhrCache;

    return declare('sqleditor/models/FileManagerStore', null, {

        idProperty: 'id',

        target: '/io',

        headers: {},

        accepts: 'application/javascript, application/json',

        rootQuery: {},

        queryEngine: null,

        /**
         * A combination of a Cache, JsonRest, and Memory store.
         *
         * xhr -> Handles populating the Memory store and get/delete/put/add
         * requests.
         *
         * Memory -> Handles query requests
         *
         * All succesful xhr POST/PUT/DELETE requests are propogated to the
         * Memory store.
         *
         * Methods putItem and addItem are present in order to bypass the
         * observable functionality of the Tree. For example, for each PUT
         * request, we do not want to notify the tree.
         * @param {Object} kwArgs Keyword Arguments
         * @constructor
         */
        constructor: function (kwArgs) {
            lang.mixin(this, kwArgs);

            this.queryEngine = memory.queryEngine;

            this.getTarget = function (id) {
                var target = this.target;
                if (target.charAt(target.length - 1) === '/') {
                    target += id;
                } else {
                    target += '/' + id;
                }

                return target;
            };

        },

        /**
         * Gets the memory store cache. If the cache has not been initialized
         * will query the server and initialize it.
         * @returns {Promise->Memory} A memory store.
         */
        getCache: function () {
            var that = this;
            if (!xhrCache) {
                xhrCache = xhr(this.target, {
                    handleAs: 'json'
                });
            }

            return xhrCache.then(function (data) {
                if (!memory.data.length) {
                    memory.setData(data);
                    that.rootQuery = { id: memory.data[0].id };
                }

                return memory;
            });
        },

        /**
         * Clears the cache.
         */
        clearCache: function () {
            xhrCache = null;
        },

        /**
         * Gets children of a tree node.
         * @param {Object} object A tree node.
         * @returns {Promise->Array} The children of the tree node.
         */
        getChildren: function (object) {
            return this.query({ parentId: object.id });
        },

        /**
         * Gets the id property of an object.
         * @param {Object} object The object containing an id property.
         * @returns {string || number} The id property of an object.
         */
        getIdentity: function (object) {
            return object[this.idProperty];
        },

        /**
         * Gets file or folder contents.
         * If the id is for a file, returns the contents of the file.
         * If the id is for a folder, returns the files and folders in the
         * folder.
         *
         * @param {string} id The base64 encoded path of the file or folder.
         * @param {object} options The XHR options.
         * @returns {Promise->string || array} The file contents or directory listing
         * of the folder.
         */
        get: function (id, options) {
            options = options || {};
            return xhr(this.getTarget(id), {
                handleAs: 'json',
                headers: lang.mixin({}, this.headers, options.headers)
            });
        },

        /**
         * Adds an item to the store.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options
         * @returns {Promise->string} The id added.
         */
        add: function (object, options) {
            if (options && options.observe) {
                return object;
            }

            return this.put(object, options);
        },

        /**
         * Queries the tree store.
         * @param {Object} query The query.
         * @param {Object} options The
         * @returns {Promise->QueryResult} The dojo store QueryResults.
         */
        query: function (query, options) {
            return new QueryResults(this.getCache().then(function (cache) {
                return cache.query(query, options);
            }));
        },

        /**
         * Removes an item from the store.
         * @param {string} id The id to remove.
         * @param {Object} options The XHR options.
         * @returns {Promise}
         */
        remove: function (id, options) {
            var that = this,
                request;

            options = options || {};
            request = xhr(this.getTarget(id), {
                method: 'DELETE',
                headers: lang.mixin({}, this.headers, options.headers)
            });

            return request.then(function () {
                return that.getCache().then(function (cache) {
                    return cache.remove(id);
                });
            }, function () {
                return request;
            });
        },

        /**
         * Performs an XHR put to modify an item
         * in the store.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options.
         * @returns {Promise->Object} The object added.
         */
        put: function (object, options) {
            options = options || {};
            options.isFromPut = true;
            return this.putProxy(object, options);
        },

        /**
         * Same as this.add but not observed and therefore does not change the
         * dijit tree.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options.
         * @returns {Promise->Object} The item added.
         */
        addItem: function (object, options) {
            return this.putProxy(object, options);
        },

        /**
         * Same as this.put but not observed and therefore does not change the
         * dijit tree.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options.
         * @returns {Promise->Object} The item added.
         */
        putItem: function (object, options) {
            options = options || {};
            options.isFromPut = true;
            return this.putProxy(object, options);
        },

        /**
         * Adds a file or folder. When a tree store is wrapped in an observable
         * any store.add(data) calls are intercepted and dispatched to
         * observers. In the case of a POST operation, data wont have an id as
         * the server creates it. Unfortunately, the Tree._itemsNodeMap gets
         * notified of the pre-server data without the id.
         *
         * This method willn post data to the server and then call
         * store.add(data, options['observe'] = true)) so that store.add
         * can be observed with the id, and then suppressed.
         * @param {} object The item to add.
         * @param {} options The XHR options.
         * @returns {} The added file.
         */
        putProxy: function (object, options) {
            var that = this,
                method = object.isDir || !object.id ? 'POST' : 'PUT',
                url = method === 'POST' ? this.target : this.getTarget(object.id),
                request;

            options = options || {};
            request = xhr(url, {
                method: method,
                data: JSON.stringify(object),
                handleAs: 'json',
                headers: lang.mixin({
                    'Content-Type': 'application/json',
                    Accept: this.accepts
                }, this.headers, options.headers)
            });

            return request.then(function (data) {
                return that.getCache().then(function (cache) {
                    var result = cache.put(data);
                    if (!options.isFromPut) {
                        options.observe = true;
                        that.add(data, options);
                    }

                    return result;
                });
            }, function () {
                return request;
            });
        }
    });
});
<commit_msg>Fixed comments<commit_after>define([
    'dojo/request/xhr',
    'dojo/store/Memory',
    'dojo/_base/lang',
    'dojo/store/util/QueryResults',
    'dojo/_base/declare'
], function (xhr, Memory, lang, QueryResults, declare) {

    var memory = new Memory(),
        xhrCache;

    return declare('sqleditor/models/FileManagerStore', null, {

        idProperty: 'id',

        target: '/io',

        headers: {},

        accepts: 'application/javascript, application/json',

        rootQuery: {},

        queryEngine: null,

        /**
         * A combination of a Cache, JsonRest, and Memory store.
         *
         * xhr -> Handles populating the Memory store and get/delete/put/add
         * requests.
         *
         * Memory -> Handles query requests
         *
         * All succesful xhr POST/PUT/DELETE requests are propogated to the
         * Memory store.
         *
         * Methods putItem and addItem are present in order to bypass the
         * observable functionality of the Tree. For example, for each PUT
         * request, we do not want to notify the tree.
         * @param {Object} kwArgs Keyword Arguments
         * @constructor
         */
        constructor: function (kwArgs) {
            lang.mixin(this, kwArgs);

            this.queryEngine = memory.queryEngine;

            this.getTarget = function (id) {
                var target = this.target;
                if (target.charAt(target.length - 1) === '/') {
                    target += id;
                } else {
                    target += '/' + id;
                }

                return target;
            };

        },

        /**
         * Gets the memory store cache. If the cache has not been initialized
         * will query the server and initialize it.
         * @returns {Promise->Memory} A memory store.
         */
        getCache: function () {
            var that = this;
            if (!xhrCache) {
                xhrCache = xhr(this.target, {
                    handleAs: 'json'
                });
            }

            return xhrCache.then(function (data) {
                if (!memory.data.length) {
                    memory.setData(data);
                    that.rootQuery = { id: memory.data[0].id };
                }

                return memory;
            });
        },

        /**
         * Clears the cache.
         */
        clearCache: function () {
            xhrCache = null;
        },

        /**
         * Gets children of a tree node.
         * @param {Object} object A tree node.
         * @returns {Promise->Array} The children of the tree node.
         */
        getChildren: function (object) {
            return this.query({ parentId: object.id });
        },

        /**
         * Gets the id property of an object.
         * @param {Object} object The object containing an id property.
         * @returns {string || number} The id property of an object.
         */
        getIdentity: function (object) {
            return object[this.idProperty];
        },

        /**
         * Gets file or folder contents.
         * If the id is for a file, returns the contents of the file.
         * If the id is for a folder, returns the files and folders in the
         * folder.
         *
         * @param {string} id The base64 encoded path of the file or folder.
         * @param {object} options The XHR options.
         * @returns {Promise->string || array} The file contents or directory listing
         * of the folder.
         */
        get: function (id, options) {
            options = options || {};
            return xhr(this.getTarget(id), {
                handleAs: 'json',
                headers: lang.mixin({}, this.headers, options.headers)
            });
        },

        /**
         * Adds an item to the store.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options
         * @returns {Promise->string} The id added.
         */
        add: function (object, options) {
            if (options && options.observe) {
                return object;
            }

            return this.put(object, options);
        },

        /**
         * Queries the tree store.
         * @param {Object} query The query.
         * @param {Object} options The
         * @returns {Promise->QueryResult} The dojo store QueryResults.
         */
        query: function (query, options) {
            return new QueryResults(this.getCache().then(function (cache) {
                return cache.query(query, options);
            }));
        },

        /**
         * Removes an item from the store.
         * @param {string} id The id to remove.
         * @param {Object} options The XHR options.
         * @returns {Promise}
         */
        remove: function (id, options) {
            var that = this,
                request;

            options = options || {};
            request = xhr(this.getTarget(id), {
                method: 'DELETE',
                headers: lang.mixin({}, this.headers, options.headers)
            });

            return request.then(function () {
                return that.getCache().then(function (cache) {
                    return cache.remove(id);
                });
            }, function () {
                return request;
            });
        },

        /**
         * Performs an XHR put to modify an item
         * in the store.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options.
         * @returns {Promise->Object} The object added.
         */
        put: function (object, options) {
            options = options || {};
            options.isFromPut = true;
            return this.putProxy(object, options);
        },

        /**
         * Same as this.add but not observed and therefore does not change the
         * dijit tree.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options.
         * @returns {Promise->Object} The item added.
         */
        addItem: function (object, options) {
            return this.putProxy(object, options);
        },

        /**
         * Same as this.put but not observed and therefore does not change the
         * dijit tree.
         * @param {Object} object The item to add.
         * @param {Object} options The XHR options.
         * @returns {Promise->Object} The item added.
         */
        putItem: function (object, options) {
            options = options || {};
            options.isFromPut = true;
            return this.putProxy(object, options);
        },

        /**
         * Adds a file or folder. When a tree store is wrapped in an observable
         * any store.add(data) calls are intercepted and dispatched to
         * observers. In the case of a POST operation, data wont have an id as
         * the server creates it. Unfortunately, the Tree._itemsNodeMap gets
         * notified of the pre-server data without the id.
         *
         * This method will post data to the server and then call
         * store.add(data, options['observe'] = true)) so that store.add
         * can be observed with the id, and then suppressed.
         * @param {} object The item to add.
         * @param {} options The XHR options.
         * @returns {} The added file.
         */
        putProxy: function (object, options) {
            var that = this,
                method = object.isDir || !object.id ? 'POST' : 'PUT',
                url = method === 'POST' ? this.target : this.getTarget(object.id),
                request;

            options = options || {};
            request = xhr(url, {
                method: method,
                data: JSON.stringify(object),
                handleAs: 'json',
                headers: lang.mixin({
                    'Content-Type': 'application/json',
                    Accept: this.accepts
                }, this.headers, options.headers)
            });

            return request.then(function (data) {
                return that.getCache().then(function (cache) {
                    var result = cache.put(data);
                    if (!options.isFromPut) {
                        options.observe = true;
                        that.add(data, options);
                    }

                    return result;
                });
            }, function () {
                return request;
            });
        }
    });
});
<|endoftext|>


<commit_before>import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {defaults as defaultInteractions, Modify, Select} from '../src/ol/interaction.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';

const styleFunction = (function() {
  const styles = {};
  const image = new CircleStyle({
    radius: 5,
    fill: null,
    stroke: new Stroke({color: 'orange', width: 2})
  });
  styles['Point'] = new Style({image: image});
  styles['Polygon'] = new Style({
    stroke: new Stroke({
      color: 'blue',
      width: 3
    }),
    fill: new Fill({
      color: 'rgba(0, 0, 255, 0.1)'
    })
  });
  styles['MultiLineString'] = new Style({
    stroke: new Stroke({
      color: 'green',
      width: 3
    })
  });
  styles['MultiPolygon'] = new Style({
    stroke: new Stroke({
      color: 'yellow',
      width: 1
    }),
    fill: new Fill({
      color: 'rgba(255, 255, 0, 0.1)'
    })
  });
  styles['default'] = new Style({
    stroke: new Stroke({
      color: 'red',
      width: 3
    }),
    fill: new Fill({
      color: 'rgba(255, 0, 0, 0.1)'
    }),
    image: image
  });
  return function(feature) {
    return styles[feature.getGeometry().getType()] || styles['default'];
  };
})();

const geojsonObject = {
  'type': 'FeatureCollection',
  'crs': {
    'type': 'name',
    'properties': {
      'name': 'EPSG:3857'
    }
  },
  'features': [{
    'type': 'Feature',
    'geometry': {
      'type': 'Point',
      'coordinates': [0, 0]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'MultiPoint',
      'coordinates': [[-2e6, 0], [0, -2e6]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'LineString',
      'coordinates': [[4e6, -2e6], [8e6, 2e6], [9e6, 2e6]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'LineString',
      'coordinates': [[4e6, -2e6], [8e6, 2e6], [8e6, 3e6]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'Polygon',
      'coordinates': [[[-5e6, -1e6], [-4e6, 1e6],
        [-3e6, -1e6], [-5e6, -1e6]], [[-4.5e6, -0.5e6],
        [-3.5e6, -0.5e6], [-4e6, 0.5e6], [-4.5e6, -0.5e6]]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'MultiLineString',
      'coordinates': [
        [[-1e6, -7.5e5], [-1e6, 7.5e5]],
        [[-1e6, -7.5e5], [-1e6, 7.5e5], [-5e5, 0], [-1e6, -7.5e5]],
        [[1e6, -7.5e5], [15e5, 0], [15e5, 0], [1e6, 7.5e5]],
        [[-7.5e5, -1e6], [7.5e5, -1e6]],
        [[-7.5e5, 1e6], [7.5e5, 1e6]]
      ]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'MultiPolygon',
      'coordinates': [
        [[[-5e6, 6e6], [-5e6, 8e6], [-3e6, 8e6],
          [-3e6, 6e6], [-5e6, 6e6]]],
        [[[-3e6, 6e6], [-2e6, 8e6], [0, 8e6],
          [0, 6e6], [-3e6, 6e6]]],
        [[[1e6, 6e6], [1e6, 8e6], [3e6, 8e6],
          [3e6, 6e6], [1e6, 6e6]]]
      ]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'GeometryCollection',
      'geometries': [{
        'type': 'LineString',
        'coordinates': [[-5e6, -5e6], [0, -5e6]]
      }, {
        'type': 'Point',
        'coordinates': [4e6, -5e6]
      }, {
        'type': 'Polygon',
        'coordinates': [
          [[1e6, -6e6], [2e6, -4e6], [3e6, -6e6], [1e6, -6e6]]
        ]
      }]
    }
  }]
};

const source = new VectorSource({
  features: (new GeoJSON()).readFeatures(geojsonObject),
  wrapX: false
});

const layer = new VectorLayer({
  source: source,
  style: styleFunction
});

const overlayStyle = (function() {
  const styles = {};
  styles['Polygon'] = [
    new Style({
      fill: new Fill({
        color: [255, 255, 255, 0.5]
      })
    }),
    new Style({
      stroke: new Stroke({
        color: [255, 255, 255, 1],
        width: 5
      })
    }),
    new Style({
      stroke: new Stroke({
        color: [0, 153, 255, 1],
        width: 3
      })
    })
  ];
  styles['MultiPolygon'] = styles['Polygon'];

  styles['LineString'] = [
    new Style({
      stroke: new Stroke({
        color: [255, 255, 255, 1],
        width: 5
      })
    }),
    new Style({
      stroke: new Stroke({
        color: [0, 153, 255, 1],
        width: 3
      })
    })
  ];
  styles['MultiLineString'] = styles['LineString'];

  styles['Point'] = [
    new Style({
      image: new CircleStyle({
        radius: 7,
        fill: new Fill({
          color: [0, 153, 255, 1]
        }),
        stroke: new Stroke({
          color: [255, 255, 255, 0.75],
          width: 1.5
        })
      }),
      zIndex: 100000
    })
  ];
  styles['MultiPoint'] = styles['Point'];

  styles['GeometryCollection'] = styles['Polygon'].concat(styles['Point']);

  return function(feature) {
    return styles[feature.getGeometry().getType()];
  };
})();

const select = new Select({
  style: overlayStyle
});

const modify = new Modify({
  features: select.getFeatures(),
  style: overlayStyle,
  insertVertexCondition: function() {
    // prevent new vertices to be added to the polygons
    return !select.getFeatures().getArray().every(function(feature) {
      return feature.getGeometry().getType().match(/Polygon/);
    });
  }
});

const map = new Map({
  interactions: defaultInteractions().extend([select, modify]),
  layers: [layer],
  target: 'map',
  view: new View({
    center: [0, 1000000],
    zoom: 2,
    multiWorld: true
  })
});
<commit_msg>Ensure example opens at correct zoom<commit_after>import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {defaults as defaultInteractions, Modify, Select} from '../src/ol/interaction.js';
import VectorLayer from '../src/ol/layer/Vector.js';
import VectorSource from '../src/ol/source/Vector.js';
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';

const styleFunction = (function() {
  const styles = {};
  const image = new CircleStyle({
    radius: 5,
    fill: null,
    stroke: new Stroke({color: 'orange', width: 2})
  });
  styles['Point'] = new Style({image: image});
  styles['Polygon'] = new Style({
    stroke: new Stroke({
      color: 'blue',
      width: 3
    }),
    fill: new Fill({
      color: 'rgba(0, 0, 255, 0.1)'
    })
  });
  styles['MultiLineString'] = new Style({
    stroke: new Stroke({
      color: 'green',
      width: 3
    })
  });
  styles['MultiPolygon'] = new Style({
    stroke: new Stroke({
      color: 'yellow',
      width: 1
    }),
    fill: new Fill({
      color: 'rgba(255, 255, 0, 0.1)'
    })
  });
  styles['default'] = new Style({
    stroke: new Stroke({
      color: 'red',
      width: 3
    }),
    fill: new Fill({
      color: 'rgba(255, 0, 0, 0.1)'
    }),
    image: image
  });
  return function(feature) {
    return styles[feature.getGeometry().getType()] || styles['default'];
  };
})();

const geojsonObject = {
  'type': 'FeatureCollection',
  'crs': {
    'type': 'name',
    'properties': {
      'name': 'EPSG:3857'
    }
  },
  'features': [{
    'type': 'Feature',
    'geometry': {
      'type': 'Point',
      'coordinates': [0, 0]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'MultiPoint',
      'coordinates': [[-2e6, 0], [0, -2e6]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'LineString',
      'coordinates': [[4e6, -2e6], [8e6, 2e6], [9e6, 2e6]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'LineString',
      'coordinates': [[4e6, -2e6], [8e6, 2e6], [8e6, 3e6]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'Polygon',
      'coordinates': [[[-5e6, -1e6], [-4e6, 1e6],
        [-3e6, -1e6], [-5e6, -1e6]], [[-4.5e6, -0.5e6],
        [-3.5e6, -0.5e6], [-4e6, 0.5e6], [-4.5e6, -0.5e6]]]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'MultiLineString',
      'coordinates': [
        [[-1e6, -7.5e5], [-1e6, 7.5e5]],
        [[-1e6, -7.5e5], [-1e6, 7.5e5], [-5e5, 0], [-1e6, -7.5e5]],
        [[1e6, -7.5e5], [15e5, 0], [15e5, 0], [1e6, 7.5e5]],
        [[-7.5e5, -1e6], [7.5e5, -1e6]],
        [[-7.5e5, 1e6], [7.5e5, 1e6]]
      ]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'MultiPolygon',
      'coordinates': [
        [[[-5e6, 6e6], [-5e6, 8e6], [-3e6, 8e6],
          [-3e6, 6e6], [-5e6, 6e6]]],
        [[[-3e6, 6e6], [-2e6, 8e6], [0, 8e6],
          [0, 6e6], [-3e6, 6e6]]],
        [[[1e6, 6e6], [1e6, 8e6], [3e6, 8e6],
          [3e6, 6e6], [1e6, 6e6]]]
      ]
    }
  }, {
    'type': 'Feature',
    'geometry': {
      'type': 'GeometryCollection',
      'geometries': [{
        'type': 'LineString',
        'coordinates': [[-5e6, -5e6], [0, -5e6]]
      }, {
        'type': 'Point',
        'coordinates': [4e6, -5e6]
      }, {
        'type': 'Polygon',
        'coordinates': [
          [[1e6, -6e6], [2e6, -4e6], [3e6, -6e6], [1e6, -6e6]]
        ]
      }]
    }
  }]
};

const source = new VectorSource({
  features: (new GeoJSON()).readFeatures(geojsonObject)
});

const layer = new VectorLayer({
  source: source,
  style: styleFunction
});

const overlayStyle = (function() {
  const styles = {};
  styles['Polygon'] = [
    new Style({
      fill: new Fill({
        color: [255, 255, 255, 0.5]
      })
    }),
    new Style({
      stroke: new Stroke({
        color: [255, 255, 255, 1],
        width: 5
      })
    }),
    new Style({
      stroke: new Stroke({
        color: [0, 153, 255, 1],
        width: 3
      })
    })
  ];
  styles['MultiPolygon'] = styles['Polygon'];

  styles['LineString'] = [
    new Style({
      stroke: new Stroke({
        color: [255, 255, 255, 1],
        width: 5
      })
    }),
    new Style({
      stroke: new Stroke({
        color: [0, 153, 255, 1],
        width: 3
      })
    })
  ];
  styles['MultiLineString'] = styles['LineString'];

  styles['Point'] = [
    new Style({
      image: new CircleStyle({
        radius: 7,
        fill: new Fill({
          color: [0, 153, 255, 1]
        }),
        stroke: new Stroke({
          color: [255, 255, 255, 0.75],
          width: 1.5
        })
      }),
      zIndex: 100000
    })
  ];
  styles['MultiPoint'] = styles['Point'];

  styles['GeometryCollection'] = styles['Polygon'].concat(styles['Point']);

  return function(feature) {
    return styles[feature.getGeometry().getType()];
  };
})();

const select = new Select({
  style: overlayStyle
});

const modify = new Modify({
  features: select.getFeatures(),
  style: overlayStyle,
  insertVertexCondition: function() {
    // prevent new vertices to be added to the polygons
    return !select.getFeatures().getArray().every(function(feature) {
      return feature.getGeometry().getType().match(/Polygon/);
    });
  }
});

const map = new Map({
  interactions: defaultInteractions().extend([select, modify]),
  layers: [layer],
  target: 'map',
  view: new View({
    center: [0, 1000000],
    zoom: 2,
    multiWorld: true
  })
});
<|endoftext|>


<commit_before>/*global ares, enyo, $L */

// Action popup now accept call back that will be run when user click
// on ok or cancel. Note that events are not fired when callback are
// defined

enyo.kind({
	name: "Ares.ActionPopup",
	kind: "onyx.Popup",
	modal: true,
	centered: true,
	floating: true,
	autoDismiss: false,
	classes:"ares-classic-popup",
	published: {
		title: "",
		actionButton: "",
		action1Button: "",
		cancelButton: "",
		allowHtmlMsg: false,
		message: ""
	},
	events: {
		onConfirmActionPopup: "",
		onConfirmAction1Popup: "",
		onCancelActionPopup: ""
	},
	components: [
		{tag: "div", name: "title", classes:"title", content: ""},
		{kind: "enyo.Scroller",  classes:"ares-small-popup", fit: true, components: [
			{classes:"ares-small-popup-details", name:"popupContent", components:[
				{name:"message"}
			]}
		]},
		{kind: "onyx.Toolbar", classes:"bottom-toolbar", name: "buttons", components: [
			{name:"actionButton", kind: "onyx.Button", content: "Action", ontap: "actionConfirm"},
			{name:"action1Button", kind: "onyx.Button", content: "Action1", ontap: "action1Confirm", showing: false},
			{name:"cancelButton", classes:"right", kind: "onyx.Button", content: $L("Cancel"), ontap: "actionCancel"}
		]}
	],
	callbacks: {},
	/** @private */
	create: function() {
		ares.setupTraceLogger(this);
		this.inherited(arguments);

		this.titleChanged();
		this.messageChanged();
		this.actionButtonChanged();
		this.action1ButtonChanged();
		this.cancelButtonChanged();
		this.$.message.setAllowHtml(this.allowHtmlMsg);
	},
	/** @private */
	titleChanged: function(oldVal) {
		this.$.title.setContent(this.title);
	},
	/** @private */
	messageChanged:function(oldVal) {
		this.$.message.setContent(this.message);
	},
	/** @private */
	actionButtonChanged: function(oldVal) {
		if (this.actionButton !== "") {
			this.$.actionButton.setContent(this.actionButton);
		}
	},
	/** @private */
	action1ButtonChanged: function(oldVal) {
		if (this.action1Button !== "") {
			this.$.action1Button.setContent(this.action1Button);
			this.$.action1Button.show();
		} else {
			this.$.action1Button.hide();
		}
	},
	/** @private */
	cancelButtonChanged: function(oldVal) {
		if (this.cancelButton !== "") {
			this.$.cancelButton.setContent(this.cancelButton);
		}
	},
	/** @private */
	actionConfirm: function(inSender, inEvent) {
		this.hide();
		this.trace('actionConfirm tapped', inSender, inEvent);
		this.runCallbackOrBubbleUp('action', 'onConfirmActionPopup');
		return true;
	},
	/** @private */
	action1Confirm: function(inSender, inEvent) {
		this.hide();
		this.runCallbackOrBubbleUp('action1', 'onConfirmAction1Popup');
		return true;
	},
	/** @private */
	actionCancel: function(inSender, inEvent) {
		this.hide();
		this.log('');
		this.runCallbackOrBubbleUp('cancel', 'onCancelActionPopup');
		return true;
	},
	/** @private */
	runCallbackOrBubbleUp: function(cbName, fallbackEvent) {
		var theCb = this.callbacks[cbName];

		// to be re-entrant, all callbacks must be deleted before
		// calling the the relevant callback (and not
		// after). Otherwise, the code used in callback may reuse and
		// set its own callback before the end fo runCallBack function
		this.callbacks = {};

		if (typeof theCb === 'function') {
			this.trace("Running callback " + cbName);
			theCb();
		} else {
			this.trace("Bubbling fallback event " + fallbackEvent);
			this.bubble(fallbackEvent);
		}
	},
	setActionCallback: function(cb) {
		this.callbacks.action = cb;
	},
	setAction1Callback: function(cb) {
		this.callbacks.action1 = cb;
	},
	setCancelCallback: function(cb) {
		this.callbacks.cancel = cb;
	},
	setCallbacks: function(allCbs) {
		this.callbacks = allCbs;
	}
});
<commit_msg>ENYO-3082: removed forgotten log<commit_after>/*global ares, enyo, $L */

// Action popup now accept call back that will be run when user click
// on ok or cancel. Note that events are not fired when callback are
// defined

enyo.kind({
	name: "Ares.ActionPopup",
	kind: "onyx.Popup",
	modal: true,
	centered: true,
	floating: true,
	autoDismiss: false,
	classes:"ares-classic-popup",
	published: {
		title: "",
		actionButton: "",
		action1Button: "",
		cancelButton: "",
		allowHtmlMsg: false,
		message: ""
	},
	events: {
		onConfirmActionPopup: "",
		onConfirmAction1Popup: "",
		onCancelActionPopup: ""
	},
	components: [
		{tag: "div", name: "title", classes:"title", content: ""},
		{kind: "enyo.Scroller",  classes:"ares-small-popup", fit: true, components: [
			{classes:"ares-small-popup-details", name:"popupContent", components:[
				{name:"message"}
			]}
		]},
		{kind: "onyx.Toolbar", classes:"bottom-toolbar", name: "buttons", components: [
			{name:"actionButton", kind: "onyx.Button", content: "Action", ontap: "actionConfirm"},
			{name:"action1Button", kind: "onyx.Button", content: "Action1", ontap: "action1Confirm", showing: false},
			{name:"cancelButton", classes:"right", kind: "onyx.Button", content: $L("Cancel"), ontap: "actionCancel"}
		]}
	],
	callbacks: {},
	/** @private */
	create: function() {
		ares.setupTraceLogger(this);
		this.inherited(arguments);

		this.titleChanged();
		this.messageChanged();
		this.actionButtonChanged();
		this.action1ButtonChanged();
		this.cancelButtonChanged();
		this.$.message.setAllowHtml(this.allowHtmlMsg);
	},
	/** @private */
	titleChanged: function(oldVal) {
		this.$.title.setContent(this.title);
	},
	/** @private */
	messageChanged:function(oldVal) {
		this.$.message.setContent(this.message);
	},
	/** @private */
	actionButtonChanged: function(oldVal) {
		if (this.actionButton !== "") {
			this.$.actionButton.setContent(this.actionButton);
		}
	},
	/** @private */
	action1ButtonChanged: function(oldVal) {
		if (this.action1Button !== "") {
			this.$.action1Button.setContent(this.action1Button);
			this.$.action1Button.show();
		} else {
			this.$.action1Button.hide();
		}
	},
	/** @private */
	cancelButtonChanged: function(oldVal) {
		if (this.cancelButton !== "") {
			this.$.cancelButton.setContent(this.cancelButton);
		}
	},
	/** @private */
	actionConfirm: function(inSender, inEvent) {
		this.hide();
		this.trace('actionConfirm tapped', inSender, inEvent);
		this.runCallbackOrBubbleUp('action', 'onConfirmActionPopup');
		return true;
	},
	/** @private */
	action1Confirm: function(inSender, inEvent) {
		this.hide();
		this.runCallbackOrBubbleUp('action1', 'onConfirmAction1Popup');
		return true;
	},
	/** @private */
	actionCancel: function(inSender, inEvent) {
		this.hide();
		this.runCallbackOrBubbleUp('cancel', 'onCancelActionPopup');
		return true;
	},
	/** @private */
	runCallbackOrBubbleUp: function(cbName, fallbackEvent) {
		var theCb = this.callbacks[cbName];

		// to be re-entrant, all callbacks must be deleted before
		// calling the the relevant callback (and not
		// after). Otherwise, the code used in callback may reuse and
		// set its own callback before the end fo runCallBack function
		this.callbacks = {};

		if (typeof theCb === 'function') {
			this.trace("Running callback " + cbName);
			theCb();
		} else {
			this.trace("Bubbling fallback event " + fallbackEvent);
			this.bubble(fallbackEvent);
		}
	},
	setActionCallback: function(cb) {
		this.callbacks.action = cb;
	},
	setAction1Callback: function(cb) {
		this.callbacks.action1 = cb;
	},
	setCancelCallback: function(cb) {
		this.callbacks.cancel = cb;
	},
	setCallbacks: function(allCbs) {
		this.callbacks = allCbs;
	}
});
<|endoftext|>


<commit_before>var createExpHelperInst = window.optly.mrkt.form.createExp({formId: 'create-exp-form'});

$(createExpHelperInst.formElm).on('submit', function(e) {
  var uri,
    validationError = false;

  e.preventDefault();

  validationError = createExpHelperInst.validateInputs();

  if(!validationError) {

    createExpHelperInst.processingAdd();

    uri = createExpHelperInst.getUri();

    w.analytics.track('create experiment submit', {
      category: 'experiment',
      label: w.location.pathname
    }, {
      integrations: {
        Marketo: false
      }
    });

    w.setTimeout(function() {
      window.location.href = uri;
    }, 500);

  } else {
    createExpHelperInst.showOptionsError();
  }

});
<commit_msg>Send create experiment submit to Marketo.<commit_after>var createExpHelperInst = window.optly.mrkt.form.createExp({formId: 'create-exp-form'});

$(createExpHelperInst.formElm).on('submit', function(e) {
  var uri,
    validationError = false;

  e.preventDefault();

  validationError = createExpHelperInst.validateInputs();

  if(!validationError) {

    createExpHelperInst.processingAdd();

    uri = createExpHelperInst.getUri();

    w.analytics.track('create experiment submit', {
      category: 'experiment',
      label: w.location.pathname
    });

    w.setTimeout(function() {
      window.location.href = uri;
    }, 500);

  } else {
    createExpHelperInst.showOptionsError();
  }

});
<|endoftext|>


<commit_before>'use strict'
var React = require('react');
var $script = require('scriptjs');

module.exports.GenomeBrowser = React.createClass({
    componentDidMount: function () {
        $script('dalliance', function() {
            var encode = 'https://www.encodeproject.org';
            var Dalliance = require('dalliance').browser;
            var browser = new Dalliance({
                chr:          '22',
                viewStart:    29890000,
                viewEnd:      30050000,
                cookieKey:    'human-grc_h37-fp',
                coordSystem: {
                    speciesName: 'Human',
                    taxon: 9606,
                    auth: 'GRCh',
                    version: '37',
                    ucscName: 'hg19',
                },
                sources: [],
                noTitle: true,
                disablePoweredBy: true
            });
            var files = this.props.files;
            browser.sources = [];
            var assembly = this.props.assembly;
            if(assembly[0] == 'hg19') {
                browser.sources = [
                    {
                        name: 'Genome',
                        twoBitURI: 'https://www.biodalliance.org/datasets/hg19.2bit',
                        tier_type: 'sequence',
                        provides_entrypoints: true,
                        pinned: true
                    },
                    {
                        name: 'GENCODE',
                        bwgURI: 'https://www.biodalliance.org/datasets/gencode.bb',
                        stylesheet_uri: 'http://www.biodalliance.org/stylesheets/gencode.xml',
                        collapseSuperGroups: true,
                        trixURI: 'https://www.biodalliance.org/datasets/geneIndex.ix'
                    },
                    {
                        name: 'Repeats',
                        desc: 'Repeat annotation from RepeatMasker',
                        bwgURI: 'https://www.biodalliance.org/datasets/repeats.bb',
                        stylesheet_uri: 'https://www.biodalliance.org/stylesheets/bb-repeats.xml',
                        forceReduction: -1
                    }
                ];
            }
            else if(assembly[0] == 'mm10') {
                browser.chr = '19';
                browser.viewStart = 30000000;
                browser.viewEnd = 30100000;
                browser.cookieKey = 'mouse38';
                browser.coordSystem = {speciesName: 'Mouse', taxon: 10090, auth: 'GRCm', version: 38, ucscName: 'mm10'};
                browser.sources = [
                    {
                        name: 'Genome',
                        twoBitURI:  'https://www.biodalliance.org/datasets/GRCm38/mm10.2bit',
                        desc: 'Mouse reference genome build GRCm38',
                        tier_type: 'sequence',
                        provides_entrypoints: true
                    },
                    {
                        name: 'Genes',
                        desc: 'Gene structures from GENCODE M2',
                        bwgURI: 'https://www.biodalliance.org/datasets/GRCm38/gencodeM2.bb',
                        stylesheet_uri: 'https://www.biodalliance.org/stylesheets/gencode.xml',
                        collapseSuperGroups: true,
                        trixURI: 'https://www.biodalliance.org/datasets/GRCm38/gencodeM2.ix'
                    },
                    {
                        name: 'Repeats',
                        desc: 'Repeat annotation from UCSC',
                        bwgURI: 'https://www.biodalliance.org/datasets/GRCm38/repeats.bb',
                        stylesheet_uri: 'https://www.biodalliance.org/stylesheets/bb-repeats2.xml'
                    }
                ];
            } else if(assembly[0] == 'mm9') {
                browser.chr = '19';
                browser.viewStart = 30000000;
                browser.viewEnd = 30030000;
                browser.cookieKey = 'mouse';
                browser.coordSystem = {speciesName: 'Mouse', taxon: 10090, auth: 'NCBIM', version: 37};
                browser.sources = [
                    {
                        name: 'Genome',
                        uri:  'https://www.derkholm.net:9080/das/mm9comp/',
                        desc: 'Mouse reference genome build NCBIm37',
                        tier_type: 'sequence',
                        provides_entrypoints: true},
                    {
                        name: 'Genes',
                        desc: 'Gene structures from Ensembl 58',
                        uri:  'https://www.derkholm.net:8080/das/mmu_58_37k/',
                        collapseSuperGroups: true,
                        provides_karyotype: true,
                        provides_search: true
                    },
                    {
                        name: 'Repeats',
                        desc: 'Repeat annotation from Ensembl 58',
                        uri: 'https://www.derkholm.net:8080/das/mmu_58_37k/',
                        stylesheet_uri: 'https://www.derkholm.net/dalliance-test/stylesheets/mouse-repeats.xml'
                    }
                ];
            }
            files.forEach(function (file) {
                if(file.file_format == 'bigWig') {
                    browser.sources.push({
                        name: file.accession,
                        bwgURI: encode + file.href,
                        style: [
                            {
                                type: 'default',
                                style: {
                                    glyph: 'HISTOGRAM',
                                    HEIGHT: 30,
                                    BGCOLOR: 'rgb(166,71,71)'
                                }
                            }
                        ]
                    });
                }
                else if(file.file_format == 'bigBed') {
                    browser.sources.push({
                        name: file.accession,
                        bwgURI: encode + file.href,
                        style: [
                            {
                                style: {
                                    HEIGHT: 10
                                }
                            }
                        ]
                    });
                }
            });
        }.bind(this));
    },
    render: function() {
        return (

        );
    }
});
<commit_msg>Fetch files proxied through local url.<commit_after>'use strict'
var React = require('react');
var $script = require('scriptjs');

module.exports.GenomeBrowser = React.createClass({
    componentDidMount: function () {
        $script('dalliance', function() {
            var Dalliance = require('dalliance').browser;
            var browser = new Dalliance({
                chr:          '22',
                viewStart:    29890000,
                viewEnd:      30050000,
                cookieKey:    'human-grc_h37-fp',
                coordSystem: {
                    speciesName: 'Human',
                    taxon: 9606,
                    auth: 'GRCh',
                    version: '37',
                    ucscName: 'hg19',
                },
                sources: [],
                noTitle: true,
                disablePoweredBy: true
            });
            var files = this.props.files;
            browser.sources = [];
            var assembly = this.props.assembly;
            if(assembly[0] == 'hg19') {
                browser.sources = [
                    {
                        name: 'Genome',
                        twoBitURI: 'https://www.biodalliance.org/datasets/hg19.2bit',
                        tier_type: 'sequence',
                        provides_entrypoints: true,
                        pinned: true
                    },
                    {
                        name: 'GENCODE',
                        bwgURI: 'https://www.biodalliance.org/datasets/gencode.bb',
                        stylesheet_uri: 'http://www.biodalliance.org/stylesheets/gencode.xml',
                        collapseSuperGroups: true,
                        trixURI: 'https://www.biodalliance.org/datasets/geneIndex.ix'
                    },
                    {
                        name: 'Repeats',
                        desc: 'Repeat annotation from RepeatMasker',
                        bwgURI: 'https://www.biodalliance.org/datasets/repeats.bb',
                        stylesheet_uri: 'https://www.biodalliance.org/stylesheets/bb-repeats.xml',
                        forceReduction: -1
                    }
                ];
            }
            else if(assembly[0] == 'mm10') {
                browser.chr = '19';
                browser.viewStart = 30000000;
                browser.viewEnd = 30100000;
                browser.cookieKey = 'mouse38';
                browser.coordSystem = {speciesName: 'Mouse', taxon: 10090, auth: 'GRCm', version: 38, ucscName: 'mm10'};
                browser.sources = [
                    {
                        name: 'Genome',
                        twoBitURI:  'https://www.biodalliance.org/datasets/GRCm38/mm10.2bit',
                        desc: 'Mouse reference genome build GRCm38',
                        tier_type: 'sequence',
                        provides_entrypoints: true
                    },
                    {
                        name: 'Genes',
                        desc: 'Gene structures from GENCODE M2',
                        bwgURI: 'https://www.biodalliance.org/datasets/GRCm38/gencodeM2.bb',
                        stylesheet_uri: 'https://www.biodalliance.org/stylesheets/gencode.xml',
                        collapseSuperGroups: true,
                        trixURI: 'https://www.biodalliance.org/datasets/GRCm38/gencodeM2.ix'
                    },
                    {
                        name: 'Repeats',
                        desc: 'Repeat annotation from UCSC',
                        bwgURI: 'https://www.biodalliance.org/datasets/GRCm38/repeats.bb',
                        stylesheet_uri: 'https://www.biodalliance.org/stylesheets/bb-repeats2.xml'
                    }
                ];
            } else if(assembly[0] == 'mm9') {
                browser.chr = '19';
                browser.viewStart = 30000000;
                browser.viewEnd = 30030000;
                browser.cookieKey = 'mouse';
                browser.coordSystem = {speciesName: 'Mouse', taxon: 10090, auth: 'NCBIM', version: 37};
                browser.sources = [
                    {
                        name: 'Genome',
                        uri:  'https://www.derkholm.net:9080/das/mm9comp/',
                        desc: 'Mouse reference genome build NCBIm37',
                        tier_type: 'sequence',
                        provides_entrypoints: true},
                    {
                        name: 'Genes',
                        desc: 'Gene structures from Ensembl 58',
                        uri:  'https://www.derkholm.net:8080/das/mmu_58_37k/',
                        collapseSuperGroups: true,
                        provides_karyotype: true,
                        provides_search: true
                    },
                    {
                        name: 'Repeats',
                        desc: 'Repeat annotation from Ensembl 58',
                        uri: 'https://www.derkholm.net:8080/das/mmu_58_37k/',
                        stylesheet_uri: 'https://www.derkholm.net/dalliance-test/stylesheets/mouse-repeats.xml'
                    }
                ];
            }
            files.forEach(function (file) {
                if(file.file_format == 'bigWig') {
                    browser.sources.push({
                        name: file.accession,
                        bwgURI: file.href + '?proxy=true',
                        style: [
                            {
                                type: 'default',
                                style: {
                                    glyph: 'HISTOGRAM',
                                    HEIGHT: 30,
                                    BGCOLOR: 'rgb(166,71,71)'
                                }
                            }
                        ]
                    });
                }
                else if(file.file_format == 'bigBed') {
                    browser.sources.push({
                        name: file.accession,
                        bwgURI: file.href + '?proxy=true',
                        style: [
                            {
                                style: {
                                    HEIGHT: 10
                                }
                            }
                        ]
                    });
                }
            });
        }.bind(this));
    },
    render: function() {
        return (

        );
    }
});
<|endoftext|>


<commit_before>
// this is a test server to support tests which make requests

var io = require('socket.io');
var server = io(process.env.ZUUL_PORT);
var expect = require('expect.js');

server.of('/foo').on('connection', function(){
  // register namespace
});

server.on('connection', function(socket){
  // simple test
  socket.on('hi', function(){
    socket.emit('hi');
  });

  // ack tests
  socket.on('ack', function(){
    socket.emit('ack', function(a, b){
      if (a == 5 && b.test) {
        socket.emit('got it');
      }
    });
  });

  socket.on('getAckDate', function(data, cb){
    cb(new Date());
  });

  socket.on('getDate', function(){
    socket.emit('takeDate', new Date());
  });

  socket.on('getDateObj', function(){
    socket.emit('takeDateObj', { date: new Date() });
  });

  socket.on('getUtf8', function() {
    socket.emit('takeUtf8', 'てすと');
    socket.emit('takeUtf8', 'Я Б Г Д Ж Й');
    socket.emit('takeUtf8', 'Ä ä Ü ü ß');
    socket.emit('takeUtf8', 'utf8 — string');
    socket.emit('takeUtf8', 'utf8 — string');
  });

  // false test
  socket.on('false', function(){
    socket.emit('false', false);
  });

  // binary test
  socket.on('doge', function(){
    buf = new Buffer('asdfasdf', 'utf8');
    socket.emit('doge', buf);
  });

  // expect receiving binary to be buffer
  socket.on('buffa', function(a){
    if (Buffer.isBuffer(a)) socket.emit('buffack');
  });

  // expect receiving binary with mixed JSON
  socket.on('jsonbuff', function(a) {
    expect(a.hello).to.eql('lol');
    expect(Buffer.isBuffer(a.message)).to.be(true);
    expect(a.goodbye).to.eql('gotcha');
    socket.emit('jsonbuff-ack');
  });

  // expect receiving buffers in order
  var receivedAbuff1 = false;
  socket.on('abuff1', function(a) {
    expect(Buffer.isBuffer(a)).to.be(true);
    receivedAbuff1 = true;
  });
  socket.on('abuff2', function(a) {
    expect(receivedAbuff1).to.be(true);
    socket.emit('abuff2-ack');
  });

  // expect sent blob to be buffer
  socket.on('blob', function(a){
    if (Buffer.isBuffer(a)) socket.emit('back');
  });

  // expect sent blob mixed with json to be buffer
  socket.on('jsonblob', function(a) {
    expect(a.hello).to.eql('lol');
    expect(Buffer.isBuffer(a.message)).to.be(true);
    expect(a.goodbye).to.eql('gotcha');
    socket.emit('jsonblob-ack');
  });

  // expect blobs sent in order to arrive in correct order
  var receivedblob1 = false;
  var receivedblob2 = false;
  socket.on('blob1', function(a) {
    expect(Buffer.isBuffer(a)).to.be(true);
    receivedblob1 = true;
  });
  socket.on('blob2', function(a) {
    expect(receivedblob1).to.be(true);
    expect(a).to.eql('second');
    receivedblob2 = true;
  });
  socket.on('blob3', function(a) {
    expect(Buffer.isBuffer(a)).to.be(true);
    expect(receivedblob1).to.be(true);
    expect(receivedblob2).to.be(true);
    socket.emit('blob3-ack');
  });

  // emit buffer to base64 receiving browsers
  socket.on('getbin', function() {
    buf = new Buffer('asdfasdf', 'utf8');
    socket.emit('takebin', buf);
  });
});
<commit_msg>register other nsps<commit_after>
// this is a test server to support tests which make requests

var io = require('socket.io');
var server = io(process.env.ZUUL_PORT);
var expect = require('expect.js');

server.of('/foo').on('connection', function(){
  // register namespace
});

server.of('/timeout_socket').on('connection', function(){
  // register namespace
});

server.of('/valid').on('connection', function(){
  // register namespace
});

server.of('/asd').on('connection', function(){
  // register namespace
});

server.on('connection', function(socket){
  // simple test
  socket.on('hi', function(){
    socket.emit('hi');
  });

  // ack tests
  socket.on('ack', function(){
    socket.emit('ack', function(a, b){
      if (a == 5 && b.test) {
        socket.emit('got it');
      }
    });
  });

  socket.on('getAckDate', function(data, cb){
    cb(new Date());
  });

  socket.on('getDate', function(){
    socket.emit('takeDate', new Date());
  });

  socket.on('getDateObj', function(){
    socket.emit('takeDateObj', { date: new Date() });
  });

  socket.on('getUtf8', function() {
    socket.emit('takeUtf8', 'てすと');
    socket.emit('takeUtf8', 'Я Б Г Д Ж Й');
    socket.emit('takeUtf8', 'Ä ä Ü ü ß');
    socket.emit('takeUtf8', 'utf8 — string');
    socket.emit('takeUtf8', 'utf8 — string');
  });

  // false test
  socket.on('false', function(){
    socket.emit('false', false);
  });

  // binary test
  socket.on('doge', function(){
    buf = new Buffer('asdfasdf', 'utf8');
    socket.emit('doge', buf);
  });

  // expect receiving binary to be buffer
  socket.on('buffa', function(a){
    if (Buffer.isBuffer(a)) socket.emit('buffack');
  });

  // expect receiving binary with mixed JSON
  socket.on('jsonbuff', function(a) {
    expect(a.hello).to.eql('lol');
    expect(Buffer.isBuffer(a.message)).to.be(true);
    expect(a.goodbye).to.eql('gotcha');
    socket.emit('jsonbuff-ack');
  });

  // expect receiving buffers in order
  var receivedAbuff1 = false;
  socket.on('abuff1', function(a) {
    expect(Buffer.isBuffer(a)).to.be(true);
    receivedAbuff1 = true;
  });
  socket.on('abuff2', function(a) {
    expect(receivedAbuff1).to.be(true);
    socket.emit('abuff2-ack');
  });

  // expect sent blob to be buffer
  socket.on('blob', function(a){
    if (Buffer.isBuffer(a)) socket.emit('back');
  });

  // expect sent blob mixed with json to be buffer
  socket.on('jsonblob', function(a) {
    expect(a.hello).to.eql('lol');
    expect(Buffer.isBuffer(a.message)).to.be(true);
    expect(a.goodbye).to.eql('gotcha');
    socket.emit('jsonblob-ack');
  });

  // expect blobs sent in order to arrive in correct order
  var receivedblob1 = false;
  var receivedblob2 = false;
  socket.on('blob1', function(a) {
    expect(Buffer.isBuffer(a)).to.be(true);
    receivedblob1 = true;
  });
  socket.on('blob2', function(a) {
    expect(receivedblob1).to.be(true);
    expect(a).to.eql('second');
    receivedblob2 = true;
  });
  socket.on('blob3', function(a) {
    expect(Buffer.isBuffer(a)).to.be(true);
    expect(receivedblob1).to.be(true);
    expect(receivedblob2).to.be(true);
    socket.emit('blob3-ack');
  });

  // emit buffer to base64 receiving browsers
  socket.on('getbin', function() {
    buf = new Buffer('asdfasdf', 'utf8');
    socket.emit('takebin', buf);
  });
});
<|endoftext|>


<commit_before>var bap = require('../index');

function metronome () {
  var kit = bap.kit();
  var basic = bap.oscillator({
    attack: 0.001,
    release: 0.1,
    length: 0.08
  });

  // shorthand, add copy of oscillator as layer on first slot
  kit.slot('Q').layer(basic.with({ frequency: 330 }));

  // more verbose: create slot, append oscillator, then assign to kit
  var nextSlot = bap.slot();
  nextSlot.layer(basic.with({ frequency: 440 }));
  kit.slot('W', nextSlot);

  // create the pattern and add notes using expressions
  var pattern = bap.pattern({ bars: 2, tempo: 140 });
  pattern.channel(1).add(
    ['*.1.01',   '1Q'],
    ['*.2%1.01', '1W']
  );

  // var step = 500;
  // function one () {
  //   kit.slot('Q').start();
  //   setTimeout(two, step);
  // }
  // function two () {
  //   kit.slot('W').start();
  //   setTimeout(three, step);
  // }
  // function three () {
  //   kit.slot('W').start();
  //   setTimeout(four, step);
  // }
  // function four () {
  //   kit.slot('W').start();
  //   setTimeout(one, step);
  // }
  //
  // setTimeout(one, 1000);
  bap.clock.sequence = pattern.kit(kit);
}

module.exports = metronome;
<commit_msg>clean up metronome<commit_after>var bap = require('../index');

function metronome () {
  var kit = bap.kit();
  var basic = bap.oscillator({
    attack: 0.001,
    release: 0.1,
    length: 0.08
  });

  // shorthand, add copy of oscillator as layer on first slot
  kit.slot('Q').layer(basic.with({ frequency: 330 }));

  // more verbose: create slot, append oscillator, then assign to kit
  var nextSlot = bap.slot();
  nextSlot.layer(basic.with({ frequency: 440 }));
  kit.slot('W', nextSlot);

  // create the pattern and add notes using expressions
  var pattern = bap.pattern({ bars: 2, tempo: 140 });
  pattern.channel(1).add(
    ['*.1.01',   '1Q'],
    ['*.2%1.01', '1W']
  );

  bap.clock.sequence = pattern.kit(kit);
}

module.exports = metronome;
<|endoftext|>