<commit_before>/**
 * @author Eberhard Graether / http://egraether.com/
 */

THREE.LandscapeControls = function ( camera ) {

    THREE.EventTarget.call( this );

    var _this = this;
    STATE = { NONE : -1, ROTATE : 0, PAN : 1, ZOOM : 2 };
    var statefunc = {
        0: this.rotate.bind(this),
        1: this.pan.bind(this),
        2: this.zoom.bind(this),
    }

    this.keystate = null;
    this.camera = camera;
    this.domElement = document.getElementById("braincover");

    // API
    this.enabled = true;

    // Constants
    this.rotateSpeed = .4;
    this.zoomSpeed = .002;
    this.panSpeed = 0.3;
    this.clickTimeout = 200; // milliseconds

    // internals
    this.target = new THREE.Vector3();
    this.azimuth = 45;
    this.altitude = 45;
    this.radius = 200;

    var _state = STATE.NONE,
        _start = new THREE.Vector3(),
        _end = new THREE.Vector3();

    var _mousedowntime = 0;

    // events

    var changeEvent = { type: 'change' };

    this.update = function (flatmix) {
        var mouseChange = _end.clone().subSelf(_start);

        if (mouseChange.length() > 0 && statefunc[_state]) {
            if (statefunc[_state])
                statefunc[_state](mouseChange);
        }

        this._limitview(flatmix);
        this.setCamera();

        _start = _end;
    };

    // listeners
    function keydown( event ) {
        if ( ! this.enabled ) return;

        if (event.keyCode == 17) {
            this.keystate = STATE.ZOOM;
        } else if (event.keyCode == 16) {
            this.keystate = STATE.PAN;
        } else {
            this.keystate = null;
        }

    };

    function keyup( event ) {
        if ( ! this.enabled ) return;
        this.keystate = null;
    };

    function mousedown( event ) {
        event.preventDefault();
        event.stopPropagation();

        if ( _state === STATE.NONE ) {
            _state = this.keystate ? this.keystate : event.button;
            _start = _end = this.getMouse(event);
            _mousedowntime = new Date().getTime();
        }
    };

    function mousemove( event ) {
        if ( ! this.enabled ) return;

        if ( _state === STATE.NONE ) {
            return;
        } else {
            _end = this.getMouse(event);
        }
        this.dispatchEvent( changeEvent );
    };

    function mouseup( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        _state = STATE.NONE;
        var ctime = new Date().getTime();

        // Run picker if time since mousedown is short enough
        if ( ctime - _mousedowntime < this.clickTimeout && event.button == 0) {
            var mouse2D = this.getMouse(event).clone();
            this.dispatchEvent({ type:"pick", x:mouse2D.x, y:mouse2D.y, keep:this.keystate == STATE.ZOOM});
        }
    };

    function mousewheel( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        this.wheelzoom( event );
        this.setCamera();
        this.dispatchEvent( changeEvent );

    };

    this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );

    this.domElement.addEventListener( 'mousemove', mousemove.bind(this), false );
    this.domElement.addEventListener( 'mousedown', mousedown.bind(this), false );
    this.domElement.addEventListener( 'mouseup', mouseup.bind(this), false );
    this.domElement.addEventListener( 'mousewheel', mousewheel.bind(this), false);
    this.domElement.addEventListener( 'mouseout', mouseup.bind(this), false );

    window.addEventListener( 'keydown', keydown.bind(this), false );
    window.addEventListener( 'keyup', keyup.bind(this), false );

    this.resize($("#brain").width(), $("#brain").height() );
    this._limitview({flat:0});
    this.setCamera();
};

THREE.LandscapeControls.prototype = {
    _limitview: function( flatmix ) {
        var azlim = flatmix * 180;
        var altlim = flatmix * 90;

        this.altitude = this.altitude > 179.9999-altlim ? 179.9999-altlim : this.altitude;
        this.altitude = this.altitude < 0.0001+altlim ? 0.0001+altlim : this.altitude;

        if (azlim > this.azimuth || this.azimuth > (360 - azlim)) {
            var d1 = azlim - this.azimuth;
            var d2 = 360 - azlim - this.azimuth;
            this.azimuth = Math.abs(d1) > Math.abs(d2) ? 360-azlim : azlim;
        }

        var rad = this.radius, target = this.target.clone();
        if ($("#zlockwhole")[0].checked) {
            rad  = this.flatsize / 2 / this.camera.aspect;
            rad /= Math.tan(this.camera.fov / 2 * Math.PI / 180);
            rad -= this.flatoff;
            rad = flatmix * rad + (1 - flatmix) * this.radius;
        } else if (!$("#zlocknone")[0].checked) {
            rad  = this.flatsize / 4 / this.camera.aspect;
            rad /= Math.tan(this.camera.fov / 2 * Math.PI / 180);
            rad -= this.flatoff;
            rad = flatmix * rad + (1 - flatmix) * this.radius;
            if ($("#zlockleft")[0].checked) {
                target.x = flatmix * (-this.flatsize / 4) + (1 - flatmix) * target.x;
            } else if ($("#zlockright")[0].checked) {
                target.x = flatmix * ( this.flatsize / 4) + (1 - flatmix) * target.x;
            }
        }

        this._radius = rad;
        this._target = target;
    },

    resize: function(w, h) {
        this.domElement.style.width = w+"px";
        this.domElement.style.height = h+"px";
    },

    getMouse: function ( event ) {
        return new THREE.Vector2( event.clientX, event.clientY);
    },

    setCamera: function(az, alt, rad) {
        if (az !== undefined)
            this.azimuth = az;
        if (alt !== undefined)
            this.altitude = alt;
        if (rad !== undefined)
            this.radius = rad;

        var altrad = this.altitude*Math.PI / 180;
        var azirad = (this.azimuth+90)*Math.PI / 180;

        var eye = new THREE.Vector3(
            this._radius*Math.sin(altrad)*Math.cos(azirad),
            this._radius*Math.sin(altrad)*Math.sin(azirad),
            this._radius*Math.cos(altrad)
        );

        this.camera.position.add( this._target, eye );
        this.camera.lookAt( this._target );
    },

    rotate: function ( mouseChange ) {
        var azdiff = -this.rotateSpeed*mouseChange.x;
        var az = this.azimuth + azdiff;
        if ( this.azlim > 0 ) {
            if ( this.azlim > az || az > (360-this.azlim)) {
                this.azimuth = azdiff < 0 ? this.azlim : 360-this.azlim;
            } else {
                this.azimuth = az - 360*Math.floor(az / 360);
            }
        } else {
            this.azimuth = az - 360*Math.floor(az / 360);
        }

        this.altitude -= this.rotateSpeed*mouseChange.y;

	// Add panning depending on flatmix
	var panMouseChange = new Object;
	panMouseChange.x = mouseChange.x * Math.pow(this.flatmix, 2);
	panMouseChange.y = mouseChange.y * Math.pow(this.flatmix, 2);
	this.pan(panMouseChange);
    },

    pan: function( mouseChange ) {
        var eye = this.camera.position.clone().subSelf(this.target);
        var right = eye.clone().crossSelf( this.camera.up );
        var up = right.clone().crossSelf(eye);
        var pan = (new THREE.Vector3()).add(
            right.setLength( this.panSpeed*mouseChange.x ),
            up.setLength( this.panSpeed*mouseChange.y ));
        this.camera.position.addSelf( pan );
        this.target.addSelf( pan );
    },

    zoom: function( mouseChange ) {
        var factor = 1.0 + mouseChange.y*this.zoomSpeed;
        this.radius *= factor;
    },

    wheelzoom: function( wheelEvent ) {
        var factor = 1.0 + this.zoomSpeed * -1 * wheelEvent.wheelDelta/10.0;
        this.radius *= factor;
    }

}
<commit_msg>small fix to controls<commit_after>/**
 * @author Eberhard Graether / http://egraether.com/
 */

THREE.LandscapeControls = function ( camera ) {

    THREE.EventTarget.call( this );

    var _this = this;
    STATE = { NONE : -1, ROTATE : 0, PAN : 1, ZOOM : 2 };
    var statefunc = {
        0: this.rotate.bind(this),
        1: this.pan.bind(this),
        2: this.zoom.bind(this),
    }

    this.keystate = null;
    this.camera = camera;
    this.domElement = document.getElementById("braincover");

    // API
    this.enabled = true;

    // Constants
    this.rotateSpeed = .4;
    this.zoomSpeed = .002;
    this.panSpeed = 0.3;
    this.clickTimeout = 200; // milliseconds

    // internals
    this.target = new THREE.Vector3();
    this.azimuth = 45;
    this.altitude = 45;
    this.radius = 200;

    var _state = STATE.NONE,
        _start = new THREE.Vector3(),
        _end = new THREE.Vector3();

    var _mousedowntime = 0;

    // events

    var changeEvent = { type: 'change' };

    this.update = function (flatmix) {
        var mouseChange = _end.clone().subSelf(_start);

        if (mouseChange.length() > 0 && statefunc[_state]) {
            if (statefunc[_state])
                statefunc[_state](mouseChange);
        }

        this._limitview(flatmix);
	this.flatmix = flatmix;
        this.setCamera();

        _start = _end;
    };

    // listeners
    function keydown( event ) {
        if ( ! this.enabled ) return;

        if (event.keyCode == 17) {
            this.keystate = STATE.ZOOM;
        } else if (event.keyCode == 16) {
            this.keystate = STATE.PAN;
        } else {
            this.keystate = null;
        }

    };

    function keyup( event ) {
        if ( ! this.enabled ) return;
        this.keystate = null;
    };

    function mousedown( event ) {
        event.preventDefault();
        event.stopPropagation();

        if ( _state === STATE.NONE ) {
            _state = this.keystate ? this.keystate : event.button;
            _start = _end = this.getMouse(event);
            _mousedowntime = new Date().getTime();
        }
    };

    function mousemove( event ) {
        if ( ! this.enabled ) return;

        if ( _state === STATE.NONE ) {
            return;
        } else {
            _end = this.getMouse(event);
        }
        this.dispatchEvent( changeEvent );
    };

    function mouseup( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        _state = STATE.NONE;
        var ctime = new Date().getTime();

        // Run picker if time since mousedown is short enough
        if ( ctime - _mousedowntime < this.clickTimeout && event.button == 0) {
            var mouse2D = this.getMouse(event).clone();
            this.dispatchEvent({ type:"pick", x:mouse2D.x, y:mouse2D.y, keep:this.keystate == STATE.ZOOM});
        }
    };

    function mousewheel( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        this.wheelzoom( event );
        this.setCamera();
        this.dispatchEvent( changeEvent );

    };

    this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );

    this.domElement.addEventListener( 'mousemove', mousemove.bind(this), false );
    this.domElement.addEventListener( 'mousedown', mousedown.bind(this), false );
    this.domElement.addEventListener( 'mouseup', mouseup.bind(this), false );
    this.domElement.addEventListener( 'mousewheel', mousewheel.bind(this), false);
    this.domElement.addEventListener( 'mouseout', mouseup.bind(this), false );

    window.addEventListener( 'keydown', keydown.bind(this), false );
    window.addEventListener( 'keyup', keyup.bind(this), false );

    this.resize($("#brain").width(), $("#brain").height() );
    this._limitview({flat:0});
    this.setCamera();
};

THREE.LandscapeControls.prototype = {
    _limitview: function( flatmix ) {
        var azlim = flatmix * 180;
        var altlim = flatmix * 90;

        this.altitude = this.altitude > 179.9999-altlim ? 179.9999-altlim : this.altitude;
        this.altitude = this.altitude < 0.0001+altlim ? 0.0001+altlim : this.altitude;

        if (azlim > this.azimuth || this.azimuth > (360 - azlim)) {
            var d1 = azlim - this.azimuth;
            var d2 = 360 - azlim - this.azimuth;
            this.azimuth = Math.abs(d1) > Math.abs(d2) ? 360-azlim : azlim;
        }

        var rad = this.radius, target = this.target.clone();
        if ($("#zlockwhole")[0].checked) {
            rad  = this.flatsize / 2 / this.camera.aspect;
            rad /= Math.tan(this.camera.fov / 2 * Math.PI / 180);
            rad -= this.flatoff;
            rad = flatmix * rad + (1 - flatmix) * this.radius;
        } else if (!$("#zlocknone")[0].checked) {
            rad  = this.flatsize / 4 / this.camera.aspect;
            rad /= Math.tan(this.camera.fov / 2 * Math.PI / 180);
            rad -= this.flatoff;
            rad = flatmix * rad + (1 - flatmix) * this.radius;
            if ($("#zlockleft")[0].checked) {
                target.x = flatmix * (-this.flatsize / 4) + (1 - flatmix) * target.x;
            } else if ($("#zlockright")[0].checked) {
                target.x = flatmix * ( this.flatsize / 4) + (1 - flatmix) * target.x;
            }
        }

        this._radius = rad;
        this._target = target;
    },

    resize: function(w, h) {
        this.domElement.style.width = w+"px";
        this.domElement.style.height = h+"px";
    },

    getMouse: function ( event ) {
        return new THREE.Vector2( event.clientX, event.clientY);
    },

    setCamera: function(az, alt, rad) {
        if (az !== undefined)
            this.azimuth = az;
        if (alt !== undefined)
            this.altitude = alt;
        if (rad !== undefined)
            this.radius = rad;

        var altrad = this.altitude*Math.PI / 180;
        var azirad = (this.azimuth+90)*Math.PI / 180;

        var eye = new THREE.Vector3(
            this._radius*Math.sin(altrad)*Math.cos(azirad),
            this._radius*Math.sin(altrad)*Math.sin(azirad),
            this._radius*Math.cos(altrad)
        );

        this.camera.position.add( this._target, eye );
        this.camera.lookAt( this._target );
    },

    rotate: function ( mouseChange ) {
        var azdiff = -this.rotateSpeed*mouseChange.x;
        var az = this.azimuth + azdiff;
        if ( this.azlim > 0 ) {
            if ( this.azlim > az || az > (360-this.azlim)) {
                this.azimuth = azdiff < 0 ? this.azlim : 360-this.azlim;
            } else {
                this.azimuth = az - 360*Math.floor(az / 360);
            }
        } else {
            this.azimuth = az - 360*Math.floor(az / 360);
        }

        this.altitude -= this.rotateSpeed*mouseChange.y;

	// Add panning depending on flatmix
	var panMouseChange = new Object;
	panMouseChange.x = mouseChange.x * Math.pow(this.flatmix, 2);
	panMouseChange.y = mouseChange.y * Math.pow(this.flatmix, 2);
	this.pan(panMouseChange);
    },

    pan: function( mouseChange ) {
        var eye = this.camera.position.clone().subSelf(this.target);
        var right = eye.clone().crossSelf( this.camera.up );
        var up = right.clone().crossSelf(eye);
        var pan = (new THREE.Vector3()).add(
            right.setLength( this.panSpeed*mouseChange.x ),
            up.setLength( this.panSpeed*mouseChange.y ));
        this.camera.position.addSelf( pan );
        this.target.addSelf( pan );
    },

    zoom: function( mouseChange ) {
        var factor = 1.0 + mouseChange.y*this.zoomSpeed;
        this.radius *= factor;
    },

    wheelzoom: function( wheelEvent ) {
        var factor = 1.0 + this.zoomSpeed * -1 * wheelEvent.wheelDelta/10.0;
        this.radius *= factor;
    }

}
<|endoftext|>


<commit_before>var http = require('http');

// dados teste para testar o merge
var gitlab_mergerequest_body = {
    'object_attributes': {
        'target_project_id': 42,
        'target_branch': 'master',
        'merge_status': 'can_be_merged',
        'source_branch': 'teste',
        'created_at': '2014-08-07T15: 24: 56.404Z',
        'title': 'Teste',
        'updated_at': '2014-08-07T15: 26: 15.752Z',
        'assignee_id': None,
        'iid': 45,
        'state': 'opened',
        'author_id': 13,
        'milestone_id': None,
        'id': 58,
        'source_project_id': 42,
        'description': ''
    },
    'object_kind': 'merge_request'
};

var mergereqString = JSON.stringify(gitlab_mergerequest_body);

var headers = {
  'Content-Type': 'application/json',
  'Content-Length': mergereqString.length
};

var options = {
  host: '127.0.0.1',
  port: 5000,
  method: 'POST',
  headers: headers
};

// testa envio de dados "merge"
var req = http.request(options, function(res) {
  res.setEncoding('utf-8');

  var responseString = '';

  res.on('data', function(data) {
    responseString += data;
  });

  res.on('end', function() {
    var resultObject = JSON.parse(responseString);
    console.log(responseString);
  });
});

req.on('error', function(e) {
  // TODO: handle error.
  console.log('ocorreu erro: ' + e);
});

req.write(mergereqString);
req.end();
<commit_msg>Corrige dados para teste de merge request<commit_after>var http = require('http');

// dados teste para testar o merge
var gitlab_mergerequest_body = {
    'object_attributes': {
        'target_project_id': 42,
        'target_branch': 'master',
        'merge_status': 'can_be_merged',
        'source_branch': 'teste',
        'created_at': '2014-08-07T15: 24: 56.404Z',
        'title': 'Teste',
        'updated_at': '2014-08-07T15: 26: 15.752Z',
        'assignee_id': "None",
        'iid': 45,
        'state': 'opened',
        'author_id': 13,
        'milestone_id': "None",
        'id': 58,
        'source_project_id': 42,
        'description': ''
    },
    'object_kind': 'merge_request'
};

var mergereqString = JSON.stringify(gitlab_mergerequest_body);

var headers = {
  'Content-Type': 'application/json',
  'Content-Length': mergereqString.length
};

var options = {
  host: '127.0.0.1',
  port: 5000,
  method: 'POST',
  headers: headers
};

// testa envio de dados "merge"
var req = http.request(options, function(res) {
  res.setEncoding('utf-8');

  var responseString = '';

  res.on('data', function(data) {
    responseString += data;
  });

  res.on('end', function() {
    var resultObject = JSON.parse(responseString);
    console.log(responseString);
  });
});

req.on('error', function(e) {
  // TODO: handle error.
  console.log('ocorreu erro: ' + e);
});

req.write(mergereqString);
req.end();
<|endoftext|>


<commit_before>/**
 * Marionette Routing
 *
 * Copyright © 2015-2016 Luiz Américo Pereira Câmara. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import _ from 'underscore'
import Radio from 'backbone.radio'
import cherrytree from 'cherrytree'
import Route from './route'

let mnRouteMap = Object.create(null)
export const routerChannel = Radio.channel('router')
let router

export function createRouter(options) {
  if (router) {
    throw new Error('Instance of router already created')
  }
  return router = Route.prototype.$router = cherrytree(options)
}

export function destroyRouter(instance) {
  router = null
  Route.prototype.$router = null
  mnRouteMap = Object.create(null)
  instance.destroy()
}

export function getMnRoutes(routes) {
  return routes.map(function (route) {
    return mnRouteMap[route.name]
  })
}

routerChannel.reply('transitionTo', function () {
  return router.transitionTo.apply(router, arguments)
})

routerChannel.reply('isActive', function () {
  return router.isActive.apply(router, arguments)
})

routerChannel.reply('generate', function () {
  return router.generate.apply(router, arguments)
})

routerChannel.reply('goBack', function () {
  //in wait of a better implementation
  history.back();
})

function getChangingIndex(prevRoutes, currentRoutes){
  var index, prev, current;
  const count = Math.max(prevRoutes.length, currentRoutes.length)
  for (index = 0; index < count; index++) {
    prev = prevRoutes[index]
    current = currentRoutes[index]
    if (!(prev && current) || (prev.name !== current.name) || !_.isEqual(prev.params, current.params)) {
      break
    }
  }
  return index
}

function findRouteConfig(routeName, index, routes) {
  let parentRoutes = routes.slice(0, index).reverse().map(function (route) {
    return mnRouteMap[route.name]
  })
  let config
  parentRoutes.some(function (route) {
    let childRoutes = _.result(route, 'childRoutes')
    config = childRoutes && childRoutes[routeName]
    if (_.isFunction(config) && !(config.prototype instanceof Route)) {
      config = config.call(route)
    }
    return config
  })
  return config
}

function createRouteInstance(options, config) {
  if (options.prototype instanceof Route) {
    return new options()
  }
  let routeOptions = _.extend({}, options.routeOptions, _.pick(options, ['viewClass', 'viewOptions']))
  if (options.routeClass) {
    return new options.routeClass(routeOptions, config)
  } else if (options.viewClass) {
    return new Route(routeOptions, config)
  }
}

function createMnRoute(route, index, routes) {
  let instanceConfig = {
    name: route.name,
    path: route.path,
    options: _.clone(route.options)
  }
  let instance = createRouteInstance(route.options, instanceConfig)
  if (!instance) {
    let routeConfig = findRouteConfig(route.name, index, routes)
    return Promise.resolve(routeConfig).then(function (options) {
      return options && createRouteInstance(options, instanceConfig)
    })
  }
  return instance
}

function getParentRegion(routes, route) {
  var region, parent
  let routeIndex = routes.indexOf(route) - 1
  while (routeIndex >= 0) {
    parent = routes[routeIndex]
    if (parent.view && parent.$config.options.outlet !== false) {
      region = parent.getOutlet()
      if (region) {
        return region
      } else {
        throw new Error(`No outlet region defined in ${parent.$config.name} route`)
      }
    }
    routeIndex--
  }
  if (!router.rootRegion) {
    throw new Error('No root outlet region defined')
  }
  return router.rootRegion
}

export function middleware(transition) {

  routerChannel.trigger('before:transition', transition)

  if (transition.isCancelled) return ;

  let prevRoutes = transition.prev.routes
  let changingIndex = getChangingIndex(prevRoutes, transition.routes)
  var routeIndex, routeInstance, deactivated = []

  //deactivate previous routes
  for (routeIndex = prevRoutes.length - 1; routeIndex >= changingIndex; routeIndex--) {
    routeInstance = mnRouteMap[prevRoutes[routeIndex].name]
    if (routeInstance) {
      deactivated.push(routeInstance)
    }
  }

  if (deactivated.some(function (route) {
      routerChannel.trigger('before:deactivate', transition, route)
      return transition.isCancelled
    })) return

  if (deactivated.some(function (route) {
      route.deactivate(transition)
      routerChannel.trigger('deactivate', transition, route)
      return transition.isCancelled
    })) return

  //build route tree and creating instances if necessary
  let mnRoutes = transition.mnRoutes = []

  let promise = transition.routes.reduce(function (acc, route, i, routes) {
    return acc.then(function (res) {
      let instance = mnRouteMap[route.name]
      if (instance) {
        res.push(instance)
        return res
      } else {
        instance = createMnRoute(route, i, routes)
        return Promise.resolve(instance).then(function (mnRoute) {
          if (!mnRoute) {
            throw new Error(`Unable to create route ${route.name}: routeClass or viewClass must be defined`)
          }
          mnRouteMap[route.name] = mnRoute
          res.push(mnRoute)
          return res
        })
      }
    });
  }, Promise.resolve(mnRoutes));

  //activate routes in order
  let activated

  promise = promise.then(function () {
    activated = mnRoutes.slice(changingIndex)
    return activated.reduce(function (prevPromise, mnRoute) {
      routerChannel.trigger('before:activate', transition, mnRoute)
      return prevPromise.then(function () {
        if (!transition.isCancelled) {
          return Promise.resolve(mnRoute.activate(transition)).then(function () {
            if (!transition.isCancelled) {
              routerChannel.trigger('activate', transition, mnRoute)
            }
          })
        }
        return Promise.resolve()
      })
    }, Promise.resolve())
  })

  transition.then(function () {
    router.state.mnRoutes = mnRoutes
    routerChannel.trigger('transition', transition)
  }).catch(function (err) {
    if (err.type !== 'TransitionCancelled' && err.type !== 'TransitionRedirected') {
      routerChannel.trigger('transition:error', transition, err)
    }
  })

  //render views
  return promise.then(function () {
    if (transition.isCancelled) return ;
    //ensure at least the target (last) route is rendered
    if (!activated.length && mnRoutes.length) {
      activated.push(mnRoutes[mnRoutes.length - 1])
    }

    let renderQueue = activated.reduce(function (memo, mnRoute) {
      if (mnRoute.viewClass) {
        if (memo.length && memo[memo.length - 1].$config.options.outlet === false) {
          memo.pop()
        }
        memo.push(mnRoute)
      }
      return memo
    }, [])

    renderQueue.forEach(function (mnRoute) {
      let parentRegion = getParentRegion(mnRoutes, mnRoute)
      mnRoute.renderView(parentRegion, transition)
    })
  })
}<commit_msg>Fix setting $config property when options is a Route class<commit_after>/**
 * Marionette Routing
 *
 * Copyright © 2015-2016 Luiz Américo Pereira Câmara. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import _ from 'underscore'
import Radio from 'backbone.radio'
import cherrytree from 'cherrytree'
import Route from './route'

let mnRouteMap = Object.create(null)
export const routerChannel = Radio.channel('router')
let router

export function createRouter(options) {
  if (router) {
    throw new Error('Instance of router already created')
  }
  return router = Route.prototype.$router = cherrytree(options)
}

export function destroyRouter(instance) {
  router = null
  Route.prototype.$router = null
  mnRouteMap = Object.create(null)
  instance.destroy()
}

export function getMnRoutes(routes) {
  return routes.map(function (route) {
    return mnRouteMap[route.name]
  })
}

routerChannel.reply('transitionTo', function () {
  return router.transitionTo.apply(router, arguments)
})

routerChannel.reply('isActive', function () {
  return router.isActive.apply(router, arguments)
})

routerChannel.reply('generate', function () {
  return router.generate.apply(router, arguments)
})

routerChannel.reply('goBack', function () {
  //in wait of a better implementation
  history.back();
})

function getChangingIndex(prevRoutes, currentRoutes){
  var index, prev, current;
  const count = Math.max(prevRoutes.length, currentRoutes.length)
  for (index = 0; index < count; index++) {
    prev = prevRoutes[index]
    current = currentRoutes[index]
    if (!(prev && current) || (prev.name !== current.name) || !_.isEqual(prev.params, current.params)) {
      break
    }
  }
  return index
}

function findRouteConfig(routeName, index, routes) {
  let parentRoutes = routes.slice(0, index).reverse().map(function (route) {
    return mnRouteMap[route.name]
  })
  let config
  parentRoutes.some(function (route) {
    let childRoutes = _.result(route, 'childRoutes')
    config = childRoutes && childRoutes[routeName]
    if (_.isFunction(config) && !(config.prototype instanceof Route)) {
      config = config.call(route)
    }
    return config
  })
  return config
}

function createRouteInstance(options, config) {
  if (options.prototype instanceof Route) {
    return new options(undefined, config)
  }
  let routeOptions = _.extend({}, options.routeOptions, _.pick(options, ['viewClass', 'viewOptions']))
  if (options.routeClass) {
    return new options.routeClass(routeOptions, config)
  } else if (options.viewClass) {
    return new Route(routeOptions, config)
  }
}

function createMnRoute(route, index, routes) {
  let instanceConfig = {
    name: route.name,
    path: route.path,
    options: _.clone(route.options)
  }
  let instance = createRouteInstance(route.options, instanceConfig)
  if (!instance) {
    let routeConfig = findRouteConfig(route.name, index, routes)
    return Promise.resolve(routeConfig).then(function (options) {
      return options && createRouteInstance(options, instanceConfig)
    })
  }
  return instance
}

function getParentRegion(routes, route) {
  var region, parent
  let routeIndex = routes.indexOf(route) - 1
  while (routeIndex >= 0) {
    parent = routes[routeIndex]
    if (parent.view && parent.$config.options.outlet !== false) {
      region = parent.getOutlet()
      if (region) {
        return region
      } else {
        throw new Error(`No outlet region defined in ${parent.$config.name} route`)
      }
    }
    routeIndex--
  }
  if (!router.rootRegion) {
    throw new Error('No root outlet region defined')
  }
  return router.rootRegion
}

export function middleware(transition) {

  routerChannel.trigger('before:transition', transition)

  if (transition.isCancelled) return ;

  let prevRoutes = transition.prev.routes
  let changingIndex = getChangingIndex(prevRoutes, transition.routes)
  var routeIndex, routeInstance, deactivated = []

  //deactivate previous routes
  for (routeIndex = prevRoutes.length - 1; routeIndex >= changingIndex; routeIndex--) {
    routeInstance = mnRouteMap[prevRoutes[routeIndex].name]
    if (routeInstance) {
      deactivated.push(routeInstance)
    }
  }

  if (deactivated.some(function (route) {
      routerChannel.trigger('before:deactivate', transition, route)
      return transition.isCancelled
    })) return

  if (deactivated.some(function (route) {
      route.deactivate(transition)
      routerChannel.trigger('deactivate', transition, route)
      return transition.isCancelled
    })) return

  //build route tree and creating instances if necessary
  let mnRoutes = transition.mnRoutes = []

  let promise = transition.routes.reduce(function (acc, route, i, routes) {
    return acc.then(function (res) {
      let instance = mnRouteMap[route.name]
      if (instance) {
        res.push(instance)
        return res
      } else {
        instance = createMnRoute(route, i, routes)
        return Promise.resolve(instance).then(function (mnRoute) {
          if (!mnRoute) {
            throw new Error(`Unable to create route ${route.name}: routeClass or viewClass must be defined`)
          }
          mnRouteMap[route.name] = mnRoute
          res.push(mnRoute)
          return res
        })
      }
    });
  }, Promise.resolve(mnRoutes));

  //activate routes in order
  let activated

  promise = promise.then(function () {
    activated = mnRoutes.slice(changingIndex)
    return activated.reduce(function (prevPromise, mnRoute) {
      routerChannel.trigger('before:activate', transition, mnRoute)
      return prevPromise.then(function () {
        if (!transition.isCancelled) {
          return Promise.resolve(mnRoute.activate(transition)).then(function () {
            if (!transition.isCancelled) {
              routerChannel.trigger('activate', transition, mnRoute)
            }
          })
        }
        return Promise.resolve()
      })
    }, Promise.resolve())
  })

  transition.then(function () {
    router.state.mnRoutes = mnRoutes
    routerChannel.trigger('transition', transition)
  }).catch(function (err) {
    if (err.type !== 'TransitionCancelled' && err.type !== 'TransitionRedirected') {
      routerChannel.trigger('transition:error', transition, err)
    }
  })

  //render views
  return promise.then(function () {
    if (transition.isCancelled) return ;
    //ensure at least the target (last) route is rendered
    if (!activated.length && mnRoutes.length) {
      activated.push(mnRoutes[mnRoutes.length - 1])
    }

    let renderQueue = activated.reduce(function (memo, mnRoute) {
      if (mnRoute.viewClass) {
        if (memo.length && memo[memo.length - 1].$config.options.outlet === false) {
          memo.pop()
        }
        memo.push(mnRoute)
      }
      return memo
    }, [])

    renderQueue.forEach(function (mnRoute) {
      let parentRegion = getParentRegion(mnRoutes, mnRoute)
      mnRoute.renderView(parentRegion, transition)
    })
  })
}<|endoftext|>


<commit_before>/*
	This file is part of FacilMap.

	FacilMap is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	FacilMap is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with FacilMap.  If not, see <http://www.gnu.org/licenses/>.

	Obtain the source code from http://gitorious.org/facilmap.
*/

/**
 * An abstract class whose implementations connect to a NameFinder.
*/
FacilMap.NameFinder = OpenLayers.Class({
	/**
	 * Perform a search through a NameFinder. This function itself does not connect to an actual NameFinder, it only finds one result if
	 * the query String consists of coordinates encoded in a Lat,Lon string or an OpenStreetMap Permalink.
	 * @param String query The query string.
	 * @param Function callbackFunction A function that is executed when the search has been performed. The function takes one argument that
	 *                                  contains an array with the results. It is undefined if an error has occurred. Each result is an object
	 *                                  with the following properties:
	 *                                  * OpenLayers.LonLat lonlat The coordinates of the result
	 *                                  * String name: The title of the result.
	 *                                  * String info: Some additional information about the result, such as the type.
	 *                                  * function getZoom(OpenLayers.Map): Returns the zoom level that the search result should be displayed at on the given map.
	 *                                  * Node osm: The associated OSM object or null.
	 * @return void
	*/
	find : function(query, callbackFunction) {
		query.replace(/^\s+/, "").replace(/\s+$/, "");
		var query_match;
		var query_urlPart;
		if(query_match = query.match(/^http:\/\/(www\.)?osm\.org\/go\/([-A-Za-z0-9_@]+)/))
		{ // Coordinates, shortlink
			var shortlink = FacilMap.Util.decodeShortLink(query_match[2]);
			results = [ {
				lonlat : shortlink.lonlat,
				info : OpenLayers.i18n("Coordinates"),
				name : shortlink.lonlat.lat + ", " + shortlink.lonlat.lon,
				getZoom : function(map) {
					return shortlink.zoom;
				}
			} ];
			callbackFunction(results);
		}
		else if(query_match = query.match(/^(-?\s*\d+([.,]\d+)?)\s*[,;]?\s*(-?\s*\d+([.,]\d+)?)$/))
		{ // Coordinates
			results = [ {
				lonlat : new OpenLayers.LonLat(query_match[3].replace(",", ".").replace(/\s+/, ""), query_match[1].replace(",", ".").replace(/\s+/, "")),
				info : OpenLayers.i18n("Coordinates"),
				getZoom : function(map) {
					return 15;
				}
			} ];
			results[0].name = results[0].lonlat.lat+","+results[0].lonlat.lon;
			callbackFunction(results);
		}
		else if((query_match = query.match(/^http:\/\/.*\?(.*)$/)) && typeof (query_urlPart = FacilMap.Util.decodeQueryString(query_match[1])).lon != "undefined" && typeof query_urlPart.lat != "undefined")
		{ // OpenStreetMap Permalink
			results = [ {
				lonlat : new OpenLayers.LonLat(query_urlPart.lon, query_urlPart.lat),
				info : OpenLayers.i18n("Coordinates"),
				name : query_urlPart.lat + ", " + query_urlPart.lon,
				zoomCallback : function(map) {
					if(query_urlPart.zoom == undefined)
						return 15;
					else
						return 1*query_urlPart.zoom;
				}
			} ];
			callbackFunction(results);
		}
		else
			callbackFunction([ ]);
	},

	/**
	 * Returns an array of the position and length of an actual place that is searched for with the given query.
	 * If a name finder for example allows to search for supermarkets in London using the query string
	 * "supermarket, London, UK" then this function would return (13, 9) which is "London, UK" in that string.
	 * This is important for the auto-suggest feature as you only want to get suggestions for actual places, not
	 * for POIs that you search for.
	 * @param String query
	 * @return Array An array of offset and length of the location part or null if there is no such
	*/
	getLocationPart : function(query) {
		return [ 0, query.length ];
	},

	/**
	 * Initilise an auto-suggest feature on a text input field that will use this NameFinder.
	 *
	 * Creates the following properties on the input node:
	 * - fmAutocompleteTimeout
	 * - fmAutocompleteLoadingValue
	 * - fmAutocompleteLoadedValue
	 * - fmAutocompleteList
	 * - fmAutocompleteResults: The list of results returned by the namefinder
	 * - fmAutocompleteSelected
	 * - fmAutocompletePrevious
	 * @param Element input The DOM node of a text input field.
	 * @return void
	*/
	initAutoSuggest : function(input) {
		input.setAttribute("autocomplete", "off");

		// Opera fix
		input.style.position = "relative";

		var namefinder = this;

		OpenLayers.Event.observe(input, "keypress", OpenLayers.Function.bindAsEventListener(this._autoSuggestKeyPress, this));

		var clickOpener = OpenLayers.Function.bindAsEventListener(function() { this._openAutoSuggest(input); }, this);

		OpenLayers.Event.observe(input, "focus", OpenLayers.Function.bindAsEventListener(function(e){
			setTimeout(function(){ OpenLayers.Event.observe(input, "click", clickOpener); }, 150);
		}, this));
		OpenLayers.Event.observe(input, "blur", OpenLayers.Function.bindAsEventListener(function(e){
			OpenLayers.Event.stopObserving(input, "click", clickOpener);
		}, this));

		// Wait some time before closing the suggestion list on blur so that clicking the results still works
		OpenLayers.Event.observe(input, "blur", OpenLayers.Function.bindAsEventListener(function(){ setTimeout(function(){ namefinder._closeAutoSuggest(input); }, 150) }, this));
	},

	_autoSuggestKeyPress : function(e) {
		var input = e.target || e.srcElement;
		var namefinder = this;

		var kc_down = 40;
		var kc_up = 38;
		var kc_return = 13;
		var kc_enter = 14;
		var kc_escape = 27;

		if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
		{
			if(e.keyCode == kc_down || e.keyCode == kc_up)
			{
				this._openAutoSuggest(input);
				if(input.fmAutocompleteResults == null)
					return true;

				var currentIndex = -1;
				if(input.fmAutocompleteSelected != null)
				{
					this._unselectAutoSuggestItem(input, input.fmAutocompleteSelected);
					currentIndex = input.fmAutocompleteSelected.i;
					input.fmAutocompleteSelected = null;
				}

				if(currentIndex == -1)
					currentIndex = (e.keyCode == kc_up ? input.fmAutocompleteResults.length-1 : 0);
				else
				{
					currentIndex += (e.keyCode == kc_up ? -1 : 1);
					if(currentIndex < 0)
						currentIndex += input.fmAutocompleteResults.length;
					else if(currentIndex >= input.fmAutocompleteResults.length)
						currentIndex -= input.fmAutocompleteResults.length;
				}

				input.fmAutocompleteSelected = input.fmAutocompleteResults[currentIndex];
				this._selectAutoSuggestItem(input, input.fmAutocompleteSelected);

				OpenLayers.Event.stop(e);
				return false;
			}
			else if(e.keyCode == kc_return || e.keyCode == kc_enter)
			{
				if(input.fmAutocompleteSelected)
				{
					input.value = input.fmAutocompleteSelected.name;
					this._closeAutoSuggest(input);
					OpenLayers.Event.stop(e);
					return false;
				}
				else
				{
					if(input.fmAutocompleteTimeout != null)
						clearTimeout(input.fmAutocompleteTimeout);
					if(input.fmAutocompleteList && input.fmAutocompleteList.style.display != "none")
						this._closeAutoSuggest(input);
				}
				return true;
			}
			else if(e.keyCode == kc_escape)
			{
				if(input.fmAutocompleteList && input.fmAutocompleteList.style.display != "none")
				{
					this._closeAutoSuggest(input);
					OpenLayers.Event.stop(e);
					return false;
				}
			}
		}

		if(input.fmAutocompletePrevious == input.value)
			return true;
		input.fmAutocompletePrevious = input.value;

		if(input.fmAutocompleteTimeout != null)
			clearTimeout(input.fmAutocompleteTimeout);
		input.fmAutocompleteTimeout = setTimeout(function(){ namefinder._openAutoSuggest(input); }, 500);
		return true;
	},

	_openAutoSuggest : function(input) {
		input.fmAutocompletePrevious = input.value;

		var offset = this.getLocationPart(input.value);
		var val = (offset == null ? input.value : input.value.substr(offset[0], offset[1]));
		var valOrig = input.value;

		if(input.fmAutocompleteLoadingValue != null && input.fmAutocompleteLoadingValue == val)
		{ // List is already present, only make it visible again
			if(input.fmAutocompleteList != null)
				input.fmAutocompleteList.style.display = "block";
			return;
		}

		if(val == "" || (offset == null || offset[1] < 3))
		{
			this._closeAutoSuggest(input);
			return;
		}

		var namefinder = this;
		input.fmAutocompleteLoadingValue = val;
		if(offset != null) // If null, there is no location part so no search is useful
			this.find(val, function(results){ input.fmAutocompleteLoadedValue = val; namefinder._openAutoSuggestResult(input, results, valOrig); });
	},

	_openAutoSuggestResult : function(input, results, value) {
		// Do not show list if loading has been aborted by _closeAutoSuggest() in the meantime
		if(input.fmAutocompleteLoadingValue == null || results == null)
			return;

		var namefinder = this;

		input.fmAutocompleteResults = results;

		if(input.fmAutocompleteList == null)
		{
			input.fmAutocompleteList = document.createElement("ol");
			input.fmAutocompleteList.className = "fmAutocomplete";
			input.fmAutocompleteList.style.position = "absolute";
			input.fmAutocompleteList.style.top = (input.offsetTop + input.offsetHeight) + "px";
			input.fmAutocompleteList.style.left = input.offsetLeft + "px";
			input.fmAutocompleteList.style.minWidth = input.offsetWidth + "px";
			input.parentNode.appendChild(input.fmAutocompleteList);
		}

		while(input.fmAutocompleteList.firstChild)
			input.fmAutocompleteList.removeChild(input.fmAutocompleteList.firstChild);

		var offset = this.getLocationPart(value);

		var foundSelection = false;
		for(var i=0; i<results.length; i++) (function(i)
		{
			var li = document.createElement("li");
			var name = document.createElement("strong");
			name.appendChild(document.createTextNode(results[i].name));
			results[i].name = value.substr(0, offset[0]) + results[i].name + value.substr(offset[0]+offset[1]);
			li.appendChild(name);
			li.appendChild(document.createTextNode(" (" + results[i].info + ")"));
			input.fmAutocompleteList.appendChild(li);
			results[i].li = li;
			results[i].i = i;
			if(!foundSelection && input.fmAutocompleteSelected != null && input.fmAutocompleteSelected.lonlat == results[i].lonlat && input.fmAutocompleteSelected.name == results[i].name && input.fmAutocompleteSelected.info == results[i].info)
			{
				namefinder._selectAutoSuggestItem(input, results[i]);
				input.fmAutocompleteSelected = results[i];
				foundSelection = true;
			}
			li.onmousemove = function() {
				if(input.fmAutocompleteSelected != null)
					namefinder._unselectAutoSuggestItem(input, input.fmAutocompleteSelected);
				input.fmAutocompleteSelected = results[i];
				namefinder._selectAutoSuggestItem(input, results[i]);
			};
			li.onclick = function() {
				input.value = results[i].name;
				namefinder._closeAutoSuggest(input);
			};
		})(i);

		if(!foundSelection)
			input.fmAutocompleteSelected = null;

		input.fmAutocompleteList.style.display = "block";
	},

	_closeAutoSuggest : function(input) {
		if(input.fmAutocompleteTimeout != null)
			clearTimeout(input.fmAutocompleteTimeout);

		// Prevent showing the list if find() is currently waiting for a response
		input.fmAutocompleteLoadingValue = null;

		if(input.fmAutocompleteList != null)
			input.fmAutocompleteList.style.display = "none";
		if(input.fmAutocompleteSelected != null)
		{
			this._unselectAutoSuggestItem(input, input.fmAutocompleteSelected);
			input.fmAutocompleteSelected = null;
		}
	},

	_selectAutoSuggestItem : function(input, item)
	{
		item.li.className = "selected";

		// Scroll to item
		var list = input.fmAutocompleteList;
		if(list == null || list.scrollTop == undefined)
			return;

		var itemTop = item.li.offsetTop;
		var itemBottom = itemTop + item.li.offsetHeight;

		if(itemTop < list.scrollTop) // Need to scroll up
			list.scrollTop = itemTop;
		else if(itemBottom > list.scrollTop + list.offsetHeight) // Need to scroll down
			list.scrollTop = itemBottom - list.offsetHeight;
	},

	_unselectAutoSuggestItem : function(input, item)
	{
		item.li.className = "";
	}
});<commit_msg>Fixed searching for OSM Permalinks.<commit_after>/*
	This file is part of FacilMap.

	FacilMap is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	FacilMap is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with FacilMap.  If not, see <http://www.gnu.org/licenses/>.

	Obtain the source code from http://gitorious.org/facilmap.
*/

/**
 * An abstract class whose implementations connect to a NameFinder.
*/
FacilMap.NameFinder = OpenLayers.Class({
	/**
	 * Perform a search through a NameFinder. This function itself does not connect to an actual NameFinder, it only finds one result if
	 * the query String consists of coordinates encoded in a Lat,Lon string or an OpenStreetMap Permalink.
	 * @param String query The query string.
	 * @param Function callbackFunction A function that is executed when the search has been performed. The function takes one argument that
	 *                                  contains an array with the results. It is undefined if an error has occurred. Each result is an object
	 *                                  with the following properties:
	 *                                  * OpenLayers.LonLat lonlat The coordinates of the result
	 *                                  * String name: The title of the result.
	 *                                  * String info: Some additional information about the result, such as the type.
	 *                                  * function getZoom(OpenLayers.Map): Returns the zoom level that the search result should be displayed at on the given map.
	 *                                  * Node osm: The associated OSM object or null.
	 * @return void
	*/
	find : function(query, callbackFunction) {
		query.replace(/^\s+/, "").replace(/\s+$/, "");
		var query_match;
		var query_urlPart;
		if(query_match = query.match(/^http:\/\/(www\.)?osm\.org\/go\/([-A-Za-z0-9_@]+)/))
		{ // Coordinates, shortlink
			var shortlink = FacilMap.Util.decodeShortLink(query_match[2]);
			results = [ {
				lonlat : shortlink.lonlat,
				info : OpenLayers.i18n("Coordinates"),
				name : shortlink.lonlat.lat + ", " + shortlink.lonlat.lon,
				getZoom : function(map) {
					return shortlink.zoom;
				}
			} ];
			callbackFunction(results);
		}
		else if(query_match = query.match(/^(-?\s*\d+([.,]\d+)?)\s*[,;]?\s*(-?\s*\d+([.,]\d+)?)$/))
		{ // Coordinates
			results = [ {
				lonlat : new OpenLayers.LonLat(query_match[3].replace(",", ".").replace(/\s+/, ""), query_match[1].replace(",", ".").replace(/\s+/, "")),
				info : OpenLayers.i18n("Coordinates"),
				getZoom : function(map) {
					return 15;
				}
			} ];
			results[0].name = results[0].lonlat.lat+","+results[0].lonlat.lon;
			callbackFunction(results);
		}
		else if((query_match = query.match(/^http:\/\/.*\?(.*)$/)) && typeof (query_urlPart = FacilMap.Util.decodeQueryString(query_match[1])).lon != "undefined" && typeof query_urlPart.lat != "undefined")
		{ // OpenStreetMap Permalink
			results = [ {
				lonlat : new OpenLayers.LonLat(query_urlPart.lon, query_urlPart.lat),
				info : OpenLayers.i18n("Coordinates"),
				name : query_urlPart.lat + ", " + query_urlPart.lon,
				getZoom : function(map) {
					if(query_urlPart.zoom == undefined)
						return 15;
					else
						return 1*query_urlPart.zoom;
				}
			} ];
			callbackFunction(results);
		}
		else
			callbackFunction([ ]);
	},

	/**
	 * Returns an array of the position and length of an actual place that is searched for with the given query.
	 * If a name finder for example allows to search for supermarkets in London using the query string
	 * "supermarket, London, UK" then this function would return (13, 9) which is "London, UK" in that string.
	 * This is important for the auto-suggest feature as you only want to get suggestions for actual places, not
	 * for POIs that you search for.
	 * @param String query
	 * @return Array An array of offset and length of the location part or null if there is no such
	*/
	getLocationPart : function(query) {
		return [ 0, query.length ];
	},

	/**
	 * Initilise an auto-suggest feature on a text input field that will use this NameFinder.
	 *
	 * Creates the following properties on the input node:
	 * - fmAutocompleteTimeout
	 * - fmAutocompleteLoadingValue
	 * - fmAutocompleteLoadedValue
	 * - fmAutocompleteList
	 * - fmAutocompleteResults: The list of results returned by the namefinder
	 * - fmAutocompleteSelected
	 * - fmAutocompletePrevious
	 * @param Element input The DOM node of a text input field.
	 * @return void
	*/
	initAutoSuggest : function(input) {
		input.setAttribute("autocomplete", "off");

		// Opera fix
		input.style.position = "relative";

		var namefinder = this;

		OpenLayers.Event.observe(input, "keypress", OpenLayers.Function.bindAsEventListener(this._autoSuggestKeyPress, this));

		var clickOpener = OpenLayers.Function.bindAsEventListener(function() { this._openAutoSuggest(input); }, this);

		OpenLayers.Event.observe(input, "focus", OpenLayers.Function.bindAsEventListener(function(e){
			setTimeout(function(){ OpenLayers.Event.observe(input, "click", clickOpener); }, 150);
		}, this));
		OpenLayers.Event.observe(input, "blur", OpenLayers.Function.bindAsEventListener(function(e){
			OpenLayers.Event.stopObserving(input, "click", clickOpener);
		}, this));

		// Wait some time before closing the suggestion list on blur so that clicking the results still works
		OpenLayers.Event.observe(input, "blur", OpenLayers.Function.bindAsEventListener(function(){ setTimeout(function(){ namefinder._closeAutoSuggest(input); }, 150) }, this));
	},

	_autoSuggestKeyPress : function(e) {
		var input = e.target || e.srcElement;
		var namefinder = this;

		var kc_down = 40;
		var kc_up = 38;
		var kc_return = 13;
		var kc_enter = 14;
		var kc_escape = 27;

		if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
		{
			if(e.keyCode == kc_down || e.keyCode == kc_up)
			{
				this._openAutoSuggest(input);
				if(input.fmAutocompleteResults == null)
					return true;

				var currentIndex = -1;
				if(input.fmAutocompleteSelected != null)
				{
					this._unselectAutoSuggestItem(input, input.fmAutocompleteSelected);
					currentIndex = input.fmAutocompleteSelected.i;
					input.fmAutocompleteSelected = null;
				}

				if(currentIndex == -1)
					currentIndex = (e.keyCode == kc_up ? input.fmAutocompleteResults.length-1 : 0);
				else
				{
					currentIndex += (e.keyCode == kc_up ? -1 : 1);
					if(currentIndex < 0)
						currentIndex += input.fmAutocompleteResults.length;
					else if(currentIndex >= input.fmAutocompleteResults.length)
						currentIndex -= input.fmAutocompleteResults.length;
				}

				input.fmAutocompleteSelected = input.fmAutocompleteResults[currentIndex];
				this._selectAutoSuggestItem(input, input.fmAutocompleteSelected);

				OpenLayers.Event.stop(e);
				return false;
			}
			else if(e.keyCode == kc_return || e.keyCode == kc_enter)
			{
				if(input.fmAutocompleteSelected)
				{
					input.value = input.fmAutocompleteSelected.name;
					this._closeAutoSuggest(input);
					OpenLayers.Event.stop(e);
					return false;
				}
				else
				{
					if(input.fmAutocompleteTimeout != null)
						clearTimeout(input.fmAutocompleteTimeout);
					if(input.fmAutocompleteList && input.fmAutocompleteList.style.display != "none")
						this._closeAutoSuggest(input);
				}
				return true;
			}
			else if(e.keyCode == kc_escape)
			{
				if(input.fmAutocompleteList && input.fmAutocompleteList.style.display != "none")
				{
					this._closeAutoSuggest(input);
					OpenLayers.Event.stop(e);
					return false;
				}
			}
		}

		if(input.fmAutocompletePrevious == input.value)
			return true;
		input.fmAutocompletePrevious = input.value;

		if(input.fmAutocompleteTimeout != null)
			clearTimeout(input.fmAutocompleteTimeout);
		input.fmAutocompleteTimeout = setTimeout(function(){ namefinder._openAutoSuggest(input); }, 500);
		return true;
	},

	_openAutoSuggest : function(input) {
		input.fmAutocompletePrevious = input.value;

		var offset = this.getLocationPart(input.value);
		var val = (offset == null ? input.value : input.value.substr(offset[0], offset[1]));
		var valOrig = input.value;

		if(input.fmAutocompleteLoadingValue != null && input.fmAutocompleteLoadingValue == val)
		{ // List is already present, only make it visible again
			if(input.fmAutocompleteList != null)
				input.fmAutocompleteList.style.display = "block";
			return;
		}

		if(val == "" || (offset == null || offset[1] < 3))
		{
			this._closeAutoSuggest(input);
			return;
		}

		var namefinder = this;
		input.fmAutocompleteLoadingValue = val;
		if(offset != null) // If null, there is no location part so no search is useful
			this.find(val, function(results){ input.fmAutocompleteLoadedValue = val; namefinder._openAutoSuggestResult(input, results, valOrig); });
	},

	_openAutoSuggestResult : function(input, results, value) {
		// Do not show list if loading has been aborted by _closeAutoSuggest() in the meantime
		if(input.fmAutocompleteLoadingValue == null || results == null)
			return;

		var namefinder = this;

		input.fmAutocompleteResults = results;

		if(input.fmAutocompleteList == null)
		{
			input.fmAutocompleteList = document.createElement("ol");
			input.fmAutocompleteList.className = "fmAutocomplete";
			input.fmAutocompleteList.style.position = "absolute";
			input.fmAutocompleteList.style.top = (input.offsetTop + input.offsetHeight) + "px";
			input.fmAutocompleteList.style.left = input.offsetLeft + "px";
			input.fmAutocompleteList.style.minWidth = input.offsetWidth + "px";
			input.parentNode.appendChild(input.fmAutocompleteList);
		}

		while(input.fmAutocompleteList.firstChild)
			input.fmAutocompleteList.removeChild(input.fmAutocompleteList.firstChild);

		var offset = this.getLocationPart(value);

		var foundSelection = false;
		for(var i=0; i<results.length; i++) (function(i)
		{
			var li = document.createElement("li");
			var name = document.createElement("strong");
			name.appendChild(document.createTextNode(results[i].name));
			results[i].name = value.substr(0, offset[0]) + results[i].name + value.substr(offset[0]+offset[1]);
			li.appendChild(name);
			li.appendChild(document.createTextNode(" (" + results[i].info + ")"));
			input.fmAutocompleteList.appendChild(li);
			results[i].li = li;
			results[i].i = i;
			if(!foundSelection && input.fmAutocompleteSelected != null && input.fmAutocompleteSelected.lonlat == results[i].lonlat && input.fmAutocompleteSelected.name == results[i].name && input.fmAutocompleteSelected.info == results[i].info)
			{
				namefinder._selectAutoSuggestItem(input, results[i]);
				input.fmAutocompleteSelected = results[i];
				foundSelection = true;
			}
			li.onmousemove = function() {
				if(input.fmAutocompleteSelected != null)
					namefinder._unselectAutoSuggestItem(input, input.fmAutocompleteSelected);
				input.fmAutocompleteSelected = results[i];
				namefinder._selectAutoSuggestItem(input, results[i]);
			};
			li.onclick = function() {
				input.value = results[i].name;
				namefinder._closeAutoSuggest(input);
			};
		})(i);

		if(!foundSelection)
			input.fmAutocompleteSelected = null;

		input.fmAutocompleteList.style.display = "block";
	},

	_closeAutoSuggest : function(input) {
		if(input.fmAutocompleteTimeout != null)
			clearTimeout(input.fmAutocompleteTimeout);

		// Prevent showing the list if find() is currently waiting for a response
		input.fmAutocompleteLoadingValue = null;

		if(input.fmAutocompleteList != null)
			input.fmAutocompleteList.style.display = "none";
		if(input.fmAutocompleteSelected != null)
		{
			this._unselectAutoSuggestItem(input, input.fmAutocompleteSelected);
			input.fmAutocompleteSelected = null;
		}
	},

	_selectAutoSuggestItem : function(input, item)
	{
		item.li.className = "selected";

		// Scroll to item
		var list = input.fmAutocompleteList;
		if(list == null || list.scrollTop == undefined)
			return;

		var itemTop = item.li.offsetTop;
		var itemBottom = itemTop + item.li.offsetHeight;

		if(itemTop < list.scrollTop) // Need to scroll up
			list.scrollTop = itemTop;
		else if(itemBottom > list.scrollTop + list.offsetHeight) // Need to scroll down
			list.scrollTop = itemBottom - list.offsetHeight;
	},

	_unselectAutoSuggestItem : function(input, item)
	{
		item.li.className = "";
	}
});<|endoftext|>


<commit_before>'use strict'

const Base = require('./base')
const serializer = require('loopback-jsonapi-model-serializer')
const loopback = require('loopback')

/**
  Translates an Ash model definition to a loopback definition
  which can be used with loopback-jsonapi-model-serializer
  @param {Object} Model
*/
function translateToLoopbackModel (Model) {
  const LoopbackModel = loopback.createModel({
    name: Model.name,
    properties: Model.definition.attributes,
    relations: Model.definition.relations
  })
  LoopbackModel.pluralModelName = Model.type

  const ds = loopback.createDataSource('memory')
  ds.attach(LoopbackModel)

  return LoopbackModel
}

/**
  @class Serializer
  @extends Base
  @public
*/
module.exports = class Serializer extends Base {
  /**
    @method serialize
    @public
    @param {Object} Model
    @param {Object} data
    @param {Object} options
    @return {Object}
  */
  serialize (Model, data, options) {
    if (!data) return null
    const LoopbackModel = translateToLoopbackModel(Model)
    return serializer(data, LoopbackModel, options)
  }
}
<commit_msg>Add relationship serialization<commit_after>'use strict'

const Base = require('./base')
const serializer = require('loopback-jsonapi-model-serializer')
const loopback = require('loopback')
const ds = loopback.createDataSource('memory')

/**
  Translates an Ash model definition to a loopback definition
  which can be used with loopback-jsonapi-model-serializer
  @param {Object} Model
*/
function translateToLoopbackModel (Model) {
  const LoopbackModel = ds.createModel(Model.name, Model.definition.attributes)
  LoopbackModel.pluralModelName = Model.type

  Object.keys(Model.definition.relationships).forEach(relationshipName => {
    const relatedModelName = Model.definition.relationships[relationshipName].modelTo
    const RelatedModel = Model.store.modelFor(relatedModelName)

    const RelatedLoopbackModel = ds.createModel(RelatedModel.name, RelatedModel.definition.attributes)
    RelatedLoopbackModel.pluralModelName = RelatedModel.type

    if (Model.definition.relationships[relationshipName].type === 'belongsTo') {
      LoopbackModel.belongsTo(RelatedLoopbackModel)
    } else {
      LoopbackModel.hasMany(RelatedLoopbackModel)
    }
  })

  return LoopbackModel
}

/**
  @class Serializer
  @extends Base
  @public
*/
module.exports = class Serializer extends Base {
  /**
    @method serialize
    @public
    @param {Object} Model
    @param {Object} data
    @param {Object} options
    @return {Object}
  */
  serialize (Model, data, options) {
    if (!data) return null
    const LoopbackModel = translateToLoopbackModel(Model)
    return serializer(data, LoopbackModel, options)
  }
}
<|endoftext|>


<commit_before>/*@ngInject*/
function ProjectModelService(projectsAPI) {
    class Project {
        constructor(id, name, owner) {
            this.id = id;
            this.name = name;
            this.owner = owner;
            this.files_count = 0;
            this.description = "";
            this.overview = "";
            this.birthtime = 0;
            this.owner_details = {};
            this.selected = false;
            this.mtime = 0;
            this.processes = [];
            this.samples = [];
            this.experiments = [];
            this.reminders = [];
            this.users = [];
            this.owner_details = {fullname: ''};
            this.status = 'none';
        }

        static fromJSON(data) {
            let p = new Project(data.id, data.name, data.owner);
            p.samples = data.samples;
            p.processes = data.processes;
            p.experiments = data.experiments;
            p.files_count = data.files;
            p.description = data.description;
            p.overview = data.overview;
            p.birthtime = new Date(data.birthtime * 1000);
            p.mtime = new Date(data.mtime * 1000);
            p.users = data.users;
            p.owner_details = data.owner_details;
            p.reminders = data.reminders;
            p.status = data.status;
            return p;
        }

        static get(id) {
            return projectsAPI.getProject(id).then(
                (project) => Project.fromJSON(project)
            );
        }

        static getProjectsForCurrentUser() {
            return projectsAPI.getAllProjects().then(
                (projects) => projects.map(p => Project.fromJSON(p))
            );
        }

        save() {

        }

        update(attrs) {
            return projectsAPI.updateProject(this.id, attrs);
        }
    }

    return Project;
}

angular.module('materialscommons').factory('ProjectModel', ProjectModelService);
<commit_msg>Rename get to getProjectForCurrentUser<commit_after>/*@ngInject*/
function ProjectModelService(projectsAPI) {
    class Project {
        constructor(id, name, owner) {
            this.id = id;
            this.name = name;
            this.owner = owner;
            this.files_count = 0;
            this.description = "";
            this.overview = "";
            this.birthtime = 0;
            this.owner_details = {};
            this.selected = false;
            this.mtime = 0;
            this.processes = [];
            this.samples = [];
            this.experiments = [];
            this.reminders = [];
            this.users = [];
            this.owner_details = {fullname: ''};
            this.status = 'none';
        }

        static fromJSON(data) {
            let p = new Project(data.id, data.name, data.owner);
            p.samples = data.samples;
            p.processes = data.processes;
            p.experiments = data.experiments;
            p.files_count = data.files;
            p.description = data.description;
            p.overview = data.overview;
            p.birthtime = new Date(data.birthtime * 1000);
            p.mtime = new Date(data.mtime * 1000);
            p.users = data.users;
            p.owner_details = data.owner_details;
            p.reminders = data.reminders;
            p.status = data.status;
            return p;
        }

        static getProjectForCurrentUser(id) {
            return projectsAPI.getProject(id).then(
                (project) => Project.fromJSON(project)
            );
        }

        static getProjectsForCurrentUser() {
            return projectsAPI.getAllProjects().then(
                (projects) => projects.map(p => Project.fromJSON(p))
            );
        }

        save() {

        }

        update(attrs) {
            return projectsAPI.updateProject(this.id, attrs);
        }
    }

    return Project;
}

angular.module('materialscommons').factory('ProjectModel', ProjectModelService);
<|endoftext|>


<commit_before>import { mount } from "enzyme";
import React from "react";
import MenuRestaurante from "../../app/components/MenuRestaurante";

const crearMenuRestaurante = () => {
  const props = {
    menu: {
      platosMenu: [
        "Primer plato",
        "Segundo plato",
        "Tercer plato"],
      estaCargando: false
    },
    solicitarMenuRestaurante: jest.fn()
  };

  const menuEnzyme = mount(<MenuRestaurante {...props} />);

  return {
    menuEnzyme,
    props
  };
};

describe("Componente Tablero Pedidos", () => {
  it("Debe renderizar componente", () => {
    const { menuEnzyme } = crearMenuRestaurante();
    expect(menuEnzyme.find("div").exists())
      .toBe(true);
  });
  it("Debe mostrar todos los platos del menu", () => {
    const { menuEnzyme, props } = crearMenuRestaurante();
    const platosEnComponente = menuEnzyme.find("div > ul > li").length;
    expect(platosEnComponente)
      .toBe(props.menu.platosMenu.length);
  });
  it("Debe solicitar el menu del restuarante al montar el componente", () => {
    const { props } = crearMenuRestaurante();
    expect(props.solicitarMenuRestaurante.mock.calls.length)
      .toBe(1);
  });
  it("Debe mostrar spinner al estar cargando", () => {
    expect(true).toBe(false);
  });
});
<commit_msg>Se genera prueba de contenido cargando<commit_after>import { mount } from "enzyme";
import React from "react";
import MenuRestaurante from "../../app/components/MenuRestaurante";

const crearMenuRestaurante = (estaCargando = false) => {
  const props = {
    menu: {
      platosMenu: [
        "Primer plato",
        "Segundo plato",
        "Tercer plato"
      ],
      estaCargando
    },
    solicitarMenuRestaurante: jest.fn()
  };

  const menuEnzyme = mount(<MenuRestaurante {...props} />);

  return {
    menuEnzyme,
    props
  };
};

describe("Componente Tablero Pedidos", () => {
  it("Debe renderizar componente", () => {
    const { menuEnzyme } = crearMenuRestaurante();
    expect(menuEnzyme.find("div").exists())
      .toBe(true);
  });
  it("Debe mostrar todos los platos del menu", () => {
    const { menuEnzyme, props } = crearMenuRestaurante();
    const platosEnComponente = menuEnzyme.find("div > ul > li").length;
    expect(platosEnComponente)
      .toBe(props.menu.platosMenu.length);
  });
  it("Debe solicitar el menu del restuarante al montar el componente", () => {
    const { props } = crearMenuRestaurante();
    expect(props.solicitarMenuRestaurante.mock.calls.length)
      .toBe(1);
  });
  it("Debe mostrar spinner al estar cargando", () => {
    const { menuEnzyme } = crearMenuRestaurante(true);
    expect(menuEnzyme.find("div").text())
      .toBe("Cargando...");
  });
});
<|endoftext|>


<commit_before>/*eslint-env node, mocha */
/*global expect */
/*eslint no-console: 0*/
'use strict';

import React from 'react';
import { shallow } from 'enzyme';
import RotatorComponent from 'components//RotatorComponent.js';

describe('RotatorComponent', () => {
  let component;

  beforeEach(() => {
    component = shallow(
      <RotatorComponent
        slides={[
          {
            url: 'http://www.example.com',
            duration: 5000
          }
        ]}
      />
    );
  });

  it('should have its component name as default className', () => {
    expect(component.prop('className')).to.equal('rotator-component');
  });
});
<commit_msg>Adds the spec for rotator component<commit_after>/*eslint-env node, mocha */
/*global expect */
/*eslint no-console: 0*/
'use strict';

import React from 'react';
import { shallow } from 'enzyme';
import RotatorComponent from 'components//RotatorComponent.js';

describe('RotatorComponent', () => {
  let component;

  beforeEach(() => {
    component = shallow(
      <RotatorComponent
        slides={[
          {
            url: 'http://www.example.com',
            duration: 5000
          }
        ]}
      />
    );
  });

  it('should have its component name as default className', () => {
    expect(component.prop('className')).to.equal('rotator-component');
  });

  it('should reset the slide pointer if it is out bounds after deletion of a slide', () => {

  });

  describe('Screen rotator controls', () => {
    it('should start the timeouted display of the current screen on play()', () => {

    });

    it('should pause the screen rotation on stop()', () => {

    });

    it('should show the following screen in list on next()', () => {

    });

    it('should show the previous screen in list on prev()', () => {

    });

    it('should go to a specific screen on goto() call using the slide id', () => {

    });

    describe('Inifinite looping', () => {
      it('should start over with the first screen in list after the last one has been displayed', () => {

      });

      it('should load last screen of list if using prev() while displaying the very first screen', () => {

      });
    });
  });
});
<|endoftext|>


<commit_before>/**!
 * @license jQRangeSlider
 * A javascript slider selector that supports dates
 *
 * Copyright (C) Guillaume Gautreau 2012
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 */

(function($, undefined){

	"use strict";

	$.widget("ui.rangeSliderLabel", {
		options: {
			handle: null,
			formatter: false
		},

		cache: null,

		_create: function(){
			var left = this.options.handle.rangeSliderHandle("option", "isLeft");

			this.element
				.addClass("ui-rangeSlider-label")
				.toggleClass("ui-rangeSlider-leftLabel", left)
				.toggleClass("ui-rangeSlider-rightLabel", !left)
				.css("position", "absolute");

			this.options.handle.bind("moving", $.proxy(this._onMoving, this));

			(function(that){
				setTimeout(function(){
					that._initPosition()
				}, 100);
			})(this);
		},

		_initPosition: function(){
			this._cache();
			this._position();
		},

		_cache: function(){
			this.cache = {};
			this.cache.handle = {
				width: this.options.handle.width()
			};

			this.cache.width = {
				outer: this.element.outerWidth()
			}

			var parent = this.element.parent();
			this.cache.parent = {
				offset: parent.offset(),
				width: parent.width()
			}
		},

		_cacheIfNot: function(){
			if (this.cache === null){
				this._cache();
			}
		},

		/*
		 * Event binding
		 */
		_onMoving: function(event, ui){
			this._position(ui.offset.left);
		},

		/*
		 * Positioning
		 */
		_position: function(left){
			this._cacheIfNot();

			var offset = this.element.offset();

			offset.left = left + this.cache.handle.width / 2 - this.cache.width.outer / 2;
			offset.left = Math.max(offset.left, this.cache.parent.offset.left);
			offset.left = Math.min(offset.left, this.cache.parent.offset.left + this.cache.parent.width - this.element.outerWidth())

			this.element.offset(offset);
		}
	});

})(jQuery);<commit_msg>Label with real values<commit_after>/**!
 * @license jQRangeSlider
 * A javascript slider selector that supports dates
 *
 * Copyright (C) Guillaume Gautreau 2012
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 */

(function($, undefined){

	"use strict";

	$.widget("ui.rangeSliderLabel", {
		options: {
			handle: null,
			formatter: false
		},

		cache: null,

		_create: function(){
			var left = this.options.handle.rangeSliderHandle("option", "isLeft");

			this.element
				.addClass("ui-rangeSlider-label")
				.toggleClass("ui-rangeSlider-leftLabel", left)
				.toggleClass("ui-rangeSlider-rightLabel", !left)
				.css("position", "absolute");

			this.options.handle.bind("moving", $.proxy(this._onMoving, this));

			(function(that){
				setTimeout(function(){
					that._initPosition()
				}, 100);
			})(this);
		},

		_initPosition: function(){
			this._cache();
			this._position();
		},

		_cache: function(){
			this.cache = {};
			this.cache.handle = {
				width: this.options.handle.width()
			};

			this._cacheWidth();

			var parent = this.element.parent();
			this.cache.parent = {
				offset: parent.offset(),
				width: parent.width()
			}
		},

		_cacheWidth: function(){
			this.cache.width = {
				outer: this.element.outerWidth()
			}
		},

		_updateWidthCache: function(){
			if (this.cache === null){
				this._cache();
			}else{
				this._cacheWidth();
			}
		},

		_cacheIfNot: function(){
			if (this.cache === null){
				this._cache();
			}
		},

		_display: function(value){
			if (this.options.formatter == false){
				this.element.text(Math.round(value));
			}else{
				this.element.text(this.options.formatter(value));
			}

			this._updateWidthCache();
		},

		/*
		 * Event binding
		 */
		_onMoving: function(event, ui){
			this._display(ui.value);
			this._position(ui.offset.left);
		},

		/*
		 * Positioning
		 */
		_position: function(left){
			this._cacheIfNot();

			var offset = this.element.offset();

			offset.left = left + this.cache.handle.width / 2 - this.cache.width.outer / 2;
			offset.left = Math.max(offset.left, this.cache.parent.offset.left);
			offset.left = Math.min(offset.left, this.cache.parent.offset.left + this.cache.parent.width - this.element.outerWidth())

			this.element.offset(offset);
		}
	});

})(jQuery);<|endoftext|>


<commit_before>var chaisePage = require('./../../utils/chaise.page.js');
var chaiseConfig = {
    name: "Footer",
    apps:['record','recordedit','recordset'],
    defaultTables: {
        "1": {
            "schema": "isa",
            "table": "dataset",
            "id": "269"
        }
    }
};
var EC = protractor.ExpectedConditions;
describe('Page Footer', function() {
            chaiseConfig.apps.forEach(function(val){

                let flocation = "/" + val + "/#1/" + chaiseConfig.defaultTables[1].schema + ":" + chaiseConfig.defaultTables[1].table + "/id=" + chaiseConfig.defaultTables[1].id;

                (function(location, appPage){

                describe('Checking footer in ' + appPage +' page:', function() {

                    beforeAll(function() {
                        browser.ignoreSynchronization = true;
                        url = browser.params.url + location;
                        console.log(url);
                        browser.get(url);
                        footerMain = element(by.id('footerStyle'));
                        chaisePage.waitForElementCondition(EC.visibilityOf(footerMain));

                    });
                    it('Page footer should appear at the bottom of the page', function() {

                        browser.executeScript('return $(document).height()').then(function(docH) {
                            docHeight = docH;
                            return footerMain.getLocation();
                        }).then(function(loc) {
                            elemLoc = loc.y;
                            return footerMain.getSize();
                        }).then(function(elemH) {
                            let totalH = elemLoc + elemH.height;
                            expect(totalH).toEqual(docHeight, 'Footer is not at the bottom of the page!');
                        }).catch(function(error) {
                            console.dir(error);
                            expect('Something went wrong in this promise chain').toBe('Please see error message.', 'While checking footer position on the page.');
                        });
                    });

                    it('Page footer link should match with "privacy-policy"', function() {
                        var footerLink = element(by.id('footerStyle')).element(by.tagName('a'));
                        chaisePage.waitForElementCondition(EC.visibilityOf(footerLink));
                        footerLink.getAttribute('href').then(function(prevLink) {
                            let plink = prevLink.slice(0, -1);
                            expect(plink.substring(plink.lastIndexOf('/') + 1)).toBe("privacy-policy", "Privacy Policy is not defined. Check chaise-config.js")
                        })
                    })

                });
            })(flocation,val);
        });
});
<commit_msg>console.log removal<commit_after>var chaisePage = require('./../../utils/chaise.page.js');
var chaiseConfig = {
    name: "Footer",
    apps:['record','recordedit','recordset'],
    defaultTables: {
        "1": {
            "schema": "isa",
            "table": "dataset",
            "id": "269"
        }
    }
};
var EC = protractor.ExpectedConditions;
describe('Page Footer', function() {
            chaiseConfig.apps.forEach(function(val){

                let flocation = "/" + val + "/#1/" + chaiseConfig.defaultTables[1].schema + ":" + chaiseConfig.defaultTables[1].table + "/id=" + chaiseConfig.defaultTables[1].id;

                (function(location, appPage){

                describe('Checking footer in ' + appPage +' page:', function() {

                    beforeAll(function() {
                        browser.ignoreSynchronization = true;
                        url = browser.params.url + location;
                        browser.get(url);
                        footerMain = element(by.id('footerStyle'));
                        chaisePage.waitForElementCondition(EC.visibilityOf(footerMain));

                    });
                    it('Page footer should appear at the bottom of the page', function() {

                        browser.executeScript('return $(document).height()').then(function(docH) {
                            docHeight = docH;
                            return footerMain.getLocation();
                        }).then(function(loc) {
                            elemLoc = loc.y;
                            return footerMain.getSize();
                        }).then(function(elemH) {
                            let totalH = elemLoc + elemH.height;
                            expect(totalH).toEqual(docHeight, 'Footer is not at the bottom of the page!');
                        }).catch(function(error) {
                            console.dir(error);
                            expect('Something went wrong in this promise chain').toBe('Please see error message.', 'While checking footer position on the page.');
                        });
                    });

                    it('Page footer link should match with "privacy-policy"', function() {
                        var footerLink = element(by.id('footerStyle')).element(by.tagName('a'));
                        chaisePage.waitForElementCondition(EC.visibilityOf(footerLink));
                        footerLink.getAttribute('href').then(function(prevLink) {
                            let plink = prevLink.slice(0, -1);
                            expect(plink.substring(plink.lastIndexOf('/') + 1)).toBe("privacy-policy", "Privacy Policy is not defined. Check chaise-config.js")
                        })
                    })

                });
            })(flocation,val);
        });
});
<|endoftext|>


<commit_before>if (typeof define !== 'function') { var define = require('amdefine')(module) }

define([
  'react',
  'moment',
  './nicknamelist',
  './color',
  './inputbox'
], function(React, moment, NicknameList, Color, InputBox, undefined) {

  // TODO: transform opacity when adding a new buffer line

  var Buffer = React.createClass({

    displayName: 'Buffer',

    getInitialState: function () {
      return {messages: this.props.buffer.messages,
              nicknamelist: []};
    },

    // see http://blog.vjeux.com/2013/javascript/scroll-position-with-react.html
    componentWillUpdate: function() {
      var node = this.getDOMNode().getElementsByClassName('buffer-messages')[0];
      this.shouldScrollBottom = node.scrollTop + node.offsetHeight === node.scrollHeight;
    },

    componentDidUpdate: function() {
      if (this.shouldScrollBottom) {
        var node = this.getDOMNode().getElementsByClassName('buffer-messages')[0];
        node.scrollTop = node.scrollHeight;
      }
    },

    render: function() {
      var buffer = this.props.buffer,
          self = this,
          name = buffer.info.short_name;
      // TODO: when updating topic, short_name has a funny name
      return React.DOM.div({ className: this.props.isActive ? " buffer-active" : "buffer-unactive" }, [
          React.DOM.div({className: "list-group col-lg-10"}, [
            React.DOM.h3({ key: 'title', className: 'buffer-title', style: this.props.layout.bufferTitle || {} }, name + ": " + buffer.info.title),
            React.DOM.ul({ key: "listgroup", className: 'buffer-messages',
                           style: this.props.layout.buffer || {}},
               buffer.messages.map(function (message) {
                   return React.DOM.li({className: "list-group-item row" + (message.highlight === 1 ? " list-group-item-info" : ""),
                                        key: message.pointers.join(" ")}, [
                       React.DOM.div({className: "col-xs-6 col-sm-1 message-date text-muted", key: "date"},
                                     moment.unix(message.date).format('hh:mm:ss')),
                       React.DOM.div({className: "col-xs-6 col-sm-2 message-prefix " + (message.tags_array.indexOf("irc_privmsg") === -1 ? "text-muted" : "text-primary"),
                                      key: "prefix",
                                      dangerouslySetInnerHTML: {__html: Color.format(message.prefix)}}),
                       React.DOM.div({className: "col-xs-12 col-sm-9 message-text " + (message.tags_array.indexOf("irc_privmsg") === -1 ? "text-muted" : ""),
                                      key: "message",
                                      dangerouslySetInnerHTML: {__html: Color.format(message.message)}}
                       )
                   ]);
               })
            ),
            InputBox({nicklist: this.props.buffer.nicklist,
                      layout: this.props.layout,
                      handleSubmit: this.props.sendInputConstructor(this.props.buffer.info.pointers[0])})
          ]),
          NicknameList({
            nicklist: this.props.buffer.nicklist,
            layout: this.props.layout
          })
        ]);
    }

  });

  return Buffer;

});
<commit_msg>parse links in channel title<commit_after>if (typeof define !== 'function') { var define = require('amdefine')(module) }

define([
  'react',
  'moment',
  './nicknamelist',
  './color',
  './inputbox'
], function(React, moment, NicknameList, Color, InputBox, undefined) {

  // TODO: transform opacity when adding a new buffer line

  var Buffer = React.createClass({

    displayName: 'Buffer',

    getInitialState: function () {
      return {messages: this.props.buffer.messages,
              nicknamelist: []};
    },

    // see http://blog.vjeux.com/2013/javascript/scroll-position-with-react.html
    componentWillUpdate: function() {
      var node = this.getDOMNode().getElementsByClassName('buffer-messages')[0];
      this.shouldScrollBottom = node.scrollTop + node.offsetHeight === node.scrollHeight;
    },

    componentDidUpdate: function() {
      if (this.shouldScrollBottom) {
        var node = this.getDOMNode().getElementsByClassName('buffer-messages')[0];
        node.scrollTop = node.scrollHeight;
      }
    },

    render: function() {
      var buffer = this.props.buffer,
          self = this,
          name = buffer.info.short_name;
      // TODO: when updating topic, short_name has a funny name
      return React.DOM.div({ className: this.props.isActive ? " buffer-active" : "buffer-unactive" }, [
          React.DOM.div({className: "list-group col-lg-10"}, [
            React.DOM.h3({key: 'title',
                          className: 'buffer-title',
                          style: this.props.layout.bufferTitle || {},
                          dangerouslySetInnerHTML: {__html: Color.format(name + ": " + buffer.info.title)}}),
            React.DOM.ul({key: "listgroup",
                          className: 'buffer-messages',
                          style: this.props.layout.buffer || {}},
               buffer.messages.map(function (message) {
                   return React.DOM.li({className: "list-group-item row" + (message.highlight === 1 ? " list-group-item-info" : ""),
                                        key: message.pointers.join(" ")}, [
                       React.DOM.div({className: "col-xs-6 col-sm-1 message-date text-muted", key: "date"},
                                     moment.unix(message.date).format('hh:mm:ss')),
                       React.DOM.div({className: "col-xs-6 col-sm-2 message-prefix " + (message.tags_array.indexOf("irc_privmsg") === -1 ? "text-muted" : "text-primary"),
                                      key: "prefix",
                                      dangerouslySetInnerHTML: {__html: Color.format(message.prefix)}}),
                       React.DOM.div({className: "col-xs-12 col-sm-9 message-text " + (message.tags_array.indexOf("irc_privmsg") === -1 ? "text-muted" : ""),
                                      key: "message",
                                      dangerouslySetInnerHTML: {__html: Color.format(message.message)}}
                       )
                   ]);
               })
            ),
            InputBox({nicklist: this.props.buffer.nicklist,
                      layout: this.props.layout,
                      handleSubmit: this.props.sendInputConstructor(this.props.buffer.info.pointers[0])})
          ]),
          NicknameList({
            nicklist: this.props.buffer.nicklist,
            layout: this.props.layout
          })
        ]);
    }

  });

  return Buffer;

});
<|endoftext|>


<commit_before>/* -------- ---- -- -  -    -
** AINM = Automatic Input Name Model
** Version 1.1.0-alpha
** Automatically creates a model with two-way binding based on input element
** names. An optional root element can be specified in order to limit the
** scope (or else all matching elements in the current document will be used).
** In order to display a value in another element use the attribute data-ainm
** with the name of an input element as attribute value.
** Example:
** <input type="text" name="username">
**
** (As it happens "ainm" means "name" in Irish.)
** ---- -- -  -    -
*/
function Ainm( root ) {

	var _ATTRIBUTE = 'data-ainm';
	var _model = {};
	var _root = root || document;

	function get( key ) {
		if( key && typeof key === 'string' ) {
			return _model[ key ];
		}
	}

	function set( key, value ) {
		if( key && typeof key === 'string' ) {
			_model[ key ] = value;
			render( key );
		}
	}

	function extend( object ) {
		for( var key in object ) {
			set( key, object[ key ] );
		}
	}

	function index( array, value ) {
		for( var i = 0; i < array.length && array[ i ] !== value; i++ ){}
		return i;
	}

	function isArray( value ) {
		return Object.prototype.toString.call( value ) === '[object Array]';
	}

	function renderElement( element, value ) {
		var i;
		var tag = element.tagName.toLowerCase();

		if( tag === 'input' ) {
			if( element.type === 'radio' ) {
				element.checked = ( element.value === value );
			} else if( element.type === 'checkbox' ) {
				if( isArray( value ) ) {
					i = index( value, element.value );
					element.checked = ( i < value.length );
				} else {
					element.checked = ( element.value === value );
				}
			} else {
				element.value = value;
			}
		} else {
			if( isArray( value ) ) {
				element.innerHTML = value.join( ', ' );
			} else {
				element.innerHTML = value;
			}
		}
	}

	function render( key ) {
		var element, elements, i;
		var value = get( key );

		if( _root.querySelectorAll ) {
			elements = _root.querySelectorAll( 'input[name="' + key + '"], [' + _ATTRIBUTE + '="' + key + '"]' );
		} else if( _root.getElementsByTagName ) {
			elements = _root.getElementsByTagName( '*' );
		} else {
			return;
		}

		for( i = 0; i < elements.length; i++ ) {
			element = elements[ i ];
			if( key === ( element.getAttribute( _ATTRIBUTE ) || element.name ) ) {
				renderElement( element, value );
			}
		}
	}

	function onChange( event ) {
		var i;
		var element = event.target;
		var value = element.value;
		var key = element.getAttribute( _ATTRIBUTE ) || element.name;

		if( element.type === 'checkbox' ) {
			_model[ key ] = _model[ key ] || [];
			i = index( _model[ key ], value );
			if( element.checked ) {
				_model[ key ][ i ] = value;
			} else if( i < _model[ key ].length ) {
				_model[ key ].splice( i, 1 );
			}
		} else {
			_model[ key ] = value;
		}

		render( key );
	}

	function addEvent( element, type, handler) {
		if( element.addEventListener ) {
			element.addEventListener( type, handler );
		} else if( element.attachEvent ) {
			element.attachEvent( 'on' + type, handler );
		}
	}

	function init() {
		var element, elements, i, key;

		if( _root.getElementsByTagName ) {
			elements = _root.getElementsByTagName( 'input' );
		} else {
			return;
		}

		for( i = 0; i < elements.length; i++ ) {
			element = elements[ i ];
			key = element.getAttribute( _ATTRIBUTE ) || element.name;
			if( key && typeof key === 'string' ) {
				if( element.type === 'radio' ) {
					addEvent( element, 'click', onChange );
					if( element.checked && _model[ key ] === undefined ) {
						_model[ key ] = element.value;
					}
				} else if( element.type === 'checkbox' ) {
					addEvent( element, 'click', onChange );
					_model[ key ] = _model[ key ] || [];
					if( element.checked ) {
						_model[ key ].push( element.value );
					}
				} else {
					addEvent( element, 'change', onChange );
					_model[ key ] = element.value;
				}
			}
		}
	}

	init();

	return {
		get: get,
		set: set,
		extend: extend
	};

}
<commit_msg>Whitespace.<commit_after>/* -------- ---- -- -  -    -
** AINM = Automatic Input Name Model
** Version 1.1.0-alpha
** Automatically creates a model with two-way binding based on input element
** names. An optional root element can be specified in order to limit the
** scope (or else all matching elements in the current document will be used).
** In order to display a value in another element use the attribute data-ainm
** with the name of an input element as attribute value.
** Example:
** <input type="text" name="username">
**
** (As it happens "ainm" means "name" in Irish.)
** ---- -- -  -    -
*/
function Ainm( root ) {

	var _ATTRIBUTE = 'data-ainm';
	var _model = {};
	var _root = root || document;

	function get( key ) {
		if( key && typeof key === 'string' ) {
			return _model[ key ];
		}
	}

	function set( key, value ) {
		if( key && typeof key === 'string' ) {
			_model[ key ] = value;
			render( key );
		}
	}

	function extend( object ) {
		for( var key in object ) {
			set( key, object[ key ] );
		}
	}

	function index( array, value ) {
		for( var i = 0; i < array.length && array[ i ] !== value; i++ ) {}
		return i;
	}

	function isArray( value ) {
		return Object.prototype.toString.call( value ) === '[object Array]';
	}

	function renderElement( element, value ) {
		var i;
		var tag = element.tagName.toLowerCase();

		if( tag === 'input' ) {
			if( element.type === 'radio' ) {
				element.checked = ( element.value === value );
			} else if( element.type === 'checkbox' ) {
				if( isArray( value ) ) {
					i = index( value, element.value );
					element.checked = ( i < value.length );
				} else {
					element.checked = ( element.value === value );
				}
			} else {
				element.value = value;
			}
		} else {
			if( isArray( value ) ) {
				element.innerHTML = value.join( ', ' );
			} else {
				element.innerHTML = value;
			}
		}
	}

	function render( key ) {
		var element, elements, i;
		var value = get( key );

		if( _root.querySelectorAll ) {
			elements = _root.querySelectorAll( 'input[name="' + key + '"], [' + _ATTRIBUTE + '="' + key + '"]' );
		} else if( _root.getElementsByTagName ) {
			elements = _root.getElementsByTagName( '*' );
		} else {
			return;
		}

		for( i = 0; i < elements.length; i++ ) {
			element = elements[ i ];
			if( key === ( element.getAttribute( _ATTRIBUTE ) || element.name ) ) {
				renderElement( element, value );
			}
		}
	}

	function onChange( event ) {
		var i;
		var element = event.target;
		var value = element.value;
		var key = element.getAttribute( _ATTRIBUTE ) || element.name;

		if( element.type === 'checkbox' ) {
			_model[ key ] = _model[ key ] || [];
			i = index( _model[ key ], value );
			if( element.checked ) {
				_model[ key ][ i ] = value;
			} else if( i < _model[ key ].length ) {
				_model[ key ].splice( i, 1 );
			}
		} else {
			_model[ key ] = value;
		}

		render( key );
	}

	function addEvent( element, type, handler ) {
		if( element.addEventListener ) {
			element.addEventListener( type, handler );
		} else if( element.attachEvent ) {
			element.attachEvent( 'on' + type, handler );
		}
	}

	function init() {
		var element, elements, i, key;

		if( _root.getElementsByTagName ) {
			elements = _root.getElementsByTagName( 'input' );
		} else {
			return;
		}

		for( i = 0; i < elements.length; i++ ) {
			element = elements[ i ];
			key = element.getAttribute( _ATTRIBUTE ) || element.name;
			if( key && typeof key === 'string' ) {
				if( element.type === 'radio' ) {
					addEvent( element, 'click', onChange );
					if( element.checked && _model[ key ] === undefined ) {
						_model[ key ] = element.value;
					}
				} else if( element.type === 'checkbox' ) {
					addEvent( element, 'click', onChange );
					_model[ key ] = _model[ key ] || [];
					if( element.checked ) {
						_model[ key ].push( element.value );
					}
				} else {
					addEvent( element, 'change', onChange );
					_model[ key ] = element.value;
				}
			}
		}
	}

	init();

	return {
		get: get,
		set: set,
		extend: extend
	};

}
<|endoftext|>