<commit_before>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import {getTrackCSS, getTrackLeft, getTrackAnimateCSS} from './trackHelper';
import assign from 'object-assign';

var helpers = {
  initialize: function (props) {
    const slickList = ReactDOM.findDOMNode(this.list);

    var slideCount = React.Children.count(props.children);
    var listWidth = this.getWidth(slickList);
    var trackWidth = this.getWidth(ReactDOM.findDOMNode(this.track));
    var slideWidth;

    if (!props.vertical) {
      var centerPaddingAdj = props.centerMode && (parseInt(props.centerPadding) * 2);
      slideWidth = (this.getWidth(ReactDOM.findDOMNode(this)) - centerPaddingAdj)/props.slidesToShow;
    } else {
      slideWidth = this.getWidth(ReactDOM.findDOMNode(this));
    }

    const slideHeight = this.getHeight(slickList.querySelector('[data-index="0"]'));
    const listHeight = slideHeight * props.slidesToShow;

    var currentSlide = props.rtl ? slideCount - 1 - props.initialSlide : props.initialSlide;

    this.setState({
      slideCount,
      slideWidth,
      listWidth,
      trackWidth,
      currentSlide,
      slideHeight,
      listHeight,
    }, function () {

      var targetLeft = getTrackLeft(assign({
        slideIndex: this.state.currentSlide,
        trackRef: this.track
      }, props, this.state));
      // getCSS function needs previously set state
      var trackStyle = getTrackCSS(assign({left: targetLeft}, props, this.state));

      this.setState({trackStyle: trackStyle});

      this.autoPlay(); // once we're set up, trigger the initial autoplay.
    });
  },
  update: function (props) {
    const slickList = ReactDOM.findDOMNode(this.list);
    // This method has mostly same code as initialize method.
    // Refactor it
    var slideCount = React.Children.count(props.children);
    var listWidth = this.getWidth(slickList);
    var trackWidth = this.getWidth(ReactDOM.findDOMNode(this.track));
    var slideWidth;

    if (!props.vertical) {
      var centerPaddingAdj = props.centerMode && (parseInt(props.centerPadding) * 2);
      slideWidth = (this.getWidth(ReactDOM.findDOMNode(this)) - centerPaddingAdj)/props.slidesToShow;
    } else {
      slideWidth = this.getWidth(ReactDOM.findDOMNode(this));
    }

    const slideHeight = this.getHeight(slickList.querySelector('[data-index="0"]'));
    const listHeight = slideHeight * props.slidesToShow;

    // pause slider if autoplay is set to false
    if(!props.autoplay) {
      this.pause();
    } else {
      this.autoPlay();
    }

    this.setState({
      slideCount,
      slideWidth,
      listWidth,
      trackWidth,
      slideHeight,
      listHeight,
    }, function () {

      var targetLeft = getTrackLeft(assign({
        slideIndex: this.state.currentSlide,
        trackRef: this.track
      }, props, this.state));
      // getCSS function needs previously set state
      var trackStyle = getTrackCSS(assign({left: targetLeft}, props, this.state));

      this.setState({trackStyle: trackStyle});
    });
  },
  getWidth: function getWidth(elem) {
    return elem && (elem.getBoundingClientRect().width || elem.offsetWidth) || 0;
  },
  getHeight(elem) {
    return elem && (elem.getBoundingClientRect().height || elem.offsetHeight) || 0;
  },
  adaptHeight: function () {
    if (this.props.adaptiveHeight) {
      var selector = '[data-index="' + this.state.currentSlide +'"]';
      if (this.list) {
        var slickList = ReactDOM.findDOMNode(this.list);
        slickList.style.height = slickList.querySelector(selector).offsetHeight + 'px';
      }
    }
  },
  canGoNext: function (opts){
    var canGo = true;
    if (!opts.infinite) {
      if (opts.centerMode) {
        // check if current slide is last slide
        if (opts.currentSlide >= (opts.slideCount - 1)) {
          canGo = false;
        }
      } else {
        // check if all slides are shown in slider
        if (opts.slideCount <= opts.slidesToShow ||
          opts.currentSlide >= (opts.slideCount - opts.slidesToShow)) {
          canGo = false;
        }
      }
    }
    return canGo;
  },
  slideHandler: function (index) {
    // Functionality of animateSlide and postSlide is merged into this function
    // console.log('slideHandler', index);
    var targetSlide, currentSlide;
    var targetLeft, currentLeft;
    var callback;

    if (this.props.waitForAnimate && this.state.animating) {
      return;
    }

    if (this.props.fade) {
      currentSlide = this.state.currentSlide;

      // Don't change slide if it's not infite and current slide is the first or last slide.
      if(this.props.infinite === false &&
        (index < 0 || index >= this.state.slideCount)) {
        return;
      }

      //  Shifting targetSlide back into the range
      if (index < 0) {
        targetSlide = index + this.state.slideCount;
      } else if (index >= this.state.slideCount) {
        targetSlide = index - this.state.slideCount;
      } else {
        targetSlide = index;
      }

      if (this.props.lazyLoad && this.state.lazyLoadedList.indexOf(targetSlide) < 0) {
        this.setState({
          lazyLoadedList: this.state.lazyLoadedList.concat(targetSlide)
        });
      }

      callback = () => {
        this.setState({
          animating: false
        });
        if (this.props.afterChange) {
          this.props.afterChange(targetSlide);
        }
        delete this.animationEndCallback;
      };

      this.setState({
        animating: true,
        currentSlide: targetSlide
      }, function () {
        this.animationEndCallback = setTimeout(callback, this.props.speed);
      });

      if (this.props.beforeChange) {
        this.props.beforeChange(this.state.currentSlide, targetSlide);
      }

      this.autoPlay();
      return;
    }

    targetSlide = index;
    if (targetSlide < 0) {
      if(this.props.infinite === false) {
        currentSlide = 0;
      } else if (this.state.slideCount % this.props.slidesToScroll !== 0) {
        currentSlide = this.state.slideCount - (this.state.slideCount % this.props.slidesToScroll);
      } else {
        currentSlide = this.state.slideCount + targetSlide;
      }
    } else if (targetSlide >= this.state.slideCount) {
      if(this.props.infinite === false) {
        currentSlide = this.state.slideCount - this.props.slidesToShow;
      } else if (this.state.slideCount % this.props.slidesToScroll !== 0) {
        currentSlide = 0;
      } else {
        currentSlide = targetSlide - this.state.slideCount;
      }
    } else {
      currentSlide = targetSlide;
    }

    targetLeft = getTrackLeft(assign({
      slideIndex: targetSlide,
      trackRef: this.track
    }, this.props, this.state));

    currentLeft = getTrackLeft(assign({
      slideIndex: currentSlide,
      trackRef: this.track
    }, this.props, this.state));

    if (this.props.infinite === false) {
      targetLeft = currentLeft;
    }

    if (this.props.beforeChange) {
      this.props.beforeChange(this.state.currentSlide, currentSlide);
    }

    if (this.props.lazyLoad) {
      var loaded = true;
      var slidesToLoad = [];
      for (var i = targetSlide; i < targetSlide + this.props.slidesToShow; i++ ) {
        loaded = loaded && (this.state.lazyLoadedList.indexOf(i) >= 0);
        if (!loaded) {
          slidesToLoad.push(i);
        }
      }
      if (!loaded) {
        this.setState({
          lazyLoadedList: this.state.lazyLoadedList.concat(slidesToLoad)
        });
      }
    }

    // Slide Transition happens here.
    // animated transition happens to target Slide and
    // non - animated transition happens to current Slide
    // If CSS transitions are false, directly go the current slide.

    if (this.props.useCSS === false) {

      this.setState({
        currentSlide: currentSlide,
        trackStyle: getTrackCSS(assign({left: currentLeft}, this.props, this.state))
      }, function () {
        if (this.props.afterChange) {
          this.props.afterChange(currentSlide);
        }
      });

    } else {

      var nextStateChanges = {
        animating: false,
        currentSlide: currentSlide,
        trackStyle: getTrackCSS(assign({left: currentLeft}, this.props, this.state)),
        swipeLeft: null
      };

      callback = () => {
        this.setState(nextStateChanges);
        if (this.props.afterChange) {
          this.props.afterChange(currentSlide);
        }
        delete this.animationEndCallback;
      };

      this.setState({
        animating: true,
        currentSlide: currentSlide,
        trackStyle: getTrackAnimateCSS(assign({left: targetLeft}, this.props, this.state))
      }, function () {
        this.animationEndCallback = setTimeout(callback, this.props.speed);
      });

    }

    this.autoPlay();
  },
  swipeDirection: function (touchObject) {
    var xDist, yDist, r, swipeAngle;

    xDist = touchObject.startX - touchObject.curX;
    yDist = touchObject.startY - touchObject.curY;
    r = Math.atan2(yDist, xDist);

    swipeAngle = Math.round(r * 180 / Math.PI);
    if (swipeAngle < 0) {
        swipeAngle = 360 - Math.abs(swipeAngle);
    }
    if ((swipeAngle <= 45) && (swipeAngle >= 0) || (swipeAngle <= 360) && (swipeAngle >= 315)) {
        return (this.props.rtl === false ? 'left' : 'right');
    }
    if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
        return (this.props.rtl === false ? 'right' : 'left');
    }
    if (this.props.verticalSwiping === true) {
      if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
        return 'down';
      } else {
        return 'up';
      }
    }

    return 'vertical';
  },
  play: function(){
    var nextIndex;

    if (!this.state.mounted) {
      return false
    }

    if (this.props.rtl) {
      nextIndex = this.state.currentSlide - this.props.slidesToScroll;
    } else {
      if (this.canGoNext(Object.assign({}, this.props,this.state))) {
        nextIndex = this.state.currentSlide + this.props.slidesToScroll;
      } else {
        return false;
      }
    }

    this.slideHandler(nextIndex);
  },
  autoPlay: function () {
    if (this.state.autoPlayTimer) {
      clearTimeout(this.state.autoPlayTimer);
    }
    if (this.props.autoplay) {
      this.setState({
        autoPlayTimer: setTimeout(this.play, this.props.autoplaySpeed)
      });
    }
  },
  pause: function () {
    if (this.state.autoPlayTimer) {
      clearTimeout(this.state.autoPlayTimer);
      this.setState({
        autoPlayTimer: null
      });
    }
  }
};

export default helpers;
<commit_msg>Fix slide width issue by transform scale<commit_after>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import {getTrackCSS, getTrackLeft, getTrackAnimateCSS} from './trackHelper';
import assign from 'object-assign';

var helpers = {
  initialize: function (props) {
    const slickList = ReactDOM.findDOMNode(this.list);

    var slideCount = React.Children.count(props.children);
    var listWidth = this.getWidth(slickList);
    var trackWidth = this.getWidth(ReactDOM.findDOMNode(this.track));
    var slideWidth;

    if (!props.vertical) {
      var centerPaddingAdj = props.centerMode && (parseInt(props.centerPadding) * 2);
      slideWidth = (this.getWidth(ReactDOM.findDOMNode(this)) - centerPaddingAdj)/props.slidesToShow;
    } else {
      slideWidth = this.getWidth(ReactDOM.findDOMNode(this));
    }

    const slideHeight = this.getHeight(slickList.querySelector('[data-index="0"]'));
    const listHeight = slideHeight * props.slidesToShow;

    var currentSlide = props.rtl ? slideCount - 1 - props.initialSlide : props.initialSlide;

    this.setState({
      slideCount,
      slideWidth,
      listWidth,
      trackWidth,
      currentSlide,
      slideHeight,
      listHeight,
    }, function () {

      var targetLeft = getTrackLeft(assign({
        slideIndex: this.state.currentSlide,
        trackRef: this.track
      }, props, this.state));
      // getCSS function needs previously set state
      var trackStyle = getTrackCSS(assign({left: targetLeft}, props, this.state));

      this.setState({trackStyle: trackStyle});

      this.autoPlay(); // once we're set up, trigger the initial autoplay.
    });
  },
  update: function (props) {
    const slickList = ReactDOM.findDOMNode(this.list);
    // This method has mostly same code as initialize method.
    // Refactor it
    var slideCount = React.Children.count(props.children);
    var listWidth = this.getWidth(slickList);
    var trackWidth = this.getWidth(ReactDOM.findDOMNode(this.track));
    var slideWidth;

    if (!props.vertical) {
      var centerPaddingAdj = props.centerMode && (parseInt(props.centerPadding) * 2);
      slideWidth = (this.getWidth(ReactDOM.findDOMNode(this)) - centerPaddingAdj)/props.slidesToShow;
    } else {
      slideWidth = this.getWidth(ReactDOM.findDOMNode(this));
    }

    const slideHeight = this.getHeight(slickList.querySelector('[data-index="0"]'));
    const listHeight = slideHeight * props.slidesToShow;

    // pause slider if autoplay is set to false
    if(!props.autoplay) {
      this.pause();
    } else {
      this.autoPlay();
    }

    this.setState({
      slideCount,
      slideWidth,
      listWidth,
      trackWidth,
      slideHeight,
      listHeight,
    }, function () {

      var targetLeft = getTrackLeft(assign({
        slideIndex: this.state.currentSlide,
        trackRef: this.track
      }, props, this.state));
      // getCSS function needs previously set state
      var trackStyle = getTrackCSS(assign({left: targetLeft}, props, this.state));

      this.setState({trackStyle: trackStyle});
    });
  },
  getWidth: function getWidth(elem) {
    return elem.offsetWidth || 0;
  },
  getHeight(elem) {
    return elem.offsetHeight || 0;
  },
  adaptHeight: function () {
    if (this.props.adaptiveHeight) {
      var selector = '[data-index="' + this.state.currentSlide +'"]';
      if (this.list) {
        var slickList = ReactDOM.findDOMNode(this.list);
        slickList.style.height = slickList.querySelector(selector).offsetHeight + 'px';
      }
    }
  },
  canGoNext: function (opts){
    var canGo = true;
    if (!opts.infinite) {
      if (opts.centerMode) {
        // check if current slide is last slide
        if (opts.currentSlide >= (opts.slideCount - 1)) {
          canGo = false;
        }
      } else {
        // check if all slides are shown in slider
        if (opts.slideCount <= opts.slidesToShow ||
          opts.currentSlide >= (opts.slideCount - opts.slidesToShow)) {
          canGo = false;
        }
      }
    }
    return canGo;
  },
  slideHandler: function (index) {
    // Functionality of animateSlide and postSlide is merged into this function
    // console.log('slideHandler', index);
    var targetSlide, currentSlide;
    var targetLeft, currentLeft;
    var callback;

    if (this.props.waitForAnimate && this.state.animating) {
      return;
    }

    if (this.props.fade) {
      currentSlide = this.state.currentSlide;

      // Don't change slide if it's not infite and current slide is the first or last slide.
      if(this.props.infinite === false &&
        (index < 0 || index >= this.state.slideCount)) {
        return;
      }

      //  Shifting targetSlide back into the range
      if (index < 0) {
        targetSlide = index + this.state.slideCount;
      } else if (index >= this.state.slideCount) {
        targetSlide = index - this.state.slideCount;
      } else {
        targetSlide = index;
      }

      if (this.props.lazyLoad && this.state.lazyLoadedList.indexOf(targetSlide) < 0) {
        this.setState({
          lazyLoadedList: this.state.lazyLoadedList.concat(targetSlide)
        });
      }

      callback = () => {
        this.setState({
          animating: false
        });
        if (this.props.afterChange) {
          this.props.afterChange(targetSlide);
        }
        delete this.animationEndCallback;
      };

      this.setState({
        animating: true,
        currentSlide: targetSlide
      }, function () {
        this.animationEndCallback = setTimeout(callback, this.props.speed);
      });

      if (this.props.beforeChange) {
        this.props.beforeChange(this.state.currentSlide, targetSlide);
      }

      this.autoPlay();
      return;
    }

    targetSlide = index;
    if (targetSlide < 0) {
      if(this.props.infinite === false) {
        currentSlide = 0;
      } else if (this.state.slideCount % this.props.slidesToScroll !== 0) {
        currentSlide = this.state.slideCount - (this.state.slideCount % this.props.slidesToScroll);
      } else {
        currentSlide = this.state.slideCount + targetSlide;
      }
    } else if (targetSlide >= this.state.slideCount) {
      if(this.props.infinite === false) {
        currentSlide = this.state.slideCount - this.props.slidesToShow;
      } else if (this.state.slideCount % this.props.slidesToScroll !== 0) {
        currentSlide = 0;
      } else {
        currentSlide = targetSlide - this.state.slideCount;
      }
    } else {
      currentSlide = targetSlide;
    }

    targetLeft = getTrackLeft(assign({
      slideIndex: targetSlide,
      trackRef: this.track
    }, this.props, this.state));

    currentLeft = getTrackLeft(assign({
      slideIndex: currentSlide,
      trackRef: this.track
    }, this.props, this.state));

    if (this.props.infinite === false) {
      targetLeft = currentLeft;
    }

    if (this.props.beforeChange) {
      this.props.beforeChange(this.state.currentSlide, currentSlide);
    }

    if (this.props.lazyLoad) {
      var loaded = true;
      var slidesToLoad = [];
      for (var i = targetSlide; i < targetSlide + this.props.slidesToShow; i++ ) {
        loaded = loaded && (this.state.lazyLoadedList.indexOf(i) >= 0);
        if (!loaded) {
          slidesToLoad.push(i);
        }
      }
      if (!loaded) {
        this.setState({
          lazyLoadedList: this.state.lazyLoadedList.concat(slidesToLoad)
        });
      }
    }

    // Slide Transition happens here.
    // animated transition happens to target Slide and
    // non - animated transition happens to current Slide
    // If CSS transitions are false, directly go the current slide.

    if (this.props.useCSS === false) {

      this.setState({
        currentSlide: currentSlide,
        trackStyle: getTrackCSS(assign({left: currentLeft}, this.props, this.state))
      }, function () {
        if (this.props.afterChange) {
          this.props.afterChange(currentSlide);
        }
      });

    } else {

      var nextStateChanges = {
        animating: false,
        currentSlide: currentSlide,
        trackStyle: getTrackCSS(assign({left: currentLeft}, this.props, this.state)),
        swipeLeft: null
      };

      callback = () => {
        this.setState(nextStateChanges);
        if (this.props.afterChange) {
          this.props.afterChange(currentSlide);
        }
        delete this.animationEndCallback;
      };

      this.setState({
        animating: true,
        currentSlide: currentSlide,
        trackStyle: getTrackAnimateCSS(assign({left: targetLeft}, this.props, this.state))
      }, function () {
        this.animationEndCallback = setTimeout(callback, this.props.speed);
      });

    }

    this.autoPlay();
  },
  swipeDirection: function (touchObject) {
    var xDist, yDist, r, swipeAngle;

    xDist = touchObject.startX - touchObject.curX;
    yDist = touchObject.startY - touchObject.curY;
    r = Math.atan2(yDist, xDist);

    swipeAngle = Math.round(r * 180 / Math.PI);
    if (swipeAngle < 0) {
        swipeAngle = 360 - Math.abs(swipeAngle);
    }
    if ((swipeAngle <= 45) && (swipeAngle >= 0) || (swipeAngle <= 360) && (swipeAngle >= 315)) {
        return (this.props.rtl === false ? 'left' : 'right');
    }
    if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
        return (this.props.rtl === false ? 'right' : 'left');
    }
    if (this.props.verticalSwiping === true) {
      if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
        return 'down';
      } else {
        return 'up';
      }
    }

    return 'vertical';
  },
  play: function(){
    var nextIndex;

    if (!this.state.mounted) {
      return false
    }

    if (this.props.rtl) {
      nextIndex = this.state.currentSlide - this.props.slidesToScroll;
    } else {
      if (this.canGoNext(Object.assign({}, this.props,this.state))) {
        nextIndex = this.state.currentSlide + this.props.slidesToScroll;
      } else {
        return false;
      }
    }

    this.slideHandler(nextIndex);
  },
  autoPlay: function () {
    if (this.state.autoPlayTimer) {
      clearTimeout(this.state.autoPlayTimer);
    }
    if (this.props.autoplay) {
      this.setState({
        autoPlayTimer: setTimeout(this.play, this.props.autoplaySpeed)
      });
    }
  },
  pause: function () {
    if (this.state.autoPlayTimer) {
      clearTimeout(this.state.autoPlayTimer);
      this.setState({
        autoPlayTimer: null
      });
    }
  }
};

export default helpers;
<|endoftext|>


<commit_before>describe("Longrun", function(){

longrun.should.be.ok;

describe("register", function(){

it("should kinda work", function () {
// longrun.register

longrun.register.should.be.ok;
longrun.register("test", "succ", "fail", "poll");
longrun.register("again", "ok", "bad", "poke");
longrun._names.should.eql(["test", "again"]);
longrun._success_functions.should.eql({"test": "succ", "again": "ok"});
longrun._failure_functions.should.eql({"test": "fail", "again": "bad"});
longrun._poll_functions.should.eql({"again": "poke", "test": "poll"});
})
})

// longrun._nuke_state

describe("nuke", function(){

it("should kinda work", function () {
longrun._nuke_state();
longrun.register.should.be.ok;
longrun._names.should.be.empty;
longrun._success_functions.should.be.empty;
longrun._failure_functions.should.be.empty;
longrun._poll_functions.should.be.empty;
})
})

describe("get_state", function(){

it("should kinda work", function () {
// longrun.get_state
longrun._invoke = function (commands) {
    return JSON.stringify({"status": commands[1], "msg": commands[1]})
    // override _invoke for testing
}

var never_run = function(msg) {
    console.log("never_run: "+msg)
    never_run.should.not.be.ok;  // you should never run this function
}

var collect_done = []

done = function(msg) {
    collect_done.push(msg)
}

var fail = done;
var poll = done;
die = done;

longrun.register('success', done, never_run, never_run);
longrun.register('failure', never_run, fail, never_run);
longrun.register('running', never_run, never_run, poll);
longrun.register('killed', never_run, die, never_run);

longrun.get_state()
collect_done.should.be.eql(['success', 'failure', 'running', 'killed'])
})})
})
<commit_msg>reset between tests<commit_after>beforeEach(function(){
    console.log("nuke!")
    longrun._nuke_state()
})

describe("Longrun", function(){
  longrun.should.be.ok;

  describe("register", function(){
    it("has populated data structures correctly", function () {
      longrun.register("test", "succ", "fail", "poll");
      longrun.register("again", "ok", "bad", "poke");
      longrun.register.should.be.ok;
      longrun._names.should.eql(["test", "again"]);
      longrun._success_functions.should.eql({"test": "succ", "again": "ok"});
      longrun._failure_functions.should.eql({"test": "fail", "again": "bad"});
      longrun._poll_functions.should.eql({"again": "poke", "test": "poll"});
    })
  })

  describe("nuke", function(){
    it("destroys data structures", function () {
      longrun._nuke_state();
      longrun.register.should.be.ok;
      longrun._names.should.be.empty;
      longrun._success_functions.should.be.empty;
      longrun._failure_functions.should.be.empty;
      longrun._poll_functions.should.be.empty;
    })
  })

  describe("get_state", function(){
    it("correctly invokes commands and gets output", function () {

      var never_run = function(msg) {
	console.log("never_run: "+msg)
	never_run.should.not.be.ok;  // you should never run this function
      }

      var collect_done = []

      done = function(msg) {
	  collect_done.push(msg)
      }

      var fail = done;
      var poll = done;
      die = done;

      longrun.register('success', done, never_run, never_run);
      longrun.register('failure', never_run, fail, never_run);
      longrun.register('running', never_run, never_run, poll);
      longrun.register('killed', never_run, die, never_run);

      longrun._invoke = function (commands) {
	// override _invoke for testing
	return JSON.stringify({"status": commands[1], "msg": commands[1]})
      }

      longrun.get_state()
      collect_done.should.be.eql(['success', 'failure', 'running', 'killed'])
    })
  })
})
<|endoftext|>


<commit_before>import * as reconcile from '../reconcile.js';

describe('Merge Nodes', function() {

    it('should return no diff for equal nodes', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello world';
        var source = document.createElement('div');
        source.innerHTML = 'hello world';
        var result = reconcile.diff(source, base);
        expect(result).toEqual([]);
        expect(source.isEqualNode(base));
    });

    it('should return a text diff', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello there';
        var source = document.createElement('div');
        source.innerHTML = 'hello world';
        var result = reconcile.diff(source, base);
        expect(source.isEqualNode(base));
        expect(result.length).toEqual(1);
        expect(result[0]['action']).toEqual('replaceText');
        expect(result[0]['_deleted']).toEqual('hello there');
    });

    it('should return a new child diff', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello there';
        var source = document.createElement('div');
        source.innerHTML = 'hello there';
        var result = reconcile.diff(source, base);
        expect(source.isEqualNode(base));
        expect(result.length).toEqual(2);
        expect(result[0]['action']).toEqual('insertChildElement');
        expect(result[0]['element']['tagName']).toEqual('I');
        expect(result[1]['action']).toEqual('removeChildElement');
        expect(result[1]['element']['tagName']).toEqual('B');
    });

    it('should be able to resolve three way merges', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello world';
        var source = document.createElement('div');
        source.innerHTML = 'hello world. And something else';
        var theirs = document.createElement('div');
        theirs.innerHTML = 'more content hello austin';
        var theirMerge = reconcile.diff(theirs, base.cloneNode(true));
        var myMerge = reconcile.diff(source, base.cloneNode(true));
        var changes = reconcile.patch(theirMerge, myMerge);
        var result = reconcile.apply(changes, base);
        expect(result.unapplied).toEqual([]);
        expect(result.conflicts.length).toEqual(2);
        expect(base.innerHTML).toEqual('more content hello <theirs>austin</theirs><mine>. And something </mine>else');
    });

    it('should be able to resolve more complex three way merges', function() {
        var base = document.createElement('div');
        base.innerHTML = '

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

';
        var source = document.createElement('div');
        source.innerHTML = '

tester

asdf

asdf

asdfasdf

inserted here

asdf

and some more content here!!!

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

';
        var theirs = document.createElement('div');
        theirs.innerHTML = '

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

and some more content here!!!sadkfjaslkdjflsa

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

';
        var theirMerge = reconcile.diff(theirs, base.cloneNode(true));
        var myMerge = reconcile.diff(source, base.cloneNode(true));
        var changes = reconcile.patch(theirMerge, myMerge);
        var result = reconcile.apply(changes, base);
        expect(result.unapplied).toEqual([]);
        expect(result.conflicts.length).toEqual(0);
        expect(base.innerHTML).toEqual('

tester

asdf

asdf

asdfasdf

inserted here

asdf

and some more content here!!!

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

and some more content here!!!sadkfjaslkdjflsa

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

');
    });

});
<commit_msg>Test move and replace merge<commit_after>import * as reconcile from '../reconcile.js';

describe('Merge Nodes', function() {

    it('should return no diff for equal nodes', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello world';
        var source = document.createElement('div');
        source.innerHTML = 'hello world';
        var result = reconcile.diff(source, base);
        expect(result).toEqual([]);
        expect(source.isEqualNode(base));
    });

    it('should return a text diff', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello there';
        var source = document.createElement('div');
        source.innerHTML = 'hello world';
        var result = reconcile.diff(source, base);
        expect(source.isEqualNode(base));
        expect(result.length).toEqual(1);
        expect(result[0]['action']).toEqual('replaceText');
        expect(result[0]['_deleted']).toEqual('hello there');
    });

    it('should return a new child diff', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello there';
        var source = document.createElement('div');
        source.innerHTML = 'hello there';
        var result = reconcile.diff(source, base);
        expect(source.isEqualNode(base));
        expect(result.length).toEqual(2);
        expect(result[0]['action']).toEqual('insertChildElement');
        expect(result[0]['element']['tagName']).toEqual('I');
        expect(result[1]['action']).toEqual('removeChildElement');
        expect(result[1]['element']['tagName']).toEqual('B');
    });

    it('should be able to resolve three way merges', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello world';
        var source = document.createElement('div');
        source.innerHTML = 'hello world. And something else';
        var theirs = document.createElement('div');
        theirs.innerHTML = 'more content hello austin';
        var theirMerge = reconcile.diff(theirs, base.cloneNode(true));
        var myMerge = reconcile.diff(source, base.cloneNode(true));
        var changes = reconcile.patch(theirMerge, myMerge);
        var result = reconcile.apply(changes, base);
        expect(result.unapplied).toEqual([]);
        expect(result.conflicts.length).toEqual(2);
        expect(base.innerHTML).toEqual('more content hello <theirs>austin</theirs><mine>. And something </mine>else');
    });

    it('should be able to resolve more complex three way merges', function() {
        var base = document.createElement('div');
        base.innerHTML = '

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

';
        var source = document.createElement('div');
        source.innerHTML = '

tester

asdf

asdf

asdfasdf

inserted here

asdf

and some more content here!!!

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

';
        var theirs = document.createElement('div');
        theirs.innerHTML = '

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

and some more content here!!!sadkfjaslkdjflsa

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

';
        var theirMerge = reconcile.diff(theirs, base.cloneNode(true));
        var myMerge = reconcile.diff(source, base.cloneNode(true));
        var changes = reconcile.patch(theirMerge, myMerge);
        var result = reconcile.apply(changes, base);
        expect(result.unapplied).toEqual([]);
        expect(result.conflicts.length).toEqual(0);
        expect(base.innerHTML).toEqual('

tester

asdf

asdf

asdfasdf

inserted here

asdf

and some more content here!!!

tester

asdf

asdf

asdfasdf

asdf

fasdjflksadf

and some more content here!!!sadkfjaslkdjflsa

tester

asdf

asdf

asdfasdf

asdf

tester

asdf

asdf

asdfasdf

asdf

');
    });

    it('should be able to perform move and replace text operationally', function() {
        var base = document.createElement('div');
        base.innerHTML = 'hello world';
        var source = document.createElement('div');
        source.innerHTML = 'hello universe';
        var theirs = document.createElement('div');
        theirs.innerHTML = 'world hello austin';
        var theirMerge = reconcile.diff(theirs, base.cloneNode(true));
        var myMerge = reconcile.diff(source, base.cloneNode(true));
        var changes = reconcile.patch(theirMerge, myMerge);
        var result = reconcile.apply(changes, base);
        expect(result.unapplied).toEqual([]);
        expect(result.conflicts.length).toEqual(0);
        expect(base.innerHTML).toEqual('universe hello austin');
    });

});
<|endoftext|>


<commit_before>+(function (factory) {
  if (typeof exports === 'undefined') {
    factory(webduino || {});
  } else {
    module.exports = factory;
  }
}(function (scope) {
  'use strict';

  var Pin = scope.Pin,
    Module = scope.Module,
    BoardEvent = scope.BoardEvent,
    proto;

  function Max7219(board, din, cs, clk) {
    Module.call(this);
    this._board = board;
    this._din = din;
    this._cs = cs;
    this._clk = clk;
    this._intensity = 0;
    this._data = 'ffffffffffffffff';

    this._board.on(BoardEvent.BEFOREDISCONNECT, this.animateStop.bind(this));
    this._board.on(BoardEvent.ERROR, this.animateStop.bind(this));
    this._board.send([0xf0, 4, 8, 0, din.number, cs.number, clk.number, 0xf7]);
  }

  Max7219.prototype = proto = Object.create(Module.prototype, {
    constructor: {
      value: Max7219
    },
    intensity: {
      get: function () {
        return this._intensity;
      },
      set: function (val) {
        if (val >= 0 && val <= 15) {
          this._board.send([0xf0, 4, 8, 3, val, 0xf7]);
          this._intensity = val;
        }
      }
    }
  });

  proto.on = function (data) {
    if (data) {
      this._data = data;
    } else {
      data = this._data;
    }

    if (!data) {
      return false;
    }

    var sendData = [0xf0, 4, 8, 1];
    var i = 0;
    var len = data.length;

    for (; i < len; i++) {
      sendData.push(data.charCodeAt(i));
    }

    sendData.push(0xf7);
    this._board.send(sendData);
  };

  proto.off = function () {
    this._board.send([0xf0, 4, 8, 2, 0xf7]);
  };

  proto.animate = function(data, times, duration, callback) {
    var p = 0;

    if (typeof arguments[arguments.length - 1] === 'function') {
      callback = arguments[arguments.length - 1];
    } else {
      callback = function() {};
    }

    var run = function() {
      this.on(data[p++ % data.length]);
      this._timer = setTimeout(run, times);
    }.bind(this);

    var stop = function() {
      clearTimeout(this._timer);
      callback();
    }.bind(this);

    if (times && times > 0) {
      run();
    }

    if (duration && duration > 0) {
      this._timerDuration = setTimeout(stop, duration);
    }
  };

  proto.animateStop = function() {
    clearTimeout(this._timer);
    clearTimeout(this._timerDuration);
  };

  scope.module.Max7219 = Max7219;
}));<commit_msg>Finish API doc of Max7219.js<commit_after>+(function (factory) {
  if (typeof exports === 'undefined') {
    factory(webduino || {});
  } else {
    module.exports = factory;
  }
}(function (scope) {
  'use strict';

  var Pin = scope.Pin,
    Module = scope.Module,
    BoardEvent = scope.BoardEvent,
    proto;

  /**
   * The Max7219 Class.
   *
   * @namespace webduino.module
   * @class Max7219
   * @constructor
   * @param {webduino.Board} board The board that the Max7219 is attached to.
   * @param {Integer} din Pin number of DIn (Data In).
   * @param {Integer} cs Pin number of LOAD/CS.
   * @param {Integer} clk Pin number of CLK.
   * @extends {webduino.Module}
   */
  function Max7219(board, din, cs, clk) {
    Module.call(this);
    this._board = board;
    this._din = din;
    this._cs = cs;
    this._clk = clk;
    this._intensity = 0;
    this._data = 'ffffffffffffffff';

    this._board.on(BoardEvent.BEFOREDISCONNECT, this.animateStop.bind(this));
    this._board.on(BoardEvent.ERROR, this.animateStop.bind(this));
    this._board.send([0xf0, 4, 8, 0, din.number, cs.number, clk.number, 0xf7]);
  }

  Max7219.prototype = proto = Object.create(Module.prototype, {
    constructor: {
      value: Max7219
    },

    /**
     * The intensity indicating brightness of Max7219.
     *
     * @attribute intensity
     * @type {Integer} Value of brightness (0~15).
     */
    intensity: {
      get: function () {
        return this._intensity;
      },
      set: function (val) {
        if (val >= 0 && val <= 15) {
          this._board.send([0xf0, 4, 8, 3, val, 0xf7]);
          this._intensity = val;
        }
      }
    }
  });

  /**
   * Show pattern LED matrix.
   *
   * @method on
   * @param {String} data Pattern to display, e.g. `"0102040810204080"`.
   */
  proto.on = function (data) {
    if (data) {
      this._data = data;
    } else {
      data = this._data;
    }

    if (!data) {
      return false;
    }

    var sendData = [0xf0, 4, 8, 1];
    var i = 0;
    var len = data.length;

    for (; i < len; i++) {
      sendData.push(data.charCodeAt(i));
    }

    sendData.push(0xf7);
    this._board.send(sendData);
  };

  /**
   * Clear pattern on LED matrix.
   *
   * @method off
   */
  proto.off = function () {
    this._board.send([0xf0, 4, 8, 2, 0xf7]);
  };

  /**
   * Display animated pattern.
   *
   * @method animate
   * @param {Array} data Array of patterns, e.g. `["080c0effff0e0c08", "0808080808080800", "0102040810204000"]`.
   * @param {Integer} times Delay time (in microsecond) between patterns.
   * @param {Integer} duration Duration of animation.
   * @param {Function} callback Callback after animation.
   */
  proto.animate = function(data, times, duration, callback) {
    var p = 0;

    if (typeof arguments[arguments.length - 1] === 'function') {
      callback = arguments[arguments.length - 1];
    } else {
      callback = function() {};
    }

    var run = function() {
      this.on(data[p++ % data.length]);
      this._timer = setTimeout(run, times);
    }.bind(this);

    var stop = function() {
      clearTimeout(this._timer);
      callback();
    }.bind(this);

    if (times && times > 0) {
      run();
    }

    if (duration && duration > 0) {
      this._timerDuration = setTimeout(stop, duration);
    }
  };

  /**
   * Stop displaying animated pattern.
   *
   * @method animateStop
   */
  proto.animateStop = function() {
    clearTimeout(this._timer);
    clearTimeout(this._timerDuration);
  };

  scope.module.Max7219 = Max7219;
}));<|endoftext|>


<commit_before>var fest = require('../lib/fest'),
    vows = require('vows'),
    events = require('events'),
    assert = require('assert');

function transform(file, json,  promise, strict, options){
    var template = (new Function('return ' + fest.compile(file, strict, options)))();
    setTimeout(function(){promise.emit('success', template(json));}, 0);
}

vows.describe('Fast tests').addBatch({
    'doctype':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/doctype.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '<!DOCTYPE html>');
        }
    },
    'text':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/text.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '  ');
        }
    },
    'shorttag':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/shorttag.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '<meta/>');
        }
    },
    'comment':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/comment.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '');
        }
    },
    'value':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/value.xml', {"value":"value"}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, 'value');
        }
    },
    'setparams': {
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/setparams.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '|text1||text2||text3||text4|');
        }
    },
    'attribute': {
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/attribute.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '<input/>
foobar

foo
');
        }
    },
    'document.write': {
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/document.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, 'foobarbar');
        }
    },
    'first_attributes': {
      topic:function(){
        var promise = new(events.EventEmitter);
        transform('tests/templates/attributes.xml', {}, promise);
        return promise;
      },
      'result':function(result) {
        assert.equal(result, '<input/>texttext<button name="btn"></button>');
      }
    }
}).run();
<commit_msg>first fest:attributes check<commit_after>var fest = require('../lib/fest'),
    vows = require('vows'),
    events = require('events'),
    assert = require('assert');

function transform(file, json,  promise, strict, options){
    var template = (new Function('return ' + fest.compile(file, strict, options)))();
    setTimeout(function(){promise.emit('success', template(json));}, 0);
}

vows.describe('Fast tests').addBatch({
    'doctype':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/doctype.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '<!DOCTYPE html>');
        }
    },
    'text':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/text.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '  ');
        }
    },
    'shorttag':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/shorttag.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '<meta/>');
        }
    },
    'comment':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/comment.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '');
        }
    },
    'value':{
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/value.xml', {"value":"value"}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, 'value');
        }
    },
    'setparams': {
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/setparams.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '|text1||text2||text3||text4|');
        }
    },
    'attribute': {
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/attribute.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, '<input/>
foobar

foo
');
        }
    },
    'document.write': {
        topic:function(){
            var promise = new(events.EventEmitter);
            transform('tests/templates/document.xml', {}, promise);
            return promise;
        },
        'result':function(result){
            assert.equal(result, 'foobarbar');
        }
    },
    'first attributes': {
      topic:function(){
        var promise = new(events.EventEmitter);
        transform('tests/templates/first_attributes.xml', {}, promise);
        return promise;
      },
      'result':function(result) {
        assert.equal(result, '<input/>texttext<button name="btn"></button>');
      }
    }
}).run();
<|endoftext|>


<commit_before>(function(hello) {

    hello.init({

        joinme: {

            name: 'join.me',

            oauth: {
                version: 2,
                auth: 'https://secure.join.me/api/public/v1/auth/oauth2',
                grant: 'https://secure.join.me/api/public/v1/auth/oauth2'
            },

            refresh: false,

            scope: {
                basic: '',
                user: 'user_info',
                scheduler: 'scheduler',
                start: 'start_meeting'
            },

            scope_delim: ' ',

            login: function(p) {
                p.options.window_width = 400;
                p.options.window_height = 700;
            },

            base: 'https://api.join.me/v1/',

            get: {
                "me": "user",
                "meetings": "meetings",
                "meetings/info": "meetings/@{id}"
            },

            post: {
                "meetings/start/adhoc": function(p, callback) {
                    callback('meetings/start');
                },

                "meetings/start/scheduled": function(p, callback) {
                    var meetingId = p.data.meetingId;
                    p.data = {};
                    callback('meetings/' + meetingId + '/start');
                },

                "meetings/schedule": function(p, callback) {
                    callback('meetings');
                }
            },

            patch: {
                "meetings/update": function(p, callback) {
                    callback('meetings/' + p.data.meetingId);
                }
            },

            del: {
                "meetings/delete": "meetings/@{id}"
            },

            wrap: {
                me: function(o, headers) {
                    formatError(o, headers);

                    if (!o.email) {
                        return o;
                    }

                    o.name = o.fullName;
                    o.first_name = o.name.split(' ')[0];
                    o.last_name = o.name.split(' ')[1];
                    o.id = o.email;

                    return o;
                },

                'default': function(o, headers) {
                    formatError(o, headers);

                    return o;
                }
            },

            xhr: formatRequest

        }
    });

    function formatError(o, headers) {
        var errorCode, message, details;

        if (o && ('Message' in o)) {
            message = o.Message;
            delete o.Message;

            if ('ErrorCode' in o) {
                errorCode = o.ErrorCode;
                delete o.ErrorCode;
            }
            else {
                errorCode = getErrorCode(headers);
            }

            o.error = {
                code: errorCode,
                message: message,
                details: o
            };
        }

        return o;
    }

    function formatRequest(p, qs) {
        // move the access token from the request body to the request header
        var token = qs.access_token;
        delete qs.access_token;
        p.headers = {
            "Authorization": "Bearer " + token
        };

        // format non-get requests to indicate json body
        if (p.method !== 'get' && p.data) {
            p.headers['Content-Type'] = 'application/json';
            if (typeof (p.data) === 'object') {
                p.data = JSON.stringify(p.data);
            }
        }

        if (p.method === 'put') {
            p.method = 'patch';
        }

        return true;
    }

    function getErrorCode(headers) {
        switch (headers.statusCode) {
            case 400:
                return 'invalid_request';
            case 403:
                return 'stale_token';
            case 401:
                return 'invalid_token';
            case 500:
                return 'server_error';
            default:
                return 'server_error';
        }
    }

}(hello));
<commit_msg>manual formatting using jscs rules<commit_after>(function(hello) {

	hello.init({

		joinme: {

			name: 'join.me',

			oauth: {
				version: 2,
				auth: 'https://secure.join.me/api/public/v1/auth/oauth2',
				grant: 'https://secure.join.me/api/public/v1/auth/oauth2'
			},

			refresh: false,

			scope: {
				basic: '',
				user: 'user_info',
				scheduler: 'scheduler',
				start: 'start_meeting'
			},

			scope_delim: ' ',

			login: function(p) {
				p.options.window_width = 400;
				p.options.window_height = 700;
			},

			base: 'https://api.join.me/v1/',

			get: {
				me: 'user',
				meetings: 'meetings',
				'meetings/info': 'meetings/@{id}'
			},

			post: {
				'meetings/start/adhoc': function(p, callback) {
					callback('meetings/start');
				},

				'meetings/start/scheduled': function(p, callback) {
					var meetingId = p.data.meetingId;
					p.data = {};
					callback('meetings/' + meetingId + '/start');
				},

				'meetings/schedule': function(p, callback) {
					callback('meetings');
				}
			},

			patch: {
				'meetings/update': function(p, callback) {
					callback('meetings/' + p.data.meetingId);
				}
			},

			del: {
				'meetings/delete': 'meetings/@{id}'
			},

			wrap: {
				me: function(o, headers) {
					formatError(o, headers);

					if (!o.email) {
						return o;
					}

					o.name = o.fullName;
					o.first_name = o.name.split(' ')[0];
					o.last_name = o.name.split(' ')[1];
					o.id = o.email;

					return o;
				},

				'default': function(o, headers) {
					formatError(o, headers);

					return o;
				}
			},

			xhr: formatRequest

		}
	});

	function formatError(o, headers) {
		var errorCode;
		var message;
		var details;

		if (o && ('Message' in o)) {
			message = o.Message;
			delete o.Message;

			if ('ErrorCode' in o) {
				errorCode = o.ErrorCode;
				delete o.ErrorCode;
			}
			else {
				errorCode = getErrorCode(headers);
			}

			o.error = {
				code: errorCode,
				message: message,
				details: o
			};
		}

		return o;
	}

	function formatRequest(p, qs) {
		// Move the access token from the request body to the request header
		var token = qs.access_token;
		delete qs.access_token;
		p.headers.Authorization = 'Bearer ' + token;

		// Format non-get requests to indicate json body
		if (p.method !== 'get' && p.data) {
			p.headers['Content-Type'] = 'application/json';
			if (typeof (p.data) === 'object') {
				p.data = JSON.stringify(p.data);
			}
		}

		if (p.method === 'put') {
			p.method = 'patch';
		}

		return true;
	}

	function getErrorCode(headers) {
		switch (headers.statusCode) {
			case 400:
				return 'invalid_request';
			case 403:
				return 'stale_token';
			case 401:
				return 'invalid_token';
			case 500:
				return 'server_error';
			default:
				return 'server_error';
		}
	}

}(hello));
<|endoftext|>


<commit_before>var events = require('events'),
  util = require('util'),
  mysql = require('mysql'),
  _ = require('lodash'),
  defaultCallback = require('../utils/defaultCallback'),
  Collection = require('./Collection');

/**
 * Constructs a new MySQL database.
 * @param {Object} connectionProperties connection properties.
 * @see https://github.com/felixge/node-mysql#connection-options for a list of connection properties to use.
 * @constructor
 */
function Database(connectionProperties) {
  this.connectionProperties = connectionProperties;
  this.tables = {};
  this.isConnected = false;

  events.EventEmitter.call(this);
  this.setMaxListeners(99);
}

// Database extends the EventEmitter class
util.inherits(Database, events.EventEmitter);

/**
 * Attempts to connect to database, using the connection properties given at construction time.
 * @param {Function} [callback] a callback function to execute when connection has been established, i.e. function (err).
 * @returns {Database} this instance, to enable method chaining.
 */
Database.prototype.connect = function (callback) {
  // handle optional "callback" param
  if (typeof callback !== 'function') {
    callback = defaultCallback;
  }

  if (!this.isConnected) {
    this._pool = mysql.createPool(this.connectionProperties);
    this.isConnected = true;

    this.emit('connect');
  }

  callback();

  return this;
};

/**
 * Gracefully closes all database connections.
 * The instance will become practically useless after calling this method, unless calling connect() again.
 * @param {Function} [callback] a callback function to execute when connection has been closed, i.e. function (err).
 * @returns {Database} this to enable method chaining.
 */
Database.prototype.disconnect = function (callback) {
  // handle optional "callback" param
  if (typeof callback !== 'function') {
    callback = defaultCallback;
  }

  if (this.isConnected) {
    this._pool.end(callback);
    this.isConnected = false;

    this.emit('disconnect');

  } else {
    callback();
  }

  return this;
};

/**
 * Runs the given SQL statement to the database.
 * @param {String} sql a parameterized SQL statement.
 * @param {Array} [params] an array of parameter values.
 * @param {Object} [options] query options, i.e. {nestTables: true} to handle overlapping column names.
 * @param {Function} [callback] a callback function, i.e. function(error, records, meta) for SELECT statements and function(error, meta) for DML statements.
 */
Database.prototype.query = function (sql, params, options, callback) {
  var type;

  // make sure "sql" parameter is valid
  type = typeof(sql);

  if (type !== 'string') {
    throw new Error('You must specify a valid SQL statement');
  }

  // make sure "params" parameter is valid
  if (!_.isArray(params)) {
    type = typeof(params);

    if (_.isPlainObject(params)) {
      options = params;
    } else if (type === 'function') {
      callback = params;
    } else if (type !== 'undefined') { // not Array, nor Object, nor Function, nor undefined
      throw new Error('Invalid query parameters - expected array, received ' + type);
    }

    params = [];
  }

  // make sure "options" parameter is valid
  if (!_.isPlainObject(options)) {
    type = typeof(options);

    if (type === 'function') {
      callback = options;
    } else if (type !== 'undefined') { // not Object, nor Function, nor undefined
      throw new Error('Invalid query options - expected object, received ' + type);
    }

    options = {};
  }

  // make sure "callback" parameter is valid
  type = typeof(callback);

  if (type !== 'function') {
    if (type === 'undefined') {
      callback = defaultCallback;
    } else {
      throw new Error('Invalid callback - expected function, received ' + type);
    }
  }

  // make sure db is connected
  if (!this.isConnected) {
    return callback(new Error('Connection is closed - did you forget to call #connect()?'));
  }

  // get an available db connection
  console.log('Attempting to get connection from pool (closed: ' + this._pool._closed + ')');
  this._pool.getConnection(function (err, connection) {
    if (err) return callback(err);

    // use the "nestTables" option Luke
    if (options.nestTables) {
      sql = {
        sql: sql,
        nestTables: options.nestTables
      };
    }

    // run Forrest, run
    connection.query(sql, params, function(error, records) {
      var meta = {};

      if (error) {
        callback(error);

      } else if (Array.isArray(records)) { // SELECT statement
        callback(null, records);

      } else { // DML statement
        meta.insertId = records.insertId;
        meta.affectedRows = records.affectedRows;

        callback(null, meta);
      }

      connection.release();
    });
  });
};

/**
 * Creates and returns a new data collection representing the designated table.
 * @param {String} table the name of an existing table in database.
 * @param {Object} [customProperties] the collection's custom properties.
 * Please note that this function will not create a new table on database.
 */
Database.prototype.extend = function (table, customProperties) {
  var collection;

  // make sure "table" parameter is valid
  if (typeof table !== 'string') {
    throw new Error('Invalid table name - expected string, received ' + typeof(table));
  }

  // create new collection
  collection = new Collection(this, table);

  // assign custom properties
  if (_.isPlainObject(customProperties)) {
    collection = _.extend(collection, customProperties);
  }

  return collection;
};

module.exports = Database;
<commit_msg>Removed debug console.log statements.<commit_after>var events = require('events'),
  util = require('util'),
  mysql = require('mysql'),
  _ = require('lodash'),
  defaultCallback = require('../utils/defaultCallback'),
  Collection = require('./Collection');

/**
 * Constructs a new MySQL database.
 * @param {Object} connectionProperties connection properties.
 * @see https://github.com/felixge/node-mysql#connection-options for a list of connection properties to use.
 * @constructor
 */
function Database(connectionProperties) {
  this.connectionProperties = connectionProperties;
  this.tables = {};
  this.isConnected = false;

  events.EventEmitter.call(this);
  this.setMaxListeners(99);
}

// Database extends the EventEmitter class
util.inherits(Database, events.EventEmitter);

/**
 * Attempts to connect to database, using the connection properties given at construction time.
 * @param {Function} [callback] a callback function to execute when connection has been established, i.e. function (err).
 * @returns {Database} this instance, to enable method chaining.
 */
Database.prototype.connect = function (callback) {
  // handle optional "callback" param
  if (typeof callback !== 'function') {
    callback = defaultCallback;
  }

  if (!this.isConnected) {
    this._pool = mysql.createPool(this.connectionProperties);
    this.isConnected = true;

    this.emit('connect');
  }

  callback();

  return this;
};

/**
 * Gracefully closes all database connections.
 * The instance will become practically useless after calling this method, unless calling connect() again.
 * @param {Function} [callback] a callback function to execute when connection has been closed, i.e. function (err).
 * @returns {Database} this to enable method chaining.
 */
Database.prototype.disconnect = function (callback) {
  // handle optional "callback" param
  if (typeof callback !== 'function') {
    callback = defaultCallback;
  }

  if (this.isConnected) {
    this._pool.end(callback);
    this.isConnected = false;

    this.emit('disconnect');

  } else {
    callback();
  }

  return this;
};

/**
 * Runs the given SQL statement to the database.
 * @param {String} sql a parameterized SQL statement.
 * @param {Array} [params] an array of parameter values.
 * @param {Object} [options] query options, i.e. {nestTables: true} to handle overlapping column names.
 * @param {Function} [callback] a callback function, i.e. function(error, records, meta) for SELECT statements and function(error, meta) for DML statements.
 */
Database.prototype.query = function (sql, params, options, callback) {
  var type;

  // make sure "sql" parameter is valid
  type = typeof(sql);

  if (type !== 'string') {
    throw new Error('You must specify a valid SQL statement');
  }

  // make sure "params" parameter is valid
  if (!_.isArray(params)) {
    type = typeof(params);

    if (_.isPlainObject(params)) {
      options = params;
    } else if (type === 'function') {
      callback = params;
    } else if (type !== 'undefined') { // not Array, nor Object, nor Function, nor undefined
      throw new Error('Invalid query parameters - expected array, received ' + type);
    }

    params = [];
  }

  // make sure "options" parameter is valid
  if (!_.isPlainObject(options)) {
    type = typeof(options);

    if (type === 'function') {
      callback = options;
    } else if (type !== 'undefined') { // not Object, nor Function, nor undefined
      throw new Error('Invalid query options - expected object, received ' + type);
    }

    options = {};
  }

  // make sure "callback" parameter is valid
  type = typeof(callback);

  if (type !== 'function') {
    if (type === 'undefined') {
      callback = defaultCallback;
    } else {
      throw new Error('Invalid callback - expected function, received ' + type);
    }
  }

  // make sure db is connected
  if (!this.isConnected) {
    return callback(new Error('Connection is closed - did you forget to call #connect()?'));
  }

  // get an available db connection
  this._pool.getConnection(function (err, connection) {
    if (err) return callback(err);

    // use the "nestTables" option Luke
    if (options.nestTables) {
      sql = {
        sql: sql,
        nestTables: options.nestTables
      };
    }

    // run Forrest, run
    connection.query(sql, params, function(error, records) {
      var meta = {};

      if (error) {
        callback(error);

      } else if (Array.isArray(records)) { // SELECT statement
        callback(null, records);

      } else { // DML statement
        meta.insertId = records.insertId;
        meta.affectedRows = records.affectedRows;

        callback(null, meta);
      }

      connection.release();
    });
  });
};

/**
 * Creates and returns a new data collection representing the designated table.
 * @param {String} table the name of an existing table in database.
 * @param {Object} [customProperties] the collection's custom properties.
 * Please note that this function will not create a new table on database.
 */
Database.prototype.extend = function (table, customProperties) {
  var collection;

  // make sure "table" parameter is valid
  if (typeof table !== 'string') {
    throw new Error('Invalid table name - expected string, received ' + typeof(table));
  }

  // create new collection
  collection = new Collection(this, table);

  // assign custom properties
  if (_.isPlainObject(customProperties)) {
    collection = _.extend(collection, customProperties);
  }

  return collection;
};

module.exports = Database;
<|endoftext|>


<commit_before>console.log("Overriding Digipost JavaScript functions");

(function() {

  "use strict";

  if (dp.url) {
    dp.url.real_normalize = dp.url.normalize;

    dp.url.normalize = function(url) {
      if (url.indexOf("blob:") === 0) {
        return url;
      }
      return dp.url.real_normalize(url);
    }
  }

  if (dp.embed) {
    dp.embed.real_html = dp.embed.html;
    dp.embed.html = function(options) {
      var options = options || {};
      options.sandbox = '';
      return dp.embed.real_html(options);
    }
  }

  if (dp.views.content) {
    dp.views.content.init_original = dp.views.content.init;

		/**
		 * Trap frontend calls to display contents. If the document is encrypted with a user key,
		 * dispatch an event to start downloading and decryption.
		 */
    dp.views.content.init = function() {
      if (!this.doc.data.userKeyEncrypted) {
        // Don't try to decrypt contents if original is not encrypted with user key. Call original content view function.
        return dp.views.content.init_original.apply(this, arguments);
      }

      var view = this;
      dp.spinner.show({ label: 'Laster ned dokument…' });
      document.addEventListener('downloaded', decrypt);
      document.addEventListener('decrypted', show);
      document.addEventListener('decryption-failed', failed);

			// Trigger the content script to start processing the encrypted document.
      document.dispatchEvent(new CustomEvent('processEncryptedDocument', {
					detail: {
						contentUri: this.doc.contentUri()
					}
			}));

      function decrypt(e) {
        document.removeEventListener('downloaded', decrypt);
        dp.spinner.hide();
        dp.spinner.show({ label: 'Dekrypterer dokument…' });
        document.dispatchEvent(new CustomEvent('decrypt', {
          detail: {
            data: e.detail.data,
            contentType: e.detail.contentType
          }
        }));
      }

			/**
			 * Show data as decrypted by the content script
			 */
      function show(data){
        dp.spinner.hide();
        document.removeEventListener('decrypted', show);
        view.doc.contentUri = function() {
          return data.detail.url;
        };
        view.imageUrl = view.doc.contentUri;
        dp.views.content.init_original.apply(view);
        dp.sizes.update($(".doc"));
        $(".meta h2 a").attr('href', data.detail.url);
        $("a[download]").attr('href', data.detail.url);
      }

      function failed(data) {
        dp.spinner.hide();
        dp.modal.show(data.detail.error);
      }
    };
  }

})();<commit_msg>Moved display functions in override script out of overridden Digipost methods context. This way we only have to add the event listeners once, avoiding the need to remove them for every decrypted document. This will reduce the probablity of multiple event listeners for the same event because we forget to remove them after having displayed a document.<commit_after>(function() {

  "use strict";

	console.log("Overriding Digipost JavaScript functions");

	/**
	 * View where we will show the document once decryption is done.
	 */
	var activeContentView;

	overrideDigipostJavascriptFunctions();

	document.addEventListener('downloaded', showDecryptionSpinner);
	document.addEventListener('decrypted', showDecryptedDocument);
	document.addEventListener('decryption-failed', showEncryptionFailedError);

	function showDecryptionSpinner(e) {
		dp.spinner.hide();
		dp.spinner.show({ label: 'Dekrypterer dokument…' });
		document.dispatchEvent(new CustomEvent('decrypt', {
			detail: {
				data: e.detail.data,
				contentType: e.detail.contentType
			}
		}));
	}

	/**
	 * Show data as decrypted by the content script
	 */
	function showDecryptedDocument(data){
		dp.spinner.hide();
		activeContentView.doc.contentUri = function() {
			return data.detail.url;
		};
		activeContentView.imageUrl = activeContentView.doc.contentUri;
		dp.views.content.init_original.apply(activeContentView);
		dp.sizes.update($(".doc"));
		$(".meta h2 a").attr('href', data.detail.url);
		$("a[download]").attr('href', data.detail.url);
	}

	function showEncryptionFailedError(data) {
		dp.spinner.hide();
		dp.modal.show(data.detail.error);
	}

	/**
	 * Override Javascript functions in Digipost frontend code to be able to hook into display logic to decrypt documents in the browser.
	 */
	function overrideDigipostJavascriptFunctions() {
		/**
		 * Prevent normalization of data URLs. These are browser generated URLs to access Javascript in-memory resources, and should never be modified.
		 */
		if (dp.url) {
			dp.url.real_normalize = dp.url.normalize;
			dp.url.normalize = function (url) {
				if (url.indexOf("blob:") === 0) {
					return url;
				}
				return dp.url.real_normalize(url);
			}
		}

		/**
		 * Override embed function to always set the sandbox attribute of the content iframe to an empty string.
		 * Empty string sandbox attribute enables all sandbox restrictions for the iframe, i.e. content is treated as NOT same origin,
		 * even though its URL is same origin as the parent page. This is important as data URLs (blobs) are same origin as the parent page.
		 */
		if (dp.embed) {
			dp.embed.real_html = dp.embed.html;
			dp.embed.html = function (options) {
				var options = options || {};
				options.sandbox = '';
				return dp.embed.real_html(options);
			}
		}

		/**
		 * Trap frontend calls to display contents. If the document is encrypted with a user key,
		 * dispatch an event to start downloading and decryption.
		 */
		if (dp.views.content) {
			dp.views.content.init_original = dp.views.content.init;
			dp.views.content.init = function () {
				if (!this.doc.data.userKeyEncrypted) {
					// Don't try to decrypt contents if original is not encrypted with user key. Call original content view function.
					return dp.views.content.init_original.apply(this, arguments);
				}
				activeContentView = this;
				dp.spinner.show({label: 'Laster ned dokument…'});
				// Trigger the content script to start processing the encrypted document.
				document.dispatchEvent(new CustomEvent('processEncryptedDocument', {
					detail: {
						contentUri: this.doc.contentUri()
					}
				}));
			};
		}
	}

})();<|endoftext|>


<commit_before>/**
 * Handles opening of and synchronization with the reveal.js
 * notes window.
 *
 * Handshake process:
 * 1. This window posts 'connect' to notes window
 *    - Includes URL of presentation to show
 * 2. Notes window responds with 'connected' when it is available
 * 3. This window proceeds to send the current presentation state
 *    to the notes window
 */
var RevealNotes = (function() {

	function openNotes( notesFilePath ) {

		if( !notesFilePath ) {
			var jsFileLocation = document.querySelector('script[src$="notes.js"]').src;  // this js file path
			jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, '');   // the js folder path
			notesFilePath = jsFileLocation + 'notes.html';
		}

		var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' );

		/**
		 * Connect to the notes window through a postmessage handshake.
		 * Using postmessage enables us to work in situations where the
		 * origins differ, such as a presentation being opened from the
		 * file system.
		 */
		function connect() {
			// Keep trying to connect until we get a 'connected' message back
			var connectInterval = setInterval( function() {
				notesPopup.postMessage( JSON.stringify( {
					namespace: 'reveal-notes',
					type: 'connect',
					url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search,
					state: Reveal.getState()
				} ), '*' );
			}, 500 );

			window.addEventListener( 'message', function( event ) {
				var data = JSON.parse( event.data );
				if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
					clearInterval( connectInterval );
					onConnected();
				}
			} );
		}

		/**
		 * Posts the current slide data to the notes window
		 */
		function post() {

			var slideElement = Reveal.getCurrentSlide(),
				notesElement = slideElement.querySelector( 'aside.notes' );

			var messageData = {
				namespace: 'reveal-notes',
				type: 'state',
				notes: '',
				markdown: false,
				whitespace: 'normal',
				state: Reveal.getState()
			};

			// Look for notes defined in a slide attribute
			if( slideElement.hasAttribute( 'data-notes' ) ) {
				messageData.notes = slideElement.getAttribute( 'data-notes' );
				messageData.whitespace = 'pre-wrap';
			}

			// Look for notes defined in an aside element
			if( notesElement ) {
				messageData.notes = notesElement.innerHTML;
				messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
			}

			notesPopup.postMessage( JSON.stringify( messageData ), '*' );

		}

		/**
		 * Called once we have established a connection to the notes
		 * window.
		 */
		function onConnected() {

			// Monitor events that trigger a change in state
			Reveal.addEventListener( 'slidechanged', post );
			Reveal.addEventListener( 'fragmentshown', post );
			Reveal.addEventListener( 'fragmenthidden', post );
			Reveal.addEventListener( 'overviewhidden', post );
			Reveal.addEventListener( 'overviewshown', post );
			Reveal.addEventListener( 'paused', post );
			Reveal.addEventListener( 'resumed', post );

			// Post the initial state
			post();

		}

		connect();

	}

	if( !/receiver/i.test( window.location.search ) ) {

		// If the there's a 'notes' query set, open directly
		if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
			openNotes();
		}

		// Open the notes when the 's' key is hit
		document.addEventListener( 'keydown', function( event ) {
			// Disregard the event if the target is editable or a
			// modifier is present
			if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;

			// Disregard the event if keyboard is disabled
			if ( Reveal.getConfig().keyboard === false ) return;

			if( event.keyCode === 83 ) {
				event.preventDefault();
				openNotes();
			}
		}, false );

		// Show our keyboard shortcut in the reveal.js help overlay
		if( window.Reveal ) Reveal.registerKeyboardShortcut( 'S', 'Speaker notes view' );

	}

	return { open: openNotes };

})();
<commit_msg>For a fragment: allow to show a separate note defined in it<commit_after>/**
 * Handles opening of and synchronization with the reveal.js
 * notes window.
 *
 * Handshake process:
 * 1. This window posts 'connect' to notes window
 *    - Includes URL of presentation to show
 * 2. Notes window responds with 'connected' when it is available
 * 3. This window proceeds to send the current presentation state
 *    to the notes window
 */
var RevealNotes = (function() {

	function openNotes( notesFilePath ) {

		if( !notesFilePath ) {
			var jsFileLocation = document.querySelector('script[src$="notes.js"]').src;  // this js file path
			jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, '');   // the js folder path
			notesFilePath = jsFileLocation + 'notes.html';
		}

		var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' );

		/**
		 * Connect to the notes window through a postmessage handshake.
		 * Using postmessage enables us to work in situations where the
		 * origins differ, such as a presentation being opened from the
		 * file system.
		 */
		function connect() {
			// Keep trying to connect until we get a 'connected' message back
			var connectInterval = setInterval( function() {
				notesPopup.postMessage( JSON.stringify( {
					namespace: 'reveal-notes',
					type: 'connect',
					url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search,
					state: Reveal.getState()
				} ), '*' );
			}, 500 );

			window.addEventListener( 'message', function( event ) {
				var data = JSON.parse( event.data );
				if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
					clearInterval( connectInterval );
					onConnected();
				}
			} );
		}

		/**
		 * Posts the current slide data to the notes window
		 */
		function post(event) {

			var slideElement = Reveal.getCurrentSlide(),
				notesElement = slideElement.querySelector( 'aside.notes' );

			var messageData = {
				namespace: 'reveal-notes',
				type: 'state',
				notes: '',
				markdown: false,
				whitespace: 'normal',
				state: Reveal.getState()
			};

			// Look for notes defined in a fragment, if it is a fragmentshown event
			if (event && event.hasOwnProperty('fragment')) {
				var innerNotes = event.fragment.querySelector( 'aside.notes' );

				if ( innerNotes) {
					notesElement = innerNotes;
				}
			}

			// Look for notes defined in a slide attribute
			if( slideElement.hasAttribute( 'data-notes' ) ) {
				messageData.notes = slideElement.getAttribute( 'data-notes' );
				messageData.whitespace = 'pre-wrap';
			}

			// Look for notes defined in an aside element
			if( notesElement ) {
				messageData.notes = notesElement.innerHTML;
				messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
			}

			notesPopup.postMessage( JSON.stringify( messageData ), '*' );

		}

		/**
		 * Called once we have established a connection to the notes
		 * window.
		 */
		function onConnected() {

			// Monitor events that trigger a change in state
			Reveal.addEventListener( 'slidechanged', post );
			Reveal.addEventListener( 'fragmentshown', post );
			Reveal.addEventListener( 'fragmenthidden', post );
			Reveal.addEventListener( 'overviewhidden', post );
			Reveal.addEventListener( 'overviewshown', post );
			Reveal.addEventListener( 'paused', post );
			Reveal.addEventListener( 'resumed', post );

			// Post the initial state
			post();

		}

		connect();

	}

	if( !/receiver/i.test( window.location.search ) ) {

		// If the there's a 'notes' query set, open directly
		if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
			openNotes();
		}

		// Open the notes when the 's' key is hit
		document.addEventListener( 'keydown', function( event ) {
			// Disregard the event if the target is editable or a
			// modifier is present
			if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;

			// Disregard the event if keyboard is disabled
			if ( Reveal.getConfig().keyboard === false ) return;

			if( event.keyCode === 83 ) {
				event.preventDefault();
				openNotes();
			}
		}, false );

		// Show our keyboard shortcut in the reveal.js help overlay
		if( window.Reveal ) Reveal.registerKeyboardShortcut( 'S', 'Speaker notes view' );

	}

	return { open: openNotes };

})();
<|endoftext|>