<commit_before>/* global app:true */

var socket;
var currenttime;
var username='noname';

var width = 720,
	height = 1050,
	cellWidth = 80,
	cellHeight = 50, // cell size
	gapWidth = 12;
	gapHeight = 6;

var hour = d3.time.format("%I"),
	minute = d3.time.format("%M"),
	month = d3.time.format("%b"),
	weekday = d3.time.format("%a"),
	date = d3.time.format("%d"),
	ampm = d3.time.format("%p"),
	format = d3.time.format("%b/%d %H:%M%p");

(function() {
  'use strict';

	var myClock;

	function myTimer(){
		socket.emit('lookclock');
	}

  var blockdata = [];
  var clockbar = $('#clock_bar');

  var callBlocks = function(ticket){
	// +- 1 hour blocks range
	var beginT = d3.time.hour.floor(ticket);
	beginT = d3.time.hour.offset(beginT, -1);
	var endT = d3.time.hour.offset(beginT, 3);

	socket.emit('timeline', { type: 'callblocks', user:username, begintime: beginT, endtime: endT});
  }

  var draw = function(blockdata){
    d3.select("svg")
       .remove();
	var tip = d3.tip()
		.attr('class', 'd3-tip')
		.direction('e')
		.offset([0,10])
		.html(function(d) {
			return "time: "+d.time;
		});

	var svg = d3.select("#d3Area").append("svg")
		.attr("width", width)
		.attr("height", height)
		.append("g")
		.attr("transform", "translate(24, 24)");

	svg.call(tip);

	var block = svg.selectAll(".block")
		.data(blockdata)
	.enter().append("g")
		.attr("class", "block")
		.attr("transform", function (d,i)
		{
			//var dx = (i-i%12)/12*(cellWidth+gapWidth);
			var dx = 0;
			//var dy =  i%12 * (cellHeight+gapHeight);
			var dy = i * (cellHeight+gapHeight);
			return "translate(" + dx + ","+ dy + ")";
		})
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);

	block.append("rect")
		.attr("class", function (d)
		{
			if (d.lock==1){
				class_name="block-locked";
			}else{
				if (d.current==1){
					class_name="block-current";
				}else{
					var class_name="block-default";
				}
			}
			return class_name;
		})
		.attr("width", cellWidth)
		.attr("height", cellHeight)
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide)
		.on('click', mouseclick);

	block.append("text")
		.attr("class", "block-name")
		.attr("x",cellWidth/2)
		.attr("y",cellHeight/2)
		.attr("dy", ".3em")
		.style("text-anchor", "middle")
		.text(function(d) {
			var h = d.time.getHours();
			var ampm = (h<12 ? "AM":"PM");
			//h=("0" + h%12).slice(-2);
			h=(h%12);
			if(h==0){h="12";}
			var m = d.time.getMinutes();
			m=("0" + m).slice(-2);
			return h+":"+m+" "+ampm;
		})
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);
  }

  function mouseclick(d){
  	console.log(this);
  	d3.selectAll(".block rect").transition().duration(1000)
  		.attr("width", cellWidth);
  	d3.select(this).transition().duration(1000)
        .attr("width", cellWidth*2);
  }

  socket = io.connect('http://171.65.102.132:3006');

  socket.on('postblocks', function(data){
  	blockdata = [];
  	var num_ele = 9;
	for (var i=0;i<=data.length/num_ele;i++){
		var block = new Object();
		block.id = i;

		var d = new Date(0);
		d.setTime(data[i*num_ele]);
		block.time = d;

		block.lock = data[i*num_ele+1];
		block.user_id = data[i*num_ele+2];
		block.exp_id = data[i*num_ele+3];
		block.pattern_id = data[i*num_ele+4];
		block.past = data[i*num_ele+5];
		block.admin = data[i*num_ele+6];
		block.current = data[i*num_ele+7];
		block.image = data[i*num_ele+8];

		blockdata.push(block);
	}
	blockdata.length = blockdata.length-2;
	console.dir(blockdata);
	draw(blockdata);
  });

  socket.on('server_clock', function(data){
  	//console.log(data);
  	clockbar.html(""+data+"");
  });

  socket.on('message', function(msg){
	console.log(msg);
  });

  socket.on('connect', function() {
	console.log("Connected!");
	currenttime = new Date();
	callBlocks(currenttime);
	myClock=setInterval(function(){myTimer()},500);
  });

  socket.on('disconnect', function() {
	console.log('disconnected');
  });

  app = app || {};

  app.Blocks = Backbone.Model.extend({
    url: '/account/timeline/',
    defaults: {
      username: '',
      timestamp: ''
    }
  });

  app.BlocksView = Backbone.View.extend({
    el: '#blocks_nav',
    template: _.template( $('#tmpl-blocks_nav').html() ),
    events: {
      'click .btn-prev': 'reqPrev',
      'click .btn-now': 'reqNow',
      'click .btn-next': 'reqNext'
    },
    initialize: function() {
      this.model = new app.Blocks();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes));
    },
    reqPrev: function() {
      currenttime.setHours(currenttime.getHours() - 1);
      callBlocks(currenttime);
    },
    reqNow: function() {
      currenttime = new Date();
      callBlocks(currenttime);
    },
    reqNext: function() {
      currenttime.setHours(currenttime.getHours() + 1);
      callBlocks(currenttime);
    }
  });

  $(document).ready(function() {
    app.blocksView = new app.BlocksView();
  });

}());
<commit_msg>timeblock display<commit_after>/* global app:true */

var socket;
var currenttime;
var username='noname';

var width = 720,
	height = 1050,
	cellWidth = 80,
	cellHeight = 50, // cell size
	gapWidth = 12;
	gapHeight = 6;

var hour = d3.time.format("%I"),
	minute = d3.time.format("%M"),
	month = d3.time.format("%b"),
	weekday = d3.time.format("%a"),
	date = d3.time.format("%d"),
	ampm = d3.time.format("%p"),
	format = d3.time.format("%b/%d %H:%M%p");

(function() {
  'use strict';

	var myClock;

	function myTimer(){
		socket.emit('lookclock');
	}

  var blockdata = [];
  var clockbar = $('#clock_bar');

  var callBlocks = function(ticket){
	// +- 1 hour blocks range
	var beginT = d3.time.hour.floor(ticket);
	beginT = d3.time.minute.offset(beginT, -30);
	var endT = d3.time.minute.offset(beginT, 30);

	socket.emit('timeline', { type: 'callblocks', user:username, begintime: beginT, endtime: endT});
  }

  var draw = function(blockdata){
    d3.select("svg")
       .remove();
	var tip = d3.tip()
		.attr('class', 'd3-tip')
		.direction('e')
		.offset([0,10])
		.html(function(d) {
			return "time: "+d.time;
		});

	var svg = d3.select("#d3Area").append("svg")
		.attr("width", width)
		.attr("height", height)
		.append("g")
		.attr("transform", "translate(24, 24)");

	svg.call(tip);

	var block = svg.selectAll(".block")
		.data(blockdata)
	.enter().append("g")
		.attr("class", "block")
		.attr("transform", function (d,i)
		{
			//var dx = (i-i%12)/12*(cellWidth+gapWidth);
			var dx = 0;
			//var dy =  i%12 * (cellHeight+gapHeight);
			var dy = i * (cellHeight+gapHeight);
			return "translate(" + dx + ","+ dy + ")";
		})
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);

	block.append("rect")
		.attr("class", function (d)
		{
			if (d.lock==1){
				class_name="block-locked";
			}else{
				if (d.current==1){
					class_name="block-current";
				}else{
					var class_name="block-default";
				}
			}
			return class_name;
		})
		.attr("width", cellWidth)
		.attr("height", cellHeight)
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide)
		.on('click', mouseclick);

	block.append("text")
		.attr("class", "block-name")
		.attr("x",cellWidth/2)
		.attr("y",cellHeight/2)
		.attr("dy", ".3em")
		.style("text-anchor", "middle")
		.text(function(d) {
			var h = d.time.getHours();
			var ampm = (h<12 ? "AM":"PM");
			//h=("0" + h%12).slice(-2);
			h=(h%12);
			if(h==0){h="12";}
			var m = d.time.getMinutes();
			m=("0" + m).slice(-2);
			return h+":"+m+" "+ampm;
		})
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);
  }

  function mouseclick(d){
  	console.log(this);
  	d3.selectAll(".block rect").transition().duration(1000)
  		.attr("width", cellWidth);
  	d3.select(this).transition().duration(1000)
        .attr("width", cellWidth*2);
  }

  socket = io.connect('http://171.65.102.132:3006');

  socket.on('postblocks', function(data){
  	blockdata = [];
  	var num_ele = 9;
	for (var i=0;i<=data.length/num_ele;i++){
		var block = new Object();
		block.id = i;

		var d = new Date(0);
		d.setTime(data[i*num_ele]);
		block.time = d;

		block.lock = data[i*num_ele+1];
		block.user_id = data[i*num_ele+2];
		block.exp_id = data[i*num_ele+3];
		block.pattern_id = data[i*num_ele+4];
		block.past = data[i*num_ele+5];
		block.admin = data[i*num_ele+6];
		block.current = data[i*num_ele+7];
		block.image = data[i*num_ele+8];

		blockdata.push(block);
	}
	blockdata.length = blockdata.length-2;
	console.dir(blockdata);
	draw(blockdata);
  });

  socket.on('server_clock', function(data){
  	//console.log(data);
  	clockbar.html(""+data+"");
  });

  socket.on('message', function(msg){
	console.log(msg);
  });

  socket.on('connect', function() {
	console.log("Connected!");
	currenttime = new Date();
	callBlocks(currenttime);
	myClock=setInterval(function(){myTimer()},500);
  });

  socket.on('disconnect', function() {
	console.log('disconnected');
  });

  app = app || {};

  app.Blocks = Backbone.Model.extend({
    url: '/account/timeline/',
    defaults: {
      username: '',
      timestamp: ''
    }
  });

  app.BlocksView = Backbone.View.extend({
    el: '#blocks_nav',
    template: _.template( $('#tmpl-blocks_nav').html() ),
    events: {
      'click .btn-prev': 'reqPrev',
      'click .btn-now': 'reqNow',
      'click .btn-next': 'reqNext'
    },
    initialize: function() {
      this.model = new app.Blocks();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes));
    },
    reqPrev: function() {
      currenttime.setHours(currenttime.getHours() - 1);
      callBlocks(currenttime);
    },
    reqNow: function() {
      currenttime = new Date();
      callBlocks(currenttime);
    },
    reqNext: function() {
      currenttime.setHours(currenttime.getHours() + 1);
      callBlocks(currenttime);
    }
  });

  $(document).ready(function() {
    app.blocksView = new app.BlocksView();
  });

}());
<|endoftext|>


<commit_before>/*global jQuery psc window */
psc.namespace("subject");

(function ($) {
  psc.subject.ScheduleList = (function () {
    function zeropad(i) {
      if (i < 10) {
        return "0" + i;
      } else {
        return "" + i;
      }
    }

    function dateKey(date) {
      return date.getUTCFullYear() + "-" +
        zeropad(date.getUTCMonth() + 1) + "-" +
        zeropad(date.getUTCDate());
    }

    function scheduleReady() {
      var schedule = psc.subject.ScheduleData.current();

      if (null !== schedule) {
        var container = $('#scheduled-activities').empty()
        jQuery.each(schedule.allDays(), function (i, day) {
          var key = dateKey(day);
          var activities =
            (schedule.days && schedule.days[key] && schedule.days[key].activities)
          if (psc.subject.isToday(day) && !activities) {
            container.append("

");
          }
          if (activities) {
            var items = $.map(activities, function (sa) {
              return resigTemplate('list_day_sa_entry', sa)
            }).join('\n');
            container.append(
              resigTemplate('list_day_entry', {
                dateClass: activities[0].dateClasses(),
                isToday: activities[0].isToday(),
                scheduledActivities: activities,
                displayDate: key,
                scheduledActivityListItems: items
              })
            )
            $(container.find("div.day:last-child")[0]).data("date", day)
          }
        })
        psc.subject.ScheduleList.FocusHandler.init()
      }

      $('#schedule-error').hide()
      $('.loading').fadeOut().hide();
    }

    function scheduleError(evt, message) {
      $('#schedule-error').empty().
        append("Problem loading schedule data: " + message).show();
      $('.loading').fadeOut();
    }

    return {
      init: function () {
        $('#schedule').bind('schedule-load-start', function () {
          $('.loading').fadeIn();
        });
        $('#schedule').bind('schedule-ready', scheduleReady);
        $('#schedule').bind('schedule-error', scheduleError);
      },

      FocusHandler: (function () {
        var SOURCE_NAME = "list";
        var hoverUpdating = false, manualScrolling = false;
        var programaticallyScrolling = false;

        var hoverAnimator = new psc.tools.AsyncUpdater(function (dateStr) {
          $('#scheduled-activities .day').removeClass('hover-date');
          if (dateStr) {
            $('#scheduled-activities .date-' + dateStr).addClass('hover-date');
          }
        });

        var focusAnimator = new psc.tools.AsyncUpdater(function (data) {
          var scrollTo = determineOffsetToDate(data.date, data.range);
          if (scrollTo) {
            programaticallyScrolling = true;
            $('#schedule').scrollTop(scrollTo);
            programaticallyScrolling = false;
          }
        }, function (v) {
          return v === null ? null : v.date.getTime();
        });

        function extractDate(classes) {
          var bits = classes.match(/date-(\d{4})-(\d{1,2})-(\d{1,2})/);
          return new Date(Date.UTC(bits[1], bits[2] - 1, bits[3], 12, 0, 0, 0));
        }

        function hoverOverDay(evt) {
          psc.subject.ScheduleData.hoverDate(extractDate(this.className), SOURCE_NAME)
        }

        function hoverOutDay() {
          psc.subject.ScheduleData.hoverDate(null, SOURCE_NAME)
        }

        function hoverEvent(evt, triggerData) {
          if (triggerData.date) {
            hoverAnimator.update(dateKey(triggerData.date));
          } else {
            hoverAnimator.update(null);
          }
        }

        function determineOffsetToDate(date, range) {
          var offset;
          if (psc.subject.isToday(date)) {
            var todayElts = $('#schedule-today-marker, #scheduled-activities .today');
            if (todayElts.length > 0) {
              offset = todayElts.position().top;
            }
          } else {
            var nextVisibleBlock;
            $('#scheduled-activities > .day').each(function (i, dayBlock) {
              if (date < $(dayBlock).data('date')) {
                nextVisibleBlock = $(dayBlock);
                return false;
              }
            });
            // only shift the list if the next visible activity in the list
            // is actually visible on the timeline (avoids nasty feedback)
            if (nextVisibleBlock && range.includes(nextVisibleBlock.data('date'))) {
              offset = nextVisibleBlock.position().top;
            } else {
              offset = 0;
            }
          }

          if (offset !== undefined) {
            return offset + $('#schedule').scrollTop();
          } else {
            return $('#scheduled-activities').height();
          }
        }

        function visibleRange() {
          var min, max;
          var scheduleBlockHeight = $('#schedule').height();
          $('#scheduled-activities > .day').each(function (i, dayBlock) {
            var header = $(dayBlock).find("h3");
            if (!min && ($(dayBlock).position().top + header.position().top + header.height() > 0)) {
              min = $(dayBlock).data('date');
            } else if ($(dayBlock).position().top + $(dayBlock).height() > scheduleBlockHeight) {
              max = $(dayBlock).data('date');
            }
            if (min && max) {
              return false;
            }
          })
          if (!max) {
            max = $('#scheduled-activities > .day:last-child').data('date');
          }
          if (min && max) {
            return new psc.tools.Range(min, max);
          } else {
            return null;
          }
        }

        function fireFocusChanged(evt) {
          if (!programaticallyScrolling) {
            var span = visibleRange();
            psc.subject.ScheduleData.focusDate(span.start, SOURCE_NAME, span);
          }
        }

        function scrollToFocusDate(evt, triggerData) {
          if (triggerData.source !== SOURCE_NAME) {
            focusAnimator.update(triggerData);
          }
        }

        return {
          init: function () {
            $('#scheduled-activities > .day').mouseover(hoverOverDay).mouseout(hoverOutDay);
            $('#schedule').scroll(fireFocusChanged)

            $('#schedule').bind('hover-date-changed', hoverEvent)
            $('#schedule').bind('focus-date-changed', scrollToFocusDate)
          }
        }
      }())
    };
  }());
}(jQuery));<commit_msg>Delinting<commit_after>/*global jQuery psc window resigTemplate */
psc.namespace("subject");

(function ($) {
  psc.subject.ScheduleList = (function () {
    function zeropad(i) {
      if (i < 10) {
        return "0" + i;
      } else {
        return "" + i;
      }
    }

    function dateKey(date) {
      return date.getUTCFullYear() + "-" +
        zeropad(date.getUTCMonth() + 1) + "-" +
        zeropad(date.getUTCDate());
    }

    function scheduleReady() {
      var schedule = psc.subject.ScheduleData.current();

      if (null !== schedule) {
        var container = $('#scheduled-activities').empty();
        jQuery.each(schedule.allDays(), function (i, day) {
          var key = dateKey(day);
          var activities =
            (schedule.days && schedule.days[key] && schedule.days[key].activities);
          if (psc.subject.isToday(day) && !activities) {
            container.append("

");
          }
          if (activities) {
            var items = $.map(activities, function (sa) {
              return resigTemplate('list_day_sa_entry', sa);
            }).join('\n');
            container.append(
              resigTemplate('list_day_entry', {
                dateClass: activities[0].dateClasses(),
                isToday: activities[0].isToday(),
                scheduledActivities: activities,
                displayDate: key,
                scheduledActivityListItems: items
              })
            );
            $(container.find("div.day:last-child")[0]).data("date", day);
          }
        });
        psc.subject.ScheduleList.FocusHandler.init();
      }

      $('#schedule-error').hide();
      $('.loading').fadeOut().hide();
    }

    function scheduleError(evt, message) {
      $('#schedule-error').empty().
        append("Problem loading schedule data: " + message).show();
      $('.loading').fadeOut();
    }

    return {
      init: function () {
        $('#schedule').bind('schedule-load-start', function () {
          $('.loading').fadeIn();
        });
        $('#schedule').bind('schedule-ready', scheduleReady);
        $('#schedule').bind('schedule-error', scheduleError);
      },

      FocusHandler: (function () {
        var SOURCE_NAME = "list";
        var hoverUpdating = false, manualScrolling = false;
        var programaticallyScrolling = false;

        var hoverAnimator = new psc.tools.AsyncUpdater(function (dateStr) {
          $('#scheduled-activities .day').removeClass('hover-date');
          if (dateStr) {
            $('#scheduled-activities .date-' + dateStr).addClass('hover-date');
          }
        });

        var focusAnimator = new psc.tools.AsyncUpdater(function (data) {
          var scrollTo = determineOffsetToDate(data.date, data.range);
          if (scrollTo) {
            programaticallyScrolling = true;
            $('#schedule').scrollTop(scrollTo);
            programaticallyScrolling = false;
          }
        }, function (v) {
          return v === null ? null : v.date.getTime();
        });

        function extractDate(classes) {
          var bits = classes.match(/date-(\d{4})-(\d{1,2})-(\d{1,2})/);
          return new Date(Date.UTC(bits[1], bits[2] - 1, bits[3], 12, 0, 0, 0));
        }

        function hoverOverDay(evt) {
          psc.subject.ScheduleData.hoverDate(
            extractDate(this.className), SOURCE_NAME);
        }

        function hoverOutDay() {
          psc.subject.ScheduleData.hoverDate(null, SOURCE_NAME);
        }

        function hoverEvent(evt, triggerData) {
          if (triggerData.date) {
            hoverAnimator.update(dateKey(triggerData.date));
          } else {
            hoverAnimator.update(null);
          }
        }

        function determineOffsetToDate(date, range) {
          var offset;
          if (psc.subject.isToday(date)) {
            var todayElts = $('#schedule-today-marker, #scheduled-activities .today');
            if (todayElts.length > 0) {
              offset = todayElts.position().top;
            }
          } else {
            var nextVisibleBlock;
            $('#scheduled-activities > .day').each(function (i, dayBlock) {
              if (date < $(dayBlock).data('date')) {
                nextVisibleBlock = $(dayBlock);
                return false;
              }
            });
            // only shift the list if the next visible activity in the list
            // is actually visible on the timeline (avoids nasty feedback)
            if (nextVisibleBlock && range.includes(nextVisibleBlock.data('date'))) {
              offset = nextVisibleBlock.position().top;
            } else {
              offset = 0;
            }
          }

          if (offset !== undefined) {
            return offset + $('#schedule').scrollTop();
          } else {
            return $('#scheduled-activities').height();
          }
        }

        function visibleRange() {
          var min, max;
          var scheduleBlockHeight = $('#schedule').height();
          $('#scheduled-activities > .day').each(function (i, dayBlock) {
            var header = $(dayBlock).find("h3");
            if (!min && ($(dayBlock).position().top + header.position().top + header.height() > 0)) {
              min = $(dayBlock).data('date');
            } else if ($(dayBlock).position().top + $(dayBlock).height() > scheduleBlockHeight) {
              max = $(dayBlock).data('date');
            }
            if (min && max) {
              return false;
            }
          });
          if (!max) {
            max = $('#scheduled-activities > .day:last-child').data('date');
          }
          if (min && max) {
            return new psc.tools.Range(min, max);
          } else {
            return null;
          }
        }

        function fireFocusChanged(evt) {
          if (!programaticallyScrolling) {
            var span = visibleRange();
            psc.subject.ScheduleData.focusDate(span.start, SOURCE_NAME, span);
          }
        }

        function scrollToFocusDate(evt, triggerData) {
          if (triggerData.source !== SOURCE_NAME) {
            focusAnimator.update(triggerData);
          }
        }

        return {
          init: function () {
            $('#scheduled-activities > .day').mouseover(hoverOverDay).mouseout(hoverOutDay);
            $('#schedule').scroll(fireFocusChanged);

            $('#schedule').bind('hover-date-changed', hoverEvent);
            $('#schedule').bind('focus-date-changed', scrollToFocusDate);
          }
        };
      }())
    };
  }());
}(jQuery));<|endoftext|>


<commit_before>/*
	A simple, lightweight jQuery plugin for creating sortable tables.
	https://github.com/kylefox/jquery-tablesort
	Version 0.0.2
*/
$(function(){var a=window.jQuery;a.tablesort=function(d,c){var e=this;this.$table=d;this.$thead=this.$table.find("thead");this.settings=a.extend({},a.tablesort.defaults,c);this.$table.find("th").bind("click.tablesort",function(){e.sort(a(this))});this.direction=this.$th=this.index=null};a.tablesort.prototype={sort:function(d,c){var e=new Date,b=this,g=this.$table,n=0<this.$thead.length?g.find("tbody tr"):g.find("tr").has("td"),m=g.find("tr td:nth-of-type("+(d.index()+1)+")"),h=d.data().sortBy,k=[],
l=m.map(function(c,e){return h?"function"===typeof h?h(a(d),a(e),b):h:null!=a(this).data().sortValue?a(this).data().sortValue:a(this).text()});if(0!==l.length){b.$table.find("th").removeClass(b.settings.asc+" "+b.settings.desc);this.direction="asc"!==c&&"desc"!==c?"asc"===this.direction?"desc":"asc":c;c="asc"==this.direction?1:-1;b.$table.trigger("tablesort:start",[b]);b.log("Sorting by "+this.index+" "+this.direction);for(var f=0,p=l.length;f<p;f++)k.push({index:f,cell:m[f],row:n[f],value:l[f]});
k.sort(function(a,b){return a.value>b.value?1*c:a.value<b.value?-1*c:0});a.each(k,function(a,b){g.append(b.row)});d.addClass(b.settings[b.direction]);b.log("Sort finished in "+((new Date).getTime()-e.getTime())+"ms");b.$table.trigger("tablesort:complete",[b])}},log:function(d){(a.tablesort.DEBUG||this.settings.debug)&&console&&console.log&&console.log("[tablesort] "+d)},destroy:function(){this.$table.find("th").unbind("click.tablesort");this.$table.data("tablesort",null);return null}};a.tablesort.DEBUG=
!1;a.tablesort.defaults={debug:a.tablesort.DEBUG,asc:"sorted ascending",desc:"sorted descending"};a.fn.tablesort=function(d){var c,e;return this.each(function(){c=a(this);(e=c.data("tablesort"))&&e.destroy();c.data("tablesort",new a.tablesort(c,d))})}});
<commit_msg>Removed jquery-tablesort (tablesort.min.js) as the project is now using jquery-tablesorter instead<commit_after><|endoftext|>


<commit_before>try {
  window;
} catch(e) {
  var BUTTONS = require('./input');
}

function Character(team, spawnPoint) {
  this.breakingCoefficient = 0.025;
  this.accelerationCoefficient = 0.012;
  this.bodyRadius = 0.6;
  this.MAX_HP = 10;
  this.team = team;
  this.onCP = false;
  this.kills = 0;
  this.deaths = 0;
  this.init(spawnPoint);
}

Character.MAX_SHIELD_ARC = 0.2 * Math.PI;
Character.OVERHEAT_THRESHOLD = 1.5;

Character.prototype.init = function(spawnPoint) {
  if (spawnPoint) {
    this.x = spawnPoint.x;
    this.y = spawnPoint.y;
    this.timeDied = null;
  } else {
    this.x = 32;
    this.y = 32;
    this.timeDied = +new Date();
  }

  this.dx = 0;
  this.dy = 0;
  this.hp = this.MAX_HP;
  this.isShieldActive = false;
  this.fireCooldown = 0;
  this.shieldEnergy = 1;
  this.weaponHeat = 0;
  this.overheated = false;
  this.points = 0;
  this.respawnTime = 4000;
};

Character.prototype.getState = function() {
  return {
    t: 'C',
    x: this.x,
    y: this.y,
    hp: this.hp,
    kills: this.kills,
    deaths: this.deaths,
    respawnTime: this.respawnTime,
    mouseDirection: this.mouseDirection,
    isShieldActive: this.isShieldActive,
    shieldEnergy: this.shieldEnergy,
    team: this.team,
    weaponHeat: this.weaponHeat,
    overheated: this.overheated,
    timeDied: this.timeDied
  };
};

Character.prototype.hit = function(bullet, soundsToPlay) {
  if (bullet.team == this.team){
    return;
  }

  if (this.canShieldTakeBullet(bullet)) {
    this.shieldEnergy -= 0.45;
    var shieldSoundIndex = Math.floor(3 * Math.random()) + 1;
    soundsToPlay['shield-hit-' + shieldSoundIndex + '.mp3'] = true;
  } else {
    this.dx += bullet.dx;
    this.dy += bullet.dy;

    this.hp --;
    if (this.hp <= 0){
      this.deaths++;
      if(bullet.character){
        bullet.character.killed(this);
      }
      this.die();
    }
  }
};

Character.prototype.killed = function(enemy){
  //YEEY
  this.kills++;
};

Character.prototype.die = function(){
  this.hp = 0;
  this.timeDied = +new Date();
  this.respawnTime = 1000 + this.points * 0.3;
};

Character.prototype.canShieldTakeBullet = function(bullet) {
  if (!this.isShieldActive) {
    return false;
  }
  var mouseDirection = this.mouseDirection;
  if (mouseDirection < 0) {
    mouseDirection += 2 * Math.PI;
  }
  var oppositeShieldDirection = mouseDirection + Math.PI;
  var minShieldDirection = oppositeShieldDirection - Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0);
  var maxShieldDirection = oppositeShieldDirection + Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0);
  var bulletDirection = bullet.direction + 2 * Math.PI;
  return bulletDirection <= maxShieldDirection && bulletDirection >= minShieldDirection;
};

Character.prototype.getTimeUntilRespawn = function(timeDied) {
  var currentTime = +new Date();
  return Math.max(timeDied + this.respawnTime - currentTime, 0);
};

var defaultSpawn = [{x:5, y:32}, {x:55, y:32}];
Character.getDefaultPoint = function(team) {
  return defaultSpawn[team];
};

Character.getClosestSpawnPoint = function(team, character, capturePoints) {
  var spawnPoint = defaultSpawn[team];
  var dist = 999999; //bigger than map.
  for (var i = 0; i < capturePoints.length; i++) {
    var capturePoint = capturePoints[i];
    if (team === 0 && capturePoint.ownage_d === -1 || team === 1 && capturePoint.ownage_d === 1) {
      if(capturePoint.sqDistanceTo(character) < dist){
        spawnPoint = capturePoint;
      }
    }
  }
  return spawnPoint;
};
Character.prototype.update = function(input, walls, utility, capturePoints, points) {
  this.points = points;
  if (this.timeDied) {
    var timeUntilRespawn = this.getTimeUntilRespawn(this.timeDied);
    if (timeUntilRespawn <= 0) {
      var spawnPoint = Character.getClosestSpawnPoint(this.team,this, capturePoints);
      if (spawnPoint) {
        this.init(spawnPoint);
      }
    }
    return;
  }

  this.applyMovementForce(input);
  this.applyFrictionForce();
  this.mouseDirection = input[BUTTONS.MOUSE_DIR];

  this.isShieldActive = input[BUTTONS.ALTERNATE_FIRE];
  this.shieldEnergy += 0.003;
  if (this.shieldEnergy > 1) {
    this.shieldEnergy = 1;
  }

  this.weaponHeat -= this.overheated ? 0.005 : 0.01;
  if (this.weaponHeat < 0) {
    this.weaponHeat = 0;
  }
  if (this.weaponHeat < 1) {
    this.overheated = false;
  }

  for(var i = 0; i < walls.length; i++) {
    if(utility.intersectLineCircle(walls[i].start_x, walls[i].start_y, walls[i].end_x, walls[i].end_y, this.x, this.y, this.bodyRadius)) {
      var p = walls[i].getPushVector(this.x, this.y, this.bodyRadius);

      //Decompose velocity!
      var newDx = 0;
      var newDy = 0;

      var p_l = Math.sqrt(p.x * p.x + p.y * p.y);
      if(p_l > 0.0001){
        p = { x: p.x/p_l, y: p.y / p_l }

        var newSpeed = p.x * this.dx + p.y * this.dy;
        if(newSpeed > 0){ //Moving away from wall. this is ok.
          newDx += p.x * newSpeed;
          newDy += p.y * newSpeed;
        }

      }

      var n = { x: -p.y, y: p.x };
      var n_l = Math.sqrt(n.x * n.x + n.y * n.y);
      if(n_l > 0.0001){
        n = { x: n.x/n_l, y: n.y / n_l }

        var newSpeed = n.x * this.dx + n.y * this.dy;
        newDx += n.x * newSpeed;
        newDy += n.y * newSpeed;
      }

      this.dx = newDx;
      this.dy = newDy;
    }
  }

  this.x += this.dx;
  this.y += this.dy;

  // stay within bounds
  if (this.x < 0) {
    this.x = 0;
  } else if (this.x > 64) {
    this.x = 64;
  }
  if (this.y < 0) {
    this.y = 0;
  } else if (this.y > 64) {
    this.y = 64;
  }
};

Character.prototype.applyMovementForce = function(input) {
  var fx = 0;
  var fy = 0;
  var shouldMove = false;
  if (input[BUTTONS.MOVE_UP]) { // W
    fy += -1;
    shouldMove = true;
  }
  if (input[BUTTONS.MOVE_DOWN]) { // S
    fy += 1;
    shouldMove = true;
  }
  if (input[BUTTONS.MOVE_LEFT]) { // A
    fx += -1;
    shouldMove = true;
  }
  if (input[BUTTONS.MOVE_RIGHT]) { // D
    fx += 1;
    shouldMove = true;
  }

  if (shouldMove) {
    var targetDirection = Math.atan2(fy, fx);

    fx = this.accelerationCoefficient * Math.cos(targetDirection);
    fy = this.accelerationCoefficient * Math.sin(targetDirection);

    this.dx += fx;
    this.dy += fy;
  }
};

Character.prototype.getCurrentDirection = function() {
  return Math.atan2(this.dy, this.dx);
};

Character.prototype.applyFrictionForce = function() {
  var currentDirection = this.getCurrentDirection();
  var currentSpeed = Math.sqrt(Math.pow(this.dx, 2) + Math.pow(this.dy, 2));
  var activeShieldFactor = this.isShieldActive ? 2.2 : 1; // more friction while shield is active
  var frictionScalar = - activeShieldFactor * this.breakingCoefficient * Math.pow(currentSpeed * 5 +.15, 2);
  var breakFx = frictionScalar * Math.cos(currentDirection);
  var breakFy = frictionScalar * Math.sin(currentDirection);
  this.dx += breakFx;
  this.dy += breakFy;
};

Character.prototype.render = function(ctx, player_next, coeff, lightImg, darkImg, name) {
  if (!player_next) {
    return;
  }
  var x = this.x * (1 - coeff) + player_next.x * coeff;
  var y = this.y * (1 - coeff) + player_next.y * coeff;

  if (this.timeDied) {
    ctx.save();
    ctx.translate(x * GU, y * GU);
    ctx.scale(1.2, 1.2);
    ctx.font = GU + 'px Arial';
    ctx.fillStyle = 'white';
    ctx.textAlign = 'center';
    var timeUntilRespawn = Character.prototype.getTimeUntilRespawn.call(this, this.timeDied);
    ctx.fillText(name + ' is dead (' + Math.ceil(timeUntilRespawn / 1000).toString() + ')', 0, 0);
    ctx.restore();
    return;
  }

  var hp = this.hp * (1 - coeff) + player_next.hp * coeff;

  var bodyRadius = this.bodyRadius;
  ctx.save();
  ctx.translate(x * GU, y * GU);
  ctx.scale(0.6, 0.6);
  ctx.font = (.5 * GU) + 'px Arial';
  var width = ctx.measureText(name).width;
  var padding = GU * 0.5;
  ctx.fillStyle = 'white';
  ctx.textAlign = 'center';
  ctx.fillText(name , 0, -2.1 * GU);

  ctx.fillStyle = 'white';
  ctx.strokeStyle = '#888';
  ctx.lineWidth = 0.05 * GU;
  var hpWidth = 3 * GU;
  ctx.fillRect(
      -hpWidth / 2,
      -1.8 * GU,
      hpWidth * hp / 10, 0.2 * GU);

  ctx.strokeRect(
      -hpWidth / 2 - 0.1 * GU,
      -1.9 * GU,
      hpWidth + 0.2 * GU, 0.4 * GU);

  ctx.restore();
  ctx.save();

  ctx.translate(x * GU, y * GU);
  ctx.scale(GU * 0.005, GU * 0.005);
  ctx.rotate(this.mouseDirection);
  var img = this.team == 0 ? lightImg : darkImg;
  ctx.drawImage(img, -img.width / 2, -img.height / 2 - 52);

  ctx.restore();
  ctx.save();

  ctx.translate(x * GU, y * GU);
  ctx.scale(0.6, 0.6);
  ctx.rotate(this.mouseDirection);

  if (this.isShieldActive && this.shieldEnergy > 0) {
    ctx.beginPath();
    ctx.strokeStyle = '#BCBCBC';
    ctx.lineWidth = 10  + 10 * this.shieldEnergy;
    ctx.arc(
      0,
      0,
      180,
      -Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0),
      Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0),
      false
    );
    ctx.stroke();
  }
  ctx.restore();
};

Character.prototype.renderUi = function(ctx) {
  // draw overheat indicator
  ctx.save();
  var fillAlpha = 0.5;
  if (this.overheated) {
    fillAlpha += Math.sin(0.02 * t);
  }
  if(fillAlpha > 0.5) {
    ctx.fillStyle = 'rgba(255, 255, 255, ' + fillAlpha + ')';
  } else {
    ctx.fillStyle = 'rgba(255, 2555, 255, ' + fillAlpha + ')';
  }
  ctx.strokeStyle = 'rgba(255, 255, 255, .5)';
  ctx.strokeWidth = 0.1 * GU;
  ctx.fillRect(0.5 * GU, 8.5 * GU, GU * this.weaponHeat, 0.2 * GU);
  ctx.strokeRect(0.5 * GU, 8.5 * GU, GU * Character.OVERHEAT_THRESHOLD, 0.2 * GU);
  ctx.restore();
};

module.exports = Character;
<commit_msg>fix respawn timer<commit_after>try {
  window;
} catch(e) {
  var BUTTONS = require('./input');
}

function Character(team, spawnPoint) {
  this.breakingCoefficient = 0.025;
  this.accelerationCoefficient = 0.012;
  this.bodyRadius = 0.6;
  this.MAX_HP = 10;
  this.team = team;
  this.onCP = false;
  this.kills = 0;
  this.deaths = 0;
  this.init(spawnPoint);
}

Character.MAX_SHIELD_ARC = 0.2 * Math.PI;
Character.OVERHEAT_THRESHOLD = 1.5;

Character.prototype.init = function(spawnPoint) {
  if (spawnPoint) {
    this.x = spawnPoint.x;
    this.y = spawnPoint.y;
    this.timeToRespawn = null;
  } else {
    this.x = 32;
    this.y = 32;
    this.timeDied = +new Date();
    this.timeToRespawn = this.getTimeUntilRespawn(this.timeDied);
  }

  this.dx = 0;
  this.dy = 0;
  this.hp = this.MAX_HP;
  this.isShieldActive = false;
  this.fireCooldown = 0;
  this.shieldEnergy = 1;
  this.weaponHeat = 0;
  this.overheated = false;
  this.points = 0;
  this.respawnTime = 4000;
};

Character.prototype.getState = function() {
  return {
    t: 'C',
    x: this.x,
    y: this.y,
    hp: this.hp,
    kills: this.kills,
    deaths: this.deaths,
    mouseDirection: this.mouseDirection,
    isShieldActive: this.isShieldActive,
    shieldEnergy: this.shieldEnergy,
    team: this.team,
    weaponHeat: this.weaponHeat,
    overheated: this.overheated,
    respawnTime: this.respawnTime,
    timeToRespawn: this.timeToRespawn
  };
};

Character.prototype.hit = function(bullet, soundsToPlay) {
  if (bullet.team == this.team){
    return;
  }

  if (this.canShieldTakeBullet(bullet)) {
    this.shieldEnergy -= 0.45;
    var shieldSoundIndex = Math.floor(3 * Math.random()) + 1;
    soundsToPlay['shield-hit-' + shieldSoundIndex + '.mp3'] = true;
  } else {
    this.dx += bullet.dx;
    this.dy += bullet.dy;

    this.hp --;
    if (this.hp <= 0){
      this.deaths++;
      if(bullet.character){
        bullet.character.killed(this);
      }
      this.die();
    }
  }
};

Character.prototype.killed = function(enemy){
  //YEEY
  this.kills++;
};

Character.prototype.die = function(){
  this.hp = 0;
  this.timeDied = +new Date();
  this.respawnTime = 1000 + this.points * 0.3;
};

Character.prototype.canShieldTakeBullet = function(bullet) {
  if (!this.isShieldActive) {
    return false;
  }
  var mouseDirection = this.mouseDirection;
  if (mouseDirection < 0) {
    mouseDirection += 2 * Math.PI;
  }
  var oppositeShieldDirection = mouseDirection + Math.PI;
  var minShieldDirection = oppositeShieldDirection - Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0);
  var maxShieldDirection = oppositeShieldDirection + Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0);
  var bulletDirection = bullet.direction + 2 * Math.PI;
  return bulletDirection <= maxShieldDirection && bulletDirection >= minShieldDirection;
};

Character.prototype.getTimeUntilRespawn = function(timeDied) {
  var currentTime = +new Date();
  return Math.max(timeDied + this.respawnTime - currentTime, 0);
};

var defaultSpawn = [{x:5, y:32}, {x:55, y:32}];
Character.getDefaultPoint = function(team) {
  return defaultSpawn[team];
};

Character.getClosestSpawnPoint = function(team, character, capturePoints) {
  var spawnPoint = defaultSpawn[team];
  var dist = 999999; //bigger than map.
  for (var i = 0; i < capturePoints.length; i++) {
    var capturePoint = capturePoints[i];
    if (team === 0 && capturePoint.ownage_d === -1 || team === 1 && capturePoint.ownage_d === 1) {
      if(capturePoint.sqDistanceTo(character) < dist){
        spawnPoint = capturePoint;
      }
    }
  }
  return spawnPoint;
};
Character.prototype.update = function(input, walls, utility, capturePoints, points) {
  this.points = points;
  if (this.timeDied) {
    this.timeToRespawn = this.getTimeUntilRespawn(this.timeDied);
    if (this.timeToRespawn <= 0) {
      var spawnPoint = Character.getClosestSpawnPoint(this.team,this, capturePoints);
      if (spawnPoint) {
        this.init(spawnPoint);
      }
    }
    return;
  }

  this.applyMovementForce(input);
  this.applyFrictionForce();
  this.mouseDirection = input[BUTTONS.MOUSE_DIR];

  this.isShieldActive = input[BUTTONS.ALTERNATE_FIRE];
  this.shieldEnergy += 0.003;
  if (this.shieldEnergy > 1) {
    this.shieldEnergy = 1;
  }

  this.weaponHeat -= this.overheated ? 0.005 : 0.01;
  if (this.weaponHeat < 0) {
    this.weaponHeat = 0;
  }
  if (this.weaponHeat < 1) {
    this.overheated = false;
  }

  for(var i = 0; i < walls.length; i++) {
    if(utility.intersectLineCircle(walls[i].start_x, walls[i].start_y, walls[i].end_x, walls[i].end_y, this.x, this.y, this.bodyRadius)) {
      var p = walls[i].getPushVector(this.x, this.y, this.bodyRadius);

      //Decompose velocity!
      var newDx = 0;
      var newDy = 0;

      var p_l = Math.sqrt(p.x * p.x + p.y * p.y);
      if(p_l > 0.0001){
        p = { x: p.x/p_l, y: p.y / p_l }

        var newSpeed = p.x * this.dx + p.y * this.dy;
        if(newSpeed > 0){ //Moving away from wall. this is ok.
          newDx += p.x * newSpeed;
          newDy += p.y * newSpeed;
        }

      }

      var n = { x: -p.y, y: p.x };
      var n_l = Math.sqrt(n.x * n.x + n.y * n.y);
      if(n_l > 0.0001){
        n = { x: n.x/n_l, y: n.y / n_l }

        var newSpeed = n.x * this.dx + n.y * this.dy;
        newDx += n.x * newSpeed;
        newDy += n.y * newSpeed;
      }

      this.dx = newDx;
      this.dy = newDy;
    }
  }

  this.x += this.dx;
  this.y += this.dy;

  // stay within bounds
  if (this.x < 0) {
    this.x = 0;
  } else if (this.x > 64) {
    this.x = 64;
  }
  if (this.y < 0) {
    this.y = 0;
  } else if (this.y > 64) {
    this.y = 64;
  }
};

Character.prototype.applyMovementForce = function(input) {
  var fx = 0;
  var fy = 0;
  var shouldMove = false;
  if (input[BUTTONS.MOVE_UP]) { // W
    fy += -1;
    shouldMove = true;
  }
  if (input[BUTTONS.MOVE_DOWN]) { // S
    fy += 1;
    shouldMove = true;
  }
  if (input[BUTTONS.MOVE_LEFT]) { // A
    fx += -1;
    shouldMove = true;
  }
  if (input[BUTTONS.MOVE_RIGHT]) { // D
    fx += 1;
    shouldMove = true;
  }

  if (shouldMove) {
    var targetDirection = Math.atan2(fy, fx);

    fx = this.accelerationCoefficient * Math.cos(targetDirection);
    fy = this.accelerationCoefficient * Math.sin(targetDirection);

    this.dx += fx;
    this.dy += fy;
  }
};

Character.prototype.getCurrentDirection = function() {
  return Math.atan2(this.dy, this.dx);
};

Character.prototype.applyFrictionForce = function() {
  var currentDirection = this.getCurrentDirection();
  var currentSpeed = Math.sqrt(Math.pow(this.dx, 2) + Math.pow(this.dy, 2));
  var activeShieldFactor = this.isShieldActive ? 2.2 : 1; // more friction while shield is active
  var frictionScalar = - activeShieldFactor * this.breakingCoefficient * Math.pow(currentSpeed * 5 +.15, 2);
  var breakFx = frictionScalar * Math.cos(currentDirection);
  var breakFy = frictionScalar * Math.sin(currentDirection);
  this.dx += breakFx;
  this.dy += breakFy;
};

Character.prototype.render = function(ctx, player_next, coeff, lightImg, darkImg, name) {
  if (!player_next) {
    return;
  }
  var x = this.x * (1 - coeff) + player_next.x * coeff;
  var y = this.y * (1 - coeff) + player_next.y * coeff;

  if (this.timeToRespawn) {
    ctx.save();
    ctx.translate(x * GU, y * GU);
    ctx.scale(1.2, 1.2);
    ctx.font = GU + 'px Arial';
    ctx.fillStyle = 'white';
    ctx.textAlign = 'center';
    ctx.fillText(name + ' is dead (' + Math.ceil(this.timeToRespawn / 1000).toString() + ')', 0, 0);
    ctx.restore();
    return;
  }

  var hp = this.hp * (1 - coeff) + player_next.hp * coeff;

  var bodyRadius = this.bodyRadius;
  ctx.save();
  ctx.translate(x * GU, y * GU);
  ctx.scale(0.6, 0.6);
  ctx.font = (.5 * GU) + 'px Arial';
  var width = ctx.measureText(name).width;
  var padding = GU * 0.5;
  ctx.fillStyle = 'white';
  ctx.textAlign = 'center';
  ctx.fillText(name , 0, -2.1 * GU);

  ctx.fillStyle = 'white';
  ctx.strokeStyle = '#888';
  ctx.lineWidth = 0.05 * GU;
  var hpWidth = 3 * GU;
  ctx.fillRect(
      -hpWidth / 2,
      -1.8 * GU,
      hpWidth * hp / 10, 0.2 * GU);

  ctx.strokeRect(
      -hpWidth / 2 - 0.1 * GU,
      -1.9 * GU,
      hpWidth + 0.2 * GU, 0.4 * GU);

  ctx.restore();
  ctx.save();

  ctx.translate(x * GU, y * GU);
  ctx.scale(GU * 0.005, GU * 0.005);
  ctx.rotate(this.mouseDirection);
  var img = this.team == 0 ? lightImg : darkImg;
  ctx.drawImage(img, -img.width / 2, -img.height / 2 - 52);

  ctx.restore();
  ctx.save();

  ctx.translate(x * GU, y * GU);
  ctx.scale(0.6, 0.6);
  ctx.rotate(this.mouseDirection);

  if (this.isShieldActive && this.shieldEnergy > 0) {
    ctx.beginPath();
    ctx.strokeStyle = '#BCBCBC';
    ctx.lineWidth = 10  + 10 * this.shieldEnergy;
    ctx.arc(
      0,
      0,
      180,
      -Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0),
      Character.MAX_SHIELD_ARC * Math.max(this.shieldEnergy, 0),
      false
    );
    ctx.stroke();
  }
  ctx.restore();
};

Character.prototype.renderUi = function(ctx) {
  // draw overheat indicator
  ctx.save();
  var fillAlpha = 0.5;
  if (this.overheated) {
    fillAlpha += Math.sin(0.02 * t);
  }
  if(fillAlpha > 0.5) {
    ctx.fillStyle = 'rgba(255, 255, 255, ' + fillAlpha + ')';
  } else {
    ctx.fillStyle = 'rgba(255, 2555, 255, ' + fillAlpha + ')';
  }
  ctx.strokeStyle = 'rgba(255, 255, 255, .5)';
  ctx.strokeWidth = 0.1 * GU;
  ctx.fillRect(0.5 * GU, 8.5 * GU, GU * this.weaponHeat, 0.2 * GU);
  ctx.strokeRect(0.5 * GU, 8.5 * GU, GU * Character.OVERHEAT_THRESHOLD, 0.2 * GU);
  ctx.restore();
};

module.exports = Character;
<|endoftext|>


<commit_before>var expect      = require('chai').expect;
var _           = require("lodash");
var creditcards = require("../src/Creditcards.js");

describe("English locale tests (en_US)", function() {
    it ('returns "Visa" for "visa" (network name)', function() {
    	expect(creditcards.getCreditcardName("en_US", "visa")).to.equal("Visa");
    });

    it ('returns "Expiry Date" for "expiration" (field name)', function() {
    	expect(creditcards.getFieldName("en_US", "expiration")).to.equal("Expiry Date");
    });
});

describe("Invalid locale tests (xx_XX)", function() {
    it ('returns empty string for "visa" (network name)', function() {
    	expect(creditcards.getCreditcardName("xx_XX", "visa")).to.equal("");
    });

    it ('returns empty string for "expiration" (field name)', function() {
    	expect(creditcards.getFieldName("xx_XX", "expiration")).to.equal("");
    });
});
<commit_msg>Arrow functions.<commit_after>var expect      = require('chai').expect;
var _           = require("lodash");
var creditcards = require("../src/Creditcards.js");

describe("English locale tests (en_US)", () => {
    it ('returns "Visa" for "visa" (network name)', () => {
    	expect(creditcards.getCreditcardName("en_US", "visa")).to.equal("Visa");
    });

    it ('returns "Expiry Date" for "expiration" (field name)', () => {
    	expect(creditcards.getFieldName("en_US", "expiration")).to.equal("Expiry Date");
    });
});

describe("Invalid locale tests (xx_XX)", () => {
    it ('returns empty string for "visa" (network name)', () => {
    	expect(creditcards.getCreditcardName("xx_XX", "visa")).to.equal("");
    });

    it ('returns empty string for "expiration" (field name)', () => {
    	expect(creditcards.getFieldName("xx_XX", "expiration")).to.equal("");
    });
});
<|endoftext|>


<commit_before>import path from 'path';

import sqlite3 from 'sqlite3';

const MAX_CHUNK_SIZE = 100;

function normalizedExportName(string) {
  return string.toLowerCase().replace(/[-_.]/g, '');
}

function inParam(sql, values) {
  // https://github.com/mapbox/node-sqlite3/issues/721
  return sql.replace('?#', values.map(() => '?').join(','));
}

function arrayToChunks(array, chunkSize) {
  const chunks = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    chunks.push(array.slice(i, i + chunkSize));
  }
  return chunks;
}

export default class ExportsStorage {
  constructor(workingDirectory) {
    this.workingDirectory = workingDirectory;
  }

  init(dbFilename) {
    return new Promise((resolve, reject) => {
      this.db = new sqlite3.Database(
        dbFilename || path.join(this.workingDirectory, '.importjs.db'));
      this.db.run(`
        CREATE TABLE IF NOT EXISTS exports (
          key VARCHAR(100),
          name VARCHAR(100),
          path TEXT
        )
      `, (err) => {
        if (err) {
          reject(err);
          return;
        }

        this.db.run(`
          CREATE TABLE IF NOT EXISTS mtimes (
            path TEXT,
            mtime NUMERIC
          )
        `, (err) => {
          if (err) {
            reject(err);
            return;
          }

          resolve();
        });
      });
    });
  }

  close() {
    return new Promise((resolve, reject) => {
      this.db.close((err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  }

  needsUpdate(files) {
    if (files.length > MAX_CHUNK_SIZE) {
      // sqlite has a max number for arguments passed. We need to execute in
      // chunks if we exceed the max.
      const promises = arrayToChunks(files, MAX_CHUNK_SIZE).map((chunk) =>
        this.needsUpdate(chunk));
      return Promise.all(promises)
        .then((chunks) => chunks.reduce((a, b) => a.concat(b))); // flatten
    }

    return new Promise((resolve, reject) => {
      const filePaths = files.map(({ path: p }) => p);
      this.db.all(inParam(`
        SELECT path, mtime FROM mtimes
        WHERE (path IN (?#))
      `, filePaths), filePaths, (err, items) => {
        if (err) {
          reject(err);
          return;
        }
        const mtimes = {};
        items.forEach(({ path: pathToFile, mtime }) => {
          mtimes[pathToFile] = mtime;
        });
        const filtered = files.filter(({ path: pathToFile, mtime }) =>
          mtime !== mtimes[pathToFile]);
        resolve(filtered);
      });
    });
  }

  allFiles() {
    return new Promise((resolve, reject) => {
      this.db.all('SELECT path FROM mtimes', (err, files) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(files.map(({ path }) => path));
      });
    });
  }

  updateMtime(pathToFile, mtime) {
    return new Promise((resolve, reject) => {
      this.db.get('SELECT mtime FROM mtimes WHERE (path = ?)',
        pathToFile, (err, item) => {
          if (err) {
            reject(err);
            return;
          }
          if (item) {
            this.db.run('UPDATE mtimes SET mtime = ? WHERE (path = ?)',
              mtime, pathToFile, (err) => {
                if (err) {
                  reject(err);
                  return;
                }
                resolve();
              });
          } else {
            this.db.run('INSERT INTO mtimes (mtime, path) VALUES (?, ?)',
              mtime, pathToFile, (err) => {
                if (err) {
                  reject(err);
                  return;
                }
                resolve();
              });
          }
        });
    });
  }

  exists(key, pathToFile) {
    return new Promise((resolve, reject) => {
      this.db.get('SELECT key FROM exports WHERE (key = ? AND path = ?)',
        key, pathToFile, (err, item) => {
          if (err) {
            reject(err);
            return;
          }
          resolve(!!item);
        });
    });
  }

  upsert({ name, pathToFile, isDefault }) {
    return new Promise((resolve, reject) => {
      const key = normalizedExportName(name);
      const exportName = isDefault ? 'default' : name;

      this.exists(key, pathToFile).then((exists) => {
        if (exists) {
          this.db.run('UPDATE exports SET name = ? WHERE (key = ? AND path = ?)',
            exportName, key, pathToFile, (err) => {
              if (err) {
                reject(err);
                return;
              }
              resolve();
            });
        } else {
          this.db.run('INSERT INTO exports (key, name, path) VALUES (?, ?, ?)',
            key, exportName, pathToFile, (err) => {
              if (err) {
                reject(err);
                return;
              }
              resolve();
            });
        }
      });
    });
  }

  update({ names, defaultNames, pathToFile, mtime }) {
    return this.remove(pathToFile).then(() =>
      this.updateMtime(pathToFile, mtime).then(() => {
        const promises = names.map((name) =>
          this.upsert({ name, pathToFile, isDefault: false }));
        promises.push(...defaultNames.map((name) =>
          this.upsert({ name, pathToFile, isDefault: true })));
        return Promise.all(promises);
      }));
  }

  remove(pathToFile) {
    return new Promise((resolve, reject) => {
      this.db.run('DELETE FROM exports WHERE (path = ?)', pathToFile, (err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  }

  get(variableName) {
    return new Promise((resolve, reject) => {
      this.db.all('SELECT name, path FROM exports WHERE (key = ?)',
        normalizedExportName(variableName), (err, rows) => {
          if (err) {
            reject(err);
            return;
          }
          resolve(rows);
        });
    });
  }
}
<commit_msg>Remove files from mtimes table as well<commit_after>import path from 'path';

import sqlite3 from 'sqlite3';

const MAX_CHUNK_SIZE = 100;

function normalizedExportName(string) {
  return string.toLowerCase().replace(/[-_.]/g, '');
}

function inParam(sql, values) {
  // https://github.com/mapbox/node-sqlite3/issues/721
  return sql.replace('?#', values.map(() => '?').join(','));
}

function arrayToChunks(array, chunkSize) {
  const chunks = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    chunks.push(array.slice(i, i + chunkSize));
  }
  return chunks;
}

export default class ExportsStorage {
  constructor(workingDirectory) {
    this.workingDirectory = workingDirectory;
  }

  init(dbFilename) {
    return new Promise((resolve, reject) => {
      this.db = new sqlite3.Database(
        dbFilename || path.join(this.workingDirectory, '.importjs.db'));
      this.db.run(`
        CREATE TABLE IF NOT EXISTS exports (
          key VARCHAR(100),
          name VARCHAR(100),
          path TEXT
        )
      `, (err) => {
        if (err) {
          reject(err);
          return;
        }

        this.db.run(`
          CREATE TABLE IF NOT EXISTS mtimes (
            path TEXT,
            mtime NUMERIC
          )
        `, (err) => {
          if (err) {
            reject(err);
            return;
          }

          resolve();
        });
      });
    });
  }

  close() {
    return new Promise((resolve, reject) => {
      this.db.close((err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  }

  needsUpdate(files) {
    if (files.length > MAX_CHUNK_SIZE) {
      // sqlite has a max number for arguments passed. We need to execute in
      // chunks if we exceed the max.
      const promises = arrayToChunks(files, MAX_CHUNK_SIZE).map((chunk) =>
        this.needsUpdate(chunk));
      return Promise.all(promises)
        .then((chunks) => chunks.reduce((a, b) => a.concat(b))); // flatten
    }

    return new Promise((resolve, reject) => {
      const filePaths = files.map(({ path: p }) => p);
      this.db.all(inParam(`
        SELECT path, mtime FROM mtimes
        WHERE (path IN (?#))
      `, filePaths), filePaths, (err, items) => {
        if (err) {
          reject(err);
          return;
        }
        const mtimes = {};
        items.forEach(({ path: pathToFile, mtime }) => {
          mtimes[pathToFile] = mtime;
        });
        const filtered = files.filter(({ path: pathToFile, mtime }) =>
          mtime !== mtimes[pathToFile]);
        resolve(filtered);
      });
    });
  }

  allFiles() {
    return new Promise((resolve, reject) => {
      this.db.all('SELECT path FROM mtimes', (err, files) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(files.map(({ path }) => path));
      });
    });
  }

  updateMtime(pathToFile, mtime) {
    return new Promise((resolve, reject) => {
      this.db.get('SELECT mtime FROM mtimes WHERE (path = ?)',
        pathToFile, (err, item) => {
          if (err) {
            reject(err);
            return;
          }
          if (item) {
            this.db.run('UPDATE mtimes SET mtime = ? WHERE (path = ?)',
              mtime, pathToFile, (err) => {
                if (err) {
                  reject(err);
                  return;
                }
                resolve();
              });
          } else {
            this.db.run('INSERT INTO mtimes (mtime, path) VALUES (?, ?)',
              mtime, pathToFile, (err) => {
                if (err) {
                  reject(err);
                  return;
                }
                resolve();
              });
          }
        });
    });
  }

  exists(key, pathToFile) {
    return new Promise((resolve, reject) => {
      this.db.get('SELECT key FROM exports WHERE (key = ? AND path = ?)',
        key, pathToFile, (err, item) => {
          if (err) {
            reject(err);
            return;
          }
          resolve(!!item);
        });
    });
  }

  upsert({ name, pathToFile, isDefault }) {
    return new Promise((resolve, reject) => {
      const key = normalizedExportName(name);
      const exportName = isDefault ? 'default' : name;

      this.exists(key, pathToFile).then((exists) => {
        if (exists) {
          this.db.run('UPDATE exports SET name = ? WHERE (key = ? AND path = ?)',
            exportName, key, pathToFile, (err) => {
              if (err) {
                reject(err);
                return;
              }
              resolve();
            });
        } else {
          this.db.run('INSERT INTO exports (key, name, path) VALUES (?, ?, ?)',
            key, exportName, pathToFile, (err) => {
              if (err) {
                reject(err);
                return;
              }
              resolve();
            });
        }
      });
    });
  }

  update({ names, defaultNames, pathToFile, mtime }) {
    return this.remove(pathToFile).then(() =>
      this.updateMtime(pathToFile, mtime).then(() => {
        const promises = names.map((name) =>
          this.upsert({ name, pathToFile, isDefault: false }));
        promises.push(...defaultNames.map((name) =>
          this.upsert({ name, pathToFile, isDefault: true })));
        return Promise.all(promises);
      }));
  }

  remove(pathToFile) {
    return new Promise((resolve, reject) => {
      this.db.run('DELETE FROM exports WHERE (path = ?)', pathToFile, (err) => {
        if (err) {
          reject(err);
          return;
        }
        this.db.run('DELETE FROM mtimes WHERE (path = ?)', pathToFile, (mErr) => {
          if (mErr) {
            reject(mErr);
            return;
          }
          resolve();
        });
      });
    });
  }

  get(variableName) {
    return new Promise((resolve, reject) => {
      this.db.all('SELECT name, path FROM exports WHERE (key = ?)',
        normalizedExportName(variableName), (err, rows) => {
          if (err) {
            reject(err);
            return;
          }
          resolve(rows);
        });
    });
  }
}
<|endoftext|>


<commit_before>minerva.collections.SourceCollection = minerva.collections.MinervaCollection.extend({

    model: function (attrs, options) {
        if (attrs.meta && ('minerva' in attrs.meta)) {
            if (attrs.meta.minerva.source_type === 'wms') {
                return new minerva.models.WmsSourceModel(attrs, options);
            }
        } else {
            console.error('Source collection includes unknown source type');
            console.error(attrs);
            girder.events.trigger('g:alert', {
                icon: 'cancel',
                text: 'Unknown source type in collection.',
                type: 'error',
                timeout: 4000
            });
        }
    },
    path: 'minerva_source'

});
<commit_msg>Specify initData on SourceCollection<commit_after>minerva.collections.SourceCollection = minerva.collections.MinervaCollection.extend({

    model: function (attrs, options) {
        if (attrs.meta && ('minerva' in attrs.meta)) {
            if (attrs.meta.minerva.source_type === 'wms') {
                return new minerva.models.WmsSourceModel(attrs, options);
            }
        } else {
            console.error('Source collection includes unknown source type');
            console.error(attrs);
            girder.events.trigger('g:alert', {
                icon: 'cancel',
                text: 'Unknown source type in collection.',
                type: 'error',
                timeout: 4000
            });
        }
    },

    path: 'minerva_source',
    getInitData: function () {
        var initData = { userId: girder.currentUser.get('_id') };
        return initData;
    }

});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule setupDevtools
 * @flow
 */
'use strict';

var NativeModules = require('NativeModules');
var Platform = require('Platform');

function setupDevtools() {
  var messageListeners = [];
  var closeListeners = [];
  var hostname = 'localhost';
  if (Platform.OS === 'android' && NativeModules.AndroidConstants) {
    hostname = NativeModules.AndroidConstants.ServerHost.split(':')[0];
  }
  var ws = new window.WebSocket('ws://' + hostname + ':8097/devtools');
  // this is accessed by the eval'd backend code
  var FOR_BACKEND = { // eslint-disable-line no-unused-vars
    resolveRNStyle: require('flattenStyle'),
    wall: {
      listen(fn) {
        messageListeners.push(fn);
      },
      onClose(fn) {
        closeListeners.push(fn);
      },
      send(data) {
        ws.send(JSON.stringify(data));
      },
    },
  };
  ws.onclose = handleClose;
  ws.onerror = handleClose;
  ws.onopen = function () {
    tryToConnect();
  };

  var hasClosed = false;
  function handleClose() {
    if (!hasClosed) {
      hasClosed = true;
      setTimeout(setupDevtools, 2000);
      closeListeners.forEach(fn => fn());
    }
  }

  function tryToConnect() {
    ws.send('attach:agent');
    var _interval = setInterval(() => ws.send('attach:agent'), 500);
    ws.onmessage = evt => {
      if (evt.data.indexOf('eval:') === 0) {
        clearInterval(_interval);
        initialize(evt.data.slice('eval:'.length));
      }
    };
  }

  function initialize(text) {
    try {
      // FOR_BACKEND is used by the eval'd code
      eval(text); // eslint-disable-line no-eval
    } catch (e) {
      console.error('Failed to eval: ' + e.message);
      return;
    }
    // This is breaking encapsulation of the React package. Move plz.
    var ReactNativeComponentTree = require('ReactNativeComponentTree');
    window.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
      ComponentTree: {
        getClosestInstanceFromNode: function (node) {
          return ReactNativeComponentTree.getClosestInstanceFromNode(node);
        },
        getNodeFromInstance: function (inst) {
          // inst is an internal instance (but could be a composite)
          while (inst._renderedComponent) {
            inst = inst._renderedComponent;
          }
          if (inst) {
            return ReactNativeComponentTree.getNodeFromInstance(inst);
          } else {
            return null;
          }
        }
      },
      Mount: require('ReactNativeMount'),
      Reconciler: require('ReactReconciler')
    });
    ws.onmessage = handleMessage;
  }

  function handleMessage(evt) {
    // It's hard to handle JSON in a safe manner without inspecting it at
    // runtime, hence the any
    var data: any;
    try {
      data = JSON.parse(evt.data);
    } catch (e) {
      return console.error('failed to parse json: ' + evt.data);
    }
    // the devtools closed
    if (data.$close || data.$error) {
      closeListeners.forEach(fn => fn());
      window.__REACT_DEVTOOLS_GLOBAL_HOOK__.emit('shutdown');
      tryToConnect();
      return;
    }
    if (data.$open) {
      return; // ignore
    }
    messageListeners.forEach(fn => {
      try {
        fn(data);
      } catch (e) {
        // jsc doesn't play so well with tracebacks that go into eval'd code,
        // so the stack trace here will stop at the `eval()` call. Getting the
        // message that caused the error is the best we can do for now.
        console.log(data);
        throw e;
      }
    });
  }
}

module.exports = setupDevtools;
<commit_msg>Make react-devtools server port can be changed<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule setupDevtools
 * @flow
 */
'use strict';

var NativeModules = require('NativeModules');
var Platform = require('Platform');

function setupDevtools() {
  var messageListeners = [];
  var closeListeners = [];
  var hostname = 'localhost';
  if (Platform.OS === 'android' && NativeModules.AndroidConstants) {
    hostname = NativeModules.AndroidConstants.ServerHost.split(':')[0];
  }
  var port = window.__REACT_DEVTOOLS_PORT__ || 8097;
  var ws = new window.WebSocket('ws://' + hostname + ':' +  port + '/devtools');
  // this is accessed by the eval'd backend code
  var FOR_BACKEND = { // eslint-disable-line no-unused-vars
    resolveRNStyle: require('flattenStyle'),
    wall: {
      listen(fn) {
        messageListeners.push(fn);
      },
      onClose(fn) {
        closeListeners.push(fn);
      },
      send(data) {
        ws.send(JSON.stringify(data));
      },
    },
  };
  ws.onclose = handleClose;
  ws.onerror = handleClose;
  ws.onopen = function () {
    tryToConnect();
  };

  var hasClosed = false;
  function handleClose() {
    if (!hasClosed) {
      hasClosed = true;
      setTimeout(setupDevtools, 2000);
      closeListeners.forEach(fn => fn());
    }
  }

  function tryToConnect() {
    ws.send('attach:agent');
    var _interval = setInterval(() => ws.send('attach:agent'), 500);
    ws.onmessage = evt => {
      if (evt.data.indexOf('eval:') === 0) {
        clearInterval(_interval);
        initialize(evt.data.slice('eval:'.length));
      }
    };
  }

  function initialize(text) {
    try {
      // FOR_BACKEND is used by the eval'd code
      eval(text); // eslint-disable-line no-eval
    } catch (e) {
      console.error('Failed to eval: ' + e.message);
      return;
    }
    // This is breaking encapsulation of the React package. Move plz.
    var ReactNativeComponentTree = require('ReactNativeComponentTree');
    window.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
      ComponentTree: {
        getClosestInstanceFromNode: function (node) {
          return ReactNativeComponentTree.getClosestInstanceFromNode(node);
        },
        getNodeFromInstance: function (inst) {
          // inst is an internal instance (but could be a composite)
          while (inst._renderedComponent) {
            inst = inst._renderedComponent;
          }
          if (inst) {
            return ReactNativeComponentTree.getNodeFromInstance(inst);
          } else {
            return null;
          }
        }
      },
      Mount: require('ReactNativeMount'),
      Reconciler: require('ReactReconciler')
    });
    ws.onmessage = handleMessage;
  }

  function handleMessage(evt) {
    // It's hard to handle JSON in a safe manner without inspecting it at
    // runtime, hence the any
    var data: any;
    try {
      data = JSON.parse(evt.data);
    } catch (e) {
      return console.error('failed to parse json: ' + evt.data);
    }
    // the devtools closed
    if (data.$close || data.$error) {
      closeListeners.forEach(fn => fn());
      window.__REACT_DEVTOOLS_GLOBAL_HOOK__.emit('shutdown');
      tryToConnect();
      return;
    }
    if (data.$open) {
      return; // ignore
    }
    messageListeners.forEach(fn => {
      try {
        fn(data);
      } catch (e) {
        // jsc doesn't play so well with tracebacks that go into eval'd code,
        // so the stack trace here will stop at the `eval()` call. Getting the
        // message that caused the error is the best we can do for now.
        console.log(data);
        throw e;
      }
    });
  }
}

module.exports = setupDevtools;
<|endoftext|>


<commit_before>(function (module, undefined) {

  /*
   *
   */
  function getStyle(element, property) {
    // IE8 and below does not support getComputedStyle. Use currentStyle instead.
    var styles = (window.getComputedStyle && window.getComputedStyle(element) || element.currentStyle);
    return parseFloat(styles[property]);
  }

  /*
   *
   */
  function height(element) {
    var total = getStyle(element, 'height');
    var boxModel = getStyle(element, 'boxSizing');
    if (boxModel === 'border-box') {
      return total - getStyle(element, 'paddingTop') - getStyle(element, 'paddingBottom');
    } else {
      // Assume content-box model
      return total;
    }
  }

  /* Trims leading and trailing whitespace. Regular expression taken from jQuery.
   * See https://github.com/jquery/jquery/blob/master/speed/jquery-basis.js
   *
   * str - The original string to trim.
   *
   * Returns trimmed string.
   */
  function trim(str) {
    return (str || '').replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g, ''); // from jQuery
  }

  /*
   *
   */
  function getHTMLInRange(node, startIndex, endIndex) {
    var index, childNode;
    var childNodes = node.childNodes,
        length = childNodes.length,
        html = '';

    for (index = startIndex; index <= endIndex && index < length; index++) {
      childNode = childNodes[index];
      if (childNode.nodeType === childNode.COMMENT_NODE) {
        // Need the commend node HTML in order to reconstruct original DOM structure
        // This manual way is the only way to get a comment node's HTML
        html += '';
      } else {
        html += childNode.outerHTML || childNode.nodeValue;
      }
    }
    return html;
  }

  /* Truncates a text node using binary search.
   *
   * textNode - The text node to truncate.
   * rootNode - The root node (ancestor of the textNode) to measure the truncated height.
   * options  - An object containing:
   *            showMore  - The HTML string to append at the end of the string.
   *            maxHeight - The maximum height for the root node.
   *
   * Returns nothing.
   */
  function truncateTextNode(textNode, rootNode, options) {
    var originalHTML = textNode.nodeValue,
        mid,
        low = 0,
        high = originalHTML.length,
        chunk,
        maxChunk = '';

    // Binary Search
    while (low <= high) {
      mid = low + ((high - low) >> 1); // Integer division

      chunk = trim(originalHTML.substr(0, mid + 1)) + options.showMore;
      textNode.nodeValue = chunk;

      if (height(rootNode) > options.maxHeight) {
        high = mid - 1;
      } else {
        low = mid + 1;
        maxChunk = maxChunk.length > chunk.length ? maxChunk : chunk;
      }
    }

    textNode.nodeValue = maxChunk;
  }

  function truncateNestedNode(element, rootNode, options) {

    var childNodes = element.childNodes,
        length = childNodes.length;

    if (length === 0) {

      // Base case: single element remaining

      if (element.nodeType === element.TEXT_NODE) {
        // Truncate the text node
        truncateTextNode(element, rootNode, options);
      } else {
        // Remove the node itself
        element.parentNode.removeChild(element);
      }

      return;

    } else {

      // Recursive case: iterate backwards on children nodes until tipping node is found

      var index, node, chunk;
      var originalHTML = element.innerHTML;

      for (index = length - 1; index >= 0; index--) {
        node = childNodes[index];

        chunk = getHTMLInRange(element, 0, index);
        element.innerHTML = chunk;

        if (height(rootNode) <= options.maxHeight) {

          // Check if element is not the last child
          if (index + 1 <= length - 1) {
            // Reset HTML so original childNodes tree is available
            element.innerHTML = originalHTML;

            chunk += getHTMLInRange(element, index + 1, index + 1);
            element.innerHTML = chunk;

            index += 1;
          }

          return truncateNestedNode(childNodes[index], rootNode, options);
        }
      }

      return truncateNestedNode(childNodes[0], rootNode, options);

    }
  }

  /* Public: Creates an instance of Truncate.
   *
   * element - A DOM element to be truncated.
   * options - An Object literal containing setup options.
   *
   * Examples:
   *
   *   var element = document.createElement('span');
   *   element.innerHTML = 'This is
odd.';
   *   var truncated = new Truncate(element, {
   *     lines: 1,
   *     lineHeight: 16,
   *     showMore: 'Show More',
   *     showLess: 'Show Less'
   *   });
   *
   *   // Update HTML
   *   truncated.update('This is not very odd.');
   *
   *   // Undo truncation
   *   truncated.expand();
   *
   *   // Redo truncation
   *   truncated.collapse();
   */
  function Truncate(element, options) {
    this.options = options || {};
    options.showMore = typeof options.showMore !== 'undefined' ? options.showMore : '…';
    options.showLess = typeof options.showLess !== 'undefined' ? options.showLess : '';

    this.options.maxHeight = options.lines * options.lineHeight;

    this.element = element;
    this.originalHTML = element.innerHTML;
    this.cachedHTML = null;

    this.update();
  }

  /* Public: Updates the inner HTML of the element and re-truncates.
   *
   * newHTML - The new HTML.
   *
   * Returns nothing.
   */
  Truncate.prototype.update = function (newHTML) {
    // Update HTML if provided, otherwise default to current inner HTML.
    if (newHTML) {
      this.originalHTML = this.element.innerHTML = newHTML;
    }

    // Already meets height requirement
    if (height(this.element) <= this.options.maxHeight) {
      return;
    }

    var visibility = this.element.style.visibility;
    this.element.style.visibility = 'hidden';

    truncateNestedNode(this.element, this.element, this.options);
    this.cachedHTML = this.element.innerHTML;

    this.element.style.visibility = visibility;
  };

  /* Public: Expands the element to show content in full.
   *
   * Returns nothing.
   */
  Truncate.prototype.expand = function () {
    this.element.innerHTML = this.originalHTML + this.options.showLess;
  };

  /* Public: Collapses the element to the truncated state.
   * Uses the cached HTML from .update().
   *
   * Returns nothing.
   */
  Truncate.prototype.collapse = function () {
    this.element.innerHTML = this.cachedHTML;
  };

  module.Truncate = Truncate;

})(this);
<commit_msg>Fix comment<commit_after>(function (module, undefined) {

  /*
   *
   */
  function getStyle(element, property) {
    // IE8 and below does not support getComputedStyle. Use currentStyle instead.
    var styles = (window.getComputedStyle && window.getComputedStyle(element) || element.currentStyle);
    return parseFloat(styles[property]);
  }

  /*
   *
   */
  function height(element) {
    var total = getStyle(element, 'height');
    var boxModel = getStyle(element, 'boxSizing');
    if (boxModel === 'border-box') {
      return total - getStyle(element, 'paddingTop') - getStyle(element, 'paddingBottom');
    } else {
      // Assume content-box model
      return total;
    }
  }

  /* Trims leading and trailing whitespace. Regular expression taken from jQuery.
   * See https://github.com/jquery/jquery/blob/master/speed/jquery-basis.js
   *
   * str - The original string to trim.
   *
   * Returns trimmed string.
   */
  function trim(str) {
    return (str || '').replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g, '');
  }

  /*
   *
   */
  function getHTMLInRange(node, startIndex, endIndex) {
    var index, childNode;
    var childNodes = node.childNodes,
        length = childNodes.length,
        html = '';

    for (index = startIndex; index <= endIndex && index < length; index++) {
      childNode = childNodes[index];
      if (childNode.nodeType === childNode.COMMENT_NODE) {
        // Need the commend node HTML in order to reconstruct original DOM structure
        // This manual way is the only way to get a comment node's HTML
        html += '';
      } else {
        html += childNode.outerHTML || childNode.nodeValue;
      }
    }
    return html;
  }

  /* Truncates a text node using binary search.
   *
   * textNode - The text node to truncate.
   * rootNode - The root node (ancestor of the textNode) to measure the truncated height.
   * options  - An object containing:
   *            showMore  - The HTML string to append at the end of the string.
   *            maxHeight - The maximum height for the root node.
   *
   * Returns nothing.
   */
  function truncateTextNode(textNode, rootNode, options) {
    var originalHTML = textNode.nodeValue,
        mid,
        low = 0,
        high = originalHTML.length,
        chunk,
        maxChunk = '';

    // Binary Search
    while (low <= high) {
      mid = low + ((high - low) >> 1); // Integer division

      chunk = trim(originalHTML.substr(0, mid + 1)) + options.showMore;
      textNode.nodeValue = chunk;

      if (height(rootNode) > options.maxHeight) {
        high = mid - 1;
      } else {
        low = mid + 1;
        maxChunk = maxChunk.length > chunk.length ? maxChunk : chunk;
      }
    }

    textNode.nodeValue = maxChunk;
  }

  function truncateNestedNode(element, rootNode, options) {

    var childNodes = element.childNodes,
        length = childNodes.length;

    if (length === 0) {

      // Base case: single element remaining

      if (element.nodeType === element.TEXT_NODE) {
        // Truncate the text node
        truncateTextNode(element, rootNode, options);
      } else {
        // Remove the node itself
        element.parentNode.removeChild(element);
      }

      return;

    } else {

      // Recursive case: iterate backwards on children nodes until tipping node is found

      var index, node, chunk;
      var originalHTML = element.innerHTML;

      for (index = length - 1; index >= 0; index--) {
        node = childNodes[index];

        chunk = getHTMLInRange(element, 0, index);
        element.innerHTML = chunk;

        if (height(rootNode) <= options.maxHeight) {

          // Check if element is not the last child
          if (index + 1 <= length - 1) {
            // Reset HTML so original childNodes tree is available
            element.innerHTML = originalHTML;

            chunk += getHTMLInRange(element, index + 1, index + 1);
            element.innerHTML = chunk;

            index += 1;
          }

          return truncateNestedNode(childNodes[index], rootNode, options);
        }
      }

      return truncateNestedNode(childNodes[0], rootNode, options);

    }
  }

  /* Public: Creates an instance of Truncate.
   *
   * element - A DOM element to be truncated.
   * options - An Object literal containing setup options.
   *
   * Examples:
   *
   *   var element = document.createElement('span');
   *   element.innerHTML = 'This is
odd.';
   *   var truncated = new Truncate(element, {
   *     lines: 1,
   *     lineHeight: 16,
   *     showMore: 'Show More',
   *     showLess: 'Show Less'
   *   });
   *
   *   // Update HTML
   *   truncated.update('This is not very odd.');
   *
   *   // Undo truncation
   *   truncated.expand();
   *
   *   // Redo truncation
   *   truncated.collapse();
   */
  function Truncate(element, options) {
    this.options = options || {};
    options.showMore = typeof options.showMore !== 'undefined' ? options.showMore : '…';
    options.showLess = typeof options.showLess !== 'undefined' ? options.showLess : '';

    this.options.maxHeight = options.lines * options.lineHeight;

    this.element = element;
    this.originalHTML = element.innerHTML;
    this.cachedHTML = null;

    this.update();
  }

  /* Public: Updates the inner HTML of the element and re-truncates.
   *
   * newHTML - The new HTML.
   *
   * Returns nothing.
   */
  Truncate.prototype.update = function (newHTML) {
    // Update HTML if provided, otherwise default to current inner HTML.
    if (newHTML) {
      this.originalHTML = this.element.innerHTML = newHTML;
    }

    // Already meets height requirement
    if (height(this.element) <= this.options.maxHeight) {
      return;
    }

    var visibility = this.element.style.visibility;
    this.element.style.visibility = 'hidden';

    truncateNestedNode(this.element, this.element, this.options);
    this.cachedHTML = this.element.innerHTML;

    this.element.style.visibility = visibility;
  };

  /* Public: Expands the element to show content in full.
   *
   * Returns nothing.
   */
  Truncate.prototype.expand = function () {
    this.element.innerHTML = this.originalHTML + this.options.showLess;
  };

  /* Public: Collapses the element to the truncated state.
   * Uses the cached HTML from .update().
   *
   * Returns nothing.
   */
  Truncate.prototype.collapse = function () {
    this.element.innerHTML = this.cachedHTML;
  };

  module.Truncate = Truncate;

})(this);
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow strict-local
 */

'use strict';

import type {DangerouslyImpreciseStyle} from './StyleSheet';

const OUTER_PROPS = Object.assign(Object.create(null), {
  margin: true,
  marginHorizontal: true,
  marginVertical: true,
  marginBottom: true,
  marginTop: true,
  marginLeft: true,
  marginRight: true,
  flex: true,
  flexGrow: true,
  flexShrink: true,
  flexBasis: true,
  alignSelf: true,
  height: true,
  minHeight: true,
  maxHeight: true,
  width: true,
  minWidth: true,
  maxWidth: true,
  position: true,
  left: true,
  right: true,
  bottom: true,
  top: true,
  transform: true,
});

function splitLayoutProps(
  props: ?DangerouslyImpreciseStyle,
): {
  outer: DangerouslyImpreciseStyle,
  inner: DangerouslyImpreciseStyle,
  ...
} {
  const inner = {};
  const outer = {};
  if (props) {
    Object.keys(props).forEach(k => {
      const value: $ElementType<DangerouslyImpreciseStyle, typeof k> = props[k];
      if (OUTER_PROPS[k]) {
        outer[k] = value;
      } else {
        inner[k] = value;
      }
    });
  }
  return {outer, inner};
}

module.exports = splitLayoutProps;
<commit_msg>Add type annotations to prevent issues with planned Flow changes<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow strict-local
 */

'use strict';

import type {DangerouslyImpreciseStyle} from './StyleSheet';

const OUTER_PROPS = Object.assign(Object.create(null), {
  margin: true,
  marginHorizontal: true,
  marginVertical: true,
  marginBottom: true,
  marginTop: true,
  marginLeft: true,
  marginRight: true,
  flex: true,
  flexGrow: true,
  flexShrink: true,
  flexBasis: true,
  alignSelf: true,
  height: true,
  minHeight: true,
  maxHeight: true,
  width: true,
  minWidth: true,
  maxWidth: true,
  position: true,
  left: true,
  right: true,
  bottom: true,
  top: true,
  transform: true,
});

function splitLayoutProps(
  props: ?DangerouslyImpreciseStyle,
): {
  outer: DangerouslyImpreciseStyle,
  inner: DangerouslyImpreciseStyle,
  ...
} {
  const inner = {};
  const outer = {};
  if (props) {
    Object.keys(props).forEach((k: string) => {
      const value = props[k];
      if (OUTER_PROPS[k]) {
        outer[k] = value;
      } else {
        inner[k] = value;
      }
    });
  }
  return {outer, inner};
}

module.exports = splitLayoutProps;
<|endoftext|>