<commit_before>/*
**	elation panel component
**
**		Contents:
**			Panel
*/

elation.extend('panel', new function(options) {
  this.options = options;
  this.panels = [];
  this.panelmap = {};

	this.add = function(name, args, data, content, parent) {
    if (!this.panelmap[name]) {
			this.panelmap[name] = this.panels.length;
			this.panels.push(args || {});
    }

		this.Init(name, args);
  }

  this.Init = function(name, args) {
    elation.timing.set(true);
    var panel = this.panels[this.panelmap[name]] || null;

    if (args) {
			if (args.id)
				panel.element = $TF("#"+args.id);

			panel.items = {};
			if (args.cfg && args.cfg.items) {
				$TF.each(args.cfg.items, function(k, v) {
					panel.items[k] = new elation.panel.add_item(k, v, panel);
				});
			}
      if (panel.cfg) {
        if (panel.cfg.jsobject && panel.cfg.jsobject != "false") {
          var obj = eval(panel.cfg.jsobject);

          if (typeof obj == 'function') {
            panel.jsobj = new obj(this, panel);
            elation[panel.name] = panel.jsobj;

            if (typeof panel.jsobj.init == 'function')
              panel.jsobj.init();
          }
        }

        if (panel.cfg.navigation == "true") {
          panel.container = document.getElementById(panel.cfg.targetid);
          this.lis = $TF('div.tf_utils_panel_' + name + ' ul li');;

          for (var i=0; i<this.lis.length; i++)
            if (elation.html.hasclass(this.lis[i], 'selected'))
              panel.li = this.lis[i];

          for (var item in panel.items) {
            var	element = panel.items[item].element;

            if (typeof element == 'object' && element.length > 0) {
              elation.events.add(element[0], 'click', this);
              element[0].onselectstart = function() { return(false); };
            }
          }

          panel.item = this.get_item(panel, $TF('div.tf_utils_panel_' + name + ' ul li.selected')[0]);
        }
      }
			panel.content = {};
		}
    elation.timing.print(name + ' panel', true);
	}

	this.handleEvent = function(event) {
		event = event || window.event;
		target = event.target || event.srcElement;

		switch (event.type) {
			case "click":
				this.click(event, target);
				break;
		}
	}

	this.click = function(event, target) {
		while (target && target.nodeName != 'LI')
			target = target.parentNode;

		if (!target || elation.html.hasclass(target, 'tf_utils_state_disabled'))
			return;

		// find the proper panel for event and item for target
		for (var key in this.panelmap) {
			var	panel	= this.panels[this.panelmap[key]],
					item	= this.get_item(panel, target);

			if (item)
				break;
		}

		if (elation.utils.arrayget(item, 'args.unselectable'))
			return;

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

		if (item.name == panel.item.name)
			return;

    if (typeof pandoraLog == 'object') {
			pandoraLog.mouseovertype = item.name;
    }

    if (typeof googleAnalytics == 'object') {
      googleAnalytics.mouseovertype = item.name;
      if (item.name == "shoplikeme")
        googleAnalytics.trackEvent(['tab', 'shoplikeme', googleAnalytics.pagetype]);
      else if (item.name == "theweb")
        googleAnalytics.trackEvent(['tab', 'theWeb', googleAnalytics.pagetype]);
			else if (item.name == "nearby")
        googleAnalytics.trackEvent(['tab', 'nearby', googleAnalytics.pagetype]);
      else if (item.name == "shoplikefriends")
        googleAnalytics.trackEvent(['tab', 'shoplikefriends', googleAnalytics.pagetype]);
			else if (item.name == "myfinds")
        googleAnalytics.trackEvent(['tab', 'myfinds', googleAnalytics.pagetype]);
      else
        googleAnalytics.trackEvent(['popup_tab', googleAnalytics.mouseovertype]);
    }

		this.load_tab_content(panel, target, item);
	}

	this.load_tab_content = function(panel, target, item) {
		var	target = (typeof target == 'string')
					? document.getElementById(target)
					: target,
				panel = (typeof panel == 'object')
					? panel
					: this.panels[this.panelmap[panel]],
				item = item || this.get_item(panel, target);

		if (!panel.container) {
			var href = target.getElementsByTagName('a').length > 0
						? target.getElementsByTagName('a')[0].href
						: '';

			if (href) {
				var	input = elation.find('input.tf_search_input_element')[0],
            query = input
              ? input.value
              : '',
						queryString;

				// stop tab switch reloading on default_query
				if (query == elation.default_query)
					query = '';

				if (query)
					query = encodeURIComponent(query);

				(query) ? queryString = (href.indexOf('?') == -1 ? '?' : '&') + 'query=' + query : queryString = '';

				if ((query || !input) && href.search('/myfinds') === -1) {
				  window.location.href = href + queryString;
				} else if (input) {
          // FIXME - quick hack to disable the form-focus thing for tabs since we now have homepages for all of them
					if (true || href.search('/myfinds') !== -1) {
						window.location.href = href;
					}
					else {
						var form = elation.utils.getParent(input, 'FORM');

						if (form)
							form.action = href;

						elation.html.addclass(input, 'tf_util_form_error');
						input.focus();
					}
				}
			}

			this.select_item(item, panel);

			return panel.item = item;
		}

		this.select_item(item, panel);

		// cache content of tab for later retrieval
		if (!panel.cfg.nocache) {
			if ($TF('img.tf_results_ajax_spinner',panel.container).length == 0) // kludgy - dont save content if content still loading
				panel.content[panel.item.name] = panel.container.innerHTML;
			}
			panel.item = item;

			if (!panel.cfg.nocache) {
			// if cached copy exists use that
			if (panel.content[item.name])
				return panel.container.innerHTML = panel.content[item.name];
		} else {
			// tab fade-in effect
			if (elation.browser && elation.browser.type != 'msie')
				$TF(panel.container).animate({ opacity: 0 }, 'fast');
		}
		if (!panel.container.style.minHeight)
			panel.container.style.minHeight = panel.container.offsetHeight + 'px';

		if (panel.cfg.spinner)
			panel.container.innerHTML = panel.cfg.spinner;

		// Merge args from both the panel and any specified contentcomponentargs
		var urlargs = {};

		if (typeof panel.args == 'object')
			for (var k in panel.args)
				if (panel.args.hasOwnProperty(k))
					urlargs[k] = panel.args[k];

		if (typeof item.args.contentcomponentargs == 'object')
			for (var k in item.args.contentcomponentargs)
				if (item.args.contentcomponentargs.hasOwnProperty(k))
					urlargs[k] = item.args.contentcomponentargs[k];

		urlargs['targetid'] = panel.cfg.targetid;
		urlargs['tab'] = item.args.argname;
		panel.active_argname = item.args.argname;

		var parms = elation.utils.encodeURLParams(urlargs);

		if (panel.jsobj) {
      if (typeof panel.jsobj.setTab == 'function')
        panel.jsobj.setTab(target, item, panel);

      if (panel.jsobj.args)
        parms = parms + (parms ? '&' : '') + elation.utils.encodeURLParams(panel.jsobj.args);
		}

		var componentname = item.args.contentcomponent || panel.cfg.contentcomponent;

		// ajax-fetch tab content
		ajaxlib.Queue({
			url: componentname,
			args: parms,
			callback: [
				this,
				function(response) {
					// tab fade-in effect
					if (elation.browser && elation.browser.type != 'msie')
						$TF(panel.container).css({ opacity: 0 })
							.animate({ opacity: 1 }, 'fast')
							.animate({ opacity: 'auto' }, 0);

          if (panel.jsobj && typeof panel.jsobj.success == 'function') {
            panel.jsobj.success(response);
          }
        }
			]
		});
	}

	this.select_item = function(item, panel) {
		var	li = elation.utils.arrayget(item, 'element'),
        li = li.length > 0 ? li[0] : li;

		if (elation.html.hasclass(li, 'tf_utils_state_disabled'))
			return;

		if (panel.li)
			elation.html.removeclass(panel.li, 'selected');

		elation.html.addclass(li, 'selected');

		return panel.li = li;
	}

  this.set_args = function(panelname, args) {
		var panel, item;

  	if (panel = this.panels[this.panelmap[panelname]]) {
      for (var key in args)
        elation.utils.arrayset(panel.args, key, args[key]);

			for (var item_key in panel.items) {
				item = panel.items[item_key];
				if ((item.args.disableiffalse && !elation.utils.isTrue(args[item.args.disableiffalse])) || (item.args.disableiftrue && elation.utils.isTrue(args[item.args.disableiftrue])) || (item.args.disableifempty && elation.utils.isEmpty(args[item.args.disableifempty]))) {
					elation.html.addclass(item.element[0], 'tf_utils_state_disabled');

          if(item.args.disabledtype)
  					elation.html.addclass(item.element[0], 'tf_utils_state_disabled_'+item.args.disabledtype);
        }
			}
		}
  }

	this.get_item = function(panel, target) {
		for (var key in panel.items) {
			var	item = panel.items[key],
					element = item.element[0];

			if (target == element)
				return item;
		}

		return false;
	}

  this.add_item = function(name, args, panel, content) {
    this.name = name;
    this.args = args || {};
    this.panel = panel;

    this.init = function() {
      if (!this.panel)
				return;

			this.element = $TF("ul.tf_utils_panel_content li#" + this.panel.id + "_" + this.name);

			if (this.args.contentcomponent && !this.args.nopopup && this.element.length > 0) {
				var panelname = this.panel.name.replace(/\./g, "_") + "_" + this.name;

				elation.ui.infobox.add(
					panelname,
					{
						width:			this.args.contentwidth		|| '20em',
						titlebar:		this.args.contenttitle		|| true,
						label:			this.args.contentlabel		|| false,
						loading:		this.args.contentloading	|| false,
            fullscreen: this.args.fullscreen			|| false,
            absolute:   this.args.absolute				|| false,
            animation:  this.args.animation			|| '',
						lightbox: 	'tf_infobox_lightbox',
						border:			'div',
						classname:	'tf_myfinds_infobox_popup',
						activecss:	'tf_myfinds_infobox_selected',
						bgcolor:		'white',
						event:			'click',
						tailsrc:		'div',
            killscroll: true,
						vertical:		true,
						nocache:		true,
						resize:   	true,
						ajax:				true
					},
					this.args.contentcomponentargs || null,
					"/" + this.args.contentcomponent.replace(/\./, "/"),
					this.element[0]
				);
			}
    }

    this.init();
  }
});
<commit_msg>removed some debug info<commit_after>/*
**	elation panel component
**
**		Contents:
**			Panel
*/

elation.extend('panel', new function(options) {
  this.options = options;
  this.panels = [];
  this.panelmap = {};

	this.add = function(name, args, data, content, parent) {
    if (!this.panelmap[name]) {
			this.panelmap[name] = this.panels.length;
			this.panels.push(args || {});
    }

		this.Init(name, args);
  }

  this.Init = function(name, args) {
    elation.timing.set(true);
    var panel = this.panels[this.panelmap[name]] || null;

    if (args) {
			if (args.id)
				panel.element = $TF("#"+args.id);

			panel.items = {};
			if (args.cfg && args.cfg.items) {
				$TF.each(args.cfg.items, function(k, v) {
					panel.items[k] = new elation.panel.add_item(k, v, panel);
				});
			}
      if (panel.cfg) {
        if (panel.cfg.jsobject && panel.cfg.jsobject != "false") {
          var obj = eval(panel.cfg.jsobject);

          if (typeof obj == 'function') {
            panel.jsobj = new obj(this, panel);
            elation[panel.name] = panel.jsobj;

            if (typeof panel.jsobj.init == 'function')
              panel.jsobj.init();
          }
        }

        if (panel.cfg.navigation == "true") {
          panel.container = document.getElementById(panel.cfg.targetid);
          this.lis = $TF('div.tf_utils_panel_' + name + ' ul li');;

          for (var i=0; i<this.lis.length; i++)
            if (elation.html.hasclass(this.lis[i], 'selected'))
              panel.li = this.lis[i];

          for (var item in panel.items) {
            var	element = panel.items[item].element;

            if (typeof element == 'object' && element.length > 0) {
              elation.events.add(element[0], 'click', this);
              element[0].onselectstart = function() { return(false); };
            }
          }

          panel.item = this.get_item(panel, $TF('div.tf_utils_panel_' + name + ' ul li.selected')[0]);
        }
      }
			panel.content = {};
		}
    elation.timing.print(name + ' panel', true);
	}

	this.handleEvent = function(event) {
		event = event || window.event;
		target = event.target || event.srcElement;

		switch (event.type) {
			case "click":
				this.click(event, target);
				break;
		}
	}

	this.click = function(event, target) {
		while (target && target.nodeName != 'LI')
			target = target.parentNode;

		if (!target || elation.html.hasclass(target, 'tf_utils_state_disabled'))
			return;

		// find the proper panel for event and item for target
		for (var key in this.panelmap) {
			var	panel	= this.panels[this.panelmap[key]],
					item	= this.get_item(panel, target);

			if (item)
				break;
		}

		if (elation.utils.arrayget(item, 'args.unselectable'))
			return;

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

		if (item.name == panel.item.name)
			return;

    if (typeof pandoraLog == 'object') {
			pandoraLog.mouseovertype = item.name;
    }

    if (typeof googleAnalytics == 'object') {
      googleAnalytics.mouseovertype = item.name;
      if (item.name == "shoplikeme")
        googleAnalytics.trackEvent(['tab', 'shoplikeme', googleAnalytics.pagetype]);
      else if (item.name == "theweb")
        googleAnalytics.trackEvent(['tab', 'theWeb', googleAnalytics.pagetype]);
			else if (item.name == "nearby")
        googleAnalytics.trackEvent(['tab', 'nearby', googleAnalytics.pagetype]);
      else if (item.name == "shoplikefriends")
        googleAnalytics.trackEvent(['tab', 'shoplikefriends', googleAnalytics.pagetype]);
			else if (item.name == "myfinds")
        googleAnalytics.trackEvent(['tab', 'myfinds', googleAnalytics.pagetype]);
      else
        googleAnalytics.trackEvent(['popup_tab', googleAnalytics.mouseovertype]);
    }

		this.load_tab_content(panel, target, item);
	}

	this.load_tab_content = function(panel, target, item) {
		var	target = (typeof target == 'string')
					? document.getElementById(target)
					: target,
				panel = (typeof panel == 'object')
					? panel
					: this.panels[this.panelmap[panel]],
				item = item || this.get_item(panel, target);

		if (!panel.container) {
			var href = target.getElementsByTagName('a').length > 0
						? target.getElementsByTagName('a')[0].href
						: '';

			if (href) {
				var	input = elation.find('input.tf_search_input_element')[0],
            query = input
              ? input.value
              : '',
						queryString;

				// stop tab switch reloading on default_query
				if (query == elation.default_query)
					query = '';

				if (query)
					query = encodeURIComponent(query);

				(query) ? queryString = (href.indexOf('?') == -1 ? '?' : '&') + 'query=' + query : queryString = '';

				if ((query || !input) && href.search('/myfinds') === -1) {
				  window.location.href = href + queryString;
				} else if (input) {
          // FIXME - quick hack to disable the form-focus thing for tabs since we now have homepages for all of them
					if (true || href.search('/myfinds') !== -1) {
						window.location.href = href;
					}
					else {
						var form = elation.utils.getParent(input, 'FORM');

						if (form)
							form.action = href;

						elation.html.addclass(input, 'tf_util_form_error');
						input.focus();
					}
				}
			}

			this.select_item(item, panel);

			return panel.item = item;
		}

		this.select_item(item, panel);

		// cache content of tab for later retrieval
		if (!panel.cfg.nocache) {
			if ($TF('img.tf_results_ajax_spinner',panel.container).length == 0) // kludgy - dont save content if content still loading
				panel.content[panel.item.name] = panel.container.innerHTML;
			}
			panel.item = item;

			if (!panel.cfg.nocache) {
			// if cached copy exists use that
			if (panel.content[item.name])
				return panel.container.innerHTML = panel.content[item.name];
		} else {
			// tab fade-in effect
			if (elation.browser && elation.browser.type != 'msie')
				$TF(panel.container).animate({ opacity: 0 }, 'fast');
		}
		if (!panel.container.style.minHeight)
			panel.container.style.minHeight = panel.container.offsetHeight + 'px';

		if (panel.cfg.spinner)
			panel.container.innerHTML = panel.cfg.spinner;

		// Merge args from both the panel and any specified contentcomponentargs
		var urlargs = {};

		if (typeof panel.args == 'object')
			for (var k in panel.args)
				if (panel.args.hasOwnProperty(k))
					urlargs[k] = panel.args[k];

		if (typeof item.args.contentcomponentargs == 'object')
			for (var k in item.args.contentcomponentargs)
				if (item.args.contentcomponentargs.hasOwnProperty(k))
					urlargs[k] = item.args.contentcomponentargs[k];

		urlargs['targetid'] = panel.cfg.targetid;
		urlargs['tab'] = item.args.argname;
		panel.active_argname = item.args.argname;

		var parms = elation.utils.encodeURLParams(urlargs);

		if (panel.jsobj) {
      if (typeof panel.jsobj.setTab == 'function')
        panel.jsobj.setTab(target, item, panel);

      if (panel.jsobj.args)
        parms = parms + (parms ? '&' : '') + elation.utils.encodeURLParams(panel.jsobj.args);
		}

		var componentname = item.args.contentcomponent || panel.cfg.contentcomponent;

		// ajax-fetch tab content
		ajaxlib.Queue({
			url: componentname,
			args: parms,
			callback: [
				this,
				function(response) {
					// tab fade-in effect
					if (elation.browser && elation.browser.type != 'msie')
						$TF(panel.container).css({ opacity: 0 })
							.animate({ opacity: 1 }, 'fast')
							.animate({ opacity: 'auto' }, 0);

          if (panel.jsobj && typeof panel.jsobj.success == 'function') {
            panel.jsobj.success(response);
          }
        }
			]
		});
	}

	this.select_item = function(item, panel) {
		var	li = elation.utils.arrayget(item, 'element'),
        li = li.length > 0 ? li[0] : li;

		if (elation.html.hasclass(li, 'tf_utils_state_disabled'))
			return;

		if (panel.li)
			elation.html.removeclass(panel.li, 'selected');

		elation.html.addclass(li, 'selected');

		return panel.li = li;
	}

  this.set_args = function(panelname, args) {
		var panel, item;

  	if (panel = this.panels[this.panelmap[panelname]]) {
      for (var key in args)
        elation.utils.arrayset(panel.args, key, args[key]);

			for (var item_key in panel.items) {
				item = panel.items[item_key];
				if ((item.args.disableiffalse && !elation.utils.isTrue(args[item.args.disableiffalse])) || (item.args.disableiftrue && elation.utils.isTrue(args[item.args.disableiftrue])) || (item.args.disableifempty && elation.utils.isEmpty(args[item.args.disableifempty]))) {
					elation.html.addclass(item.element[0], 'tf_utils_state_disabled');

          if(item.args.disabledtype)
  					elation.html.addclass(item.element[0], 'tf_utils_state_disabled_'+item.args.disabledtype);
        }
			}
		}
  }

	this.get_item = function(panel, target) {
		for (var key in panel.items) {
			var	item = panel.items[key],
					element = item.element[0];

			if (target == element)
				return item;
		}

		return false;
	}

  this.add_item = function(name, args, panel, content) {
    this.name = name;
    this.args = args || {};
    this.panel = panel;

    this.init = function() {
      if (!this.panel)
				return;

			this.element = $TF("ul.tf_utils_panel_content li#" + this.panel.id + "_" + this.name);

			if (this.args.contentcomponent && !this.args.nopopup && this.element.length > 0) {
				var panelname = this.panel.name.replace(/\./g, "_") + "_" + this.name;

				elation.ui.infobox.add(
					panelname,
					{
						width:			this.args.contentwidth		|| '20em',
						titlebar:		this.args.contenttitle		|| true,
						label:			this.args.contentlabel		|| false,
						loading:		this.args.contentloading	|| false,
            fullscreen: this.args.fullscreen			|| false,
            absolute:   this.args.absolute				|| false,
            animation:  this.args.animation			|| '',
						lightbox: 	'tf_infobox_lightbox',
						border:			'div',
						classname:	'tf_myfinds_infobox_popup',
						activecss:	'tf_myfinds_infobox_selected',
						bgcolor:		'white',
						event:			'click',
						tailsrc:		'div',
            killscroll: true,
						vertical:		true,
						nocache:		true,
						resize:   	true,
						ajax:				true
					},
					this.args.contentcomponentargs || null,
					"/" + this.args.contentcomponent.replace(/\./, "/"),
					this.element[0]
				);
			}
    }

    this.init();
  }
});
<|endoftext|>


<commit_before> $(document).ready(function(){

  toSection(".section_welcome")

  $("body").css("height",$(window).innerHeight())
  $(".main_content_top").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_bottom").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_top_label").css("margin-top", $(".header").height())

  //
  // Crypt & decrypt
  //
  var emoji_list = ['😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂','😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂']
  _.each(emoji_list, function(d){
    $(".keyslider_content").append('
'+d+'
')
  })
  $('.main_content_top_input').bind('input propertychange', function() {
    encryptText()
  })
  $('.key').click(function(){
    var key = $(this).attr('key')
    keySelect(key)
    encryptText()
  })
})

function toSection(button){
  $(".section").hide()
  $(button).show()
}

//
// Encrypt / key select
//
function keySelect(key) {
  Criptoloji.key = key
  console.log('Chosen key', key)
}
function encryptText() {
  var text = $('.main_content_top_input').val()
  $('.main_content_bottom_input').text(Criptoloji.encrypt(text))
}

//
// Key Slider
//
function keysliderGoto(toElem, elementWidth) {
  $('.keyslider').animate({scrollLeft: toElem*elementWidth}, 200)
}
var debouncedKeysliderGoto = _.debounce(keysliderGoto, 200)
var lastPos = 0
var $wrapper = $('.keyslider')
$('.keyslider').scroll(function (event) {
  // debugger;
  var elementWidth = $('.key:nth-child(1)', $wrapper).outerWidth(true)
  console.log('elwidth', elementWidth)
  var currPos = $wrapper.scrollLeft()
  var direction = (currPos > lastPos) ? 'right' : 'left'
  console.log('keyslider direction: ' + direction)
  // calculate proper slide to element
  var toElem = (currPos / elementWidth)
  var rightThreshold = 0.5
  var leftThreshold = 0.75
  var decimal = (toElem % 1).toFixed(1)
  console.log(toElem, decimal)
  if (direction === 'right' && decimal > rightThreshold)
    toElem += 1
  if (direction === 'left' && decimal > 0 && decimal < leftThreshold)
    toElem -= 1
  toElem = Math.ceil(toElem)
  console.log('keyslider goTo', toElem)
  debouncedKeysliderGoto(toElem, elementWidth)
  lastPos = currPos
});
<commit_msg>keyslider goto on tap and select key on scroll<commit_after> $(document).ready(function(){

  toSection(".section_welcome")

  $("body").css("height",$(window).innerHeight())
  $(".main_content_top").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_bottom").css("height",$(window).innerHeight()/2-$(".main_keyslider").height()/2)
  $(".main_content_top_label").css("margin-top", $(".header").height())

  //
  // Crypt & decrypt
  //
  var emoji_list = ['😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂','😹','😤','😐','😖','😀','😻','😕','🙍','😠','😨','😘','😇','😄','😂']
  _.each(emoji_list, function(d){
    $(".keyslider_content").append('
'+d+'
')
  })
  $('.main_content_top_input').bind('input propertychange', function() {
    encryptText()
  })
  $('.key').click(function(){
    var key = $(this).attr('key')
    keySelect(key)
    encryptText()

    var elementWidth = $('.key:nth-child(1)', $wrapper).outerWidth(true)
    var toElem = $('.key').index(this)
    keysliderGoto(toElem, elementWidth)
  })
})

function toSection(button){
  $(".section").hide()
  $(button).show()
}

//
// Encrypt / key select
//
function keySelect(key) {
  Criptoloji.key = key
  console.log('Chosen key', key)
}
function encryptText() {
  var text = $('.main_content_top_input').val()
  $('.main_content_bottom_input').text(Criptoloji.encrypt(text))
}

//
// Key Slider
//
function keysliderGoto(toElem, elementWidth) {
  // console.log(toElem, elementWidth)
  $('.keyslider').animate({scrollLeft: toElem*elementWidth}, 200)
  keySelect($('.keyslider .key:nth-child('+toElem+')').attr('key'))
  encryptText()
}
var debouncedKeysliderGoto = _.debounce(keysliderGoto, 200)
var lastPos = 0
var $wrapper = $('.keyslider')
$('.keyslider').scroll(function (event) {
  // debugger;
  var elementWidth = $('.key:nth-child(1)', $wrapper).outerWidth(true)
  // console.log('elwidth', elementWidth)
  var currPos = $wrapper.scrollLeft()
  var direction = (currPos > lastPos) ? 'right' : 'left'
  // console.log('keyslider direction: ' + direction)
  // calculate proper slide to element
  var toElem = (currPos / elementWidth)
  var rightThreshold = 0.5
  var leftThreshold = 0.75
  var decimal = (toElem % 1).toFixed(1)
  // console.log(toElem, decimal)
  if (direction === 'right' && decimal > rightThreshold)
    toElem += 1
  if (direction === 'left' && decimal > 0 && decimal < leftThreshold)
    toElem -= 1
  toElem = Math.ceil(toElem)
  // console.log('keyslider goTo', toElem)
  debouncedKeysliderGoto(toElem, elementWidth)
  lastPos = currPos
});
<|endoftext|>


<commit_before>/**
 * Viewerに関する処理
 * @param {EditorList} editorList
 */
var Viewer = function (editorList) {
	var $templates = $('#ko-cha-templates');
	/**
	 * アイコンのHTMLテンプレート
	 * @type {jQuery Object}
	 */
	this.$icon = $templates.find('.viewer-icon').clone();

	/**
	 * EditorListのインスタンス
	 * @type {EditorList}
	 */
	this.editorList = editorList;
}
Viewer.prototype = {
	/**
	 * 初期化
	 */
	init: function () {
		$('.js_my_icon').addClass(roomInfo.viewer.viewer_id).css({
			'background-image': 'url(' + this.getIconUrl(roomInfo.viewer.image) + ')'
		});
		// 自分自身をビューワーリストに追加して、自分のエディタを全画面で表示する
		this.add(roomInfo.viewer);
		$('.viewer-list').find('[data-viewer-id="' + roomInfo.viewer.viewer_id + '"]').addClass('active');
		editorList.setLayout(roomInfo.viewer.viewer_id, 4);

		// SNSログイン
		$('.sns-login').find('span').click(function () {
			var sns = $(this).data('sns');
			var url = 'auth/login/' + sns;
			window.open(url, '', 'width=800,height=500');
		});
	},

	/**
	 * 受信データを反映
	 * @param  {Object} data
	 */
	update: function (data) {
		for (var i in data) {
			if (data[i].viewer_id in this.editorList.editorList) {
				var image = this.getIconUrl(data[i].image);
				this.changeIcon(image, data[i].viewer_id);

				$('.viewer-list').find('[data-viewer-id="' + data[i].viewer_id + '"]').addClass(data[i].viewer_id).css('background-image', 'url(' + image + ')');
				$('#' + data[i].viewer_id).find('.editor-user-icon').css('background-image', 'url(' + image + ')').addClass(data[i].viewer_id);
			} else {
				this.add(data[i]);
			}

			// PeerConnectionのオファーが来た
			if (data[i].peer_id &&　data[i].viewing == '1' && data[i].viewer_id !== getMyViewerId()) {
				connection.onOffer(data[i].peer_id);
			}
		}
	},

	/**
	 * Viewerの追加
	 * @param {Object} data
	 */
	add: function (data) {
		this.editorList.add(data.viewer_id);
		var image = this.getIconUrl(data.image);

		this.$icon.clone().attr('data-viewer-id', data.viewer_id).addClass(data.viewer_id).css('background-image', 'url(' + image + ')').appendTo(".viewer-list");
		$('#' + data.viewer_id).find('.editor-user-icon').css('background-image', 'url(' + image + ')').addClass(data.viewer_id).mouseenter(function () {
			$(this).addClass('hidden');
			var that = this;
			setTimeout(function() {$(that).removeClass('hidden') }, 2000);
		});

		if (roomInfo.viewer.viewer_id === data.viewer_id) {
			$('#' + data.viewer_id).addClass('self-editor');
		}
	},

	/**
	 * Viewerがアクティブかを設定
	 * @param {Boolean} active
	 */
	setActive: function (viewerId, active) {
		if (viewerId === getMyViewerId()) return;

		$('.viewer-list').find('[data-viewer-id="' + viewerId + '"]')[active ? 'addClass' : 'removeClass']('active');
	},

	/**
	 * ユーザーアイコンのHTML生成
	 * @param  {Object} data
	 * @return {String} HTML
	 */
	getIconUrl: function (data) {
		data = "" + data;
		return data.length < 10 ? 'assets/img/user/default/' + data + '.png' : data;
	},

	/**
	 * ユーザーアイコンを変更する
	 * @param  {String} image - 新しいアイコンのURL
	 * @param  {String} viewerId
	 */
	changeIcon: (function () {
		var viewerInfoMap = {};

		return function (image, viewerId) {
			if (viewerId === roomInfo.viewer.viewer_id) {
				roomInfo.viewer.image = image;
			}
			if (!(viewerId in viewerInfoMap)) {
				viewerInfoMap[viewerId] = "";
			}
			if (viewerInfoMap[viewerId] !== image) {
				viewerInfoMap[viewerId] = image;
				$('.' + viewerId).css('background-image', 'url(' + image + ')');
			}
		}
	}())
}

var viewer = new Viewer(editorList);

/**
 * SNSのアイコン画像を適用する
 * @param  {String} image - 新しいアイコンのURL
 * @param  {String} name
 */
function snsApply(image, name) {
	connection.send({
		type: 'update_image',
		data: {
			'image': image,
			'name': name
		}
	});
}
<commit_msg>jsdoc修正<commit_after>/**
 * Viewerに関する処理
 * @param {EditorList} editorList
 */
var Viewer = function (editorList) {
	var $templates = $('#ko-cha-templates');
	/**
	 * アイコンのHTMLテンプレート
	 * @type {jQuery Object}
	 */
	this.$icon = $templates.find('.viewer-icon').clone();

	/**
	 * EditorListのインスタンス
	 * @type {EditorList}
	 */
	this.editorList = editorList;
}
Viewer.prototype = {
	/**
	 * 初期化
	 */
	init: function () {
		$('.js_my_icon').addClass(roomInfo.viewer.viewer_id).css({
			'background-image': 'url(' + this.getIconUrl(roomInfo.viewer.image) + ')'
		});
		// 自分自身をビューワーリストに追加して、自分のエディタを全画面で表示する
		this.add(roomInfo.viewer);
		$('.viewer-list').find('[data-viewer-id="' + roomInfo.viewer.viewer_id + '"]').addClass('active');
		editorList.setLayout(roomInfo.viewer.viewer_id, 4);

		// SNSログイン
		$('.sns-login').find('span').click(function () {
			var sns = $(this).data('sns');
			var url = 'auth/login/' + sns;
			window.open(url, '', 'width=800,height=500');
		});
	},

	/**
	 * 受信データを反映
	 * @param  {Object} data
	 */
	update: function (data) {
		for (var i in data) {
			if (data[i].viewer_id in this.editorList.editorList) {
				var image = this.getIconUrl(data[i].image);
				this.changeIcon(image, data[i].viewer_id);

				$('.viewer-list').find('[data-viewer-id="' + data[i].viewer_id + '"]').addClass(data[i].viewer_id).css('background-image', 'url(' + image + ')');
				$('#' + data[i].viewer_id).find('.editor-user-icon').css('background-image', 'url(' + image + ')').addClass(data[i].viewer_id);
			} else {
				this.add(data[i]);
			}

			// PeerConnectionのオファーが来た
			if (data[i].peer_id &&　data[i].viewing == '1' && data[i].viewer_id !== getMyViewerId()) {
				connection.onOffer(data[i].peer_id);
			}
		}
	},

	/**
	 * Viewerの追加
	 * @param {Object} data
	 */
	add: function (data) {
		this.editorList.add(data.viewer_id);
		var image = this.getIconUrl(data.image);

		this.$icon.clone().attr('data-viewer-id', data.viewer_id).addClass(data.viewer_id).css('background-image', 'url(' + image + ')').appendTo(".viewer-list");
		$('#' + data.viewer_id).find('.editor-user-icon').css('background-image', 'url(' + image + ')').addClass(data.viewer_id).mouseenter(function () {
			$(this).addClass('hidden');
			var that = this;
			setTimeout(function() {$(that).removeClass('hidden') }, 2000);
		});

		if (roomInfo.viewer.viewer_id === data.viewer_id) {
			$('#' + data.viewer_id).addClass('self-editor');
		}
	},

	/**
	 * Viewerがアクティブ化を設定
	 * @param {String} viewerId
	 * @param {String} active
	 */
	setActive: function (viewerId, active) {
		if (viewerId === getMyViewerId()) return;

		$('.viewer-list').find('[data-viewer-id="' + viewerId + '"]')[active ? 'addClass' : 'removeClass']('active');
	},

	/**
	 * ユーザーアイコンのHTML生成
	 * @param  {Object} data
	 * @return {String} HTML
	 */
	getIconUrl: function (data) {
		data = "" + data;
		return data.length < 10 ? 'assets/img/user/default/' + data + '.png' : data;
	},

	/**
	 * ユーザーアイコンを変更する
	 * @param  {String} image - 新しいアイコンのURL
	 * @param  {String} viewerId
	 */
	changeIcon: (function () {
		var viewerInfoMap = {};

		return function (image, viewerId) {
			if (viewerId === roomInfo.viewer.viewer_id) {
				roomInfo.viewer.image = image;
			}
			if (!(viewerId in viewerInfoMap)) {
				viewerInfoMap[viewerId] = "";
			}
			if (viewerInfoMap[viewerId] !== image) {
				viewerInfoMap[viewerId] = image;
				$('.' + viewerId).css('background-image', 'url(' + image + ')');
			}
		}
	}())
}

var viewer = new Viewer(editorList);

/**
 * SNSのアイコン画像を適用する
 * @param  {String} image - 新しいアイコンのURL
 * @param  {String} name
 */
function snsApply(image, name) {
	connection.send({
		type: 'update_image',
		data: {
			'image': image,
			'name': name
		}
	});
}
<|endoftext|>


<commit_before>'use strict';

var $ = global.jQuery = require('jquery');
var parsley = require('parsleyjs');
var timeago = global.__timeago = require('timeago.js');
var selectizeRender = {};

require('bootstrap');
require('selectize');
require('summernote');

// Our main initializations, tolerate the long format
$().ready(function() {  // eslint-disable-line max-statements
  // Get language code from HTML tag
  // (Default is just in case we miss it.  It _should_ always be set.)
  var lang = $('html').attr('lang') || 'en';
  var locales = {
    ar: 'ar-AR',
    bg: 'bg-BG',
    ca: 'ca-ES',
    cs: 'cs-CZ',
    da: 'da-DK',
    de: 'de-DE',
    es: 'es-ES',
    fa: 'fa-IR',
    fi: 'fi-FI',
    fr: 'fr-FR',
    gl: 'gl-ES',
    he: 'he-IL',
    hr: 'hr-HR',
    hu: 'hu-HU',
    id: 'id-ID',
    it: 'it-IT',
    ja: 'ja-JP',
    ko: 'ko-KR',
    lt: 'lt-LT',
    nb: 'nb-NO',
    nl: 'nl-NL',
    pl: 'pl-PL',
    pt: 'pt-PT',
    ro: 'ro-RO',
    ru: 'ru-RU',
    sk: 'sk-SK',
    sl: 'sl-SI',
    sv: 'sv-SE',
    th: 'th-TH',
    tr: 'tr-TR',
    uk: 'uk-UA',
    vi: 'vi-VN',
    zh: 'zh-CN'
  };
  var locale = locales[lang];

  var excludedInputs = 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], .input-like input, .rich-edit';  // eslint-disable-line max-len

  // A valid e-mail for us has: nospaces, '@', nospaces, '.', nospaces
  // Actual RFC822 implementations are pages long and wouldn't benefit us much.
  var regexEMail = /^[^@ ]+@[^@ .]+\.[^@ ]+$/;
  var regexNameEMail = /^([^<]+)<([^@ ]+@[^@ .]+\.[^@ ]+)>$/;

  // Hide-away fields
  $('.hideaway-focus').on('focus', function() {
    $(this)
      .closest('.hideaway')
      .css({
        position: 'relative',
        left    : 0
      });
  });

  // Bootstrap-ize forms before enabling Parsley on them

  // LARGE FORMS
  //
  // leftright: labels on the left, one input/button per line, errors below
  // tight: labels and errors inside inputs, button on own line
  //
  $('form.form-leftright, form.form-tight').each(function() {
    $(this)
      .attr('name', $(this).attr('id'))
      .addClass('form-horizontal')
    ;
  });
  $('form.form-leftright > input, form.form-leftright > .btn-group, form.form-leftright > select, form.form-leftright > textarea, form.form-leftright > .input-like')  // eslint-disable-line max-len
    .not(excludedInputs)
    .each(function() {
      var id        = $(this).attr('id');
      var label     = $(this).attr('data-label');
      var fgClasses = '';
      var icon      = null;

      if ($(this).is('[class*="feedback-"]')) {
        fgClasses = ' has-feedback has-feedback-left';
        icon = $(this)
          .attr('class')
          .match(/\bfeedback-([a-zA-Z0-9_-]+)\b/)[1];
      }

      if (!$(this).hasClass('btn-group') && !$(this).hasClass('input-group')) {
        $(this).addClass('form-control');
      }

      $(this)
        .attr('name', id)
        .wrap('

')
        .parent()
        .prepend(
          ''
          + label
          + ''
        )
      ;
      $(this).wrap('

');
      if (icon) {
        $(this).after(
            ''
          );
      }
    }
  );
  $('form.form-tight input, form.form-tight select, form.form-tight textarea')
    .not(excludedInputs)
    .each(function() {
      var id      = $(this).attr('id');
      var label   = $(this).attr('data-label');
      var colsize = $(this).attr('data-colsize') || 6;
      var fgClasses = '';
      var icon      = null;

      if ($(this).is('[class*="feedback-"]')) {
        fgClasses = ' has-feedback has-feedback-left';
        icon = $(this)
          .attr('class')
          .match(/\bfeedback-([a-zA-Z0-9_-]+)\b/)[1];
      }

      $(this)
        .attr('name', id)
        .addClass('form-control')
        .wrap(
            '

'
          )
        .parent()
        .prepend('' + label + '')
      ;
      if (icon) {
        $(this).after(
            ''
          );
      }
    }
  );
  $('form.form-leftright button, form.form-tight button[type=submit]')
    .not('.input-like button, .form-group button')
    .each(function() {
      $(this)
        .addClass('btn btn-default')
        .wrap('

')
        .wrap('

')
      ;
    }
  );

  // INLINE FORMS
  //
  $('form.form-compact').each(function() {
    $(this)
      .attr('name', $(this).attr('id'))
      .addClass('form-inline')
    ;
  });
  $('form.form-compact input, form.form-compact select, form.form-compact textarea')  // eslint-disable-line max-len
    .not(excludedInputs)
    .each(function() {
      var id    = $(this).attr('id');
      var label = $(this).attr('data-label');

      $(this)
        .attr('name', id)
        .addClass('form-control')
        .wrap('

')
        .parent()
        .prepend(
          ''
          + label
          + ''
        )
      ;
    }
  );
  $('form.form-compact button').each(function() {
    $(this)
      .addClass('btn btn-default')
    ;
  });

  // Styled file inputs
  //

  // Single with probable submit button
  $('.fileupload-single input[type="file"]').each(function() {
    var widget = $(this).closest('.fileupload-single');
    var nameTag = widget.find('.file-name');
    var button = widget.find('button[type="submit"], input[type="submit"]');

    nameTag.hide();
    $(this).on('change', function() {
      nameTag
        .text($(this).val())
        .show()
      ;
      button
        .removeClass('disabled')
        .attr('disabled', false)
      ;
    });
  });

  // Multiple
  $('.fileupload-multiple input[type="file"]').each(function() {
    var wid = $(this).closest('.fileupload-multiple');
    var id = wid.attr('data-basename') + '_' + wid.attr('data-i');

    wid.find('.file-name, .filelabel-change').hide();
    wid.find('label').attr('for', id);
    $(this)
      .attr('name', id)
      .attr('id', id)
    ;

    $(this).on('change', function() {
      var widget = $(this).closest('.fileupload-multiple');
      var newWidget = widget.clone(true, true);
      var newInput = newWidget.find('input[type="file"]');
      var newId;

      newWidget.attr('data-i', parseInt(newWidget.attr('data-i'), 10) + 1);
      newId = newWidget.attr('data-basename')
        + '_'
        + newWidget.attr('data-i')
      ;
      newWidget.find('label').attr('for', newId);
      newInput
        .attr('name', newId)
        .attr('id', newId)
        .val(null)
      ;

      widget.find('.file-name')
        .text($(this).val())
        .show()
      ;
      widget.find('.filelabel-add, .filelabel-change').toggle();
      widget.after('
', newWidget);
    });
  });

  // Selectize some advanced selects
  //
  selectizeRender = {
    option_create: function(data, escape) {  // eslint-disable-line camelcase
      return '
+ '
        + escape(data.input)
        + '…
'
      ;
    }
  };
  $('select.advanced').selectize({
    plugins  : ['remove_button'],
    highlight: false
  });
  $('select.keywords').selectize({
    plugins     : ['remove_button'],
    highlight   : false,
    delimiter   : ';',
    create      : true,
    createOnBlur: true,
    openOnFocus : false,
    maxItems    : 6,
    // Work around default template including the English word "Add"
    render      : selectizeRender
  });

  /**
   * Clean up raw item into expected "user" structure
   *
   * Input item is expected to have 'text' and 'value' properties from which
   * 'name' and 'email' properties will be derived if 'email' is missing.
   * Conversely if 'email' is present but 'value' is not, then 'value' gets
   * the e-mail address.
   *
   * @param {Object} item Data
   *
   * @return {Object} Formatted item
   */
  function itemToUser(item) {
    var match;

    item.text = item.text.trim();
    if (item['email'] === undefined) {
      match = item.text.trim().match(regexNameEMail);
      if (match !== null) {
        item.email = match[2];
        item.name = match[1];
      } else {
        item.email = item.text;
        item.name = null;
      }
    }
    if (item['value'] === undefined
        || !Number.isInteger(Number(item['value']))
       ) {
      item.value = item.email;
    }
    return item;
  }
  selectizeRender['item'] = function(item, escape) {
    item = itemToUser(item);
    return '
'
      + (item.name ? '' + escape(item.name) + '' : '')
      + '' + escape(item.email) + ''
      + '
';
  };
  selectizeRender['option'] = function(item, escape) {
    var label;
    var caption;

    item = itemToUser(item);
    label = item.name || item.email;
    caption = item.name ? item.email : null;
    return '
'
      + '' + escape(label) + ''
      + (caption ? '' + escape(caption) + '' : '')
      + '
';
  };
  $('select.users').selectize({
    plugins  : ['remove_button'],
    highlight: false,
    persist  : false,
    render   : selectizeRender
  });

  // Creating users
  $('select.users-create').selectize({
    plugins     : ['remove_button'],
    highlight   : false,
    createOnBlur: true,
    persist     : false,
    render      : selectizeRender,
    createFilter: function(input) {
      return regexEMail.test(input) || input.match(regexNameEMail) !== null;
    },
    create: function(input) {
      var match = input.match(regexNameEMail);
      var opt = false;

      if (match !== null) {
        opt = {
          text : input,
          value: match[2],
          email: match[2],
          name : match[1]
        };
      }
      if (regexEMail.test(input)) {
        opt = {
          text : input,
          value: input,
          email: input,
          name : null
        };
      }

      return opt;
    },
    onOptionAdd: function(value, data) {
      var sel = this;
      var form = $('#user-modal form');

      // Not much works unless we let Selectize finish first.
      setTimeout(function() {
        form.find('input').val(null);
        form.find('select').prop('selectedIndex', 0);
        form.parsley().reset();

        $('#user-modal .modal-title .text').text(value);
        $('#user-modal input[name=email]').val(value);

        $('#user-modal').modal({
          backdrop: 'static',
          keyboard: false,
          show    : true
        });
        setTimeout(
          function() {
            form
              .find('input:visible, select:visible')
              .first()
              .focus();
          },
          350
        );

        $('#user-modal .modal-footer button').on('click', function() {
          var outform = $(sel.$wrapper).closest('form');
          var outbase = $('#user-modal').attr('data-append-base');
          var outkey  = $('#user-modal').attr('data-append-key');
          var outdata = {};

          if (form.parsley().validate()) {
            $(this).off('click');
            form.serializeArray().forEach(function(item) {
              outdata[item.name] = item.value;
            });
            outkey = outdata[outkey];

            data['name'] = outdata['name'];

            Object.keys(outdata).forEach(function(key) {
              outform.append(
                $('<input />')
                  .attr('type', 'hidden')
                  .attr('name', outbase + '[' + outkey + '][' + key + ']')
                  .attr('value', outdata[key])
              );
            });

            // Destroy the popover before its element disappears.
            // tag.popover('destroy');
            $('#user-modal').modal('hide');

            // Force a refresh of our items where refreshItems() won't.
            // Thanks to: https://github.com/selectize/selectize.js/issues/1162
            // sel.clearCache();
            sel.updateOption(value, sel.options[value]);

            // Work around strange bug which reopens the select after creation
            sel.close();
          }
        });
      });
    }
  });

  // Set parsley to found language instead of last loaded
  parsley.setLocale(lang);

  // Integrate Parsley with Twitter Bootstrap
  // Initially inspired by https://gist.github.com/askehansen/6809825
  // ...and http://jimmybonney.com/articles/parsley_js_twitter_bootstrap/
  // CAUTION: $.fn.parsley.defaults({...}) was IGNORED.
  $('form').parsley({
    // exclude :hidden for non-modal forms?
    excluded    : excludedInputs + ', [disabled]',
    successClass: 'has-success',
    errorClass  : 'has-error',
    classHandler: function(el) {
      // This differs from all examples I could find!
      return $(el.$element).closest('.form-group');
    },
    errorsContainer: function() {},
    errorsWrapper  : '',
    errorTemplate  : ''
  });

  // Initialize timeago.js
  new timeago().render($('.timeago'), lang);  // eslint-disable-line new-cap

  // Initialize Summernote
  $('.rich-edit').summernote({
    lang   : locale,
    toolbar: [
      ['style', ['style']],
      ['font', ['bold', 'underline', 'clear']],
      ['color', ['color']],
      // ['para', ['ul', 'ol', 'indent', 'outdent']],
      ['para', ['ul', 'ol']],
      ['insert', ['link']]
      // ['help', ['help']]
    ]
  });
});

<commit_msg>Configurable maximum for Selectize<commit_after>'use strict';

var $ = global.jQuery = require('jquery');
var parsley = require('parsleyjs');
var timeago = global.__timeago = require('timeago.js');
var selectizeRender = {};

require('bootstrap');
require('selectize');
require('summernote');

// Our main initializations, tolerate the long format
$().ready(function() {  // eslint-disable-line max-statements
  // Get language code from HTML tag
  // (Default is just in case we miss it.  It _should_ always be set.)
  var lang = $('html').attr('lang') || 'en';
  var locales = {
    ar: 'ar-AR',
    bg: 'bg-BG',
    ca: 'ca-ES',
    cs: 'cs-CZ',
    da: 'da-DK',
    de: 'de-DE',
    es: 'es-ES',
    fa: 'fa-IR',
    fi: 'fi-FI',
    fr: 'fr-FR',
    gl: 'gl-ES',
    he: 'he-IL',
    hr: 'hr-HR',
    hu: 'hu-HU',
    id: 'id-ID',
    it: 'it-IT',
    ja: 'ja-JP',
    ko: 'ko-KR',
    lt: 'lt-LT',
    nb: 'nb-NO',
    nl: 'nl-NL',
    pl: 'pl-PL',
    pt: 'pt-PT',
    ro: 'ro-RO',
    ru: 'ru-RU',
    sk: 'sk-SK',
    sl: 'sl-SI',
    sv: 'sv-SE',
    th: 'th-TH',
    tr: 'tr-TR',
    uk: 'uk-UA',
    vi: 'vi-VN',
    zh: 'zh-CN'
  };
  var locale = locales[lang];

  var excludedInputs = 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], .input-like input, .rich-edit';  // eslint-disable-line max-len

  // A valid e-mail for us has: nospaces, '@', nospaces, '.', nospaces
  // Actual RFC822 implementations are pages long and wouldn't benefit us much.
  var regexEMail = /^[^@ ]+@[^@ .]+\.[^@ ]+$/;
  var regexNameEMail = /^([^<]+)<([^@ ]+@[^@ .]+\.[^@ ]+)>$/;

  // Hide-away fields
  $('.hideaway-focus').on('focus', function() {
    $(this)
      .closest('.hideaway')
      .css({
        position: 'relative',
        left    : 0
      });
  });

  // Bootstrap-ize forms before enabling Parsley on them

  // LARGE FORMS
  //
  // leftright: labels on the left, one input/button per line, errors below
  // tight: labels and errors inside inputs, button on own line
  //
  $('form.form-leftright, form.form-tight').each(function() {
    $(this)
      .attr('name', $(this).attr('id'))
      .addClass('form-horizontal')
    ;
  });
  $('form.form-leftright > input, form.form-leftright > .btn-group, form.form-leftright > select, form.form-leftright > textarea, form.form-leftright > .input-like')  // eslint-disable-line max-len
    .not(excludedInputs)
    .each(function() {
      var id        = $(this).attr('id');
      var label     = $(this).attr('data-label');
      var fgClasses = '';
      var icon      = null;

      if ($(this).is('[class*="feedback-"]')) {
        fgClasses = ' has-feedback has-feedback-left';
        icon = $(this)
          .attr('class')
          .match(/\bfeedback-([a-zA-Z0-9_-]+)\b/)[1];
      }

      if (!$(this).hasClass('btn-group') && !$(this).hasClass('input-group')) {
        $(this).addClass('form-control');
      }

      $(this)
        .attr('name', id)
        .wrap('

')
        .parent()
        .prepend(
          ''
          + label
          + ''
        )
      ;
      $(this).wrap('

');
      if (icon) {
        $(this).after(
            ''
          );
      }
    }
  );
  $('form.form-tight input, form.form-tight select, form.form-tight textarea')
    .not(excludedInputs)
    .each(function() {
      var id      = $(this).attr('id');
      var label   = $(this).attr('data-label');
      var colsize = $(this).attr('data-colsize') || 6;
      var fgClasses = '';
      var icon      = null;

      if ($(this).is('[class*="feedback-"]')) {
        fgClasses = ' has-feedback has-feedback-left';
        icon = $(this)
          .attr('class')
          .match(/\bfeedback-([a-zA-Z0-9_-]+)\b/)[1];
      }

      $(this)
        .attr('name', id)
        .addClass('form-control')
        .wrap(
            '

'
          )
        .parent()
        .prepend('' + label + '')
      ;
      if (icon) {
        $(this).after(
            ''
          );
      }
    }
  );
  $('form.form-leftright button, form.form-tight button[type=submit]')
    .not('.input-like button, .form-group button')
    .each(function() {
      $(this)
        .addClass('btn btn-default')
        .wrap('

')
        .wrap('

')
      ;
    }
  );

  // INLINE FORMS
  //
  $('form.form-compact').each(function() {
    $(this)
      .attr('name', $(this).attr('id'))
      .addClass('form-inline')
    ;
  });
  $('form.form-compact input, form.form-compact select, form.form-compact textarea')  // eslint-disable-line max-len
    .not(excludedInputs)
    .each(function() {
      var id    = $(this).attr('id');
      var label = $(this).attr('data-label');

      $(this)
        .attr('name', id)
        .addClass('form-control')
        .wrap('

')
        .parent()
        .prepend(
          ''
          + label
          + ''
        )
      ;
    }
  );
  $('form.form-compact button').each(function() {
    $(this)
      .addClass('btn btn-default')
    ;
  });

  // Styled file inputs
  //

  // Single with probable submit button
  $('.fileupload-single input[type="file"]').each(function() {
    var widget = $(this).closest('.fileupload-single');
    var nameTag = widget.find('.file-name');
    var button = widget.find('button[type="submit"], input[type="submit"]');

    nameTag.hide();
    $(this).on('change', function() {
      nameTag
        .text($(this).val())
        .show()
      ;
      button
        .removeClass('disabled')
        .attr('disabled', false)
      ;
    });
  });

  // Multiple
  $('.fileupload-multiple input[type="file"]').each(function() {
    var wid = $(this).closest('.fileupload-multiple');
    var id = wid.attr('data-basename') + '_' + wid.attr('data-i');

    wid.find('.file-name, .filelabel-change').hide();
    wid.find('label').attr('for', id);
    $(this)
      .attr('name', id)
      .attr('id', id)
    ;

    $(this).on('change', function() {
      var widget = $(this).closest('.fileupload-multiple');
      var newWidget = widget.clone(true, true);
      var newInput = newWidget.find('input[type="file"]');
      var newId;

      newWidget.attr('data-i', parseInt(newWidget.attr('data-i'), 10) + 1);
      newId = newWidget.attr('data-basename')
        + '_'
        + newWidget.attr('data-i')
      ;
      newWidget.find('label').attr('for', newId);
      newInput
        .attr('name', newId)
        .attr('id', newId)
        .val(null)
      ;

      widget.find('.file-name')
        .text($(this).val())
        .show()
      ;
      widget.find('.filelabel-add, .filelabel-change').toggle();
      widget.after('
', newWidget);
    });
  });

  // Selectize some advanced selects
  //
  selectizeRender = {
    option_create: function(data, escape) {  // eslint-disable-line camelcase
      return '
+ '
        + escape(data.input)
        + '…
'
      ;
    }
  };
  $('select.advanced').selectize({
    plugins  : ['remove_button'],
    highlight: false
  });
  $('select.keywords').each(function() {
    var maxItems = $(this).attr('data-maxcount');

    $(this).selectize({
      plugins     : ['remove_button'],
      highlight   : false,
      delimiter   : ';',
      create      : true,
      createOnBlur: true,
      openOnFocus : false,
      maxItems    : maxItems,
      // Work around default template including the English word "Add"
      render      : selectizeRender
    });
  });

  /**
   * Clean up raw item into expected "user" structure
   *
   * Input item is expected to have 'text' and 'value' properties from which
   * 'name' and 'email' properties will be derived if 'email' is missing.
   * Conversely if 'email' is present but 'value' is not, then 'value' gets
   * the e-mail address.
   *
   * @param {Object} item Data
   *
   * @return {Object} Formatted item
   */
  function itemToUser(item) {
    var match;

    item.text = item.text.trim();
    if (item['email'] === undefined) {
      match = item.text.trim().match(regexNameEMail);
      if (match !== null) {
        item.email = match[2];
        item.name = match[1];
      } else {
        item.email = item.text;
        item.name = null;
      }
    }
    if (item['value'] === undefined
        || !Number.isInteger(Number(item['value']))
       ) {
      item.value = item.email;
    }
    return item;
  }
  selectizeRender['item'] = function(item, escape) {
    item = itemToUser(item);
    return '
'
      + (item.name ? '' + escape(item.name) + '' : '')
      + '' + escape(item.email) + ''
      + '
';
  };
  selectizeRender['option'] = function(item, escape) {
    var label;
    var caption;

    item = itemToUser(item);
    label = item.name || item.email;
    caption = item.name ? item.email : null;
    return '
'
      + '' + escape(label) + ''
      + (caption ? '' + escape(caption) + '' : '')
      + '
';
  };
  $('select.users').each(function() {
    var maxItems = $(this).attr('data-maxcount');

    if (maxItems === undefined) {
      maxItems = null;
    }
    $(this).selectize({
      plugins  : ['remove_button'],
      highlight: false,
      persist  : false,
      maxItems : maxItems,
      render   : selectizeRender
    });
  });

  // Creating users
  $('select.users-create').each(function() {
    var maxItems = $(this).attr('data-maxcount');

    if (maxItems === undefined) {
      maxItems = null;
    }
    $(this).selectize({
      plugins     : ['remove_button'],
      highlight   : false,
      createOnBlur: true,
      persist     : false,
      maxItems    : maxItems,
      render      : selectizeRender,
      createFilter: function(input) {
        return regexEMail.test(input) || input.match(regexNameEMail) !== null;
      },
      create: function(input) {
        var match = input.match(regexNameEMail);
        var opt = false;

        if (match !== null) {
          opt = {
            text : input,
            value: match[2],
            email: match[2],
            name : match[1]
          };
        }
        if (regexEMail.test(input)) {
          opt = {
            text : input,
            value: input,
            email: input,
            name : null
          };
        }

        return opt;
      },
      onOptionAdd: function(value, data) {
        var sel = this;
        var form = $('#user-modal form');

        // Not much works unless we let Selectize finish first.
        setTimeout(function() {
          form.find('input').val(null);
          form.find('select').prop('selectedIndex', 0);
          form.parsley().reset();

          $('#user-modal .modal-title .text').text(value);
          $('#user-modal input[name=email]').val(value);

          $('#user-modal').modal({
            backdrop: 'static',
            keyboard: false,
            show    : true
          });
          setTimeout(
            function() {
              form
                .find('input:visible, select:visible')
                .first()
                .focus();
            },
            350
          );

          $('#user-modal .modal-footer button').on('click', function() {
            var outform = $(sel.$wrapper).closest('form');
            var outbase = $('#user-modal').attr('data-append-base');
            var outkey  = $('#user-modal').attr('data-append-key');
            var outdata = {};

            if (form.parsley().validate()) {
              $(this).off('click');
              form.serializeArray().forEach(function(item) {
                outdata[item.name] = item.value;
              });
              outkey = outdata[outkey];

              data['name'] = outdata['name'];

              Object.keys(outdata).forEach(function(key) {
                outform.append(
                  $('<input />')
                    .attr('type', 'hidden')
                    .attr('name', outbase + '[' + outkey + '][' + key + ']')
                    .attr('value', outdata[key])
                );
              });

              // Destroy the popover before its element disappears.
              // tag.popover('destroy');
              $('#user-modal').modal('hide');

              // Force a refresh of our items where refreshItems() won't.
              // Thanks: https://github.com/selectize/selectize.js/issues/1162
              // sel.clearCache();
              sel.updateOption(value, sel.options[value]);

              // Work around strange bug which reopens the select after creation
              sel.close();
            }
          });
        });
      }
    });
  });

  // Set parsley to found language instead of last loaded
  parsley.setLocale(lang);

  // Integrate Parsley with Twitter Bootstrap
  // Initially inspired by https://gist.github.com/askehansen/6809825
  // ...and http://jimmybonney.com/articles/parsley_js_twitter_bootstrap/
  // CAUTION: $.fn.parsley.defaults({...}) was IGNORED.
  $('form').parsley({
    // exclude :hidden for non-modal forms?
    excluded    : excludedInputs + ', [disabled]',
    successClass: 'has-success',
    errorClass  : 'has-error',
    classHandler: function(el) {
      // This differs from all examples I could find!
      return $(el.$element).closest('.form-group');
    },
    errorsContainer: function() {},
    errorsWrapper  : '',
    errorTemplate  : ''
  });

  // Initialize timeago.js
  new timeago().render($('.timeago'), lang);  // eslint-disable-line new-cap

  // Initialize Summernote
  $('.rich-edit').summernote({
    lang   : locale,
    toolbar: [
      ['style', ['style']],
      ['font', ['bold', 'underline', 'clear']],
      ['color', ['color']],
      // ['para', ['ul', 'ol', 'indent', 'outdent']],
      ['para', ['ul', 'ol']],
      ['insert', ['link']]
      // ['help', ['help']]
    ]
  });
});

<|endoftext|>


<commit_before>'use strict';
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const historyApiFallback = require('connect-history-api-fallback');
const DEFAULT_OPTIONS = {
  server: {
    host: 'localhost',
    port: 3000,
    server: {
      baseDir: 'public'
    },
    watchOptions: {
      ignoreInitial: true,
      ignored: '*.map'
    },
    files: [
      '!**/*.map',
      'public/**/*'
    ]
  },
  historyApiFallback: false,
  file: {
    log: false
  }
};
module.exports = function(options = {}) {
  options = webpackMerge({},DEFAULT_OPTIONS,options);
  if (options.historyApiFallback) {
    options.server.middleware = options.server.middleware || [];
    options.server.middleware.push(historyApiFallback());
  }
  if (options.server.proxy) {
    delete options.server.server;
  }
  return {
    plugins: [
      new BrowserSyncPlugin(options.server,{reload: false})
    ]
  };
};<commit_msg>server.serverがstringのときにエラーになってしまうのを修正<commit_after>'use strict';
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const historyApiFallback = require('connect-history-api-fallback');
const DEFAULT_OPTIONS = {
  server: {
    host: 'localhost',
    port: 3000,
    server: {
      baseDir: 'public',
      middleware: []
    },
    watchOptions: {
      ignoreInitial: true,
      ignored: '*.map'
    },
    files: [
      '!**/*.map',
      'public/**/*'
    ]
  },
  historyApiFallback: false,
  file: {
    log: false
  }
};
module.exports = function(options = {}) {
  options = webpackMerge({},DEFAULT_OPTIONS,options);
  if (options.historyApiFallback) {
    if (typeof options.server === 'string') {
      options.server = {
        baseDir: options.server,
        middleware: []
      };
    }
    options.server.middleware = options.server.middleware || [];
    options.server.middleware.push(historyApiFallback());
  }
  if (options.server.proxy) {
    delete options.server.server;
  }
  return {
    plugins: [
      new BrowserSyncPlugin(options.server,{reload: false})
    ]
  };
};<|endoftext|>


<commit_before>/**
 * Copyright 2016 - 2022 SigScale Global Inc.
 * 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.
 */

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-fab/paper-fab.js';
import '@vaadin/vaadin-grid/theme/material/vaadin-grid.js';
import '@vaadin/vaadin-grid/vaadin-grid.js';
import '@vaadin/vaadin-grid/vaadin-grid-filter.js';
import '@polymer/iron-icons/iron-icons.js';
import './style-element.js'

class offerList extends PolymerElement {
	static get template() {
		return html`

			<vaadin-grid
					id="offerGrid"
					loading="{{loading}}"
					active-item="{{activeItem}}"
					theme="no-border">
				<vaadin-grid-column>
					<template class="header">
						<vaadin-grid-filter
								aria-label="name"
								path="id"
								value="{{_filterName}}">
							<input
									slot="filter"
									placeholder="Name"
									value="{{_filterName::input}}"
									focus-target>
						</vaadin-grid-filter>
					</template>
					<template>[[item.id]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Description
					</template>
					<template>[[item.description]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Start Date
					</template>
					<template>[[item.startDate]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							End Date
					</template>
					<template>[[item.endDate]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Status
					</template>
					<template>[[item.status]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Price
					</template>
					<template>[[item.price]]</template>
				</vaadin-grid-column>
			</vaadin-grid>

				<paper-fab
						icon="add"
						on-tap="showAddOfferModal">
				</paper-fab>

			<iron-ajax
					id="getProductOffersAjax"
					url="/catalogManagement/v2/productOffering"
					rejectWithRequest>
			</iron-ajax>
			<iron-ajax
					id="getPrefixTableAjax"
					url="/resourceInventoryManagement/v1/resource"
					on-response="_getPrefixTableResponse"
					on-error="_getPrefixTableError">
			</iron-ajax>
		`;
	}

	static get properties() {
		return {
			offers: {
				type: Array,
				readOnly: true,
				notify: true,
				value: function() {
					return []
				}
			},
			tables: {
				type: Array,
				readOnly: true,
				notify: true,
				value: function() {
					return []
				}
			},
			loading: {
				type: Boolean,
				notify: true
			},
			etag: {
				type: String,
				value: null
			},
			activeItem: {
				type: Object,
				notify: true
			},
			_filterName: {
				type: Boolean,
				observer: '_filterChanged'
			}
		}
	}

	ready() {
		super.ready();
		var grid = this.shadowRoot.getElementById('offerGrid');
		var ajax1 = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-list').shadowRoot.getElementById('getPrefixTableAjax');
		ajax1.params['resourceSpecification.id'] = '1';
		ajax1.generateRequest();
		grid.dataProvider = this.getOffers;
		grid.cellClassNameGenerator = this._cellClassNameGenerator;
	}

	_cellClassNameGenerator(column, model) {
		if(column !== undefined && model.item.entityClass !== undefined) {
			return model.item.entityClass;
		} else {
			return null;
		}
	}

	getOffers(params, callback) {
		var grid = this;
		if(!grid.size) {
			grid.size = 0;
		}
		var offerList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-list');
		var ajax = offerList.shadowRoot.getElementById("getProductOffersAjax");
		delete ajax.params['filter'];
		function checkHead(param) {
			return param.path == "id";
		}
		params.filters.filter(checkHead).forEach(function(filter) {
			if (filter.value) {
				ajax.params['filter'] = "\"[{id.like=[" + filter.value + "%";
			}
		});
		function checkChar(param) {
			return param.path != "id";
		}
		params.filters.filter(checkChar).forEach(function(filter) {
			if (filter.value) {
				if (!ajax.params['filter']) {
					ajax.params['filter'] = "\"[{";
				} else {
					ajax.params['filter'] += "],";
				}
				ajax.params['filter'] += "characteristic.contains=[{name=description" + ",value.like=[" + filter.value + "%]}";
			}
		});
		if (ajax.params['filter']) {
			ajax.params['filter'] += "]}]\"";
		}
		var handleAjaxResponse = function(request) {
			if (request) {
				offerList.etag = request.xhr.getResponseHeader('ETag');
				var range = request.xhr.getResponseHeader('Content-Range');
				var range1 = range.split("/");
				var range2 = range1[0].split("-");
				if (range1[1] != "*") {
					grid.size = Number(range1[1]);
				} else {
					grid.size = Number(range2[1]) + grid.pageSize * 2;
				}
				var vaadinItems = new Array();
				function checkChar(characteristic){
					return characteristic.name == "id";
				}
				for (var index in request.response) {
					var newRecord = new Object();
					offerList.push('offers', request.response[index].name);
					newRecord.id = request.response[index].name;
					newRecord.description = request.response[index].description;
					newRecord.productSpecification = request.response[index].productSpecification;
					if(request.response[index].validFor && request.response[index].validFor != "") {
						var date = new Date();
						var currentDate = date.toISOString();
						if(request.response[index].validFor.startDateTime
									&& request.response[index].validFor.startDateTime != ""){
							newRecord.startDate = request.response[index].validFor.startDateTime.split("T")[0];
							if(Date.parse(newRecord.startDate) > Date.parse(currentDate)) {
								newRecord.entityClass = "correctable";
							}
						}
						if(request.response[index].validFor.endDateTime
									&& request.response[index].validFor.endDateTime != ""){
							newRecord.endDate = request.response[index].validFor.endDateTime.split("T")[0];
							if(Date.parse(newRecord.endDate) < Date.parse(currentDate)) {
								newRecord.entityClass = "terminal";
							}
						}
					}
					if(request.response[index].lifecycleStatus) {
						newRecord.lifecycleStatus = request.response[index].lifecycleStatus;
						if(request.response[index].lifecycleStatus == "In Study" || request.response[index].lifecycleStatus == "In Design" || request.response[index].lifecycleStatus == "In Test") {
							newRecord.correctable = request.response[index].lifecycleStatus;
							if(newRecord.correctable) {
								newRecord.entityClass = "correctable";
							}
						}
						if(request.response[index].lifecycleStatus == "Rejected" || request.response[index].lifecycleStatus == "Retired" || request.response[index].lifecycleStatus == "Obsolete") {
							newRecord.terminal = request.response[index].lifecycleStatus;
							if(newRecord.terminal) {
								newRecord.entityClass = "terminal";
							}
						}
					}
					if(request.response[index].productOfferingPrice && request.response[index].productOfferingPrice != "")
					{
						function getNames(price) {
							return price.name;
						}
						newRecord.price = request.response[index].productOfferingPrice.map(getNames).join(", ");
						newRecord.prices = request.response[index].productOfferingPrice;
					}
					newRecord.bundledProductOffering = request.response[index].bundledProductOffering;
					newRecord.prodSpecCharValueUse = request.response[index].prodSpecCharValueUse;
					vaadinItems[index] = newRecord;
				}
				callback(vaadinItems);
			} else {
				grid.size = 0;
				callback([]);
			}
		};
		var handleAjaxError = function(error) {
			offerList.etag = null;
			var toast = document.body.querySelector('sig-app').shadowRoot.getElementById('restError');
			toast.text = "Error";
			toast.open();
			if(!grid.size) {
				grid.size = 0;
			}
			callback([]);
		}
		if(ajax.loading) {
			ajax.lastRequest.completes.then(function(request) {
				var startRange = params.page * params.pageSize + 1;
				var endRange = startRange + params.pageSize - 1;
				ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
				if (offerList.etag && params.page > 0) {
					ajax.headers['If-Range'] = offerList.etag;
				} else {
					delete ajax.headers['If-Range'];
				}
				return ajax.generateRequest().completes;
			}, handleAjaxError).then(handleAjaxResponse, handleAjaxError);
		} else {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (offerList.etag && params.page > 0) {
				ajax.headers['If-Range'] = offerList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			ajax.generateRequest().completes.then(handleAjaxResponse, handleAjaxError);
		}
	}

	_getPrefixTableResponse(event) {
		var grid = this.shadowRoot.getElementById('offerGrid');
		var results = event.detail.xhr.response;
		this.splice("tables", 0, this.tables.length)
		for (var indexTable in results) {
			var tableRecord = new Object();
			tableRecord.id = results[indexTable].id;
			tableRecord.href = results[indexTable].href;
			this.push('tables', tableRecord);
		}
	}

	_getPrefixTableError(event) {
		this.shadowRoot.getElementById('offerGrid').size = 0;
		cbProduct([]);
		if (!lastItem && event.detail.request.xhr.status != 416) {
			var toast = document.body.querySelector('sig-app').shadowRoot.getElementById('restError');
			toast.text = "Error";
			toast.open();
		}
	}

	_filterChanged(filter) {
		this.etag = null;
		var grid = this.shadowRoot.getElementById('offerGrid');
		grid.size = 0;
	}

	showAddOfferModal() {
		var offerList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-list');
		offerList.shadowRoot.getElementById("getProductOffersAjax").generateRequest();
		document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-add').shadowRoot.getElementById('addOfferModal').open();
	}
}

window.customElements.define('sig-offer-list', offerList);
<commit_msg>remove unused clause<commit_after>/**
 * Copyright 2016 - 2022 SigScale Global Inc.
 * 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.
 */

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-fab/paper-fab.js';
import '@vaadin/vaadin-grid/theme/material/vaadin-grid.js';
import '@vaadin/vaadin-grid/vaadin-grid.js';
import '@vaadin/vaadin-grid/vaadin-grid-filter.js';
import '@polymer/iron-icons/iron-icons.js';
import './style-element.js'

class offerList extends PolymerElement {
	static get template() {
		return html`

			<vaadin-grid
					id="offerGrid"
					loading="{{loading}}"
					active-item="{{activeItem}}"
					theme="no-border">
				<vaadin-grid-column>
					<template class="header">
						<vaadin-grid-filter
								aria-label="name"
								path="id"
								value="{{_filterName}}">
							<input
									slot="filter"
									placeholder="Name"
									value="{{_filterName::input}}"
									focus-target>
						</vaadin-grid-filter>
					</template>
					<template>[[item.id]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Description
					</template>
					<template>[[item.description]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Start Date
					</template>
					<template>[[item.startDate]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							End Date
					</template>
					<template>[[item.endDate]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Status
					</template>
					<template>[[item.status]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column>
					<template class="header">
							Price
					</template>
					<template>[[item.price]]</template>
				</vaadin-grid-column>
			</vaadin-grid>

				<paper-fab
						icon="add"
						on-tap="showAddOfferModal">
				</paper-fab>

			<iron-ajax
					id="getProductOffersAjax"
					url="/catalogManagement/v2/productOffering"
					rejectWithRequest>
			</iron-ajax>
			<iron-ajax
					id="getPrefixTableAjax"
					url="/resourceInventoryManagement/v1/resource"
					on-response="_getPrefixTableResponse"
					on-error="_getPrefixTableError">
			</iron-ajax>
		`;
	}

	static get properties() {
		return {
			offers: {
				type: Array,
				readOnly: true,
				notify: true,
				value: function() {
					return []
				}
			},
			tables: {
				type: Array,
				readOnly: true,
				notify: true,
				value: function() {
					return []
				}
			},
			loading: {
				type: Boolean,
				notify: true
			},
			etag: {
				type: String,
				value: null
			},
			activeItem: {
				type: Object,
				notify: true
			},
			_filterName: {
				type: Boolean,
				observer: '_filterChanged'
			}
		}
	}

	ready() {
		super.ready();
		var grid = this.shadowRoot.getElementById('offerGrid');
		var ajax1 = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-list').shadowRoot.getElementById('getPrefixTableAjax');
		ajax1.params['resourceSpecification.id'] = '1';
		ajax1.generateRequest();
		grid.dataProvider = this.getOffers;
		grid.cellClassNameGenerator = this._cellClassNameGenerator;
	}

	_cellClassNameGenerator(column, model) {
		if(column !== undefined && model.item.entityClass !== undefined) {
			return model.item.entityClass;
		} else {
			return null;
		}
	}

	getOffers(params, callback) {
		var grid = this;
		if(!grid.size) {
			grid.size = 0;
		}
		var offerList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-list');
		var ajax = offerList.shadowRoot.getElementById("getProductOffersAjax");
		delete ajax.params['filter'];
		function checkHead(param) {
			return param.path == "id";
		}
		params.filters.filter(checkHead).forEach(function(filter) {
			if (filter.value) {
				ajax.params['filter'] = "\"[{id.like=[" + filter.value + "%";
			}
		});
		function checkChar(param) {
			return param.path != "id";
		}
		params.filters.filter(checkChar).forEach(function(filter) {
			if (filter.value) {
				if (!ajax.params['filter']) {
					ajax.params['filter'] = "\"[{";
				} else {
					ajax.params['filter'] += "],";
				}
				ajax.params['filter'] += "characteristic.contains=[{name=description" + ",value.like=[" + filter.value + "%]}";
			}
		});
		if (ajax.params['filter']) {
			ajax.params['filter'] += "]}]\"";
		}
		var handleAjaxResponse = function(request) {
			if (request) {
				offerList.etag = request.xhr.getResponseHeader('ETag');
				var range = request.xhr.getResponseHeader('Content-Range');
				var range1 = range.split("/");
				var range2 = range1[0].split("-");
				if (range1[1] != "*") {
					grid.size = Number(range1[1]);
				} else {
					grid.size = Number(range2[1]) + grid.pageSize * 2;
				}
				var vaadinItems = new Array();
				function checkChar(characteristic){
					return characteristic.name == "id";
				}
				for (var index in request.response) {
					var newRecord = new Object();
					offerList.push('offers', request.response[index].name);
					newRecord.id = request.response[index].name;
					newRecord.description = request.response[index].description;
					newRecord.productSpecification = request.response[index].productSpecification;
					if(request.response[index].validFor && request.response[index].validFor != "") {
						var date = new Date();
						var currentDate = date.toISOString();
						if(request.response[index].validFor.startDateTime
									&& request.response[index].validFor.startDateTime != ""){
							newRecord.startDate = request.response[index].validFor.startDateTime.split("T")[0];
							if(Date.parse(newRecord.startDate) > Date.parse(currentDate)) {
								newRecord.entityClass = "correctable";
							}
						}
						if(request.response[index].validFor.endDateTime
									&& request.response[index].validFor.endDateTime != ""){
							newRecord.endDate = request.response[index].validFor.endDateTime.split("T")[0];
							if(Date.parse(newRecord.endDate) < Date.parse(currentDate)) {
								newRecord.entityClass = "terminal";
							}
						}
					}
					if(request.response[index].lifecycleStatus) {
						newRecord.lifecycleStatus = request.response[index].lifecycleStatus;
						if(request.response[index].lifecycleStatus == "In Study" || request.response[index].lifecycleStatus == "In Design" || request.response[index].lifecycleStatus == "In Test") {
							newRecord.correctable = request.response[index].lifecycleStatus;
							if(newRecord.correctable) {
								newRecord.entityClass = "correctable";
							}
						}
						if(request.response[index].lifecycleStatus == "Rejected" || request.response[index].lifecycleStatus == "Retired" || request.response[index].lifecycleStatus == "Obsolete") {
							newRecord.terminal = request.response[index].lifecycleStatus;
							if(newRecord.terminal) {
								newRecord.entityClass = "terminal";
							}
						}
					}
					if(request.response[index].productOfferingPrice && request.response[index].productOfferingPrice != "")
					{
						function getNames(price) {
							return price.name;
						}
						newRecord.price = request.response[index].productOfferingPrice.map(getNames).join(", ");
						newRecord.prices = request.response[index].productOfferingPrice;
					}
					newRecord.bundledProductOffering = request.response[index].bundledProductOffering;
					newRecord.prodSpecCharValueUse = request.response[index].prodSpecCharValueUse;
					vaadinItems[index] = newRecord;
				}
				callback(vaadinItems);
			} else {
				grid.size = 0;
				callback([]);
			}
		};
		var handleAjaxError = function(error) {
			offerList.etag = null;
			var toast = document.body.querySelector('sig-app').shadowRoot.getElementById('restError');
			toast.text = "Error";
			toast.open();
			if(!grid.size) {
				grid.size = 0;
			}
			callback([]);
		}
		if(ajax.loading) {
			ajax.lastRequest.completes.then(function(request) {
				var startRange = params.page * params.pageSize + 1;
				var endRange = startRange + params.pageSize - 1;
				ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
				if (offerList.etag && params.page > 0) {
					ajax.headers['If-Range'] = offerList.etag;
				} else {
					delete ajax.headers['If-Range'];
				}
				return ajax.generateRequest().completes;
			}, handleAjaxError).then(handleAjaxResponse, handleAjaxError);
		} else {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (offerList.etag && params.page > 0) {
				ajax.headers['If-Range'] = offerList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			ajax.generateRequest().completes.then(handleAjaxResponse, handleAjaxError);
		}
	}

	_getPrefixTableResponse(event) {
		var grid = this.shadowRoot.getElementById('offerGrid');
		var results = event.detail.xhr.response;
		this.splice("tables", 0, this.tables.length)
		for (var indexTable in results) {
			var tableRecord = new Object();
			tableRecord.id = results[indexTable].id;
			tableRecord.href = results[indexTable].href;
			this.push('tables', tableRecord);
		}
	}

	_getPrefixTableError(event) {
		this.shadowRoot.getElementById('offerGrid').size = 0;
		cbProduct([]);
		var toast = document.body.querySelector('sig-app').shadowRoot.getElementById('restError');
		toast.text = "Error";
		toast.open();
	}

	_filterChanged(filter) {
		this.etag = null;
		var grid = this.shadowRoot.getElementById('offerGrid');
		grid.size = 0;
	}

	showAddOfferModal() {
		var offerList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-list');
		offerList.shadowRoot.getElementById("getProductOffersAjax").generateRequest();
		document.body.querySelector('sig-app').shadowRoot.querySelector('sig-offer-add').shadowRoot.getElementById('addOfferModal').open();
	}
}

window.customElements.define('sig-offer-list', offerList);
<|endoftext|>


<commit_before>
/*!
 * Connect - HTTPServer
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , parse = require('url').parse
  , assert = require('assert')
  , statusCodes = http.STATUS_CODES;

// prototype

var app = module.exports = {};

// environment

var env = process.env.NODE_ENV || 'development';

/**
 * Utilize the given middleware `handle` to the given `route`,
 * defaulting to _/_. This "route" is the mount-point for the
 * middleware, when given a value other than _/_ the middleware
 * is only effective when that segment is present in the request's
 * pathname.
 *
 * For example if we were to mount a function at _/admin_, it would
 * be invoked on _/admin_, and _/admin/settings_, however it would
 * not be invoked for _/_, or _/posts_.
 *
 * This is effectively the same as passing middleware to `connect.createServer()`,
 * however provides a progressive api.
 *
 * Examples:
 *
 *      var server = connect.createServer();
 *      server.use(connect.favicon());
 *      server.use(connect.logger());
 *      server.use(connect.static(__dirname + '/public'));
 *
 * If we wanted to prefix static files with _/public_, we could
 * "mount" the `static()` middleware:
 *
 *      server.use('/public', connect.static(__dirname + '/public'));
 *
 * This api is chainable, meaning the following is valid:
 *
 *      connect.createServer()
 *        .use(connect.favicon())
 *        .use(connect.logger())
 *        .use(connect.static(__dirname + '/public'))
 *        .listen(3000);
 *
 * @param {String|Function} route or handle
 * @param {Function} handle
 * @return {Server}
 * @api public
 */

app.use = function(route, handle){
  this.route = '/';

  // default route to '/'
  if ('string' != typeof route) {
    handle = route;
    route = '/';
  }

  // wrap sub-apps
  if ('function' == typeof handle.handle) {
    var server = handle;
    handle.route = route;
    handle = function(req, res, next){
      server.handle(req, res, next);
    };
  }

  // wrap vanilla http.Servers
  if (handle instanceof http.Server) {
    handle = handle.listeners('request')[0];
  }

  // normalize route to not trail with slash
  if ('/' == route[route.length - 1]) {
    route = route.substr(0, route.length - 1);
  }

  // add the middleware
  this.stack.push({ route: route, handle: handle });

  // allow chaining
  return this;
};

/**
 * Handle server requests, punting them down
 * the middleware stack.
 *
 * @api private
 */

app.handle = function(req, res, out) {
  var writeHead = res.writeHead
    , stack = this.stack
    , called = []
    , removed = ''
    , index = 0;

  function next(err) {
    var layer, path, c;
    req.url = removed + req.url;
    req.originalUrl = req.originalUrl || req.url;
    removed = '';

    // fabricate error from {4,5}xx
    if ('number' == typeof err) {
      res.statusCode = err;
      err = new Error(statusCodes[err]);
    }

    layer = stack[index++];

    // callback used to track
    // and report double next()
    function callback(err) {
      if (~called.indexOf(layer.handle)) {
        reportDoubleNext(layer.handle);
      } else {
        called.push(layer.handle);
        next(err);
      }
    }

    // all done
    if (!layer) {
      // delegate to parent
      if (out) return out(err);

      if (err) {
        if ('test' != env) console.error(err.stack || err.toString());
        if (res.statusCode < 400) res.statusCode = 500;
        var body = statusCodes[res.statusCode];
        res.setHeader('Content-Type', 'text/plain');
        res.setHeader('Content-Length', body.length);
        res.end(body);
      } else {
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Cannot ' + req.method + ' ' + req.url);
      }
      return;
    }

    try {
      path = parse(req.url).pathname;
      if (undefined == path) path = '/';

      // skip this layer if the route doesn't match.
      if (0 != path.indexOf(layer.route)) return next(err);

      c = path[layer.route.length];
      if (c && '/' != c && '.' != c) return next(err);

      // Call the layer handler
      // Trim off the part of the url that matches the route
      removed = layer.route;
      req.url = req.url.substr(removed.length);

      // Ensure leading slash
      if ('/' != req.url[0]) req.url = '/' + req.url;

      var arity = layer.handle.length;
      if (err) {
        if (arity === 4) {
          layer.handle(err, req, res, callback);
        } else {
          next(err);
        }
      } else if (arity < 4) {
        layer.handle(req, res, callback);
      } else {
        next();
      }
    } catch (e) {
      if (e instanceof assert.AssertionError) {
        console.error(e.stack + '\n');
        next(e);
      } else {
        next(e);
      }
    }
  }
  next();
};

/**
 * Report that the given `fn` was invoked
 * more than once. This _is_ an error, and
 * should be fixed in your application, however
 * this logic prevents the user from seeing
 * how node handles it via more obscure
 * errors such as: "Error: Can't set headers after they are sent."
 *
 * @param {Function} fn
 * @api private
 */

function reportDoubleNext(fn) {
  process.stderr.write('Error: the following middleware invoked next() more than once: ');
  if (fn.name) {
    console.error(fn.name + '()');
  } else {
    console.error('\n\n' + fn.toString() + '\n');
  }
}
<commit_msg>port d0e61c900132595408359c22752c9be396dabc51 to 2.x<commit_after>
/*!
 * Connect - HTTPServer
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , parse = require('url').parse
  , assert = require('assert')
  , statusCodes = http.STATUS_CODES;

// prototype

var app = module.exports = {};

// environment

var env = process.env.NODE_ENV || 'development';

/**
 * Utilize the given middleware `handle` to the given `route`,
 * defaulting to _/_. This "route" is the mount-point for the
 * middleware, when given a value other than _/_ the middleware
 * is only effective when that segment is present in the request's
 * pathname.
 *
 * For example if we were to mount a function at _/admin_, it would
 * be invoked on _/admin_, and _/admin/settings_, however it would
 * not be invoked for _/_, or _/posts_.
 *
 * This is effectively the same as passing middleware to `connect.createServer()`,
 * however provides a progressive api.
 *
 * Examples:
 *
 *      var server = connect.createServer();
 *      server.use(connect.favicon());
 *      server.use(connect.logger());
 *      server.use(connect.static(__dirname + '/public'));
 *
 * If we wanted to prefix static files with _/public_, we could
 * "mount" the `static()` middleware:
 *
 *      server.use('/public', connect.static(__dirname + '/public'));
 *
 * This api is chainable, meaning the following is valid:
 *
 *      connect.createServer()
 *        .use(connect.favicon())
 *        .use(connect.logger())
 *        .use(connect.static(__dirname + '/public'))
 *        .listen(3000);
 *
 * @param {String|Function} route or handle
 * @param {Function} handle
 * @return {Server}
 * @api public
 */

app.use = function(route, handle){
  this.route = '/';

  // default route to '/'
  if ('string' != typeof route) {
    handle = route;
    route = '/';
  }

  // wrap sub-apps
  if ('function' == typeof handle.handle) {
    var server = handle;
    handle.route = route;
    handle = function(req, res, next){
      server.handle(req, res, next);
    };
  }

  // wrap vanilla http.Servers
  if (handle instanceof http.Server) {
    handle = handle.listeners('request')[0];
  }

  // normalize route to not trail with slash
  if ('/' == route[route.length - 1]) {
    route = route.substr(0, route.length - 1);
  }

  // add the middleware
  this.stack.push({ route: route, handle: handle });

  // allow chaining
  return this;
};

/**
 * Handle server requests, punting them down
 * the middleware stack.
 *
 * @api private
 */

app.handle = function(req, res, out) {
  var writeHead = res.writeHead
    , stack = this.stack
    , called = []
    , removed = ''
    , index = 0;

  function next(err) {
    var layer, path, c;
    req.url = removed + req.url;
    req.originalUrl = req.originalUrl || req.url;
    removed = '';

    // fabricate error from {4,5}xx
    if ('number' == typeof err) {
      res.statusCode = err;
      err = new Error(statusCodes[err]);
    }

    layer = stack[index++];

    // callback used to track
    // and report double next()
    function callback(err) {
      if (~called.indexOf(layer.handle)) {
        reportDoubleNext(layer.handle);
      } else {
        called.push(layer.handle);
        next(err);
      }
    }

    // all done
    if (!layer) {
      // delegate to parent
      if (out) return out(err);

      if (err) {
        if ('test' != env) console.error(err.stack || err.toString());
        if (res.headerSent) return res.socket.destroy();
        if (res.statusCode < 400) res.statusCode = 500;
        var body = statusCodes[res.statusCode];
        res.setHeader('Content-Type', 'text/plain');
        res.setHeader('Content-Length', body.length);
        res.end(body);
      } else {
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Cannot ' + req.method + ' ' + req.url);
      }
      return;
    }

    try {
      path = parse(req.url).pathname;
      if (undefined == path) path = '/';

      // skip this layer if the route doesn't match.
      if (0 != path.indexOf(layer.route)) return next(err);

      c = path[layer.route.length];
      if (c && '/' != c && '.' != c) return next(err);

      // Call the layer handler
      // Trim off the part of the url that matches the route
      removed = layer.route;
      req.url = req.url.substr(removed.length);

      // Ensure leading slash
      if ('/' != req.url[0]) req.url = '/' + req.url;

      var arity = layer.handle.length;
      if (err) {
        if (arity === 4) {
          layer.handle(err, req, res, callback);
        } else {
          next(err);
        }
      } else if (arity < 4) {
        layer.handle(req, res, callback);
      } else {
        next();
      }
    } catch (e) {
      if (e instanceof assert.AssertionError) {
        console.error(e.stack + '\n');
        next(e);
      } else {
        next(e);
      }
    }
  }
  next();
};

/**
 * Report that the given `fn` was invoked
 * more than once. This _is_ an error, and
 * should be fixed in your application, however
 * this logic prevents the user from seeing
 * how node handles it via more obscure
 * errors such as: "Error: Can't set headers after they are sent."
 *
 * @param {Function} fn
 * @api private
 */

function reportDoubleNext(fn) {
  process.stderr.write('Error: the following middleware invoked next() more than once: ');
  if (fn.name) {
    console.error(fn.name + '()');
  } else {
    console.error('\n\n' + fn.toString() + '\n');
  }
}
<|endoftext|>