<commit_before>// http://www.quirksmode.org/js/keys.html
/**
 * atta(b completion)
 * usage:
 *   $(selector).atta({
 *      completions: function () { return ['Foo', 'Bar', 'Baz' ] }
 *   })
 */
function ($) {
  'use strict';
  var defaults = {
      completions: function() {
          return $("#rsvp-list a.mem-name").
              map(function (i, a) { return a.text; }).sort();
      },
      at : {
          is: function(e){
              return  String.fromCharCode(e.which || e.keyCode) === "2" && e.shiftKey
          }
          , char : '@'
      }
  };
  /**
   * options is an object which may contain one of:
   * completions - a function which returns a list of completion options
   * at - an object representing the at trigger for tab completion.
   *      this object should contain a function, 'is', which should accept a key event
   *      and return true if the key event matches the trigger
   *      and a 'char' property which represents the display of the trigger.
   */
  $.fn.atta = function(options) {
     var self = this
      , options = options || {}
      , keys = {
          'up': 38
          , 'down': 40
          , 'escape': 27
          , 'enter': 13
          , 'tab': 9
      }
      , styles = [
          '#atta-list-container { position:relative; top: 0px; left: 5px; }'
          , '#atta-list { position:relative;margin-top:18px;background:#fff;border-radius:3px;border:1px solid #ddd;box-shadow:0 0 5px rgba(0,0,0,0.1);min-width:180px;}'
          , '#atta-list ul { list-style:none;margin:0;padding:0; }'
          , '#atta-list li { padding:5px 10px;font-weight:bold;border-bottom:1px solid #eee; color:#333; }'
          , '#atta-list li.sel { background:#1DCAFF; color:#fff; }' ]
      , completions = options.completions || defaults.completions
      , at = options.at || defaults.at
      , newList = function () {
          return $("

");
      }
      , newItem = function (name, i) {
          return '
' +
              name + '
';
      }
      , key = function(e, alias) {
          return (e.which || e.keyCode) === keys[alias];
      }
      , cancelKey = function (e) { return key(e, 'escape'); }
      , acceptKey = function (e) { return key(e, 'enter') || key(e, 'tab'); }
      , upKey = function (e) { return key(e, 'up'); }
      , downKey = function (e) { return key(e, 'down'); }
      , tabKey = function (e) { return key(e, 'tab'); }
      , buildMarkup = function (cs) {
          var current = $("#atta-list-container")
          , markup = current.length > 0 && current || newList()
          , ul = markup.find('ul')
          , buff = [];
          for(var i = 0, l = cs.length;i < l;i++) {
              buff.push(newItem(cs[i], i));
          }
          ul.empty().append(buff.join(''));
          return markup;
      }
      , cancel = function() {
          $('#atta-list-container').remove();
      }
      , showCompletions = function (ta, cs) {
          var markup = buildMarkup(cs);
          $(ta).parent().append(markup);
      }
      , navigationBound = false // todo better way to detect this
      , bindNavigation = function() {
          navigationBound = true
          $(window).on('keyup', function (e) {
              var sel = $("#atta-list li.sel")
              , kids = $(sel.parent()).children()
              , cnt = kids.length
              , index = sel.length > 0 && sel.data().index || 0;
              if (cnt) {
                  if (upKey(e)) {
                      e.preventDefault();
                      sel.removeClass('sel');
                      if (index > 0) {
                          $(kids[index-1]).addClass('sel')
                      } else if (index == 0) {
                          $(kids[cnt-1]).addClass('sel')
                      }
                      return false;
                  } else if (downKey(e)) {
                      e.preventDefault();
                      sel.removeClass('sel');
                      if (index < cnt-1) {
                          $(kids[index+1]).addClass('sel')
                      } else if (index == cnt-1) {
                          $(kids[0]).addClass('sel')
                      }
                      return false;
                  }
              }
          });
      };

      // append atta styles only once
      if ($('#atta-style').length < 1) {
          $('head').append('')
      }

      // bind accept and cancelation listener
      $(window).on('keyup', function(e) {
          if (cancelKey(e)) {
              cancel();
          } else if (acceptKey(e)) {
              var container = $('#atta-list-container');
              if (container.length > 0) {
                  e.preventDefault();
                  var focused = $("*:focus");
                  console.log(focused);
                  var name = container.find('.sel').text();
                  console.log('select ' + name);
                  cancel();
                  return false;
              }
          }
      });

      // bind query listener
      return self.each(function() {
          $(this).live('keyup', function (e) {
              var el = $(e.target);
              if (at.is(e)) {
                  showCompletions(e.target, completions() || []);
                  if (!navigationBound) {
                      bindNavigation();
                  }
              } else {
                  var container = $("#atta-list-container");
                  if (container.length > 0) {
                      var txt = el.val(), query, matching;
                      if (txt.length > 0) {
                          var lastAt = txt.lastIndexOf(at.char);
                          if (lastAt != -1) {
                              query = txt.slice(lastAt + 1, txt.length);
                              matching = function(i, e) {
                                  return e.toLowerCase().indexOf(query.toLowerCase()) != -1;
                              }
                              showCompletions(el, (completions() || []).filter(matching));
                          }
                      }
                  }
              }
          });
      });
  };
)(jQuery);<commit_msg>rm key ref<commit_after>/**
 * atta(b completion)
 * usage:
 *   $(selector).atta({
 *      completions: function () { return ['Foo', 'Bar', 'Baz' ] }
 *   })
 */
function ($) {
  'use strict';
  var defaults = {
      completions: function() {
          return $("#rsvp-list a.mem-name").
              map(function (i, a) { return a.text; }).sort();
      },
      at : {
          is: function(e){
              return  String.fromCharCode(e.which || e.keyCode) === "2" && e.shiftKey
          }
          , char : '@'
      }
  };
  /**
   * options is an object which may contain one of:
   * completions - a function which returns a list of completion options
   * at - an object representing the at trigger for tab completion.
   *      this object should contain a function, 'is', which should accept a key event
   *      and return true if the key event matches the trigger
   *      and a 'char' property which represents the display of the trigger.
   */
  $.fn.atta = function(options) {
     var self = this
      , options = options || {}
      , keys = {
          'up': 38
          , 'down': 40
          , 'escape': 27
          , 'enter': 13
          , 'tab': 9
      }
      , styles = [
          '#atta-list-container { position:relative; top: 0px; left: 5px; }'
          , '#atta-list { position:relative;margin-top:18px;background:#fff;border-radius:3px;border:1px solid #ddd;box-shadow:0 0 5px rgba(0,0,0,0.1);min-width:180px;}'
          , '#atta-list ul { list-style:none;margin:0;padding:0; }'
          , '#atta-list li { padding:5px 10px;font-weight:bold;border-bottom:1px solid #eee; color:#333; }'
          , '#atta-list li.sel { background:#1DCAFF; color:#fff; }' ]
      , completions = options.completions || defaults.completions
      , at = options.at || defaults.at
      , newList = function () {
          return $("

");
      }
      , newItem = function (name, i) {
          return '
' +
              name + '
';
      }
      , key = function(e, alias) {
          return (e.which || e.keyCode) === keys[alias];
      }
      , cancelKey = function (e) { return key(e, 'escape'); }
      , acceptKey = function (e) { return key(e, 'enter') || key(e, 'tab'); }
      , upKey = function (e) { return key(e, 'up'); }
      , downKey = function (e) { return key(e, 'down'); }
      , tabKey = function (e) { return key(e, 'tab'); }
      , buildMarkup = function (cs) {
          var current = $("#atta-list-container")
          , markup = current.length > 0 && current || newList()
          , ul = markup.find('ul')
          , buff = [];
          for(var i = 0, l = cs.length;i < l;i++) {
              buff.push(newItem(cs[i], i));
          }
          ul.empty().append(buff.join(''));
          return markup;
      }
      , cancel = function() {
          $('#atta-list-container').remove();
      }
      , showCompletions = function (ta, cs) {
          var markup = buildMarkup(cs);
          $(ta).parent().append(markup);
      }
      , navigationBound = false // todo better way to detect this
      , bindNavigation = function() {
          navigationBound = true
          $(window).on('keyup', function (e) {
              var sel = $("#atta-list li.sel")
              , kids = $(sel.parent()).children()
              , cnt = kids.length
              , index = sel.length > 0 && sel.data().index || 0;
              if (cnt) {
                  if (upKey(e)) {
                      e.preventDefault();
                      sel.removeClass('sel');
                      if (index > 0) {
                          $(kids[index-1]).addClass('sel')
                      } else if (index == 0) {
                          $(kids[cnt-1]).addClass('sel')
                      }
                      return false;
                  } else if (downKey(e)) {
                      e.preventDefault();
                      sel.removeClass('sel');
                      if (index < cnt-1) {
                          $(kids[index+1]).addClass('sel')
                      } else if (index == cnt-1) {
                          $(kids[0]).addClass('sel')
                      }
                      return false;
                  }
              }
          });
      };

      // append atta styles only once
      if ($('#atta-style').length < 1) {
          $('head').append('')
      }

      // bind accept and cancelation listener
      $(window).on('keyup', function(e) {
          if (cancelKey(e)) {
              cancel();
          } else if (acceptKey(e)) {
              var container = $('#atta-list-container');
              if (container.length > 0) {
                  e.preventDefault();
                  var focused = $("*:focus");
                  console.log(focused);
                  var name = container.find('.sel').text();
                  console.log('select ' + name);
                  cancel();
                  return false;
              }
          }
      });

      // bind query listener
      return self.each(function() {
          $(this).live('keyup', function (e) {
              var el = $(e.target);
              if (at.is(e)) {
                  showCompletions(e.target, completions() || []);
                  if (!navigationBound) {
                      bindNavigation();
                  }
              } else {
                  var container = $("#atta-list-container");
                  if (container.length > 0) {
                      var txt = el.val(), query, matching;
                      if (txt.length > 0) {
                          var lastAt = txt.lastIndexOf(at.char);
                          if (lastAt != -1) {
                              query = txt.slice(lastAt + 1, txt.length);
                              matching = function(i, e) {
                                  return e.toLowerCase().indexOf(query.toLowerCase()) != -1;
                              }
                              showCompletions(el, (completions() || []).filter(matching));
                          }
                      }
                  }
              }
          });
      });
  };
)(jQuery);<|endoftext|>


<commit_before>var SCREEN_WIDTH = 0;
var SCREEN_HEIGHT = 0;
var PLAYER_RADIUS = 12;
var PLAYER_SPEED = 4;
var FRICTION = 0.8;
var LEVELS = [
  { l: 48, t: 24, r: 752, b: 576 },
  { l: 0, t: 0, r: 2000, b: 2000 }
];

var gInput = {}
var gPlayer = {}
var gScene = {}
var gAudio = {}
var gRenderer = {}

var Target = function() { return this }
var Bolt = function() { return this }
var ChannelBase = function() { return this }
var EffectChannel = function() { return this }
var MusicChannel = function() { return this }
<commit_msg>Add round function to round numbers by specified decimal place or 2 places<commit_after>var SCREEN_WIDTH = 0;
var SCREEN_HEIGHT = 0;
var PLAYER_RADIUS = 12;
var PLAYER_SPEED = 4;
var FRICTION = 0.8;
var LEVELS = [
  { l: 48, t: 24, r: 752, b: 576 },
  { l: 0, t: 0, r: 2000, b: 2000 }
];

var round = function(num, place) {
  if (isNaN(num)) return num;
  var place = place ? place : 2;
  var mod = Math.pow(10, place);
  return Math.round(num * mod) / mod;
}

var gInput = {}
var gPlayer = {}
var gScene = {}
var gAudio = {}
var gRenderer = {}

var Target = function() { return this }
var Bolt = function() { return this }
var ChannelBase = function() { return this }
var EffectChannel = function() { return this }
var MusicChannel = function() { return this }
<|endoftext|>


<commit_before>/**
 * @fileoverview
 * A special message panel group to display system exception informations.
 * @author Partridge Jiang
 */

/*
 * requires /lan/classes.js
 * requires /common/kekule.exceptions.js
 * requires /utils/kekule.utils.js
 * requires /utils/kekule.domUtils.js
 * requires /xbrowsers/kekule.x.js
 * requires /widgets/kekule.widget.base.js
 * requires /widgets/commonCtrls/kekulw.widget.msgPanels.js
 */

(function(){
"use strict";

var EU = Kekule.HtmlElementUtils;
var CNS = Kekule.Widget.HtmlClassNames;

/** @ignore */
Kekule.Widget.HtmlClassNames = Object.extend(Kekule.Widget.HtmlClassNames, {
	SYSMSGGROUP: 'K-SysMsgGroup'
});

/**
 * An message group to display special system message (mainly Kekule exceptions).
 * @class
 * @augments Kekule.Widget.MsgGroup
 */
Kekule.Widget.SysMsgGroup = Class.create(Kekule.Widget.MsgGroup,
/** @lends Kekule.Widget.SysMsgGroup# */
{
	/** @private */
	CLASS_NAME: 'Kekule.Widget.SysMsgGroup',
	/** @constructs */
	initialize: function($super, parentOrElementOrDocument)
	{
		$super(parentOrElementOrDocument);
	},
	/** @ignore */
	initPropValues: function($super)
	{
		$super();
		// default values
		this.setMaxMsgCount(6);
	},
	/** @ignore */
	doGetWidgetClassName: function($super)
	{
		return $super() + ' ' + CNS.SYSMSGGROUP;
	}
});

/**
 * Exception handler that can report exceptions and messages by widget system.
 * @class
 * @augments Kekule.ExceptionHandler
 */
Kekule.Widget.ExceptionHandler = Class.create(Kekule.ExceptionHandler,
/** @lends Kekule.Widget.ExceptionHandler# */
{
	/** @private */
	CLASS_NAME: 'Kekule.Widget.ExceptionHandler',
	/** @private */
	initProperties: function()
	{
		this.defineProp('document', {'dataType': DataType.OBJECT, 'serializable': false,
			'getter': function()
			{
				return this.getPropStoreFieldValue('document') || document;
			}
		});
		this.defineProp('sysMsgGroup', {'dataType': 'Kekule.Widget.SysMsgGroup', 'serializable': false, 'setter': null,
			'getter': function()
			{
				var result = this.getPropStoreFieldValue('sysMsgGroup');
				if (!result)
				{
					result = new Kekule.Widget.SysMsgGroup(this.getDocument());
					result.appendToElem(this.getDocument().body);
					this.setPropStoreFieldValue('sysMsgGroup', result);
				}
				return result;
			}
		});
	},

	/** @ignore */
	throwException: function($super, e, exceptionLevel)
	{
		var EL = Kekule.ExceptionLevel;
		var MT = Kekule.Widget.MsgType;
		if (!exceptionLevel)
			exceptionLevel = EL.ERROR;
		var msg;
		if (typeof(e) === 'string')
			msg = e;
		else
			msg = e.message;
		if (msg)
		{
			var msgType =
				(exceptionLevel === EL.ERROR) || !exceptionLevel? MT.ERROR:
				(exceptionLevel === EL.WARNING)? MT.WARNING:
				(exceptionLevel === EL.NOTE)? MT.INFO:
					MT.NORMAL;
			this.getSysMsgGroup().addMessage(msg, msgType);
		}
		return $super(e, exceptionLevel);
	}
});
Kekule.ClassUtils.makeSingleton(Kekule.Widget.ExceptionHandler);

// register exception handler
Kekule.X.domReady(function()
{
	Kekule.exceptionHandler = Kekule.Widget.ExceptionHandler.getInstance();
});

})();<commit_msg>Make system message widget available in web component context<commit_after>/**
 * @fileoverview
 * A special message panel group to display system exception informations.
 * @author Partridge Jiang
 */

/*
 * requires /lan/classes.js
 * requires /common/kekule.exceptions.js
 * requires /utils/kekule.utils.js
 * requires /utils/kekule.domUtils.js
 * requires /xbrowsers/kekule.x.js
 * requires /widgets/kekule.widget.base.js
 * requires /widgets/commonCtrls/kekulw.widget.msgPanels.js
 */

(function(){
"use strict";

var EU = Kekule.HtmlElementUtils;
var CNS = Kekule.Widget.HtmlClassNames;

/** @ignore */
Kekule.Widget.HtmlClassNames = Object.extend(Kekule.Widget.HtmlClassNames, {
	SYSMSGGROUP: 'K-SysMsgGroup'
});

/**
 * An message group to display special system message (mainly Kekule exceptions).
 * @class
 * @augments Kekule.Widget.MsgGroup
 */
Kekule.Widget.SysMsgGroup = Class.create(Kekule.Widget.MsgGroup,
/** @lends Kekule.Widget.SysMsgGroup# */
{
	/** @private */
	CLASS_NAME: 'Kekule.Widget.SysMsgGroup',
	/** @constructs */
	initialize: function($super, parentOrElementOrDocument)
	{
		$super(parentOrElementOrDocument);
	},
	/** @ignore */
	initPropValues: function($super)
	{
		$super();
		// default values
		this.setMaxMsgCount(6);
	},
	/** @ignore */
	doGetWidgetClassName: function($super)
	{
		return $super() + ' ' + CNS.SYSMSGGROUP;
	}
});

/**
 * Exception handler that can report exceptions and messages by widget system.
 * @class
 * @augments Kekule.ExceptionHandler
 */
Kekule.Widget.ExceptionHandler = Class.create(Kekule.ExceptionHandler,
/** @lends Kekule.Widget.ExceptionHandler# */
{
	/** @private */
	CLASS_NAME: 'Kekule.Widget.ExceptionHandler',
	/** @private */
	initProperties: function()
	{
		this.defineProp('document', {'dataType': DataType.OBJECT, 'serializable': false,
			'getter': function()
			{
				return this.getPropStoreFieldValue('document') || document;
			}
		});
		this.defineProp('sysMsgGroup', {'dataType': 'Kekule.Widget.SysMsgGroup', 'serializable': false, 'setter': null,
			'getter': function()
			{
				var result = this.getPropStoreFieldValue('sysMsgGroup');
				if (!result)
				{
					result = new Kekule.Widget.SysMsgGroup(this.getDocument());
					//result.appendToElem(this.getDocument().body);
					var GM = result.getGlobalManager();
					result.appendToElem(GM.getDefaultContextRootElem());
					this.setPropStoreFieldValue('sysMsgGroup', result);
				}
				return result;
			}
		});
	},

	/** @ignore */
	throwException: function($super, e, exceptionLevel)
	{
		var EL = Kekule.ExceptionLevel;
		var MT = Kekule.Widget.MsgType;
		if (!exceptionLevel)
			exceptionLevel = EL.ERROR;
		var msg;
		if (typeof(e) === 'string')
			msg = e;
		else
			msg = e.message;
		if (msg)
		{
			var msgType =
				(exceptionLevel === EL.ERROR) || !exceptionLevel? MT.ERROR:
				(exceptionLevel === EL.WARNING)? MT.WARNING:
				(exceptionLevel === EL.NOTE)? MT.INFO:
					MT.NORMAL;
			this.getSysMsgGroup().addMessage(msg, msgType);
		}
		return $super(e, exceptionLevel);
	}
});
Kekule.ClassUtils.makeSingleton(Kekule.Widget.ExceptionHandler);

// register exception handler
Kekule.X.domReady(function()
{
	Kekule.exceptionHandler = Kekule.Widget.ExceptionHandler.getInstance();
});

})();<|endoftext|>


<commit_before><commit_msg>add guards for command line arguments<commit_after><|endoftext|>


<commit_before>// Load all tabs
const tabs = getElementsByClassName('hero-slide-container')
const literalNumbers = ['one', 'two', 'three', 'four', 'five', 'six']

// Preload images and randomly rotate
const fadeInSlide = slideNumber => {
	// Make sure arrows are hidden
	const heroArrows = getElementByClassName('hero-arrows', 0)
	heroArrows.classList.remove('fade-slide')
	// Hero Image
	const hero = getElementByClassName('hero-slide', slideNumber)
	hero.classList.add('fade')
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + literalNumbers[i], slideNumber)
			title.classList.add('fade-slide')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => {
		const heroButton = getElementByClassName('hero-button', slideNumber)
		heroButton.classList.add('fade-slide')
	}, 800)
	// Slide in Hero Arrows
	setTimeout(() => {
		heroArrows.classList.add('fade-slide')
	}, 1100)
}

const resetSlide = slideNumber => {
	// Hide Hero Text
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + literalNumbers[i], slideNumber)
		title.classList.remove('fade-slide')
	}
	// Hide Hero Button
	const heroButton = getElementByClassName('hero-button', slideNumber)
	heroButton.classList.remove('fade-slide')
}

const getSlideNumber = () => {
	let obj
	for (let i = 0; i < tabs.length; i++) {
		if (tabs[i].classList.contains('w--tab-active')) {
			obj = i === tabs.length - 1
				? { current: i, next: 0 }
				: { current: i, next: i + 1 }
		}
	}
	return obj
}

// Begin
if (window.location.pathname === '/') {

	fadeInSlide(0)

	// Add event listener to cycle through all hero messages on arrow click
	const rightArrow = getElementByClassName('hero-arrow right', 0)
	rightArrow.addEventListener('click', () => {
			const slideNumber = getSlideNumber()
			// Deactivate current tab
			tabs[slideNumber.current].classList.remove('w--tab-active')
			// Activate new tab
			tabs[slideNumber.next].classList.add('w--tab-active')
			// Fade in new slide
			fadeInSlide(slideNumber.next)
			// Reset current slide
			resetSlide(slideNumber.current)
	})

}<commit_msg>Hero.<commit_after>// Load all tabs
const tabs = getElementsByClassName('hero-slide-container')
const literalNumbers = ['one', 'two', 'three', 'four', 'five', 'six']

// Preload images and randomly rotate
const fadeInSlide = slideNumber => {
	// Hero Image
	const hero = getElementByClassName('hero-slide', slideNumber)
	hero.classList.add('fade')
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + literalNumbers[i], slideNumber)
			title.classList.add('fade-slide')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => {
		const heroButton = getElementByClassName('hero-button', slideNumber)
		heroButton.classList.add('fade-slide')
	}, 800)
	// Slide in Hero Arrows
	setTimeout(() => {
		const heroArrows = getElementByClassName('hero-arrows', slideNumber)
		heroArrows.classList.add('fade-slide')
	}, 1100)
}

const resetSlide = slideNumber => {
	// Hide Hero Text
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + literalNumbers[i], slideNumber)
		title.classList.remove('fade-slide')
	}
	// Hide Hero Button
	const heroButton = getElementByClassName('hero-button', slideNumber)
	heroButton.classList.remove('fade-slide')
	// Hide Hero Arrows
	const heroArrows = getElementByClassName('hero-arrows', slideNumber)
	heroArrows.classList.remove('fade-slide')
}

const getSlideNumber = () => {
	let obj
	for (let i = 0; i < tabs.length; i++) {
		if (tabs[i].classList.contains('w--tab-active')) {
			obj = i === tabs.length - 1
				? { current: i, next: 0 }
				: { current: i, next: i + 1 }
		}
	}
	return obj
}

// Begin
if (window.location.pathname === '/') {

	fadeInSlide(0)

	// Add event listener to cycle through all hero messages on arrow click
	const rightArrow = getElementByClassName('hero-arrow right', 0)
	rightArrow.addEventListener('click', () => {
			const slideNumber = getSlideNumber()
			// Deactivate current tab
			tabs[slideNumber.current].classList.remove('w--tab-active')
			// Activate new tab
			tabs[slideNumber.next].classList.add('w--tab-active')
			// Fade in new slide
			fadeInSlide(slideNumber.next)
			// Reset current slide
			resetSlide(slideNumber.current)
	})

}<|endoftext|>


<commit_before>// Load all tabs
const ALL_TABS = getElementsByClassName('hero-tab')
const NUMBER_CLASS = ['one', 'two', 'three', 'four', 'five', 'six']
let ACTIVE_TAB_INDEX = 0

// Calculate Section.Hero height
const setHeroHeight = () => {
	const heroSection = getElementByClassName('section hero')
	if (
		deviceType() === 'desktop'
		|| (deviceType() === 'large tablet' && deviceOrientation() === 'landscape')
		|| deviceType() === 'tablet'
		|| deviceType() === 'mobile'
	) {
		// Set min height on mobile to 550px
		heroSection.style.height = deviceType() === 'mobile' && deviceOrientation() === 'landscape'
			? Math.max(window.innerHeight * 0.95 + 'px', '550px')
			: window.innerHeight * 0.95 + 'px'
	}
	else {
		heroSection.style.height = window.innerHeight * 0.5 + 'px'
	}
}

// Set width of boxes section for width that’s smaller than desktop yet larger than iPad portrait; not configurable in Webflow interface.
const setBoxSections = () => {
	const boxSections = getElementsByClassName('section boxes')
	const boxContainers = getElementsByClassName('box-container')
	let sectionHeight, containerWidth
	if (window.innerWidth >= 930 && window.innerWidth < 1240) {
		sectionHeight = '500px'
		containerWidth = '768px'
	}
	else {
		sectionHeight = '200px'
		containerWidth = ''
	}
	// Do this for all box section and containers on homepage
	for (let i = 0; i < boxContainers.length; i++) {
		boxSections[i].style.height = sectionHeight
		boxContainers[i].style.width = containerWidth
	}
}

// Preload images and randomly rotate
const fadeInTab = tabIndex => {
	// Make tab and clickable elements visible
	ALL_TABS[tabIndex].classList.add('display')
	const heroButton = getElementByClassName('hero-button', tabIndex)
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroButton.classList.add('display')
	heroArrows.classList.add('display')
	// Fade in image
	setTimeout(() => ALL_TABS[tabIndex].classList.add('fade'), 100)
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + NUMBER_CLASS[i], tabIndex)
			title.classList.add('fade-move')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => heroButton.classList.add('fade-move'), 800)
	// Slide in Hero Arrows
	setTimeout(() => heroArrows.classList.add('fade-move'), 1100)
}

const resetSlide = tabIndex => {
	// Hide Hero Text
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + NUMBER_CLASS[i], tabIndex)
		title.classList.remove('fade-move')
	}
	// Hide Hero Button
	const heroButton = getElementByClassName('hero-button', tabIndex)
	heroButton.classList.remove('fade-move')
	// Hide Hero Arrows
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroArrows.classList.remove('fade-move')
	// Make tab and clickable elements invisible
	ALL_TABS[tabIndex].classList.remove('display')
	heroButton.classList.remove('display')
	heroArrows.classList.remove('display')
}

const transitionTabs = ({ currentTab, nextTab }) => {
	// Fade out current tab
	ALL_TABS[currentTab].classList.remove('fade')
	// Fade in new slide
	fadeInTab(nextTab)
	// Reset current slide
	setTimeout(() => resetSlide(currentTab), 500)
}

// Begin
if (window.location.pathname === '/') {

	windowEventListener(['onload', 'orientationchange', 'resize'], () => {
		// Recalculate hero height on orientation change
		setHeroHeight()
		// As well as box section and container dimensions
		setBoxSections()
	})

	// Add event listener to cycle through all hero messages on arrow click
	const leftArrows = getElementsByClassName('arrow left')
	const rightArrows = getElementsByClassName('arrow right')
	for (let tabIndex = 0; tabIndex < rightArrows.length; tabIndex++) {
		// Cycle forward
		rightArrows[tabIndex].addEventListener('click', () => {
			ACTIVE_TAB_INDEX = tabIndex === ALL_TABS.length - 1 ? 0 : tabIndex + 1
			transitionTabs({ currentTab: tabIndex, nextTab: ACTIVE_TAB_INDEX })
			// Interrupt auto-cycling if user manually clicked arrow
			clearInterval(tabInterval)
		})
		// Cycle backward
		leftArrows[tabIndex].addEventListener('click', () => {
			ACTIVE_TAB_INDEX = tabIndex === 0 ? ALL_TABS.length - 1 : tabIndex - 1
			transitionTabs({ currentTab: tabIndex, nextTab: ACTIVE_TAB_INDEX })
			// Interrupt auto-cycling if user manually clicked arrow
			clearInterval(tabInterval)
		})
	}

	// Remove display classes on init
	ALL_TABS[0].classList.remove('fade')
	ALL_TABS[0].classList.remove('display')
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + NUMBER_CLASS[i], 0)
		title.classList.remove('fade-move')
	}
	const heroButton = getElementByClassName('hero-button', tabIndex)
	heroButton.classList.remove('fade-move')
	heroButton.classList.remove('display')
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroArrows.classList.remove('fade-move')
	heroArrows.classList.remove('display')

	// Set hero height
	setHeroHeight()
	// Fade in first slide
	fadeInTab(0)

	// Switch tabs periodically
	const tabInterval = setInterval(() => {
		const currentTab = ACTIVE_TAB_INDEX
		ACTIVE_TAB_INDEX = ACTIVE_TAB_INDEX === ALL_TABS.length - 1 ? 0 : ACTIVE_TAB_INDEX + 1
		transitionTabs({ currentTab, nextTab: ACTIVE_TAB_INDEX })
	}, 8000)

}<commit_msg>Homepage.<commit_after>// Load all tabs
const ALL_TABS = getElementsByClassName('hero-tab')
const NUMBER_CLASS = ['one', 'two', 'three', 'four', 'five', 'six']
let ACTIVE_TAB_INDEX = 0

// Calculate Section.Hero height
const setHeroHeight = () => {
	const heroSection = getElementByClassName('section hero')
	if (
		deviceType() === 'desktop'
		|| (deviceType() === 'large tablet' && deviceOrientation() === 'landscape')
		|| deviceType() === 'tablet'
		|| deviceType() === 'mobile'
	) {
		// Set min height on mobile to 550px
		heroSection.style.height = deviceType() === 'mobile' && deviceOrientation() === 'landscape'
			? Math.max(window.innerHeight * 0.95 + 'px', '550px')
			: window.innerHeight * 0.95 + 'px'
	}
	else {
		heroSection.style.height = window.innerHeight * 0.5 + 'px'
	}
}

// Set width of boxes section for width that’s smaller than desktop yet larger than iPad portrait; not configurable in Webflow interface.
const setBoxSections = () => {
	const boxSections = getElementsByClassName('section boxes')
	const boxContainers = getElementsByClassName('box-container')
	let sectionHeight, containerWidth
	if (window.innerWidth >= 930 && window.innerWidth < 1240) {
		sectionHeight = '500px'
		containerWidth = '768px'
	}
	else {
		sectionHeight = '200px'
		containerWidth = ''
	}
	// Do this for all box section and containers on homepage
	for (let i = 0; i < boxContainers.length; i++) {
		boxSections[i].style.height = sectionHeight
		boxContainers[i].style.width = containerWidth
	}
}

// Preload images and randomly rotate
const fadeInTab = tabIndex => {
	// Make tab and clickable elements visible
	ALL_TABS[tabIndex].classList.add('display')
	const heroButton = getElementByClassName('hero-button', tabIndex)
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroButton.classList.add('display')
	heroArrows.classList.add('display')
	// Fade in image
	setTimeout(() => ALL_TABS[tabIndex].classList.add('fade'), 100)
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + NUMBER_CLASS[i], tabIndex)
			title.classList.add('fade-move')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => heroButton.classList.add('fade-move'), 800)
	// Slide in Hero Arrows
	setTimeout(() => heroArrows.classList.add('fade-move'), 1100)
}

const resetSlide = tabIndex => {
	// Hide Hero Text
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + NUMBER_CLASS[i], tabIndex)
		title.classList.remove('fade-move')
	}
	// Hide Hero Button
	const heroButton = getElementByClassName('hero-button', tabIndex)
	heroButton.classList.remove('fade-move')
	// Hide Hero Arrows
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroArrows.classList.remove('fade-move')
	// Make tab and clickable elements invisible
	ALL_TABS[tabIndex].classList.remove('display')
	heroButton.classList.remove('display')
	heroArrows.classList.remove('display')
}

const transitionTabs = ({ currentTab, nextTab }) => {
	// Fade out current tab
	ALL_TABS[currentTab].classList.remove('fade')
	// Fade in new slide
	fadeInTab(nextTab)
	// Reset current slide
	setTimeout(() => resetSlide(currentTab), 500)
}

// Begin
if (window.location.pathname === '/') {

	windowEventListener(['onload', 'orientationchange', 'resize'], () => {
		// Recalculate hero height on orientation change
		setHeroHeight()
		// As well as box section and container dimensions
		setBoxSections()
	})

	// Add event listener to cycle through all hero messages on arrow click
	const leftArrows = getElementsByClassName('arrow left')
	const rightArrows = getElementsByClassName('arrow right')
	for (let tabIndex = 0; tabIndex < rightArrows.length; tabIndex++) {
		// Cycle forward
		rightArrows[tabIndex].addEventListener('click', () => {
			ACTIVE_TAB_INDEX = tabIndex === ALL_TABS.length - 1 ? 0 : tabIndex + 1
			transitionTabs({ currentTab: tabIndex, nextTab: ACTIVE_TAB_INDEX })
			// Interrupt auto-cycling if user manually clicked arrow
			clearInterval(tabInterval)
		})
		// Cycle backward
		leftArrows[tabIndex].addEventListener('click', () => {
			ACTIVE_TAB_INDEX = tabIndex === 0 ? ALL_TABS.length - 1 : tabIndex - 1
			transitionTabs({ currentTab: tabIndex, nextTab: ACTIVE_TAB_INDEX })
			// Interrupt auto-cycling if user manually clicked arrow
			clearInterval(tabInterval)
		})
	}

	// Remove display classes on init
	ALL_TABS[0].classList.remove('fade')
	ALL_TABS[0].classList.remove('display')
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + NUMBER_CLASS[i], 0)
		title.classList.remove('fade-move')
	}
	const heroButton = getElementByClassName('hero-button', 0)
	heroButton.classList.remove('fade-move')
	heroButton.classList.remove('display')
	const heroArrows = getElementByClassName('hero-arrows', 0)
	heroArrows.classList.remove('fade-move')
	heroArrows.classList.remove('display')

	// Set hero height
	setHeroHeight()
	// Fade in first slide
	fadeInTab(0)

	// Switch tabs periodically
	const tabInterval = setInterval(() => {
		const currentTab = ACTIVE_TAB_INDEX
		ACTIVE_TAB_INDEX = ACTIVE_TAB_INDEX === ALL_TABS.length - 1 ? 0 : ACTIVE_TAB_INDEX + 1
		transitionTabs({ currentTab, nextTab: ACTIVE_TAB_INDEX })
	}, 8000)

}<|endoftext|>


<commit_before>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

"use strict";

var hanson  = require('hanson');

var Subst = function() {
  var replaceParamsRE = /%\(([^\)]+)\)s/g;
  var replaceHandlers = {};

  this.registerReplaceHandler = function(keyword, handler) {
    replaceHandlers[keyword] = handler;
  };

  /**
   * Replace %(id)s in strings with values in objects(s)
   *
   * Given a string like `"Hello %(name)s from %(user.country)s"`
   * and an object like `{name:"Joe",user:{country:"USA"}}` would
   * return `"Hello Joe from USA"`.
   *
   * @param {string} str string to do replacements in
   * @param {Object|Object[]} params one or more objects.
   * @returns {string} string with replaced parts
   */
  this.replaceParams = function(str, params) {
    if (!params.length) {
      params = [params];
    }

    return str.replace(replaceParamsRE, function(match, key) {
      var colonNdx = key.indexOf(":");
      if (colonNdx >= 0) {
        try {
          var args = hanson.parse("{" + key + "}");
          var handlerName = Object.keys(args)[0];
          var handler = replaceHandlers[handlerName];
          if (handler) {
            return handler(args[handlerName], params);
          }
          console.error("unknown substition handler: " + handlerName);
        } catch (e) {
          console.error(e);
          console.error("bad substitution: %(" + key + ")s");
        }
      } else {
        // handle normal substitutions.
        var keys = key.split('.');
        for (var ii = 0; ii < params.length; ++ii) {
          var obj = params[ii];
          for (var jj = 0; jj < keys.length; ++jj) {
            var k = keys[jj];
            obj = obj[k];
            if (obj === undefined) {
              break;
            }
          }
          if (obj !== undefined) {
            return obj;
          }
        }
      }
      console.error("unknown key: " + key);
      return "%(" + key + ")s";
    });
  };
};

module.exports = Subst;

<commit_msg>change subst to have templates<commit_after>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

"use strict";

var hanson  = require('hanson');

var Subst = function() {
  var replaceParamsRE = /%\(([^\)]+)\)s/g;
  var replaceHandlers = {};

  var handleString = function(data, params) {
    return data.data;
  }.bind(this);

  var handleSubst = function(data, params) {
    var key = data.data;
    // If there's a colon it's a handler.
    var colonNdx = key.indexOf(":");
    if (colonNdx >= 0) {
      try {
        var args = hanson.parse("{" + key + "}");
        var handlerName = Object.keys(args)[0];  // there should only be one key here
        var handler = replaceHandlers[handlerName];
        if (handler) {
          return replaceParams(handler(args[handlerName], this, params), params);
        }
        console.error("unknown substition handler: " + handlerName);
      } catch (e) {
        console.error(e);
        console.error("bad substitution: %(" + key + ")s");
      }
    } else {
      // handle normal substitutions.
      var keys = key.split('.');
      for (var ii = 0; ii < params.length; ++ii) {
        var obj = params[ii];
        for (var jj = 0; jj < keys.length; ++jj) {
          var k = keys[jj];
          obj = obj[k];
          if (obj === undefined) {
            break;
          }
        }
        if (obj !== undefined) {
          return replaceParams(obj, params);
        }
      }
    }
    console.error("unknown key: " + key);
    return "%(" + key + ")s";
  }.bind(this);

  function registerReplaceHandler(keyword, handler) {
    replaceHandlers[keyword] = handler;
  };

  function Template(template) {
    this.apply = function(params) {
      params = Array.isArray(params) ? params : [params];

      var result = template.map(function(part) {
        return part.fn(part, params);
      });

      return result.join("");
    }
  }

  function createTemplate(str) {
    var template = [];
    var length = str.length;
    var depth = 0;
    var lastChar = '';
    var justEnded = false;
    var start = 0;
    var startLine = -1;
    var lineNum = 1;

    function addString(start, end) {
      template.push({ fn: handleString, data: str.substring(start, end) });
    }

    function addSubst(start, end) {
      template.push({ fn: handleSubst,  data: str.substring(start, end) });
    }

    for (var ii = 0; ii < length; ++ii) {
      var c = str[ii];
      if (c === '%') {
        if (lastChar === '%') {
          addString(start, ii);
          start = ii + 1;
          c = '';  // so lastChar will not be '%'
        }
      } else if (c === '(') {
        if (lastChar === '%') {
          if (depth === 0) {
            addString(start, ii - 1);
            start = ii + 1;
          }
          ++depth;
        }
      } else if (c === ')') {
        if (depth > 0) {
          --depth;
          if (depth < 0) {
            throw new Error("bad template at line: " + lineNum);
          }
          if (depth === 0) {
            addSubst(start, ii);
            startLine = lineNum;
            start = ii + 1;
            justEnded = true;
          }
        }
      } else if (lastChar === ')') {
        if (justEnded) {
          justEnded = false;
          template[template.length - 1].subtype = c;
          start += 1;
        }
      } else if (c === '\n') {
        ++lineNum;
      }
      lastChar = c;
    }

    if (depth) {
      throw new Error("no closing param for substitution at line: " + startLine);
    }

    addString(start, ii);
    return new Template(template);
  };

  /**
   * Replace %(id)s in strings with values in objects(s)
   *
   * Given a string like `"Hello %(name)s from %(user.country)s"`
   * and an object like `{name:"Joe",user:{country:"USA"}}` would
   * return `"Hello Joe from USA"`.
   *
   * @param {string} str string to do replacements in
   * @param {Object|Object[]} params one or more objects.
   * @returns {string} string with replaced parts
   */
  function replaceParams(str, params) {
    return createTemplate(str).apply(params);
  };

  this.replaceParams = replaceParams;
  this.createTemplate = createTemplate;
  this.registerReplaceHandler = registerReplaceHandler;
};

module.exports = Subst;

<|endoftext|>


<commit_before>// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Cursor range iterator iterates cursor of an index or an
 * object store.
 *
 * @author kyawtun@yathit.com (Kyaw Tun)
 */

goog.provide('ydn.db.query.ConjunctionIterator');
goog.require('goog.log');
goog.require('goog.functions');
goog.require('ydn.db.Cursor');
goog.require('ydn.db.Iterator');
goog.require('ydn.db.KeyRange');
goog.require('ydn.db.Where');
goog.require('ydn.db.base');
goog.require('ydn.db.core.EquiJoin');
goog.require('ydn.db.core.req.ICursor');
goog.require('ydn.debug.error.ArgumentException');

/**
 * Create an iterator object.
 * @param {!string} store store name.
 * @param {string=} opt_index store field, where key query is preformed.
 * @param {(KeyRangeJson|ydn.db.KeyRange|IDBKeyRange)=} opt_key_range key range.
 * @param {boolean=} opt_reverse reverse.
 * @param {boolean=} opt_unique unique.
 * @param {boolean=} opt_key_only true for key only iterator. Default value is
 * true if index is specified, false if not defined.
 * @param {(!Array.<string>|string)=} opt_index_key_path index key path. If
 * key path is specified, key path is used to lookup the index instead of
 * index name.
 * @constructor
 * @struct
 * @extends {ydn.db.Iterator}
 */
ydn.db.query.ConjunctionIterator = function(store, opt_index, opt_key_range,
    opt_reverse, opt_unique, opt_key_only, opt_index_key_path) {
  goog.base(this, store, opt_index, opt_key_range, opt_reverse,
      opt_unique, opt_key_only, opt_index_key_path);
};
goog.inherits(ydn.db.query.ConjunctionIterator, ydn.db.Iterator);

/**
 * @protected
 * @type {goog.debug.Logger} logger.
 */
ydn.db.query.ConjunctionIterator.prototype.logger =
    goog.log.getLogger('ydn.db.query.ConjunctionIterator');

/**
 *
 * @return {number} number of record iterated.
 */
ydn.db.query.ConjunctionIterator.prototype.count = function() {
  return this.cursor_ ? this.cursor_.getCount() : NaN;
};

/**
 * Create a new iterator with new ordering.
 * @param {string} field_name field name to order.
 * @param {IDBKey} value field value.
 * @return {!ydn.db.query.ConjunctionIterator} newly created iterator applying given
 * restriction.
 */
ydn.db.query.ConjunctionIterator.prototype.order = function(field_name, value) {
  goog.asserts.assertString(field_name, 'field name in string require but, "' +
      field_name + '" of type ' + typeof field_name + ' found.');
  goog.asserts.assert(ydn.db.Key.isValidKey(value), 'key value "' +
      ydn.json.toShortString(value) + '" is invalid');
  var key_range;
  var base = [value];
  if (this.key_range_) {
    var lower = goog.isDefAndNotNull(this.key_range_.lower) ?
        base.concat(this.key_range_.lower) : base;
    var upper = goog.isDefAndNotNull(this.key_range_.upper) ?
        base.concat(this.key_range_.upper) : base;
    key_range = new ydn.db.KeyRange(lower, upper,
        !!this.key_range_.lowerOpen, !!this.key_range_.upperOpen);
  } else {
    if (this.is_index_iterator_) {
      key_range = ydn.db.KeyRange.starts(base);
    } else {
      key_range = ydn.db.KeyRange.only(value);
    }
  }
  var index_name;
  var index_key_path;
  if (this.index_key_path_) {
    index_key_path = [field_name].concat(this.index_key_path_);
  } else if (this.is_index_iterator_) {
    index_key_path = [field_name].concat(this.index_name_);
  } else {
    index_name = field_name;
  }

  return new ydn.db.query.ConjunctionIterator(this.store_name_, index_name, key_range,
      this.isReversed(), this.isUnique(), this.is_key_iterator_,
      index_key_path);
};

/**
 * @param {ydn.db.base.Transaction} tx tx.
 * @param {string} tx_lbl tx label.
 * @param {ydn.db.core.req.IRequestExecutor} executor executor.
 * @param {ydn.db.base.QueryMethod=} opt_query query method.
 * @return {!ydn.db.Cursor} newly created cursor.
 */
ydn.db.query.ConjunctionIterator.prototype.iterate = function(tx, tx_lbl, executor,
                                             opt_query) {

  var query_mth = opt_query || ydn.db.base.QueryMethod.LIST_VALUE;
  var cursor = executor.getCursor(tx, tx_lbl, this.store_name_,
      this.index_key_path_ || this.index_name_,
      this.key_range_, this.direction_, this.is_key_iterator_, query_mth);
  var cursors = [cursor];
  for (var i = 0, n = this.joins_ ? this.joins_.length : 0; i < n; i++) {
    /**
     * @type {!ydn.db.core.EquiJoin}
     */
    var join = this.joins_[i];
    if (join.field_name && goog.isDefAndNotNull(join.value)) {
      var key_range;
      if (this.isPrimaryIterator()) {
        key_range = ydn.db.IDBKeyRange.only(join.value);
      } else {
        key_range = ydn.db.KeyRange.parseIDBKeyRange(
            ydn.db.KeyRange.starts([join.value]));
      }
      var cur = executor.getCursor(tx, tx_lbl, join.store_name,
          join.field_name, key_range,
          this.direction_, this.is_key_iterator_, query_mth);
      cursors.push(cur);
    }
  }

  var msg = '';
  if (this.cursor_) {
    msg = ' by resuming ' + this.cursor_;
  }

  this.cursor_ = new ydn.db.Cursor(cursors, this.cursor_);

  goog.log.finest(this.logger, tx_lbl + ' ' + this + ' created ' + this.cursor_ + msg);
  return this.cursor_;
};

/**
 * Modified iterator with a given restriction.
 * @param {string} field_name restriction feild name.
 * @param {IDBKey} value restriction field value.
 * @return {!ydn.db.Iterator}
 */
ydn.db.query.ConjunctionIterator.prototype.restrict = function(field_name, value) {
  goog.asserts.assertString(field_name, 'field name in string require but, "' +
      field_name + '" of type ' + typeof field_name + ' found.');
  goog.asserts.assert(ydn.db.Key.isValidKey(value), 'key value "' +
      ydn.json.toShortString(value) + '" is invalid');
  return this.join(this.store_name_, field_name, value);
};

/**
 * @type {Array.<!ydn.db.core.EquiJoin>} list of joins.
 * @protected
 */
ydn.db.query.ConjunctionIterator.prototype.joins_;

/**
 * Join operation.
 * @param {string} store_name store name to join.
 * @param {string=} opt_field_name restriction feild name.
 * @param {IDBKey=} opt_value restriction field value.
 * @return {!ydn.db.Iterator} Newly created iterator with join operation
 * applied.
 */
ydn.db.query.ConjunctionIterator.prototype.join = function(store_name, opt_field_name,
                                          opt_value) {
  var iter = new ydn.db.Iterator(this.store_name_, this.index_name_,
      this.key_range_, this.isReversed(), this.isUnique(),
      this.is_key_iterator_, this.index_key_path_);

  var join = new ydn.db.core.EquiJoin(store_name, opt_field_name,
      opt_value);

  if (this.joins_) {
    iter.joins_ = this.joins_.concat(join);
  } else {
    iter.joins_ = [join];
  }

  return iter;
};

/**
 *
 * @return {!Array.<string>} list of stores.
 */
ydn.db.query.ConjunctionIterator.prototype.stores = function() {
  var stores = [this.getStoreName()];
  if (this.joins_) {
    for (var i = 0; i < this.joins_.length; i++) {
      if (!goog.array.contains(stores, this.joins_[i].store_name)) {
        stores.push(this.joins_[i].store_name);
      }
    }
  }
  return stores;
};
<commit_msg>upgrade build stamp.<commit_after>// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Cursor range iterator iterates cursor of an index or an
 * object store.
 *
 * @author kyawtun@yathit.com (Kyaw Tun)
 */

goog.provide('ydn.db.query.ConjunctionIterator');
goog.require('goog.log');
goog.require('goog.functions');
goog.require('ydn.db.query.ConjunctionCursor');
goog.require('ydn.db.Iterator');
goog.require('ydn.db.KeyRange');
goog.require('ydn.db.Where');
goog.require('ydn.db.base');
goog.require('ydn.db.query.EquiJoin');
goog.require('ydn.db.core.req.ICursor');
goog.require('ydn.debug.error.ArgumentException');

/**
 * Create an iterator object.
 * @param {!string} store store name.
 * @param {string=} opt_index store field, where key query is preformed.
 * @param {(KeyRangeJson|ydn.db.KeyRange|IDBKeyRange)=} opt_key_range key range.
 * @param {boolean=} opt_reverse reverse.
 * @param {boolean=} opt_unique unique.
 * @param {boolean=} opt_key_only true for key only iterator. Default value is
 * true if index is specified, false if not defined.
 * @param {(!Array.<string>|string)=} opt_index_key_path index key path. If
 * key path is specified, key path is used to lookup the index instead of
 * index name.
 * @constructor
 * @struct
 * @extends {ydn.db.Iterator}
 */
ydn.db.query.ConjunctionIterator = function(store, opt_index, opt_key_range,
    opt_reverse, opt_unique, opt_key_only, opt_index_key_path) {
  goog.base(this, store, opt_index, opt_key_range, opt_reverse,
      opt_unique, opt_key_only, opt_index_key_path);
};
goog.inherits(ydn.db.query.ConjunctionIterator, ydn.db.Iterator);

/**
 * @protected
 * @type {goog.debug.Logger} logger.
 */
ydn.db.query.ConjunctionIterator.prototype.logger =
    goog.log.getLogger('ydn.db.query.ConjunctionIterator');

/**
 *
 * @return {number} number of record iterated.
 */
ydn.db.query.ConjunctionIterator.prototype.count = function() {
  return this.cursor_ ? this.cursor_.getCount() : NaN;
};

/**
 * Create a new iterator with new ordering.
 * @param {string} field_name field name to order.
 * @param {IDBKey} value field value.
 * @return {!ydn.db.query.ConjunctionIterator} newly created iterator applying given
 * restriction.
 */
ydn.db.query.ConjunctionIterator.prototype.order = function(field_name, value) {
  goog.asserts.assertString(field_name, 'field name in string require but, "' +
      field_name + '" of type ' + typeof field_name + ' found.');
  goog.asserts.assert(ydn.db.Key.isValidKey(value), 'key value "' +
      ydn.json.toShortString(value) + '" is invalid');
  var key_range;
  var base = [value];
  if (this.key_range_) {
    var lower = goog.isDefAndNotNull(this.key_range_.lower) ?
        base.concat(this.key_range_.lower) : base;
    var upper = goog.isDefAndNotNull(this.key_range_.upper) ?
        base.concat(this.key_range_.upper) : base;
    key_range = new ydn.db.KeyRange(lower, upper,
        !!this.key_range_.lowerOpen, !!this.key_range_.upperOpen);
  } else {
    if (this.is_index_iterator_) {
      key_range = ydn.db.KeyRange.starts(base);
    } else {
      key_range = ydn.db.KeyRange.only(value);
    }
  }
  var index_name;
  var index_key_path;
  if (this.index_key_path_) {
    index_key_path = [field_name].concat(this.index_key_path_);
  } else if (this.is_index_iterator_) {
    index_key_path = [field_name].concat(this.index_name_);
  } else {
    index_name = field_name;
  }

  return new ydn.db.query.ConjunctionIterator(this.store_name_, index_name, key_range,
      this.isReversed(), this.isUnique(), this.is_key_iterator_,
      index_key_path);
};

/**
 * @param {ydn.db.base.Transaction} tx tx.
 * @param {string} tx_lbl tx label.
 * @param {ydn.db.core.req.IRequestExecutor} executor executor.
 * @param {ydn.db.base.QueryMethod=} opt_query query method.
 * @return {!ydn.db.query.ConjunctionCursor} newly created cursor.
 */
ydn.db.query.ConjunctionIterator.prototype.iterate = function(tx, tx_lbl, executor,
                                             opt_query) {

  var query_mth = opt_query || ydn.db.base.QueryMethod.LIST_VALUE;
  var cursor = executor.getCursor(tx, tx_lbl, this.store_name_,
      this.index_key_path_ || this.index_name_,
      this.key_range_, this.direction_, this.is_key_iterator_, query_mth);
  var cursors = [cursor];
  for (var i = 0, n = this.joins_ ? this.joins_.length : 0; i < n; i++) {
    /**
     * @type {!ydn.db.query.EquiJoin}
     */
    var join = this.joins_[i];
    if (join.field_name && goog.isDefAndNotNull(join.value)) {
      var key_range;
      if (this.isPrimaryIterator()) {
        key_range = ydn.db.IDBKeyRange.only(join.value);
      } else {
        key_range = ydn.db.KeyRange.parseIDBKeyRange(
            ydn.db.KeyRange.starts([join.value]));
      }
      var cur = executor.getCursor(tx, tx_lbl, join.store_name,
          join.field_name, key_range,
          this.direction_, this.is_key_iterator_, query_mth);
      cursors.push(cur);
    }
  }

  var msg = '';
  if (this.cursor_) {
    msg = ' by resuming ' + this.cursor_;
  }

  this.cursor_ = new ydn.db.query.ConjunctionCursor(cursors, this.cursor_);

  goog.log.finest(this.logger, tx_lbl + ' ' + this + ' created ' + this.cursor_ + msg);
  return this.cursor_;
};

/**
 * Modified iterator with a given restriction.
 * @param {string} field_name restriction feild name.
 * @param {IDBKey} value restriction field value.
 * @return {!ydn.db.Iterator}
 */
ydn.db.query.ConjunctionIterator.prototype.restrict = function(field_name, value) {
  goog.asserts.assertString(field_name, 'field name in string require but, "' +
      field_name + '" of type ' + typeof field_name + ' found.');
  goog.asserts.assert(ydn.db.Key.isValidKey(value), 'key value "' +
      ydn.json.toShortString(value) + '" is invalid');
  return this.join(this.store_name_, field_name, value);
};

/**
 * @type {Array.<!ydn.db.query.EquiJoin>} list of joins.
 * @protected
 */
ydn.db.query.ConjunctionIterator.prototype.joins_;

/**
 * Join operation.
 * @param {string} store_name store name to join.
 * @param {string=} opt_field_name restriction feild name.
 * @param {IDBKey=} opt_value restriction field value.
 * @return {!ydn.db.Iterator} Newly created iterator with join operation
 * applied.
 */
ydn.db.query.ConjunctionIterator.prototype.join = function(store_name, opt_field_name,
                                          opt_value) {
  var iter = new ydn.db.Iterator(this.store_name_, this.index_name_,
      this.key_range_, this.isReversed(), this.isUnique(),
      this.is_key_iterator_, this.index_key_path_);

  var join = new ydn.db.query.EquiJoin(store_name, opt_field_name,
      opt_value);

  if (this.joins_) {
    iter.joins_ = this.joins_.concat(join);
  } else {
    iter.joins_ = [join];
  }

  return iter;
};

/**
 *
 * @return {!Array.<string>} list of stores.
 */
ydn.db.query.ConjunctionIterator.prototype.stores = function() {
  var stores = [this.getStoreName()];
  if (this.joins_) {
    for (var i = 0; i < this.joins_.length; i++) {
      if (!goog.array.contains(stores, this.joins_[i].store_name)) {
        stores.push(this.joins_[i].store_name);
      }
    }
  }
  return stores;
};
<|endoftext|>


<commit_before>const api = require('../api');
const mailchimp = require('../../mailchimp');
const getPrice = require('../../db/methods/getPrice');
const setPrice = require('../../db/methods/setPrice');

module.exports = function (req, res) {
    const body = req.body;

    if (!body) {
        return api.write(res, { error: 'Missing payload' }, 500);
    }

    console.log('POST /api/subscribe', body);

    const email = body.email;
    const firstname = body.firstname || '';
    const lastname = body.lastname || '';

    mailchimp.list.subscribe(email, firstname, lastname)
        .then(result => {
            // Only succeed when there are new members in the list...
            if (result.new_members.length === 0) {
                return api.write(res, null, 500);
            }

            api.write(res, { success: true }, 200);
        });
};<commit_msg>Added error-message when user is already registered<commit_after>const api = require('../api');
const mailchimp = require('../../mailchimp');
const getPrice = require('../../db/methods/getPrice');
const setPrice = require('../../db/methods/setPrice');

module.exports = function (req, res) {
    const body = req.body;

    if (!body) {
        return api.write(res, { error: 'Missing payload' }, 500);
    }

    console.log('POST /api/subscribe', body);

    const email = body.email;
    const firstname = body.firstname || '';
    const lastname = body.lastname || '';

    mailchimp.list.subscribe(email, firstname, lastname)
        .then(result => {
            // Only succeed when there are new members in the list...
            if (result.new_members.length === 0) {
                return api.write(res, { error: 'You are already registered.' }, 500);
            }

            api.write(res, { success: true }, 200);
        });
};<|endoftext|>


<commit_before>define([
    'jquery',
    '/common/common-interface.js',
    '/bower_components/chainpad-json-validator/json-ot.js',

    '/bower_components/chainpad/chainpad.dist.js',
], function ($, UI, JsonOT) {
    var ChainPad = window.ChainPad;
    var History = {};

    var getStates = function (rt) {
        var states = [];
        var b = rt.getAuthBlock();
        if (b) { states.unshift(b); }
        while (b.getParent()) {
            b = b.getParent();
            states.unshift(b);
        }
        return states;
    };

    var loadHistory = function (config, common, cb) {
        var createRealtime = function () {
            return ChainPad.create({
                userName: 'history',
                validateContent: function (content) {
                    try {
                        JSON.parse(content);
                        return true;
                    } catch (e) {
                        console.log('Failed to parse, rejecting patch');
                        return false;
                    }
                },
                initialState: '',
                transformFunction: JsonOT.validate,
                logLevel: 0,
                noPrune: true
            });
        };
        var realtime = createRealtime();

        History.readOnly = common.getMetadataMgr().getPrivateData().readOnly;

        var to = window.setTimeout(function () {
            cb('[GET_FULL_HISTORY_TIMEOUT]');
        }, 30000);

        common.getFullHistory(realtime, function () {
            window.clearTimeout(to);
            cb(null, realtime);
        });
    };

    History.create = function (common, config) {
        if (!config.$toolbar) { return void console.error("config.$toolbar is undefined");}
        if (History.loading) { return void console.error("History is already being loaded..."); }
        History.loading = true;
        var $toolbar = config.$toolbar;

        if (!config.applyVal || !config.setHistory || !config.onLocal || !config.onRemote) {
            throw new Error("Missing config element: applyVal, onLocal, onRemote, setHistory");
        }

        // config.setHistory(bool, bool)
        // - bool1: history value
        // - bool2: reset old content?
        var render = function (val) {
            if (typeof val === "undefined") { return; }
            try {
                config.applyVal(val);
            } catch (e) {
                // Probably a parse error
                console.error(e);
            }
        };
        var onClose = function () { config.setHistory(false, true); };
        var onRevert = function () {
            config.setHistory(false, false);
            config.onLocal();
            config.onRemote();
        };

        config.setHistory(true);
        var onReady = function () { };

        var Messages = common.Messages;

        var realtime;

        var states = [];
        var c = states.length - 1;

        var $hist = $toolbar.find('.cp-toolbar-history');
        var $left = $toolbar.find('.cp-toolbar-leftside');
        var $right = $toolbar.find('.cp-toolbar-rightside');
        var $cke = $toolbar.find('.cke_toolbox_main');

        $hist.html('').show();
        $left.hide();
        $right.hide();
        $cke.hide();

        UI.spinner($hist).get().show();

        var onUpdate;

        var update = function () {
            if (!realtime) { return []; }
            states = getStates(realtime);
            if (typeof onUpdate === "function") { onUpdate(); }
            return states;
        };

        // Get the content of the selected version, and change the version number
        var get = function (i) {
            i = parseInt(i);
            if (isNaN(i)) { return; }
            if (i < 0) { i = 0; }
            if (i > states.length - 1) { i = states.length - 1; }
            var val = states[i].getContent().doc;
            c = i;
            if (typeof onUpdate === "function") { onUpdate(); }
            $hist.find('.cp-toolbar-history-next, .cp-toolbar-history-previous').css('visibility', '');
            if (c === states.length - 1) { $hist.find('.cp-toolbar-history-next').css('visibility', 'hidden'); }
            if (c === 0) { $hist.find('.cp-toolbar-history-previous').css('visibility', 'hidden'); }

            if (config.debug) {
                console.log(states[i]);
                var ops = states[i] && states[i].getPatch() && states[i].getPatch().operations;
                if (Array.isArray(ops)) {
                    ops.forEach(function (op) { console.log(op); });
                }
            }

            return val || '';
        };

        var getNext = function (step) {
            return typeof step === "number" ? get(c + step) : get(c + 1);
        };
        var getPrevious = function (step) {
            return typeof step === "number" ? get(c - step) : get(c - 1);
        };

        // Create the history toolbar
        var display = function () {
            $hist.html('');
            var $prev =$('<button>', {
                'class': 'cp-toolbar-history-previous fa fa-step-backward buttonPrimary',
                title: Messages.history_prev
            }).appendTo($hist);
            var $nav = $('
', {'class': 'cp-toolbar-history-goto'}).appendTo($hist);
            var $next = $('<button>', {
                'class': 'cp-toolbar-history-next fa fa-step-forward buttonPrimary',
                title: Messages.history_next
            }).appendTo($hist);

            $('').text(Messages.history_version).appendTo($nav);
            var $cur = $('<input>', {
                'class' : 'cp-toolbar-history-goto-input',
                'type' : 'number',
                'min' : '1',
                'max' : states.length
            }).val(c + 1).appendTo($nav).mousedown(function (e) {
                // stopPropagation because the event would be cancelled by the dropdown menus
                e.stopPropagation();
            });
            var $label2 = $('').text(' / '+ states.length).appendTo($nav);
            $('
').appendTo($nav);
            var $close = $('<button>', {
                'class':'cp-toolbar-history-close',
                title: Messages.history_closeTitle
            }).text(Messages.history_closeTitle).appendTo($nav);
            var $rev = $('<button>', {
                'class':'cp-toolbar-history-revert buttonSuccess',
                title: Messages.history_restoreTitle
            }).text(Messages.history_restore).appendTo($nav);
            if (History.readOnly) { $rev.hide(); }

            onUpdate = function () {
                $cur.attr('max', states.length);
                $cur.val(c+1);
                $label2.text(' / ' + states.length);
            };

            var close = function () {
                $hist.hide();
                $left.show();
                $right.show();
                $cke.show();
                $(window).trigger('resize');
            };

            // Buttons actions
            $prev.click(function () { render(getPrevious()); });
            $next.click(function () { render(getNext()); });
            $cur.keydown(function (e) {
                var p = function () { e.preventDefault(); };
                if (e.which === 13) { p(); return render( get($cur.val() - 1) ); } // Enter
                if ([37, 40].indexOf(e.which) >= 0) { p(); return render(getPrevious()); } // Left
                if ([38, 39].indexOf(e.which) >= 0) { p(); return render(getNext()); } // Right
                if (e.which === 33) { p(); return render(getNext(10)); } // PageUp
                if (e.which === 34) { p(); return render(getPrevious(10)); } // PageUp
                if (e.which === 27) { p(); $close.click(); }
            }).keyup(function (e) { e.stopPropagation(); }).focus();
            $cur.on('change', function () {
                render( get($cur.val() - 1) );
            });
            $close.click(function () {
                states = [];
                close();
                onClose();
            });
            $rev.click(function () {
                UI.confirm(Messages.history_restorePrompt, function (yes) {
                    if (!yes) { return; }
                    close();
                    onRevert();
                    UI.log(Messages.history_restoreDone);
                });
            });

            // Display the latest content
            render(get(c));
            $(window).trigger('resize');
        };

        // Load all the history messages into a new chainpad object
        loadHistory(config, common, function (err, newRt) {
            History.loading = false;
            if (err) { throw new Error(err); }
            realtime = newRt;
            update();
            c = states.length - 1;
            display();
            onReady();
        });
    };

    return History;
});

<commit_msg>Add chainpad log to the debug app<commit_after>define([
    'jquery',
    '/common/common-interface.js',
    '/bower_components/chainpad-json-validator/json-ot.js',

    '/bower_components/chainpad/chainpad.dist.js',
], function ($, UI, JsonOT) {
    var ChainPad = window.ChainPad;
    var History = {};

    var getStates = function (rt) {
        var states = [];
        var b = rt.getAuthBlock();
        if (b) { states.unshift(b); }
        while (b.getParent()) {
            b = b.getParent();
            states.unshift(b);
        }
        return states;
    };

    var loadHistory = function (config, common, cb) {
        var createRealtime = function () {
            return ChainPad.create({
                userName: 'history',
                validateContent: function (content) {
                    try {
                        JSON.parse(content);
                        return true;
                    } catch (e) {
                        console.log('Failed to parse, rejecting patch');
                        return false;
                    }
                },
                initialState: '',
                transformFunction: JsonOT.validate,
                logLevel: config.debug ? 1 : 0,
                noPrune: true
            });
        };
        var realtime = createRealtime();

        History.readOnly = common.getMetadataMgr().getPrivateData().readOnly;

        var to = window.setTimeout(function () {
            cb('[GET_FULL_HISTORY_TIMEOUT]');
        }, 30000);

        common.getFullHistory(realtime, function () {
            window.clearTimeout(to);
            cb(null, realtime);
        });
    };

    History.create = function (common, config) {
        if (!config.$toolbar) { return void console.error("config.$toolbar is undefined");}
        if (History.loading) { return void console.error("History is already being loaded..."); }
        History.loading = true;
        var $toolbar = config.$toolbar;

        if (!config.applyVal || !config.setHistory || !config.onLocal || !config.onRemote) {
            throw new Error("Missing config element: applyVal, onLocal, onRemote, setHistory");
        }

        // config.setHistory(bool, bool)
        // - bool1: history value
        // - bool2: reset old content?
        var render = function (val) {
            if (typeof val === "undefined") { return; }
            try {
                config.applyVal(val);
            } catch (e) {
                // Probably a parse error
                console.error(e);
            }
        };
        var onClose = function () { config.setHistory(false, true); };
        var onRevert = function () {
            config.setHistory(false, false);
            config.onLocal();
            config.onRemote();
        };

        config.setHistory(true);
        var onReady = function () { };

        var Messages = common.Messages;

        var realtime;

        var states = [];
        var c = states.length - 1;

        var $hist = $toolbar.find('.cp-toolbar-history');
        var $left = $toolbar.find('.cp-toolbar-leftside');
        var $right = $toolbar.find('.cp-toolbar-rightside');
        var $cke = $toolbar.find('.cke_toolbox_main');

        $hist.html('').show();
        $left.hide();
        $right.hide();
        $cke.hide();

        UI.spinner($hist).get().show();

        var onUpdate;

        var update = function () {
            if (!realtime) { return []; }
            states = getStates(realtime);
            if (typeof onUpdate === "function") { onUpdate(); }
            return states;
        };

        // Get the content of the selected version, and change the version number
        var get = function (i) {
            i = parseInt(i);
            if (isNaN(i)) { return; }
            if (i < 0) { i = 0; }
            if (i > states.length - 1) { i = states.length - 1; }
            var val = states[i].getContent().doc;
            c = i;
            if (typeof onUpdate === "function") { onUpdate(); }
            $hist.find('.cp-toolbar-history-next, .cp-toolbar-history-previous').css('visibility', '');
            if (c === states.length - 1) { $hist.find('.cp-toolbar-history-next').css('visibility', 'hidden'); }
            if (c === 0) { $hist.find('.cp-toolbar-history-previous').css('visibility', 'hidden'); }

            if (config.debug) {
                console.log(states[i]);
                var ops = states[i] && states[i].getPatch() && states[i].getPatch().operations;
                if (Array.isArray(ops)) {
                    ops.forEach(function (op) { console.log(op); });
                }
            }

            return val || '';
        };

        var getNext = function (step) {
            return typeof step === "number" ? get(c + step) : get(c + 1);
        };
        var getPrevious = function (step) {
            return typeof step === "number" ? get(c - step) : get(c - 1);
        };

        // Create the history toolbar
        var display = function () {
            $hist.html('');
            var $prev =$('<button>', {
                'class': 'cp-toolbar-history-previous fa fa-step-backward buttonPrimary',
                title: Messages.history_prev
            }).appendTo($hist);
            var $nav = $('
', {'class': 'cp-toolbar-history-goto'}).appendTo($hist);
            var $next = $('<button>', {
                'class': 'cp-toolbar-history-next fa fa-step-forward buttonPrimary',
                title: Messages.history_next
            }).appendTo($hist);

            $('').text(Messages.history_version).appendTo($nav);
            var $cur = $('<input>', {
                'class' : 'cp-toolbar-history-goto-input',
                'type' : 'number',
                'min' : '1',
                'max' : states.length
            }).val(c + 1).appendTo($nav).mousedown(function (e) {
                // stopPropagation because the event would be cancelled by the dropdown menus
                e.stopPropagation();
            });
            var $label2 = $('').text(' / '+ states.length).appendTo($nav);
            $('
').appendTo($nav);
            var $close = $('<button>', {
                'class':'cp-toolbar-history-close',
                title: Messages.history_closeTitle
            }).text(Messages.history_closeTitle).appendTo($nav);
            var $rev = $('<button>', {
                'class':'cp-toolbar-history-revert buttonSuccess',
                title: Messages.history_restoreTitle
            }).text(Messages.history_restore).appendTo($nav);
            if (History.readOnly) { $rev.hide(); }

            onUpdate = function () {
                $cur.attr('max', states.length);
                $cur.val(c+1);
                $label2.text(' / ' + states.length);
            };

            var close = function () {
                $hist.hide();
                $left.show();
                $right.show();
                $cke.show();
                $(window).trigger('resize');
            };

            // Buttons actions
            $prev.click(function () { render(getPrevious()); });
            $next.click(function () { render(getNext()); });
            $cur.keydown(function (e) {
                var p = function () { e.preventDefault(); };
                if (e.which === 13) { p(); return render( get($cur.val() - 1) ); } // Enter
                if ([37, 40].indexOf(e.which) >= 0) { p(); return render(getPrevious()); } // Left
                if ([38, 39].indexOf(e.which) >= 0) { p(); return render(getNext()); } // Right
                if (e.which === 33) { p(); return render(getNext(10)); } // PageUp
                if (e.which === 34) { p(); return render(getPrevious(10)); } // PageUp
                if (e.which === 27) { p(); $close.click(); }
            }).keyup(function (e) { e.stopPropagation(); }).focus();
            $cur.on('change', function () {
                render( get($cur.val() - 1) );
            });
            $close.click(function () {
                states = [];
                close();
                onClose();
            });
            $rev.click(function () {
                UI.confirm(Messages.history_restorePrompt, function (yes) {
                    if (!yes) { return; }
                    close();
                    onRevert();
                    UI.log(Messages.history_restoreDone);
                });
            });

            // Display the latest content
            render(get(c));
            $(window).trigger('resize');
        };

        // Load all the history messages into a new chainpad object
        loadHistory(config, common, function (err, newRt) {
            History.loading = false;
            if (err) { throw new Error(err); }
            realtime = newRt;
            update();
            c = states.length - 1;
            display();
            onReady();
        });
    };

    return History;
});

<|endoftext|>


<commit_before><commit_msg>Added todo note to `GET_CONSTRUCTION_DOCKS`<commit_after><|endoftext|>


<commit_before>// Test
var assert = require('chai').assert;
var sinon = require('sinon');
var Factory = require('factory_girl');

// Dependencies
var _ = require('underscore');
var Marionette = require('backbone.marionette');
var Radio = require('backbone.radio');

// Fixtures
var fs = require('fs');
var fixtures = require('fixtures');
var BaseRegionsFixt = fs.readFileSync(__dirname + '/../fixtures/base-regions.html', 'utf8');

// App
var Controller = require('app/controller');
var EntitiesAPI = require('app/entities').API;
var LayoutView = require('app/list/views').LayoutView;
var LoadingView = require('app/common/views').LoadingView;
var NameView = require('app/edit/views').NameView;
var MoveFormView = require('app/edit/views').MoveFormView;
var Move = require('app/entities').Move;
var Moves = require('app/entities').Moves;
var Spots = require('app/entities').Spots;
var Spot = require('app/entities').Spot;

var channel = Radio.channel('global');

describe('Controller', function(){
    before(function(){
        fixtures.append(BaseRegionsFixt);

        channel.reply('get:region', function(name){
            if (name === 'main'){
                return this.mainRegion;
            }
        }, this);

        this.mainRegion = new Marionette.Region({
            el: '#main-region'
        });

        this.entitiesAPI = new EntitiesAPI();
    });

    beforeEach(function(){
        var moves = this.moves = new Moves();
        this.replyMovesStub = sinon.stub(this.entitiesAPI, 'replyMoves', function(){
            return moves;
        });

        var move = this.move = new Move();
        this.replyMoveStub = sinon.stub(this.entitiesAPI, 'replyMove', function(){
            return move;
        });

        var spots = this.spots = new Spots();
        this.replySpotsStub = sinon.stub(this.entitiesAPI, 'replySpots', function(){
            return spots;
        });

        this.server = sinon.fakeServer.create();
        this.server.respondWith(moves.url, JSON.stringify({results: []}));
        this.server.respondWith(spots.url, JSON.stringify(new Spot({id: 1, name: 'food'})));

        this.controller = new Controller();
    });

    after(function(){
        channel.stopReplying('get:region');
    });

    afterEach(function(){
        this.replyMovesStub.restore();
        this.replyMoveStub.restore();
        this.replySpotsStub.restore();
        this.server.restore();
        this.mainRegion.empty();
    });

    after(function(){
        fixtures.cleanup();
    });

    describe('initialize', function(){
        it('registers call:method request handler', function(){
            var args = 'something';
            var editStub = sinon.stub(this.controller, 'edit');
            channel.trigger('call:method', 'edit', args);
            assert.isTrue(editStub.calledOnce, 'editStub is called');
            assert.isTrue(editStub.calledWith(args), 'editStub is passed an argument');
        });
    });

    describe('destroy', function(){
        it('unregisters call:method request handler', function(){
            var editStub = sinon.stub(this.controller, 'edit');
            this.controller.destroy();
            channel.trigger('call:method', 'edit');
            assert.isFalse(editStub.calledOnce, 'call:method does not call method');
        });
    });

    describe('list', function(){
        it('shows loading view before view is loaded', function(){
            assert.isFalse(this.mainRegion.hasView(), 'no view shown yet');
            this.controller.list();
            assert.isTrue(this.mainRegion.hasView(), 'a view in the mainRegion');
            assert.isTrue(this.mainRegion.currentView instanceof LoadingView, 'view in mainRegion is LoadingView');
        });

        it('shows list LayoutView after moves and spots are fetched', function(){
            this.controller.list();
            this.server.respond();
            assert.isTrue(this.mainRegion.hasView(), 'a view in the mainRegion');
            assert.isTrue(this.mainRegion.currentView instanceof LayoutView, 'view in mainRegion is LayoutView');
        });

        it('passes saveAlert to LayoutView as recentSave option', function(){
            this.controller.list(true);
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView.getOption('recentSave'), 'passes true if save alert');
        });
    });

    describe('edit', function(){
        it('inserts view immediately if spots have already been fetched', function(){
            this.spots.fetch();
            this.server.respond();
            this.controller.edit();
            assert.isTrue(this.mainRegion.currentView instanceof NameView, 'view in mainRegion is NameView');
        });
        it('inserts loading view first if spots have not already been fetched', function(){
            this.controller.edit();
            assert.isTrue(this.mainRegion.currentView instanceof LoadingView, 'view in mainRegion is LoadingView');
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView instanceof NameView, 'view in mainRegion is NameView');
        });
        it('inserts NameView if move does not a have user name', function(){
            this.controller.edit();
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView instanceof NameView, 'view in mainRegion is NameView');
        });
        it('inserts MoveFormView if move does have a name', function(){
            this.move.set({user: "user"});
            this.controller.edit();
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView instanceof MoveFormView, 'view in mainRegion is MoveFormView');
        });
    });
});
<commit_msg>Remove underscore dependency.<commit_after>// Test
var assert = require('chai').assert;
var sinon = require('sinon');
var Factory = require('factory_girl');

// Dependencies
var Marionette = require('backbone.marionette');
var Radio = require('backbone.radio');

// Fixtures
var fs = require('fs');
var fixtures = require('fixtures');
var BaseRegionsFixt = fs.readFileSync(__dirname + '/../fixtures/base-regions.html', 'utf8');

// App
var Controller = require('app/controller');
var EntitiesAPI = require('app/entities').API;
var LayoutView = require('app/list/views').LayoutView;
var LoadingView = require('app/common/views').LoadingView;
var NameView = require('app/edit/views').NameView;
var MoveFormView = require('app/edit/views').MoveFormView;
var Move = require('app/entities').Move;
var Moves = require('app/entities').Moves;
var Spots = require('app/entities').Spots;
var Spot = require('app/entities').Spot;

var channel = Radio.channel('global');

describe('Controller', function(){
    before(function(){
        fixtures.append(BaseRegionsFixt);

        channel.reply('get:region', function(name){
            if (name === 'main'){
                return this.mainRegion;
            }
        }, this);

        this.mainRegion = new Marionette.Region({
            el: '#main-region'
        });

        this.entitiesAPI = new EntitiesAPI();
    });

    beforeEach(function(){
        var moves = this.moves = new Moves();
        this.replyMovesStub = sinon.stub(this.entitiesAPI, 'replyMoves', function(){
            return moves;
        });

        var move = this.move = new Move();
        this.replyMoveStub = sinon.stub(this.entitiesAPI, 'replyMove', function(){
            return move;
        });

        var spots = this.spots = new Spots();
        this.replySpotsStub = sinon.stub(this.entitiesAPI, 'replySpots', function(){
            return spots;
        });

        this.server = sinon.fakeServer.create();
        this.server.respondWith(moves.url, JSON.stringify({results: []}));
        this.server.respondWith(spots.url, JSON.stringify(new Spot({id: 1, name: 'food'})));

        this.controller = new Controller();
    });

    after(function(){
        channel.stopReplying('get:region');
    });

    afterEach(function(){
        this.replyMovesStub.restore();
        this.replyMoveStub.restore();
        this.replySpotsStub.restore();
        this.server.restore();
        this.mainRegion.empty();
    });

    after(function(){
        fixtures.cleanup();
    });

    describe('initialize', function(){
        it('registers call:method request handler', function(){
            var args = 'something';
            var editStub = sinon.stub(this.controller, 'edit');
            channel.trigger('call:method', 'edit', args);
            assert.isTrue(editStub.calledOnce, 'editStub is called');
            assert.isTrue(editStub.calledWith(args), 'editStub is passed an argument');
        });
    });

    describe('destroy', function(){
        it('unregisters call:method request handler', function(){
            var editStub = sinon.stub(this.controller, 'edit');
            this.controller.destroy();
            channel.trigger('call:method', 'edit');
            assert.isFalse(editStub.calledOnce, 'call:method does not call method');
        });
    });

    describe('list', function(){
        it('shows loading view before view is loaded', function(){
            assert.isFalse(this.mainRegion.hasView(), 'no view shown yet');
            this.controller.list();
            assert.isTrue(this.mainRegion.hasView(), 'a view in the mainRegion');
            assert.isTrue(this.mainRegion.currentView instanceof LoadingView, 'view in mainRegion is LoadingView');
        });

        it('shows list LayoutView after moves and spots are fetched', function(){
            this.controller.list();
            this.server.respond();
            assert.isTrue(this.mainRegion.hasView(), 'a view in the mainRegion');
            assert.isTrue(this.mainRegion.currentView instanceof LayoutView, 'view in mainRegion is LayoutView');
        });

        it('passes saveAlert to LayoutView as recentSave option', function(){
            this.controller.list(true);
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView.getOption('recentSave'), 'passes true if save alert');
        });
    });

    describe('edit', function(){
        it('inserts view immediately if spots have already been fetched', function(){
            this.spots.fetch();
            this.server.respond();
            this.controller.edit();
            assert.isTrue(this.mainRegion.currentView instanceof NameView, 'view in mainRegion is NameView');
        });
        it('inserts loading view first if spots have not already been fetched', function(){
            this.controller.edit();
            assert.isTrue(this.mainRegion.currentView instanceof LoadingView, 'view in mainRegion is LoadingView');
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView instanceof NameView, 'view in mainRegion is NameView');
        });
        it('inserts NameView if move does not a have user name', function(){
            this.controller.edit();
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView instanceof NameView, 'view in mainRegion is NameView');
        });
        it('inserts MoveFormView if move does have a name', function(){
            this.move.set({user: "user"});
            this.controller.edit();
            this.server.respond();
            assert.isTrue(this.mainRegion.currentView instanceof MoveFormView, 'view in mainRegion is MoveFormView');
        });
    });
});
<|endoftext|>