<commit_before>//
// Example of how to override default behaviour
//
//leafletClusterMap.prototype.getBoundsSettings = function() {
//    return {
//        maxZoom: 13
//    };
//};

// Extend the Default marker class
var clubIcon2 = L.Icon.Default.extend({
    options: {
        //iconUrl: CLUBS.basePath + '/assets/css/images/marker-icon.png'
    }
});

var clubLayerMap = leafletClusterMap.extend({
    init: function(args) {
        this._super(args);
        that = this;
        loaded = false;

        jQuery.ajax({
            url: CLUBS.basePath + '/clubs.json',
            async: false,
            dataType: 'json',
            success: function(json) {
                that.geoJson = L.geoJson(json, {
                    pointToLayer: function (feature, latlng) {
                        return that.defineMarker(feature, latlng);
                    },
                    onEachFeature: function (feature, layer) {
                        that.definePopup(feature, layer);
                    }
                });

                that.resetCluster();
            }
        });

        that.tiles.on('load', function() {
            if (loaded === false) {
                that.fitBounds();
                loaded = true;
            }
        });

        _toggleCat = function(catname, action) {
            that.geoJson.eachLayer(function (layer) {
                hasCat = false;

                a = layer.feature.properties.tags;
                for (var i = 0; i < a.length; i++) {
                    if (catname === a[i].name) {
                        hasCat = true;
                    }
                }

                if (hasCat === true) {
                    if (action === 'add') {
                        that.markerClusters.addLayer(layer);
                    } else if (action === 'remove') {
                        that.markerClusters.removeLayer(layer);
                    }
                }
            });
        };

        // Call function which can be prototyped
        that.hook_init();
    },

    hook_init: function() {},

    removeCat: function(catname) {
        this.fireEvent('clubmap_removeCat_before');
        this.toggleCat(catname, 'remove');
        this.fireEvent('clubmap_removeCat_after');
    },

    addCat: function(catname) {
        this.fireEvent('clubmap_addCat_before');
        this.toggleCat(catname, 'add');
        this.fireEvent('clubmap_addCat_after');
    },

    toggleCat: function(catname, action) {
        this.fireEvent('clubmap_toggleCat_before');
        _toggleCat(catname, action);
        this.fitBounds();
        this.fireEvent('clubmap_toggleCat_after');
    },

    resetCluster: function() {
        that.fireEvent('clubmap_resetCluster_before');
        this.refreshLayers();
        that.fireEvent('clubmap_resetCluster_after');
    },

    refreshLayers: function() {
        that = this;
        that.markerClusters.clearLayers();
        that.geoJson.eachLayer(function (layer) {
            that.markerClusters.addLayer(layer);
        });
    },

    definePopup: function(feature, layer) {
        tag = '
' + feature.properties.venue.name + '
';
        if (feature.properties.hasOwnProperty('clubs')) {
            tag += '
The following clubs play here:

';
            for (var i = 0; i < feature.properties.clubs.length; i++) {
                tag += '
' + feature.properties.clubs[i].name + '
';
            }
            tag += '
';
        }
        layer.bindPopup(tag);
    },

    defineMarker: function(feature, latlng) {
        var ic = new clubIcon2();
        return L.marker(
            latlng,
            {
                icon: ic
            }
        );
    }
});<commit_msg>Icon ref fix.<commit_after>//
// Example of how to override default behaviour
//
//leafletClusterMap.prototype.getBoundsSettings = function() {
//    return {
//        maxZoom: 13
//    };
//};

// Extend the Default marker class
var clubIcon2 = L.Icon.Default.extend({
    options: {
        iconUrl: CLUBS.basePath + '/assets/js/images/marker-icon.png'
    }
});

var clubLayerMap = leafletClusterMap.extend({
    init: function(args) {
        this._super(args);
        that = this;
        loaded = false;

        jQuery.ajax({
            url: CLUBS.basePath + '/clubs.json',
            async: false,
            dataType: 'json',
            success: function(json) {
                that.geoJson = L.geoJson(json, {
                    pointToLayer: function (feature, latlng) {
                        return that.defineMarker(feature, latlng);
                    },
                    onEachFeature: function (feature, layer) {
                        that.definePopup(feature, layer);
                    }
                });

                that.resetCluster();
            }
        });

        that.tiles.on('load', function() {
            if (loaded === false) {
                that.fitBounds();
                loaded = true;
            }
        });

        _toggleCat = function(catname, action) {
            that.geoJson.eachLayer(function (layer) {
                hasCat = false;

                a = layer.feature.properties.tags;
                for (var i = 0; i < a.length; i++) {
                    if (catname === a[i].name) {
                        hasCat = true;
                    }
                }

                if (hasCat === true) {
                    if (action === 'add') {
                        that.markerClusters.addLayer(layer);
                    } else if (action === 'remove') {
                        that.markerClusters.removeLayer(layer);
                    }
                }
            });
        };

        // Call function which can be prototyped
        that.hook_init();
    },

    hook_init: function() {},

    removeCat: function(catname) {
        this.fireEvent('clubmap_removeCat_before');
        this.toggleCat(catname, 'remove');
        this.fireEvent('clubmap_removeCat_after');
    },

    addCat: function(catname) {
        this.fireEvent('clubmap_addCat_before');
        this.toggleCat(catname, 'add');
        this.fireEvent('clubmap_addCat_after');
    },

    toggleCat: function(catname, action) {
        this.fireEvent('clubmap_toggleCat_before');
        _toggleCat(catname, action);
        this.fitBounds();
        this.fireEvent('clubmap_toggleCat_after');
    },

    resetCluster: function() {
        that.fireEvent('clubmap_resetCluster_before');
        this.refreshLayers();
        that.fireEvent('clubmap_resetCluster_after');
    },

    refreshLayers: function() {
        that = this;
        that.markerClusters.clearLayers();
        that.geoJson.eachLayer(function (layer) {
            that.markerClusters.addLayer(layer);
        });
    },

    definePopup: function(feature, layer) {
        tag = '
' + feature.properties.venue.name + '
';
        if (feature.properties.hasOwnProperty('clubs')) {
            tag += '
The following clubs play here:

';
            for (var i = 0; i < feature.properties.clubs.length; i++) {
                tag += '
' + feature.properties.clubs[i].name + '
';
            }
            tag += '
';
        }
        layer.bindPopup(tag);
    },

    defineMarker: function(feature, latlng) {
        var ic = new clubIcon2();
        return L.marker(
            latlng,
            {
                icon: ic
            }
        );
    }
});
<|endoftext|>


<commit_before>var $ = require('jQuery');
var onReady = require('kwf/on-ready');

var ErrorStyleAbstract = function(form) {
    this.form = form;
};
ErrorStyleAbstract.prototype = {
    _showErrorMessagesAbove: function(messages, r)
    {
        var html = '
';
        html += '
' + r.errorPlaceholder + ':
';
        html += '
';
        for (var i=0; i < messages.length; i++) {
            html += '
' + messages[i] + '
';
        }
        html += '
';
        html += '
';
        $(html).insertAfter(this.form.el.find('form'));
        onReady.callOnContentReady(this.form.el, {newRender: true});
    },
    showErrors: function() {
    },
    hideErrors: function() {
        $.each(this.form.fields, (function(index, field) {
            this.hideFieldError(field);
        }).bind(this));
    },
    hideFieldError: function(field) {
    }
};

module.exports = ErrorStyleAbstract;
<commit_msg>Change insertAfter to insertBefore<commit_after>var $ = require('jQuery');
var onReady = require('kwf/on-ready');

var ErrorStyleAbstract = function(form) {
    this.form = form;
};
ErrorStyleAbstract.prototype = {
    _showErrorMessagesAbove: function(messages, r)
    {
        var html = '
';
        html += '
' + r.errorPlaceholder + ':
';
        html += '
';
        for (var i=0; i < messages.length; i++) {
            html += '
' + messages[i] + '
';
        }
        html += '
';
        html += '
';
        $(html).insertBefore(this.form.el.find('form'));
        onReady.callOnContentReady(this.form.el, {newRender: true});
    },
    showErrors: function() {
    },
    hideErrors: function() {
        $.each(this.form.fields, (function(index, field) {
            this.hideFieldError(field);
        }).bind(this));
    },
    hideFieldError: function(field) {
    }
};

module.exports = ErrorStyleAbstract;
<|endoftext|>


<commit_before>/*-------------------------------

	POPUP.JS

	Simple Popup plugin for jQuery

	@author Todd Francis
	@version 2.1.0

-------------------------------*/

;(function($, window){

	'use strict';

	/**
	 * Popup jQuery method
	 *
	 * @param  {Object} settings
	 * @return {Object}
	 */
	$.fn.popup = function(settings){

		var selector = this.selector,
			popup = new $.Popup(settings);

		$(document)
			.on('click.popup', selector, function(e){

				e.preventDefault();

				popup.open($(this).attr('href'), undefined, this);

			});

		return this.each(function(){

			$(this)
				.data('popup', popup);

		});

	};

	/**
	 * Main Popup Class
	 *
	 * @param {Object} settings
	 */
	$.Popup = function(settings)
	{

		var p = this,
			defaults = {

				// Markup
				backClass : 'popup_back',
				backOpacity : 0.7,
				containerClass : 'popup_cont',
				closeContent : '
×
',
				markup : '

',
				contentClass : 'popup_content',
				preloaderContent : '
Loading
',
				activeClass : 'popup_active',
				hideFlash : false,
				speed : 200,
				popupPlaceholderClass : 'popup_placeholder',
				keepInlineChanges :  true,

				// Content
				modal : false,
				content : null,
				type : 'auto',
				width : null,
				height : null,

				// Params
				typeParam : 'pt',
				widthParam : 'pw',
				heightParam : 'ph',

				// Callbacks
				beforeOpen : function(type){},
				afterOpen : function(){},
				beforeClose : function(){},
				afterClose : function(){},
				error : function(){},
				show : function($popup, $back){

					var plugin = this;

					// Center the popup
					plugin.center();

					// Animate in
					$popup
						.animate({opacity : 1}, plugin.o.speed, function(){
							// Call the open callback
							plugin.o.afterOpen.call(plugin);
						});

				},
				replaced : function($popup, $back){

					// Center the popup and call the open callback
					this
						.center()
						.o.afterOpen.call(this);

				},
				hide : function($popup, $back){

					if( $popup !== undefined ){

						// Fade the popup out
						$popup.animate({opacity : 0}, this.o.speed);

					}

				},
				types : {
					inline : function(content, callback){

						var $content = $(content);

						$content
							.addClass(p.o.popupPlaceholderClass);

						// If we don't want to keep any inline changes,
						// get a fresh copy now
						if( !p.o.keepInlineChanges ){
							cachedContent = $content.html();
						}

						callback.call(this, $content.children());

					},
					image : function(content, callback){

						var plugin = this;

						var $image = $('')
							.one('load', function(){

								var img = this;

								// Timeout for Webkit
								// As the width/height of the image is 0 initially
								setTimeout(function(){

									callback.call(plugin, img);

								}, 0);

							})
							.one('error', function(){

								p.o.error.call(p, content, 'image');

							})
							.attr('src', content)
							.each(function() {

								if( this.complete ){

									$(this).trigger('load');

								}

							});

					},
					external : function(content, callback){

						var $frame = $('')
							.attr({
								src : content,
								frameborder : 0,
								width : p.width,
								height : p.height
							});

							callback.call(this, $frame);

					},
					html					: function(content, callback){

						callback.call(this, content);

					},
					jQuery					: function(content, callback){

						callback.call(this, content.html());

					},
					'function'				: function(content, callback){

						callback.call(this, content.call(p));

					},
					ajax					: function(content, callback){

						$.ajax({
							url : content,
							success : function(data){
								callback.call(this, data);
							},
							error : function(data){
								p.o.error.call(p, content, 'ajax');
							}
						});

					}
				}
			},
			imageTypes = ['png', 'jpg', 'gif'],
			type,
			cachedContent,
			$back,
			$pCont,
			$close,
			$preloader,
			$p;

		p.ele = undefined;

		p.o = $.extend(true, {}, defaults, settings);

		/**
		 * Opens a new popup window
		 *
		 * @param  {string} content
		 * @param  {string} popupType
		 * @param  {Object} ele
		 * @return {void}
		 */
		p.open = function(content, popupType, ele){

			// Get the content
			content = ( content === undefined || content === '#' )
				? p.o.content
				: content;

			// If no content is set
			if( content === null ){

				p.o.error.call(p, content, type);
				return false;

			}

			// Was an element passed in?
			if( ele !== undefined ){

				// Remove current active class
				if( p.ele && p.o.activeClass ){

					$(p.ele).removeClass(p.o.activeClass);

				}

				// Record the element
				p.ele = ele;

				// Add an active class
				if( p.ele && p.o.activeClass ){

					$(p.ele).addClass(p.o.activeClass);

				}

			}

			// If we're not open already
			if( $back === undefined ){

				// Create back and fade in
				$back = $('
')
					.appendTo($('body'))
					.css('opacity', 0)
					.animate({
						opacity : p.o.backOpacity
					}, p.o.speed);

				// If modal isn't specified, bind click event
				if( !p.o.modal ){

					$back.one('click.popup', function(){
						p.close();
					});

				}

				// Should we hide the flash?
				if( p.o.hideFlash ){

					$('object, embed').css('visibility', 'hidden');

				}

				// Preloader
				if( p.o.preloaderContent ){

					$preloader = $(p.o.preloaderContent)
						.appendTo($('body'));

				}

			}

			// Get the popupType
			popupType = getValue([popupType, p.o.type]);

			// If it's at auto, guess a real type
			popupType = ( popupType === 'auto' )
				? guessType(content)
				: popupType;

			// Cache the type to use globally
			type = popupType;

			// Do we have a width set?
			p.width = ( p.o.width )
				? p.o.width
				: null;

			// Do we have a height set?
			p.height = ( p.o.height )
				? p.o.height
				: null;

			// If it's not inline, jQuery or a function
			// it might have params, and they are top priority
			if( $.inArray(popupType, ['inline', 'jQuery', 'function']) === -1 ){

				var paramType = getParameterByName(p.o.typeParam, content),
					paramWidth = getParameterByName(p.o.widthParam, content),
					paramHeight = getParameterByName(p.o.heightParam, content);

				// Do we have an overriding paramter?
				popupType = ( paramType !== null )
					? paramType
					: popupType;

				// Do we have an overriding width?
				p.width = ( paramWidth !== null )
					? paramWidth
					: p.width;

				// Do we have an overriding height?
				p.height = ( paramHeight !== null )
					? paramHeight
					: p.height;
			}

			// Callback
			p.o.beforeOpen.call(p, popupType);

			// Show the content based
			if( p.o.types[popupType] ){

				p.o.types[popupType].call(p, content, showContent);

			}else{

				p.o.types.ajax.call(p, content, showContent);

			}

		};

		/**
		 * Return the correct value to be used
		 *
		 * @param  {array} items
		 * @return {mixed}
		 */
		function getValue(items){

			var finalValue;

			$.each(items, function(i, value){

				if( value ){
					finalValue = value;
					return false;
				}

			});

			return finalValue;

		}

		/**
		 * Guess the type of content to show
		 *
		 * @param  {string|Object|function} content
		 * @return {string}
		 */
		function guessType(content){

			if( typeof content === 'function' ){

				return 'function';

			} else if( content instanceof $ ){

				return 'jQuery';

			} else if( content.substr(0, 1) === '#' || content.substr(0, 1) === '.' ){

				return 'inline';

			} else if( $.inArray(content.substr(content.length - 3), imageTypes) !== -1 ) {

				return 'image';

			} else if( content.substr(0, 4) === 'http' ) {

				return 'external';

			}else{

				return 'ajax';

			}

		}

		/**
		 * Shows the content
		 *
		 * @param  {string} content
		 * @return {void}
		 */
		function showContent(content){

			// Do we have a preloader?
			if( $preloader ){

				// If so, hide!
				$preloader.fadeOut('fast', function(){

					$(this).remove();

				});

			}

			// Presume we're replacing
			var replacing = true;

			// If we're not open already
			if( $pCont === undefined ){

				// We're not replacing!
				replacing = false;

				// Create the container
				$pCont = $('
');

				// Add in the popup markup
				$p = $(p.o.markup)
					.appendTo($pCont);

				// Add in the close button
				$close = $(p.o.closeContent)
					.one('click', function(){

						p.close();

					})
					.appendTo($pCont);

				// Bind the resize event
				$(window).resize(p.center);

				// Append the container to the body
				// and set the opacity
				$pCont
					.appendTo($('body'))
					.css('opacity', 0);

			}

			// Get the actual content element
			var $pContent = $('.'+p.o.contentClass, $pCont);

			// Do we have a set width/height?
			if( p.width ){

				$pContent.css('width', p.width, 10);

			}else{

				$pContent.css('width', '');
			}

			if( p.height ){

				$pContent.css('height', p.height, 10);

			}else{

				$pContent.css('height', '');

			}

			// Put the content in place!
			if( $p.hasClass(p.o.contentClass) ){

				$p
					.html(content);

			}else{

				$p
					.find('.'+p.o.contentClass)
					.html(content);

			}

			// Callbacks!
			if( !replacing ){

				p.o.show.call(p, $pCont, $back);

			}else{

				p.o.replaced.call(p, $pCont, $back);

			}

		}

		/**
		 * Close the popup
		 *
		 * @return {Object}
		 */
		p.close = function(){

			p.o.beforeClose.call(p);

			// If we got some inline content, cache it
			// so we can put it back
			if(
				type === 'inline' &&
				p.o.keepInlineChanges
			){
				cachedContent = $('.'+p.o.contentClass).html();
			}

			if( $back !== undefined ){

				// Fade out the back
				$back.animate({opacity : 0}, p.o.speed, function(){

					// Clean up after ourselves
					p.cleanUp();

				});

			}

			// Call the hide callback
			p.o.hide.call(p, $pCont, $back);

			return p;

		};

		/**
		 * Clean up the popup
		 *
		 * @return {Object}
		 */
		p.cleanUp = function(){

			$back
				.add($pCont)
				.remove();

			$pCont = $back = undefined;

			// Unbind the resize event
			$(window).unbind('resize', p.center);

			// Did we hide the flash?
			if( p.o.hideFlash ){

				$('object, embed').css('visibility', 'visible');

			}

			// Remove active class if we can
			if( p.ele && p.o.activeClass ){

				$(p.ele).removeClass(p.o.activeClass);

			}

			var $popupPlaceholder = $('.'+p.o.popupPlaceholderClass);

			// If we got inline content
			// put it back
			if(
				type == 'inline' &&
				$popupPlaceholder.length
			){
				$popupPlaceholder
					.html(cachedContent)
					.removeClass(p.o.popupPlaceholderClass);
			}

			type = null;

			// Call the afterClose callback
			p.o.afterClose.call(p);

			return p;

		};

		/**
		 * Centers the popup
		 *
		 * @return {Object}
		 */
		p.center = function(){

			$pCont.css(p.getCenter());

			// Only need force for IE6
			$back.css({
				height : document.documentElement.clientHeight
			});

			return p;

		};

		/**
		 * Get the center co-ordinates
		 *
		 * Returns the top/left co-ordinates to
		 * put the popup in the center
		 *
		 * @return {Object} top/left keys
		 */
		p.getCenter = function(){

			var pW = $pCont.children().outerWidth(true),
				pH = $pCont.children().outerHeight(true),
				wW = document.documentElement.clientWidth,
				wH = document.documentElement.clientHeight;

			return {
				top : wH * 0.5 - pH * 0.5,
				left : wW * 0.5 - pW * 0.5
			};

		};

		/**
		 * Get parameters by name
		 * @param  {string} name
		 * @return {null|string} null if not found
		 */
		function getParameterByName(name, url){

			var match = new RegExp('[?&]'+name+'=([^&]*)')
				.exec(url);

			return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

		}

	};

}(jQuery, window));<commit_msg>Adds check for overriding content.<commit_after>/*-------------------------------

	POPUP.JS

	Simple Popup plugin for jQuery

	@author Todd Francis
	@version 2.1.0

-------------------------------*/

;(function($, window){

	'use strict';

	/**
	 * Popup jQuery method
	 *
	 * @param  {Object} settings
	 * @return {Object}
	 */
	$.fn.popup = function(settings){

		var selector = this.selector,
			popup = new $.Popup(settings),
			content = settings && settings.content
				? settings.content
				: $(this).attr('href');

		$(document)
			.on('click.popup', selector, function(e){

				e.preventDefault();

				popup.open(content, undefined, this);

			});

		return this.each(function(){

			$(this)
				.data('popup', popup);

		});

	};

	/**
	 * Main Popup Class
	 *
	 * @param {Object} settings
	 */
	$.Popup = function(settings)
	{

		var p = this,
			defaults = {

				// Markup
				backClass : 'popup_back',
				backOpacity : 0.7,
				containerClass : 'popup_cont',
				closeContent : '
×
',
				markup : '

',
				contentClass : 'popup_content',
				preloaderContent : '
Loading
',
				activeClass : 'popup_active',
				hideFlash : false,
				speed : 200,
				popupPlaceholderClass : 'popup_placeholder',
				keepInlineChanges :  true,

				// Content
				modal : false,
				content : null,
				type : 'auto',
				width : null,
				height : null,

				// Params
				typeParam : 'pt',
				widthParam : 'pw',
				heightParam : 'ph',

				// Callbacks
				beforeOpen : function(type){},
				afterOpen : function(){},
				beforeClose : function(){},
				afterClose : function(){},
				error : function(){},
				show : function($popup, $back){

					var plugin = this;

					// Center the popup
					plugin.center();

					// Animate in
					$popup
						.animate({opacity : 1}, plugin.o.speed, function(){
							// Call the open callback
							plugin.o.afterOpen.call(plugin);
						});

				},
				replaced : function($popup, $back){

					// Center the popup and call the open callback
					this
						.center()
						.o.afterOpen.call(this);

				},
				hide : function($popup, $back){

					if( $popup !== undefined ){

						// Fade the popup out
						$popup.animate({opacity : 0}, this.o.speed);

					}

				},
				types : {
					inline : function(content, callback){

						var $content = $(content);

						$content
							.addClass(p.o.popupPlaceholderClass);

						// If we don't want to keep any inline changes,
						// get a fresh copy now
						if( !p.o.keepInlineChanges ){
							cachedContent = $content.html();
						}

						callback.call(this, $content.children());

					},
					image : function(content, callback){

						var plugin = this;

						var $image = $('')
							.one('load', function(){

								var img = this;

								// Timeout for Webkit
								// As the width/height of the image is 0 initially
								setTimeout(function(){

									callback.call(plugin, img);

								}, 0);

							})
							.one('error', function(){

								p.o.error.call(p, content, 'image');

							})
							.attr('src', content)
							.each(function() {

								if( this.complete ){

									$(this).trigger('load');

								}

							});

					},
					external : function(content, callback){

						var $frame = $('')
							.attr({
								src : content,
								frameborder : 0,
								width : p.width,
								height : p.height
							});

							callback.call(this, $frame);

					},
					html					: function(content, callback){

						callback.call(this, content);

					},
					jQuery					: function(content, callback){

						callback.call(this, content.html());

					},
					'function'				: function(content, callback){

						callback.call(this, content.call(p));

					},
					ajax					: function(content, callback){

						$.ajax({
							url : content,
							success : function(data){
								callback.call(this, data);
							},
							error : function(data){
								p.o.error.call(p, content, 'ajax');
							}
						});

					}
				}
			},
			imageTypes = ['png', 'jpg', 'gif'],
			type,
			cachedContent,
			$back,
			$pCont,
			$close,
			$preloader,
			$p;

		p.ele = undefined;

		p.o = $.extend(true, {}, defaults, settings);

		/**
		 * Opens a new popup window
		 *
		 * @param  {string} content
		 * @param  {string} popupType
		 * @param  {Object} ele
		 * @return {void}
		 */
		p.open = function(content, popupType, ele){

			// Get the content
			content = ( content === undefined || content === '#' )
				? p.o.content
				: content;

			// If no content is set
			if( content === null ){

				p.o.error.call(p, content, type);
				return false;

			}

			// Was an element passed in?
			if( ele !== undefined ){

				// Remove current active class
				if( p.ele && p.o.activeClass ){

					$(p.ele).removeClass(p.o.activeClass);

				}

				// Record the element
				p.ele = ele;

				// Add an active class
				if( p.ele && p.o.activeClass ){

					$(p.ele).addClass(p.o.activeClass);

				}

			}

			// If we're not open already
			if( $back === undefined ){

				// Create back and fade in
				$back = $('
')
					.appendTo($('body'))
					.css('opacity', 0)
					.animate({
						opacity : p.o.backOpacity
					}, p.o.speed);

				// If modal isn't specified, bind click event
				if( !p.o.modal ){

					$back.one('click.popup', function(){
						p.close();
					});

				}

				// Should we hide the flash?
				if( p.o.hideFlash ){

					$('object, embed').css('visibility', 'hidden');

				}

				// Preloader
				if( p.o.preloaderContent ){

					$preloader = $(p.o.preloaderContent)
						.appendTo($('body'));

				}

			}

			// Get the popupType
			popupType = getValue([popupType, p.o.type]);

			// If it's at auto, guess a real type
			popupType = ( popupType === 'auto' )
				? guessType(content)
				: popupType;

			// Cache the type to use globally
			type = popupType;

			// Do we have a width set?
			p.width = ( p.o.width )
				? p.o.width
				: null;

			// Do we have a height set?
			p.height = ( p.o.height )
				? p.o.height
				: null;

			// If it's not inline, jQuery or a function
			// it might have params, and they are top priority
			if( $.inArray(popupType, ['inline', 'jQuery', 'function']) === -1 ){

				var paramType = getParameterByName(p.o.typeParam, content),
					paramWidth = getParameterByName(p.o.widthParam, content),
					paramHeight = getParameterByName(p.o.heightParam, content);

				// Do we have an overriding paramter?
				popupType = ( paramType !== null )
					? paramType
					: popupType;

				// Do we have an overriding width?
				p.width = ( paramWidth !== null )
					? paramWidth
					: p.width;

				// Do we have an overriding height?
				p.height = ( paramHeight !== null )
					? paramHeight
					: p.height;
			}

			// Callback
			p.o.beforeOpen.call(p, popupType);

			// Show the content based
			if( p.o.types[popupType] ){

				p.o.types[popupType].call(p, content, showContent);

			}else{

				p.o.types.ajax.call(p, content, showContent);

			}

		};

		/**
		 * Return the correct value to be used
		 *
		 * @param  {array} items
		 * @return {mixed}
		 */
		function getValue(items){

			var finalValue;

			$.each(items, function(i, value){

				if( value ){
					finalValue = value;
					return false;
				}

			});

			return finalValue;

		}

		/**
		 * Guess the type of content to show
		 *
		 * @param  {string|Object|function} content
		 * @return {string}
		 */
		function guessType(content){

			if( typeof content === 'function' ){

				return 'function';

			} else if( content instanceof $ ){

				return 'jQuery';

			} else if( content.substr(0, 1) === '#' || content.substr(0, 1) === '.' ){

				return 'inline';

			} else if( $.inArray(content.substr(content.length - 3), imageTypes) !== -1 ) {

				return 'image';

			} else if( content.substr(0, 4) === 'http' ) {

				return 'external';

			}else{

				return 'ajax';

			}

		}

		/**
		 * Shows the content
		 *
		 * @param  {string} content
		 * @return {void}
		 */
		function showContent(content){

			// Do we have a preloader?
			if( $preloader ){

				// If so, hide!
				$preloader.fadeOut('fast', function(){

					$(this).remove();

				});

			}

			// Presume we're replacing
			var replacing = true;

			// If we're not open already
			if( $pCont === undefined ){

				// We're not replacing!
				replacing = false;

				// Create the container
				$pCont = $('
');

				// Add in the popup markup
				$p = $(p.o.markup)
					.appendTo($pCont);

				// Add in the close button
				$close = $(p.o.closeContent)
					.one('click', function(){

						p.close();

					})
					.appendTo($pCont);

				// Bind the resize event
				$(window).resize(p.center);

				// Append the container to the body
				// and set the opacity
				$pCont
					.appendTo($('body'))
					.css('opacity', 0);

			}

			// Get the actual content element
			var $pContent = $('.'+p.o.contentClass, $pCont);

			// Do we have a set width/height?
			if( p.width ){

				$pContent.css('width', p.width, 10);

			}else{

				$pContent.css('width', '');
			}

			if( p.height ){

				$pContent.css('height', p.height, 10);

			}else{

				$pContent.css('height', '');

			}

			// Put the content in place!
			if( $p.hasClass(p.o.contentClass) ){

				$p
					.html(content);

			}else{

				$p
					.find('.'+p.o.contentClass)
					.html(content);

			}

			// Callbacks!
			if( !replacing ){

				p.o.show.call(p, $pCont, $back);

			}else{

				p.o.replaced.call(p, $pCont, $back);

			}

		}

		/**
		 * Close the popup
		 *
		 * @return {Object}
		 */
		p.close = function(){

			p.o.beforeClose.call(p);

			// If we got some inline content, cache it
			// so we can put it back
			if(
				type === 'inline' &&
				p.o.keepInlineChanges
			){
				cachedContent = $('.'+p.o.contentClass).html();
			}

			if( $back !== undefined ){

				// Fade out the back
				$back.animate({opacity : 0}, p.o.speed, function(){

					// Clean up after ourselves
					p.cleanUp();

				});

			}

			// Call the hide callback
			p.o.hide.call(p, $pCont, $back);

			return p;

		};

		/**
		 * Clean up the popup
		 *
		 * @return {Object}
		 */
		p.cleanUp = function(){

			$back
				.add($pCont)
				.remove();

			$pCont = $back = undefined;

			// Unbind the resize event
			$(window).unbind('resize', p.center);

			// Did we hide the flash?
			if( p.o.hideFlash ){

				$('object, embed').css('visibility', 'visible');

			}

			// Remove active class if we can
			if( p.ele && p.o.activeClass ){

				$(p.ele).removeClass(p.o.activeClass);

			}

			var $popupPlaceholder = $('.'+p.o.popupPlaceholderClass);

			// If we got inline content
			// put it back
			if(
				type == 'inline' &&
				$popupPlaceholder.length
			){
				$popupPlaceholder
					.html(cachedContent)
					.removeClass(p.o.popupPlaceholderClass);
			}

			type = null;

			// Call the afterClose callback
			p.o.afterClose.call(p);

			return p;

		};

		/**
		 * Centers the popup
		 *
		 * @return {Object}
		 */
		p.center = function(){

			$pCont.css(p.getCenter());

			// Only need force for IE6
			$back.css({
				height : document.documentElement.clientHeight
			});

			return p;

		};

		/**
		 * Get the center co-ordinates
		 *
		 * Returns the top/left co-ordinates to
		 * put the popup in the center
		 *
		 * @return {Object} top/left keys
		 */
		p.getCenter = function(){

			var pW = $pCont.children().outerWidth(true),
				pH = $pCont.children().outerHeight(true),
				wW = document.documentElement.clientWidth,
				wH = document.documentElement.clientHeight;

			return {
				top : wH * 0.5 - pH * 0.5,
				left : wW * 0.5 - pW * 0.5
			};

		};

		/**
		 * Get parameters by name
		 * @param  {string} name
		 * @return {null|string} null if not found
		 */
		function getParameterByName(name, url){

			var match = new RegExp('[?&]'+name+'=([^&]*)')
				.exec(url);

			return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

		}

	};

}(jQuery, window));<|endoftext|>


<commit_before>import _ from 'lodash'
import { BloomFilter } from 'bloomfilter'

export const SET_SELECTION = 'SET_SELECTION'
export const ADD_SELECTION = 'ADD_SELECTION'
export const REMOVE_SELECTION = 'ADD_SELECTION'
export const TOGGLE_SELECTION = 'TOGGLE_SELECTION'

export const setSelection = (key, selection) => {
    return {
        type: SET_SELECTION,
        key: key,
        selection: selection
    }
}

export const addSelection = (key, newItem) => {
    return {
        type: ADD_SELECTION,
        key: key,
        item: newItem
    }
}

export const removeSelection = (key, oldItem) => {
    return {
        type: REMOVE_SELECTION,
        key: key,
        item: oldItem
    }
}

export const toggleSelection = (key, item) => {
    return {
        type: TOGGLE_SELECTION,
        key: key,
        item: item
    }
}

class SelectionRange {
    constructor(slice) {
        this.slice = slice
        this.bloom = new BloomFilter(32 * 256, 16)
        _.each(slice, i => this.bloom.add(i))
    }

    contains(value) {
        if (this.bloom.test(value)) {
            return this.slice.indexOf(value) != -1
        } else {
            return false
        }
    }
}

export default class Selectable {
    constructor(key) {
        this.key = key
    }

    selected(state) {
        return new SelectionRange(_.get(state.selections.selections, this.key, []))
    }

    bindActionCreators(dispatch) {
        return {
            add: id => dispatch(addSelection(this.key, id)),
            remove: id => dispatch(removeSelection(this.key, id)),
            set: selection => dispatch(setSelection(this.key, selection)),
            toggle: id => dispatch(toggleSelection(this.key, id))
        }
    }
}
<commit_msg>store: select: use correct string for action type<commit_after>import _ from 'lodash'
import { BloomFilter } from 'bloomfilter'

export const SET_SELECTION = 'SET_SELECTION'
export const ADD_SELECTION = 'ADD_SELECTION'
export const REMOVE_SELECTION = 'REMOVE_SELECTION'
export const TOGGLE_SELECTION = 'TOGGLE_SELECTION'

export const setSelection = (key, selection) => {
    return {
        type: SET_SELECTION,
        key: key,
        selection: selection
    }
}

export const addSelection = (key, newItem) => {
    return {
        type: ADD_SELECTION,
        key: key,
        item: newItem
    }
}

export const removeSelection = (key, oldItem) => {
    return {
        type: REMOVE_SELECTION,
        key: key,
        item: oldItem
    }
}

export const toggleSelection = (key, item) => {
    return {
        type: TOGGLE_SELECTION,
        key: key,
        item: item
    }
}

class SelectionRange {
    constructor(slice) {
        this.slice = slice
        this.bloom = new BloomFilter(32 * 256, 16)
        _.each(slice, i => this.bloom.add(i))
    }

    contains(value) {
        if (this.bloom.test(value)) {
            return this.slice.indexOf(value) != -1
        } else {
            return false
        }
    }
}

export default class Selectable {
    constructor(key) {
        this.key = key
    }

    selected(state) {
        return new SelectionRange(_.get(state.selections.selections, this.key, []))
    }

    bindActionCreators(dispatch) {
        return {
            add: id => dispatch(addSelection(this.key, id)),
            remove: id => dispatch(removeSelection(this.key, id)),
            set: selection => dispatch(setSelection(this.key, selection)),
            toggle: id => dispatch(toggleSelection(this.key, id))
        }
    }
}
<|endoftext|>


<commit_before>/* UMD.define */ (function (root, factory) {
    if (typeof customLoader === 'function'){ customLoader(factory, 'dom'); }else if (typeof define === 'function' && define.amd) { define([], factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.returnExports = factory(); window.dom = factory(); }
}(this, function () {
    //  convenience library for common DOM methods
    //      dom()
    //          create dom nodes
    //      dom.style()
    //          set/get node style
    //      dom.attr()
    //          set/get attributes
    //      dom.destroy()
    //          obliterates a node
    //      dom.box()
    //          get node dimensions
    //      dom.uid()
    //          get a unique ID (not dom specific)
    //
    var
        isDimension = {
            width:1,
            height:1,
            top:1,
            left:1,
            right:1,
            bottom:1,
            maxWidth:1,
            'max-width':1,
            minWidth:1,
            'min-width':1,
            maxHeight:1,
            'max-height':1
        },
        uids = {},
        destroyer = document.createElement('div');

    function uid(type){
        if(!uids[type]){
            uids[type] = [];
        }
        var id = type + '-' + (uids[type].length + 1);
        uids[type].push(id);
        return id;
    }

    function isNode(item){
        // safer test for custom elements in FF (with wc shim)
        return typeof item === 'object' && typeof item.innerHTML === 'string';
    }

    function getNode(item){

        if(!item){ return item; }
        if(typeof item === 'string'){
            return document.getElementById(item);
        }
        // de-jqueryify
        return item.get ? item.get(0) :
            // item is a dom node
            item;
    }

    function byId(id){
        return getNode(id);
    }

    function style(node, prop, value){
        // get/set node style(s)
        //      prop: string or object
        //
        var key, computed;
        if(typeof prop === 'object'){
            // object setter
            for(key in prop){
                if(prop.hasOwnProperty(key)){
                    style(node, key, prop[key]);
                }
            }
            return null;
        }else if(value !== undefined){
            // property setter
            if(typeof value === 'number' && isDimension[prop]){
                value += 'px';
            }
            node.style[prop] = value;

            if(prop === 'userSelect'){
                value = !!value ? 'text' : 'none';
                style(node, {
                    webkitTouchCallout: value,
                    webkitUserSelect: value,
                    khtmlUserSelect: value,
                    mozUserSelect: value,
                    msUserSelect: value
                });
            }
        }

        // getter, if a simple style
        if(node.style[prop]){
            if(isDimension[prop]){
                return parseInt(node.style[prop], 10);
            }
            return node.style[prop];
        }

        // getter, computed
        computed = getComputedStyle(node, prop);
        if(computed[prop]){
            if(/\d/.test(computed[prop])){
                return parseInt(computed[prop], 10);
            }
            return computed[prop];
        }
        return '';
    }

    function attr(node, prop, value){
        // get/set node attribute(s)
        //      prop: string or object
        //
        var key;
        if(typeof prop === 'object'){
            for(key in prop){
                if(prop.hasOwnProperty(key)){
                    attr(node, key, prop[key]);
                }
            }
            return null;
        }
        else if(value !== undefined){
            if(prop === 'text' || prop === 'html' || prop === 'innerHTML'){
                node.innerHTML = value;
            }else{
                node.setAttribute(prop, value);
            }
        }

        return node.getAttribute(prop);
    }

    function box(node){
        if(node === window){
            return {
                width: node.innerWidth,
                height: node.innerHeight
            };
        }
        // node dimensions
        // returned object is immutable
        // add scroll positioning and convenience abbreviations
        var
            dimensions = getNode(node).getBoundingClientRect(),
            box = {
                top: dimensions.top,
                right: dimensions.right,
                bottom: dimensions.bottom,
                left: dimensions.left,
                height: dimensions.height,
                h: dimensions.height,
                width: dimensions.width,
                w: dimensions.width,
                scrollY: window.scrollY,
                scrollX: window.scrollX,
                x: dimensions.left + window.pageXOffset,
                y: dimensions.top + window.pageYOffset
            };

        return box;
    }

    function query(node, selector){
        // TODO: Always return one node
        // Deprecate old way of return one or many (or null or [])
        if(!selector){
            selector = node;
            node = document;
        }
        return node.querySelector(selector);
    }

    function queryAll(node, selector){
        if(!selector){
            selector = node;
            node = document;
        }
        var nodes = node.querySelectorAll(selector);

        if(!nodes.length){ return []; }

        // convert to Array and return it
        return Array.prototype.slice.call(nodes);
    }

    function toDom(html, options, parent){
        // create a node from an HTML string
        var node = dom('div', {html: html});
        parent = byId(parent || options);
        if(parent){
            while(node.firstChild){
                parent.appendChild(node.firstChild);
            }
            return node.firstChild;
        }
        if(html.indexOf('<') !== 0){
            return node;
        }
        return node.firstChild;
    }

    function toFrag(html){
        var frag = document.createDocumentFragment();
        frag.innerHTML = html;
        return frag;
    }

    function dom(nodeType, options, parent, prepend){
        // create a node
        // if first argument is a string and starts with <, it is assumed
        // to use toDom, and creates a node from HTML. Optional second arg is
        // parent to append to
        // else:
        //      nodeType: string, type of node to create
        //      options: object with style, className, or attr properties
        //          (can also be objects)
        //      parent: Node, optional node to append to
        //      prepend: truthy, to append node as the first child
        //
        if(nodeType.indexOf('<') === 0){
            return toDom(nodeType, options, parent);
        }

        options = options || {};
        var
            className = options.css || options.className,
            node = document.createElement(nodeType);

        parent = getNode(parent);

        if(className){
            node.className = className;
        }

        if(options.html || options.innerHTML){
            node.innerHTML = options.html || options.innerHTML;
        }

        if(options.cssText){
            node.style.cssText = options.cssText;
        }

        if(options.id){
            node.id = options.id;
        }

        if(options.style){
            style(node, options.style);
        }

        if(options.attr){
            attr(node, options.attr);
        }

        if(parent && isNode(parent)){
            if(prepend && parent.hasChildNodes()){
                parent.insertBefore(node, parent.children[0]);
            }else{
                parent.appendChild(node);
            }
        }

        return node;
    }

    function destroy(node){
        // destroys a node completely
        //
        if(node) {
            destroyer.appendChild(node);
            destroyer.innerHTML = '';
        }
    }

    function clean(node, dispose){
        //	Removes all child nodes
        //		dispose: destroy child nodes
        if(dispose){
            while(node.children.length){
                destroy(node.children[0]);
            }
            return;
        }
        while(node.children.length){
            node.removeChild(node.children[0]);
        }
    }

    function ancestor (node, selector){
        // TODO: replace this with 'closest' and 'matches'
        // gets the ancestor of node based on selector criteria
        // useful for getting the target node when a child node is clicked upon
        //
        // USAGE
        //      on.selector(childNode, '.app.active');
        //      on.selector(childNode, '#thinger');
        //      on.selector(childNode, 'div');
        //	DOES NOT SUPPORT:
        //		combinations of above
        var
            test,
            parent = node;

        if(selector.indexOf('.') === 0){
            // className
            selector = selector.replace('.', ' ').trim();
            test = function(n){
                return n.classList.contains(selector);
            };
        }
        else if(selector.indexOf('#') === 0){
            // node id
            selector = selector.replace('#', '').trim();
            test = function(n){
                return n.id === selector;
            };
        }
        else if(selector.indexOf('[') > -1){
            // attribute
            console.error('attribute selectors are not yet supported');
        }
        else{
            // assuming node name
            selector = selector.toUpperCase();
            test = function(n){
                return n.nodeName === selector;
            };
        }

        while(parent){
            if(parent === document.body || parent === document){ return false; }
            if(test(parent)){ break; }
            parent = parent.parentNode;
        }

        return parent;
    }

    dom.classList = {
        remove: function(node, names){
            toArray(names).forEach(function(name){
                node.classList.remove(name);
            });
        },
        add: function(node, names){
            toArray(names).forEach(function(name){
                node.classList.add(name);
            });
        },
        contains: function(node, names){
            return toArray(names).every(function (name) {
                return node.classList.contains(name);
            });
        },
        toggle: function(node, names, value){
            toArray(names).forEach(function(name){
                node.classList.toggle(name, value);
            });
        }
    };

    function toArray(names){
        if(!names){
            console.error('dom.classList should include a node and a className');
            return [];
        }
        return names.split(' ').map(function (name) {
            return name.trim();
        });
    }

    if (!window.requestAnimationFrame) {
        dom.requestAnimationFrame = function(callback){
            setTimeout(callback, 0);
        };
    }else{
        dom.requestAnimationFrame = function(cb){
            window.requestAnimationFrame(cb);
        };
    }

    dom.clean = clean;
    dom.query = query;
    dom.queryAll = queryAll;
    dom.byId = byId;
    dom.attr = attr;
    dom.box = box;
    dom.style = style;
    dom.destroy = destroy;
    dom.uid = uid;
    dom.isNode = isNode;
    dom.ancestor = ancestor;
    dom.toDom = toDom;
    dom.toFrag = toFrag;

    return dom;
}));
<commit_msg>get style check for NaN<commit_after>/* UMD.define */ (function (root, factory) {
    if (typeof customLoader === 'function'){ customLoader(factory, 'dom'); }else if (typeof define === 'function' && define.amd) { define([], factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.returnExports = factory(); window.dom = factory(); }
}(this, function () {
    //  convenience library for common DOM methods
    //      dom()
    //          create dom nodes
    //      dom.style()
    //          set/get node style
    //      dom.attr()
    //          set/get attributes
    //      dom.destroy()
    //          obliterates a node
    //      dom.box()
    //          get node dimensions
    //      dom.uid()
    //          get a unique ID (not dom specific)
    //
    var
        isDimension = {
            width:1,
            height:1,
            top:1,
            left:1,
            right:1,
            bottom:1,
            maxWidth:1,
            'max-width':1,
            minWidth:1,
            'min-width':1,
            maxHeight:1,
            'max-height':1
        },
        uids = {},
        destroyer = document.createElement('div');

    function uid(type){
        if(!uids[type]){
            uids[type] = [];
        }
        var id = type + '-' + (uids[type].length + 1);
        uids[type].push(id);
        return id;
    }

    function isNode(item){
        // safer test for custom elements in FF (with wc shim)
        return typeof item === 'object' && typeof item.innerHTML === 'string';
    }

    function getNode(item){

        if(!item){ return item; }
        if(typeof item === 'string'){
            return document.getElementById(item);
        }
        // de-jqueryify
        return item.get ? item.get(0) :
            // item is a dom node
            item;
    }

    function byId(id){
        return getNode(id);
    }

    function style(node, prop, value){
        // get/set node style(s)
        //      prop: string or object
        //
        var key, computed;
        if(typeof prop === 'object'){
            // object setter
            for(key in prop){
                if(prop.hasOwnProperty(key)){
                    style(node, key, prop[key]);
                }
            }
            return null;
        }else if(value !== undefined){
            // property setter
            if(typeof value === 'number' && isDimension[prop]){
                value += 'px';
            }
            node.style[prop] = value;

            if(prop === 'userSelect'){
                value = !!value ? 'text' : 'none';
                style(node, {
                    webkitTouchCallout: value,
                    webkitUserSelect: value,
                    khtmlUserSelect: value,
                    mozUserSelect: value,
                    msUserSelect: value
                });
            }
        }

        // getter, if a simple style
        if(node.style[prop]){
            if(isDimension[prop]){
                return parseInt(node.style[prop], 10);
            }
            return node.style[prop];
        }

        // getter, computed
        computed = getComputedStyle(node, prop);
        if(computed[prop]){
            if(/\d/.test(computed[prop])){
                if(!isNaN(parseInt(computed[prop], 10))){
                    return parseInt(computed[prop], 10);
                }
                return computed[prop];
            }
            return computed[prop];
        }
        return '';
    }

    function attr(node, prop, value){
        // get/set node attribute(s)
        //      prop: string or object
        //
        var key;
        if(typeof prop === 'object'){
            for(key in prop){
                if(prop.hasOwnProperty(key)){
                    attr(node, key, prop[key]);
                }
            }
            return null;
        }
        else if(value !== undefined){
            if(prop === 'text' || prop === 'html' || prop === 'innerHTML'){
                node.innerHTML = value;
            }else{
                node.setAttribute(prop, value);
            }
        }

        return node.getAttribute(prop);
    }

    function box(node){
        if(node === window){
            return {
                width: node.innerWidth,
                height: node.innerHeight
            };
        }
        // node dimensions
        // returned object is immutable
        // add scroll positioning and convenience abbreviations
        var
            dimensions = getNode(node).getBoundingClientRect(),
            box = {
                top: dimensions.top,
                right: dimensions.right,
                bottom: dimensions.bottom,
                left: dimensions.left,
                height: dimensions.height,
                h: dimensions.height,
                width: dimensions.width,
                w: dimensions.width,
                scrollY: window.scrollY,
                scrollX: window.scrollX,
                x: dimensions.left + window.pageXOffset,
                y: dimensions.top + window.pageYOffset
            };

        return box;
    }

    function query(node, selector){
        // TODO: Always return one node
        // Deprecate old way of return one or many (or null or [])
        if(!selector){
            selector = node;
            node = document;
        }
        return node.querySelector(selector);
    }

    function queryAll(node, selector){
        if(!selector){
            selector = node;
            node = document;
        }
        var nodes = node.querySelectorAll(selector);

        if(!nodes.length){ return []; }

        // convert to Array and return it
        return Array.prototype.slice.call(nodes);
    }

    function toDom(html, options, parent){
        // create a node from an HTML string
        var node = dom('div', {html: html});
        parent = byId(parent || options);
        if(parent){
            while(node.firstChild){
                parent.appendChild(node.firstChild);
            }
            return node.firstChild;
        }
        if(html.indexOf('<') !== 0){
            return node;
        }
        return node.firstChild;
    }

    function toFrag(html){
        var frag = document.createDocumentFragment();
        frag.innerHTML = html;
        return frag;
    }

    function dom(nodeType, options, parent, prepend){
        // create a node
        // if first argument is a string and starts with <, it is assumed
        // to use toDom, and creates a node from HTML. Optional second arg is
        // parent to append to
        // else:
        //      nodeType: string, type of node to create
        //      options: object with style, className, or attr properties
        //          (can also be objects)
        //      parent: Node, optional node to append to
        //      prepend: truthy, to append node as the first child
        //
        if(nodeType.indexOf('<') === 0){
            return toDom(nodeType, options, parent);
        }

        options = options || {};
        var
            className = options.css || options.className,
            node = document.createElement(nodeType);

        parent = getNode(parent);

        if(className){
            node.className = className;
        }

        if(options.html || options.innerHTML){
            node.innerHTML = options.html || options.innerHTML;
        }

        if(options.cssText){
            node.style.cssText = options.cssText;
        }

        if(options.id){
            node.id = options.id;
        }

        if(options.style){
            style(node, options.style);
        }

        if(options.attr){
            attr(node, options.attr);
        }

        if(parent && isNode(parent)){
            if(prepend && parent.hasChildNodes()){
                parent.insertBefore(node, parent.children[0]);
            }else{
                parent.appendChild(node);
            }
        }

        return node;
    }

    function destroy(node){
        // destroys a node completely
        //
        if(node) {
            destroyer.appendChild(node);
            destroyer.innerHTML = '';
        }
    }

    function clean(node, dispose){
        //	Removes all child nodes
        //		dispose: destroy child nodes
        if(dispose){
            while(node.children.length){
                destroy(node.children[0]);
            }
            return;
        }
        while(node.children.length){
            node.removeChild(node.children[0]);
        }
    }

    function ancestor (node, selector){
        // TODO: replace this with 'closest' and 'matches'
        // gets the ancestor of node based on selector criteria
        // useful for getting the target node when a child node is clicked upon
        //
        // USAGE
        //      on.selector(childNode, '.app.active');
        //      on.selector(childNode, '#thinger');
        //      on.selector(childNode, 'div');
        //	DOES NOT SUPPORT:
        //		combinations of above
        var
            test,
            parent = node;

        if(selector.indexOf('.') === 0){
            // className
            selector = selector.replace('.', ' ').trim();
            test = function(n){
                return n.classList.contains(selector);
            };
        }
        else if(selector.indexOf('#') === 0){
            // node id
            selector = selector.replace('#', '').trim();
            test = function(n){
                return n.id === selector;
            };
        }
        else if(selector.indexOf('[') > -1){
            // attribute
            console.error('attribute selectors are not yet supported');
        }
        else{
            // assuming node name
            selector = selector.toUpperCase();
            test = function(n){
                return n.nodeName === selector;
            };
        }

        while(parent){
            if(parent === document.body || parent === document){ return false; }
            if(test(parent)){ break; }
            parent = parent.parentNode;
        }

        return parent;
    }

    dom.classList = {
        remove: function(node, names){
            toArray(names).forEach(function(name){
                node.classList.remove(name);
            });
        },
        add: function(node, names){
            toArray(names).forEach(function(name){
                node.classList.add(name);
            });
        },
        contains: function(node, names){
            return toArray(names).every(function (name) {
                return node.classList.contains(name);
            });
        },
        toggle: function(node, names, value){
            toArray(names).forEach(function(name){
                node.classList.toggle(name, value);
            });
        }
    };

    function toArray(names){
        if(!names){
            console.error('dom.classList should include a node and a className');
            return [];
        }
        return names.split(' ').map(function (name) {
            return name.trim();
        });
    }

    if (!window.requestAnimationFrame) {
        dom.requestAnimationFrame = function(callback){
            setTimeout(callback, 0);
        };
    }else{
        dom.requestAnimationFrame = function(cb){
            window.requestAnimationFrame(cb);
        };
    }

    dom.clean = clean;
    dom.query = query;
    dom.queryAll = queryAll;
    dom.byId = byId;
    dom.attr = attr;
    dom.box = box;
    dom.style = style;
    dom.destroy = destroy;
    dom.uid = uid;
    dom.isNode = isNode;
    dom.ancestor = ancestor;
    dom.toDom = toDom;
    dom.toFrag = toFrag;

    return dom;
}));
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { object, string } from 'prop-types'
import Encounter from './Encounter'
import Combatants from './Combatants'
import { defaultConfig } from './helpers'

import './reboot.css'
import './index.css'
import './overlay.css'

class Overlay extends Component {
  static propTypes = {
    Combatant: object,
    Encounter: object,
    isActive: string
  }
  state = {
    currentViewIndex: 0,
    config: {},
    isConfigOpen: false
  }
  defaultConfig = defaultConfig
  configWindow = {}
  componentDidMount() {
    const configStore = localStorage.getItem('horizoverlay')
    if (!configStore) {
      const config = this.defaultConfig
      localStorage.setItem('horizoverlay', JSON.stringify(config))
      this.setState({ config })
    } else {
      const config = JSON.parse(configStore)
      this.setState({ config })
    }
  }
  shouldComponentUpdate(nextProps, nextState) {
    // if (this.state.openConfig) return false
    if (nextProps.Encounter.encdps === '---') return false
    if (this.state.currentViewIndex !== nextState.currentViewIndex) {
      return true
    }
    if (this.state.selectedEncounter) {
      return false
    }
    return true
  }
  handleConfig = e => {
    const target = e.target
    const config = { ...this.state.config }
    let key = target.name,
      value = target.value

    // Why aren't HTML elements more consistent? 😦
    if (target.type === 'checkbox') {
      value = target.checked
    }

    // update the value in our copied state...
    config[key] = value
    // ...and set it to component' state
    this.setState({ config })

    // And then save it to localStorage!
    localStorage.setItem('horizoverlay', JSON.stringify(config))
  }
  openConfig = () => {
    this.setState({ isConfigOpen: true })
    const windowFeatures =
      'menubar=no,location=no,resizable=no,scrollbars=yes,status=no,width=1000,height=187'
    this.configWindow = window.open(
      '/config/',
      'Horizoverlay Config',
      windowFeatures
    )
  }
  render() {
    return (
      <div
        className={`damage-meter${this.props.isActive ? '' : ' inactive'}`}
        onContextMenu={this.openConfig}
      >

Awaiting data.

        <Combatants
          data={this.props.Combatant}
          encounterDamage={this.props.Encounter.damage}
          config={this.state.config}
        />
        <Encounter {...this.props.Encounter} config={this.state.config} />

    )
  }
}

export default Overlay
<commit_msg>Sometimes it's bool, sometimes it's not...<commit_after>import React, { Component } from 'react'
import { object, string, bool, oneOfType } from 'prop-types'
import Encounter from './Encounter'
import Combatants from './Combatants'
import { defaultConfig } from './helpers'

import './reboot.css'
import './index.css'
import './overlay.css'

class Overlay extends Component {
  static propTypes = {
    Combatant: object,
    Encounter: object,
    isActive: oneOfType([string, bool])
  }
  state = {
    currentViewIndex: 0,
    config: {},
    isConfigOpen: false
  }
  defaultConfig = defaultConfig
  configWindow = {}
  componentDidMount() {
    const configStore = localStorage.getItem('horizoverlay')
    if (!configStore) {
      const config = this.defaultConfig
      localStorage.setItem('horizoverlay', JSON.stringify(config))
      this.setState({ config })
    } else {
      const config = JSON.parse(configStore)
      this.setState({ config })
    }
  }
  shouldComponentUpdate(nextProps, nextState) {
    // if (this.state.openConfig) return false
    if (nextProps.Encounter.encdps === '---') return false
    if (this.state.currentViewIndex !== nextState.currentViewIndex) {
      return true
    }
    if (this.state.selectedEncounter) {
      return false
    }
    return true
  }
  handleConfig = e => {
    const target = e.target
    const config = { ...this.state.config }
    let key = target.name,
      value = target.value

    // Why aren't HTML elements more consistent? 😦
    if (target.type === 'checkbox') {
      value = target.checked
    }

    // update the value in our copied state...
    config[key] = value
    // ...and set it to component' state
    this.setState({ config })

    // And then save it to localStorage!
    localStorage.setItem('horizoverlay', JSON.stringify(config))
  }
  openConfig = () => {
    this.setState({ isConfigOpen: true })
    const windowFeatures =
      'menubar=no,location=no,resizable=no,scrollbars=yes,status=no,width=1000,height=187'
    this.configWindow = window.open(
      '/config/',
      'Horizoverlay Config',
      windowFeatures
    )
  }
  render() {
    return (
      <div
        className={`damage-meter${this.props.isActive ? '' : ' inactive'}`}
        onContextMenu={this.openConfig}
      >

Awaiting data.

        <Combatants
          data={this.props.Combatant}
          encounterDamage={this.props.Encounter.damage}
          config={this.state.config}
        />
        <Encounter {...this.props.Encounter} config={this.state.config} />

    )
  }
}

export default Overlay
<|endoftext|>


<commit_before>import { VNode } from "./VNode"

const stack = new Array(128)
let stackIndex = 0
let bodyNode = null
let prevMountedElement = null

const elementOpen = function(type, props, srcElement)
{
	const parent = stack[stackIndex]

	let node = parent.children[parent.index]
	if(!node)
	{
		const element = srcElement || document.createElement(type)
		node = new VNode(parent.index, type, props, element, parent)

		if(prevMountedElement) {
			node.prevElement = prevMountedElement
			prevMountedElement = null
		}

		if(props) {
			for(let key in props) {
				setProp(element, key, props[key])
			}
		}

		parent.children[parent.index] = node
	}
	else
	{
		if(node.type !== type)
		{
			const element = srcElement || document.createElement(type)

			if(node.component)
			{
				node.component.remove()
				node.component = null

				const children = node.children
				for(let n = 0; n < children.length; n++) {
					element.appendChild(children[n].element)
				}
			}
			else
			{
				const prevElement = node.element

				while(prevElement.firstChild) {
					element.appendChild(prevElement.firstChild)
				}

				prevElement.parentElement.replaceChild(element, prevElement)
			}

			if(props)
			{
				for(let key in props) {
					setProp(element, key, props[key])
				}
				node.props = props
			}

			node.id = parent.index
			node.type = type
			node.element = element
		}
		else
		{
			const element = node.element
			const prevProps = node.props

			if(props !== prevProps)
			{
				if(props)
				{
					if(prevProps)
					{
						for(let key in prevProps) {
							if(props[key] === undefined) {
								unsetProp(element, key)
							}
						}

						for(let key in props) {
							const value = props[key]
							if(value !== prevProps[key]) {
								setProp(element, key, value)
							}
						}
					}
					else
					{
						for(let key in props) {
							setProp(element, key, props[key])
						}
					}

					node.props = props
				}
				else
				{
					if(prevProps)
					{
						for(let key in prevProps) {
							unsetProp(element, key)
						}

						node.props = null
					}
				}
			}
		}

		if(prevMountedElement) {
			node.prevElement = prevMountedElement
			prevMountedElement = null
		}
		else {
			node.prevElement = null
		}
	}

	parent.index++
	stackIndex++
	stack[stackIndex] = node

	return node
}

const elementClose = function(type)
{
	const node = stack[stackIndex]

	if(node.type !== type) {
		console.error(`(Element.close) Unexpected element closed: ${type} but was expecting: ${node.type}`)
	}

	if(node.index !== node.children.length) {
		removeUnusedNodes(node)
	}
	node.index = 0

	if(!node.element.parentElement) {
		const parent = stack[stackIndex - 1]
		if((parent.children.length - 1) > node.id) {
			parent.element.insertBefore(node.element, parent.children[node.id + 1].element)
		}
		else {
			parent.element.appendChild(node.element)
		}
	}

	stackIndex--
	prevMountedElement = node.element
}

const elementVoid = function(type, props) {
	const node = elementOpen(type, props)
	elementClose(type)
	return node
}

const element = function(element, props) {
	const node = elementOpen(element.localName, props, element)
	elementClose(element.localName)
	return node
}

const componentVoid = function(componentCls, props)
{
	const parent = stack[stackIndex]

	let node = parent.children[parent.index]
	if(!node) {
		return createComponent(componentCls, parent, node, props)
	}
	else
	{
		const component = node.component
		if(component)
		{
			if(component.constructor !== componentCls) {
				component.remove()
				createComponent(componentCls, parent, node, props)
			}
			else
			{
				const prevProps = node.props
				if(props !== prevProps)
				{
					if(props)
					{
						if(prevProps)
						{
							for(let key in prevProps)
							{
								if(props[key] === undefined) {
									if(key[0] === "$") {
										component[key] = component.state[key.slice(1)]
									}
									else {
										component[key] = null
									}
								}
							}

							for(let key in props) {
								const value = props[key]
								if(component[key] !== value) {
									component[key] = value
								}
							}
						}
						else
						{
							for(let key in props) {
								component[key] = props[key]
							}
						}

						node.props = props
					}
					else if(prevProps)
					{
						for(let key in prevProps) {
							if(key[0] === "$") {
								component[key] = component.state[ket.slice(1)]
							}
							else {
								component[key] = null
							}
						}

						node.props = null
					}
				}

				if(component.dirty)
				{
					parent.index++
					stackIndex++
					stack[stackIndex] = node

					component.render()
					component.index = 0
					component.dirty = false

					if(node.index !== node.children.length) {
						removeUnusedNodes(node)
					}

					node.index = 0

					stackIndex--
				}
				else {
					parent.index++
				}
			}
		}
		else {
			return createComponent(componentCls, parent, node, props)
		}
	}

	return node.component
}

const createComponent = function(componentCls, parent, node, props)
{
	const component = new componentCls()

	if(props) {
		for(let key in props) {
			component[key] = props[key]
		}
	}

	if(component.mount) {
		component.mount()
	}

	let vnode
	if(node)
	{
		if(node.component) {
			vnode = node
			vnode.index = 0
		}
		else {
			vnode = new VNode(0, null, props, parent.element, parent)
			vnode.children.push(node)
			vnode.id = node.id
			node.parent.children[node.id] = vnode
			node.id = 0
			node.index = 0
			node.parent = vnode
		}
	}
	else {
		vnode = new VNode(0, null, props, parent.element, parent)
		parent.children.push(vnode)
	}

	vnode.component = component
	vnode.prevElement = prevMountedElement

	parent.index++
	stackIndex++
	stack[stackIndex] = vnode

	component.vnode = vnode
	component.depth = stackIndex
	component.render()
	component.dirty = false

	if(vnode.index !== vnode.children.length) {
		removeUnusedNodes(vnode)
	}

	vnode.index = 0

	stackIndex--

	return component
}

const text = function(txt)
{
	const parent = stack[stackIndex]
	let node = parent.children[parent.index]
	if(!node) {
		const element = document.createTextNode(txt)
		const node = new VNode(parent.index, "#text", null, element, parent, null)
		parent.children[parent.index] = node
		parent.element.appendChild(element)
	}
	else
	{
		if(node.type !== "#text")
		{
			const element = document.createTextNode(txt)
			node.type = "#text"

			if(node.component) {
				node.component.remove()
				node.component = null
				if(node.prevElement) {
					parent.element.insertBefore(element, node.prevElement.nextSibling)
				}
				else {
					parent.element.appendChild(element)
				}
			}
			else {
				node.element.parentElement.replaceChild(element, node.element)
			}

			node.element = element
			removeUnusedNodes(node)
		}
		else if(node.element.nodeValue !== txt) {
			node.element.nodeValue = txt
		}
	}

	parent.index++

	return node
}

const setProp = function(element, name, value)
{
	if(name === "class") {
		element.className = value
	}
	else if(name === "style")
	{
		if(typeof value === "object") {
			const elementStyle = element.style
			for(let key in value) {
				elementStyle[key] = value[key]
			}
		}
		else {
			element.style.cssText = value
		}
	}
	else if(name[0] === "o" && name[1] === "n") {
		element[name] = value
	}
	else {
		element.setAttribute(name, value)
	}
}

const unsetProp = function(element, name)
{
	if(name === "class") {
		element.className = ""
	}
	else if(name === "style") {
		element.style.cssText = ""
	}
	else if(name[0] === "o" && name[1] === "n") {
		element[name] = null
	}
	else {
		element.removeAttribute(name)
	}
}

const render = function(component, parentElement)
{
	if(!bodyNode) {
		bodyNode = new VNode(0, "body", null, parentElement, null)
	}

	stackIndex = 0
	stack[0] = bodyNode

	componentVoid(component)

	if(bodyNode.index !== bodyNode.children.length) {
		removeUnusedNodes(bodyNode)
	}

	bodyNode.index = 0
}

const renderInstance = function(instance)
{
	const vnode = instance.vnode
	stackIndex = instance.depth
	stack[instance.depth] = vnode
	prevMountedElement = vnode.prevElement
	instance.render()
	instance.dirty = false

	if(vnode.index !== vnode.children.length) {
		removeUnusedNodes(vnode)
	}

	vnode.index = 0
}

const removeUnusedNodes = function(node)
{
	const children = node.children
	for(let n = node.index; n < children.length; n++) {
		const child = children[n]
		removeNode(child)
	}

	children.length = node.index
}

const removeNode = function(node)
{
	if(node.component) {
		node.component.remove()
	}
	else {
		if(node.element.parentElement) {
			node.element.parentElement.removeChild(node.element)
		}
	}

	const children = node.children
	for(let n = 0; n < children.length; n++) {
		const child = children[n]
		removeNode(child)
	}

	node.children.length = 0
}

const removeAll = function() {
	removeUnusedNodes(bodyNode)
}

export {
	elementOpen,
	elementClose,
	elementVoid,
	element,
	componentVoid,
	text,
	render,
	renderInstance,
	removeAll
}<commit_msg>Fix dom insertion if previous element was a component<commit_after>import { VNode } from "./VNode"

const stack = new Array(128)
let stackIndex = 0
let bodyNode = null
let prevMountedElement = null

const elementOpen = function(type, props, srcElement)
{
	const parent = stack[stackIndex]

	let node = parent.children[parent.index]
	if(!node)
	{
		const element = srcElement || document.createElement(type)
		node = new VNode(parent.index, type, props, element, parent)

		if(prevMountedElement) {
			node.prevElement = prevMountedElement
			prevMountedElement = null
		}

		if(props) {
			for(let key in props) {
				setProp(element, key, props[key])
			}
		}

		parent.children[parent.index] = node
	}
	else
	{
		if(node.type !== type)
		{
			const element = srcElement || document.createElement(type)

			if(node.component)
			{
				node.component.remove()
				node.component = null

				const nextIndex = parent.index + 1
				if(parent.children.length > nextIndex) {
					parent.element.insertBefore(element, parent.children[nextIndex].prevElement)
				}

				const children = node.children
				for(let n = 0; n < children.length; n++) {
					element.appendChild(children[n].element)
				}
			}
			else
			{
				const prevElement = node.element

				while(prevElement.firstChild) {
					element.appendChild(prevElement.firstChild)
				}

				prevElement.parentElement.replaceChild(element, prevElement)
			}

			if(props)
			{
				for(let key in props) {
					setProp(element, key, props[key])
				}
				node.props = props
			}

			node.id = parent.index
			node.type = type
			node.element = element
		}
		else
		{
			const element = node.element
			const prevProps = node.props

			if(props !== prevProps)
			{
				if(props)
				{
					if(prevProps)
					{
						for(let key in prevProps) {
							if(props[key] === undefined) {
								unsetProp(element, key)
							}
						}

						for(let key in props) {
							const value = props[key]
							if(value !== prevProps[key]) {
								setProp(element, key, value)
							}
						}
					}
					else
					{
						for(let key in props) {
							setProp(element, key, props[key])
						}
					}

					node.props = props
				}
				else
				{
					if(prevProps)
					{
						for(let key in prevProps) {
							unsetProp(element, key)
						}

						node.props = null
					}
				}
			}
		}

		if(prevMountedElement) {
			node.prevElement = prevMountedElement
			prevMountedElement = null
		}
		else {
			node.prevElement = null
		}
	}

	parent.index++
	stackIndex++
	stack[stackIndex] = node

	return node
}

const elementClose = function(type)
{
	const node = stack[stackIndex]

	if(node.type !== type) {
		console.error(`(Element.close) Unexpected element closed: ${type} but was expecting: ${node.type}`)
	}

	if(node.index !== node.children.length) {
		removeUnusedNodes(node)
	}
	node.index = 0

	if(!node.element.parentElement) {
		const parent = stack[stackIndex - 1]
		parent.element.appendChild(node.element)
	}

	stackIndex--
	prevMountedElement = node.element
}

const elementVoid = function(type, props) {
	const node = elementOpen(type, props)
	elementClose(type)
	return node
}

const element = function(element, props) {
	const node = elementOpen(element.localName, props, element)
	elementClose(element.localName)
	return node
}

const componentVoid = function(componentCls, props)
{
	const parent = stack[stackIndex]

	let node = parent.children[parent.index]
	if(!node) {
		return createComponent(componentCls, parent, node, props)
	}
	else
	{
		const component = node.component
		if(component)
		{
			if(component.constructor !== componentCls) {
				component.remove()
				createComponent(componentCls, parent, node, props)
			}
			else
			{
				const prevProps = node.props
				if(props !== prevProps)
				{
					if(props)
					{
						if(prevProps)
						{
							for(let key in prevProps)
							{
								if(props[key] === undefined) {
									if(key[0] === "$") {
										component[key] = component.state[key.slice(1)]
									}
									else {
										component[key] = null
									}
								}
							}

							for(let key in props) {
								const value = props[key]
								if(component[key] !== value) {
									component[key] = value
								}
							}
						}
						else
						{
							for(let key in props) {
								component[key] = props[key]
							}
						}

						node.props = props
					}
					else if(prevProps)
					{
						for(let key in prevProps) {
							if(key[0] === "$") {
								component[key] = component.state[ket.slice(1)]
							}
							else {
								component[key] = null
							}
						}

						node.props = null
					}
				}

				if(component.dirty)
				{
					parent.index++
					stackIndex++
					stack[stackIndex] = node

					component.render()
					component.index = 0
					component.dirty = false

					if(node.index !== node.children.length) {
						removeUnusedNodes(node)
					}

					node.index = 0

					stackIndex--
				}
				else {
					parent.index++
				}
			}
		}
		else {
			return createComponent(componentCls, parent, node, props)
		}
	}

	return node.component
}

const createComponent = function(componentCls, parent, node, props)
{
	const component = new componentCls()

	if(props) {
		for(let key in props) {
			component[key] = props[key]
		}
	}

	if(component.mount) {
		component.mount()
	}

	let vnode
	if(node)
	{
		if(node.component) {
			vnode = node
			vnode.index = 0
		}
		else {
			vnode = new VNode(0, null, props, parent.element, parent)
			vnode.children.push(node)
			vnode.id = node.id
			node.parent.children[node.id] = vnode
			node.id = 0
			node.index = 0
			node.parent = vnode
		}
	}
	else {
		vnode = new VNode(0, null, props, parent.element, parent)
		parent.children.push(vnode)
	}

	vnode.component = component
	vnode.prevElement = prevMountedElement

	parent.index++
	stackIndex++
	stack[stackIndex] = vnode

	component.vnode = vnode
	component.depth = stackIndex
	component.render()
	component.dirty = false

	if(vnode.index !== vnode.children.length) {
		removeUnusedNodes(vnode)
	}

	vnode.index = 0

	stackIndex--

	return component
}

const text = function(txt)
{
	const parent = stack[stackIndex]
	let node = parent.children[parent.index]
	if(!node) {
		const element = document.createTextNode(txt)
		const node = new VNode(parent.index, "#text", null, element, parent, null)
		parent.children[parent.index] = node
		parent.element.appendChild(element)
	}
	else
	{
		if(node.type !== "#text")
		{
			const element = document.createTextNode(txt)
			node.type = "#text"

			if(node.component) {
				node.component.remove()
				node.component = null
				if(node.prevElement) {
					parent.element.insertBefore(element, node.prevElement.nextSibling)
				}
				else {
					parent.element.appendChild(element)
				}
			}
			else {
				node.element.parentElement.replaceChild(element, node.element)
			}

			node.element = element
			removeUnusedNodes(node)
		}
		else if(node.element.nodeValue !== txt) {
			node.element.nodeValue = txt
		}
	}

	parent.index++

	return node
}

const setProp = function(element, name, value)
{
	if(name === "class") {
		element.className = value
	}
	else if(name === "style")
	{
		if(typeof value === "object") {
			const elementStyle = element.style
			for(let key in value) {
				elementStyle[key] = value[key]
			}
		}
		else {
			element.style.cssText = value
		}
	}
	else if(name[0] === "o" && name[1] === "n") {
		element[name] = value
	}
	else {
		element.setAttribute(name, value)
	}
}

const unsetProp = function(element, name)
{
	if(name === "class") {
		element.className = ""
	}
	else if(name === "style") {
		element.style.cssText = ""
	}
	else if(name[0] === "o" && name[1] === "n") {
		element[name] = null
	}
	else {
		element.removeAttribute(name)
	}
}

const render = function(component, parentElement)
{
	if(!bodyNode) {
		bodyNode = new VNode(0, "body", null, parentElement, null)
	}

	stackIndex = 0
	stack[0] = bodyNode

	componentVoid(component)

	if(bodyNode.index !== bodyNode.children.length) {
		removeUnusedNodes(bodyNode)
	}

	bodyNode.index = 0
}

const renderInstance = function(instance)
{
	const vnode = instance.vnode
	stackIndex = instance.depth
	stack[instance.depth] = vnode
	prevMountedElement = vnode.prevElement
	instance.render()
	instance.dirty = false

	if(vnode.index !== vnode.children.length) {
		removeUnusedNodes(vnode)
	}

	vnode.index = 0
}

const removeUnusedNodes = function(node)
{
	const children = node.children
	for(let n = node.index; n < children.length; n++) {
		const child = children[n]
		removeNode(child)
	}

	children.length = node.index
}

const removeNode = function(node)
{
	if(node.component) {
		node.component.remove()
	}
	else {
		if(node.element.parentElement) {
			node.element.parentElement.removeChild(node.element)
		}
	}

	const children = node.children
	for(let n = 0; n < children.length; n++) {
		const child = children[n]
		removeNode(child)
	}

	node.children.length = 0
}

const removeAll = function() {
	removeUnusedNodes(bodyNode)
}

export {
	elementOpen,
	elementClose,
	elementVoid,
	element,
	componentVoid,
	text,
	render,
	renderInstance,
	removeAll
}<|endoftext|>


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

import Polyfill from './utils/polyfill.js';
import Features from './core/features.js';
import {BaseLoader, LoaderStatus, LoaderErrors} from './io/loader.js';
import FlvPlayer from './player/flv-player.js';
import NativePlayer from './player/native-player.js';
import PlayerEvents from './player/player-events.js';
import {ErrorTypes, ErrorDetails} from './player/player-errors.js';
import LoggingControl from './utils/logging-control.js';
import {InvalidArgumentException} from './utils/exception.js';

// here are all the interfaces

// install polyfills
Polyfill.install();

// factory method
function createPlayer(mediaDataSource, optionalConfig) {
    let mds = mediaDataSource;
    if (mds == null || typeof mds !== 'object') {
        throw new InvalidArgumentException('MediaDataSource must be an javascript object!');
    }

    if (!mds.hasOwnProperty('type')) {
        throw new InvalidArgumentException('MediaDataSource must has type field to indicate video file type!');
    }

    switch (mds.type) {
        case 'flv':
            return new FlvPlayer(mds, optionalConfig);
        default:
            return new NativePlayer(mds, optionalConfig);
    }
}

// feature detection
function isSupported() {
    return Features.supportMSEH264Playback();
}

function getFeatureList() {
    return Features.getFeatureList();
}

// interfaces
let flvjs = {};

flvjs.createPlayer = createPlayer;
flvjs.isSupported = isSupported;
flvjs.getFeatureList = getFeatureList;

flvjs.BaseLoader = BaseLoader;
flvjs.LoaderStatus = LoaderStatus;
flvjs.LoaderErrors = LoaderErrors;

flvjs.Events = PlayerEvents;
flvjs.ErrorTypes = ErrorTypes;
flvjs.ErrorDetails = ErrorDetails;

flvjs.FlvPlayer = FlvPlayer;
flvjs.NativePlayer = NativePlayer;
flvjs.LoggingControl = LoggingControl;

Object.defineProperty(flvjs, 'version', {
    enumerable: true,
    get: function () {
        // replaced by browserify-versionify transform
        return __VERSION__;
    }
});

export default flvjs;<commit_msg>src/flv.js: Update comment<commit_after>/*
 * Copyright (C) 2016 Bilibili. All Rights Reserved.
 *
 * @author zheng qian <xqq@xqq.im>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import Polyfill from './utils/polyfill.js';
import Features from './core/features.js';
import {BaseLoader, LoaderStatus, LoaderErrors} from './io/loader.js';
import FlvPlayer from './player/flv-player.js';
import NativePlayer from './player/native-player.js';
import PlayerEvents from './player/player-events.js';
import {ErrorTypes, ErrorDetails} from './player/player-errors.js';
import LoggingControl from './utils/logging-control.js';
import {InvalidArgumentException} from './utils/exception.js';

// here are all the interfaces

// install polyfills
Polyfill.install();

// factory method
function createPlayer(mediaDataSource, optionalConfig) {
    let mds = mediaDataSource;
    if (mds == null || typeof mds !== 'object') {
        throw new InvalidArgumentException('MediaDataSource must be an javascript object!');
    }

    if (!mds.hasOwnProperty('type')) {
        throw new InvalidArgumentException('MediaDataSource must has type field to indicate video file type!');
    }

    switch (mds.type) {
        case 'flv':
            return new FlvPlayer(mds, optionalConfig);
        default:
            return new NativePlayer(mds, optionalConfig);
    }
}

// feature detection
function isSupported() {
    return Features.supportMSEH264Playback();
}

function getFeatureList() {
    return Features.getFeatureList();
}

// interfaces
let flvjs = {};

flvjs.createPlayer = createPlayer;
flvjs.isSupported = isSupported;
flvjs.getFeatureList = getFeatureList;

flvjs.BaseLoader = BaseLoader;
flvjs.LoaderStatus = LoaderStatus;
flvjs.LoaderErrors = LoaderErrors;

flvjs.Events = PlayerEvents;
flvjs.ErrorTypes = ErrorTypes;
flvjs.ErrorDetails = ErrorDetails;

flvjs.FlvPlayer = FlvPlayer;
flvjs.NativePlayer = NativePlayer;
flvjs.LoggingControl = LoggingControl;

Object.defineProperty(flvjs, 'version', {
    enumerable: true,
    get: function () {
        // replace by webpack.DefinePlugin
        return __VERSION__;
    }
});

export default flvjs;<|endoftext|>