<commit_before>/*
 * Swipe 2.0
 *
 * Brad Birdsall
 * Copyright 2013, MIT License
 *
*/

function Swipe(container, options) {

  "use strict";

  // utilities
  var noop = function() {}; // simple no operation function
  var offloadFn = function(fn) { setTimeout(fn || noop, 0) }; // offload a functions execution

  // check browser capabilities
  var browser = {
    addEventListener: !!window.addEventListener,
    touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
    transitions: (function(temp) {
      var props = ['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'];
      for ( var i in props ) if (temp.style[ props[i] ] !== undefined) return true;
      return false;
    })(document.createElement('swipe'))
  };

  // quit if no root element
  if (!container) return;
  var element = container.children[0];
  var slides, slidePos, width;
  options = options || {};
  var index = parseInt(options.startSlide, 10) || 0;
  var speed = options.speed || 300;
  options.continuous = options.continuous ? options.continuous : true;

  function setup() {

    // cache slides
    slides = element.children;

    // create an array to store current positions of each slide
    slidePos = new Array(slides.length);

    // determine width of each slide
    width = container.getBoundingClientRect().width || container.offsetWidth;

    element.style.width = (slides.length * width) + 'px';

    // stack elements
    var pos = slides.length;
    while(pos--) {

      var slide = slides[pos];

      slide.style.width = width + 'px';
      slide.setAttribute('data-index', pos);

      if (browser.transitions) {
        slide.style.left = (pos * -width) + 'px';
        move(pos, index > pos ? -width : (index < pos ? width : 0), 0);
      }

    }

    if (!browser.transitions) element.style.left = (index * -width) + 'px';

    container.style.visibility = 'visible';

  }

  function prev() {

    if (index) slide(index-1);
    else if (options.continuous) slide(slides.length-1);

  }

  function next() {

    if (index < slides.length - 1) slide(index+1);
    else if (options.continuous) slide(0);

  }

  function slide(to, slideSpeed) {

    // do nothing if already on requested slide
    if (index == to) return;

    if (browser.transitions) {

      var diff = Math.abs(index-to) - 1;
      var direction = Math.abs(index-to) / (index-to); // 1:right -1:left

      while (diff--) move((to > index ? to : index) - diff - 1, width * direction, 0);

      move(index, width * direction, slideSpeed || speed);
      move(to, 0, slideSpeed || speed);

    } else {

      animate(index * -width, to * -width, slideSpeed || speed);

    }

    index = to;

    offloadFn(options.callback && options.callback(index, slides[index]));

  }

  function move(index, dist, speed) {

    translate(index, dist, speed);
    slidePos[index] = dist;

  }

  function translate(index, dist, speed) {

    var slide = slides[index];
    var style = slide && slide.style;

    if (!style) return;

    style.webkitTransitionDuration =
    style.MozTransitionDuration =
    style.msTransitionDuration =
    style.OTransitionDuration =
    style.transitionDuration = speed + 'ms';

    style.webkitTransform = 'translate(' + dist + 'px,0)' + 'translateZ(0)';
    style.msTransform =
    style.MozTransform =
    style.OTransform = 'translateX(' + dist + 'px)';

  }

  function animate(from, to, speed) {

    // if not an animation, just reposition
    if (!speed) {

      element.style.left = to + 'px';
      return;

    }

    var start = +new Date;

    var timer = setInterval(function() {

      var timeElap = +new Date - start;

      if (timeElap > speed) {

        element.style.left = to + 'px';

        if (delay) begin();

        options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);

        clearInterval(timer);
        return;

      }

      element.style.left = (( (to - from) * (Math.floor((timeElap / speed) * 100) / 100) ) + from) + 'px';

    }, 4);

  }

  // setup auto slideshow
  var delay = options.auto || 0;
  var interval;

  function begin() {

    interval = setTimeout(next, delay);

  }

  function stop() {

    delay = 0;
    clearTimeout(interval);

  }

  // setup initial vars
  var start = {};
  var delta = {};
  var isScrolling;

  // setup event capturing
  var events = {

    handleEvent: function(event) {

      switch (event.type) {
        case 'touchstart': this.start(event); break;
        case 'touchmove': this.move(event); break;
        case 'touchend': offloadFn(this.end(event)); break;
        case 'webkitTransitionEnd':
        case 'msTransitionEnd':
        case 'oTransitionEnd':
        case 'otransitionend':
        case 'transitionend': offloadFn(this.transitionEnd(event)); break;
        case 'resize': offloadFn(setup.call()); break;
      }

      if (options.stopPropagation) event.stopPropagation();

    },
    start: function(event) {

      var touches = event.touches[0];

      // measure start values
      start = {

        // get initial touch coords
        x: touches.pageX,
        y: touches.pageY,

        // store time to determine touch duration
        time: +new Date

      };

      // used for testing first move event
      isScrolling = undefined;

      // reset delta and end measurements
      delta = {};

      // attach touchmove and touchend listeners
      element.addEventListener('touchmove', this, false);
      element.addEventListener('touchend', this, false);

    },
    move: function(event) {

      // ensure swiping with one touch and not pinching
      if ( event.touches.length > 1 || event.scale && event.scale !== 1) return

      if (options.disableScroll) event.preventDefault();

      var touches = event.touches[0];

      // measure change in x and y
      delta = {
        x: touches.pageX - start.x,
        y: touches.pageY - start.y
      }

      // determine if scrolling test has run - one time test
      if ( typeof isScrolling == 'undefined') {
        isScrolling = !!( isScrolling || Math.abs(delta.x) < Math.abs(delta.y) );
      }

      // if user is not trying to scroll vertically
      if (!isScrolling) {

        // prevent native scrolling
        event.preventDefault();

        // stop slideshow
        stop();

        // increase resistance if first or last slide
        delta.x =
          delta.x /
            ( (!index && delta.x > 0               // if first slide and sliding left
              || index == slides.length - 1        // or if last slide and sliding right
              && delta.x < 0                       // and if sliding at all
            ) ?
            ( Math.abs(delta.x) / width + 1 )      // determine resistance level
            : 1 );                                 // no resistance if false

        // translate 1:1
        translate(index-1, delta.x + slidePos[index-1], 0);
        translate(index, delta.x + slidePos[index], 0);
        translate(index+1, delta.x + slidePos[index+1], 0);

      }

    },
    end: function(event) {

      // measure duration
      var duration = +new Date - start.time;

      // determine if slide attempt triggers next/prev slide
      var isValidSlide =
            Number(duration) < 250               // if slide duration is less than 250ms
            && Math.abs(delta.x) > 20            // and if slide amt is greater than 20px
            || Math.abs(delta.x) > width/2;      // or if slide amt is greater than half the width

      // determine if slide attempt is past start and end
      var isPastBounds =
            !index && delta.x > 0                            // if first slide and slide amt is greater than 0
            || index == slides.length - 1 && delta.x < 0;    // or if last slide and slide amt is less than 0

      // determine direction of swipe (true:right, false:left)
      var direction = delta.x < 0;

      // if not scrolling vertically
      if (!isScrolling) {

        if (isValidSlide && !isPastBounds) {

          if (direction) {

            move(index-1, -width, 0);
            move(index, slidePos[index]-width, speed);
            move(index+1, slidePos[index+1]-width, speed);
            index += 1;

          } else {

            move(index+1, width, 0);
            move(index, slidePos[index]+width, speed);
            move(index-1, slidePos[index-1]+width, speed);
            index += -1;

          }

          options.callback && options.callback(index, slides[index]);

        } else {

          move(index-1, -width, speed);
          move(index, 0, speed);
          move(index+1, width, speed);

        }

      }

      // kill touchmove and touchend event listeners until touchstart called again
      element.removeEventListener('touchmove', events, false)
      element.removeEventListener('touchend', events, false)

    },
    transitionEnd: function(event) {

      if (parseInt(event.target.getAttribute('data-index'), 10) == index) {

        if (delay) begin();

        options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);

      }

    }

  }

  // trigger setup
  setup();

  // start auto slideshow if applicable
  if (delay) begin();

  // add event listeners
  if (browser.addEventListener) {

    // set touchstart event on element
    if (browser.touch) element.addEventListener('touchstart', events, false);

    if (browser.transitions) {
      element.addEventListener('webkitTransitionEnd', events, false);
      element.addEventListener('msTransitionEnd', events, false);
      element.addEventListener('oTransitionEnd', events, false);
      element.addEventListener('otransitionend', events, false);
      element.addEventListener('transitionend', events, false);
    }

    // set resize event on window
    window.addEventListener('resize', events, false);

  } else {

    window.onresize = function () { setup() }; // to play nice with old IE

  }

  // expose the Swipe API
  return {
    setup: function() {

      setup();

    },
    slide: function(to, speed) {

      // cancel slideshow
      stop();

      slide(to, speed);

    },
    prev: function() {

      stop();

      prev();

    },
    next: function() {

      stop();

      next();

    },
    getPos: function() {

      // return current index position
      return index;

    },
    kill: function() {

      // cancel slideshow
      stop();

      // reset element
      element.style.width = 'auto';
      element.style.left = 0;

      // reset slides
      var pos = slides.length;
      while(pos--) {

        var slide = slides[pos];
        slide.style.width = '100%';
        slide.style.left = 0;

        if (browser.transitions) translate(pos, 0, 0);

      }

      // removed event listeners
      if (browser.addEventListener) {

        // remove current event listeners
        element.removeEventListener('touchstart', events, false);
        element.removeEventListener('webkitTransitionEnd', events, false);
        element.removeEventListener('msTransitionEnd', events, false);
        element.removeEventListener('oTransitionEnd', events, false);
        element.removeEventListener('otransitionend', events, false);
        element.removeEventListener('transitionend', events, false);
        window.removeEventListener('resize', events, false);

      }
      else {

        window.onresize = null;

      }

    }
  }

}

if ( window.jQuery || window.Zepto ) {
  (function($) {
    $.fn.Swipe = function(params) {
      return this.each(function() {
        $(this).data('Swipe', new Swipe($(this)[0], params));
      });
    }
  })( window.jQuery || window.Zepto )
}
<commit_msg>Consistent comments<commit_after>/*
 * Swipe 2.0
 *
 * Brad Birdsall
 * Copyright 2013, MIT License
 *
*/

function Swipe(container, options) {

  "use strict";

  // utilities
  var noop = function() {}; // simple no operation function
  var offloadFn = function(fn) { setTimeout(fn || noop, 0) }; // offload a functions execution

  // check browser capabilities
  var browser = {
    addEventListener: !!window.addEventListener,
    touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
    transitions: (function(temp) {
      var props = ['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'];
      for ( var i in props ) if (temp.style[ props[i] ] !== undefined) return true;
      return false;
    })(document.createElement('swipe'))
  };

  // quit if no root element
  if (!container) return;
  var element = container.children[0];
  var slides, slidePos, width;
  options = options || {};
  var index = parseInt(options.startSlide, 10) || 0;
  var speed = options.speed || 300;
  options.continuous = options.continuous ? options.continuous : true;

  function setup() {

    // cache slides
    slides = element.children;

    // create an array to store current positions of each slide
    slidePos = new Array(slides.length);

    // determine width of each slide
    width = container.getBoundingClientRect().width || container.offsetWidth;

    element.style.width = (slides.length * width) + 'px';

    // stack elements
    var pos = slides.length;
    while(pos--) {

      var slide = slides[pos];

      slide.style.width = width + 'px';
      slide.setAttribute('data-index', pos);

      if (browser.transitions) {
        slide.style.left = (pos * -width) + 'px';
        move(pos, index > pos ? -width : (index < pos ? width : 0), 0);
      }

    }

    if (!browser.transitions) element.style.left = (index * -width) + 'px';

    container.style.visibility = 'visible';

  }

  function prev() {

    if (index) slide(index-1);
    else if (options.continuous) slide(slides.length-1);

  }

  function next() {

    if (index < slides.length - 1) slide(index+1);
    else if (options.continuous) slide(0);

  }

  function slide(to, slideSpeed) {

    // do nothing if already on requested slide
    if (index == to) return;

    if (browser.transitions) {

      var diff = Math.abs(index-to) - 1;
      var direction = Math.abs(index-to) / (index-to); // 1:right -1:left

      while (diff--) move((to > index ? to : index) - diff - 1, width * direction, 0);

      move(index, width * direction, slideSpeed || speed);
      move(to, 0, slideSpeed || speed);

    } else {

      animate(index * -width, to * -width, slideSpeed || speed);

    }

    index = to;

    offloadFn(options.callback && options.callback(index, slides[index]));

  }

  function move(index, dist, speed) {

    translate(index, dist, speed);
    slidePos[index] = dist;

  }

  function translate(index, dist, speed) {

    var slide = slides[index];
    var style = slide && slide.style;

    if (!style) return;

    style.webkitTransitionDuration =
    style.MozTransitionDuration =
    style.msTransitionDuration =
    style.OTransitionDuration =
    style.transitionDuration = speed + 'ms';

    style.webkitTransform = 'translate(' + dist + 'px,0)' + 'translateZ(0)';
    style.msTransform =
    style.MozTransform =
    style.OTransform = 'translateX(' + dist + 'px)';

  }

  function animate(from, to, speed) {

    // if not an animation, just reposition
    if (!speed) {

      element.style.left = to + 'px';
      return;

    }

    var start = +new Date;

    var timer = setInterval(function() {

      var timeElap = +new Date - start;

      if (timeElap > speed) {

        element.style.left = to + 'px';

        if (delay) begin();

        options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);

        clearInterval(timer);
        return;

      }

      element.style.left = (( (to - from) * (Math.floor((timeElap / speed) * 100) / 100) ) + from) + 'px';

    }, 4);

  }

  // setup auto slideshow
  var delay = options.auto || 0;
  var interval;

  function begin() {

    interval = setTimeout(next, delay);

  }

  function stop() {

    delay = 0;
    clearTimeout(interval);

  }

  // setup initial vars
  var start = {};
  var delta = {};
  var isScrolling;

  // setup event capturing
  var events = {

    handleEvent: function(event) {

      switch (event.type) {
        case 'touchstart': this.start(event); break;
        case 'touchmove': this.move(event); break;
        case 'touchend': offloadFn(this.end(event)); break;
        case 'webkitTransitionEnd':
        case 'msTransitionEnd':
        case 'oTransitionEnd':
        case 'otransitionend':
        case 'transitionend': offloadFn(this.transitionEnd(event)); break;
        case 'resize': offloadFn(setup.call()); break;
      }

      if (options.stopPropagation) event.stopPropagation();

    },
    start: function(event) {

      var touches = event.touches[0];

      // measure start values
      start = {

        // get initial touch coords
        x: touches.pageX,
        y: touches.pageY,

        // store time to determine touch duration
        time: +new Date

      };

      // used for testing first move event
      isScrolling = undefined;

      // reset delta and end measurements
      delta = {};

      // attach touchmove and touchend listeners
      element.addEventListener('touchmove', this, false);
      element.addEventListener('touchend', this, false);

    },
    move: function(event) {

      // ensure swiping with one touch and not pinching
      if ( event.touches.length > 1 || event.scale && event.scale !== 1) return

      if (options.disableScroll) event.preventDefault();

      var touches = event.touches[0];

      // measure change in x and y
      delta = {
        x: touches.pageX - start.x,
        y: touches.pageY - start.y
      }

      // determine if scrolling test has run - one time test
      if ( typeof isScrolling == 'undefined') {
        isScrolling = !!( isScrolling || Math.abs(delta.x) < Math.abs(delta.y) );
      }

      // if user is not trying to scroll vertically
      if (!isScrolling) {

        // prevent native scrolling
        event.preventDefault();

        // stop slideshow
        stop();

        // increase resistance if first or last slide
        delta.x =
          delta.x /
            ( (!index && delta.x > 0               // if first slide and sliding left
              || index == slides.length - 1        // or if last slide and sliding right
              && delta.x < 0                       // and if sliding at all
            ) ?
            ( Math.abs(delta.x) / width + 1 )      // determine resistance level
            : 1 );                                 // no resistance if false

        // translate 1:1
        translate(index-1, delta.x + slidePos[index-1], 0);
        translate(index, delta.x + slidePos[index], 0);
        translate(index+1, delta.x + slidePos[index+1], 0);

      }

    },
    end: function(event) {

      // measure duration
      var duration = +new Date - start.time;

      // determine if slide attempt triggers next/prev slide
      var isValidSlide =
            Number(duration) < 250               // if slide duration is less than 250ms
            && Math.abs(delta.x) > 20            // and if slide amt is greater than 20px
            || Math.abs(delta.x) > width/2;      // or if slide amt is greater than half the width

      // determine if slide attempt is past start and end
      var isPastBounds =
            !index && delta.x > 0                            // if first slide and slide amt is greater than 0
            || index == slides.length - 1 && delta.x < 0;    // or if last slide and slide amt is less than 0

      // determine direction of swipe (true:right, false:left)
      var direction = delta.x < 0;

      // if not scrolling vertically
      if (!isScrolling) {

        if (isValidSlide && !isPastBounds) {

          if (direction) {

            move(index-1, -width, 0);
            move(index, slidePos[index]-width, speed);
            move(index+1, slidePos[index+1]-width, speed);
            index += 1;

          } else {

            move(index+1, width, 0);
            move(index, slidePos[index]+width, speed);
            move(index-1, slidePos[index-1]+width, speed);
            index += -1;

          }

          options.callback && options.callback(index, slides[index]);

        } else {

          move(index-1, -width, speed);
          move(index, 0, speed);
          move(index+1, width, speed);

        }

      }

      // kill touchmove and touchend event listeners until touchstart called again
      element.removeEventListener('touchmove', events, false)
      element.removeEventListener('touchend', events, false)

    },
    transitionEnd: function(event) {

      if (parseInt(event.target.getAttribute('data-index'), 10) == index) {

        if (delay) begin();

        options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);

      }

    }

  }

  // trigger setup
  setup();

  // start auto slideshow if applicable
  if (delay) begin();

  // add event listeners
  if (browser.addEventListener) {

    // set touchstart event on element
    if (browser.touch) element.addEventListener('touchstart', events, false);

    if (browser.transitions) {
      element.addEventListener('webkitTransitionEnd', events, false);
      element.addEventListener('msTransitionEnd', events, false);
      element.addEventListener('oTransitionEnd', events, false);
      element.addEventListener('otransitionend', events, false);
      element.addEventListener('transitionend', events, false);
    }

    // set resize event on window
    window.addEventListener('resize', events, false);

  } else {

    window.onresize = function () { setup() }; // to play nice with old IE

  }

  // expose the Swipe API
  return {
    setup: function() {

      setup();

    },
    slide: function(to, speed) {

      // cancel slideshow
      stop();

      slide(to, speed);

    },
    prev: function() {

      // cancel slideshow
      stop();

      prev();

    },
    next: function() {

      // cancel slideshow
      stop();

      next();

    },
    getPos: function() {

      // return current index position
      return index;

    },
    kill: function() {

      // cancel slideshow
      stop();

      // reset element
      element.style.width = 'auto';
      element.style.left = 0;

      // reset slides
      var pos = slides.length;
      while(pos--) {

        var slide = slides[pos];
        slide.style.width = '100%';
        slide.style.left = 0;

        if (browser.transitions) translate(pos, 0, 0);

      }

      // removed event listeners
      if (browser.addEventListener) {

        // remove current event listeners
        element.removeEventListener('touchstart', events, false);
        element.removeEventListener('webkitTransitionEnd', events, false);
        element.removeEventListener('msTransitionEnd', events, false);
        element.removeEventListener('oTransitionEnd', events, false);
        element.removeEventListener('otransitionend', events, false);
        element.removeEventListener('transitionend', events, false);
        window.removeEventListener('resize', events, false);

      }
      else {

        window.onresize = null;

      }

    }
  }

}

if ( window.jQuery || window.Zepto ) {
  (function($) {
    $.fn.Swipe = function(params) {
      return this.each(function() {
        $(this).data('Swipe', new Swipe($(this)[0], params));
      });
    }
  })( window.jQuery || window.Zepto )
}
<|endoftext|>


<commit_before>M.wrap('github/jillix/table/v0.0.1/table.js', function (require, module, exports) {

var View = require('github/jillix/view/v0.0.1/view');

function createTemplates (schema) {

    // create headers and rows
    var columns = {
        headers: '
',
        rows: '
'
    };

    for (var field in schema) {
        columns.headers += '' + field + '	';
        columns.rows += '{' + field + '}	';
    }
    columns.headers += '
';
    columns.rows += '
';

    return columns;
}

function clickRowHander (state, source, id) {
    return function () {
        state.emit('/editor/' + source + '/' + id);
    };
}

function load (stateConf) {
    var self = this;

    // state can be emitted before the view is ready
    if (!self.item) {
        return;
    }

    // render items
    self.item.model(getModelFromUrl(), function (err, model) {

        if (err || !model) {
            return;
        }

        self.model = model;

        // render title
        if (self.title) {
            self.title.template.render([{title: model.name}]);
        }

        var templates = createTemplates(model.schema);

        // render header
        if (self.head) {
            self.head.template.set(templates.headers);
            self.head.template.render();
        }

        if (self.item) {
            self.item.template.set(templates.rows);
            model.read({q: {}, o: {}}, function (err, data) {

                if (err || !data) {
                    data = [err] || ['no data'];
                }

                self.item.template.render(data);

                // add clicks to rows
                var rows = self.item.template.dom.querySelectorAll('tr');
                for (var i = 0; i < rows.length; ++i) {
                    rows[i].addEventListener('click', clickRowHander(self.item.state, self.model.name, data[i]._id), false);
                }
            });
        }

        //add click to create button
        var create = self.mono.config.data.create;
        $(create).on('click', function () {
            self.item.state.emit(stateConf.createAction + self.model.name + '/new');
        });
    });
}

function getModelFromUrl (model) {
    return location.pathname.split('/')[2];
}

function init () {
    var self = this;
    var config = self.mono.config.data;

    // state handler
    self.load = load;

    // init view
    if (config && config.layout) {
        var V = View(self);

        V.load(config.layout, function (err, layout) {

            if (err) {
                return;
            }

            // save view instance
            self.layout = layout;

            if (self.layout.template) {

                // render layout view
                self.layout.template.render();

                // load controller
                var count = 0;
                var handler = function (err) {
                    if (++count === 3) {
                        self.layout.model(getModelFromUrl(), function (err, model) {

                            if (!err) {
                                layout.state.emit();
                            }

                            self.emit('ready');
                        });
                    }
                };

                // load title
                if (config.title) {
                    V.load(config.title, function (err, title) {
                        self.title = title;
                        handler(err);
                    });
                } else {
                    handler();
                }

                // load headers
                if (config.head) {
                    V.load(config.head, function (err, head) {
                        self.head = head;
                        handler(err);
                    });
                } else {
                    handler();
                }

                // load items
                if (config.item) {
                    V.load(config.item, function (err, item) {
                        self.item = item;
                        handler(err);
                    });
                } else {
                    handler();
                }
            }
        });
    }
}

module.exports = init;

return module;

});
<commit_msg>added table pattern config for searching the model<commit_after>M.wrap('github/jillix/table/v0.0.1/table.js', function (require, module, exports) {

var View = require('github/jillix/view/v0.0.1/view');

function createTemplates (schema) {

    // create headers and rows
    var columns = {
        headers: '
',
        rows: '
'
    };

    for (var field in schema) {
        columns.headers += '' + field + '	';
        columns.rows += '{' + field + '}	';
    }
    columns.headers += '
';
    columns.rows += '
';

    return columns;
}

function clickRowHander (state, source, id) {
    return function () {
        state.emit('/editor/' + source + '/' + id);
    };
}

function load (stateConf) {
    var self = this;

    // state can be emitted before the view is ready
    if (!self.item) {
        return;
    }

    // render items
    self.item.model(getModelFromUrl(self.mono.config.data.pattern), function (err, model) {

        if (err || !model) {
            return;
        }

        self.model = model;

        // render title
        if (self.title) {
            self.title.template.render([{title: model.name}]);
        }

        var templates = createTemplates(model.schema);

        // render header
        if (self.head) {
            self.head.template.set(templates.headers);
            self.head.template.render();
        }

        if (self.item) {
            self.item.template.set(templates.rows);
            model.read({q: {}, o: {}}, function (err, data) {

                if (err || !data) {
                    data = [err] || ['no data'];
                }

                self.item.template.render(data);

                // add clicks to rows
                var rows = self.item.template.dom.querySelectorAll('tr');
                for (var i = 0; i < rows.length; ++i) {
                    rows[i].addEventListener('click', clickRowHander(self.item.state, self.model.name, data[i]._id), false);
                }
            });
        }

        //add click to create button
        var create = self.mono.config.data.create;
        $(create).on('click', function () {
            self.item.state.emit(stateConf.createAction + self.model.name + '/new');
        });
    });
}

function getModelFromUrl (pattern) {
    var match = location.pathname.match(pattern);
    if (match && match[1]) {
        return match[1];
    }

    return;
}

function init () {
    var self = this;
    var config = self.mono.config.data;

    // state handler
    self.load = load;

    // init view
    if (config && config.layout) {
        var V = View(self);

        V.load(config.layout, function (err, layout) {

            if (err) {
                return;
            }

            // save view instance
            self.layout = layout;

            if (self.layout.template) {

                // render layout view
                self.layout.template.render();

                // load controller
                var count = 0;
                var handler = function (err) {
                    if (++count === 3) {
                        self.layout.model(getModelFromUrl(config.pattern), function (err, model) {

                            if (!err) {
                                layout.state.emit();
                            }

                            self.emit('ready');
                        });
                    }
                };

                // load title
                if (config.title) {
                    V.load(config.title, function (err, title) {
                        self.title = title;
                        handler(err);
                    });
                } else {
                    handler();
                }

                // load headers
                if (config.head) {
                    V.load(config.head, function (err, head) {
                        self.head = head;
                        handler(err);
                    });
                } else {
                    handler();
                }

                // load items
                if (config.item) {
                    V.load(config.item, function (err, item) {
                        self.item = item;
                        handler(err);
                    });
                } else {
                    handler();
                }
            }
        });
    }
}

module.exports = init;

return module;

});
<|endoftext|>


<commit_before>/*! Tappy! - a lightweight normalized tap event. Copyright 2013 @scottjehl, Filament Group, Inc. Licensed MIT */
(function( w, $, undefined ){

	// handling flag is true when an event sequence is in progress (thx androood)
	w.tapHandling = false;

	var tap = function( $els ){
		return $els.each(function(){

			var $el = $( this ),
				resetTimer,
				lastScroll,
				scrollTolerance = 15;

			function trigger( e ){
				$( e.target ).trigger( "tap", [ e, $( e.target ).attr( "href" ) ] );
				e.stopImmediatePropagation();
			}

			function getScroll(){
				return w.document.body.scrollTop !== undefined ? w.document.body.scrollTop : w.document.documentElement.scrollTop;
			}

			function start( e ){
				if( e.touches && e.touches.length > 1 || e.targetTouches && e.targetTouches.length > 1 ){
					return false;
				}
				lastScroll = getScroll();
			}

			function end( e ){
				clearTimeout( resetTimer );
				resetTimer = setTimeout( function(){
					w.tapHandling = false;
					lastScroll = null;
				}, 1000 );

				if( e.ctrlKey || e.metaKey ){
					return;
				}

				e.preventDefault();

				// this part prevents a double callback from touch and mouse on the same tap

				// if a scroll happened between touchstart and touchend
				if( w.tapHandling && w.tapHandling !== e.type || ( e.type === "touchend" || e.type === "MSPointerUp" ) && Math.abs( getScroll() - lastScroll ) > scrollTolerance ){
					return false;
				}

				w.tapHandling = e.type;
				trigger( e );
			}

			$el
				.bind( "touchstart MSPointerDown", start )
				.bind( "touchend MSPointerUp", end )
				.bind( "click", end );
		});
	};

	// monkeybind
	var oldBind = $.fn.bind;
	$.fn.bind = function( evt, callback ){
		if( /(^| )tap( |$)/.test( evt ) ){
			tap( this );
		}
		return oldBind.apply( this, [evt, callback] );
	};

}( this, jQuery ));
<commit_msg>Allow eventData to be passed to $.fn.bind<commit_after>/*! Tappy! - a lightweight normalized tap event. Copyright 2013 @scottjehl, Filament Group, Inc. Licensed MIT */
(function( w, $, undefined ){

	// handling flag is true when an event sequence is in progress (thx androood)
	w.tapHandling = false;

	var tap = function( $els ){
		return $els.each(function(){

			var $el = $( this ),
				resetTimer,
				lastScroll,
				scrollTolerance = 15;

			function trigger( e ){
				$( e.target ).trigger( "tap", [ e, $( e.target ).attr( "href" ) ] );
				e.stopImmediatePropagation();
			}

			function getScroll(){
				return w.document.body.scrollTop !== undefined ? w.document.body.scrollTop : w.document.documentElement.scrollTop;
			}

			function start( e ){
				if( e.touches && e.touches.length > 1 || e.targetTouches && e.targetTouches.length > 1 ){
					return false;
				}
				lastScroll = getScroll();
			}

			function end( e ){
				clearTimeout( resetTimer );
				resetTimer = setTimeout( function(){
					w.tapHandling = false;
					lastScroll = null;
				}, 1000 );

				if( e.ctrlKey || e.metaKey ){
					return;
				}

				e.preventDefault();

				// this part prevents a double callback from touch and mouse on the same tap

				// if a scroll happened between touchstart and touchend
				if( w.tapHandling && w.tapHandling !== e.type || ( e.type === "touchend" || e.type === "MSPointerUp" ) && Math.abs( getScroll() - lastScroll ) > scrollTolerance ){
					return false;
				}

				w.tapHandling = e.type;
				trigger( e );
			}

			$el
				.bind( "touchstart MSPointerDown", start )
				.bind( "touchend MSPointerUp", end )
				.bind( "click", end );
		});
	};

	// monkeybind
	var oldBind = $.fn.bind;
	$.fn.bind = function( evt ){
		if( /(^| )tap( |$)/.test( evt ) ){
			tap( this );
		}
		return oldBind.apply( this, arguments );
	};

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


<commit_before>git test<commit_msg>git test<commit_after>git test

111<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react/lib/ReactTestUtils';
import {Observable} from 'rx';
import Transmitter from './index';
import jsdom from 'mocha-jsdom';
import assert from 'assert';
import sinon from 'sinon';

describe('Transmitter', () => {
	jsdom();

	const Component = (props) =>
;
	const VALUE = 'value';
	const FIRST_ACTION_TIMEOUT = 1;
	const SECOND_ACTION_TIMEOUT = 10;
	const ShallowRender = (view) => {
		const ReactShallow = TestUtils.createRenderer();
		ReactShallow.render(view);
		return ReactShallow.getRenderOutput();
	};

	it('should create React component', () => {
		const Container = Transmitter.create(Component, {});

		assert.ok(TestUtils.isElement(<Container />), 'Container should be a React component');
		assert.equal(Container.displayName, 'Transmitter(Component)', 'Container should have Component\'s name with suffix');
	});

	it('should create React component if enum is used', () => {
		const Container = Transmitter.create({success: Component}, {});

		assert.ok(TestUtils.isElement(<Container />), 'Container should be a React component');
		assert.equal(Container.displayName, 'Transmitter(Component)', 'Container should have Component\'s name with suffix');
	});

	it('should raise an error if no components are specified', () => {
		assert.throws(() => Transmitter.create({success: null}, {}), /Success, Failure and Pending should be React components/);
		assert.throws(() => Transmitter.create({}, {}), /Success component should be specified/);
	});

	it('should render Pending component by default', () => {
		const Spinner = () =>
Loading...
;
		const Container = Transmitter.create({success: Component, pending: Spinner}, {});
		const RenderOutput = ShallowRender(<Container />);

		assert.ok(TestUtils.isElementOfType(RenderOutput, Spinner), 'Pending component should be rendered');
	});

	it('should render Success component with data fetched from fragments', (done) => {
		const thingFragment = sinon.stub().returns(new Promise((resolve) => {
			setTimeout(resolve, FIRST_ACTION_TIMEOUT, VALUE);
		}));
		const Container = Transmitter.create(Component, {
			fragments: {thing: thingFragment}
		});
		const ReactShallow = TestUtils.createRenderer();

		ReactShallow.render(<Container />);

		setTimeout(() => {
			const Output = ReactShallow.getRenderOutput();

			assert.ok(TestUtils.isElementOfType(Output, Component), 'Success component should be rendered');
			assert.deepEqual(Output.props, {thing: VALUE}, 'Component should be rendered with data fetched via fragments');
			done();
		}, SECOND_ACTION_TIMEOUT);
	});

	it('should call fragments with passed variables', () => {
		const thingFragment = sinon.stub().returns(Promise.resolve(VALUE));
		const Container = Transmitter.create(Component, {
			fragments: {thing: thingFragment}
		});
		const variables = {id: VALUE};
		const RenderOutput = ShallowRender(<Container variables={variables} />);

		assert.ok(thingFragment.calledWith(variables), 'Fragment should be called with passed variables');
	});

	it('should use initial variables if actual are not specified', () => {
		const thingFragment = sinon.stub().returns(Promise.resolve(VALUE));
		const Container = Transmitter.create(Component, {
			initialVariables: {a: VALUE},
			fragments: {thing: thingFragment}
		});
		const variables = {id: VALUE};
		const RenderOutput = ShallowRender(<Container variables={variables} />);

		assert.ok(thingFragment.calledWith({a: VALUE, id: VALUE}), 'Fragment should be called with passed variables mixed with initial variables');
	});

	xit('should actually work with stores and simple observables', () => {
		// TODO: implement this test
	});

	it('should dispose subscriptions after unmount', () => {
		const RENDER_ROOT = document.createElement('div');
		const disposeStub = sinon.spy();
		const Disposable = Observable.create(observer => ({dispose: disposeStub}));
		const Container = Transmitter.create(Component, {
			fragments: {thing: () => Disposable}
		});

		ReactDOM.render(<Container />, RENDER_ROOT);
		ReactDOM.unmountComponentAtNode(RENDER_ROOT);

		assert.ok(disposeStub.called, 'Dispose method should be called if Container was unmounted');
	});

	// waiting for https://github.com/facebook/react/pull/5247 being merged
	xit('should immediately render Success component if fragments are passed via props', () => {
		const thingFragment = sinon.stub().returns(new Promise((resolve) => {
			setTimeout(resolve, FIRST_ACTION_TIMEOUT, VALUE);
		}));
		const Container = Transmitter.create(Component, {
			fragments: {thing: thingFragment}
		});
		const RenderOutput = ShallowRender(<Container thing={VALUE} />)

		assert.ok(!thingFragment.called, 'Fragment should not be called');
		assert.ok(TestUtils.isElementOfType(RenderOutput, Component), 'Success component should be rendered');
		assert.deepEqual(RenderOutput.props, {thing: VALUE}, 'Component should be rendered with data fetched via fragments');
	});

	xit('should handle failed streams and render Failure element', () => {
		// TODO: implement this test
	});

	xit('should render `null` for not specified components', () => {
		// TODO: implement this test
	});

	xit('should restart fetching if onRetry was called', () => {
		// TODO: implement this test
	});

	xit('should abort fetching if onAbort was called', () => {
		// TODO: implement this test
	});

	xit('should use custom `shouldContainerUpdate` hook', () => {
		// TODO: implement this test
	});

	xit('should be able to get child fragment', () => {
		// TODO: implement this test
	});

	xit('should pass functions from fragments', () => {
		// TODO: implement this test
	});
});
<commit_msg>added test for Failure component rendering<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react/lib/ReactTestUtils';
import {Observable} from 'rx';
import Transmitter from './index';
import jsdom from 'mocha-jsdom';
import assert from 'assert';
import sinon from 'sinon';

describe('Transmitter', () => {
	jsdom();

	const Component = (props) =>
;
	const FailureComponent = (props) =>
;
	const VALUE = 'value';
	const ERROR = new Error('Something happened');
	const FIRST_ACTION_TIMEOUT = 1;
	const SECOND_ACTION_TIMEOUT = 10;
	const ShallowRender = (view) => {
		const ReactShallow = TestUtils.createRenderer();
		ReactShallow.render(view);
		return ReactShallow.getRenderOutput();
	};

	it('should create React component', () => {
		const Container = Transmitter.create(Component, {});

		assert.ok(TestUtils.isElement(<Container />), 'Container should be a React component');
		assert.equal(Container.displayName, 'Transmitter(Component)', 'Container should have Component\'s name with suffix');
	});

	it('should create React component if enum is used', () => {
		const Container = Transmitter.create({success: Component}, {});

		assert.ok(TestUtils.isElement(<Container />), 'Container should be a React component');
		assert.equal(Container.displayName, 'Transmitter(Component)', 'Container should have Component\'s name with suffix');
	});

	it('should raise an error if no components are specified', () => {
		assert.throws(() => Transmitter.create({success: null}, {}), /Success, Failure and Pending should be React components/);
		assert.throws(() => Transmitter.create({}, {}), /Success component should be specified/);
	});

	it('should render Pending component by default', () => {
		const Spinner = () =>
Loading...
;
		const Container = Transmitter.create({success: Component, pending: Spinner}, {});
		const RenderOutput = ShallowRender(<Container />);

		assert.ok(TestUtils.isElementOfType(RenderOutput, Spinner), 'Pending component should be rendered');
	});

	it('should render Success component with data fetched from fragments', (done) => {
		const thingFragment = sinon.stub().returns(new Promise((resolve) => {
			setTimeout(resolve, FIRST_ACTION_TIMEOUT, VALUE);
		}));
		const Container = Transmitter.create(Component, {
			fragments: {thing: thingFragment}
		});
		const ReactShallow = TestUtils.createRenderer();

		ReactShallow.render(<Container />);

		setTimeout(() => {
			const Output = ReactShallow.getRenderOutput();

			assert.ok(TestUtils.isElementOfType(Output, Component), 'Success component should be rendered');
			assert.deepEqual(Output.props, {thing: VALUE}, 'Component should be rendered with data fetched via fragments');
			done();
		}, SECOND_ACTION_TIMEOUT);
	});

	it('should render Failure component with error raised from fragments', (done) => {
		const thingFragment = sinon.stub().returns(new Promise((_, reject) => {
			setTimeout(reject, FIRST_ACTION_TIMEOUT, ERROR);
		}));
		const Container = Transmitter.create({success: Component, failure: FailureComponent}, {
			fragments: {thing: thingFragment}
		});
		const ReactShallow = TestUtils.createRenderer();

		ReactShallow.render(<Container />);

		setTimeout(() => {
			const Output = ReactShallow.getRenderOutput();

			assert.ok(TestUtils.isElementOfType(Output, FailureComponent), 'Failure component should be rendered');
			assert.deepEqual(Output.props.error, {type: Transmitter.FETCH_FAILED, error: ERROR}, 'Component should be rendered with error raised via fragments');
			assert.ok(typeof Output.props.onRetry === 'function', 'onRetry callback should be passed as prop');
			done();
		}, SECOND_ACTION_TIMEOUT);
	});

	it('should call fragments with passed variables', () => {
		const thingFragment = sinon.stub().returns(Promise.resolve(VALUE));
		const Container = Transmitter.create(Component, {
			fragments: {thing: thingFragment}
		});
		const variables = {id: VALUE};
		const RenderOutput = ShallowRender(<Container variables={variables} />);

		assert.ok(thingFragment.calledWith(variables), 'Fragment should be called with passed variables');
	});

	it('should use initial variables if actual are not specified', () => {
		const thingFragment = sinon.stub().returns(Promise.resolve(VALUE));
		const Container = Transmitter.create(Component, {
			initialVariables: {a: VALUE},
			fragments: {thing: thingFragment}
		});
		const variables = {id: VALUE};
		const RenderOutput = ShallowRender(<Container variables={variables} />);

		assert.ok(thingFragment.calledWith({a: VALUE, id: VALUE}), 'Fragment should be called with passed variables mixed with initial variables');
	});

	xit('should actually work with stores and simple observables', () => {
		// TODO: implement this test
	});

	it('should dispose subscriptions after unmount', () => {
		const RENDER_ROOT = document.createElement('div');
		const disposeStub = sinon.spy();
		const Disposable = Observable.create(observer => ({dispose: disposeStub}));
		const Container = Transmitter.create(Component, {
			fragments: {thing: () => Disposable}
		});

		ReactDOM.render(<Container />, RENDER_ROOT);
		ReactDOM.unmountComponentAtNode(RENDER_ROOT);

		assert.ok(disposeStub.called, 'Dispose method should be called if Container was unmounted');
	});

	// waiting for https://github.com/facebook/react/pull/5247 being merged
	xit('should immediately render Success component if fragments are passed via props', () => {
		const thingFragment = sinon.stub().returns(new Promise((resolve) => {
			setTimeout(resolve, FIRST_ACTION_TIMEOUT, VALUE);
		}));
		const Container = Transmitter.create(Component, {
			fragments: {thing: thingFragment}
		});
		const RenderOutput = ShallowRender(<Container thing={VALUE} />)

		assert.ok(!thingFragment.called, 'Fragment should not be called');
		assert.ok(TestUtils.isElementOfType(RenderOutput, Component), 'Success component should be rendered');
		assert.deepEqual(RenderOutput.props, {thing: VALUE}, 'Component should be rendered with data fetched via fragments');
	});

	xit('should handle failed streams and render Failure element', () => {
		// TODO: implement this test
	});

	xit('should render `null` for not specified components', () => {
		// TODO: implement this test
	});

	xit('should restart fetching if onRetry was called', () => {
		// TODO: implement this test
	});

	xit('should abort fetching if onAbort was called', () => {
		// TODO: implement this test
	});

	xit('should use custom `shouldContainerUpdate` hook', () => {
		// TODO: implement this test
	});

	xit('should be able to get child fragment', () => {
		// TODO: implement this test
	});

	xit('should pass functions from fragments', () => {
		// TODO: implement this test
	});
});
<|endoftext|>


<commit_before>console.log('Loading graph');
var graph = require('./lib/loadgraph.js')();
console.log('Loaded ' + graph.getNodesCount() + ' nodes; ' + graph.getLinksCount() + ' packages');

var createLayout = require('ngraph.offline.layout');
var layout = createLayout(graph);
console.log('Starting layout');
layout.run();
console.log('Done. Now export this to binary format:');
console.log('node toBinary.js');
<commit_msg>Fixed help text<commit_after>console.log('Loading graph');
var graph = require('./lib/loadgraph.js')();
console.log('Loaded ' + graph.getNodesCount() + ' nodes; ' + graph.getLinksCount() + ' edges');

var createLayout = require('ngraph.offline.layout');
var layout = createLayout(graph);
console.log('Starting layout');
layout.run();
console.log('Done. Now export this to binary format:');
console.log('node toBinary.js');
<|endoftext|>


<commit_before>var shutting_down = true;

var pg = require('pg');
var default_owner = null;
var new_pg_client = function () {
  var c = new pg.Client(process.env.DATABASE_URL);
  c.connect();

  // process.on('SIGINT', function () {

    // log('Closing db connections.');
    // c.end();

  // });

  // process.on('SIGTERM', function () {

    // log('Closing db connections.');
    // c.end();

    // setTimeout( function () {
      // console.error("Could not close connections in time, forcing shut down");
      // process.exit(1);
    // }, 30*1000);

  // });

  return c;
}

var pg_client = new_pg_client();
pg_client.query("SELECT usename AS owner FROM pg_database, pg_user WHERE datname = current_database() AND datdba = usesysid;", [], function (err, meta) {
  pg_client.end();
  if (err)
    throw err;
  default_owner = meta.rows[0].owner;
});

function log() {
  console['log'].apply(console, arguments);
}

exports.new_pg_client = new_pg_client;
exports.get_default_owner = function () {
  return default_owner;
}

exports.show_databases = function (func) {
  var pg_client = new_pg_client();
  pg_client.query("SELECT datname AS name FROM pg_database WHERE datistemplate = false;", [], function (err, meta) {
    pg_client.end();
    if (err)
      throw err;
    func(meta);
  });
}

<commit_msg>Added: query buffer<commit_after>var shutting_down = true;

var pg = require('pg');
var default_owner = null;
var new_pg_client = function () {
  var c = new pg.Client(process.env.DATABASE_URL);
  c.connect();

  // process.on('SIGINT', function () {

    // log('Closing db connections.');
    // c.end();

  // });

  // process.on('SIGTERM', function () {

    // log('Closing db connections.');
    // c.end();

    // setTimeout( function () {
      // console.error("Could not close connections in time, forcing shut down");
      // process.exit(1);
    // }, 30*1000);

  // });

  return c;
}

function query(sql, vals, func) {
  this.client   = new_pg_client();
  this.client.connect();
  this.querys   = [];
  this.querys.push([sql, vals]);
  this.on_error = null;
  this.on_end  = func || null;
}

query.prototype.on_error = function (func) {
  this.on_error = func;
}

query.prototype.on_end = function (func) {
  this.on_end = func;
}

query.prototype.run = function () {
  if (this.is_running)
    throw new Error('Already running.');
  else {
    this.is_running = true;
    this.run_next();
  }
}

query.prototype.run_next = function () {
  var me = query;
  if (this.querys.length === 0) {
    return false;
  }

  var q = this.querys.shift();
  this.client.query(q[0], q[1], function (err, meta) {
    var is_end = me.querys.length === 0;
    if (is_end) {
      me.client.end()
    }

    if (err) {
      if (me.on_error)
        return me.on_error(err, meta, me);
      if (me.on_end)
        return me.on_end(err, meta, me);
      throw err;
    }

    if (is_end && me.on_end)
      return me.on_end(err, meta);

    me.run_next();

  });
}

var pg_client = new_pg_client();
pg_client.query("SELECT usename AS owner FROM pg_database, pg_user WHERE datname = current_database() AND datdba = usesysid;", [], function (err, meta) {
  pg_client.end();
  if (err)
    throw err;
  default_owner = meta.rows[0].owner;
});

function log() {
  console['log'].apply(console, arguments);
}

exports.query = query;
exports.new_pg_client = new_pg_client;
exports.get_default_owner = function () {
  return default_owner;
}

exports.show_databases = function (func) {
  var pg_client = new_pg_client();
  pg_client.query("SELECT datname AS name FROM pg_database WHERE datistemplate = false;", [], function (err, meta) {
    pg_client.end();
    if (err)
      throw err;
    func(meta);
  });
}

<|endoftext|>


<commit_before>/**
 * ThramJS
 *
 * Micro front-end framework
 *
 * Created by thram on 17/06/15.
 */
var thram = (function () {

    /**
     * Based on domready by Dustin Diaz: https://github.com/ded/domready
     *
     * @returns {Function}
     * @private
     */
    function _ready() {
        var fns = [], listener
            , doc = document
            , hack = doc.documentElement.doScroll
            , domContentLoaded = 'DOMContentLoaded'
            , loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState);

        if (!loaded)
            doc.addEventListener(domContentLoaded, listener = function () {
                doc.removeEventListener(domContentLoaded, listener);
                loaded = 1;
                while (listener = fns.shift()) listener();
            });

        return function (fn) {
            loaded ? setTimeout(fn, 0) : fns.push(fn);
        }

    }

    var controllers = (function () {
        var _controllers = {};

        function get(key) {
            return _controllers[key];
        }

        function add(key, controller) {
            _controllers[key] = controller;
        }

        return {
            get: get,
            add: add
        }
    })();

    var views = (function () {
        var _views = {};

        function enter() {
            events.trigger('view:enter');
        }

        function leave() {
            events.trigger('view:leave');
        }

        window.onbeforeunload = function () {
            leave();
        };

        function get(key) {
            return _views[key];
        }

        function add(key, view) {
            _views[key] = view;
        }

        return {
            enter: enter,
            leave: leave,
            get: get,
            add: add
        }
    })();

    var components = (function () {
        var _components = {};

        function get(key) {
            return _components[key];
        }

        function add(key, component) {
            _components[key] = component;
        }

        return {
            get: get,
            add: add
        }
    })();

    var modules = (function () {

        var _modules = {};

        function get(key) {
            return _modules[key];
        }

        function add(key, module) {
            _modules[key] = module;
        }

        return {
            get: get,
            add: add
        }
    })();
    var models = (function () {

        var _modules = {};

        function get(key) {
            return _modules[key];
        }

        function add(key, model) {
            _modules[key] = model;
        }

        return {
            get: get,
            add: add
        }
    })();

    var router = (function () {
        function go(route) {
            window.location.href = route;
        }

        function process() {
            var BreakException = {};
            try {
                thram.routes.forEach(function (route) {
                    var routeMatcher = new RegExp(route.route.replace(/:[^\s/]+/g, '([\\w-]+)'));
                    var url = window.location.pathname;
                    var match = url.match(routeMatcher);
                    if (match && match.length > 0 && match[0] === url) {
                        var params = {};
                        if (route.route.indexOf(':') >= 0) {
                            var keys = route.route.match(/:(.+?)(\/|\?|$)/g);
                            if (keys) {
                                keys = keys.join('&').replace(/:/g, '').replace(/\//g, '').split('&');
                                var values = match;
                                keys.forEach(function (key, i) {
                                    params[key] = values[i];
                                });
                            }
                        }

                        function initView() {
                            var base = thram.views.get('base');
                            base && base.init(url, params);
                            thram.views.get(route.view).init(url, params);
                        }

                        route.validate ?
                            (route.validate.validation() ? initView() : route.validate.onValidationFail())
                            : initView();

                        throw BreakException;
                    }
                });
            } catch (e) {
                if (e !== BreakException) throw e;
            }
        }

        return {
            go: go,
            process: process
        }
    })();

    var events = (function () {

        function trigger(event, data) {
            var ev = new Event('thram:' + event, data);
            dispatchEvent(ev);
        }

        function on(event, func) {
            addEventListener("thram:" + event, func);
        }

        function off(event, func) {
            removeEventListener("thram:" + event, func);
        }

        return {
            off: off,
            on: on,
            trigger: trigger
        }
    })();

    var toolbox = (function () {

        var _tools = {};

        function get(key) {
            return _tools[key];
        }

        function add(key, tool) {
            _tools[key] = tool;
        }

        return {
            get: get,
            add: add
        }
    })();

    function start() {
        _ready()(function () {
            views.enter();
            router.process();
        });
    }

    return {
        routes: [],
        examples: {},
        toolbox: toolbox,
        events: events,
        router: router,
        models: models,
        modules: modules,
        components: components,
        controllers: controllers,
        views: views,
        start: start
    }
})();

thram.examples.view = function () {

    // View Example
    function init(url, params) {
        // Initialize View
    }

    return {
        init: init
    }
};

// Route Example
thram.examples.route = {
    route: '/test/:id',
    view: 'test'
};
<commit_msg>Implement templates and client-side routing<commit_after>/**
 * ThramJS
 *
 * Micro front-end framework
 *
 * Created by thram on 17/06/15.
 */
var thram = (function () {

    /**
     *
     * Object.watch and Object.unwatch
     *
     * 2012-04-03
     *
     * By Eli Grey, http://eligrey.com
     * Public Domain.
     *
     * Modified by Nenad Damnjanović
     * Nov 9, 2014
     *
     * Thanks!
     *
     * Example usage:

     var o = {p: 1};

     o.watch("p", function (id, oldval, newval) {
            console.log( "o." + id + " changed from " + oldval + " to " + newval );
            return newval;
    });

     o.p = 2; // should log the change
     o.p = 2; // should do nothing

     */

    if (!Object.prototype.watch) {
        Object.defineProperty(Object.prototype, "watch", {
            enumerable: false
            , configurable: true
            , writable: false
            , value: function (prop, handler) {
                var
                    oldval = this[prop]
                    , getter = function () {
                        return oldval;
                    }
                    , setter = function (newval) {
                        if (oldval !== newval) {
                            handler.call(this, prop, oldval, newval);
                            oldval = newval;
                        }
                        else {
                            return false
                        }
                    }
                    ;

                if (delete this[prop]) { // can't watch constants
                    Object.defineProperty(this, prop, {
                        get: getter
                        , set: setter
                        , enumerable: true
                        , configurable: true
                    });
                }
            }
        });
    }
    if (!Object.prototype.unwatch) {
        Object.defineProperty(Object.prototype, "unwatch", {
            enumerable: false
            , configurable: true
            , writable: false
            , value: function (prop) {
                var val = this[prop];
                delete this[prop]; // remove accessors
                this[prop] = val;
            }
        });
    }

    /**
     * DOM Ready
     *
     * Based on domready by Dustin Diaz: https://github.com/ded/domready
     *
     * @returns {Function}
     * @private
     */
    function _ready() {
        var fns = [], listener
            , doc = document
            , hack = doc.documentElement.doScroll
            , domContentLoaded = 'DOMContentLoaded'
            , loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState);

        if (!loaded)
            doc.addEventListener(domContentLoaded, listener = function () {
                doc.removeEventListener(domContentLoaded, listener);
                loaded = 1;
                while (listener = fns.shift()) listener();
            });

        return function (fn) {
            loaded ? setTimeout(fn, 0) : fns.push(fn);
        }

    }

    /**
     * Storage
     *
     * Implements https://github.com/marcuswestin/store.js/
     *
     */

    var storage = (function () {
        // Store.js
        var store = {},
            win = window,
            doc = win.document,
            localStorageName = 'localStorage',
            scriptTag = 'script',
            storage;

        store.disabled = false;
        store.version = '1.3.17';
        store.set = function (key, value) {
        };
        store.get = function (key, defaultVal) {
        };
        store.has = function (key) {
            return store.get(key) !== undefined
        };
        store.remove = function (key) {
        };
        store.clear = function () {
        };
        store.transact = function (key, defaultVal, transactionFn) {
            if (transactionFn == null) {
                transactionFn = defaultVal;
                defaultVal = null;
            }
            if (defaultVal == null) {
                defaultVal = {};
            }
            var val = store.get(key, defaultVal);
            transactionFn(val);
            store.set(key, val);
        };
        store.getAll = function () {
        };
        store.forEach = function () {
        };

        store.serialize = function (value) {
            return JSON.stringify(value);
        };
        store.deserialize = function (value) {
            if (typeof value != 'string') {
                return undefined;
            }
            try {
                return JSON.parse(value);
            }
            catch (e) {
                return value || undefined;
            }
        };

        // Functions to encapsulate questionable FireFox 3.6.13 behavior
        // when about.config::dom.storage.enabled === false
        // See https://github.com/marcuswestin/store.js/issues#issue/13
        function isLocalStorageNameSupported() {
            try {
                return (localStorageName in win && win[localStorageName]);
            }
            catch (err) {
                return false;
            }
        }

        if (isLocalStorageNameSupported()) {
            storage = win[localStorageName];
            store.set = function (key, val) {
                if (val === undefined) {
                    return store.remove(key);
                }
                storage.setItem(key, store.serialize(val));
                return val;
            };
            store.get = function (key, defaultVal) {
                var val = store.deserialize(storage.getItem(key));
                return (val === undefined ? defaultVal : val)
            };
            store.remove = function (key) {
                storage.removeItem(key);
            };
            store.clear = function () {
                storage.clear()
            };
            store.getAll = function () {
                var ret = {};
                store.forEach(function (key, val) {
                    ret[key] = val;
                });
                return ret;
            };
            store.forEach = function (callback) {
                for (var i = 0; i < storage.length; i++) {
                    var key = storage.key(i);
                    callback(key, store.get(key));
                }
            }
        } else if (doc.documentElement.addBehavior) {
            var storageOwner,
                storageContainer;
            // Since #userData storage applies only to specific paths, we need to
            // somehow link our data to a specific path.  We choose /favicon.ico
            // as a pretty safe option, since all browsers already make a request to
            // this URL anyway and being a 404 will not hurt us here.  We wrap an
            // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
            // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
            // since the iframe access rules appear to allow direct access and
            // manipulation of the document element, even for a 404 page.  This
            // document can be used instead of the current document (which would
            // have been limited to the current path) to perform #userData storage.
            try {
                storageContainer = new ActiveXObject('htmlfile');
                storageContainer.open();
                storageContainer.write('<' + scriptTag + '>document.w=window</' + scriptTag + '><iframe src="/favicon.ico"></iframe>');
                storageContainer.close();
                storageOwner = storageContainer.w.frames[0].document;
                storage = storageOwner.createElement('div');
            } catch (e) {
                // somehow ActiveXObject instantiation failed (perhaps some special
                // security settings or otherwse), fall back to per-path storage
                storage = doc.createElement('div');
                storageOwner = doc.body;
            }
            var withIEStorage = function (storeFunction) {
                return function () {
                    var args = Array.prototype.slice.call(arguments, 0);
                    args.unshift(storage);
                    // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
                    // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
                    storageOwner.appendChild(storage);
                    storage.addBehavior('#default#userData');
                    storage.load(localStorageName);
                    var result = storeFunction.apply(store, args);
                    storageOwner.removeChild(storage);
                    return result;
                }
            };

            // In IE7, keys cannot start with a digit or contain certain chars.
            // See https://github.com/marcuswestin/store.js/issues/40
            // See https://github.com/marcuswestin/store.js/issues/83
            var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
            var ieKeyFix = function (key) {
                return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___');
            };
            store.set = withIEStorage(function (storage, key, val) {
                key = ieKeyFix(key);
                if (val === undefined) {
                    return store.remove(key);
                }
                storage.setAttribute(key, store.serialize(val));
                storage.save(localStorageName);
                return val;
            });
            store.get = withIEStorage(function (storage, key, defaultVal) {
                key = ieKeyFix(key);
                var val = store.deserialize(storage.getAttribute(key));
                return (val === undefined ? defaultVal : val);
            });
            store.remove = withIEStorage(function (storage, key) {
                key = ieKeyFix(key);
                storage.removeAttribute(key);
                storage.save(localStorageName);
            });
            store.clear = withIEStorage(function (storage) {
                var attributes = storage.XMLDocument.documentElement.attributes;
                storage.load(localStorageName);
                while (attributes.length) {
                    storage.removeAttribute(attributes[0].name);
                }
                storage.save(localStorageName);
            });
            store.getAll = function (storage) {
                var ret = {};
                store.forEach(function (key, val) {
                    ret[key] = val;
                });
                return ret;
            };
            store.forEach = withIEStorage(function (storage, callback) {
                var attributes = storage.XMLDocument.documentElement.attributes;
                for (var i = 0, attr; attr = attributes[i]; ++i) {
                    callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
                }
            })
        }

        try {
            var testKey = '__storejs__';
            store.set(testKey, testKey);
            if (store.get(testKey) != testKey) {
                store.disabled = true;
            }
            store.remove(testKey);
        } catch (e) {
            store.disabled = true;
        }
        store.enabled = !store.disabled;

        return store;
    })();

    /**
     * Templates
     *
     * @type {{process}}
     */

    var templates = (function () {
        //function process(id, data) {
        //  var html = document.querySelector('script#' + id + '[type=template]').innerHTML;
        function _loader(templateUrl, success, error) {
            var loader = $("<div>");
            views.enter();
            return loader.load(templateUrl, function (res) {
                views.leave();
                return success && success(res);
            }, error);
        }

        function _processMarkup(template, data) {
            if (template) {
                data = data || {};
                var re = /\{\{(.+?)}}/g,
                    reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g,
                    code = 'with(obj) { var r=[];\n',
                    cursor = 0,
                    result, match;
                var add = function (line, js) {
                    js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
                        (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
                    return add;
                };
                while (match = re.exec(template)) {
                    add(template.slice(cursor, match.index))(match[1], true);
                    cursor = match.index + match[0].length;
                }
                add(template.substr(cursor, template.length - cursor));
                code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, '');
                try {
                    result = new Function('obj', code).apply(data, [data]);
                }
                catch (err) {
                    console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n");
                }
                return result;
            } else {
                throw {error: 'Template undefined'};
            }

        }

        function process(template, options) {
            if (options['async']) {
                _loader(template, function (res) {
                    var container = options['container'] || $('[data-thram-view]');
                    var html = _processMarkup(res, options['data']);
                    container.html(html);
                    options['success'] || options['success'](container);
                });
            } else {
                _processMarkup(template, options['data']);
            }
        }

        return {
            process: process
        }
    })();

    /**
     * Router
     *
     * @type {{go, process}}
     */

    var router = (function () {
        var settings = {
            clientSide: false
        };

        function go(route) {
            window.location.href = route;
        }

        function _processView(url, route, params) {
            thram.views.base && thram.views.base.init(url, params);
            thram.views[route.view].init(url, params);
        }

        function process() {
            var BreakException = {};
            try {
                thram.routes.forEach(function (route) {
                    var routeMatcher = new RegExp(route.route.replace(/:[^\s/]+/g, '([\\w-]+)'));
                    var url = window.location.pathname;
                    if (settings.clientSide && window.location.hash != '') {
                        var hash = window.location.hash;
                        if (hash.indexOf('#/') === 0) {
                            url = hash.substr(hash.indexOf('#') + 1);
                        } else {
                            views.scrollTo(hash);
                        }
                    }

                    var match = url.match(routeMatcher);
                    if (match && match.length > 0 && match[0] === url) {
                        var params = {};
                        if (route.route.indexOf(':') >= 0) {
                            var keys = route.route.match(/:(.+?)(\/|\?|$)/g);
                            if (keys) {
                                keys = keys.join('&').replace(/:/g, '').replace(/\//g, '').split('&');
                                var values = match;
                                keys.forEach(function (key, i) {
                                    params[key] = values[i];
                                });
                            }
                        }

                        function initView() {
                            if (settings.clientSide) {
                                var options = {
                                    async: false,
                                    data: route.data
                                };
                                options['data'].params = params;
                                if (route.templateUrl) {
                                    options['async'] = true;
                                    options['success'] = function (res) {
                                        _processView(url, route, params);
                                    };
                                    templates.process(route.templateUrl, options);
                                } else {
                                    templates.process(route.template, options);
                                }
                            }
                            _processView(url, route, params)
                        }

                        route.validate ?
                            (route.validate.validation() ? initView() : route.validate.onValidationFail())
                            : initView();

                        throw BreakException;
                    }
                });
            } catch (e) {
                if (e !== BreakException) throw e;
            }
        }

        function enableClientSideRouting() {
            settings.clientSide = true;
            $(window).bind('hashchange', function (e) {
                process();
                console.log(window.location.hash);
            });
        }

        return {
            enableClientSideRouting: enableClientSideRouting,
            go: go,
            process: process
        }
    })();

    /**
     * Basic Thram Object
     *
     * @returns {{}}
     * @constructor
     */

    var BaseObject = function () {
        var _object = {};

        function add(key, object) {
            _object[key] = object;
        }

        _object['add'] = add;

        return _object;
    };

    /**
     * Views
     */
    var views = new BaseObject();
    views.add('enter', function () {
        events.trigger('view:enter');
    });
    views.add('leave', function () {
        events.trigger('view:leave');
    });
    views.add('scrollTo', function (selector, callback) {
        var target = $(selector);
        // Smooth Scrolling
        if (target.length) {
            $('html,body').animate({
                scrollTop: target.offset().top
            }, 500, callback);
        }
    });
    window.onbeforeunload = views.leave;

    /**
     * Events
     *
     * @type {{off, on, trigger}}
     */

    var events = new BaseObject();
    events.add('trigger', function (event, data) {
        var ev = new Event('thram:' + event, data);
        dispatchEvent(ev);
    });
    events.add('on', function on(event, func) {
        addEventListener("thram:" + event, func);
    });
    events.add('off', function (event, func) {
        removeEventListener("thram:" + event, func);
    });

    /**
     * Controllers
     *
     * @type {BaseObject}
     */
    var controllers = new BaseObject();

    /**
     * Components
     *
     * TODO Add renderable components
     *
     * @type {BaseObject}
     */
    var components = new BaseObject();
    /**
     * Modules
     *
     * @type {BaseObject}
     */
    var modules = new BaseObject();
    /**
     * Models
     *
     * @type {BaseObject}
     */
    var models = new BaseObject();

    /**
     * Toolbox
     *
     * @type {BaseObject}
     */

    var toolbox = new BaseObject();

    function start() {
        _ready()(function () {
            views.enter();
            router.process();
        });
    }

    return {
        routes: [],
        examples: {},
        storage: storage,
        templates: templates,
        toolbox: toolbox,
        events: events,
        router: router,
        models: models,
        modules: modules,
        components: components,
        controllers: controllers,
        views: views,
        start: start
    }
})();

thram.examples.view = function () {

    // View Example
    function init(url, params) {
        // Initialize View
    }

    return {
        init: init
    }
};

// Route Example
thram.examples.route = {
    route: '/test/:id',
    view: 'test'
};
<|endoftext|>


<commit_before>var x11 = require('x11')
var X

var Layout = require('./layout')
var u      = require('./utils')

require('./xorg')(function (err, client, display) {
  if(err) throw err

  var rw = client.root

  var layouts = [new Layout(rw), new Layout(rw), new Layout(rw)]

  var l = layouts[0]

  function cycleLayout(dir) {
    l._delay = Date.now() + l.delay
    l.hide()
    l = u.relative(layouts, l, dir || 1)
    l.show()
  }

  //create a new window, but don't add it to the tree.

  var EV = x11.eventMask.Exposure | x11.eventMask.SubstructureRedirect
      | x11.eventMask.MapRequest | x11.eventMask.SubstructureNotify
      | x11.eventMask.EnterWindow

  rw.set({eventMask: EV}, function(err) {
    if (err && err.error == 10) {
        console.error('Error: another window manager already running.');
        process.exit(1);
    }
  })

  rw.children(function (err, children) {
    children.forEach(function (win) {
      win.kill()
      l.remove(win)
    })
    l.layout()
  })

  rw.on('MapRequest', function (ev, win) {
    //load the window's properties, and then lay it out.
    win.load(function () {
      //add to current layout
      l.add(win)
      win.map()
      l.layout()
    })
    win.set({eventMask: x11.eventMask.EnterWindow})
  })

  rw.on('DestroyNotify', function (ev, win) {
    l.remove(win)
    //UGLY HACK AROUND STRANGE ERROR WHERE
    //KB SHORTCUTS STOP WORKING WHEN YOU CLOSE ALL THE WINDOWS
    if(!l.tiles.length)
      spawn(process.env.TERM || 'xterm')
  })

  rw.on('ConfigureRequest', function (ev, win) {
    //prevent windows from sizing themselves?
    if(win.bounds)
      win.bounds.size.set(ev.width, ev.height)
    else
      win.resize(ev.width, ev.height)
  })

  var spawn = require('child_process').spawn

  //open terminal
  //Command-T/K
  rw.onKey(0x40, 45, function (ev) {
    if(ev.down)
      spawn(process.env.TERM || 'xterm')
  })

  //Command-C/I
  rw.onKey(0x40, 31, function (ev) {
    if(ev.down)
      spawn(process.env.BROWSER || 'chromium')
  })

  //Command-Esc
  rw.onKey(0x40, 9, function (ev) {
    if(ev.down) {
      console.log('quiting...')
      process.exit(0)
    }
  })

  //Command-Space
  rw.onKey(0x40, 65, function (ev) {
    if(ev.down) l.toggle()
  })

  //Command-Left
  rw.onKey(0x40, 113, function (ev) {
    if(ev.down) l.cycle(-1)
  })
  rw.onKey(0x40, 114, function (ev) {
    if(ev.down) l.cycle(1)
  })

  //Command-Left
  rw.onKey(0x41, 113, function (ev) {
    if(ev.down) l.move(-1)
  })

  rw.onKey(0x41, 114, function (ev) {
    if(ev.down) l.move(1)
  })

  rw.onKey(0x40, 111, function (ev) {
    if(ev.down) cycleLayout(1)
  })

  rw.onKey(0x40, 116 , function (ev) {
    if(ev.down) cycleLayout(-1)
  })

  function close (ev) {
    if(ev.down && l.focused) {
      var _focused = l.focused
      l.cycle(-1)
      _focused.close()
    }
  }

  rw.onKey(0x40, 53, close) //command-Q
  rw.onKey(0x40, 59, close) //command-W
})

<commit_msg>allow creating more spaces<commit_after>var x11 = require('x11')
var X

var Layout = require('./layout')
var u      = require('./utils')

require('./xorg')(function (err, client, display) {
  if(err) throw err

  var rw = client.root

  var layouts = [new Layout(rw)]

  var l = layouts[0]

  function cycleLayout(dir) {
    l._delay = Date.now() + l.delay
    l.hide()
    l = u.relative(layouts, l, dir || 1)
    l.show()
  }

  //create a new window, but don't add it to the tree.

  var EV = x11.eventMask.Exposure | x11.eventMask.SubstructureRedirect
      | x11.eventMask.MapRequest | x11.eventMask.SubstructureNotify
      | x11.eventMask.EnterWindow

  rw.set({eventMask: EV}, function(err) {
    if (err && err.error == 10) {
        console.error('Error: another window manager already running.');
        process.exit(1);
    }
  })

  rw.children(function (err, children) {
    children.forEach(function (win) {
      win.kill()
      l.remove(win)
    })
    l.layout()
  })

  rw.on('MapRequest', function (ev, win) {
    //load the window's properties, and then lay it out.
    win.load(function () {
      //add to current layout
      win.map()
      l.add(win)
      win.focus()
      win.raise()
      l.layout()
    })
    win.set({eventMask: x11.eventMask.EnterWindow})
  })

  rw.on('DestroyNotify', function (ev, win) {
    l.remove(win)
    //UGLY HACK AROUND STRANGE ERROR WHERE
    //KB SHORTCUTS STOP WORKING WHEN YOU CLOSE ALL THE WINDOWS
    if(!l.tiles.length)
      spawn(process.env.TERM || 'xterm')
  })

  rw.on('ConfigureRequest', function (ev, win) {
    //prevent windows from sizing themselves?
    if(win.bounds)
      win.bounds.size.set(ev.width, ev.height)
    else
      win.resize(ev.width, ev.height)
  })

  var spawn = require('child_process').spawn

  //open terminal
  //Command-T/K
  rw.onKey(0x40, 45, function (ev) {
    if(ev.down)
      spawn(process.env.TERM || 'xterm')
  })

  //Command-C/I
  rw.onKey(0x40, 31, function (ev) {
    if(ev.down)
      spawn(process.env.BROWSER || 'chromium')
  })

  //Command-Esc
  rw.onKey(0x40, 9, function (ev) {
    if(ev.down) {
      console.log('quiting...')
      process.exit(0)
    }
  })

  //Command-Space
  rw.onKey(0x40, 65, function (ev) {
    if(ev.down) l.toggle()
  })

  //Command-Left
  rw.onKey(0x40, 113, function (ev) {
    if(ev.down) l.cycle(-1)
  })
  rw.onKey(0x40, 114, function (ev) {
    if(ev.down) l.cycle(1)
  })

  //Command-Left
  rw.onKey(0x41, 113, function (ev) {
    if(ev.down) l.move(-1)
  })

  rw.onKey(0x41, 114, function (ev) {
    if(ev.down) l.move(1)
  })

  rw.onKey(0x40, 111, function (ev) {
    if(ev.down) cycleLayout(1)
  })

  rw.onKey(0x40, 116 , function (ev) {
    if(ev.down) cycleLayout(-1)
  })

  //Ctrl-N
  rw.onKey(0x40, 46 , function (ev) {
    if(!ev.down) return
    console.log('new layout')
    l.hide()
    layouts.push(l = new Layout(rw))
    l.show()
  })

  function close (ev) {
    if(ev.down && l.focused) {
      var _focused = l.focused
      l.cycle(-1)
      _focused.close()
    }
  }

  function closeLayout () {
    var _l = u.relative(layouts, l, -1)
    if(layouts.length <= 1) return
    l.hide()
    if(layouts.length) u.remove(layouts, l.closeAll())
    l = _l
    _l.show()
  }

  rw.onKey(0x40, 53, close) //command-Q
  rw.onKey(0x40, 59, close) //command-W
  rw.onKey(0x41, 59, closeLayout) //command-W
})

<|endoftext|>


<commit_before>/*global Timer:false, performance:false */
"use strict";

// var Timer = Timer || (function () {
// 	var Timer, timerPrototype,
// 	now = Date.now || function () {
// 		return (new Date()).getTime();
// 	};

// 	if (typeof chrome !== "undefined" && typeof chrome.Interval === "function") {
// 		// Google Chrome has a native timer constructor
// 		timerPrototype = (Timer = chrome.Interval).prototype;
// 		timerPrototype.milliseconds = function () {
// 			return this.microseconds() / 1000;
// 		};
// 	}
// 	else {
// 		timerPrototype = (Timer = function () {
// 			var startT = 0,
// 			stopT = 0;

// 			this.start = function () {
// 				stopT = 0;
// 				startT = performance.now();
// 			};

// 			this.stop = function () {
// 				stopT = now();
// 				if (startT === 0) {
// 					stopT = 0;
// 				}
// 			};
// 			this.milliseconds = function () {
// 				var stop = stopT;
// 				if (stop === 0 && startT !== 0) {
// 					stop = performance.now();
// 				}
// 				return stop - startT;
// 			};
// 		}).prototype;
// 		timerPrototype.microseconds = function () {
// 			return this.milliseconds() * 1000;
// 		};
// 	}
// 	timerPrototype.profile = function (fn, iterations) {
// 		if (typeof fn === "string") {
// 			fn = new Function(fn);
// 		}
// 		this.start();
// 		while (iterations--) {
// 			fn();
// 		}
// 		this.stop();
// 	};
// 	timerPrototype.seconds = function () {
// 		return this.milliseconds() / 1000;
// 	};
// 	return Timer;
// }());

(function() {
	var _startTime = 0, _stopTime = 0, _start, _stop, _milliseconds;

	window.Timer = {};

	Timer.start = function(){
		_start();
	};

	Timer.stop = function(){
		_stop();
	};

	Timer.microseconds = function(){
		return _milliseconds()*1000;
	};

	Timer.milliseconds = function(){
		return _milliseconds();
	};

	Timer.seconds = function(){
		return _milliseconds()/1000;
	};

	_start = function(){
		_startTime = performance.now();
		_stopTime = 0;
	};

	_stop = function(){
		_stopTime = performance.now();

		if(_startTime === 0){
			_stopTime = 0;
		}
	};

	_milliseconds = function(){
		var stop = _stopTime;

		if(_startTime !== 0 && stop === 0){
			stop = performance.now();
		}

		return stop - _startTime;
	};
})();<commit_msg>final code<commit_after>/*global Timer:false, performance:false */
"use strict";

(function(window) {
	var Local = (function(window){

		function Local(){
			this.startTime = 0;
			this.stopTime = 0;
		}

		Local.prototype.start = function(){
			this.startTime = performance.now();
			this.stopTime = 0;
		};

		Local.prototype.stop = function(){
			this.stopTime = performance.now();

			if(this.startTime === 0){
				this.stopTime = 0;
			}
		};

		Local.prototype.milliseconds = function(){
			var stop = this.stopTime;

			if(this.startTime !== 0 && stop === 0){
				stop = performance.now();
			}

			return stop - this.startTime;
		};

		return Local;
	})(window);

	var Timer = function Timer(){
		Local = new Local();
	};

	Timer.prototype.start = function(){
		Local.start();
	};

	Timer.prototype.stop = function(){
		Local.stop();
	};

	Timer.prototype.microseconds = function(){
		return Local.milliseconds()*1000;
	};

	Timer.prototype.milliseconds = function(){
		return Local.milliseconds();
	};

	Timer.prototype.seconds = function(){
		return Local.milliseconds()/1000;
	};

	var Timer = new Timer();
	window.Timer = Timer;
})(window);<|endoftext|>


<commit_before>/*
Name:         tk102
Description:  TK102 GPS server for Node.js
Author:       Franklin van de Meent (https://frankl.in)
Source:       https://github.com/fvdm/nodejs-tk102
Feedback:     https://github.com/fvdm/nodejs-tk102/issues
License:      Unlicense / Public Domain (see UNLICENSE file)
              (https://github.com/fvdm/nodejs-tk102/raw/master/UNLICENSE)
*/

var net = require ('net');
var EventEmitter = require ('events') .EventEmitter;
var tk102 = new EventEmitter ();

// defaults
tk102.settings = {
  ip: '0.0.0.0',
  port: 0, // 0 = random, see `listening` event
  connections: 10,
  timeout: 10
};

// device data
var specs = [
  // 1203292316,0031698765432,GPRMC,211657.000,A,5213.0247,N,00516.7757,E,0.00,273.30,290312,,,A*62,F,imei:123456789012345,123
  function (raw) {
    var result = null;
    try {
      var raw = raw.trim ();
      var str = raw.split (',');

      if (str.length === 18 && str [2] === 'GPRMC') {
        var datetime = str [0] .replace (/([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/, function (s, y, m, d, h, i) {
          return '20'+ y +'-'+ m +'-'+ d +' '+ h +':'+ i;
        });

        var gpsdate = str [11] .replace (/([0-9]{2})([0-9]{2})([0-9]{2})/, function (s, d, m, y) {
          return '20'+ y +'-'+ m +'-'+ d;
        });

        var gpstime = str [3] .replace (/([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{3})/, function (s, h, i, s, ms) {
          return h +':'+ i +':'+ s +'.'+ ms
        });

        result = {
          'raw': raw,
          'datetime': datetime,
          'phone': str [1],
          'gps': {
            'date': gpsdate,
            'time': gpstime,
            'signal': str [15] == 'F' ? 'full' : 'low',
            'fix': str [4] == 'A' ? 'active' : 'invalid'
          },
          'geo': {
            'latitude': tk102.fixGeo (str [5], str [6]),
            'longitude': tk102.fixGeo (str [7], str [8]),
            'bearing': parseInt (str [10])
          },
          'speed': {
            'knots': Math.round (str [9] * 1000) / 1000,
            'kmh': Math.round (str [9] * 1.852 * 1000) / 1000,
            'mph': Math.round (str [9] * 1.151 * 1000) / 1000
          },
          'imei': str [16] .replace ('imei:', '');
        };
      }
    }
    catch (e) {}
    return result;
  }
];

// Catch uncaught exceptions (server kill)
process.on ('uncaughtException', function (err) {
  var error = new Error ('uncaught exception');
  error.error = err;
  console.trace (error);
});

// Create server
tk102.createServer = function (vars) {
  // override settings
  if( typeof vars === 'object' && Object.keys (vars) .length >= 1 ) {
    for (var key in vars) {
      tk102.settings [key] = vars [key];
    }
  }

  // start server
  tk102.server = net.createServer (function (socket) {
    // socket idle timeout
    if (tk102.settings.timeout > 0) {
      socket.setTimeout (tk102.settings.timeout * 1000, function () {
        tk102.emit ('timeout', socket);
        socket.end ();
      });
    }
  }) .listen (tk102.settings.port, tk102.settings.ip, function () {
    // server ready
    tk102.emit ('listening', tk102.server.address ());
  });

  // maximum number of slots
  tk102.server.maxConnections = tk102.settings.connections;

  // inbound connection
  tk102.server.on ('connection', function (socket) {
    tk102.emit ('connection', socket);
    socket.setEncoding ('utf8');
    var data = [];
    var size = 0;

    socket.on ('data', function (ch) {
      tk102.emit ('data', ch);
      data.push (ch);
      size += ch.length;
    });

    socket.on( 'close', function() {
      data = Buffer.concat (data, size).toString ('utf8');
      var gps = {};
      gps = tk102.parse (data);
      if (data != '') {
        var gps = tk102.parse (data);
        if (gps) {
          tk102.emit ('track', gps);
        } else {
          var err = new Error ('Cannot parse GPS data from device');
          err.reason = err.message;
          err.socket = socket;
          err.input = data;
          tk102.emit ('fail', err);
        }
      }
    });

    // error
    socket.on ('error', function (error) {
      var err = new Error ('Socket error');
      err.reason = err.message;
      err.socket = socket;
      err.settings = tk102.settings;
      tk102.emit ('error', err);
    });
  });

  tk102.server.on ('error', function (error) {
    if (error === 'EADDRNOTAVAIL') {
      var err = new Error ('IP or port not available');
    } else {
      var err = new Error ('Server error');
    }

    err.reason = err.message;
    err.input = tk102.settings;
    tk102.emit ('error', err);
  });
};

// Parse GPRMC string
tk102.parse = function (raw) {
  var data = null;
  var i = 0;
  while (data === null && i < specs.length) {
    data = specs [i] (raw);
    i++;
  }
  return data;
};

// Clean geo positions, with 6 decimals
tk102.fixGeo = function (one, two) {
  var minutes = one.substr (-7, 7);
  var degrees = parseInt (one.replace (minutes, ''), 10);
  var one = degrees + (minutes / 60);
  var one = parseFloat ((two === 'S' || two === 'W' ? '-' : '') + one);
  return Math.round (one * 1000000) / 1000000;
};

// ready
module.exports = tk102;
<commit_msg>Removed invalid semicolon<commit_after>/*
Name:         tk102
Description:  TK102 GPS server for Node.js
Author:       Franklin van de Meent (https://frankl.in)
Source:       https://github.com/fvdm/nodejs-tk102
Feedback:     https://github.com/fvdm/nodejs-tk102/issues
License:      Unlicense / Public Domain (see UNLICENSE file)
              (https://github.com/fvdm/nodejs-tk102/raw/master/UNLICENSE)
*/

var net = require ('net');
var EventEmitter = require ('events') .EventEmitter;
var tk102 = new EventEmitter ();

// defaults
tk102.settings = {
  ip: '0.0.0.0',
  port: 0, // 0 = random, see `listening` event
  connections: 10,
  timeout: 10
};

// device data
var specs = [
  // 1203292316,0031698765432,GPRMC,211657.000,A,5213.0247,N,00516.7757,E,0.00,273.30,290312,,,A*62,F,imei:123456789012345,123
  function (raw) {
    var result = null;
    try {
      var raw = raw.trim ();
      var str = raw.split (',');

      if (str.length === 18 && str [2] === 'GPRMC') {
        var datetime = str [0] .replace (/([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/, function (s, y, m, d, h, i) {
          return '20'+ y +'-'+ m +'-'+ d +' '+ h +':'+ i;
        });

        var gpsdate = str [11] .replace (/([0-9]{2})([0-9]{2})([0-9]{2})/, function (s, d, m, y) {
          return '20'+ y +'-'+ m +'-'+ d;
        });

        var gpstime = str [3] .replace (/([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{3})/, function (s, h, i, s, ms) {
          return h +':'+ i +':'+ s +'.'+ ms
        });

        result = {
          'raw': raw,
          'datetime': datetime,
          'phone': str [1],
          'gps': {
            'date': gpsdate,
            'time': gpstime,
            'signal': str [15] == 'F' ? 'full' : 'low',
            'fix': str [4] == 'A' ? 'active' : 'invalid'
          },
          'geo': {
            'latitude': tk102.fixGeo (str [5], str [6]),
            'longitude': tk102.fixGeo (str [7], str [8]),
            'bearing': parseInt (str [10])
          },
          'speed': {
            'knots': Math.round (str [9] * 1000) / 1000,
            'kmh': Math.round (str [9] * 1.852 * 1000) / 1000,
            'mph': Math.round (str [9] * 1.151 * 1000) / 1000
          },
          'imei': str [16] .replace ('imei:', '')
        };
      }
    }
    catch (e) {}
    return result;
  }
];

// Catch uncaught exceptions (server kill)
process.on ('uncaughtException', function (err) {
  var error = new Error ('uncaught exception');
  error.error = err;
  console.trace (error);
});

// Create server
tk102.createServer = function (vars) {
  // override settings
  if( typeof vars === 'object' && Object.keys (vars) .length >= 1 ) {
    for (var key in vars) {
      tk102.settings [key] = vars [key];
    }
  }

  // start server
  tk102.server = net.createServer (function (socket) {
    // socket idle timeout
    if (tk102.settings.timeout > 0) {
      socket.setTimeout (tk102.settings.timeout * 1000, function () {
        tk102.emit ('timeout', socket);
        socket.end ();
      });
    }
  }) .listen (tk102.settings.port, tk102.settings.ip, function () {
    // server ready
    tk102.emit ('listening', tk102.server.address ());
  });

  // maximum number of slots
  tk102.server.maxConnections = tk102.settings.connections;

  // inbound connection
  tk102.server.on ('connection', function (socket) {
    tk102.emit ('connection', socket);
    socket.setEncoding ('utf8');
    var data = [];
    var size = 0;

    socket.on ('data', function (ch) {
      tk102.emit ('data', ch);
      data.push (ch);
      size += ch.length;
    });

    socket.on( 'close', function() {
      data = Buffer.concat (data, size).toString ('utf8');
      var gps = {};
      gps = tk102.parse (data);
      if (data != '') {
        var gps = tk102.parse (data);
        if (gps) {
          tk102.emit ('track', gps);
        } else {
          var err = new Error ('Cannot parse GPS data from device');
          err.reason = err.message;
          err.socket = socket;
          err.input = data;
          tk102.emit ('fail', err);
        }
      }
    });

    // error
    socket.on ('error', function (error) {
      var err = new Error ('Socket error');
      err.reason = err.message;
      err.socket = socket;
      err.settings = tk102.settings;
      tk102.emit ('error', err);
    });
  });

  tk102.server.on ('error', function (error) {
    if (error === 'EADDRNOTAVAIL') {
      var err = new Error ('IP or port not available');
    } else {
      var err = new Error ('Server error');
    }

    err.reason = err.message;
    err.input = tk102.settings;
    tk102.emit ('error', err);
  });
};

// Parse GPRMC string
tk102.parse = function (raw) {
  var data = null;
  var i = 0;
  while (data === null && i < specs.length) {
    data = specs [i] (raw);
    i++;
  }
  return data;
};

// Clean geo positions, with 6 decimals
tk102.fixGeo = function (one, two) {
  var minutes = one.substr (-7, 7);
  var degrees = parseInt (one.replace (minutes, ''), 10);
  var one = degrees + (minutes / 60);
  var one = parseFloat ((two === 'S' || two === 'W' ? '-' : '') + one);
  return Math.round (one * 1000000) / 1000000;
};

// ready
module.exports = tk102;
<|endoftext|>