<commit_before>/**
 * @file Mouse Observer
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @private
 */

import { Vector2 } from "../../lib/three.es6.js";
import Signal from "../../lib/signals.es6.js";

import { defaults } from "../utils.js";

/**
 * @example
 * mouseObserver.signals.scroll.add( function( delta ){ ... } );
 *
 * @typedef {Object} MouseSignals
 * @property {Signal<Integer, Integer>} moved - on move: deltaX, deltaY
 * @property {Signal<Number>} scrolled - on scroll: delta
 * @property {Signal<Integer, Integer>} dragged - on drag: deltaX, deltaY
 * @property {Signal} dropped - on drop
 * @property {Signal} clicked - on click
 * @property {Signal} hovered - on hover
 */

/**
 * Mouse observer
 */
class MouseObserver{

    /**
     * @param  {Element} domElement - the dom element to observe mouse events in
     * @param  {Object} params - parameters object
     * @param  {Integer} params.hoverTimeout - timeout until the {@link MouseSignals.hovered}
     *                                         signal is fired, set to -1 to ignore hovering
     */
    constructor( domElement, params ){

        /**
         * Events emitted by the mouse observer
         * @type {MouseSignals}
         */
        this.signals = {
            moved: new Signal(),
            scrolled: new Signal(),
            dragged: new Signal(),
            dropped: new Signal(),
            clicked: new Signal(),
            hovered: new Signal()
        };

        var p = Object.assign( {}, params );

        this.hoverTimeout = defaults( p.hoverTimeout, 50 );

        this.domElement = domElement;

        /**
         * Position on page
         * @type {Vector2}
         */
        this.position = new Vector2();
        /**
         * Previous position on page
         * @type {Vector2}
         */
        this.prevPosition = new Vector2();
        /**
         * Position on page when clicked
         * @type {Vector2}
         */
        this.down = new Vector2();
        /**
         * Position on dom element
         * @type {Vector2}
         */
        this.canvasPosition = new Vector2();
        /**
         * Flag indicating if the mouse is moving
         * @type {Boolean}
         */
        this.moving = false;
        /**
         * Flag indicating if the mouse is hovering
         * @type {Boolean}
         */
        this.hovering = true;
        /**
         * Flag indicating if there was a scolling event
         * since the last mouse move
         * @type {Boolean}
         */
        this.scrolled = false;
        /**
         * Timestamp of last mouse move
         * @type {Number}
         */
        this.lastMoved = Infinity;
        /**
         * Indicates which mouse button was pressed:
         * 0: No button; 1: Left button; 2: Middle button; 3: Right button
         * @type {Integer}
         */
        this.which = undefined;
        /**
         * Flag indicating if the mouse is pressed down
         * @type {Boolean}
         */
        this.pressed = undefined;
        /**
         * Flag indicating if the alt key is pressed
         * @type {Boolean}
         */
        this.altKey = undefined;
        /**
         * Flag indicating if the ctrl key is pressed
         * @type {Boolean}
         */
        this.ctrlKey = undefined;
        /**
         * Flag indicating if the meta key is pressed
         * @type {Boolean}
         */
        this.metaKey = undefined;
        /**
         * Flag indicating if the shift key is pressed
         * @type {Boolean}
         */
        this.shiftKey = undefined;

        this._listen = this._listen.bind( this );
        this._onMousewheel = this._onMousewheel.bind( this );
        this._onMousemove = this._onMousemove.bind( this );
        this._onMousedown = this._onMousedown.bind( this );
        this._onMouseup = this._onMouseup.bind( this );

        this.listen();

        domElement.addEventListener( 'mousewheel', this._onMousewheel );
        domElement.addEventListener( 'wheel', this._onMousewheel );
        domElement.addEventListener( 'MozMousePixelScroll', this._onMousewheel );
        domElement.addEventListener( 'mousemove', this._onMousemove );
        domElement.addEventListener( 'mousedown', this._onMousedown );
        domElement.addEventListener( 'mouseup', this._onMouseup );
        domElement.addEventListener( 'contextmenu', this._onContextmenu );

    }

    setParameters( params ){
        var p = Object.assign( {}, params );
        this.hoverTimeout = defaults( p.hoverTimeout, this.hoverTimeout );
    }

    /**
     * listen to mouse actions
     * @emits {MouseSignals.hovered} when hovered
     * @return {undefined}
     */
    _listen(){
        if( performance.now() - this.lastMoved > this.hoverTimeout ){
            this.moving = false;
        }
        if( this.scrolled || ( !this.moving && !this.hovering ) ){
            this.scrolled = false;
            if( this.hoverTimeout !== -1 ){
                this.hovering = true;
                this.signals.hovered.dispatch();
            }
        }
        requestAnimationFrame( this.listen );
    }

    /**
     * handle mouse scroll
     * @emits {MouseSignals.scrolled} when scrolled
     * @param  {Event} event - mouse event
     * @return {undefined}
     */
    _onMousewheel( event ){
        event.preventDefault();
        this._setKeys( event );

        var delta = 0;
        if( event.wheelDelta ){
            // WebKit / Opera / Explorer 9
            delta = event.wheelDelta / 40;
        }else if( event.detail ){
            // Firefox
            delta = - event.detail / 3;
        }else{
            // Firefox or IE 11
            delta = - event.deltaY / ( event.deltaMode ? 0.33 : 30 );
        }

        this.signals.scrolled.dispatch( delta );

        setTimeout( () => {
            this.scrolled = true;
        }, this.hoverTimeout );
    }

    /**
     * handle mouse move
     * @emits {MouseSignals.moved} when moved
     * @emits {MouseSignals.dragged} when dragged
     * @param  {Event} event - mouse event
     * @return {undefined}
     */
    _onMousemove( event ){
        event.preventDefault();
        this._setKeys( event );
        this.moving = true;
        this.hovering = false;
        this.lastMoved = performance.now();
        this.prevPosition.copy( this.position );
        this.position.set( event.layerX, event.layerY );
        this._setCanvasPosition( event );
        var x = this.prevPosition.x - this.position.x;
        var y = this.prevPosition.y - this.position.y;
        this.signals.moved.dispatch( x, y );
        if( this.pressed ){
            this.signals.dragged.dispatch( x, y );
        }
    }

    _onMousedown( event ){
        event.preventDefault();
        this._setKeys( event );
        this.moving = false;
        this.hovering = false;
        this.down.set( event.layerX, event.layerY );
        this.which = event.which;
        this.pressed = true;
        this.setCanvasPosition( event );
    }

    /**
     * handle mouse up
     * @emits {MouseSignals.clicked} when clicked
     * @emits {MouseSignals.dropped} when dropped
     * @param  {Event} event - mouse event
     * @return {undefined}
     */
    _onMouseup( event ){
        event.preventDefault();
        this._setKeys( event );
        this.signals.clicked.dispatch();
        // if( this.distance() > 3 || event.which === RightMouseButton ){
        //     this.signals.dropped.dispatch();
        // }
        this.which = undefined;
        this.pressed = undefined;
    }

    _onContextmenu( event ){
        event.preventDefault();
    }

    _distance(){
        return this.position.distanceTo( this.down );
    }

    _setCanvasPosition( event ){
        var box = this.domElement.getBoundingClientRect();
        var offsetX = event.clientX - box.left;
        var offsetY = event.clientY - box.top;
        this.canvasPosition.set( offsetX, box.height - offsetY );
    }

    _setKeys( event ){
        this.altKey = event.altKey;
        this.ctrlKey = event.ctrlKey;
        this.metaKey = event.metaKey;
        this.shiftKey = event.shiftKey;
    }

    dispose(){
        var domElement = this.domElement;
        domElement.removeEventListener( 'mousewheel', this._onMousewheel );
        domElement.removeEventListener( 'wheel', this._onMousewheel );
        domElement.removeEventListener( 'MozMousePixelScroll', this._onMousewheel );
        domElement.removeEventListener( 'mousemove', this._onMousemove );
        domElement.removeEventListener( 'mousedown', this._onMousedown );
        domElement.removeEventListener( 'mouseup', this._onMouseup );
        domElement.removeEventListener( 'contextmenu', this._onContextmenu );
    }

}

export default MouseObserver;
<commit_msg>method name typo<commit_after>/**
 * @file Mouse Observer
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @private
 */

import { Vector2 } from "../../lib/three.es6.js";
import Signal from "../../lib/signals.es6.js";

import { defaults } from "../utils.js";

/**
 * @example
 * mouseObserver.signals.scroll.add( function( delta ){ ... } );
 *
 * @typedef {Object} MouseSignals
 * @property {Signal<Integer, Integer>} moved - on move: deltaX, deltaY
 * @property {Signal<Number>} scrolled - on scroll: delta
 * @property {Signal<Integer, Integer>} dragged - on drag: deltaX, deltaY
 * @property {Signal} dropped - on drop
 * @property {Signal} clicked - on click
 * @property {Signal} hovered - on hover
 */

/**
 * Mouse observer
 */
class MouseObserver{

    /**
     * @param  {Element} domElement - the dom element to observe mouse events in
     * @param  {Object} params - parameters object
     * @param  {Integer} params.hoverTimeout - timeout until the {@link MouseSignals.hovered}
     *                                         signal is fired, set to -1 to ignore hovering
     */
    constructor( domElement, params ){

        /**
         * Events emitted by the mouse observer
         * @type {MouseSignals}
         */
        this.signals = {
            moved: new Signal(),
            scrolled: new Signal(),
            dragged: new Signal(),
            dropped: new Signal(),
            clicked: new Signal(),
            hovered: new Signal()
        };

        var p = Object.assign( {}, params );

        this.hoverTimeout = defaults( p.hoverTimeout, 50 );

        this.domElement = domElement;

        /**
         * Position on page
         * @type {Vector2}
         */
        this.position = new Vector2();
        /**
         * Previous position on page
         * @type {Vector2}
         */
        this.prevPosition = new Vector2();
        /**
         * Position on page when clicked
         * @type {Vector2}
         */
        this.down = new Vector2();
        /**
         * Position on dom element
         * @type {Vector2}
         */
        this.canvasPosition = new Vector2();
        /**
         * Flag indicating if the mouse is moving
         * @type {Boolean}
         */
        this.moving = false;
        /**
         * Flag indicating if the mouse is hovering
         * @type {Boolean}
         */
        this.hovering = true;
        /**
         * Flag indicating if there was a scolling event
         * since the last mouse move
         * @type {Boolean}
         */
        this.scrolled = false;
        /**
         * Timestamp of last mouse move
         * @type {Number}
         */
        this.lastMoved = Infinity;
        /**
         * Indicates which mouse button was pressed:
         * 0: No button; 1: Left button; 2: Middle button; 3: Right button
         * @type {Integer}
         */
        this.which = undefined;
        /**
         * Flag indicating if the mouse is pressed down
         * @type {Boolean}
         */
        this.pressed = undefined;
        /**
         * Flag indicating if the alt key is pressed
         * @type {Boolean}
         */
        this.altKey = undefined;
        /**
         * Flag indicating if the ctrl key is pressed
         * @type {Boolean}
         */
        this.ctrlKey = undefined;
        /**
         * Flag indicating if the meta key is pressed
         * @type {Boolean}
         */
        this.metaKey = undefined;
        /**
         * Flag indicating if the shift key is pressed
         * @type {Boolean}
         */
        this.shiftKey = undefined;

        this._listen = this._listen.bind( this );
        this._onMousewheel = this._onMousewheel.bind( this );
        this._onMousemove = this._onMousemove.bind( this );
        this._onMousedown = this._onMousedown.bind( this );
        this._onMouseup = this._onMouseup.bind( this );

        this._listen();

        domElement.addEventListener( 'mousewheel', this._onMousewheel );
        domElement.addEventListener( 'wheel', this._onMousewheel );
        domElement.addEventListener( 'MozMousePixelScroll', this._onMousewheel );
        domElement.addEventListener( 'mousemove', this._onMousemove );
        domElement.addEventListener( 'mousedown', this._onMousedown );
        domElement.addEventListener( 'mouseup', this._onMouseup );
        domElement.addEventListener( 'contextmenu', this._onContextmenu );

    }

    setParameters( params ){
        var p = Object.assign( {}, params );
        this.hoverTimeout = defaults( p.hoverTimeout, this.hoverTimeout );
    }

    /**
     * listen to mouse actions
     * @emits {MouseSignals.hovered} when hovered
     * @return {undefined}
     */
    _listen(){
        if( performance.now() - this.lastMoved > this.hoverTimeout ){
            this.moving = false;
        }
        if( this.scrolled || ( !this.moving && !this.hovering ) ){
            this.scrolled = false;
            if( this.hoverTimeout !== -1 ){
                this.hovering = true;
                this.signals.hovered.dispatch();
            }
        }
        requestAnimationFrame( this.listen );
    }

    /**
     * handle mouse scroll
     * @emits {MouseSignals.scrolled} when scrolled
     * @param  {Event} event - mouse event
     * @return {undefined}
     */
    _onMousewheel( event ){
        event.preventDefault();
        this._setKeys( event );

        var delta = 0;
        if( event.wheelDelta ){
            // WebKit / Opera / Explorer 9
            delta = event.wheelDelta / 40;
        }else if( event.detail ){
            // Firefox
            delta = - event.detail / 3;
        }else{
            // Firefox or IE 11
            delta = - event.deltaY / ( event.deltaMode ? 0.33 : 30 );
        }

        this.signals.scrolled.dispatch( delta );

        setTimeout( () => {
            this.scrolled = true;
        }, this.hoverTimeout );
    }

    /**
     * handle mouse move
     * @emits {MouseSignals.moved} when moved
     * @emits {MouseSignals.dragged} when dragged
     * @param  {Event} event - mouse event
     * @return {undefined}
     */
    _onMousemove( event ){
        event.preventDefault();
        this._setKeys( event );
        this.moving = true;
        this.hovering = false;
        this.lastMoved = performance.now();
        this.prevPosition.copy( this.position );
        this.position.set( event.layerX, event.layerY );
        this._setCanvasPosition( event );
        var x = this.prevPosition.x - this.position.x;
        var y = this.prevPosition.y - this.position.y;
        this.signals.moved.dispatch( x, y );
        if( this.pressed ){
            this.signals.dragged.dispatch( x, y );
        }
    }

    _onMousedown( event ){
        event.preventDefault();
        this._setKeys( event );
        this.moving = false;
        this.hovering = false;
        this.down.set( event.layerX, event.layerY );
        this.which = event.which;
        this.pressed = true;
        this.setCanvasPosition( event );
    }

    /**
     * handle mouse up
     * @emits {MouseSignals.clicked} when clicked
     * @emits {MouseSignals.dropped} when dropped
     * @param  {Event} event - mouse event
     * @return {undefined}
     */
    _onMouseup( event ){
        event.preventDefault();
        this._setKeys( event );
        this.signals.clicked.dispatch();
        // if( this.distance() > 3 || event.which === RightMouseButton ){
        //     this.signals.dropped.dispatch();
        // }
        this.which = undefined;
        this.pressed = undefined;
    }

    _onContextmenu( event ){
        event.preventDefault();
    }

    _distance(){
        return this.position.distanceTo( this.down );
    }

    _setCanvasPosition( event ){
        var box = this.domElement.getBoundingClientRect();
        var offsetX = event.clientX - box.left;
        var offsetY = event.clientY - box.top;
        this.canvasPosition.set( offsetX, box.height - offsetY );
    }

    _setKeys( event ){
        this.altKey = event.altKey;
        this.ctrlKey = event.ctrlKey;
        this.metaKey = event.metaKey;
        this.shiftKey = event.shiftKey;
    }

    dispose(){
        var domElement = this.domElement;
        domElement.removeEventListener( 'mousewheel', this._onMousewheel );
        domElement.removeEventListener( 'wheel', this._onMousewheel );
        domElement.removeEventListener( 'MozMousePixelScroll', this._onMousewheel );
        domElement.removeEventListener( 'mousemove', this._onMousemove );
        domElement.removeEventListener( 'mousedown', this._onMousedown );
        domElement.removeEventListener( 'mouseup', this._onMouseup );
        domElement.removeEventListener( 'contextmenu', this._onContextmenu );
    }

}

export default MouseObserver;
<|endoftext|>


<commit_before>'use strict';

var http = require('superagent'),
  _ = require('lodash'),
  Q = require('q');

var neo4j_server_url = process.env.GRAPHENEDB_URL || 'http://localhost:7474';
var url = neo4j_server_url + '/db/data';

var XEBIAN_TYPE = 'XEBIAN';
var SKILL_TYPE = 'SKILL';

var KNOWS = 'KNOWS';

var credentialsNEO4J = url.match(/^https?:\/\/(.*)@/)[1] || null;

var getCypherQuery = function() {
  return http
    .post(url + '/cypher')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json');
};

var createNodePromise = function(nodeType, nodeData) {
  var deferred = Q.defer();
  getCypherQuery()
    .send({
      'query': 'CREATE (n:' + nodeType + ' { props } ) RETURN n',
      'params': {
        'props': nodeData
      }
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('created node: ' + res.body.data[0][0].self);
        deferred.resolve(res.body.data[0][0].self);
      }
    });
  return deferred.promise;
};

exports.createXebian = function(user) {
  var xebian = {
    'email': user.email,
    'firstName': user.firstName,
    'lastName': user.lastName,
    'displayName': user.displayName
  };
  return createNodePromise(XEBIAN_TYPE, xebian);
};

exports.createSkill = function(skillName) {
  var skill = {
    'name': skillName
  };
  return createNodePromise(SKILL_TYPE, skill);
};

exports.deleteNode = function(nodeUrl) {
  var deferred = Q.defer();
  http
    .del(nodeUrl)
    .end(function(res){
      console.log('deleted node: ' + nodeUrl + ' with status ' + res.statusCode);
      deferred.resolve(res);
  });
  return deferred.promise;
};

var findPromise = function(query) {
  console.log('Cypher find query: ' + JSON.stringify(query));
  var deferred = Q.defer();
  getCypherQuery()
    .send(query)
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('query result: ' + JSON.stringify(res.body.data));
        if (_.isEmpty(res.body.data)) {
          deferred.resolve(null);
        } else {
          deferred.resolve(res.body.data);
        }
      }
    });
  return deferred.promise;
};

exports.findXebian = function(email) {
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+') WHERE n.email = {email} RETURN n',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);
};

exports.findXebianSkillz = function(email){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[:`'+KNOWS+'`]->s WHERE n.email = {email} RETURN s',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);

};

exports.findXebiansBySkillz = function (skillName){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[r:`'+KNOWS+'`]->s WHERE s.name= {skillName} RETURN n,r, s',
    'params' : {
      'skillName': skillName
    }
  };
  return findPromise(query);
};

exports.findSkill = function(name) {
  var query = {
    'query': 'MATCH (n: '+SKILL_TYPE+' ) WHERE n.name= {name} RETURN n',
    'params': {
      'name': name
    }
  };
  return findPromise(query);
};

exports.associateSkillToUser = function(userNodeUrl, skillNodeUrl) {
  console.log('userNodeUrl: ' + userNodeUrl);
  console.log('skillNodeUrl: ' + skillNodeUrl);

  var securedURL = userNodeUrl.replace(/:\/\//g,'://' + credentialsNEO4J + '@');

  console.log(securedURL);

  var deferred = Q.defer();
  http
    .post(securedURL + '/relationships')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json')
    .send({
      'to' : skillNodeUrl,
      'type' : 'KNOWS'
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('associateSkillToUser', res.statusCode, JSON.stringify(res.body) );
        deferred.resolve(res.body.self);
      }
    });
  return deferred.promise;
};
<commit_msg>Add insensitive case search and CONTAINS<commit_after>'use strict';

var http = require('superagent'),
  _ = require('lodash'),
  Q = require('q');

var neo4j_server_url = process.env.GRAPHENEDB_URL || 'http://localhost:7474';
var url = neo4j_server_url + '/db/data';

var XEBIAN_TYPE = 'XEBIAN';
var SKILL_TYPE = 'SKILL';

var KNOWS = 'KNOWS';

var credentialsNEO4J = url.match(/^https?:\/\/(.*)@/)[1] || null;

var getCypherQuery = function() {
  return http
    .post(url + '/cypher')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json');
};

var createNodePromise = function(nodeType, nodeData) {
  var deferred = Q.defer();
  getCypherQuery()
    .send({
      'query': 'CREATE (n:' + nodeType + ' { props } ) RETURN n',
      'params': {
        'props': nodeData
      }
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('created node: ' + res.body.data[0][0].self);
        deferred.resolve(res.body.data[0][0].self);
      }
    });
  return deferred.promise;
};

exports.createXebian = function(user) {
  var xebian = {
    'email': user.email,
    'firstName': user.firstName,
    'lastName': user.lastName,
    'displayName': user.displayName
  };
  return createNodePromise(XEBIAN_TYPE, xebian);
};

exports.createSkill = function(skillName) {
  var skill = {
    'name': skillName
  };
  return createNodePromise(SKILL_TYPE, skill);
};

exports.deleteNode = function(nodeUrl) {
  var deferred = Q.defer();
  http
    .del(nodeUrl)
    .end(function(res){
      console.log('deleted node: ' + nodeUrl + ' with status ' + res.statusCode);
      deferred.resolve(res);
  });
  return deferred.promise;
};

var findPromise = function(query) {
  console.log('Cypher find query: ' + JSON.stringify(query));
  var deferred = Q.defer();
  getCypherQuery()
    .send(query)
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('query result: ' + JSON.stringify(res.body.data));
        if (_.isEmpty(res.body.data)) {
          deferred.resolve(null);
        } else {
          deferred.resolve(res.body.data);
        }
      }
    });
  return deferred.promise;
};

exports.findXebian = function(email) {
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+') WHERE n.email = {email} RETURN n',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);
};

exports.findXebianSkillz = function(email){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[:`'+KNOWS+'`]->s WHERE n.email = {email} RETURN s',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);

};

exports.findXebiansBySkillz = function (skillName){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[r:`'+KNOWS+'`]->s WHERE s.name=~ \'(?i).*'+skillName+'.*\' RETURN n,r, s'
  };
  return findPromise(query);
};

exports.findSkill = function(name) {
  var query = {
    'query': 'MATCH (n: '+SKILL_TYPE+' ) WHERE n.name= {name} RETURN n',
    'params': {
      'name': name
    }
  };
  return findPromise(query);
};

exports.associateSkillToUser = function(userNodeUrl, skillNodeUrl) {
  console.log('userNodeUrl: ' + userNodeUrl);
  console.log('skillNodeUrl: ' + skillNodeUrl);

  var securedURL = userNodeUrl.replace(/:\/\//g,'://' + credentialsNEO4J + '@');

  console.log(securedURL);

  var deferred = Q.defer();
  http
    .post(securedURL + '/relationships')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json')
    .send({
      'to' : skillNodeUrl,
      'type' : 'KNOWS'
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('associateSkillToUser', res.statusCode, JSON.stringify(res.body) );
        deferred.resolve(res.body.self);
      }
    });
  return deferred.promise;
};
<|endoftext|>


<commit_before>'use strict';

var http = require('superagent'),
  _ = require('lodash'),
  Q = require('q');

var neo4j_server_url = process.env.GRAPHENEDB_URL || 'http://localhost:7474';
var url = neo4j_server_url + '/db/data';

console.log('NEO4J: ',neo4j_server_url);

var XEBIAN_TYPE = 'XEBIAN';
var SKILL_TYPE = 'SKILL';

var KNOWS = 'KNOWS';

var credentialsNEO4J;

var credentialsRegexp = /^https?:\/\/(.*)@/;

var isSecuredDatabase = function(){
  return credentialsRegexp.test(url);
};

if(isSecuredDatabase()){
  credentialsNEO4J = url.match()[1];
}else{
  credentialsNEO4J = '';
}

var makeURLSecured = function(url){
  if(isSecuredDatabase()){
    return url.replace(/:\/\//g,'://' + credentialsNEO4J + '@');
  }else{
    return url;
  }
};

var getCypherQuery = function() {
  return http
    .post(url + '/cypher')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json');
};

var createNodePromise = function(nodeType, nodeData) {
  var deferred = Q.defer();
  getCypherQuery()
    .send({
      'query': 'CREATE (n:' + nodeType + ' { props } ) RETURN n',
      'params': {
        'props': nodeData
      }
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('created node: ' + res.body.data[0][0].self);
        deferred.resolve(res.body.data[0][0].self);
      }
    });
  return deferred.promise;
};

exports.createXebian = function(user) {
  var xebian = {
    'email': user.email,
    'firstName': user.firstName,
    'lastName': user.lastName,
    'displayName': user.displayName
  };
  return createNodePromise(XEBIAN_TYPE, xebian);
};

exports.createSkill = function(skillName) {
  var skill = {
    'name': skillName
  };
  return createNodePromise(SKILL_TYPE, skill);
};

exports.deleteNode = function(nodeUrl) {
  var deferred = Q.defer();
  http
    .del(nodeUrl)
    .end(function(res){
      console.log('deleted node: ' + nodeUrl + ' with status ' + res.statusCode);
      deferred.resolve(res);
  });
  return deferred.promise;
};

var findPromise = function(query) {
  console.log('Cypher find query: ' + JSON.stringify(query));
  var deferred = Q.defer();
  getCypherQuery()
    .send(query)
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('query result: ' + JSON.stringify(res.body.data));
        if (_.isEmpty(res.body.data)) {
          deferred.resolve(null);
        } else {
          deferred.resolve(res.body.data);
        }
      }
    });
  return deferred.promise;
};

exports.findXebian = function(email) {
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+') WHERE n.email = {email} RETURN n',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);
};

exports.findXebianSkillz = function(email){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[:`'+KNOWS+'`]->s WHERE n.email = {email} RETURN s',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);

};

exports.findXebiansBySkillz = function (skillName){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[r:`'+KNOWS+'`]->s WHERE s.name=~ \'(?i).*'+skillName+'.*\' RETURN n,r, s'
  };
  return findPromise(query);
};

exports.findSkill = function(name) {
  var query = {
    'query': 'MATCH (n: '+SKILL_TYPE+' ) WHERE n.name= {name} RETURN n',
    'params': {
      'name': name
    }
  };
  return findPromise(query);
};

exports.associateSkillToUser = function(userNodeUrl, skillNodeUrl) {
  var securedURL = makeURLSecured(userNodeUrl);

  var deferred = Q.defer();
  http
    .post(securedURL + '/relationships')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json')
    .send({
      'to' : skillNodeUrl,
      'type' : 'KNOWS'
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('associateSkillToUser', res.statusCode );
        deferred.resolve(res.body.self);
      }
    });
  return deferred.promise;
};
<commit_msg>Use query params in findXebiansBySkillz<commit_after>'use strict';

var http = require('superagent'),
  _ = require('lodash'),
  Q = require('q');

var neo4j_server_url = process.env.GRAPHENEDB_URL || 'http://localhost:7474';
var url = neo4j_server_url + '/db/data';

console.log('NEO4J: ',neo4j_server_url);

var XEBIAN_TYPE = 'XEBIAN';
var SKILL_TYPE = 'SKILL';

var KNOWS = 'KNOWS';

var credentialsNEO4J;

var credentialsRegexp = /^https?:\/\/(.*)@/;

var isSecuredDatabase = function(){
  return credentialsRegexp.test(url);
};

if(isSecuredDatabase()){
  credentialsNEO4J = url.match()[1];
}else{
  credentialsNEO4J = '';
}

var makeURLSecured = function(url){
  if(isSecuredDatabase()){
    return url.replace(/:\/\//g,'://' + credentialsNEO4J + '@');
  }else{
    return url;
  }
};

var getCypherQuery = function() {
  return http
    .post(url + '/cypher')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json');
};

var createNodePromise = function(nodeType, nodeData) {
  var deferred = Q.defer();
  getCypherQuery()
    .send({
      'query': 'CREATE (n:' + nodeType + ' { props } ) RETURN n',
      'params': {
        'props': nodeData
      }
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('created node: ' + res.body.data[0][0].self);
        deferred.resolve(res.body.data[0][0].self);
      }
    });
  return deferred.promise;
};

exports.createXebian = function(user) {
  var xebian = {
    'email': user.email,
    'firstName': user.firstName,
    'lastName': user.lastName,
    'displayName': user.displayName
  };
  return createNodePromise(XEBIAN_TYPE, xebian);
};

exports.createSkill = function(skillName) {
  var skill = {
    'name': skillName
  };
  return createNodePromise(SKILL_TYPE, skill);
};

exports.deleteNode = function(nodeUrl) {
  var deferred = Q.defer();
  http
    .del(nodeUrl)
    .end(function(res){
      console.log('deleted node: ' + nodeUrl + ' with status ' + res.statusCode);
      deferred.resolve(res);
  });
  return deferred.promise;
};

var findPromise = function(query) {
  console.log('Cypher find query: ' + JSON.stringify(query));
  var deferred = Q.defer();
  getCypherQuery()
    .send(query)
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('query result: ' + JSON.stringify(res.body.data));
        if (_.isEmpty(res.body.data)) {
          deferred.resolve(null);
        } else {
          deferred.resolve(res.body.data);
        }
      }
    });
  return deferred.promise;
};

exports.findXebian = function(email) {
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+') WHERE n.email = {email} RETURN n',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);
};

exports.findXebianSkillz = function(email){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[:`'+KNOWS+'`]->s WHERE n.email = {email} RETURN s',
    'params' : {
      'email': email
    }
  };
  return findPromise(query);

};

exports.findXebiansBySkillz = function (skillName){
  var query = {
    'query' : 'MATCH (n: '+XEBIAN_TYPE+')-[r:`'+KNOWS+'`]->s WHERE s.name=~ {q} RETURN n,r, s',
    'params': {
      'q': '(?i).*' + skillName + '.*'
    }
  };
  return findPromise(query);
};

exports.findSkill = function(name) {
  var query = {
    'query': 'MATCH (n: '+SKILL_TYPE+' ) WHERE n.name= {name} RETURN n',
    'params': {
      'name': name
    }
  };
  return findPromise(query);
};

exports.associateSkillToUser = function(userNodeUrl, skillNodeUrl) {
  var securedURL = makeURLSecured(userNodeUrl);

  var deferred = Q.defer();
  http
    .post(securedURL + '/relationships')
    .set('Accept', 'application/json; charset=UTF-8')
    .set('Content-Type', 'application/json')
    .send({
      'to' : skillNodeUrl,
      'type' : 'KNOWS'
    })
    .end(function(err, res) {
      if (err) {
        deferred.reject(err);
      } else {
        console.log('associateSkillToUser', res.statusCode );
        deferred.resolve(res.body.self);
      }
    });
  return deferred.promise;
};
<|endoftext|>


<commit_before>
settings.primaryColor = "#E0F4F4";
settings.primaryLight = "#F2FFFF";
//settings.autocomplete = false;
settings.lemgramSelect = false;
settings.wordpicture = false;

$("#lemgram_list_item").remove();
$("#results-lemgram").remove();
$("#showLineDiagram").remove();

settings.corpora = {};
settings.corporafolders = {};
settings.corpora["digidaily"] = {
    morf : 'saldom|dalinm',
	id : "digidaily",
	title : "Digidaily - tets ",
	description : "",
	within : settings.defaultWithin,
	context : settings.spContext,
	attributes : {
    	posset :  settings.posset,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix
	},
	struct_attributes : {
		text_title : {
			label : "title"},
		text_date : {label : "date"}
	//	text_edition : {label : "edition"}
	}
};

settings.corpusListing = new CorpusListing(settings.corpora);

function getAnnotationRank(anno) {
	return {
		"word" : 1,
		"gf" : 2,
		"lemgram" : 3,
		"sense" : 4
	}[anno] || 5;
}

<commit_msg>digidaily mode<commit_after>
settings.primaryColor = "#E0F4F4";
settings.primaryLight = "#F2FFFF";
//settings.autocomplete = false;
settings.lemgramSelect = false;
settings.wordpicture = false;

$("#lemgram_list_item").remove();
$("#results-lemgram").remove();
$("#showLineDiagram").remove();

settings.corpora = {};
settings.corporafolders = {};
settings.corpora["digidaily"] = {
    morf : 'saldom|dalinm',
	id : "digidaily",
	title : "Digidaily - test ",
	description : "",
	within : settings.defaultWithin,
	context : settings.spContext,
	attributes : {
    	posset :  settings.posset,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix
	},
	struct_attributes : {
		text_title : {
			label : "title"},
		text_date : {label : "date"}
	//	text_edition : {label : "edition"}
	}
};

settings.corpusListing = new CorpusListing(settings.corpora);

function getAnnotationRank(anno) {
	return {
		"word" : 1,
		"gf" : 2,
		"lemgram" : 3,
		"sense" : 4
	}[anno] || 5;
}

<|endoftext|>


<commit_before>
(function($) {

    window.console = (window.console || { log: function() {}, error: function() {}});

    var app = window.pig = {
        categories: {},
        $messageNode: null,

        init: function(page, options) {
            options = (options || {});

            console.log("Starting piggy client on '" + page + "' page", options);

            app.$messageNode = $("aside.messages");

            if (app[page] && app[page].init && app[page].init.apply) {
                app[page].init.apply(app[page], [options]);
            }

        },

        main: {
            init: function() {
                app.main.$acctBalance = $("#page_account .amount");
                app.main.$recentTrans = $("div.recentTrans");
                app.main.$recentTransCount = $(".recentTransCount");

                $("form[action=\\/transaction\\/add]")
                    .on("submit", this.handleAddTransaction)
                    .find("[required]")
                        .on("invalid", function() {
                            $(this)
                                .closest("form")
                                    .find(".ui-submit")
                                        .removeClass("ui-btn-active");
                        });
            },

            handleAddTransaction: function(e) {
                var form = $(this),
                    data = {};

                e.preventDefault();

                app.alerts.clearAll();

                form.serializeArray().forEach(function(item) {
                    data[item.name] = item.value;
                });

                if (!Number(data.amount)) {
                    app.alerts.error("Please enter an amount (greater than zero)");
                    form.find(".ui-submit").removeClass("ui-btn-active");
                    return false;
                }
                data.amount = Number(data.amount);

                // if an expense, flip the amount to negative
                if (form.find("[name=amount]").hasClass("expense") && data.amount > 0) {
                    data.amount *= -1;
                }

                app.trans.add(data, {
                    success: function(trans) {
                        console.log(trans);

                        var balance = Number(app.main.$acctBalance.text().substr(1)),
                            transDiv = $("
");

                        if (balance) {
                            app.main.$acctBalance.text("$" + (balance + trans.amount).toFixed(2));
                        }

                        app.main.$recentTrans.find(".ui-first-child").removeClass("ui-first-child");

                        transDiv.append(
                            "
$" + trans.amount.toFixed(2) + " " + trans.dateDisplay + "
" +
                            "
" + trans.description + "
" +
                            "
" + app.categories[trans.category] + "
"
                        );
                        app.main.$recentTrans.prepend(transDiv);
                        transDiv.collapsible();
                        app.main.$recentTransCount.text(Number(app.main.$recentTransCount.text()) + 1);

                        app.alerts.success("Transaction added successfully!");
                        form.find("[name=description]").val("");
                        form.find("[name=amount]").val("").focus();
                        form.find(".ui-submit").removeClass("ui-btn-active");
                    },
                    error: function(err) {
                        app.alerts.error(err);
                        form.find(".ui-submit").removeClass("ui-btn-active");
                    }
                });

                return false;
            }

        },

        login: {
            $account: null,
            $lock: null,

            init: function() {
                var loc;

                $("form[action=\\/account\\/login]").on("submit", function(e) {
                    console.error("Login form submission (should not occur)");
                    e.preventDefault();
                    return false;
                });

                app.login.$account = $("[name=account]");
                app.login.$lock = $(".pattern-lock");

                if (window.location.hash) {
                    loc = $("[name=location]");
                    loc.val(loc.val() + window.location.hash);
                }

                if (localStorage.account && !app.login.$account.val().length) {
                    app.login.$account.val(localStorage.account).blur();
                }

                app.login.$lock.patternInput({
                    onFinish: this.handleLoginPattern
                });
            },

            handleLoginPattern: function(pattern) {
                app.alerts.clearAll();

                app.login.$account.attr("disabled", "disabled");
                app.login.$lock.hide();

                app.alerts.info("Working...");

                $.ajax({
                    url: "/account/login",
                    type: "post",
                    data: {
                        owner: app.login.$account.val(),
                        pattern: pattern.join("")
                    },
                    dataType: "json",
                    success: app.ajaxSuccess(app.login.success, app.login.error),
                    error: app.ajaxError(app.login.error)
                });
            },

            success: function() {
                localStorage.account = app.login.$account.val();
                window.location.replace($("[name=location]").val());
            },

            error: function(err) {
                app.alerts.clearAll();
                app.alerts.error(err);
                app.login.$lock.show();
                app.login.$account.removeAttr("disabled");
            }
        },

        trans: {
            add: function(data, cb) {
                var cat,
                    valid = true;

                console.log("adding transaction with", data);

                cb = (cb || {});

                if (!data.amount || !Number(data.amount)) {
                    app.alerts.error("Please enter a number for the amount");
                    valid = false;
                }
                if (!data.date || !Date(data.date)) {
                    app.alerts.error("Please enter a valid date");
                    valid = false;
                }
                cat = Number(data.category);
                if (!cat && cat !== 0) {
                    app.alerts.error("Please select a valid category");
                    valid = false;
                }

                if (!valid) { return; }

                $.ajax({
                    url: "/transaction/add",
                    type: "post",
                    data: data,
                    dataType: "json",
                    success: app.ajaxSuccess(cb.success, cb.error),
                    error: app.ajaxError(cb.error)
                });
            }
        },

        ajaxSuccess: function(success, error) {
            success = (success || function() {});
            error = (error || function() {});
            return function(data) {
                data = (data || {});
                if (data.error) {
                    (app.ajaxError(error))({
                        responseText: JSON.stringify(data),
                        status: data.status
                    });
                } else {
                    success(data);
                }
            };
        },

        ajaxError: function(handler) {
            handler = (handler || function() {});
            return function(xhr) {
                var errJSON;
                try {
                    errJSON = JSON.parse(xhr.responseText);
                } catch(err) {
                    errJSON = {
                        error: xhr.responseText,
                        status: xhr.status
                    };
                }

                if (errJSON.status === 404) {
                    console.error("Unable to find endpoint (404)", errJSON.error);
                    handler("Sorry, but I couldn't complete that request");
                } else if (errJSON.status && errJSON.status < 500) {
                    handler(errJSON.error);
                } else {
                    console.error("Server error: ", errJSON.error);
                    handler("Sorry, but I couldn't complete that request");
                }
            };
        },

        alerts: {
            error: function(msg) { this.add("error", msg); },
            warn: function(msg) { this.add("warn", msg); },
            info: function(msg) { this.add("info", msg); },
            success: function(msg) { this.add("success", msg); },

            add: function(cls, msg) {
                app.$messageNode.append("
" + msg + "
");
            },

            clearAll: function() {
                app.$messageNode.empty();
            }
        }

    };

})(window.jQuery);<commit_msg>Fix pattern-lock UI in certain browsers<commit_after>
(function($) {

    window.console = (window.console || { log: function() {}, error: function() {}});

    var app = window.pig = {
        categories: {},
        $messageNode: null,

        init: function(page, options) {
            options = (options || {});

            console.log("Starting piggy client on '" + page + "' page", options);

            app.$messageNode = $("aside.messages");

            if (app[page] && app[page].init && app[page].init.apply) {
                app[page].init.apply(app[page], [options]);
            }

        },

        main: {
            init: function() {
                app.main.$acctBalance = $("#page_account .amount");
                app.main.$recentTrans = $("div.recentTrans");
                app.main.$recentTransCount = $(".recentTransCount");

                $("form[action=\\/transaction\\/add]")
                    .on("submit", this.handleAddTransaction)
                    .find("[required]")
                        .on("invalid", function() {
                            $(this)
                                .closest("form")
                                    .find(".ui-submit")
                                        .removeClass("ui-btn-active");
                        });
            },

            handleAddTransaction: function(e) {
                var form = $(this),
                    data = {};

                e.preventDefault();

                app.alerts.clearAll();

                form.serializeArray().forEach(function(item) {
                    data[item.name] = item.value;
                });

                if (!Number(data.amount)) {
                    app.alerts.error("Please enter an amount (greater than zero)");
                    form.find(".ui-submit").removeClass("ui-btn-active");
                    return false;
                }
                data.amount = Number(data.amount);

                // if an expense, flip the amount to negative
                if (form.find("[name=amount]").hasClass("expense") && data.amount > 0) {
                    data.amount *= -1;
                }

                app.trans.add(data, {
                    success: function(trans) {
                        console.log(trans);

                        var balance = Number(app.main.$acctBalance.text().substr(1)),
                            transDiv = $("
");

                        if (balance) {
                            app.main.$acctBalance.text("$" + (balance + trans.amount).toFixed(2));
                        }

                        app.main.$recentTrans.find(".ui-first-child").removeClass("ui-first-child");

                        transDiv.append(
                            "
$" + trans.amount.toFixed(2) + " " + trans.dateDisplay + "
" +
                            "
" + trans.description + "
" +
                            "
" + app.categories[trans.category] + "
"
                        );
                        app.main.$recentTrans.prepend(transDiv);
                        transDiv.collapsible();
                        app.main.$recentTransCount.text(Number(app.main.$recentTransCount.text()) + 1);

                        app.alerts.success("Transaction added successfully!");
                        form.find("[name=description]").val("");
                        form.find("[name=amount]").val("").focus();
                        form.find(".ui-submit").removeClass("ui-btn-active");
                    },
                    error: function(err) {
                        app.alerts.error(err);
                        form.find(".ui-submit").removeClass("ui-btn-active");
                    }
                });

                return false;
            }

        },

        login: {
            $account: null,
            $lock: null,

            init: function() {
                var loc;

                $("form[action=\\/account\\/login]").on("submit", function(e) {
                    console.error("Login form submission (should not occur)");
                    e.preventDefault();
                    return false;
                });

                app.login.$account = $("[name=account]");
                app.login.$lock = $(".pattern-lock");

                if (window.location.hash) {
                    loc = $("[name=location]");
                    loc.val(loc.val() + window.location.hash);
                }

                if (localStorage.account && !app.login.$account.val().length) {
                    app.login.$account.val(localStorage.account).blur();
                }

                app.login.$lock.patternInput({
                    onFinish: this.handleLoginPattern
                });

                $("body").on("touchmove", function(e) {
                    // makes the pattern lock UI work on touch devices
                    e.preventDefault();
                });
            },

            handleLoginPattern: function(pattern) {
                app.alerts.clearAll();

                app.login.$account.attr("disabled", "disabled");
                app.login.$lock.hide();

                app.alerts.info("Working...");

                $.ajax({
                    url: "/account/login",
                    type: "post",
                    data: {
                        owner: app.login.$account.val(),
                        pattern: pattern.join("")
                    },
                    dataType: "json",
                    success: app.ajaxSuccess(app.login.success, app.login.error),
                    error: app.ajaxError(app.login.error)
                });
            },

            success: function() {
                localStorage.account = app.login.$account.val();
                window.location.replace($("[name=location]").val());
            },

            error: function(err) {
                app.alerts.clearAll();
                app.alerts.error(err);
                app.login.$lock.show();
                app.login.$account.removeAttr("disabled");
            }
        },

        trans: {
            add: function(data, cb) {
                var cat,
                    valid = true;

                console.log("adding transaction with", data);

                cb = (cb || {});

                if (!data.amount || !Number(data.amount)) {
                    app.alerts.error("Please enter a number for the amount");
                    valid = false;
                }
                if (!data.date || !Date(data.date)) {
                    app.alerts.error("Please enter a valid date");
                    valid = false;
                }
                cat = Number(data.category);
                if (!cat && cat !== 0) {
                    app.alerts.error("Please select a valid category");
                    valid = false;
                }

                if (!valid) { return; }

                $.ajax({
                    url: "/transaction/add",
                    type: "post",
                    data: data,
                    dataType: "json",
                    success: app.ajaxSuccess(cb.success, cb.error),
                    error: app.ajaxError(cb.error)
                });
            }
        },

        ajaxSuccess: function(success, error) {
            success = (success || function() {});
            error = (error || function() {});
            return function(data) {
                data = (data || {});
                if (data.error) {
                    (app.ajaxError(error))({
                        responseText: JSON.stringify(data),
                        status: data.status
                    });
                } else {
                    success(data);
                }
            };
        },

        ajaxError: function(handler) {
            handler = (handler || function() {});
            return function(xhr) {
                var errJSON;
                try {
                    errJSON = JSON.parse(xhr.responseText);
                } catch(err) {
                    errJSON = {
                        error: xhr.responseText,
                        status: xhr.status
                    };
                }

                if (errJSON.status === 404) {
                    console.error("Unable to find endpoint (404)", errJSON.error);
                    handler("Sorry, but I couldn't complete that request");
                } else if (errJSON.status && errJSON.status < 500) {
                    handler(errJSON.error);
                } else {
                    console.error("Server error: ", errJSON.error);
                    handler("Sorry, but I couldn't complete that request");
                }
            };
        },

        alerts: {
            error: function(msg) { this.add("error", msg); },
            warn: function(msg) { this.add("warn", msg); },
            info: function(msg) { this.add("info", msg); },
            success: function(msg) { this.add("success", msg); },

            add: function(cls, msg) {
                app.$messageNode.append("
" + msg + "
");
            },

            clearAll: function() {
                app.$messageNode.empty();
            }
        }

    };

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


<commit_before>(function($)
{
	$(function() {

		/* Facebox modal window */
		$('a[rel*=modal]').facebox({
		   opacity : 0.4,
		   loadingImage : APPPATH_URI + 'assets/img/facebox/loading.gif',
		   closeImage   : APPPATH_URI + 'assets/img/facebox/closelabel.gif',
		});

	   	// ---------------------------------------------------------
		// Name: Default Input Text
		// Description: Used for search boxes and other input boxes
		// 				with a default value that should vanish when
		//              a user clicks within the box
		// Useage:      Give any text input a class of 'default-input-text'
		// 		        and make sure it has an ID.
		// ---------------------------------------------------------

		// Used to store default text input valyes
		var default_input_terms = new Array();

		// hides default input text from a input box
		$('.default-input-text').focus(function() {

			// Store the default text if it hasnt already been stored
			if(typeof default_input_terms[this.id] == 'undefined') {
				default_input_terms[this.id] = $(this).val();
			}

			// If the current value is the default value, hide it
			if($(this).val() == default_input_terms[this.id]) {
				$(this).val('').removeClass('default-input-text').addClass('non-default-input-text');
			}

			// when the event is blured, put the default message back if they havent written anything
			$(this).blur( function () {
				default_term = default_input_terms[this.id];
				if($(this).val() == '') $(this).removeClass('non-default-input-text').addClass('default-input-text').val(default_term);
			} );

		});

	});
})(jQuery);<commit_msg>IE6 JS bug in front.js<commit_after>(function($)
{
	$(function() {

		/* Facebox modal window */
		$('a[rel*=modal]').facebox({
		   opacity : 0.4,
		   loadingImage : APPPATH_URI + 'assets/img/facebox/loading.gif',
		   closeImage   : APPPATH_URI + 'assets/img/facebox/closelabel.gif'
		});

	   	// ---------------------------------------------------------
		// Name: Default Input Text
		// Description: Used for search boxes and other input boxes
		// 				with a default value that should vanish when
		//              a user clicks within the box
		// Useage:      Give any text input a class of 'default-input-text'
		// 		        and make sure it has an ID.
		// ---------------------------------------------------------

		// Used to store default text input valyes
		var default_input_terms = new Array();

		// hides default input text from a input box
		$('.default-input-text').focus(function() {

			// Store the default text if it hasnt already been stored
			if(typeof default_input_terms[this.id] == 'undefined') {
				default_input_terms[this.id] = $(this).val();
			}

			// If the current value is the default value, hide it
			if($(this).val() == default_input_terms[this.id]) {
				$(this).val('').removeClass('default-input-text').addClass('non-default-input-text');
			}

			// when the event is blured, put the default message back if they havent written anything
			$(this).blur( function () {
				default_term = default_input_terms[this.id];
				if($(this).val() == '') $(this).removeClass('non-default-input-text').addClass('default-input-text').val(default_term);
			} );

		});

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


<commit_before>import Config from 'react-native-config';
import omit from 'lodash/omit';
import CONSTANTS from 'config/constants';
import RNFetchBlob from 'react-native-fetch-blob';
import { unzip } from 'react-native-zip-archive';
import { getActionsTodoCount } from 'helpers/sync';
import { removeFolder } from 'helpers/fileManagement';

import { LOGOUT_REQUEST } from 'redux-modules/user';
import { SAVE_AREA_COMMIT } from 'redux-modules/areas';
import { START_APP } from 'redux-modules/app';

const GET_LAYERS_REQUEST = 'layers/GET_LAYERS_REQUEST';
const GET_LAYERS_COMMIT = 'layers/GET_LAYERS_COMMIT';
const GET_LAYERS_ROLLBACK = 'layers/GET_LAYERS_ROLLBACK';
const SET_ACTIVE_LAYER = 'layer/SET_ACTIVE_LAYER';
const DOWNLOAD_AREA = 'layer/DOWNLOAD_AREA';
const CACHE_LAYER_REQUEST = 'layers/CACHE_LAYER_REQUEST';
const CACHE_LAYER_COMMIT = 'layers/CACHE_LAYER_COMMIT';
export const CACHE_LAYER_ROLLBACK = 'layer/CACHE_LAYER_ROLLBACK';
const SET_CACHE_STATUS = 'layer/SET_CACHE_STATUS';

// Reducer
const initialState = {
  data: [],
  synced: false,
  syncing: false,
  activeLayer: null,
  syncDate: Date.now(),

  cacheStatus: {
    // status of the current area cache
    // areaId: {
    //   progress: 0,
    //   completed: false,
    //   requested: false,
    //   error: false
    // }
  },
  cache: {
    // save the layers path for each area
    // basemap: { areaId: local files path }
  },
  pendingCache: {
    // key value with layer => areaId to cache
    // basemap: { areaId: true | false }
  }
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case START_APP: {
      return { ...state, synced: false, syncing: false };
    }
    case GET_LAYERS_REQUEST:
      return { ...state, synced: false, syncing: true };
    case GET_LAYERS_COMMIT: {
      const areas = [...action.meta.areas];
      const layers = [...action.payload];
      const syncDate = Date.now();
      const cache = { ...state.cache };
      let cacheStatus = { ...state.cacheStatus };
      cacheStatus = getCacheStatus(cache, cacheStatus, areas, layers);

      return { ...state, data: layers, cacheStatus, syncDate, synced: true, syncing: false };
    }
    case GET_LAYERS_ROLLBACK: {
      return { ...state, syncing: false };
    }
    case DOWNLOAD_AREA: {
      const area = action.payload;
      const { data, cache } = state;
      let pendingCache = { ...state.pendingCache };
      let cacheStatus = { ...state.cacheStatus };

      const layers = getLayersWithBasemap(data);

      layers.forEach((layer) => {
        if (!cache[layer.id] || (cache[layer.id] && !cache[layer.id][area.id])) {
          pendingCache = {
            ...pendingCache,
            [layer.id]: {
              ...pendingCache[layer.id],
              [area.id]: false
            }
          };
        }
      });

      if (cacheStatus[area.id]) {
        cacheStatus = {
          ...cacheStatus,
          [area.id]: {
            ...cacheStatus[area.id],
            requested: true
          }
        };
      } else {
        cacheStatus = {
          ...cacheStatus,
          [area.id]: {
            progress: 0,
            completed: false,
            requested: true,
            error: false
          }
        };
      }
      return { ...state, pendingCache, cacheStatus };
    }
    case SET_ACTIVE_LAYER:
      return { ...state, activeLayer: action.payload };
    case CACHE_LAYER_REQUEST: {
      const { area, layer } = action.payload;
      const pendingCache = {
        ...state.pendingCache,
        [layer.id]: {
          ...state.pendingCache[layer.id],
          [area.id]: true
        }
      };
      return { ...state, pendingCache };
    }
    case CACHE_LAYER_COMMIT: {
      const { area, layer } = action.meta;
      let path = action.payload;
      let cacheStatus = { ...state.cacheStatus };
      path = (path && path.length > 0) ? path[0] : path;
      const pendingCache = {
        ...state.pendingCache,
        [layer.id]: omit(state.pendingCache[layer.id], [area.id])
      };
      const cache = {
        ...state.cache,
        [layer.id]: {
          ...state.cache[layer.id],
          [area.id]: path
        }
      };

      cacheStatus = getCacheStatus(cache, cacheStatus, [area], [layer]);
      return { ...state, cache, cacheStatus, pendingCache };
    }
    case CACHE_LAYER_ROLLBACK: {
      const { area, layer } = action.meta;
      const { areas, data: layers, cacheStatus, cache } = state;
      const updatedCacheStatus = getCacheStatus(cache, cacheStatus, areas, layers);
      const areaCacheStatus = { ...updatedCacheStatus[area.id], requested: false, error: true };
      const newCacheStatus = { ...updatedCacheStatus, [area.id]: { ...areaCacheStatus } };
      const pendingCache = {
        ...state.pendingCache,
        [layer.id]: omit(state.pendingCache[layer.id], [area.id])
      };
      return { ...state, pendingCache, cacheStatus: newCacheStatus };
    }
    case SET_CACHE_STATUS: {
      return { ...state, cacheStatus: action.payload };
    }
    case SAVE_AREA_COMMIT: {
      const { cache, cacheStatus, data: layers } = state;
      const area = action.payload;
      const newCacheStatus = getCacheStatus(cache, cacheStatus, [area], layers);
      return { ...state, cacheStatus: newCacheStatus };
    }
    case LOGOUT_REQUEST:
      removeFolder(CONSTANTS.files.tiles);
      return initialState;
    default:
      return state;
  }
}

export function getUserLayers() {
  return (dispatch, state) => {
    const url = `${Config.API_URL}/contextual-layer/?enabled=true`;
    const areas = state().areas.data;
    return dispatch({
      type: GET_LAYERS_REQUEST,
      meta: {
        offline: {
          effect: { url },
          commit: { type: GET_LAYERS_COMMIT, meta: { areas } },
          rollback: { type: GET_LAYERS_ROLLBACK }
        }
      }
    });
  };
}

export function setActiveContextualLayer(layerId, value) {
  return (dispatch, state) => {
    let activeLayer = null;
    if (layerId !== state().layers.activeLayer && value) activeLayer = layerId;
    return dispatch({ type: SET_ACTIVE_LAYER, payload: activeLayer });
  };
}

async function downloadLayer(config) {
  const { area, layerId, layerUrl, zoom } = config;
  const url = `${Config.API_URL}/download-tiles/${area.geostore}/${zoom.start}/${zoom.end}?layerUrl=${layerUrl}`;
  const res = await RNFetchBlob
    // add this option that makes response data to be stored as a file,
    // this is much more performant.
    .config({ fileCache: true })
    .fetch('GET', encodeURI(url));
  const statusCode = res.info().status;
  if (statusCode >= 200 && statusCode < 400 && res.path()) {
    const downloadPath = res.path();
    const tilesPath = `${CONSTANTS.files.tiles}/${area.id}/${layerId}`;
    const targetPath = `${RNFetchBlob.fs.dirs.DocumentDir}/${tilesPath}`;
    await unzip(downloadPath, targetPath);
    res.flush(); // remove from the cache
    return `${tilesPath}/{z}x{x}x{y}`;
  }
  throw new Error(`Fetch blob error ${statusCode}`);
}

function downloadAllLayers(config) {
  const { cacheZoom } = CONSTANTS.maps;
  return Promise.all(cacheZoom.map((cacheLevel) => {
    const layerConfig = { ...config, zoom: cacheLevel };
    return downloadLayer(layerConfig);
  }, this));
}

function getAreaById(areas, areaId) {
  // Using deconstructor to generate a new object
  return { ...areas.find((areaData) => (areaData.id === areaId)) };
}

function getLayerById(layers, layerId) {
  if (!layers) return null;
  // Using deconstructor to generate a new object
  return { ...layers.find((layer) => (layer.id === layerId)) };
}

export function cacheAreaBasemap(areaId) {
  return (dispatch, state) => {
    const area = getAreaById(state().areas.data, areaId);
    const layer = {
      id: 'basemap',
      url: CONSTANTS.maps.basemap
    };
    if (area) {
      const downloadConfig = {
        area,
        layerId: layer.id,
        layerUrl: layer.url
      };

      const promise = downloadAllLayers(downloadConfig);
      dispatch({
        type: CACHE_LAYER_REQUEST,
        payload: { area, layer },
        meta: {
          offline: {
            effect: { promise, errorCode: 400 },
            commit: { type: CACHE_LAYER_COMMIT, meta: { area, layer } },
            rollback: { type: CACHE_LAYER_ROLLBACK, meta: { area, layer } }
          }
        }
      });
    }
  };
}

export function cacheAreaLayer(areaId, layerId) {
  return (dispatch, state) => {
    const area = getAreaById(state().areas.data, areaId);
    const layer = getLayerById(state().layers.data, layerId);
    if (area && layer) {
      const downloadConfig = {
        area,
        layerId: layer.id,
        layerUrl: layer.url
      };
      const promise = downloadAllLayers(downloadConfig);
      dispatch({
        type: CACHE_LAYER_REQUEST,
        payload: { area, layer },
        meta: {
          offline: {
            effect: { promise, errorCode: 400 },
            commit: { type: CACHE_LAYER_COMMIT, meta: { area, layer } },
            rollback: { type: CACHE_LAYER_ROLLBACK, meta: { area, layer } }
          }
        }
      });
    }
  };
}

export function syncLayers() {
  return (dispatch, state) => {
    const { synced, syncing } = state().layers;
    const hasAreas = state().areas.data.length;
    if (!synced && !syncing && hasAreas) dispatch(getUserLayers());
  };
}

export function downloadAreaById(areaId) {
  return (dispatch, state) => {
    const area = getAreaById(state().areas.data, areaId);
    dispatch({
      type: DOWNLOAD_AREA,
      payload: area
    });
    dispatch(cacheLayers());
  };
}

export function cacheLayers() {
  return (dispatch, state) => {
    const { pendingCache } = state().layers;
    if (getActionsTodoCount(pendingCache) > 0) {
      Object.keys(pendingCache).forEach((layer) => {
        const syncingLayersData = pendingCache[layer];
        const canDispatch = id => (typeof syncingLayersData[id] !== 'undefined' && syncingLayersData[id] === false);
        const syncLayersData = (action) => {
          Object.keys(syncingLayersData).forEach(id => {
            if (canDispatch(id)) {
              action(id);
            }
          });
        };
        switch (layer) {
          case 'basemap':
            syncLayersData(id => dispatch(cacheAreaBasemap(id)));
            break;
          default:
            syncLayersData(id => dispatch(cacheAreaLayer(id, layer)));
        }
      });
    }
  };
}

function getLayersWithBasemap(layers) {
  return [{ id: 'basemap' }, ...layers];
}

function getCacheStatus(cache = {}, cacheStatus = {}, areas = [], layers = []) {
  const enhancedLayers = getLayersWithBasemap(layers);
  const layersCount = enhancedLayers.length;
  let newCacheStatus = { ...cacheStatus };
  areas.forEach((area) => {
    let layersCached = 0;
    enhancedLayers.forEach((layer) => {
      if (cache[layer.id] && (cache[layer.id] && cache[layer.id][area.id])) {
        layersCached += 1;
      }
    });
    const progress = layersCached / layersCount;
    newCacheStatus = {
      ...newCacheStatus,
      [area.id]: {
        requested: (newCacheStatus[area.id] && newCacheStatus[area.id].requested) || false,
        progress,
        complete: progress === 1,
        error: false
      }
    };
  });
  return newCacheStatus;
}

export function resetCacheStatus(areaId) {
  return (dispatch, state) => {
    const { cacheStatus } = state().layers;
    const newCacheStatus = {
      ...cacheStatus,
      [areaId]: {
        requested: false,
        complete: false,
        progress: 0,
        error: false
      }
    };
    dispatch({
      type: SET_CACHE_STATUS,
      payload: newCacheStatus
    });
  };
}
<commit_msg>fix: gesCacheStatus receiving wrong layers<commit_after>import Config from 'react-native-config';
import omit from 'lodash/omit';
import CONSTANTS from 'config/constants';
import RNFetchBlob from 'react-native-fetch-blob';
import { unzip } from 'react-native-zip-archive';
import { getActionsTodoCount } from 'helpers/sync';
import { removeFolder } from 'helpers/fileManagement';

import { LOGOUT_REQUEST } from 'redux-modules/user';
import { SAVE_AREA_COMMIT } from 'redux-modules/areas';
import { START_APP } from 'redux-modules/app';

const GET_LAYERS_REQUEST = 'layers/GET_LAYERS_REQUEST';
const GET_LAYERS_COMMIT = 'layers/GET_LAYERS_COMMIT';
const GET_LAYERS_ROLLBACK = 'layers/GET_LAYERS_ROLLBACK';
const SET_ACTIVE_LAYER = 'layer/SET_ACTIVE_LAYER';
const DOWNLOAD_AREA = 'layer/DOWNLOAD_AREA';
const CACHE_LAYER_REQUEST = 'layers/CACHE_LAYER_REQUEST';
const CACHE_LAYER_COMMIT = 'layers/CACHE_LAYER_COMMIT';
export const CACHE_LAYER_ROLLBACK = 'layer/CACHE_LAYER_ROLLBACK';
const SET_CACHE_STATUS = 'layer/SET_CACHE_STATUS';

// Reducer
const initialState = {
  data: [],
  synced: false,
  syncing: false,
  activeLayer: null,
  syncDate: Date.now(),

  cacheStatus: {
    // status of the current area cache
    // areaId: {
    //   progress: 0,
    //   completed: false,
    //   requested: false,
    //   error: false
    // }
  },
  cache: {
    // save the layers path for each area
    // basemap: { areaId: local files path }
  },
  pendingCache: {
    // key value with layer => areaId to cache
    // basemap: { areaId: true | false }
  }
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case START_APP: {
      return { ...state, synced: false, syncing: false };
    }
    case GET_LAYERS_REQUEST:
      return { ...state, synced: false, syncing: true };
    case GET_LAYERS_COMMIT: {
      const areas = [...action.meta.areas];
      const layers = [...action.payload];
      const syncDate = Date.now();
      const cache = { ...state.cache };
      let cacheStatus = { ...state.cacheStatus };
      cacheStatus = getCacheStatus(cache, cacheStatus, areas, layers);

      return { ...state, data: layers, cacheStatus, syncDate, synced: true, syncing: false };
    }
    case GET_LAYERS_ROLLBACK: {
      return { ...state, syncing: false };
    }
    case DOWNLOAD_AREA: {
      const area = action.payload;
      const { data, cache } = state;
      let pendingCache = { ...state.pendingCache };
      let cacheStatus = { ...state.cacheStatus };

      const layers = getLayersWithBasemap(data);

      layers.forEach((layer) => {
        if (!cache[layer.id] || (cache[layer.id] && !cache[layer.id][area.id])) {
          pendingCache = {
            ...pendingCache,
            [layer.id]: {
              ...pendingCache[layer.id],
              [area.id]: false
            }
          };
        }
      });

      if (cacheStatus[area.id]) {
        cacheStatus = {
          ...cacheStatus,
          [area.id]: {
            ...cacheStatus[area.id],
            requested: true
          }
        };
      } else {
        cacheStatus = {
          ...cacheStatus,
          [area.id]: {
            progress: 0,
            completed: false,
            requested: true,
            error: false
          }
        };
      }
      return { ...state, pendingCache, cacheStatus };
    }
    case SET_ACTIVE_LAYER:
      return { ...state, activeLayer: action.payload };
    case CACHE_LAYER_REQUEST: {
      const { area, layer } = action.payload;
      const pendingCache = {
        ...state.pendingCache,
        [layer.id]: {
          ...state.pendingCache[layer.id],
          [area.id]: true
        }
      };
      return { ...state, pendingCache };
    }
    case CACHE_LAYER_COMMIT: {
      const { area, layer } = action.meta;
      const layers = [...state.data];
      let path = action.payload;
      let cacheStatus = { ...state.cacheStatus };
      path = (path && path.length > 0) ? path[0] : path;
      const pendingCache = {
        ...state.pendingCache,
        [layer.id]: omit(state.pendingCache[layer.id], [area.id])
      };
      const cache = {
        ...state.cache,
        [layer.id]: {
          ...state.cache[layer.id],
          [area.id]: path
        }
      };

      cacheStatus = getCacheStatus(cache, cacheStatus, [area], layers);
      return { ...state, cache, cacheStatus, pendingCache };
    }
    case CACHE_LAYER_ROLLBACK: {
      const { area, layer } = action.meta;
      const { areas, data: layers, cacheStatus, cache } = state;
      const updatedCacheStatus = getCacheStatus(cache, cacheStatus, areas, layers);
      const areaCacheStatus = { ...updatedCacheStatus[area.id], requested: false, error: true };
      const newCacheStatus = { ...updatedCacheStatus, [area.id]: { ...areaCacheStatus } };
      const pendingCache = {
        ...state.pendingCache,
        [layer.id]: omit(state.pendingCache[layer.id], [area.id])
      };
      return { ...state, pendingCache, cacheStatus: newCacheStatus };
    }
    case SET_CACHE_STATUS: {
      return { ...state, cacheStatus: action.payload };
    }
    case SAVE_AREA_COMMIT: {
      const { cache, cacheStatus, data: layers } = state;
      const area = action.payload;
      const newCacheStatus = getCacheStatus(cache, cacheStatus, [area], layers);
      return { ...state, cacheStatus: newCacheStatus };
    }
    case LOGOUT_REQUEST:
      removeFolder(CONSTANTS.files.tiles);
      return initialState;
    default:
      return state;
  }
}

export function getUserLayers() {
  return (dispatch, state) => {
    const url = `${Config.API_URL}/contextual-layer/?enabled=true`;
    const areas = state().areas.data;
    return dispatch({
      type: GET_LAYERS_REQUEST,
      meta: {
        offline: {
          effect: { url },
          commit: { type: GET_LAYERS_COMMIT, meta: { areas } },
          rollback: { type: GET_LAYERS_ROLLBACK }
        }
      }
    });
  };
}

export function setActiveContextualLayer(layerId, value) {
  return (dispatch, state) => {
    let activeLayer = null;
    if (layerId !== state().layers.activeLayer && value) activeLayer = layerId;
    return dispatch({ type: SET_ACTIVE_LAYER, payload: activeLayer });
  };
}

async function downloadLayer(config) {
  const { area, layerId, layerUrl, zoom } = config;
  const url = `${Config.API_URL}/download-tiles/${area.geostore}/${zoom.start}/${zoom.end}?layerUrl=${layerUrl}`;
  const res = await RNFetchBlob
    // add this option that makes response data to be stored as a file,
    // this is much more performant.
    .config({ fileCache: true })
    .fetch('GET', encodeURI(url));
  const statusCode = res.info().status;
  if (statusCode >= 200 && statusCode < 400 && res.path()) {
    const downloadPath = res.path();
    const tilesPath = `${CONSTANTS.files.tiles}/${area.id}/${layerId}`;
    const targetPath = `${RNFetchBlob.fs.dirs.DocumentDir}/${tilesPath}`;
    await unzip(downloadPath, targetPath);
    res.flush(); // remove from the cache
    return `${tilesPath}/{z}x{x}x{y}`;
  }
  throw new Error(`Fetch blob error ${statusCode}`);
}

function downloadAllLayers(config) {
  const { cacheZoom } = CONSTANTS.maps;
  return Promise.all(cacheZoom.map((cacheLevel) => {
    const layerConfig = { ...config, zoom: cacheLevel };
    return downloadLayer(layerConfig);
  }, this));
}

function getAreaById(areas, areaId) {
  // Using deconstructor to generate a new object
  return { ...areas.find((areaData) => (areaData.id === areaId)) };
}

function getLayerById(layers, layerId) {
  if (!layers) return null;
  // Using deconstructor to generate a new object
  return { ...layers.find((layer) => (layer.id === layerId)) };
}

export function cacheAreaBasemap(areaId) {
  return (dispatch, state) => {
    const area = getAreaById(state().areas.data, areaId);
    const layer = {
      id: 'basemap',
      url: CONSTANTS.maps.basemap
    };
    if (area) {
      const downloadConfig = {
        area,
        layerId: layer.id,
        layerUrl: layer.url
      };

      const promise = downloadAllLayers(downloadConfig);
      dispatch({
        type: CACHE_LAYER_REQUEST,
        payload: { area, layer },
        meta: {
          offline: {
            effect: { promise, errorCode: 400 },
            commit: { type: CACHE_LAYER_COMMIT, meta: { area, layer } },
            rollback: { type: CACHE_LAYER_ROLLBACK, meta: { area, layer } }
          }
        }
      });
    }
  };
}

export function cacheAreaLayer(areaId, layerId) {
  return (dispatch, state) => {
    const area = getAreaById(state().areas.data, areaId);
    const layer = getLayerById(state().layers.data, layerId);
    if (area && layer) {
      const downloadConfig = {
        area,
        layerId: layer.id,
        layerUrl: layer.url
      };
      const promise = downloadAllLayers(downloadConfig);
      dispatch({
        type: CACHE_LAYER_REQUEST,
        payload: { area, layer },
        meta: {
          offline: {
            effect: { promise, errorCode: 400 },
            commit: { type: CACHE_LAYER_COMMIT, meta: { area, layer } },
            rollback: { type: CACHE_LAYER_ROLLBACK, meta: { area, layer } }
          }
        }
      });
    }
  };
}

export function syncLayers() {
  return (dispatch, state) => {
    const { synced, syncing } = state().layers;
    const hasAreas = state().areas.data.length;
    if (!synced && !syncing && hasAreas) dispatch(getUserLayers());
  };
}

export function downloadAreaById(areaId) {
  return (dispatch, state) => {
    const area = getAreaById(state().areas.data, areaId);
    dispatch({
      type: DOWNLOAD_AREA,
      payload: area
    });
    dispatch(cacheLayers());
  };
}

export function cacheLayers() {
  return (dispatch, state) => {
    const { pendingCache } = state().layers;
    if (getActionsTodoCount(pendingCache) > 0) {
      Object.keys(pendingCache).forEach((layer) => {
        const syncingLayersData = pendingCache[layer];
        const canDispatch = id => (typeof syncingLayersData[id] !== 'undefined' && syncingLayersData[id] === false);
        const syncLayersData = (action) => {
          Object.keys(syncingLayersData).forEach(id => {
            if (canDispatch(id)) {
              action(id);
            }
          });
        };
        switch (layer) {
          case 'basemap':
            syncLayersData(id => dispatch(cacheAreaBasemap(id)));
            break;
          default:
            syncLayersData(id => dispatch(cacheAreaLayer(id, layer)));
        }
      });
    }
  };
}

function getCacheStatus(cache = {}, cacheStatus = {}, areas = [], layers = []) {
  const enhancedLayers = getLayersWithBasemap(layers);
  const layersCount = enhancedLayers.length;
  let newCacheStatus = { ...cacheStatus };
  areas.forEach((area) => {
    let layersCached = 0;
    enhancedLayers.forEach((layer) => {
      if (cache[layer.id] && cache[layer.id][area.id]) {
        layersCached += 1;
      }
    });
    const progress = layersCached / layersCount;
    newCacheStatus = {
      ...newCacheStatus,
      [area.id]: {
        requested: (newCacheStatus[area.id] && newCacheStatus[area.id].requested) || false,
        progress,
        complete: progress === 1,
        error: false
      }
    };
  });
  return newCacheStatus;
}

export function resetCacheStatus(areaId) {
  return (dispatch, state) => {
    const { cacheStatus } = state().layers;
    const newCacheStatus = {
      ...cacheStatus,
      [areaId]: {
        requested: false,
        complete: false,
        progress: 0,
        error: false
      }
    };
    dispatch({
      type: SET_CACHE_STATUS,
      payload: newCacheStatus
    });
  };
}

function getLayersWithBasemap(layers) {
  return [{ id: 'basemap' }, ...layers];
}
<|endoftext|>


<commit_before>function dealmd(path) {
    debugger;
    $.get(path, function(data) {
        var html_content = markdown.toHTML(data);
        $(".markdown-body").html(html_content);
        //html自动编号
        var h1Index = 0;
        var h2Index = 0;
        var h3Index = 0;
        var h4Index = 0;
        $("h1,h2,h3,h4").each(function(i, val) {
        	if("H1" == val.tagName){
        		h1Index += 1;
		        h2Index = 0;
        		$(val).prepend(h1Index+".");
        	}

        	if("H2" == val.tagName){
        		h2Index += 1;
		        h3Index = 0;
        		$(val).prepend(h1Index+"." + h2Index + ".");
        	}

        	if("H3" == val.tagName){
        		h3Index += 1;
		        h4Index = 0;
        		$(val).prepend(h1Index+"." + h2Index + "." + h3Index + ".");
        	}
        });
    });
}

//JS下拉框处理
$("#java").on("click", function(event) {
    var value = event.target.text;
    var path = "./java/" + value + ".md";
    dealmd(path);
});

//JS下拉框处理
$("#js").on("click", function(event) {
    var value = event.target.text;
    var path = "./frontend/js/" + value + ".md";
    dealmd(path);
});

//Tools便签处理
$("#tools").on("click", function(event) {
    var value = event.target.text;
    var path = "./others/" + value + ".md";
    dealmd(path);
});
<commit_msg>Update current.js<commit_after>function dealmd(path) {
    debugger;
    $.get(path, function(data) {
        var html_content = markdown.toHTML(data);
        $(".markdown-body").html(html_content);
        //html自动编号
        var h1Index = 0;
        var h2Index = 0;
        var h3Index = 0;
        var h4Index = 0;
        $("h1,h2,h3,h4").each(function(i, val) {
        	if("H1" == val.tagName){
        		h1Index += 1;
		        h2Index = 0;
        		$(val).prepend(h1Index+".");
        	}

        	if("H2" == val.tagName){
        		h2Index += 1;
		        h3Index = 0;
        		$(val).prepend(h1Index+"." + h2Index + ".");
        	}

        	if("H3" == val.tagName){
        		h3Index += 1;
		        h4Index = 0;
        		$(val).prepend(h1Index+"." + h2Index + "." + h3Index + ".");
        	}
        });
    });
}

//Java下拉框处理
$("#java").on("click", function(event) {
    var value = event.target.text;
    var path = "./java/" + value + ".md";
    dealmd(path);
});

//JS下拉框处理
$("#js").on("click", function(event) {
    var value = event.target.text;
    var path = "./frontend/js/" + value + ".md";
    dealmd(path);
});

//CSS下拉框处理
$("#css").on("click", function(event) {
    var value = event.target.text;
    var path = "./frontend/css/" + value + ".md";
    dealmd(path);
});

//othres下拉框处理
$("#others").on("click", function(event) {
    var value = event.target.text;
    var path = "./others/" + value + ".md";
    dealmd(path);
});

//hobby下拉框处理
$("#hobby").on("click", function(event) {
    var value = event.target.text;
    var path = "./hobby/" + value + ".md";
    dealmd(path);
});
<|endoftext|>


<commit_before>import * as UTILS from '../../globals';

const world = new (PHYSICS.$world(WHS.World))({
  ...UTILS.$world,

  physics: {
    ammo: process.ammoPath
  },

  softbody: true,

  gravity: [0, -10, 0]
});

const tubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xffffff,
  metalness: 1,
  emissive: 0x333333,
  roughness: 0.4
});

// TOP.
const toptube = new WHS.Tube({
  geometry: {
    path: new THREE.LineCurve3(new THREE.Vector3(-30, 30, 0), new THREE.Vector3(30, 30, 0)),
    radius: 1
  },

  mass: 0,
  material: tubeMaterial
});

toptube.addTo(world);

// LEFT.
new WHS.Tube({
  geometry: {
    path: new THREE.LineCurve3(new THREE.Vector3(-29.5, 30.5, 0), new THREE.Vector3(-40, 0, 0)),
    radius: 1
  },

  mass: 0,
  material: tubeMaterial
}).addTo(world);

// RIGHT.
new WHS.Tube({
  geometry: {
    path: new THREE.LineCurve3(new THREE.Vector3(29.5, 30.5, 0), new THREE.Vector3(40, 0, 0)),
    radius: 1
  },

  mass: 0,
  material: tubeMaterial
}).addTo(world);

const sphere = new WHS.Sphere({
  geometry: {
    radius: 3,
    widthSegments: 32,
    heightSegments: 32
  },

  mass: 3,

  material: {
    color: 0xffffff,
    kind: 'basic'
  },

  position: {
    x: -20,
    y: 10,
    z: 0
  }
});

const sphereHandler = [];

for (let i = 0; i < 5; i++) {
  const sc = sphere.clone();
  sc.position.x = -20 + i * 6;
  sc.material = sc.material.clone();
  sc.addTo(world);
  sphereHandler.push(sc);

  const v1 = sc.position.clone();
  const v2 = sc.position.clone();
  v2.y = 30;

  const rope = new WHS.Line({
    geometry: {
      curve: new THREE.LineCurve3(v1, v2)
    },

    physics: {
      piterations: 10,
      viterations: 10
    },

    mass: 1,

    softbody: true
  });

  rope.addTo(world).then(() => {
    rope.appendAnchor(world, toptube, 50, 1);
    rope.appendAnchor(world, sc, 0, 1);
  });
}

const sphereStart = new WHS.Sphere({
  geometry: {
    radius: 3,
    widthSegments: 32,
    heightSegments: 32
  },

  mass: 3,

  material: {
    color: 0xffffff,
    kind: 'basic'
  },

  position: {
    x: 25,
    y: 15,
    z: 0
  }
});

sphereStart.addTo(world);
sphereHandler.push(sphereStart);

const rope1 = new WHS.Line({
  geometry: {
    curve: new THREE.LineCurve3(sphereStart.position.clone(), new THREE.Vector3(10, 30, 0))
  },

  physics: {
    piterations: 10,
    viterations: 10
  },

  mass: 1,

  softbody: true
});

rope1.addTo(world);

rope1.appendAnchor(world, toptube, 50, 1);
rope1.appendAnchor(world, sphereStart, 0, 1);

new WHS.Plane({
  geometry: {
    width: 250,
    height: 250
  },

  mass: 0,

  material: {
    color: 0xff0000,
    kind: 'basic',
    transparent: true,
    opacity: 0
  },

  position: {
    x: 0,
    y: 0,
    z: 0
  },

  rotation: {
    x: -Math.PI / 2
  }
}).addTo(world);

new WHS.SpotLight({
  light: {
    intensity: 6,
    distance: 100,
    angle: 90
  },

  position: {
    y: 50
  }
}).addTo(world);

new WHS.AmbientLight({
  light: {
    intensity: 0.6,
    color: 0xffffff
  }
}).addTo(world);

world.start();

// Check mouse.
const mouse = new WHS.VirtualMouse(world);

for (let i = 0, max = sphereHandler.length; i < max; i++) {
  const nows = sphereHandler[i];
  mouse.track(nows);

  let dragged;

  nows.on('mouseover', () => {
    if (!dragged) nows.material.color.set(0xff0000);
  });

  nows.on('mouseout', () => {
    if (!dragged) nows.material.color.set(0xffffff);
  });

  nows.on('mousedown', () => {
    nows.material.color.set(0xff0000);
    dragged = true;
  });

  mouse.on('mouseup', () => {
    nows.material.color.set(0xffffff);
    dragged = false;
  });

  mouse.on('move', () => {
    if (dragged) nows.setLinearVelocity(mouse.project().sub(nows.position).multiplyScalar(3));
  });
}
<commit_msg>Fix softbody/ropes example<commit_after>import * as UTILS from '../../globals';

const mouse = new WHS.app.VirtualMouseModule();

const world = new WHS.App([
  new WHS.app.ElementModule(),
  new WHS.app.SceneModule(),
  new WHS.app.CameraModule({
    position: new THREE.Vector3(0, 15, 60),
    far: 10000
  }),
  new WHS.app.RenderingModule({
    bgColor: 0x162129,

    renderer: {
      antialias: true,
      shadowmap: {
        type: THREE.PCFSoftShadowMap
      }
    }
  }),
  new PHYSICS.WorldModule({
    ammo: process.ammoPath,
    gravity: new THREE.Vector3(0, -10, 0),
    softbody: true
  }),
  new WHS.app.ResizeModule(),
  mouse
]);

const tubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xffffff,
  metalness: 1,
  emissive: 0x333333,
  roughness: 0.4
});

// TOP.
const toptube = new WHS.Tube({
  geometry: {
    path: new THREE.LineCurve3(new THREE.Vector3(-30, 30, 0), new THREE.Vector3(30, 30, 0)),
    radius: 1
  },

  modules: [
    new PHYSICS.ConvexModule({
      mass: 0
    })
  ],

  material: tubeMaterial
});

toptube.addTo(world);

// LEFT.
new WHS.Tube({
  geometry: {
    path: new THREE.LineCurve3(new THREE.Vector3(-29.5, 30.5, 0), new THREE.Vector3(-40, 0, 0)),
    radius: 1
  },

  modules: [
    new PHYSICS.ConvexModule({
      mass: 0
    })
  ],

  material: tubeMaterial
}).addTo(world);

// RIGHT.
new WHS.Tube({
  geometry: {
    path: new THREE.LineCurve3(new THREE.Vector3(29.5, 30.5, 0), new THREE.Vector3(40, 0, 0)),
    radius: 1
  },

  modules: [
    new PHYSICS.ConvexModule({
      mass: 0
    })
  ],

  material: tubeMaterial
}).addTo(world);

const sphere = new WHS.Sphere({
  geometry: {
    radius: 3,
    widthSegments: 32,
    heightSegments: 32
  },

  modules: [
    new PHYSICS.SphereModule({
      mass: 3
    })
  ],

  material: new THREE.MeshBasicMaterial({
    color: 0xffffff
  }),

  position: {
    x: -20,
    y: 10,
    z: 0
  }
});

const sphereHandler = [];
const blackBasic = new THREE.MeshBasicMaterial({color: 0x000000});

for (let i = 0; i < 5; i++) {
  const sc = sphere.clone();
  sc.position.x = -20 + i * 6;
  sc.material = sc.material.clone();
  sc.addTo(world);
  sphereHandler.push(sc);

  const v1 = sc.position.clone();
  const v2 = sc.position.clone();
  v2.y = 30;

  const rope = new WHS.Line({
    geometry: {
      curve: new THREE.LineCurve3(v1, v2)
    },

    material: blackBasic,

    modules: [
      new PHYSICS.RopeModule({
        piterations: 10,
        viterations: 10,
        mass: 1
      })
    ]
  });

  rope.addTo(world).then(() => {
    rope.appendAnchor(toptube, 50, 1);
    rope.appendAnchor(sc, 0, 1);
  });
}

const sphereStart = new WHS.Sphere({
  geometry: {
    radius: 3,
    widthSegments: 32,
    heightSegments: 32
  },

  modules: [
    new PHYSICS.SphereModule({
      mass: 3
    })
  ],

  material: new THREE.MeshBasicMaterial({
    color: 0xffffff
  }),

  position: {
    x: 25,
    y: 15,
    z: 0
  }
});

sphereStart.addTo(world);
sphereHandler.push(sphereStart);

const rope1 = new WHS.Line({
  geometry: {
    curve: new THREE.LineCurve3(sphereStart.position.clone(), new THREE.Vector3(10, 30, 0))
  },

  material: blackBasic,

  modules: [
    new PHYSICS.RopeModule({
      piterations: 10,
      viterations: 10,
      mass: 1
    })
  ]
});

rope1.addTo(world).then(() => {
  rope1.appendAnchor(toptube, 50, 1);
  rope1.appendAnchor(sphereStart, 0, 1);
});

new WHS.Plane({
  geometry: {
    width: 250,
    height: 250
  },

  modules: [
    new PHYSICS.PlaneModule({
      mass: 0
    })
  ],

  material: new THREE.MeshBasicMaterial({
    color: 0xff0000,
    transparent: true,
    opacity: 0
  }),

  position: {
    x: 0,
    y: 0,
    z: 0
  },

  rotation: {
    x: -Math.PI / 2
  }
}).addTo(world);

new WHS.SpotLight({
  light: {
    intensity: 6,
    distance: 100,
    angle: 90
  },

  position: {
    y: 50
  }
}).addTo(world);

new WHS.AmbientLight({
  light: {
    intensity: 0.6,
    color: 0xffffff
  }
}).addTo(world);

world.start();

// Check mouse.

for (let i = 0, max = sphereHandler.length; i < max; i++) {
  const nows = sphereHandler[i];
  mouse.track(nows);

  let dragged;

  nows.on('mouseover', () => {
    if (!dragged) nows.material.color.set(0xff0000);
  });

  nows.on('mouseout', () => {
    if (!dragged) nows.material.color.set(0xffffff);
  });

  nows.on('mousedown', () => {
    nows.material.color.set(0xff0000);
    dragged = true;
  });

  mouse.on('mouseup', () => {
    nows.material.color.set(0xffffff);
    dragged = false;
  });

  mouse.on('move', () => {
    if (dragged) nows.setLinearVelocity(mouse.project().sub(nows.position).multiplyScalar(3));
  });
}
<|endoftext|>