<commit_before>(function(){
	/**
	 * ClientKeyframeAnimation implementation
	 * @param{string} name name of the animation
	 * @param{Array.<number>} keys keys
	 * @param{Array.<number>|undefined} positionValues
	 * @param{Array.<number>|undefined} orientationValues
	 * @constructor
	 * @implements{Animation}
	 */
	function ClientKeyframeAnimation(name, keys, positionValues, orientationValues, scaleValues, opt){

		/**
		 * name of animation
		 * @private
		 * @type {string}
		 */
		this.name = name;
		/**
		 * Array of the keys
		 * @private
		 * @type{Array.<number>}
		 */
		this.keys = keys;
		/**
		 * Array fo the position values
		 * @private
		 * @type{Array.<number>|undefined}
		 */
		this.positionValues = positionValues;
		/**
		 * Array of the orientation values
		 * @private
		 * @type{Array.<number>|undefined}
		 */
		this.orientationValues = orientationValues;
		/**
		 * Array of the scale values
		 * @private
		 * @type{Array.<number>|undefined}
		 */
		this.scaleValues = scaleValues;

		//options - set defaults
		/**
		 * loop
		 * @private
		 * @type {number}
		 */
		this.loop = 1;
		/**
		 * delay
		 * @private
		 * @type{number}
		 */
		this.delay = 0;
		/**
		 * Duration of the animation
		 * @private
		 * @type {number}
		 */
		this.duration = 1000;
		/**
		 * easing
		 * @private
		 * @type {Function}
		 */
		this.easing = TWEEN.Easing.Linear.None;
		/**
		 * Callback, executed as soon as the animation ended
		 * @private
		 * @type {Function}
		 */
		this.callback = function(){};
		if(opt){
			this.setOptions(opt);
		}
	};

	var k = ClientKeyframeAnimation.prototype;

	/** @inheritDoc */
	k.applyAnimation = function(animatable, currentTime, startTime, endTime, easing){
		var t = (currentTime - startTime) / (endTime - startTime);
		if(easing && typeof(easing) === "function") t = easing(t); //otherwise its linear
		var l = this.keys.length - 1;
		if (t <= this.keys[0]){
			this.setValue( animatable, this.getPosition(0), this.getOrientation(0) );
		}else if (t >= this.keys[l - 1]){
			this.setValue( animatable, this.getPosition(l), this.getOrientation(l) );
		}else{
			for ( var i = 0; i < l - 1; i++){
				if (this.keys[i] < t && t <= this.keys[i + 1]) {
					var p = (t - this.keys[i]) / (this.keys[i + 1] - this.keys[i]);
					this.setValue( animatable, this.getInterpolatedPosition(i, p), this.getInterpolatedOrientation(i, p), this.getInterpolatedScale(i, p) );
				}
			}
		}
	};

	/**
	 * Set position and animation of the animatable
	 * @private
	 * @param {Animatable} animatable
	 * @param {Array.<number>|undefined} position
	 * @param {Array.<number>|undefined} orientation
	 */
	k.setValue = function(animatable, position, orientation, scale){
		if(position != undefined)
			animatable.setPosition(position);
		if(orientation != undefined)
			animatable.setOrientation(orientation);
		if(scale != undefined)
			animatable.setScale(scale);
	};

	/**
	 * Interpolates positionvalues between index i and index i+1 with parameter t
	 * @private
	 * @param {number} index
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} Position
	 */
	k.getInterpolatedPosition = function(index, t){
		if(this.positionValues == undefined) return undefined;
		return this.interpolateArray(this.getPosition(index), this.getPosition(index+1), t);
	};

	/**
	 * Interpolates scalevalues between index i and index i+1 with parameter t
	 * @private
	 * @param {number} index
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} Position
	 */
	k.getInterpolatedScale = function(index, t){
		if(this.scaleValues == undefined) return undefined;
		return this.interpolateArray(this.getScale(index), this.getScale(index+1), t);
	};

	/**
	 * Interpolate the values of two arrays
	 * @private
	 * @param{Array.<number>} a1 array 1
	 * @param{Array.<number>} a2 array 2
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} interpolated array
	 */
	k.interpolateArray = function(a1, a2, t){
		var ret = [];
		var i = 0;
		var l = a1.length;
		if(a1.length != a2.length) return undefined;
		for(i=0; i<l; i++ ){
			ret[i] = a1[i] + ( a2[i] - a1[i] ) * t;
		}
		return ret;
	};

	/**
	 * Interpolates keyvalues between index i and index i+1 with parameter t
	 * @private
	 * @param {number} index
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} Orientation
	 */
	k.getInterpolatedOrientation = function(index, t){
		if(this.orientationValues == undefined) return undefined;
		var start = this.getOrientation(index);
		var end = this.getOrientation(index+1);
		return XMOT.slerp(start, end, t);
	};

	/**
	 * Gets a position corresponding to a key
	 * @private
	 * @param {number} key
	 * @return {Array.<number>|undefined} Position
	 */
	k.getPosition = function(key){
		if(this.positionValues == undefined || key > this.keys.length-1 /*just in case*/) return undefined;
		var index = key*3;
		return [ this.positionValues[index], this.positionValues[index+1], this.positionValues[index+2] ];
	};

	/**
	 * Gets a sacle corresponding to a key
	 * @private
	 * @param {number} key
	 * @return {Array.<number>|undefined} Position
	 */
	k.getScale = function(key){
		if(this.scaleValues == undefined || key > this.keys.length-1 /*just in case*/) return undefined;
		var index = key*3;
		return [ this.scaleValues[index], this.scaleValues[index+1], this.scaleValues[index+2] ];
	};

	/**
	 * Gets an orientation corresponding to a key
	 * @private
	 * @param {number} key
	 * @return {Array.<number>|undefined} Orientation
	 */
	k.getOrientation = function(key){
		if(this.orientationValues == undefined || key > this.keys.length-1 /*just in case*/) return undefined;
		var index = key*4;
		return [ this.orientationValues[index], this.orientationValues[index+1], this.orientationValues[index+2], this.orientationValues[index+3] ];
	};

	/** @inheritDoc */
	k.getOptions = function(){
		return {duration: this.duration, loop: this.loop, delay: this.delay, easing: this.easing, callback: this.callback};
	};

    /** @inheritDoc */
    k.setOptions = function(opt){
		if(opt.loop)
			this.loop = opt.loop;
		if(opt.duration)
			this.duration = opt.duration;
		if(opt.easingk && typeof(opt.easing) === "function")
			this.easing = opt.easing;
		if(opt.callback && typeof(opt.callback) === "function")
			this.callback = opt.callback;
    };

	//export
	XMOT.ClientKeyframeAnimation = ClientKeyframeAnimation;
}());<commit_msg>Bugfix: apply the last key as well<commit_after>(function(){
	/**
	 * ClientKeyframeAnimation implementation
	 * @param{string} name name of the animation
	 * @param{Array.<number>} keys keys
	 * @param{Array.<number>|undefined} positionValues
	 * @param{Array.<number>|undefined} orientationValues
	 * @constructor
	 * @implements{Animation}
	 */
	function ClientKeyframeAnimation(name, keys, positionValues, orientationValues, scaleValues, opt){

		/**
		 * name of animation
		 * @private
		 * @type {string}
		 */
		this.name = name;
		/**
		 * Array of the keys
		 * @private
		 * @type{Array.<number>}
		 */
		this.keys = keys;
		/**
		 * Array fo the position values
		 * @private
		 * @type{Array.<number>|undefined}
		 */
		this.positionValues = positionValues;
		/**
		 * Array of the orientation values
		 * @private
		 * @type{Array.<number>|undefined}
		 */
		this.orientationValues = orientationValues;
		/**
		 * Array of the scale values
		 * @private
		 * @type{Array.<number>|undefined}
		 */
		this.scaleValues = scaleValues;

		//options - set defaults
		/**
		 * loop
		 * @private
		 * @type {number}
		 */
		this.loop = 1;
		/**
		 * delay
		 * @private
		 * @type{number}
		 */
		this.delay = 0;
		/**
		 * Duration of the animation
		 * @private
		 * @type {number}
		 */
		this.duration = 1000;
		/**
		 * easing
		 * @private
		 * @type {Function}
		 */
		this.easing = TWEEN.Easing.Linear.None;
		/**
		 * Callback, executed as soon as the animation ended
		 * @private
		 * @type {Function}
		 */
		this.callback = function(){};
		if(opt){
			this.setOptions(opt);
		}
	};

	var k = ClientKeyframeAnimation.prototype;

	/** @inheritDoc */
	k.applyAnimation = function(animatable, currentTime, startTime, endTime, easing){
		var t = (currentTime - startTime) / (endTime - startTime);
		if(easing && typeof(easing) === "function") t = easing(t); //otherwise its linear
		var lmo = this.keys.length - 1;
		if (t <= this.keys[0]){
			this.setValue( animatable, this.getPosition(0), this.getOrientation(0), this.getScale(0) );
		}else if (t >= this.keys[lmo]){
			this.setValue( animatable, this.getPosition(lmo), this.getOrientation(lmo), this.getScale(lmo) );
		}else{
			for ( var i = 0; i < lmo; i++){
				if (this.keys[i] < t && t <= this.keys[i + 1]) {
					var p = (t - this.keys[i]) / (this.keys[i + 1] - this.keys[i]);
					this.setValue( animatable, this.getInterpolatedPosition(i, p), this.getInterpolatedOrientation(i, p), this.getInterpolatedScale(i, p) );
				}
			}
		}
	};

	/**
	 * Set position and animation of the animatable
	 * @private
	 * @param {Animatable} animatable
	 * @param {Array.<number>|undefined} position
	 * @param {Array.<number>|undefined} orientation
	 */
	k.setValue = function(animatable, position, orientation, scale){
		if(position != undefined)
			animatable.setPosition(position);
		if(orientation != undefined)
			animatable.setOrientation(orientation);
		if(scale != undefined)
			animatable.setScale(scale);
	};

	/**
	 * Interpolates positionvalues between index i and index i+1 with parameter t
	 * @private
	 * @param {number} index
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} Position
	 */
	k.getInterpolatedPosition = function(index, t){
		if(this.positionValues == undefined) return undefined;
		return this.interpolateArray(this.getPosition(index), this.getPosition(index+1), t);
	};

	/**
	 * Interpolates scalevalues between index i and index i+1 with parameter t
	 * @private
	 * @param {number} index
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} Position
	 */
	k.getInterpolatedScale = function(index, t){
		if(this.scaleValues == undefined) return undefined;
		return this.interpolateArray(this.getScale(index), this.getScale(index+1), t);
	};

	/**
	 * Interpolate the values of two arrays
	 * @private
	 * @param{Array.<number>} a1 array 1
	 * @param{Array.<number>} a2 array 2
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} interpolated array
	 */
	k.interpolateArray = function(a1, a2, t){
		var ret = [];
		var i = 0;
		var l = a1.length;
		if(a1.length != a2.length) return undefined;
		for(i=0; i<l; i++ ){
			ret[i] = a1[i] + ( a2[i] - a1[i] ) * t;
		}
		return ret;
	};

	/**
	 * Interpolates keyvalues between index i and index i+1 with parameter t
	 * @private
	 * @param {number} index
	 * @param {number} t interpolationparameter
	 * @return {Array.<number>|undefined} Orientation
	 */
	k.getInterpolatedOrientation = function(index, t){
		if(this.orientationValues == undefined) return undefined;
		var start = this.getOrientation(index);
		var end = this.getOrientation(index+1);
		return XMOT.slerp(start, end, t);
	};

	/**
	 * Gets a position corresponding to a key
	 * @private
	 * @param {number} key
	 * @return {Array.<number>|undefined} Position
	 */
	k.getPosition = function(key){
		if(this.positionValues == undefined || key > this.keys.length-1 /*just in case*/) return undefined;
		var index = key*3;
		return [ this.positionValues[index], this.positionValues[index+1], this.positionValues[index+2] ];
	};

	/**
	 * Gets a sacle corresponding to a key
	 * @private
	 * @param {number} key
	 * @return {Array.<number>|undefined} Position
	 */
	k.getScale = function(key){
		if(this.scaleValues == undefined || key > this.keys.length-1 /*just in case*/) return undefined;
		var index = key*3;
		return [ this.scaleValues[index], this.scaleValues[index+1], this.scaleValues[index+2] ];
	};

	/**
	 * Gets an orientation corresponding to a key
	 * @private
	 * @param {number} key
	 * @return {Array.<number>|undefined} Orientation
	 */
	k.getOrientation = function(key){
		if(this.orientationValues == undefined || key > this.keys.length-1 /*just in case*/) return undefined;
		var index = key*4;
		return [ this.orientationValues[index], this.orientationValues[index+1], this.orientationValues[index+2], this.orientationValues[index+3] ];
	};

	/** @inheritDoc */
	k.getOptions = function(){
		return {duration: this.duration, loop: this.loop, delay: this.delay, easing: this.easing, callback: this.callback};
	};

    /** @inheritDoc */
    k.setOptions = function(opt){
		if(opt.loop)
			this.loop = opt.loop;
		if(opt.duration)
			this.duration = opt.duration;
		if(opt.easingk && typeof(opt.easing) === "function")
			this.easing = opt.easing;
		if(opt.callback && typeof(opt.callback) === "function")
			this.callback = opt.callback;
    };

	//export
	XMOT.ClientKeyframeAnimation = ClientKeyframeAnimation;
}());<|endoftext|>


<commit_before>lucid.html.dataTable = {
    'colSelector':'table > thead > tr > th',
    'refreshSelector':'table > tbody',
    'pagerSelector':'span.data-table-pager',
    'colsSelector':'table > thead',
    'sortIconSelector':'i',
    'searchDelay':300,
    'refreshTimeouts':{}
};

lucid.html.dataTable.getTableProperties=function(obj){
    obj = jQuery(obj);
    while(obj.hasClass('data-table') === false){
        obj = obj.parent();
    }

    var props = {
        'jquery'       :obj,
        'id'           :obj.attr('id'),
        'sort-col'     :parseInt(obj.attr('data-sort-col')),
        'sort-dir'     :(obj.attr('data-sort-dir') == 'desc')?'desc':'asc',
        'current-page' :parseInt(obj.attr('data-current-page')),
        'max-page'     :parseInt(obj.attr('data-max-page')),
        'rows-per-page':parseInt(obj.attr('data-rows-per-page')),
        'refresh-url'  :obj.attr('data-refresh-url'),
        'filters'      :{},

        'setProperty':function(prop, value){
            this[prop] = value;
            this.jquery.attr('data-'+prop, value);
            return this;
        }
    };

    var filterList = String(obj.attr('data-filters')).split(',');
    for(var i=0; i<filterList.length; i++){
        props.filters[filterList[i]] = window.jQuery('#'+props.id+'-filter-'+filterList[i]).val();
    }
    return props;
};

lucid.html.dataTable.getRefreshParameters=function(props){
    var data = {
        'sort-col'     : props['sort-col'],
        'sort-dir'     : props['sort-dir'],
        'current-page' : props['current-page'],
        'rows-per-page': props['rows-per-page'],
        'refresh-data' : props.id
    };
    for(var key in props.filters){
        data['filter-'+key] = props.filters[key];
    }
    return data;
};

lucid.html.dataTable.sort=function(col){
    var props = lucid.html.dataTable.getTableProperties(col);
    var cols  = props.jquery.find(lucid.html.dataTable.colSelector);
    var thisCol = null;
    for(var i=0; i<cols.length; i++){
        if(cols[i] == col){
            thisCol = i;
        }
    }
    if(thisCol == props['sort-col']){
        props.setProperty('sort-dir', (props['sort-dir'] == 'asc')?'desc':'asc');
    }else{
        props.setProperty('sort-col', thisCol);
        props.setProperty('sort-dir', 'asc');
    }
    props.setProperty('current-page', 0);
    lucid.html.dataTable.updateSortIndictors(props);
    lucid.html.dataTable.requestData(props);
};

lucid.html.dataTable.page=function(pager, direction){
    var props = lucid.html.dataTable.getTableProperties(pager);
    var newPage = props['current-page'];
    switch(direction){
        case 'first':
            newPage = 0;
            break;
        case 'previous':
            newPage--;
            break;
        case 'next':
            newPage++;
            break;
        case 'last':
            newPage = (props['max-page'] - 1);
            break;
        default:
            newPage = parseInt(direction);
            break;
    }

    if(newPage < 0){
        newPage = 0;
    }
    if(newPage >= props['max-page']){
        newPage = (props['max-page'] - 1);
    }

    if(newPage != props['current-page']){
        props.setProperty('current-page', newPage);
        html.dataTable.requestData(props);
    }
};

lucid.html.dataTable.filter = function(filter, delay){
    var props = lucid.html.dataTable.getTableProperties(filter);
    props.setProperty('current-page',0);
    if(delay === false){
        html.dataTable.requestData(props);
    }else{
        window.clearTimeout(lucid.html.dataTable.refreshTimeouts[props.id]);
        lucid.html.dataTable.refreshTimeouts[props.id] = window.setTimeout(function(){
            lucid.html.dataTable.requestData(props);
        }, lucid.html.dataTable.searchDelay);
    }
};

lucid.html.dataTable.noDataMessage=function(props, show){
    if(show === true){
        props.jquery.find(lucid.html.dataTable.colsSelector).hide();
        props.jquery.find(lucid.html.dataTable.pagerSelector).hide();
    }else{
        props.jquery.find(lucid.html.dataTable.colsSelector).show();
        props.jquery.find(lucid.html.dataTable.pagerSelector).show();
    }
};

lucid.html.dataTable.requestData=function(props){
    window.jQuery.ajax(props['refresh-url'], {
        'method':'POST',
        'data':lucid.html.dataTable.getRefreshParameters(props),
        'complete':function(response, statusCode){
            console.log('loading new data');
            props.jquery.find(lucid.html.dataTable.refreshSelector).html(response.responseJSON.tbody);
            props.setProperty('max-page', response.responseJSON.max_page);
            html.dataTable.updatePager(props, response.responseJSON.pager);
            html.dataTable.noDataMessage(props, (response.responseJSON.max_page === 0));
        }
    });
};

lucid.html.dataTable.updateSortIndictors=function(props){
    var cols = props.jquery.find(lucid.html.dataTable.colSelector);
    console.log(cols);
    var i = 0;
    cols.each(function(){
        var col = $(this);
        if(col.attr('data-sortable') == 'true'){
            var sortIcon = col.find(lucid.html.dataTable.sortIconSelector);
            sortIcon.removeClass('fa-chevron-up fa-chevron-down fa-chevron-right');
            if(i == props['sort-col']){
                sortIcon.addClass('fa-chevron-'+((props['sort-dir'] == 'asc')?'up':'down'));
            }else{
                sortIcon.addClass('fa-chevron-right');
            }
        }
        i++;
    });
};

lucid.html.dataTable.updatePager=function(props, newPager){
    var pager = props.jquery.find(lucid.html.dataTable.pagerSelector);
    pager.html(newPager);
};
<commit_msg>fixing function names due to renames<commit_after>lucid.html.dataTable = {
    'colSelector':'table > thead > tr > th',
    'refreshSelector':'table > tbody',
    'pagerSelector':'span.data-table-pager',
    'colsSelector':'table > thead',
    'sortIconSelector':'i',
    'searchDelay':300,
    'refreshTimeouts':{}
};

lucid.html.dataTable.getTableProperties=function(obj){
    obj = jQuery(obj);
    while(obj.hasClass('data-table') === false){
        obj = obj.parent();
    }

    var props = {
        'jquery'       :obj,
        'id'           :obj.attr('id'),
        'sort-col'     :parseInt(obj.attr('data-sort-col')),
        'sort-dir'     :(obj.attr('data-sort-dir') == 'desc')?'desc':'asc',
        'current-page' :parseInt(obj.attr('data-current-page')),
        'max-page'     :parseInt(obj.attr('data-max-page')),
        'rows-per-page':parseInt(obj.attr('data-rows-per-page')),
        'refresh-url'  :obj.attr('data-refresh-url'),
        'filters'      :{},

        'setProperty':function(prop, value){
            this[prop] = value;
            this.jquery.attr('data-'+prop, value);
            return this;
        }
    };

    var filterList = String(obj.attr('data-filters')).split(',');
    for(var i=0; i<filterList.length; i++){
        props.filters[filterList[i]] = window.jQuery('#'+props.id+'-filter-'+filterList[i]).val();
    }
    return props;
};

lucid.html.dataTable.getRefreshParameters=function(props){
    var data = {
        'sort-col'     : props['sort-col'],
        'sort-dir'     : props['sort-dir'],
        'current-page' : props['current-page'],
        'rows-per-page': props['rows-per-page'],
        'refresh-data' : props.id
    };
    for(var key in props.filters){
        data['filter-'+key] = props.filters[key];
    }
    return data;
};

lucid.html.dataTable.sort=function(col){
    var props = lucid.html.dataTable.getTableProperties(col);
    var cols  = props.jquery.find(lucid.html.dataTable.colSelector);
    var thisCol = null;
    for(var i=0; i<cols.length; i++){
        if(cols[i] == col){
            thisCol = i;
        }
    }
    if(thisCol == props['sort-col']){
        props.setProperty('sort-dir', (props['sort-dir'] == 'asc')?'desc':'asc');
    }else{
        props.setProperty('sort-col', thisCol);
        props.setProperty('sort-dir', 'asc');
    }
    props.setProperty('current-page', 0);
    lucid.html.dataTable.updateSortIndictors(props);
    lucid.html.dataTable.requestData(props);
};

lucid.html.dataTable.page=function(pager, direction){
    var props = lucid.html.dataTable.getTableProperties(pager);
    var newPage = props['current-page'];
    switch(direction){
        case 'first':
            newPage = 0;
            break;
        case 'previous':
            newPage--;
            break;
        case 'next':
            newPage++;
            break;
        case 'last':
            newPage = (props['max-page'] - 1);
            break;
        default:
            newPage = parseInt(direction);
            break;
    }

    if(newPage < 0){
        newPage = 0;
    }
    if(newPage >= props['max-page']){
        newPage = (props['max-page'] - 1);
    }

    if(newPage != props['current-page']){
        props.setProperty('current-page', newPage);
        lucid.html.dataTable.requestData(props);
    }
};

lucid.html.dataTable.filter = function(filter, delay){
    var props = lucid.html.dataTable.getTableProperties(filter);
    props.setProperty('current-page',0);
    if(delay === false){
        lucid.html.dataTable.requestData(props);
    }else{
        window.clearTimeout(lucid.html.dataTable.refreshTimeouts[props.id]);
        lucid.html.dataTable.refreshTimeouts[props.id] = window.setTimeout(function(){
            lucid.html.dataTable.requestData(props);
        }, lucid.html.dataTable.searchDelay);
    }
};

lucid.html.dataTable.noDataMessage=function(props, show){
    if(show === true){
        props.jquery.find(lucid.html.dataTable.colsSelector).hide();
        props.jquery.find(lucid.html.dataTable.pagerSelector).hide();
    }else{
        props.jquery.find(lucid.html.dataTable.colsSelector).show();
        props.jquery.find(lucid.html.dataTable.pagerSelector).show();
    }
};

lucid.html.dataTable.requestData=function(props){
    window.jQuery.ajax(props['refresh-url'], {
        'method':'POST',
        'data':lucid.html.dataTable.getRefreshParameters(props),
        'complete':function(response, statusCode){
            console.log('loading new data');
            props.jquery.find(lucid.html.dataTable.refreshSelector).html(response.responseJSON.tbody);
            props.setProperty('max-page', response.responseJSON.max_page);
            lucid.html.dataTable.updatePager(props, response.responseJSON.pager);
            lucid.html.dataTable.noDataMessage(props, (response.responseJSON.max_page === 0));
        }
    });
};

lucid.html.dataTable.updateSortIndictors=function(props){
    var cols = props.jquery.find(lucid.html.dataTable.colSelector);
    console.log(cols);
    var i = 0;
    cols.each(function(){
        var col = $(this);
        if(col.attr('data-sortable') == 'true'){
            var sortIcon = col.find(lucid.html.dataTable.sortIconSelector);
            sortIcon.removeClass('fa-chevron-up fa-chevron-down fa-chevron-right');
            if(i == props['sort-col']){
                sortIcon.addClass('fa-chevron-'+((props['sort-dir'] == 'asc')?'up':'down'));
            }else{
                sortIcon.addClass('fa-chevron-right');
            }
        }
        i++;
    });
};

lucid.html.dataTable.updatePager=function(props, newPager){
    var pager = props.jquery.find(lucid.html.dataTable.pagerSelector);
    pager.html(newPager);
};
<|endoftext|>


<commit_before>"use strict"

const ansi = require("./ansi")

module.exports = function (strings) {
    let v = "", t = "", prev = "", tags = [], vals = [], result = []

    for (let i = 0; i < strings.length; i++) {
        let s = strings[i]

        for (let j = 0; j < s.length; j++) {
            let c = s[j]

            if (c === "<") {
                if (v !== "") {
                    if (tags.length === 0) {
                        result.push(v)
                    } else {
                        if (Array.isArray(vals[vals.length - 1])) {
                            vals[vals.length - 1].push(v)

                        } else {
                            vals.push(v)
                        }
                    }
                    v = ""
                }

                if (prev === c) {
                    throw SyntaxError("Unexpected <")
                }

                prev = c
                continue
            }

            if (c === ">") {
                if (t === "") {
                    throw SyntaxError("Unexpected >")
                }

                if (prev === "/") {
                    const tag = tags.pop()

                    if (tag !== t) {
                        throw SyntaxError("Unxpected tag: " + tag)
                    }

                    const obj = {
                        style: tag,
                        value: Array.isArray(vals[vals.length - 1])
                            ? vals.pop()
                            : vals//.slice()
                    }

                    if (tags.length === 0) {
                        result.push(obj)

                        if (Array.isArray(vals[vals.length - 1]))
                            delete vals[vals.length - 1]
                        else
                            vals = []
                    } else {
                        if (Array.isArray(vals[vals.length - 1])) {
                            vals[vals.length - 1].push(obj)
                        } else {
                            vals.push(obj)
                        }
                    }

                } else {
                    if (tags.length > 0) {
                        vals.push([])
                    }
                    tags.push(t)
                }

                prev = c

                t = ""
                continue
            }

            if (c === "/") {
                if (prev === "<") {
                    prev = c
                    continue
                } else {
                    v += c
                }
            }

            if (prev === "<" || prev === "/") {
                t += c
            } else {
                v += c
            }

        }//j

        v += arguments[i + 1] || ""

    }//i

    if (v !== "") {
        result.push(v)
    }

    const unwrap = obj => Object.keys(obj).map(k => obj[k]).reduce((s, i) =>
        s + (i.style ? ansi[i.style][0] + unwrap(i.value) + ansi[i.style][1] : i), "")

    return unwrap(result) + ansi.reset[0]
}
<commit_msg>Fix #8.<commit_after>"use strict"

const ansi = require("./ansi")

const cx = c => function (strings) {
    let v = "", t = "", prev = "", tags = [], vals = [], result = []

    for (let i = 0; i < strings.length; i++) {
        let s = strings[i]

        for (let j = 0; j < s.length; j++) {
            let c = s[j]

            if (c === "<") {
                if (v !== "") {
                    if (tags.length === 0) {
                        result.push(v)
                    } else {
                        if (Array.isArray(vals[vals.length - 1])) {
                            vals[vals.length - 1].push(v)

                        } else {
                            vals.push(v)
                        }
                    }
                    v = ""
                }

                if (prev === c) {
                    throw SyntaxError("Unexpected <")
                }

                prev = c
                continue
            }

            if (c === ">") {
                if (t === "") {
                    throw SyntaxError("Unexpected >")
                }

                if (prev === "/") {
                    const tag = tags.pop()

                    if (tag !== t) {
                        throw SyntaxError("Unxpected tag: " + tag)
                    }

                    const obj = {
                        style: tag,
                        value: Array.isArray(vals[vals.length - 1])
                            ? vals.pop()
                            : vals//.slice()
                    }

                    if (tags.length === 0) {
                        result.push(obj)

                        if (Array.isArray(vals[vals.length - 1]))
                            delete vals[vals.length - 1]
                        else
                            vals = []
                    } else {
                        if (Array.isArray(vals[vals.length - 1])) {
                            vals[vals.length - 1].push(obj)
                        } else {
                            vals.push(obj)
                        }
                    }

                } else {
                    if (tags.length > 0) {
                        vals.push([])
                    }
                    tags.push(t)
                }

                prev = c

                t = ""
                continue
            }

            if (c === "/") {
                if (prev === "<") {
                    prev = c
                    continue
                }
            }

            if (prev === "<" || prev === "/") {
                t += c
            } else {
                v += c
            }

        }//j

        v += arguments[i + 1] || ""

    }//i

    if (v !== "") {
        result.push(v)
    }

    return c(result) + ansi.reset[0]
}

const c = obj => Object
    .keys(obj)
    .map(k => obj[k])
    .reduce((s, i) => s + (i.style
        ? ansi[i.style][0] + c(i.value) + ansi[i.style][1]
        : i), "")

module.exports = cx(c)<|endoftext|>


<commit_before>"use strict";

const _ = require("lodash");
const basicChecks = require("./lib/testUtils/basicChecks");
const less = require("postcss-less");
const stylelint = require("./lib/standalone");

jest.mock("./lib/utils/getOsEol", () => () => "\n");

global.testRule = (rule, schema) => {
  expect.extend({
    toHaveMessage(testCase) {
      if (testCase.message === undefined) {
        return {
          message: () =>
            'Expected "reject" test case to have a "message" property',
          pass: false
        };
      }

      return {
        pass: true
      };
    }
  });

  describe(schema.ruleName, () => {
    const stylelintConfig = {
      rules: {
        [schema.ruleName]: schema.config
      }
    };

    let passingTestCases = schema.accept || [];
    if (!schema.skipBasicChecks) {
      passingTestCases = passingTestCases.concat(basicChecks);
    }

    if (passingTestCases && passingTestCases.length) {
      describe("accept", () => {
        passingTestCases.forEach(testCase => {
          const spec = testCase.only ? it.only : it;
          describe(JSON.stringify(schema.config, replacer), () => {
            describe(JSON.stringify(testCase.code), () => {
              spec(testCase.description || "no description", () => {
                const options = {
                  code: testCase.code,
                  config: stylelintConfig,
                  syntax: schema.syntax
                };
                return stylelint(options).then(output => {
                  expect(output.results[0].warnings).toEqual([]);
                  expect(output.results[0].parseErrors).toEqual([]);
                  if (!schema.fix) return;

                  // Check the fix
                  return stylelint(Object.assign({ fix: true }, options)).then(
                    output => {
                      const fixedCode = getOutputCss(output);
                      expect(fixedCode).toBe(testCase.code);
                    }
                  );
                });
              });
            });
          });
        });
      });
    }

    if (schema.reject && schema.reject.length) {
      describe("reject", () => {
        schema.reject.forEach(testCase => {
          const spec = testCase.only ? it.only : it;
          describe(JSON.stringify(schema.config, replacer), () => {
            describe(JSON.stringify(testCase.code), () => {
              spec(testCase.description || "no description", () => {
                const options = {
                  code: testCase.code,
                  config: stylelintConfig,
                  syntax: schema.syntax
                };
                return stylelint(options).then(output => {
                  const warning = output.results[0].warnings[0];

                  expect(output.results[0].parseErrors).toEqual([]);
                  expect(testCase).toHaveMessage();

                  if (testCase.message !== undefined) {
                    expect(_.get(warning, "text")).toBe(testCase.message);
                  }
                  if (testCase.line !== undefined) {
                    expect(_.get(warning, "line")).toBe(testCase.line);
                  }
                  if (testCase.column !== undefined) {
                    expect(_.get(warning, "column")).toBe(testCase.column);
                  }

                  if (!schema.fix) return;

                  if (!testCase.fixed) {
                    throw new Error(
                      "If using { fix: true } in test schema, all reject cases must have { fixed: .. }"
                    );
                  }

                  // Check the fix
                  return stylelint(Object.assign({ fix: true }, options)).then(
                    output => {
                      const fixedCode = getOutputCss(output);
                      expect(fixedCode).toBe(testCase.fixed);
                      expect(fixedCode).not.toBe(testCase.code);
                    }
                  );
                });
              });
            });
          });
        });
      });
    }
  });
};

function getOutputCss(output) {
  const result = output.results[0]._postcssResult;
  const css = result.root.toString(result.opts.syntax);
  if (result.opts.syntax === less) {
    // Less needs us to manually strip whitespace at the end of single-line comments ¯\_(ツ)_/¯
    return css.replace(/(\n?\s*\/\/.*?)[ \t]*(\r?\n)/g, "$1$2");
  }
  return css;
}

function replacer(key, value) {
  return value instanceof RegExp ? `[RegExp] ${value.toString()}` : value;
}
<commit_msg>Increase Jest timeout<commit_after>"use strict";

const _ = require("lodash");
const basicChecks = require("./lib/testUtils/basicChecks");
const less = require("postcss-less");
const stylelint = require("./lib/standalone");

// Temporarily increase timeout
jest.setTimeout(10000);

jest.mock("./lib/utils/getOsEol", () => () => "\n");

global.testRule = (rule, schema) => {
  expect.extend({
    toHaveMessage(testCase) {
      if (testCase.message === undefined) {
        return {
          message: () =>
            'Expected "reject" test case to have a "message" property',
          pass: false
        };
      }

      return {
        pass: true
      };
    }
  });

  describe(schema.ruleName, () => {
    const stylelintConfig = {
      rules: {
        [schema.ruleName]: schema.config
      }
    };

    let passingTestCases = schema.accept || [];
    if (!schema.skipBasicChecks) {
      passingTestCases = passingTestCases.concat(basicChecks);
    }

    if (passingTestCases && passingTestCases.length) {
      describe("accept", () => {
        passingTestCases.forEach(testCase => {
          const spec = testCase.only ? it.only : it;
          describe(JSON.stringify(schema.config, replacer), () => {
            describe(JSON.stringify(testCase.code), () => {
              spec(testCase.description || "no description", () => {
                const options = {
                  code: testCase.code,
                  config: stylelintConfig,
                  syntax: schema.syntax
                };
                return stylelint(options).then(output => {
                  expect(output.results[0].warnings).toEqual([]);
                  expect(output.results[0].parseErrors).toEqual([]);
                  if (!schema.fix) return;

                  // Check the fix
                  return stylelint(Object.assign({ fix: true }, options)).then(
                    output => {
                      const fixedCode = getOutputCss(output);
                      expect(fixedCode).toBe(testCase.code);
                    }
                  );
                });
              });
            });
          });
        });
      });
    }

    if (schema.reject && schema.reject.length) {
      describe("reject", () => {
        schema.reject.forEach(testCase => {
          const spec = testCase.only ? it.only : it;
          describe(JSON.stringify(schema.config, replacer), () => {
            describe(JSON.stringify(testCase.code), () => {
              spec(testCase.description || "no description", () => {
                const options = {
                  code: testCase.code,
                  config: stylelintConfig,
                  syntax: schema.syntax
                };
                return stylelint(options).then(output => {
                  const warning = output.results[0].warnings[0];

                  expect(output.results[0].parseErrors).toEqual([]);
                  expect(testCase).toHaveMessage();

                  if (testCase.message !== undefined) {
                    expect(_.get(warning, "text")).toBe(testCase.message);
                  }
                  if (testCase.line !== undefined) {
                    expect(_.get(warning, "line")).toBe(testCase.line);
                  }
                  if (testCase.column !== undefined) {
                    expect(_.get(warning, "column")).toBe(testCase.column);
                  }

                  if (!schema.fix) return;

                  if (!testCase.fixed) {
                    throw new Error(
                      "If using { fix: true } in test schema, all reject cases must have { fixed: .. }"
                    );
                  }

                  // Check the fix
                  return stylelint(Object.assign({ fix: true }, options)).then(
                    output => {
                      const fixedCode = getOutputCss(output);
                      expect(fixedCode).toBe(testCase.fixed);
                      expect(fixedCode).not.toBe(testCase.code);
                    }
                  );
                });
              });
            });
          });
        });
      });
    }
  });
};

function getOutputCss(output) {
  const result = output.results[0]._postcssResult;
  const css = result.root.toString(result.opts.syntax);
  if (result.opts.syntax === less) {
    // Less needs us to manually strip whitespace at the end of single-line comments ¯\_(ツ)_/¯
    return css.replace(/(\n?\s*\/\/.*?)[ \t]*(\r?\n)/g, "$1$2");
  }
  return css;
}

function replacer(key, value) {
  return value instanceof RegExp ? `[RegExp] ${value.toString()}` : value;
}
<|endoftext|>


<commit_before>/*TODO: get by date*/
var NOVA = function(){
/****************************************************/
/******************** Analysis **********************/
/****************************************************/
    var loadPDF = function(loc,scale) {
        var promise = new Promise(function(resolve,reject){
            if (typeof PDFJS === 'undefined') {
                reject(new Error('Built version of pdf.js is not found\nPlease run `node make generic`'));
            }
            PDFJS.getDocument(loc).then(function(pdf) {
                pdf.getPage(1).then(function(page) {
                    var viewport;
                    /*scale handeler*/
                    if(!scale || !isNaN(parseFloat(scale))){
                        viewport = page.getViewport(scale||1);
                    }else if(scale.width || scale.height){
                        viewport = page.getViewport(1);
                        if(scale.width && scale.height){
                            if(scale.renderMode=='cover'){
                                viewport = page.getViewport(Math.max((scale.width/viewport.width),(scale.height/viewport.height)));
                            }else{//contain is default, therefore anything but 'cover'
                                viewport = page.getViewport(Math.min((scale.width/viewport.width),(scale.height/viewport.height)));
                            }
                        }else if(scale.width){
                            viewport = page.getViewport(scale.width/viewport.width);
                        }else if(scale.height){
                            viewport = page.getViewport(scale.height/viewport.height);
                        }
                    }
                    page.getTextContent().then(function(textContent) {
                        resolve({page:page,viewport:viewport,textContent:textContent});
                    },function(err){reject(err)});
                },function(err){reject(err)});
            },function(err){reject(err)});
        });
        return promise
    };
    var loadNovaPDF = function(locObj,scale){
        if(locObj.schoolId && locObj.id && locObj.week)
            return loadPDF('php/phpProxy.php?id='+locObj.id+'&week='+locObj.week+'&school='+locObj.schoolId,scale);
    };
    var getNovaUrl = function(locObj){
        if(locObj.schoolId && locObj.id && locObj.week)
            return 'php/phpProxy.php?id='+locObj.id+'&week='+locObj.week+'&school='+locObj.schoolId;
    };

    var extractDays = function(textContent){
        textContent.items.sort(function(a,b){
            var ret = b.transform[5]-a.transform[5];
            if(ret==0)ret = a.transform[4]-b.transform[4];
            return ret
        });
        var days = [];
        for(var i=0;i<5;i++){
            days.push(textContent.items.splice(0,1)[0]);
        }
        return {textContent:textContent.items,days:days}
    };
    var sortDays = function(advTxtCont){
        var days = [];
        for(var i=0;i<advTxtCont.days.length;i++){
            advTxtCont.days[i].index=i;
            days.push({day:advTxtCont.days[i],children:[]});
        }
        for(var i=0;i<advTxtCont.textContent.length;i++){
            var text = advTxtCont.textContent[i];
            advTxtCont.days.sort(function(a,b){
                return Math.abs((a.transform[4]+a.width/2)-(text.transform[4]+text.width/2))-
                    Math.abs((b.transform[4]+b.width/2)-(text.transform[4]+text.width/2));
            });
            days[advTxtCont.days[0].index].children.push(text);
        }
        return days
    };
    var getSortedDays = function(textContent){
        return sortDays(extractDays(textContent));
    };

    var processDay = function(day,sorted){
        if(!(day.children && day.day) || Object.prototype.toString.call(day.children)!=='[object Array]')throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected [object Array]'});

        if(!sorted)day.children.sort(function(a,b){
            var ret = b.transform[5]-a.transform[5];
            if(ret==0)ret = a.transform[4]-b.transform[4];
            return ret
        });

        //Make sure only contains two time columns
        var timeCheck = [];

        var lesson /*= {start:'',stop:'',contains:[]}*/,
            lessons = new Day(sortDayData(day.day.str));
        for(var i=0;i<day.children.length;i++){
            var t = isTime(day.children[i].str);
            if(t){
                if(timeCheck.indexOf(day.children[i].transform[4])===-1)timeCheck.push(day.children[i].transform[4]);

                if(lesson){
                    var fill = sortLessonData({data:lesson.contains,start:lesson.start,stop:t});
                    var l = new Lesson(fill);
                    lessons.appendLesson(l);
                    lesson = null;
                }else{
                    lesson = {start:t/*,stop:null*/,contains:[]}
                }
            }else if(lesson){
                lesson.contains.push(day.children[i].str);
            }

        };
        //if not two time columns -> throw
        if(timeCheck.length!==2)throw new NovaError({errCode:NovaError.prototype.errCodes.UNEXPECTED_STRUCTURE,msg:'incorect amount of time-columns: '+timeCheck.length, data:'Incomplete Day'});
        return lessons
    };
    var sortLessonData = function(data){
        if(!data || !(data.data && data.start && data.stop))throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'either undefined or missing data, start, or stop'});
        var course,
            teacher,
            room;

        if(typeof data.data === 'string' || data.data.length == 1){
            course = data.data[0];
        }else if(data.data.length == 3){
            course = data.data[0];
            teacher = data.data[1];
            room = data.data[2];
        }else{
            throw new NovaError({errCode:NovaError.prototype.errCodes.UNEXPECTED_STRUCTURE,msg:'Lesson data not recognized',data:data.data});
        }

        return {startTime:data.start,stopTime:data.stop,course:course,teacher:teacher,room:room}
    };
    var sortDayData = function(data){
        if(typeof data !== 'string')throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected string'});

        var date = data.match(/\d{1,2}\/\d{1,2}/),
            str = data.replace(/(\s+|^)(\d{1,2}\/\d{1,2})(\s+|$)/,'');

        if(str===data)throw 'No change in data';
        return {date:date[0],name:str}
    };
    var isTime = function(data){
        if(typeof data !== 'string')throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected string'});

        var match = data.match(/\d\d:\d\d/g);
        var strict = data.match(/^\d\d:\d\d$/g);

        if(strict)return strict[0];
        if(match)throw ('Unrecognized time value' + data);
        return null
    };

    var processWeek = function(arr, nr){
        if(Object.prototype.toString.call(arr)!=='[object Array]' || arr.length!=5)throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected array'});

        var week = new Week();
        if(parseInt(nr)===nr)week.nr=nr;
        //if(nr) will allow week nr to be undefined
        else if(nr) throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected int'});

        for(var i=0;i<arr.length;i++){
            try {
                week.appendDay(processDay(arr[i]),i);
            }
            catch(err){
                if(err.errCode && err.errCode == NovaError.prototype.errCodes.UNEXPECTED_STRUCTURE && err.data == 'Incomplete Day')console.warn('No adv Day processing available. Skipping Day:'+i+' Week:'+nr);
                //either handle wrong day or pass down the error
                else throw err;
            }
        }
        return week
    };
/****************************************************/
/****************** Constructors ********************/
/****************************************************/

    var NovaError = function NovaError(obj) {
        if(typeof obj == 'string')
            this.message = obj;
        if(obj.errCode){
            this.message = this.errMessages[obj.errCode];
            this.errCode = obj.errCode;
        }
        if(obj.msg && typeof obj.msg == 'string')
            this.description = obj.msg;
        if(obj.data)this.data = obj.data;

        this.error = new Error(this.message+'; '+this.description);
    };
    NovaError.prototype.errCodes = {
        UNEXPECTED_ERROR: 1,
        MISSING_PARAMETER: 2,
        WRONG_TYPE: 3,
        UNEXPECTED_STRUCTURE: 4
    };
    NovaError.prototype.errMessages = {
        1: 'Unexpected error',
        2: 'Missing parameter',
        3: 'Wrong type',
        3: 'Unexpected structure'
    };
    NovaError.prototype.toString = function(){return '[object NovaError]'};

    var Schdule = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.schoolId = obj.schoolId || null,
            this.id = obj.id || null;

        if(obj.JSON)/*Convert JSON to new object*/;
    };
    Schdule.prototype.getWeeks = function(){/*Konstruera weekBasket och return*/};
    Schdule.prototype.loadWeeks = function(){/*Loop this.loadWeek()*/};
    Schdule.prototype.loadWeek = function(){/*Call hidden functions for analysis and appendWeek()*/};
    Schdule.prototype.appendWeek = function(){/*Add week to week array*/};

    var WeekBascet = function(obj){/*Construct array of selected weeks*/
        var type = Object.prototype.toString.call(obj);
        if(type=='[object Array]'){
        }else if(obj.start && obj.end){
        }
        //return new Array()//inherit array
    };
    WeekBascet.prototype = new Array();
    WeekBascet.prototype.toXML = function(){
        if(this.length == 0) {throw new NovaError({errCode: NovaError.errCodes.EXAMPLE_ERROR})}
        var xml = "";

        //init xml
        xml = xml + "<novaschedule>";

        //something

        //Stop
        xml = xml + "</novaschedule>";

        return xml;
    };
    WeekBascet.prototype.toICS = function(){};
    WeekBascet.prototype.toJSON = function(){};

    var Week = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.nr = obj.nr || null,
            this.days = [];
    };
    Week.prototype.appendDay = function(day, id){
        if(!day)throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'day is not defined'});
        //control Day constructor. Must be Day!
        day.parent = this;
        if(!day.weekDay){
            if(parseInt(id)==id)day.weekDay = id;
            else day.weekDay = this.days.length;
        }
        this.days.push(day);
    };
    Week.prototype.toXML = function(ignoreStart){};
    Week.prototype.toICS = function(ignoreStart){};
    Week.prototype.toJSON = function(){};
    Week.prototype.getDay = function(){};

    var Day = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.date = obj.date || null,
            this.name = obj.name || null,
            this.lessons = [];
    };
    Day.prototype.appendLesson = function(lesson){
        if(!lesson)throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'lesson is not defined'});
        //control Lesson constructor. Must be Lesson!
        lesson.parent = this;
        this.lessons.push(lesson);
    };
    Day.prototype.toXML = function(ignoreStart){};
    Day.prototype.toICS = function(ignoreStart){};
    Day.prototype.toJSON = function(){};
    Day.prototype.getLessonAtTime = function(){/*Low prority*/};

    var Lesson = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.startTime = obj.startTime || null,
            this.stopTime = obj.stopTime || null,
            this.course = obj.course || null,
            this.teacher = obj.teacher || null,
            this.room = obj.room || null,
            this.parent = obj.parent || null;
    };

    return {getSortedDays:getSortedDays, loadPDF:loadPDF, getNovaUrl:getNovaUrl, processWeek:processWeek}
}();

window.onload = function(){
    document.getElementById('NOVA-submit-btn').onclick = function(){
        //Disabled for development
        //var url = "php/phpProxy.php?id=" + id + "&week=" + week + "&school=" + schoolId;
        var url = NOVA.getNovaUrl({schoolId:52550,id:document.getElementById('NOVA-user-id').value,week:36});//"Schedule.pdf";

        NOVA.loadPDF(url,{width:window.innerWidth,height:500,renderMode:'contain'}).then(function(objs){
            var viewport = objs.viewport,
                page = objs.page,
                textContent = objs.textContent;

            var container = document.getElementById("pdfContainer");

            var canvas = document.createElement("canvas");
            var context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;

            container.appendChild(canvas);

            var renderContext = {
                canvasContext: context,
                viewport: viewport
            };

            page.render(renderContext);

            window.h = NOVA.getSortedDays(textContent);
            console.log(h);

        }).catch(function(err){console.log(err)});

        return false
    };
};<commit_msg>loadWeek and progressEvents<commit_after>/*TODO: get by date*/
var NOVA = function(){

    PROGRESS_STEPS = {getPdf:['Document Recived',
                              'Page Loaded',
                              'Done Loading'
                             ],
                      analyse:['Data Processed',
                               'Week created'
                              ]
                     };
/****************************************************/
/******************** Analysis **********************/
/****************************************************/
    var loadPDF = function(loc,scale,progressFn) {
        var promise = new Promise(function(resolve,reject){
            if (typeof PDFJS === 'undefined') {
                reject(new Error('Built version of pdf.js is not found\nPlease run `node make generic`'));
            }

            PDFJS.getDocument(loc).then(function(pdf) {
                progressFn({step:0,string:PROGRESS_STEPS.getPdf[0]});
                pdf.getPage(1).then(function(page) {
                    progressFn({step:1,string:PROGRESS_STEPS.getPdf[1]});
                    var viewport;
                    /*scale handeler*/
                    if(!scale || !isNaN(parseFloat(scale))){
                        viewport = page.getViewport(scale||1);
                    }else if(scale.width || scale.height){
                        viewport = page.getViewport(1);
                        if(scale.width && scale.height){
                            if(scale.renderMode=='cover'){
                                viewport = page.getViewport(Math.max((scale.width/viewport.width),(scale.height/viewport.height)));
                            }else{//contain is default, therefore anything but 'cover'
                                viewport = page.getViewport(Math.min((scale.width/viewport.width),(scale.height/viewport.height)));
                            }
                        }else if(scale.width){
                            viewport = page.getViewport(scale.width/viewport.width);
                        }else if(scale.height){
                            viewport = page.getViewport(scale.height/viewport.height);
                        }
                    }
                    page.getTextContent().then(function(textContent) {
                        progressFn({step:2,string:PROGRESS_STEPS.getPdf[2]});
                        resolve({page:page,viewport:viewport,textContent:textContent});
                    },function(err){reject(err)});
                },function(err){reject(err)});
            },function(err){reject(err)});
        });
        return promise
    };
    var loadNovaPDF = function(locObj,scale){
        if(locObj.schoolId && locObj.id && locObj.week)
            return loadPDF(getNovaUrl(locObj),scale);
    };
    var getNovaUrl = function(locObj){
        if(locObj.schoolId && locObj.id && locObj.week)
            return 'php/phpProxy.php?id='+locObj.id+'&week='+locObj.week+'&school='+locObj.schoolId;
    };

    var extractDays = function(textContent){
        textContent.items.sort(function(a,b){
            var ret = b.transform[5]-a.transform[5];
            if(ret==0)ret = a.transform[4]-b.transform[4];
            return ret
        });
        var days = [];
        for(var i=0;i<5;i++){
            days.push(textContent.items.splice(0,1)[0]);
        }
        return {textContent:textContent.items,days:days}
    };
    var sortDays = function(advTxtCont){
        var days = [];
        for(var i=0;i<advTxtCont.days.length;i++){
            advTxtCont.days[i].index=i;
            days.push({day:advTxtCont.days[i],children:[]});
        }
        for(var i=0;i<advTxtCont.textContent.length;i++){
            var text = advTxtCont.textContent[i];
            advTxtCont.days.sort(function(a,b){
                return Math.abs((a.transform[4]+a.width/2)-(text.transform[4]+text.width/2))-
                    Math.abs((b.transform[4]+b.width/2)-(text.transform[4]+text.width/2));
            });
            days[advTxtCont.days[0].index].children.push(text);
        }
        return days
    };
    var getSortedDays = function(textContent){
        return sortDays(extractDays(textContent));
    };

    var processDay = function(day,sorted){
        if(!(day.children && day.day) || Object.prototype.toString.call(day.children)!=='[object Array]')throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected [object Array]'});

        if(!sorted)day.children.sort(function(a,b){
            var ret = b.transform[5]-a.transform[5];
            if(ret==0)ret = a.transform[4]-b.transform[4];
            return ret
        });

        //Make sure only contains two time columns
        var timeCheck = [];

        var lesson /*= {start:'',stop:'',contains:[]}*/,
            lessons = new Day(sortDayData(day.day.str));
        for(var i=0;i<day.children.length;i++){
            var t = isTime(day.children[i].str);
            if(t){
                if(timeCheck.indexOf(day.children[i].transform[4])===-1)timeCheck.push(day.children[i].transform[4]);

                if(lesson){
                    var fill = sortLessonData({data:lesson.contains,start:lesson.start,stop:t});
                    var l = new Lesson(fill);
                    lessons.appendLesson(l);
                    lesson = null;
                }else{
                    lesson = {start:t/*,stop:null*/,contains:[]}
                }
            }else if(lesson){
                lesson.contains.push(day.children[i].str);
            }

        };
        //if not two time columns -> throw
        if(timeCheck.length!==2)throw new NovaError({errCode:NovaError.prototype.errCodes.UNEXPECTED_STRUCTURE,msg:'incorect amount of time-columns: '+timeCheck.length, data:'Incomplete Day'});
        return lessons
    };
    var sortLessonData = function(data){
        if(!data || !(data.data && data.start && data.stop))throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'either undefined or missing data, start, or stop'});
        var course,
            teacher,
            room;

        if(typeof data.data === 'string' || data.data.length == 1){
            course = data.data[0];
        }else if(data.data.length == 3){
            course = data.data[0];
            teacher = data.data[1];
            room = data.data[2];
        }else{
            throw new NovaError({errCode:NovaError.prototype.errCodes.UNEXPECTED_STRUCTURE,msg:'Lesson data not recognized',data:data.data});
        }

        return {startTime:data.start,stopTime:data.stop,course:course,teacher:teacher,room:room}
    };
    var sortDayData = function(data){
        if(typeof data !== 'string')throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected string'});

        var date = data.match(/\d{1,2}\/\d{1,2}/),
            str = data.replace(/(\s+|^)(\d{1,2}\/\d{1,2})(\s+|$)/,'');

        if(str===data)throw 'No change in data';
        return {date:date[0],name:str}
    };
    var isTime = function(data){
        if(typeof data !== 'string')throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected string'});

        var match = data.match(/\d\d:\d\d/g);
        var strict = data.match(/^\d\d:\d\d$/g);

        if(strict)return strict[0];
        if(match)throw ('Unrecognized time value' + data);
        return null
    };

    var processWeek = function(arr, nr){
        if(Object.prototype.toString.call(arr)!=='[object Array]' || arr.length!=5)throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected array'});

        var week = new Week();
        if(parseInt(nr)===nr)week.nr=nr;
        //if(nr) will allow week nr to be undefined
        else if(nr) throw new NovaError({errCode:NovaError.prototype.errCodes.WRONG_TYPE,msg:'expected int'});

        for(var i=0;i<arr.length;i++){
            try {
                week.appendDay(processDay(arr[i]),i);
            }
            catch(err){
                if(err.errCode && err.errCode == NovaError.prototype.errCodes.UNEXPECTED_STRUCTURE && err.data == 'Incomplete Day')console.warn('No adv Day processing available. Skipping Day:'+i+' Week:'+nr);
                //either handle wrong day or pass down the error
                else throw err;
            }
        }
        return week
    };
/****************************************************/
/****************** Constructors ********************/
/****************************************************/

    var NovaError = function NovaError(obj) {
        if(typeof obj == 'string')
            this.message = obj;
        if(obj.errCode){
            this.message = this.errMessages[obj.errCode];
            this.errCode = obj.errCode;
        }
        if(obj.msg && typeof obj.msg == 'string')
            this.description = obj.msg;
        if(obj.data)this.data = obj.data;

        this.error = new Error(this.message+'; '+this.description);
    };
    NovaError.prototype.errCodes = {
        UNEXPECTED_ERROR: 1,
        MISSING_PARAMETER: 2,
        WRONG_TYPE: 3,
        UNEXPECTED_STRUCTURE: 4
    };
    NovaError.prototype.errMessages = {
        1: 'Unexpected error',
        2: 'Missing parameter',
        3: 'Wrong type',
        3: 'Unexpected structure'
    };
    NovaError.prototype.toString = function(){return '[object NovaError]'};

    var Schdule = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.schoolId = obj.schoolId || null,
            this.id = obj.id || null
            this.weeks = [];

        if(obj.JSON)/*Convert JSON to new object*/;
    };
    Schdule.prototype.getWeeks = function(){/*Konstruera weekBasket och return*/};
    Schdule.prototype.loadWeeks = function(){/*Loop this.loadWeek()*/};
    Schdule.prototype.loadWeek = function(obj,progressFn){
        var nr = parseInt(obj),
            id = this.id,
            schoolId = this.schoolId,
            progress = progressFn || null,
            scale,
            url;

        if(isNaN(nr)){
            nr=obj.nr
            if(!nr)throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'Week nr not specified'});

            if(obj.schoolId)schoolId = obj.schoolId;
            if(obj.id)id = obj.id;
            if(!(schoolId && id))throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,
                                                      msg:'id and schoolId must be specified either in the Schedule object or  as a parameter'});

            scale = obj.scale || null;
            if(obj.progressFn)progressFn == obj.progressFn;
        }
        if(obj.pdf || obj.url)url = obj.pdf || obj.url;
        else url = getNovaUrl({schoolId:schoolId,id:id,week:nr});

        //to reach this in async functions
        var t = this;
        var promise = new Promise(function(resolve, reject){
            loadPDF(url,scale,function(e){if(progress)progress({weekNr:nr,stepType:'getPdf',step:e.step,string:e.string});}).then(function(objs){
                var week;
                try{
                    var sort = getSortedDays(objs.textContent);
                    if(progress)progress({weekNr:nr,stepType:'analyse',step:0,string:PROGRESS_STEPS.analyse[0]});
                    week = processWeek(sort);
                    week.nr = nr;
                    if(progress)progress({weekNr:nr,stepType:'analyse',step:1,string:PROGRESS_STEPS.analyse[1]});
                    t.appendWeek(week);
                    resolve({weekNr:nr,week:week,viewport:objs.viewport,page:objs.page,textContent:objs.textContent})
                }catch(err){
                    /*Analyzing error and resolve it here*/
                    reject(err)
                }
            },function(err){reject(err)});
        });
        return promise
    };
    Schdule.prototype.appendWeek = function(week){
        if(!week)throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'week is not defined'});
        //control Week constructor. Must be Week!
        week.parent = this;
        this.weeks.push(week);
    };

    var WeekBascet = function(obj){/*Construct array of selected weeks*/
        var type = Object.prototype.toString.call(obj);
        if(type=='[object Array]'){
        }else if(obj.start && obj.end){
        }
        //return new Array()//inherit array
    };
    WeekBascet.prototype = new Array();
    WeekBascet.prototype.toXML = function(){
        if(this.length == 0) {throw new NovaError({errCode: NovaError.errCodes.EXAMPLE_ERROR})}
        var xml = "";

        //init xml
        xml = xml + "<novaschedule>";

        //something

        //Stop
        xml = xml + "</novaschedule>";

        return xml;
    };
    WeekBascet.prototype.toICS = function(){};
    WeekBascet.prototype.toJSON = function(){};

    var Week = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.nr = obj.nr || null,
            this.parent = obj.parent || null,
            this.days = [];
    };
    Week.prototype.appendDay = function(day, id){
        if(!day)throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'day is not defined'});
        //control Day constructor. Must be Day!
        day.parent = this;
        if(!day.weekDay){
            if(parseInt(id)==id)day.weekDay = id;
            else day.weekDay = this.days.length;
        }
        this.days.push(day);
    };
    Week.prototype.toXML = function(ignoreStart){};
    Week.prototype.toICS = function(ignoreStart){};
    Week.prototype.toJSON = function(){};
    Week.prototype.getDay = function(){};

    var Day = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.date = obj.date || null,
            this.name = obj.name || null,
            this.lessons = [];
    };
    Day.prototype.appendLesson = function(lesson){
        if(!lesson)throw new NovaError({errCode:NovaError.prototype.errCodes.MISSING_PARAMETER,msg:'lesson is not defined'});
        //control Lesson constructor. Must be Lesson!
        lesson.parent = this;
        this.lessons.push(lesson);
    };
    Day.prototype.toXML = function(ignoreStart){};
    Day.prototype.toICS = function(ignoreStart){};
    Day.prototype.toJSON = function(){};
    Day.prototype.getLessonAtTime = function(){/*Low prority*/};

    var Lesson = function(obj){
        if(!obj)obj = {};//prevent errors at undefined obj
        this.startTime = obj.startTime || null,
            this.stopTime = obj.stopTime || null,
            this.course = obj.course || null,
            this.teacher = obj.teacher || null,
            this.room = obj.room || null,
            this.parent = obj.parent || null;
    };

    return {getSortedDays:getSortedDays, loadPDF:loadPDF, getNovaUrl:getNovaUrl, Schdule:Schdule}
}();

window.onload = function(){
    document.getElementById('NOVA-submit-btn').onclick = function(){
        //Disabled for development
        //var url = "php/phpProxy.php?id=" + id + "&week=" + week + "&school=" + schoolId;
        var url = NOVA.getNovaUrl({schoolId:52550,id:document.getElementById('NOVA-user-id').value,week:36});//"Schedule.pdf";

        NOVA.loadPDF(url,{width:window.innerWidth,height:500,renderMode:'contain'}).then(function(objs){
            var viewport = objs.viewport,
                page = objs.page,
                textContent = objs.textContent;

            var container = document.getElementById("pdfContainer");

            var canvas = document.createElement("canvas");
            var context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;

            container.appendChild(canvas);

            var renderContext = {
                canvasContext: context,
                viewport: viewport
            };

            page.render(renderContext);

            window.h = NOVA.getSortedDays(textContent);
            console.log(h);

        }).catch(function(err){console.log(err)});

        return false
    };
};<|endoftext|>


<commit_before>$(function() {
  var canvas = document.getElementById('bukvonesis');
  paper.setup(canvas);

  var offset = 0;

  $.each(devonshire, function(letter, generations) {
    var letterPath = makePath(generations[0], offset);
    animate(letterPath, generations.slice(1));
    offset += 300;
  });

  paper.view.draw();
});

function makePath(generation, offset) {
  var letterPath = new paper.CompoundPath();

  $.each(generation, function(index, coords) {
    var path = new paper.Path();

    if (coords.length == 6) {
      path.add(new paper.Point(coords[0], coords[1]));
      path.quadraticCurveTo(new paper.Point(coords[2], coords[3]),
      new paper.Point(coords[4], coords[5]));
    } else {
      path.add(new paper.Point(coords[0], coords[1]),
      new paper.Point(coords[2], coords[3]));
    }
    path.position.x += offset;
    letterPath.addChild(path);
  });

  letterPath.strokeColor = 'black';
  return letterPath;
}

function animate(letterPath, generations) {
   $.each(letterPath.children, function(index, child) {
     createjs.Tween.get(child, {loop:true})
	 .to({position:{x:0}});
   });
}
<commit_msg>Fix letter animation.<commit_after>$(function() {
  var canvas = document.getElementById('bukvonesis');
  paper.setup(canvas);

  //animateSingleLetter('n');
  animateAllLetters();
  var update = function() {
    paper.view.draw();
  };

  createjs.Ticker.setFPS(10);
  createjs.Ticker.addEventListener('tick', update);
});

function makePath(generation, offset) {
  var letterPath = new paper.CompoundPath();

  $.each(generation, function(index, coords) {
    var path = new paper.Path();

    if (coords.length == 6) {
      path.add(new paper.Point(coords[0], coords[1]));
      path.quadraticCurveTo(new paper.Point(coords[2], coords[3]),
			    new paper.Point(coords[4], coords[5]));
    } else {
      path.add(new paper.Point(coords[0], coords[1]),
	       new paper.Point(coords[2], coords[3]));
    }
    path.position.x += offset;
    letterPath.addChild(path);
  });

  letterPath.strokeColor = 'black';
  return letterPath;
}

function animate(letterPath, generations, offset) {
   $.each(letterPath.children, function(child_index, child) {
     $.each(child.segments, function(segment_index, segment) {
       var pathTween = createjs.Tween.get(segment.point, {loop:true});
       $.each(generations, function(generation_index, generation) {
	 $.each(generation, function(coords_index, coords) {
	   if (child_index == coords_index) {
	       if (coords.length == 6) {
		 if (segment_index == 0) {
		   pathTween.to({x: coords[0] + offset, y: coords[1]},
				1000, createjs.Ease.quadOut);
		   } else {
		   pathTween.to({x: coords[4] + offset, y: coords[5]},
				1000, createjs.Ease.quadOut);
		   }
	       } else {
		 pathTween.to({x: coords[segment_index + 0] + offset, y: coords[segment_index + 1]},
			      1000, createjs.Ease.quadOut);
	       }
	     }
	 });
       });
       pathTween.wait(1500);
     });
   });
}

function animateSingleLetter(letter) {
  var generations = devonshire[letter];
  var letterPath = makePath(generations[0], 0);
  animate(letterPath, generations.slice(1));
}

function animateAllLetters() {
  var offset = 0;

  $.each(devonshire, function(letter, generations) {
     var letterPath = makePath(generations[0], offset);
     animate(letterPath, generations.slice(1), offset);
     offset += 300;
   });
}
<|endoftext|>


<commit_before>define(function () {
	function getFromInfix(infixString) {
		return '';
	}

	function solve(rpnString) {
		return 0;
	}

	return {
		getFromInfix: getFromInfix,
		solve: solve
	};
});<commit_msg>Implement RPN solve()<commit_after>define(function () {
	'use strict';

	var operatorsConfig = {
		'+': {
			precedence: 2,
			assoc: 'left',
			argsCount: 2,
			execFunc: function (a, b) {
				return a + b;
			}
		},
		'-': {
			precedence: 2,
			assoc: 'left',
			argsCount: 2,
			execFunc: function (a, b) {
				return a - b;
			}
		},
		'*': {
			precedence: 3,
			assoc: 'left',
			argsCount: 2,
			execFunc: function (a, b) {
				return a * b;
			}
		},
		'x': {
			precedence: 3,
			assoc: 'left',
			argsCount: 2,
			execFunc: function (a, b) {
				return a * b;
			}
		},
		'/': {
			precedence: 3,
			assoc: 'left',
			argsCount: 2,
			execFunc: function (a, b) {
				return a / b;
			}
		},
		'^': {
			precedence: 4,
			assoc: 'right',
			argsCount: 2,
			execFunc: function (a, b) {
				return Math.pow(a, b);
			}
		}
	};

	function tokenize(string) {
		return string.replace(/ +/g, ' ').trim().split(' ');
	}

	function getFromInfix(infixString) {
		return '';
	}

	function solve(rpnString) {
		var stack = [];
		tokenize(rpnString).forEach(function (token) {
			if (!isNaN(token)) {
				stack.push(parseFloat(token));
			} else if (operatorsConfig.hasOwnProperty(token)) {
				var operator = operatorsConfig[token];

				if (operator.argsCount > stack.length) {
					throw 'Not enough operands in stack for: ' + token;
				}

				var operands = stack.splice(-1 * operator.argsCount, operator.argsCount);
				var result = operator.execFunc.apply(null, operands);

				stack.push(result);
			} else {
				throw 'Invalid token: ' + token;
			}
		});

		if (stack.length !== 1) {
			throw 'Invalid expression';
		}

		return stack.pop();
	}

	return {
		getFromInfix: getFromInfix,
		solve: solve
	};
});<|endoftext|>


<commit_before>/*
Credits: this script is shamelessly borrowed from
https://github.com/kitian616/jekyll-TeXt-theme
*/
(function() {
  function queryString() {
    // This function is anonymous, is executed immediately and
    // the return value is assigned to QueryString!
    var i = 0, queryObj = {}, pair;
    var queryStr = window.location.search.substring(1);
    var queryArr = queryStr.split('&');
    for (i = 0; i < queryArr.length; i++) {
      pair = queryArr[i].split('=');
      // If first entry with this name
      if (typeof queryObj[pair[0]] === 'undefined') {
        queryObj[pair[0]] = pair[1];
        // If second entry with this name
      } else if (typeof queryObj[pair[0]] === 'string') {
        queryObj[pair[0]] = [queryObj[pair[0]], pair[1]];
        // If third or later entry with this name
      } else {
        queryObj[pair[0]].push(pair[1]);
      }
    }
    return queryObj;
  }

  var setUrlQuery = (function() {
    var baseUrl =  window.location.href.split('?')[0];
    return function(query) {
      if (typeof query === 'string') {
        window.history.replaceState(null, '', baseUrl + query);
      } else {
        window.history.replaceState(null, '', baseUrl);
      }
    };
  })();

  $(document).ready(function() {
    var $tags = $('.js-tags');
    var $articleTags = $tags.find('.tag-button');
    var $tagShowAll = $tags.find('.tag-button--all');
    var $result = $('.js-result');
    var $sections = $result.find('section');
    var sectionArticles = []
    var $lastFocusButton = null;
    var sectionTopArticleIndex = [];
    var hasInit = false;

    $sections.each(function() {
      sectionArticles.push($(this).find('.item'));
    });

    function init() {
      var i, index = 0;
      for (i = 0; i < $sections.length; i++) {
        sectionTopArticleIndex.push(index);
        index += $sections.eq(i).find('.item').length;
      }
      sectionTopArticleIndex.push(index);
    }

    function searchButtonsByTag(_tag/*raw tag*/) {
      if (!_tag) {
        return $tagShowAll;
      }

      _tag = _tag.toString();

      var _buttons = $articleTags.filter('[data-encode="' + _tag + '"]');
      if (_buttons.length === 0) {
        return $tagShowAll;
      }
      return _buttons;
    }

    function buttonFocus(target) {
      if (target) {
        target.addClass('focus');
        $lastFocusButton && !$lastFocusButton.is(target) && $lastFocusButton.removeClass('focus');
        $lastFocusButton = target;
      }
    }

    function tagSelect (tag/*raw tag*/, target) {

      var result = {}, $articles;
      var i, j, k, _tag;

      for (i = 0; i < sectionArticles.length; i++) {
        $articles = sectionArticles[i];
        for (j = 0; j < $articles.length; j++) {
          if (tag === '' || tag === undefined) {
            result[i] || (result[i] = {});
            result[i][j] = true;
          } else {
            var tags = $articles.eq(j).data('tags').toString().split(',');
            for (k = 0; k < tags.length; k++) {
              if (tags[k] === tag) {
                result[i] || (result[i] = {});
                result[i][j] = true; break;
              }
            }
          }
        }
      }

      for (i = 0; i < sectionArticles.length; i++) {
        result[i] && $sections.eq(i).removeClass('d-none');
        result[i] || $sections.eq(i).addClass('d-none');
        for (j = 0; j < sectionArticles[i].length; j++) {
          if (result[i] && result[i][j]) {
            sectionArticles[i].eq(j).removeClass('d-none');
          } else {
            sectionArticles[i].eq(j).addClass('d-none');
          }
        }
      }

      hasInit || ($result.removeClass('d-none'), hasInit = true);

      if (target) {
        buttonFocus(target);
        _tag = target.attr('data-encode');
        if (_tag === '' || typeof _tag !== 'string') {
          setUrlQuery();
        } else {
          setUrlQuery('?tag=' + _tag);
        }
      } else {
        buttonFocus(searchButtonsByTag(tag));
      }
    }

    var query = queryString(),
        _tag = query.tag;

    init();
    tagSelect(_tag);

    $tags.on('click', 'a', function() {   /* only change */
      tagSelect($(this).data('encode'), $(this));
    });

  });
})();
<commit_msg>tagSelect에서 문자열 아닐 때 예외처리<commit_after>/*
Credits: this script is shamelessly borrowed from
https://github.com/kitian616/jekyll-TeXt-theme
*/
(function() {
  function queryString() {
    // This function is anonymous, is executed immediately and
    // the return value is assigned to QueryString!
    var i = 0, queryObj = {}, pair;
    var queryStr = window.location.search.substring(1);
    var queryArr = queryStr.split('&');
    for (i = 0; i < queryArr.length; i++) {
      pair = queryArr[i].split('=');
      // If first entry with this name
      if (typeof queryObj[pair[0]] === 'undefined') {
        queryObj[pair[0]] = pair[1];
        // If second entry with this name
      } else if (typeof queryObj[pair[0]] === 'string') {
        queryObj[pair[0]] = [queryObj[pair[0]], pair[1]];
        // If third or later entry with this name
      } else {
        queryObj[pair[0]].push(pair[1]);
      }
    }
    return queryObj;
  }

  var setUrlQuery = (function() {
    var baseUrl =  window.location.href.split('?')[0];
    return function(query) {
      if (typeof query === 'string') {
        window.history.replaceState(null, '', baseUrl + query);
      } else {
        window.history.replaceState(null, '', baseUrl);
      }
    };
  })();

  $(document).ready(function() {
    var $tags = $('.js-tags');
    var $articleTags = $tags.find('.tag-button');
    var $tagShowAll = $tags.find('.tag-button--all');
    var $result = $('.js-result');
    var $sections = $result.find('section');
    var sectionArticles = []
    var $lastFocusButton = null;
    var sectionTopArticleIndex = [];
    var hasInit = false;

    $sections.each(function() {
      sectionArticles.push($(this).find('.item'));
    });

    function init() {
      var i, index = 0;
      for (i = 0; i < $sections.length; i++) {
        sectionTopArticleIndex.push(index);
        index += $sections.eq(i).find('.item').length;
      }
      sectionTopArticleIndex.push(index);
    }

    function searchButtonsByTag(_tag/*raw tag*/) {
      if (!_tag) {
        return $tagShowAll;
      }

      var _buttons = $articleTags.filter('[data-encode="' + _tag + '"]');
      if (_buttons.length === 0) {
        return $tagShowAll;
      }
      return _buttons;
    }

    function buttonFocus(target) {
      if (target) {
        target.addClass('focus');
        $lastFocusButton && !$lastFocusButton.is(target) && $lastFocusButton.removeClass('focus');
        $lastFocusButton = target;
      }
    }

    function tagSelect (tag/*raw tag*/, target) {

      var result = {}, $articles;
      var i, j, k, _tag;

      for (i = 0; i < sectionArticles.length; i++) {
        $articles = sectionArticles[i];
        for (j = 0; j < $articles.length; j++) {
          if (tag === '' || tag === undefined) {
            result[i] || (result[i] = {});
            result[i][j] = true;
          } else {
            var tags = $articles.eq(j).data('tags');
            if( typeof tags !== 'string') {
              console.log("tags " + tags + " typeof " + typeof tags);
              continue;
            }

            var tags = tags.split(',');
            for (k = 0; k < tags.length; k++) {
              if (tags[k] === tag) {
                result[i] || (result[i] = {});
                result[i][j] = true; break;
              }
            }
          }
        }
      }

      for (i = 0; i < sectionArticles.length; i++) {
        result[i] && $sections.eq(i).removeClass('d-none');
        result[i] || $sections.eq(i).addClass('d-none');
        for (j = 0; j < sectionArticles[i].length; j++) {
          if (result[i] && result[i][j]) {
            sectionArticles[i].eq(j).removeClass('d-none');
          } else {
            sectionArticles[i].eq(j).addClass('d-none');
          }
        }
      }

      hasInit || ($result.removeClass('d-none'), hasInit = true);

      if (target) {
        buttonFocus(target);
        _tag = target.attr('data-encode');
        if (_tag === '' || typeof _tag !== 'string') {
          setUrlQuery();
        } else {
          setUrlQuery('?tag=' + _tag);
        }
      } else {
        buttonFocus(searchButtonsByTag(tag));
      }
    }

    var query = queryString(),
        _tag = query.tag;

    init();
    tagSelect(_tag);

    $tags.on('click', 'a', function() {   /* only change */
      tagSelect($(this).data('encode'), $(this));
    });

  });
})();
<|endoftext|>


<commit_before>if (typeof Object.create != 'function') {
  Object.create = function(o) {
    var F = function () {};
    F.prototype = o;
    return new F();
  };
}

var Commit = function (hash, lane, line, description, type) {
  var result = {
    hash: hash,
    type: type || 'c',
    lane: lane,
    line: line,
    description: description,
  };
  return result;
}

// -------------------------------------------------------------------

var GitGrid = function () {
  var result = {
    commits: {},
    connections: [],
    branches: [],

    drawOn: function(canvas_id) {
      this.canvas_id = canvas_id;
      this.canvas = document.getElementById(canvas_id);
      this.context = this.canvas.getContext("2d");
      this.lane_width = 40;
    },

    layout: function (lanes) {
      this.lanes = lanes;
    },

    scale: function (n) {
      return n * this.lane_width;
    },

    x: function (lane) {
      return lane * this.lane_width + this.lane_width / 2.0;
    },

    y: function (line) {
      return line * this.lane_width + this.lane_width / 2.0;
    },

    renderCommit: function(commit) {
      var x = this.x(commit.lane);
      var y = this.y(commit.line);
      this.context.beginPath();
      this.context.arc(x, y, this.scale(0.2), Math.PI*2, false);
      this.context.closePath();
      this.context.strokeStyle = "#000";
      this.context.lineWidth = 3;
      this.context.stroke();
      if (commit.type == 'c') {
        this.context.fillStyle = "#888";
      } else {
        this.context.fillStyle = "#00f";
      }
      this.context.fill();

      this.context.fillStyle = "#000";
      this.context.font = 'normal 12px sans-serif';
      this.context.textBaseline = 'middle';
      this.context.fillText(commit.hash + " -- " + commit.description, this.x(this.lanes), y);

      this.context.beginPath();
      this.context.moveTo(x + this.scale(0.4), y);
      this.context.lineTo(this.x(this.lanes) - this.scale(0.2), y);
      this.context.lineWidth = 1;
      this.context.strokeStyle = "#ccc";
      this.context.stroke();
    },

    renderConnection: function(commit1, commit2) {
      console.log(commit1);
      console.log("*** Drawing connection from " + commit1.description + " to " + commit2.description);
      var x1 = this.x(commit1.lane);
      var y1 = this.y(commit1.line);
      var x2 = this.x(commit2.lane);
      var y2 = this.y(commit2.line);

      this.context.beginPath();
      this.context.moveTo(x1, y1);
      if (commit1.lane === commit2.lane) {
        this.context.strokeStyle = "#000";
        this.context.lineTo(x2, y2);
      } else {
        this.context.strokeStyle = "#00f";
        var w = Math.abs(commit1.lane - commit2.lane);
        var mx = (x1 + x2) / 2.0;
        var my = (y1 + y2) / 2.0 - this.scale(0.5);
        this.context.quadraticCurveTo(mx, my, x2, y2);
      }
      this.context.lineWidth = 3;
      this.context.stroke();
    },

    render: function() {
      this.renderConnections();
      this.renderCommits();
    },

    renderConnections: function() {
      console.log("connections=" + this.connections);
      for (var i in this.connections) {
        var pair = this.connections[i];
        var c1 = pair[0];
        var c2 = pair[1];
        console.log("pair=" + pair);
        console.log("c1=" + c1);
        this.renderConnection(this.commits[c1], this.commits[c2]);
      }
    },

    renderCommits: function() {
      for (var i in this.commits) {
        var commit= this.commits[i];
        console.log("Drawing commit " + commit.description);
        this.renderCommit(commit);
      }
    },

    renderBranches: function() {
      for (var i=0; i < this.branches.length; i++) {
      }
    },

    addCommit: function(commit) {
      console.log("Adding commit '" + commit.hash + "' (" + commit.description + ")");
      this.commits[commit.hash] = commit;
      console.log(this.commits);
    },

    connect: function(commit1, commit2) {
      this.connections.push([commit1, commit2]);
    },

    addBranch: function() {
    },

  }
  return result;
}

// -------------------------------------------------------------------
function drawGrid() {
  var gg = new GitGrid();
  gg.drawOn("canvas");
  gg.layout(6);

  gg.addBranch(0, 0, "Prod");
  gg.addCommit(new Commit('a1', 0, 0, 'Initial commit (Jim Weirich)'));
  gg.addCommit(new Commit('b1', 1, 1, 'New Feature Branch (Jim Weirich)'));
  gg.addCommit(new Commit('c1', 2, 2, 'another feature branch (Jim Weirich)'));
  gg.addCommit(new Commit('c2', 2, 3, 'another feature branch (Jim Weirich)'));
  gg.addCommit(new Commit('x' , 5, 4, 'huh'));
  gg.addCommit(new Commit('b2', 1, 5, 'Converted GitGrid to a class like object (Jim Weirich)'));
  gg.addCommit(new Commit('a2', 0, 6, 'Merge to production (Jim Weirich)', 'm'));

  gg.connect('a1', 'b1');
  gg.connect('a1', 'c1');
  gg.connect('b1', 'b2');
  gg.connect('c1', 'c2');
  gg.connect('c2', 'a2');
  gg.connect('a1', 'x');

  gg.render();
}
// -------------------------------------------------------------------

function draw_b() {
  var b_canvas = document.getElementById("canvas");
  var b_context = b_canvas.getContext("2d");
  b_context.fillRect(50, 25, 150, 50);
}

function draw_outline() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  context.beginPath();
  context.moveTo(0.5,0.5);
  context.lineTo(0.5, canvas.height-0.5);
  context.lineTo(canvas.width-0.5, canvas.height-0.5);
  context.lineTo(canvas.width-0.5, 0.5);
  context.lineTo(0.5, 0.5);
  context.strokeStyle = "#000";
  context.stroke();
}

function draw_circle() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  context.beginPath();
  context.arc(50,50, 25, Math.PI*2, false);
  context.closePath();
  context.strokeStyle = "#ff0f80";
  context.lineWidth = 10;
  context.stroke();
  context.fillStyle = "#888";
  context.fill();
}

function draw_curve() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  context.beginPath();
  context.moveTo(50, 50);
  context.quadraticCurveTo(10, 200, 200, 200);
  context.strokeStyle = "#00ff00";
  context.lineWidth = 10;
  context.stroke();
}

function GitGraph() {
  {

  }
}
<commit_msg>Simplified public interface, Commit is now just used internally.<commit_after>if (typeof Object.create != 'function') {
  Object.create = function(o) {
    var F = function () {};
    F.prototype = o;
    return new F();
  };
}

var Commit = function (hash, lane, line, description, type) {
  var result = {
    hash: hash,
    type: type || 'c',
    lane: lane,
    line: line,
    description: description,
  };
  return result;
}

// -------------------------------------------------------------------

var GitGrid = function () {
  var result = {
    line: 0,
    commits: {},
    connections: [],
    branches: [],

    drawOn: function(canvas_id) {
      this.canvas_id = canvas_id;
      this.canvas = document.getElementById(canvas_id);
      this.context = this.canvas.getContext("2d");
      this.lane_width = 40;
    },

    layout: function (lanes) {
      this.lanes = lanes;
    },

    scale: function (n) {
      return n * this.lane_width;
    },

    x: function (lane) {
      return lane * this.lane_width + this.lane_width / 2.0;
    },

    y: function (line) {
      return line * this.lane_width + this.lane_width / 2.0;
    },

    renderCommit: function(commit) {
      var x = this.x(commit.lane);
      var y = this.y(commit.line);
      this.context.beginPath();
      this.context.arc(x, y, this.scale(0.2), Math.PI*2, false);
      this.context.closePath();
      this.context.strokeStyle = "#000";
      this.context.lineWidth = 3;
      this.context.stroke();
      if (commit.type == 'c') {
        this.context.fillStyle = "#888";
      } else {
        this.context.fillStyle = "#00f";
      }
      this.context.fill();

      this.context.fillStyle = "#000";
      this.context.font = 'normal 12px sans-serif';
      this.context.textBaseline = 'middle';
      this.context.fillText(commit.hash + " -- " + commit.description, this.x(this.lanes), y);

      this.context.beginPath();
      this.context.moveTo(x + this.scale(0.4), y);
      this.context.lineTo(this.x(this.lanes) - this.scale(0.2), y);
      this.context.lineWidth = 1;
      this.context.strokeStyle = "#ccc";
      this.context.stroke();
    },

    renderConnection: function(commit1, commit2) {
      if (! commit1 || ! commit2) {
        return;
      }
      console.log(commit1);
      console.log("*** Drawing connection from " + commit1.description + " to " + commit2.description);
      var x1 = this.x(commit1.lane);
      var y1 = this.y(commit1.line);
      var x2 = this.x(commit2.lane);
      var y2 = this.y(commit2.line);

      this.context.beginPath();
      this.context.moveTo(x1, y1);
      if (commit1.lane === commit2.lane) {
        this.context.strokeStyle = "#000";
        this.context.lineTo(x2, y2);
      } else {
        this.context.strokeStyle = "#00f";
        var w = Math.abs(commit1.lane - commit2.lane);
        var mx = (x1 + x2) / 2.0;
        var my = (y1 + y2) / 2.0 - this.scale(0.5);
        this.context.quadraticCurveTo(mx, my, x2, y2);
      }
      this.context.lineWidth = 3;
      this.context.stroke();
    },

    render: function() {
      this.renderConnections();
      this.renderCommits();
    },

    renderConnections: function() {
      console.log("connections=" + this.connections);
      for (var i in this.connections) {
        var pair = this.connections[i];
        var c1 = pair[0];
        var c2 = pair[1];
        console.log("pair=" + pair);
        console.log("c1=" + c1);
        this.renderConnection(this.commits[c1], this.commits[c2]);
      }
    },

    renderCommits: function() {
      for (var i in this.commits) {
        var commit = this.commits[i];
        console.log("Drawing commit " + commit.description);
        this.renderCommit(commit);
      }
    },

    renderBranches: function() {
      for (var i=0; i < this.branches.length; i++) {
      }
    },

    addCommit: function(hash, lane, description, type) {
      var c = new Commit(hash, lane, this.line, description, type);
      console.log("Adding commt '" + c.hash + "' (" + c.description + ")");
      this.line += 1;
      this.commits[hash] = c;
    },

    connect: function(commit1, commit2) {
      this.connections.push([commit1, commit2]);
    },

    addBranch: function(branchName) {
      this.branches.push(new Branch(branchName, this.line));
      this.line += 1;
    },

  }
  return result;
}

// -------------------------------------------------------------------
function drawGrid() {
  var gg = new GitGrid();
  gg.drawOn("canvas");
  gg.layout(6);

  gg.addBranch("Prod");
  gg.addCommit('a127846d', 0, 'Initial commit (Jim Weirich)');
  gg.addCommit('b17c3898', 1, 'New Feature Branch (Jim Weirich)');
  gg.addCommit('c1f8c863', 2, 'another feature branch (Jim Weirich)');
  gg.addCommit('c2641c99', 2, 'another feature branch (Jim Weirich)');
  gg.addCommit('a27bf806', 0, 'Merge to production (Jim Weirich)', 'm');
  gg.addCommit('f12f1158', 5, 'huh');
  gg.addCommit('f2e605dd', 5, 'huh');
  gg.addCommit('f346ab65', 5, 'huh');
  gg.addCommit('f497f0a5', 5, 'huh');
  gg.addCommit('b2f0bb37', 1, 'Converted GitGrid to a class like object (Jim Weirich)');
  gg.addCommit('a3c2b1b7', 0, 'Merge to production (Jim Weirich)', 'm');
  gg.addCommit('a444807b', 0, 'Merge to production (Jim Weirich)', 'm');

  gg.connect('a127846d', 'a27bf806');
  gg.connect('a27bf806', 'a3c2b1b7');
  gg.connect('a3c2b1b7', 'a444807b');

  gg.connect('b17c3898', 'b2f0bb37');

  gg.connect('c1f8c863', 'c2641c99');

  gg.connect('f12f1158', 'f2e605dd');
  gg.connect('f2e605dd', 'f346ab65');
  gg.connect('f346ab65', 'f497f0a5');

  gg.connect('a127846d', 'b17c3898');
  gg.connect('a127846d', 'c1f8c863');
  gg.connect('a127846d', 'f12f1158');
  gg.connect('c2641c99', 'a27bf806');
  gg.connect('b2f0bb37', 'a3c2b1b7');
  gg.connect('f497f0a5', 'a444807b');

  gg.render();

  // d0a2ed99548234f51126a77d5b16fc3789
}
// -------------------------------------------------------------------

function draw_b() {
  var b_canvas = document.getElementById("canvas");
  var b_context = b_canvas.getContext("2d");
  b_context.fillRect(50, 25, 150, 50);
}

function draw_outline() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  context.beginPath();
  context.moveTo(0.5,0.5);
  context.lineTo(0.5, canvas.height-0.5);
  context.lineTo(canvas.width-0.5, canvas.height-0.5);
  context.lineTo(canvas.width-0.5, 0.5);
  context.lineTo(0.5, 0.5);
  context.strokeStyle = "#000";
  context.stroke();
}

function draw_circle() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  context.beginPath();
  context.arc(50,50, 25, Math.PI*2, false);
  context.closePath();
  context.strokeStyle = "#ff0f80";
  context.lineWidth = 10;
  context.stroke();
  context.fillStyle = "#888";
  context.fill();
}

function draw_curve() {
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");
  context.beginPath();
  context.moveTo(50, 50);
  context.quadraticCurveTo(10, 200, 200, 200);
  context.strokeStyle = "#00ff00";
  context.lineWidth = 10;
  context.stroke();
}

function GitGraph() {
  {

  }
}
<|endoftext|>