<commit_before>/**
 * Provides Form and input features.
 *
 * @module furnace
 * @submodule furnace-forms
 */
import Ember from 'ember';
import Lookup from 'furnace-forms/utils/lookup-class';
import I18n from 'furnace-i18n';
/**
 * Abstract control component proxy
 *
 * @class Abstract
 * @namespace Furnace.Forms.Controls
 * @extends Ember.ObjectProxy
 * @private
 */
export default Ember.Object.extend(Ember.ActionHandler,{

	_name: null,

	_form: null,

	_panel: null,

	_component: null,

	_for : null,

	decorator: Ember.computed('_component,_componentType',function() {
		return this.get('_componentType')+'.'+this.get('_component');
	}),

	caption: I18n.computed(null),

	hasPrerequisites: null,

	_messagesSilent: false,

	actions: {

		reset : function(action) {
			this._reset();
		},
	},

	isEnabled: true,

	_enabled: true,

	setEnabled: function(enabled) {
		if(enabled!=this._enabled) {
			this.set('_enabled',enabled);
		}
		this.setFlag('isEnabled',this._enabled && (!this._panel || this._panel.isEnabled));
	},

	_panelEnabledObserver:Ember.observer('_panel.isEnabled',function() {
		this.setEnabled(this._enabled);
	}),

	_valid: null,

	isValid: null,

	setValid: function(valid) {
		Ember.run.once(this,function() {
			if(valid!==this._valid) {
				this.setFlag('isValid',valid);
				this.set('_valid',valid);
				this.notifyChange();
			}
		});
	},

	store: Ember.computed.alias('target.store'),

	_dirty: false,

	isDirty: false,

	setDirty: function(dirty) {
		Ember.run.once(this,function() {
			if(dirty!==this._dirty) {
				this.setFlag('isDirty',dirty);
				this.set('_dirty',dirty);
				this.notifyChange();
			}
		});
	},

	setFlag:function(property,value) {
		this.set(property,value);
		this._components.invoke('set',property,value);
	},

	init:function() {
		this._super();
		this.set('_controlMessages',Ember.A());
		this.set('_components',Ember.A());
		var control=this;
		// Initialize computed attributes
		this.constructor.eachComputedProperty(function(name, meta) {
			if (meta.type==='form-attr') {
				control.get(name);
			}
		});
		if(this._form) {
			this.set('_path',this._getPath());
			this.set('target',this._panel);
		}
		if(this.caption instanceof Ember.ComputedProperty && this.get('caption')===null) {
			var name=this.get('_panel._modelName') ? this.get('_panel._modelName')+'.'+this.get('_name') : this.get('_name');
			this.set('caption',name);
		}
		this._registerControl ? this._registerControl(this) : this._form._registerControl(this);
	},

	_apply: function() {

	},

	_reset: function() {
		this.setFlag('isValid',null);
		this.set('_valid',null);
	},

	notifyChange: function() {
		if(this._panel) {
			Ember.run.scheduleOnce('sync',this,function() {
				this._panel.propertyDidChange(this._name);
			});
		}
	},

	_getPath: function() {
		if(!this['for']) {
			return (this.get('_panel._path') ? this.get('_panel._path')+ "." : '')+this.get('_name');
		}
	},

	getFor : function(path) {
		var model=null;
		if(this['for'])
			model = this.get('for');
		else
			model = this.getForm().get('for');
		Ember.assert('Control '+this.toString()+' is trying to access the (form)model but it is not defined!',model);
		if(path) {
			return model.get(path);
		}
		return model;
	},

	getTarget : function() {
		if(this._form)
			return this.getForm().get('targetObject');
		return this.get('targetObject');
	},

	getPanel : function() {
		return this._panel;
	},

	getForm : function(path) {
		if(path) {
			return this._form.get(path);
		}
		return this._form;
	},

	_controlMessages : null,

	setMessages: function(messages,silent) {
		this._updateMessages(messages,this._controlMessages);
		if(this.get('hasPrerequisites')===false || this._components.length===0)
			silent=true;
		this._messagesSilent=silent;
//		console.log("New messages for "+this+" Components: "+this._components.length);
		if(!silent) {
			Ember.run.once(this,function() {
				this._components.invoke('_controlMessageObserver');
			});
		}
	},

	_updateMessages: function(source,target) {
		var remove=Ember.A();
		target.forEach(function(item) {
			if(!source) {
				remove.pushObject(item);
			} else {
				var _messages=source.filterBy('type',item.type).filterBy('message',item.message);
				if(!_messages.length) {
					remove.pushObject(item);
				} else {

					_messages.forEach(function(message) {
						Ember.set(item,'attributes',message.attributes);
						source.removeObject(message);
					})
				}
			}
		});
		target.removeObjects(remove);
		if(source) {
			source.forEach(function(message) {
				target.pushObject(message)
			});
		}
	},

	_components : null,

	registerComponent:function(component) {
		this._components.pushObject(component);
		component.set('isValid',this.get('isValid'));
		component.set('isEnabled',this.get('isEnabled'));
		component.set('isDirty',this.get('isDirty'));
		if(!this._messagesSilent) {
//			console.log(component+" component registered to "+this+", updating messages");
			component._controlMessageObserver();
		}
	},

	unregisterComponent:function(component) {
		this._components.removeObject(component);
	},

	_componentType : 'forms',

	getComponentClass : function() {
		var component=this._component
		if(typeof component ==="string") {
			component = Lookup.call(this,this._component,this._componentType);
		}
		return component;
	},

	getComponent : function() {
		var component=this.getComponentClass();
		if(!component)
			return null;
		return component.create({container:this.container,
								control:this,
								_debugContainerKey : component + this.get('_name')
								});
	},

	toString: function() {
		var string=this._super();
		return string.substring(0,string.length-1)+':'+this.get('_name')+'>';
	},

	willDestroy : function() {
		this._unregisterControl ? this._unregisterControl(this) : this._form._unregisterControl(this);
		this._super();
//		console.log('Destroy control ',this.toString());
	},

	destroy: function() {
		this._super();
//		console.log('destroying control',this.toString(),this._name);
//		Ember.warn('Destroying control '+this.toString()+ ' while there are still components attached! '+ (this._components.length),this._components.length===0);
//		if(this._components.length!==0)
//			console.trace();
	},

});<commit_msg>Fixed abstract control for enabled issues.<commit_after>/**
 * Provides Form and input features.
 *
 * @module furnace
 * @submodule furnace-forms
 */
import Ember from 'ember';
import Lookup from 'furnace-forms/utils/lookup-class';
import I18n from 'furnace-i18n';
/**
 * Abstract control component proxy
 *
 * @class Abstract
 * @namespace Furnace.Forms.Controls
 * @extends Ember.ObjectProxy
 * @private
 */
export default Ember.Object.extend(Ember.ActionHandler,{

	_name: null,

	_form: null,

	_panel: null,

	_component: null,

	_for : null,

	decorator: Ember.computed('_component,_componentType',function() {
		return this.get('_componentType')+'.'+this.get('_component');
	}),

	caption: I18n.computed(null),

	hasPrerequisites: null,

	_messagesSilent: false,

	actions: {

		reset : function(action) {
			this._reset();
		},
	},

	isEnabled: true,

	_enabled: true,

	setEnabled: function(enabled) {
		if(enabled!==this._enabled) {
			this.set('_enabled',enabled);
		}
		this.setFlag('isEnabled',this._enabled && (!this._panel || this._panel.isEnabled));
	},

	_panelEnabledObserver:Ember.observer('_panel.isEnabled',function() {
		this.setEnabled(this._enabled);
	}),

	_valid: null,

	isValid: null,

	setValid: function(valid) {
		Ember.run.once(this,function() {
			if(valid!==this._valid) {
				this.setFlag('isValid',valid);
				this.set('_valid',valid);
				this.notifyChange();
			}
		});
	},

	store: Ember.computed.alias('target.store'),

	_dirty: false,

	isDirty: false,

	setDirty: function(dirty) {
		Ember.run.once(this,function() {
			if(dirty!==this._dirty) {
				this.setFlag('isDirty',dirty);
				this.set('_dirty',dirty);
				this.notifyChange();
			}
		});
	},

	setFlag:function(property,value) {
		this.set(property,value);
		this._components.invoke('set',property,value);
	},

	init:function() {
		this._super();
		this.set('_controlMessages',Ember.A());
		this.set('_components',Ember.A());
		var control=this;
		// Initialize computed attributes
		this.constructor.eachComputedProperty(function(name, meta) {
			if (meta.type==='form-attr') {
				control.get(name);
			}
		});
		if(this._form) {
			this.set('_path',this._getPath());
			this.set('target',this._panel);
		}
		if(this.caption instanceof Ember.ComputedProperty && this.get('caption')===null) {
			var name=this.get('_panel._modelName') ? this.get('_panel._modelName')+'.'+this.get('_name') : this.get('_name');
			this.set('caption',name);
		}

		this._panelEnabledObserver();
		this._registerControl ? this._registerControl(this) : this._form._registerControl(this);
	},

	_apply: function() {

	},

	_reset: function() {
		this.setFlag('isValid',null);
		this.set('_valid',null);
	},

	notifyChange: function() {
		if(this._panel) {
			Ember.run.scheduleOnce('sync',this,function() {
				this._panel.propertyDidChange(this._name);
			});
		}
	},

	_getPath: function() {
		if(!this['for']) {
			return (this.get('_panel._path') ? this.get('_panel._path')+ "." : '')+this.get('_name');
		}
	},

	getFor : function(path) {
		var model=null;
		if(this['for'])
			model = this.get('for');
		else
			model = this.getForm().get('for');
		Ember.assert('Control '+this.toString()+' is trying to access the (form)model but it is not defined!',model);
		if(path) {
			return model.get(path);
		}
		return model;
	},

	getTarget : function() {
		if(this._form)
			return this.getForm().get('targetObject');
		return this.get('targetObject');
	},

	getPanel : function() {
		return this._panel;
	},

	getForm : function(path) {
		if(path) {
			return this._form.get(path);
		}
		return this._form;
	},

	_controlMessages : null,

	setMessages: function(messages,silent) {
		this._updateMessages(messages,this._controlMessages);
		if(this.get('hasPrerequisites')===false || this._components.length===0)
			silent=true;
		this._messagesSilent=silent;
//		console.log("New messages for "+this+" Components: "+this._components.length);
		if(!silent) {
			Ember.run.once(this,function() {
				this._components.invoke('_controlMessageObserver');
			});
		}
	},

	_updateMessages: function(source,target) {
		var remove=Ember.A();
		target.forEach(function(item) {
			if(!source) {
				remove.pushObject(item);
			} else {
				var _messages=source.filterBy('type',item.type).filterBy('message',item.message);
				if(!_messages.length) {
					remove.pushObject(item);
				} else {

					_messages.forEach(function(message) {
						Ember.set(item,'attributes',message.attributes);
						source.removeObject(message);
					});
				}
			}
		});
		target.removeObjects(remove);
		if(source) {
			source.forEach(function(message) {
				target.pushObject(message);
			});
		}
	},

	_components : null,

	registerComponent:function(component) {
		this._components.pushObject(component);
		component.set('isValid',this.get('isValid'));
		component.set('isEnabled',this.get('isEnabled'));
		component.set('isDirty',this.get('isDirty'));
		if(!this._messagesSilent) {
//			console.log(component+" component registered to "+this+", updating messages");
			component._controlMessageObserver();
		}
	},

	unregisterComponent:function(component) {
		this._components.removeObject(component);
	},

	_componentType : 'forms',

	getComponentClass : function() {
		var component=this._component
		if(typeof component ==="string") {
			component = Lookup.call(this,this._component,this._componentType);
		}
		return component;
	},

	getComponent : function() {
		var component=this.getComponentClass();
		if(!component)
			return null;
		return component.create({container:this.container,
								control:this,
								_debugContainerKey : component + this.get('_name')
								});
	},

	toString: function() {
		var string=this._super();
		return string.substring(0,string.length-1)+':'+this.get('_name')+'>';
	},

	willDestroy : function() {
		this._unregisterControl ? this._unregisterControl(this) : this._form._unregisterControl(this);
		this._super();
//		console.log('Destroy control ',this.toString());
	},

	destroy: function() {
		this._super();
//		console.log('destroying control',this.toString(),this._name);
//		Ember.warn('Destroying control '+this.toString()+ ' while there are still components attached! '+ (this._components.length),this._components.length===0);
//		if(this._components.length!==0)
//			console.trace();
	},

});<|endoftext|>


<commit_before>/* global impress, marked */

(function (document, window) {
    'use strict';

    var state = {
        page: 1,
        x: 0,
        y: 0,
        z: 0,
        dx: 1500,
        dy: 0,
        dz: 0,
        isOpenBracket: false,
        groups: {}
    };

    var ImpressMd = window.ImpressMd = function (rootId) {
        this.rootId = rootId || 'impress';

        var htmlContent = marked(content, {renderer: this.renderer});

        if (state.isOpenBracket) {
            htmlContent += '
';
        }

        this.root = document.getElementById(this.rootId);
        this.root.innerHTML = htmlContent;
        this.root.addEventListener('impress:stepenter', setGroupToBody);
        this.root.addEventListener('impress:stepleave', setGroupToBody);

        impress().init(this.rootId);
    };

    function setGroupToBody () {
        var body = document.body;

        var oldGroups = [];
        var newGroups = [];
        var classes = body.classList;
        for (var i = 0; i < classes.length; i++) {
            if (classes[i].match(/(impress-group-.+)/)) {
                oldGroups.push(RegExp.$1);
            }

            if (classes[i].match(/impress-on-(.+)/)) {
                newGroups = state.groups[RegExp.$1];
            }
        }

        if (oldGroups.length > 0) {
            for (var i = 0; i < oldGroups.length; i++) {
                body.classList.remove(oldGroups[i]);
            }
        }

        if (newGroups && newGroups.length > 0) {
            for (var i = 0; i < newGroups.length; i++) {
                body.classList.add('impress-group-' + newGroups[i]);
            }
        }
    }

    ImpressMd.prototype.renderer = new marked.Renderer();

    ImpressMd.prototype.renderer.heading = function (text, level) {
        var params = null;

        if (text.match(/(.*)/)) {
            text = RegExp.$1;
            params = parse(RegExp.$2);
        }
        // console.log(params);

        var config = {
            id: 'page' + state.page,
            classes: 'step',
            tx: 0,
            ty: 0,
            tz: 0
        };

        if (params) {
            if (params.x) {
                state.x = Number(params.x);
            }
            if (params.y) {
                state.y = Number(params.y);
            }
            if (params.z) {
                state.z = Number(params.z);
            }
            if (params.dx) {
                state.dx = Number(params.dx);
            }
            if (params.dy) {
                state.dy = Number(params.dy);
            }
            if (params.dz) {
                state.dz = Number(params.dz);
            }
            if (params.tx) {
                config.tx = Number(params.tx);
            }
            if (params.ty) {
                config.ty = Number(params.ty);
            }
            if (params.tz) {
                config.tz = Number(params.tz);
            }

            if (params.id) {
                config.id = params.id;
            }
            if (params['class']) {
                config.classes += ' ' + params['class'];
            }
            if (params.scale) {
                config.scale = Number(params.scale);
            }
            if (params.rotate) {
                config.rotate = params.rotate;
            }
            if (params['rotate-x']) {
                config.rotateX = params['rotate-x'];
            }
            if (params['rotate-y']) {
                config.rotateY = params['rotate-y'];
            }
            if (params['rotate-z']) {
                config.rotateZ = params['rotate-z'];
            }
        }

        if (params.group) {
            state.groups[config.id] = params.group.split(' ');
        }

        var html = '';

        if (state.isOpenBracket) {
            html += '
\n';
        }

        html += '<div id="' + config.id + '"' +
            ' class="' + config.classes + '"' +
            ' data-x="' + (state.x + config.tx) + '"' +
            ' data-y="' + (state.y + config.ty) + '"' +
            ' data-z="' + (state.z + config.tz) + '"' +
            (config.scale    ? ' data-scale="'    + config.scale    + '"' : '') +
            (config.rotate   ? ' data-rotate="'   + config.rotate   + '"' : '') +
            (config.rotateX ? ' data-rotate-x="' + config.rotateX + '"' : '') +
            (config.rotateY ? ' data-rotate-y="' + config.rotateY + '"' : '') +
            (config.rotateZ ? ' data-rotate-z="' + config.rotateZ + '"' : '') +
            '>\n';

        html += '<h' + level + '>' + text + '</h' + level + '>\n';

        // console.log(html);

        state.page++;
        state.x += state.dx;
        state.y += state.dy;
        state.z += state.dz;
        state.isOpenBracket = true;

        return html;
    };

    function parse (text) {
        var params = {};

        var strings = text.split(',');
        for (var i = 0; i < strings.length; i++) {
            if (strings[i].match(/\s*([\w-]+):\s*['"]*([\w-. ]+)['"]*/)) {
                var key = RegExp.$1;
                var value = RegExp.$2;
                // console.log(key + ': ' + value);

                params[key] = value;
            }
        }

        return params;
    }

    var content = '@@content';

})(document, window);
<commit_msg>Fix issue when slide does not have params<commit_after>/* global impress, marked */

(function (document, window) {
    'use strict';

    var state = {
        page: 1,
        x: 0,
        y: 0,
        z: 0,
        dx: 1500,
        dy: 0,
        dz: 0,
        isOpenBracket: false,
        groups: {}
    };

    var ImpressMd = window.ImpressMd = function (rootId) {
        this.rootId = rootId || 'impress';

        var htmlContent = marked(content, {renderer: this.renderer});

        if (state.isOpenBracket) {
            htmlContent += '
';
        }

        this.root = document.getElementById(this.rootId);
        this.root.innerHTML = htmlContent;
        this.root.addEventListener('impress:stepenter', setGroupToBody);
        this.root.addEventListener('impress:stepleave', setGroupToBody);

        impress().init(this.rootId);
    };

    function setGroupToBody () {
        var body = document.body;

        var oldGroups = [];
        var newGroups = [];
        var classes = body.classList;
        for (var i = 0; i < classes.length; i++) {
            if (classes[i].match(/(impress-group-.+)/)) {
                oldGroups.push(RegExp.$1);
            }

            if (classes[i].match(/impress-on-(.+)/)) {
                newGroups = state.groups[RegExp.$1];
            }
        }

        if (oldGroups.length > 0) {
            for (var i = 0; i < oldGroups.length; i++) {
                body.classList.remove(oldGroups[i]);
            }
        }

        if (newGroups && newGroups.length > 0) {
            for (var i = 0; i < newGroups.length; i++) {
                body.classList.add('impress-group-' + newGroups[i]);
            }
        }
    }

    ImpressMd.prototype.renderer = new marked.Renderer();

    ImpressMd.prototype.renderer.heading = function (text, level) {
        var params = null;

        if (text.match(/(.*)/)) {
            text = RegExp.$1;
            params = parse(RegExp.$2);
        }
        // console.log(params);

        var config = {
            id: 'page' + state.page,
            classes: 'step',
            tx: 0,
            ty: 0,
            tz: 0
        };

        if (params) {
            if (params.x) {
                state.x = Number(params.x);
            }
            if (params.y) {
                state.y = Number(params.y);
            }
            if (params.z) {
                state.z = Number(params.z);
            }
            if (params.dx) {
                state.dx = Number(params.dx);
            }
            if (params.dy) {
                state.dy = Number(params.dy);
            }
            if (params.dz) {
                state.dz = Number(params.dz);
            }
            if (params.tx) {
                config.tx = Number(params.tx);
            }
            if (params.ty) {
                config.ty = Number(params.ty);
            }
            if (params.tz) {
                config.tz = Number(params.tz);
            }

            if (params.id) {
                config.id = params.id;
            }
            if (params['class']) {
                config.classes += ' ' + params['class'];
            }
            if (params.scale) {
                config.scale = Number(params.scale);
            }
            if (params.rotate) {
                config.rotate = params.rotate;
            }
            if (params['rotate-x']) {
                config.rotateX = params['rotate-x'];
            }
            if (params['rotate-y']) {
                config.rotateY = params['rotate-y'];
            }
            if (params['rotate-z']) {
                config.rotateZ = params['rotate-z'];
            }

            if (params.group) {
                state.groups[config.id] = params.group.split(' ');
            }
        }

        var html = '';

        if (state.isOpenBracket) {
            html += '
\n';
        }

        html += '<div id="' + config.id + '"' +
            ' class="' + config.classes + '"' +
            ' data-x="' + (state.x + config.tx) + '"' +
            ' data-y="' + (state.y + config.ty) + '"' +
            ' data-z="' + (state.z + config.tz) + '"' +
            (config.scale    ? ' data-scale="'    + config.scale    + '"' : '') +
            (config.rotate   ? ' data-rotate="'   + config.rotate   + '"' : '') +
            (config.rotateX ? ' data-rotate-x="' + config.rotateX + '"' : '') +
            (config.rotateY ? ' data-rotate-y="' + config.rotateY + '"' : '') +
            (config.rotateZ ? ' data-rotate-z="' + config.rotateZ + '"' : '') +
            '>\n';

        html += '<h' + level + '>' + text + '</h' + level + '>\n';

        // console.log(html);

        state.page++;
        state.x += state.dx;
        state.y += state.dy;
        state.z += state.dz;
        state.isOpenBracket = true;

        return html;
    };

    function parse (text) {
        var params = {};

        var strings = text.split(',');
        for (var i = 0; i < strings.length; i++) {
            if (strings[i].match(/\s*([\w-]+):\s*['"]*([\w-. ]+)['"]*/)) {
                var key = RegExp.$1;
                var value = RegExp.$2;
                // console.log(key + ': ' + value);

                params[key] = value;
            }
        }

        return params;
    }

    var content = '@@content';

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


<commit_before>/*!
 * Histery.js v0.0.0, https://github.com/hoho/histery
 * (c) 2013 Marat Abdullin, MIT license
 */
var $H = (function(window, location, undefined) {
    var history = window.history || {},
        routes = {},
        pending = [],
        key,
        val,
        i,
        args,
        tmp,
        initialized,
        nopush,
        pageId = 0,
        waitCount,
        currentCallbacks,
        goCallbacks,
        processed,

        isExpr = function(hrefOrExpr) {
            return hrefOrExpr instanceof RegExp;
        },

        getRouteKey = function(hrefOrExpr) {
            return (isExpr(hrefOrExpr) ? 'e' : 's') + hrefOrExpr;
        },

        stop = function(error) {
            waitCount = 0;
            currentCallbacks = {};
            while ((tmp = pending.shift())) {
                tmp(error);
            }
        },

        getFullURI = function(href/**/, l) {
            l = location;
            if (href) {
                l = document.createElement('a');
                l.href = href;
            }
            return l.pathname + l.search + ((l.hash.length > 1) ? l.hash : '');
        },

        callDoneCallbacks = function(/**/callbacks, j) {
            for (key in currentCallbacks) {
                val = currentCallbacks[key];
                callbacks = val.c;
                args = val.a;

                for (j = 0; j < callbacks.length; j++) {
                    if ((tmp = callbacks[j].done)) {
                        args[0] = val.d[j];
                        tmp.apply(window, args);
                    }
                }
            }
            pending = [];
        };

    return {
        run: function() {
            $(window)
                .on('popstate hashchange',
                    function() {
                        if (!processed) {
                            processed = nopush = true;
                            $H.go();
                            window.setTimeout(function() {
                                processed = undefined;
                            }, 0);
                        }
                    })
                .trigger('popstate');
        },

        stop: stop,

        go: function(href) {
            stop();

            href = getFullURI(href);

            goCallbacks = [];

            for (key in routes) {
                val = routes[key];

                i = 0;

                if (key[0] === 'e') {
                    tmp = href.replace(val.h, function() {
                        i++;
                        args = Array.prototype.slice.call((args = arguments), 0, args.length - 2);
                        return '';
                    });
                } else if (val.h === href) {
                    i = 1;
                    tmp = undefined;
                    args = [href];
                }

                if (i === 1 && !tmp) {
                    args.unshift(undefined);

                    (function(meta, curPageId) {
                        var j,
                            callbacks = meta.c,
                            callback,
                            args = meta.a,
                            getDoneCallback = function(callbackIndex) {
                                return function(data, error) {
                                    if (waitCount > 0) {
                                        if (error) {
                                            waitCount = 0;
                                            stop(error);
                                        } else {
                                            meta.d[callbackIndex] = data;
                                            if (meta === currentCallbacks[curPageId] && --waitCount === 0) {
                                                callDoneCallbacks();
                                            }
                                        }
                                    }
                                }
                            };

                        pending.push(function(error) {
                            args[0] = error;
                            for (j = 0; j < callbacks.length; j++) {
                                if ((callback = callbacks[j].stop)) {
                                    callback.apply(window, args);
                                }
                            }
                        });

                        for (j = 0; j < callbacks.length; j++) {
                            if ((callback = callbacks[j].go)) {
                                waitCount++;
                                goCallbacks.push([callback, args, getDoneCallback(j)]);
                            }
                        }
                    })((currentCallbacks[++pageId] = {c: val.c, d: [], a: args}), pageId);
                }
            }

            if (!pending.length) {
                $.error('No matches for "' + href + '"');
            }

            if (initialized) {
                if (history.pushState) {
                    if (!nopush) {
                        history.pushState(null, null, href);
                    }
                } else {
                    location.href = href;
                }
            }

            initialized = true;
            nopush = false;

            if (waitCount) {
                for (i = 0; i < goCallbacks.length; i++) {
                    tmp = goCallbacks[i];
                    args = tmp[1];
                    args[0] = tmp[2];
                    tmp[0].apply(window, args);
                }
            } else {
                callDoneCallbacks();
            }
        },

        on: function(hrefOrExpr, callbacks) {
            // callbacks should look like:
            //     {go: function(doneCallback, href, ...) {},
            //      done: function(data, href, ...) {},
            //      stop: function(error, href, ...)}
            if ((val = routes[(key = getRouteKey(hrefOrExpr))])) {
                val.c.push(callbacks);
            } else {
                routes[key] = {h: hrefOrExpr, c: [callbacks]};
            }
        },

        off: function(hrefOrExpr, callbacks) {
            if (!hrefOrExpr) {
                routes = {};
            }

            if ((val = routes[(key = getRouteKey(hrefOrExpr))])) {
                if (callbacks) {
                    val = val.c;
                    i = 0;

                    while (i < val.length) {
                        if (val[i] === callbacks) {
                            val.splice(i, 1);
                        } else {
                            i++;
                        }
                    }

                    if (val.length) {
                        return;
                    }
                }

                delete routes[key];
            }
        }
    };
})(window, location);
<commit_msg>Do not call the rest of scheduled callbacks in case of error.<commit_after>/*!
 * Histery.js v0.0.0, https://github.com/hoho/histery
 * (c) 2013 Marat Abdullin, MIT license
 */
var $H = (function(window, location, undefined) {
    var history = window.history || {},
        routes = {},
        pending = [],
        key,
        val,
        i,
        args,
        tmp,
        initialized,
        nopush,
        pageId = 0,
        waitCount,
        currentCallbacks,
        goCallbacks,
        processed,

        isExpr = function(hrefOrExpr) {
            return hrefOrExpr instanceof RegExp;
        },

        getRouteKey = function(hrefOrExpr) {
            return (isExpr(hrefOrExpr) ? 'e' : 's') + hrefOrExpr;
        },

        stop = function(error) {
            waitCount = 0;
            currentCallbacks = {};
            while ((tmp = pending.shift())) {
                tmp(error);
            }
        },

        getFullURI = function(href/**/, l) {
            l = location;
            if (href) {
                l = document.createElement('a');
                l.href = href;
            }
            return l.pathname + l.search + ((l.hash.length > 1) ? l.hash : '');
        },

        callDoneCallbacks = function(/**/callbacks, j) {
            for (key in currentCallbacks) {
                val = currentCallbacks[key];
                callbacks = val.c;
                args = val.a;

                for (j = 0; j < callbacks.length; j++) {
                    if ((tmp = callbacks[j].done)) {
                        args[0] = val.d[j];
                        tmp.apply(window, args);
                    }
                }
            }
            pending = [];
        };

    return {
        run: function() {
            $(window)
                .on('popstate hashchange',
                    function() {
                        if (!processed) {
                            processed = nopush = true;
                            $H.go();
                            window.setTimeout(function() {
                                processed = undefined;
                            }, 0);
                        }
                    })
                .trigger('popstate');
        },

        stop: stop,

        go: function(href) {
            stop();

            href = getFullURI(href);

            goCallbacks = [];

            for (key in routes) {
                val = routes[key];

                i = 0;

                if (key[0] === 'e') {
                    tmp = href.replace(val.h, function() {
                        i++;
                        args = Array.prototype.slice.call((args = arguments), 0, args.length - 2);
                        return '';
                    });
                } else if (val.h === href) {
                    i = 1;
                    tmp = undefined;
                    args = [href];
                }

                if (i === 1 && !tmp) {
                    args.unshift(undefined);

                    (function(meta, curPageId) {
                        var j,
                            callbacks = meta.c,
                            callback,
                            args = meta.a,
                            getDoneCallback = function(callbackIndex) {
                                return function(data, error) {
                                    if (waitCount > 0) {
                                        if (error) {
                                            waitCount = 0;
                                            goCallbacks = [];
                                            stop(error);
                                        } else {
                                            meta.d[callbackIndex] = data;
                                            if (meta === currentCallbacks[curPageId] && --waitCount === 0) {
                                                callDoneCallbacks();
                                            }
                                        }
                                    }
                                }
                            };

                        pending.push(function(error) {
                            args[0] = error;
                            for (j = 0; j < callbacks.length; j++) {
                                if ((callback = callbacks[j].stop)) {
                                    callback.apply(window, args);
                                }
                            }
                        });

                        for (j = 0; j < callbacks.length; j++) {
                            if ((callback = callbacks[j].go)) {
                                waitCount++;
                                goCallbacks.push([callback, args, getDoneCallback(j)]);
                            }
                        }
                    })((currentCallbacks[++pageId] = {c: val.c, d: [], a: args}), pageId);
                }
            }

            if (!pending.length) {
                $.error('No matches for "' + href + '"');
            }

            if (initialized) {
                if (history.pushState) {
                    if (!nopush) {
                        history.pushState(null, null, href);
                    }
                } else {
                    location.href = href;
                }
            }

            initialized = true;
            nopush = false;

            if (waitCount) {
                while ((tmp = goCallbacks.shift())) {
                    args = tmp[1];
                    args[0] = tmp[2];
                    tmp[0].apply(window, args);
                }
            } else {
                callDoneCallbacks();
            }
        },

        on: function(hrefOrExpr, callbacks) {
            // callbacks should look like:
            //     {go: function(doneCallback, href, ...) {},
            //      done: function(data, href, ...) {},
            //      stop: function(error, href, ...)}
            if ((val = routes[(key = getRouteKey(hrefOrExpr))])) {
                val.c.push(callbacks);
            } else {
                routes[key] = {h: hrefOrExpr, c: [callbacks]};
            }
        },

        off: function(hrefOrExpr, callbacks) {
            if (!hrefOrExpr) {
                routes = {};
            }

            if ((val = routes[(key = getRouteKey(hrefOrExpr))])) {
                if (callbacks) {
                    val = val.c;
                    i = 0;

                    while (i < val.length) {
                        if (val[i] === callbacks) {
                            val.splice(i, 1);
                        } else {
                            i++;
                        }
                    }

                    if (val.length) {
                        return;
                    }
                }

                delete routes[key];
            }
        }
    };
})(window, location);
<|endoftext|>


<commit_before>/* jslint node: true */
'use strict';

var theme				= require('./theme.js');
var clientConnections	= require('./client_connections.js').clientConnections;
var ansi				= require('./ansi_term.js');
var userDb				= require('./database.js').dbs.user;

var async				= require('async');

exports.login			= login;
exports.logoff			= logoff;

function login(callingMenu, formData, extraArgs) {
	var client = callingMenu.client;

	client.user.authenticate(formData.value.username, formData.value.password, function authenticated(err) {
		if(err) {
			client.log.info( { username : formData.value.username }, 'Failed login attempt %s', err);

			//	:TODO: if username exists, record failed login attempt to properties
			//	:TODO: check Config max failed logon attempts/etc.

			client.gotoMenuModule( { name : callingMenu.menuConfig.fallback } );
		} else {
			var now		= new Date();
			var user	= callingMenu.client.user;

			//
			//	Ensure this user is not already logged in.
			//	Loop through active connections -- which includes the current --
			//	and check for matching user ID. If the count is > 1, disallow.
			//
			var existingClientConnection;
			clientConnections.forEach(function connEntry(cc) {
				if(cc.user !== user && cc.user.userId === user.userId) {
					existingClientConnection = cc;
				}
			});

			if(existingClientConnection) {
				client.log.info( {
					existingClientId	: existingClientConnection.runtime.id,
					username			: user.username,
					userId				: user.userId },
					'Already logged in'
				);

				//	:TODO: display message/art/etc.

				client.gotoMenuModule( { name : callingMenu.menuConfig.fallback } );
				return;
			}

			//	use client.user so we can get correct case
			client.log.info( { username : user.username }, 'Successful login');

			async.parallel(
				[
					function loadThemeConfig(callback) {
						theme.loadTheme(user.properties.theme_id, function themeLoaded(err, theme) {
							client.currentTheme = theme;
							callback(null);	//	always non-fatal
						});
					},
					function recordLastLogin(callback) {
						user.persistProperty('last_login_timestamp', now.toISOString(), function persisted(err) {
							callback(err);
						});
					},
					function updateUserLoginCount(callback) {
						if(!user.properties.login_count) {
							user.properties.login_count = 1;
						} else {
							user.properties.login_count++;
						}

						user.persistProperty('login_count', user.properties.login_count, function persisted(err) {
							callback(err);
						});
					},
					function recordLoginHistory(callback) {

						userDb.serialize(function serialized() {
							userDb.run(
								'INSERT INTO user_login_history (user_id, user_name, timestamp) ' +
								'VALUES(?, ?, ?);', [ user.userId, user.username, now.toISOString() ]
							);

							//	keep 30 days of records
							userDb.run(
								'DELETE FROM user_login_history '	+
								'WHERE timestamp <= DATETIME("now", "-30 day");'
								);
						});

						callback(null);
					}
				],
				function complete(err, results) {
					if(err) {
						client.log.error(err);
						//	:TODO: drop the connection?
					}
					client.gotoMenuModule( { name : callingMenu.menuConfig.next } );
				}
			);
		}
	});
}

function logoff(callingMenu, formData, extraArgs) {
	//
	//	Simple logoff. Note that recording of @ logoff properties/stats
	//	occurs elsewhere!
	//
	var client = callingMenu.client;

	setTimeout(function timeout() {
		client.term.write(ansi.normal() + '\n+++ATH0\n');
		client.end();
	}, 500);
}<commit_msg>* Message to indicate someone already logged in by username<commit_after>/* jslint node: true */
'use strict';

var theme				= require('./theme.js');
var clientConnections	= require('./client_connections.js').clientConnections;
var ansi				= require('./ansi_term.js');
var userDb				= require('./database.js').dbs.user;

var async				= require('async');

exports.login			= login;
exports.logoff			= logoff;

function login(callingMenu, formData, extraArgs) {
	var client = callingMenu.client;

	client.user.authenticate(formData.value.username, formData.value.password, function authenticated(err) {
		if(err) {
			client.log.info( { username : formData.value.username }, 'Failed login attempt %s', err);

			//	:TODO: if username exists, record failed login attempt to properties
			//	:TODO: check Config max failed logon attempts/etc.

			client.gotoMenuModule( { name : callingMenu.menuConfig.fallback } );
		} else {
			var now		= new Date();
			var user	= callingMenu.client.user;

			//
			//	Ensure this user is not already logged in.
			//	Loop through active connections -- which includes the current --
			//	and check for matching user ID. If the count is > 1, disallow.
			//
			var existingClientConnection;
			clientConnections.forEach(function connEntry(cc) {
				if(cc.user !== user && cc.user.userId === user.userId) {
					existingClientConnection = cc;
				}
			});

			if(existingClientConnection) {
				client.log.info( {
					existingClientId	: existingClientConnection.runtime.id,
					username			: user.username,
					userId				: user.userId },
					'Already logged in'
				);

				//	:TODO: display custom message if present

				client.term.write('\nA user by that name is already logged in.\n');

				setTimeout(function timeout() {
					client.gotoMenuModule( { name : callingMenu.menuConfig.fallback } );
				}, 500);

				return;
			}

			//	use client.user so we can get correct case
			client.log.info( { username : user.username }, 'Successful login');

			async.parallel(
				[
					function loadThemeConfig(callback) {
						theme.loadTheme(user.properties.theme_id, function themeLoaded(err, theme) {
							client.currentTheme = theme;
							callback(null);	//	always non-fatal
						});
					},
					function recordLastLogin(callback) {
						user.persistProperty('last_login_timestamp', now.toISOString(), function persisted(err) {
							callback(err);
						});
					},
					function updateUserLoginCount(callback) {
						if(!user.properties.login_count) {
							user.properties.login_count = 1;
						} else {
							user.properties.login_count++;
						}

						user.persistProperty('login_count', user.properties.login_count, function persisted(err) {
							callback(err);
						});
					},
					function recordLoginHistory(callback) {

						userDb.serialize(function serialized() {
							userDb.run(
								'INSERT INTO user_login_history (user_id, user_name, timestamp) ' +
								'VALUES(?, ?, ?);', [ user.userId, user.username, now.toISOString() ]
							);

							//	keep 30 days of records
							userDb.run(
								'DELETE FROM user_login_history '	+
								'WHERE timestamp <= DATETIME("now", "-30 day");'
								);
						});

						callback(null);
					}
				],
				function complete(err, results) {
					if(err) {
						client.log.error(err);
						//	:TODO: drop the connection?
					}
					client.gotoMenuModule( { name : callingMenu.menuConfig.next } );
				}
			);
		}
	});
}

function logoff(callingMenu, formData, extraArgs) {
	//
	//	Simple logoff. Note that recording of @ logoff properties/stats
	//	occurs elsewhere!
	//
	var client = callingMenu.client;

	setTimeout(function timeout() {
		client.term.write(ansi.normal() + '\n+++ATH0\n');
		client.end();
	}, 500);
}<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var ConcatSource = require("webpack-sources").ConcatSource;

function NodeHotUpdateChunkTemplatePlugin() {}
module.exports = NodeHotUpdateChunkTemplatePlugin;

NodeHotUpdateChunkTemplatePlugin.prototype.apply = function(hotUpdateChunkTemplate) {
	hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) {
		var source = new ConcatSource();
		source.add("exports.id = " + JSON.stringify(id) + ";\nexports.modules = ");
		source.add(modulesSource);
		source.add(";");
		return source;
	});
	hotUpdateChunkTemplate.plugin("hash", function(hash) {
		hash.update("NodeHotUpdateChunkTemplatePlugin");
		hash.update("3");
		hash.update(this.outputOptions.hotUpdateFunction + "");
		hash.update(this.outputOptions.library + "");
	});
};
<commit_msg>refactor(ES6): upgrade NodeHotUpdateChunkTemplatePlugin to ES6 (#3795)<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const ConcatSource = require("webpack-sources").ConcatSource;

class NodeHotUpdateChunkTemplatePlugin {

	apply(hotUpdateChunkTemplate) {
		hotUpdateChunkTemplate.plugin("render", (modulesSource, modules, removedModules, hash, id) => {
			const source = new ConcatSource();
			source.add("exports.id = " + JSON.stringify(id) + ";\nexports.modules = ");
			source.add(modulesSource);
			source.add(";");
			return source;
		});
		hotUpdateChunkTemplate.plugin("hash", function(hash) {
			hash.update("NodeHotUpdateChunkTemplatePlugin");
			hash.update("3");
			hash.update(this.outputOptions.hotUpdateFunction + "");
			hash.update(this.outputOptions.library + "");
		});
	}
}
module.exports = NodeHotUpdateChunkTemplatePlugin;
<|endoftext|>


<commit_before>import Parchment from 'parchment';
import Block from '../blots/block';
import Container from '../blots/container';

class ListItem extends Block {
  static formats(domNode) {
    return domNode.tagName === this.tagName ? undefined : super.formats(domNode);
  }

  format(name, value) {
    if (name === List.blotName && !value) {
      this.replaceWith(Parchment.create(this.statics.scope));
    } else {
      super.format(name, value);
    }
  }

  remove() {
    if (this.prev == null && this.next == null) {
      this.parent.remove();
    } else {
      super.remove();
    }
  }

  replaceWith(name, value) {
    this.parent.isolate(this.offset(this.parent), this.length());
    if (name === this.parent.statics.blotName) {
      this.parent.replaceWith(name, value);
      return this;
    } else {
      this.parent.unwrap();
      return super.replaceWith(name, value);
    }
  }
}
ListItem.blotName = 'list-item';
ListItem.tagName = 'LI';

class List extends Container {
  static create(value) {
    let tagName = value === 'ordered' ? 'OL' : 'UL';
    let node = super.create(tagName);
    if (value === 'checked' || value === 'unchecked') {
      node.setAttribute('data-checked', value === 'checked');
    }
    return node;
  }

  static formats(domNode) {
    if (domNode.tagName === 'OL') return 'ordered';
    if (domNode.tagName === 'UL') {
      if (domNode.hasAttribute('data-checked')) {
        return domNode.getAttribute('data-checked') === 'true' ? 'checked' : 'unchecked';
      } else {
        return 'bullet';
      }
    }
    return undefined;
  }

  constructor(domNode) {
    super(domNode);
    const listEventHandler = (e) => {
      if (e.target.parentNode !== domNode) return;
      let format = this.statics.formats(domNode);
      let blot = Parchment.find(e.target);
      if (format === 'checked') {
        blot.format('list', 'unchecked');
      } else if(format === 'unchecked') {
        blot.format('list', 'checked');
      }
    }
    if ('ontouchstart' in window) {
      domNode.addEventListener('touchstart', listEventHandler);
    } else {
      domNode.addEventListener('click', listEventHandler);
    }
  }

  format(name, value) {
    if (this.children.length > 0) {
      this.children.tail.format(name, value);
    }
  }

  formats() {
    // We don't inherit from FormatBlot
    return { [this.statics.blotName]: this.statics.formats(this.domNode) };
  }

  insertBefore(blot, ref) {
    if (blot instanceof ListItem) {
      super.insertBefore(blot, ref);
    } else {
      let index = ref == null ? this.length() : ref.offset(this);
      let after = this.split(index);
      after.parent.insertBefore(blot, after);
    }
  }

  optimize(context) {
    super.optimize(context);
    let next = this.next;
    if (next != null && next.prev === this &&
        next.statics.blotName === this.statics.blotName &&
        next.domNode.tagName === this.domNode.tagName &&
        next.domNode.getAttribute('data-checked') === this.domNode.getAttribute('data-checked')) {
      next.moveChildren(this);
      next.remove();
    }
  }

  replace(target) {
    if (target.statics.blotName !== this.statics.blotName) {
      let item = Parchment.create(this.statics.defaultChild);
      target.moveChildren(item);
      this.appendChild(item);
    }
    super.replace(target);
  }
}
List.blotName = 'list';
List.scope = Parchment.Scope.BLOCK_BLOT;
List.tagName = ['OL', 'UL'];
List.defaultChild = 'list-item';
List.allowedChildren = [ListItem];

export { ListItem, List as default };
<commit_msg>using mousedown instead of click<commit_after>import Parchment from 'parchment';
import Block from '../blots/block';
import Container from '../blots/container';

class ListItem extends Block {
  static formats(domNode) {
    return domNode.tagName === this.tagName ? undefined : super.formats(domNode);
  }

  format(name, value) {
    if (name === List.blotName && !value) {
      this.replaceWith(Parchment.create(this.statics.scope));
    } else {
      super.format(name, value);
    }
  }

  remove() {
    if (this.prev == null && this.next == null) {
      this.parent.remove();
    } else {
      super.remove();
    }
  }

  replaceWith(name, value) {
    this.parent.isolate(this.offset(this.parent), this.length());
    if (name === this.parent.statics.blotName) {
      this.parent.replaceWith(name, value);
      return this;
    } else {
      this.parent.unwrap();
      return super.replaceWith(name, value);
    }
  }
}
ListItem.blotName = 'list-item';
ListItem.tagName = 'LI';

class List extends Container {
  static create(value) {
    let tagName = value === 'ordered' ? 'OL' : 'UL';
    let node = super.create(tagName);
    if (value === 'checked' || value === 'unchecked') {
      node.setAttribute('data-checked', value === 'checked');
    }
    return node;
  }

  static formats(domNode) {
    if (domNode.tagName === 'OL') return 'ordered';
    if (domNode.tagName === 'UL') {
      if (domNode.hasAttribute('data-checked')) {
        return domNode.getAttribute('data-checked') === 'true' ? 'checked' : 'unchecked';
      } else {
        return 'bullet';
      }
    }
    return undefined;
  }

  constructor(domNode) {
    super(domNode);
    const listEventHandler = (e) => {
      if (e.target.parentNode !== domNode) return;
      let format = this.statics.formats(domNode);
      let blot = Parchment.find(e.target);
      if (format === 'checked') {
        blot.format('list', 'unchecked');
      } else if(format === 'unchecked') {
        blot.format('list', 'checked');
      }
    }

    domNode.addEventListener('touchstart', listEventHandler);
    domNode.addEventListener('mousedown', listEventHandler);
  }

  format(name, value) {
    if (this.children.length > 0) {
      this.children.tail.format(name, value);
    }
  }

  formats() {
    // We don't inherit from FormatBlot
    return { [this.statics.blotName]: this.statics.formats(this.domNode) };
  }

  insertBefore(blot, ref) {
    if (blot instanceof ListItem) {
      super.insertBefore(blot, ref);
    } else {
      let index = ref == null ? this.length() : ref.offset(this);
      let after = this.split(index);
      after.parent.insertBefore(blot, after);
    }
  }

  optimize(context) {
    super.optimize(context);
    let next = this.next;
    if (next != null && next.prev === this &&
        next.statics.blotName === this.statics.blotName &&
        next.domNode.tagName === this.domNode.tagName &&
        next.domNode.getAttribute('data-checked') === this.domNode.getAttribute('data-checked')) {
      next.moveChildren(this);
      next.remove();
    }
  }

  replace(target) {
    if (target.statics.blotName !== this.statics.blotName) {
      let item = Parchment.create(this.statics.defaultChild);
      target.moveChildren(item);
      this.appendChild(item);
    }
    super.replace(target);
  }
}
List.blotName = 'list';
List.scope = Parchment.Scope.BLOCK_BLOT;
List.tagName = ['OL', 'UL'];
List.defaultChild = 'list-item';
List.allowedChildren = [ListItem];

export { ListItem, List as default };
<|endoftext|>


<commit_before>/*
unFocus.FlashPlayerInfo, version 1.1 b6 (beta) (2007/09/11)
Copyright: 2005-2007, Kevin Newman (http://www.unfocus.com/Projects/)

This file is part of unFocus.History Keeper.

unFocus.History Keeper is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

unFocus.History Keeper is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
if (!window.unFocus) var unFocus = {};

unFocus.FlashPlayerInfo = (function() {
	// private vars
	var _installed = false,
		_beta = false,
		_version = 0,
		_majorRevision = 0,
		_minorRevision = 0,
		_betaVersion = 0,
		_versionRaw = "",
		_playerType = "",
		_releaseCode = "";

	// detection work
	if (navigator.plugins && navigator.plugins.length > 0) {
		_versionRaw = navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"];
		if (_versionRaw) {
			_versionRaw = _versionRaw.description;
			_installed = true;
			_playerType = "PlugIn";
			if (/Shockwave Flash/.test(_versionRaw)) {
				_version = _versionRaw.match(/Shockwave Flash (\d)\.(\d)/);
				_majorRevision = _version[2];
				if (/r\d+/.test(_versionRaw)) {
					_releaseCode = "r";
					_minorRevision = _versionRaw.match(/r(\d+)/)[1];
				}
				_version = _version[1];
				if (/[abd]\d+/.test(_versionRaw)) { // I'm not sure what other letters would be here, but I've encountered b, d and a (alpha) so far
					_betaVersion = _versionRaw.match(/([abd])(\d+)/);
					_releaseCode = _betaVersion[1];
					_beta = true;
					_betaVersion = _betaVersion[2];
				}
			} else _version = 1;
		}
	} else if (window.ActiveXObject) {
		// src: Player.vbs
		var _ax;
		function _getActiveXObject($objectString) {
			try {
				_ax = new ActiveXObject($objectString);
				return true;
			} catch (e){
				return false;
			}
		}
		var _versionTemp;

		function _parseVersion() {
			var _versionTemp = _ax.GetVariable("$version");
			_versionRaw = _versionTemp;
			_versionTemp = _versionTemp.split(",");
			_version = _versionTemp[0].match(/\d+/);
			_majorRevision = _versionTemp[1];
			_minorRevision = _versionTemp[2];
			_betaVersion = _versionTemp[3];
			if (_versionTemp[3]>0) _beta = true;
			// if the last number is 0, assume this is a release version
			else _releaseCode = "r";
		}

		// we have to detect around Flash 6, since it can crash some versions of IE
		if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.7"))
			_parseVersion();
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.6")) {
			// tread lightly
			try {
				// will throw error if < 6.0.47 (info glombed from Adobe's Detection Kit - thanks!)
				_ax.AllowScriptAccess = "always";
				// now safe to call GetVariable
				_parseVersion();
			} catch (e) {
				_version = 6;
				_minorRevision = 0; // cannot be safely detected
			}
		} else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.5"))
			_parseVersion();
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.4"))
			_version = 4;
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.3"))
			_version = 3;
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash"))
			// Tested on Windows 95 with flash player 2 - using the ".2" at the end doesn't work, but this does ;-)
			// :BUG: This doesn't seem to work when FP2 is installed in WinXP
			_version = 2;
		if (_version) {
			_installed = true;
			_playerType = "ActiveX";
		}
	} else if (/WebTV/.test(navigator.userAgent)) { // WebTV
		_playerType = "WebTV";
		_versionRaw = navigator.userAgent.match(/WebTV\/(\d\.\d)/)[1];
		if (_versionRaw > 2.5) _version = 4;
		else if (_versionRaw == 2.5) _version = 3;
		else _version = 2;
	}

	// public/priveleged Getters
	var FlashPlayerInfo = {
		isInstalled: function() {
			return _installed;
		},
		isBeta: function() {
			return _beta;
		},
		getVersion: function() {
			return _version;
		},
		getMajorRevision: function() {
			return _majorRevision;
		},
		getMinorRevision: function() {
			return _minorRevision;
		},
		getBetaVersion: function() {
			return _betaVersion;
		},
		getVersionRaw: function() {
			return _versionRaw;
		},
		// for backward compat - deprecated, will be removed in next version
		getPluginType: function() {
			return this.getPlayerType();
		},
		getPlayerType: function() {
			return _playerType;
		},
		getReleaseCode: function() {
			return _releaseCode;
		}
	};
	return FlashPlayerInfo;
})();
<commit_msg>Fixed Flash Player 10 PlugIn detection.<commit_after>/*
unFocus.FlashPlayerInfo, version 1.1 b7 (beta) (2008/05/20)
Copyright: 2005-2008, Kevin Newman (http://www.unfocus.com/Projects/)

This file is part of unFocus.History Keeper.

unFocus.History Keeper is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

unFocus.History Keeper is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
if (!window.unFocus) var unFocus = {};

unFocus.FlashPlayerInfo = (function() {
	// private vars
	var _installed = false,
		_beta = false,
		_version = 0,
		_majorRevision = 0,
		_minorRevision = 0,
		_betaVersion = 0,
		_versionRaw = "",
		_playerType = "",
		_releaseCode = "";

	// detection work
	if (navigator.plugins && navigator.plugins.length > 0) {
		_versionRaw = navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"];
		if (_versionRaw) {
			_versionRaw = _versionRaw.description;
			_installed = true;
			_playerType = "PlugIn";
			if (/Shockwave Flash/.test(_versionRaw)) {
				_version = _versionRaw.match(/Shockwave Flash (\d+)\.(\d+)/);
				_majorRevision = _version[2];
				if (/r\d+/.test(_versionRaw)) {
					_releaseCode = "r";
					_minorRevision = _versionRaw.match(/r(\d+)/)[1];
				}
				_version = _version[1];
				if (/[abd]\d+/.test(_versionRaw)) { // I'm not sure what other letters would be here, but I've encountered b, d and a (alpha) so far
					_betaVersion = _versionRaw.match(/([abd])(\d+)/);
					_releaseCode = _betaVersion[1];
					_beta = true;
					_betaVersion = _betaVersion[2];
				}
			} else _version = 1;
		}
	} else if (window.ActiveXObject) {
		// src: Player.vbs
		var _ax;
		function _getActiveXObject($objectString) {
			try {
				_ax = new ActiveXObject($objectString);
				return true;
			} catch (e){
				return false;
			}
		}
		var _versionTemp;

		function _parseVersion() {
			var _versionTemp = _ax.GetVariable("$version");
			_versionRaw = _versionTemp;
			_versionTemp = _versionTemp.split(",");
			_version = _versionTemp[0].match(/\d+/);
			_majorRevision = _versionTemp[1];
			_minorRevision = _versionTemp[2];
			_betaVersion = _versionTemp[3];
			if (_versionTemp[3]>0) _beta = true;
			// if the last number is 0, assume this is a release version
			else _releaseCode = "r";
		}

		// we have to detect around Flash 6, since it can crash some versions of IE
		if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.7"))
			_parseVersion();
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.6")) {
			// tread lightly
			try {
				// will throw error if < 6.0.47 (info glombed from Adobe's Detection Kit - thanks!)
				_ax.AllowScriptAccess = "always";
				// now safe to call GetVariable
				_parseVersion();
			} catch (e) {
				_version = 6;
				_minorRevision = 0; // cannot be safely detected
			}
		} else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.5"))
			_parseVersion();
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.4"))
			_version = 4;
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash.3"))
			_version = 3;
		else if (_getActiveXObject("ShockwaveFlash.ShockwaveFlash"))
			// Tested on Windows 95 with flash player 2 - using the ".2" at the end doesn't work, but this does ;-)
			// :BUG: This doesn't seem to work when FP2 is installed in WinXP
			_version = 2;
		if (_version) {
			_installed = true;
			_playerType = "ActiveX";
		}
	} else if (/WebTV/.test(navigator.userAgent)) { // WebTV
		_playerType = "WebTV";
		_versionRaw = navigator.userAgent.match(/WebTV\/(\d\.\d)/)[1];
		if (_versionRaw > 2.5) _version = 4;
		else if (_versionRaw == 2.5) _version = 3;
		else _version = 2;
	}

	// public/priveleged Getters
	var FlashPlayerInfo = {
		isInstalled: function() {
			return _installed;
		},
		isBeta: function() {
			return _beta;
		},
		getVersion: function() {
			return _version;
		},
		getMajorRevision: function() {
			return _majorRevision;
		},
		getMinorRevision: function() {
			return _minorRevision;
		},
		getBetaVersion: function() {
			return _betaVersion;
		},
		getVersionRaw: function() {
			return _versionRaw;
		},
		// for backward compat - deprecated, will be removed in next version
		getPluginType: function() {
			return this.getPlayerType();
		},
		getPlayerType: function() {
			return _playerType;
		},
		getReleaseCode: function() {
			return _releaseCode;
		}
	};
	return FlashPlayerInfo;
})();
<|endoftext|>


<commit_before>'use strict';
var $ = require('jquery');
//this is a mapping from the class names (generic ones, for compatability with codemirror themes), to what they -actually- represent
var tokenTypes = {
	"string-2": "prefixed",
	"atom": "var"
};

module.exports = function(yasqe, completerName) {
	//this autocompleter also fires on-change!
	yasqe.on("change", function() {
		module.exports.appendPrefixIfNeeded(yasqe, completerName);
	});

	return {
		isValidCompletionPosition: function() {
			return module.exports.isValidCompletionPosition(yasqe);
		},
		get: function(token, callback) {
			$.get("http://prefix.cc/popular/all.file.json", function(data) {
				var prefixArray = [];
				for (var prefix in data) {
					if (prefix == "bif")
						continue; // skip this one! see #231
					var completeString = prefix + ": <" + data[prefix] + ">";
					prefixArray.push(completeString); // the array we want to store in localstorage
				}

				prefixArray.sort();
				callback(prefixArray);
			});
		},
		preProcessToken: function(token) {
			return module.exports.preprocessPrefixTokenForCompletion(yasqe, token)
		},
		async: true,
		bulk: true,
		autoShow: true,
		persistent: completerName,
		callbacks: {
			pick: function() {
				yasqe.collapsePrefixes(false);
			}
		}
	};
};
module.exports.isValidCompletionPosition = function(yasqe) {
	var cur = yasqe.getCursor(),
		token = yasqe.getTokenAt(cur);

	// not at end of line
	if (yasqe.getLine(cur.line).length > cur.ch)
		return false;

	if (token.type != "ws") {
		// we want to complete token, e.g. when the prefix starts with an a
		// (treated as a token in itself..)
		// but we to avoid including the PREFIX tag. So when we have just
		// typed a space after the prefix tag, don't get the complete token
		token = yasqe.getCompleteToken();
	}

	// we shouldnt be at the uri part the prefix declaration
	// also check whether current token isnt 'a' (that makes codemirror
	// thing a namespace is a possiblecurrent
	if (!token.string.indexOf("a") == 0 && $.inArray("PNAME_NS", token.state.possibleCurrent) == -1)
		return false;

	// First token of line needs to be PREFIX,
	// there should be no trailing text (otherwise, text is wrongly inserted
	// in between)
	var previousToken = yasqe.getPreviousNonWsToken(cur.line, token);
	if (!previousToken || previousToken.string.toUpperCase() != "PREFIX") return false;
	return true;
};
module.exports.preprocessPrefixTokenForCompletion = function(yasqe, token) {
	var previousToken = yasqe.getPreviousNonWsToken(yasqe.getCursor().line, token);
	if (previousToken && previousToken.string && previousToken.string.slice(-1) == ":") {
		//combine both tokens! In this case we have the cursor at the end of line "PREFIX bla: <".
		//we want the token to be "bla: <", en not "<"
		token = {
			start: previousToken.start,
			end: token.end,
			string: previousToken.string + " " + token.string,
			state: token.state
		};
	}
	return token;
};
/**
 * Check whether typed prefix is declared. If not, automatically add declaration
 * using list from prefix.cc
 *
 * @param yasqe
 */
module.exports.appendPrefixIfNeeded = function(yasqe, completerName) {
	if (!yasqe.autocompleters.getTrie(completerName))
		return; // no prefixed defined. just stop
	if (!yasqe.options.autocompleters || yasqe.options.autocompleters.indexOf(completerName) == -1) return; //this autocompleter is disabled
	var cur = yasqe.getCursor();

	var token = yasqe.getTokenAt(cur);
	if (tokenTypes[token.type] == "prefixed") {
		var colonIndex = token.string.indexOf(":");
		if (colonIndex !== -1) {
			// check previous token isnt PREFIX, or a '<'(which would mean we are in a uri)
			//			var firstTokenString = yasqe.getNextNonWsToken(cur.line).string.toUpperCase();
			var lastNonWsTokenString = yasqe.getPreviousNonWsToken(cur.line, token).string.toUpperCase();
			var previousToken = yasqe.getTokenAt({
				line: cur.line,
				ch: token.start
			}); // needs to be null (beginning of line), or whitespace
			if (lastNonWsTokenString != "PREFIX" && (previousToken.type == "ws" || previousToken.type == null)) {
				// check whether it isnt defined already (saves us from looping
				// through the array)
				var currentPrefix = token.string.substring(0, colonIndex + 1);
				var queryPrefixes = yasqe.getPrefixesFromQuery();
				if (queryPrefixes[currentPrefix.slice(0, -1)] == null) {
					// ok, so it isnt added yet!
					var completions = yasqe.autocompleters.getTrie(completerName).autoComplete(currentPrefix);
					if (completions.length > 0) {
						yasqe.addPrefixes(completions[0]);
					}
				}
			}
		}
	}
};<commit_msg>Use protocol relative URL to retrieve prefixes<commit_after>'use strict';
var $ = require('jquery');
//this is a mapping from the class names (generic ones, for compatability with codemirror themes), to what they -actually- represent
var tokenTypes = {
	"string-2": "prefixed",
	"atom": "var"
};

module.exports = function(yasqe, completerName) {
	//this autocompleter also fires on-change!
	yasqe.on("change", function() {
		module.exports.appendPrefixIfNeeded(yasqe, completerName);
	});

	return {
		isValidCompletionPosition: function() {
			return module.exports.isValidCompletionPosition(yasqe);
		},
		get: function(token, callback) {
			$.get("//prefix.cc/popular/all.file.json", function(data) {
				var prefixArray = [];
				for (var prefix in data) {
					if (prefix == "bif")
						continue; // skip this one! see #231
					var completeString = prefix + ": <" + data[prefix] + ">";
					prefixArray.push(completeString); // the array we want to store in localstorage
				}

				prefixArray.sort();
				callback(prefixArray);
			});
		},
		preProcessToken: function(token) {
			return module.exports.preprocessPrefixTokenForCompletion(yasqe, token)
		},
		async: true,
		bulk: true,
		autoShow: true,
		persistent: completerName,
		callbacks: {
			pick: function() {
				yasqe.collapsePrefixes(false);
			}
		}
	};
};
module.exports.isValidCompletionPosition = function(yasqe) {
	var cur = yasqe.getCursor(),
		token = yasqe.getTokenAt(cur);

	// not at end of line
	if (yasqe.getLine(cur.line).length > cur.ch)
		return false;

	if (token.type != "ws") {
		// we want to complete token, e.g. when the prefix starts with an a
		// (treated as a token in itself..)
		// but we to avoid including the PREFIX tag. So when we have just
		// typed a space after the prefix tag, don't get the complete token
		token = yasqe.getCompleteToken();
	}

	// we shouldnt be at the uri part the prefix declaration
	// also check whether current token isnt 'a' (that makes codemirror
	// thing a namespace is a possiblecurrent
	if (!token.string.indexOf("a") == 0 && $.inArray("PNAME_NS", token.state.possibleCurrent) == -1)
		return false;

	// First token of line needs to be PREFIX,
	// there should be no trailing text (otherwise, text is wrongly inserted
	// in between)
	var previousToken = yasqe.getPreviousNonWsToken(cur.line, token);
	if (!previousToken || previousToken.string.toUpperCase() != "PREFIX") return false;
	return true;
};
module.exports.preprocessPrefixTokenForCompletion = function(yasqe, token) {
	var previousToken = yasqe.getPreviousNonWsToken(yasqe.getCursor().line, token);
	if (previousToken && previousToken.string && previousToken.string.slice(-1) == ":") {
		//combine both tokens! In this case we have the cursor at the end of line "PREFIX bla: <".
		//we want the token to be "bla: <", en not "<"
		token = {
			start: previousToken.start,
			end: token.end,
			string: previousToken.string + " " + token.string,
			state: token.state
		};
	}
	return token;
};
/**
 * Check whether typed prefix is declared. If not, automatically add declaration
 * using list from prefix.cc
 *
 * @param yasqe
 */
module.exports.appendPrefixIfNeeded = function(yasqe, completerName) {
	if (!yasqe.autocompleters.getTrie(completerName))
		return; // no prefixed defined. just stop
	if (!yasqe.options.autocompleters || yasqe.options.autocompleters.indexOf(completerName) == -1) return; //this autocompleter is disabled
	var cur = yasqe.getCursor();

	var token = yasqe.getTokenAt(cur);
	if (tokenTypes[token.type] == "prefixed") {
		var colonIndex = token.string.indexOf(":");
		if (colonIndex !== -1) {
			// check previous token isnt PREFIX, or a '<'(which would mean we are in a uri)
			//			var firstTokenString = yasqe.getNextNonWsToken(cur.line).string.toUpperCase();
			var lastNonWsTokenString = yasqe.getPreviousNonWsToken(cur.line, token).string.toUpperCase();
			var previousToken = yasqe.getTokenAt({
				line: cur.line,
				ch: token.start
			}); // needs to be null (beginning of line), or whitespace
			if (lastNonWsTokenString != "PREFIX" && (previousToken.type == "ws" || previousToken.type == null)) {
				// check whether it isnt defined already (saves us from looping
				// through the array)
				var currentPrefix = token.string.substring(0, colonIndex + 1);
				var queryPrefixes = yasqe.getPrefixesFromQuery();
				if (queryPrefixes[currentPrefix.slice(0, -1)] == null) {
					// ok, so it isnt added yet!
					var completions = yasqe.autocompleters.getTrie(completerName).autoComplete(currentPrefix);
					if (completions.length > 0) {
						yasqe.addPrefixes(completions[0]);
					}
				}
			}
		}
	}
};
<|endoftext|>


<commit_before>describe('validations directive', function ()
{
    'use strict';

    var scope,
        $timeout,
        $rootScope,
        $compile;

    beforeEach(module('ngFabForm'));

    beforeEach(inject(function (_$rootScope_, _$compile_, _$timeout_)
    {
        $rootScope = _$rootScope_;
        $compile = _$compile_;
        $timeout = _$timeout_;

        scope = $rootScope.$new();
    }));

    describe('simple required input', function ()
    {
        // TODO run all tests for all kind of input elements

        var element,
            form,
            input,
            messageContainer;

        beforeEach(function ()
        {
            var html = '<form name="testForm" ng-fab-form-options="customFormOptions">' +
                '<input type="text" ng-model="testInput" required>' +
                '</form>';
            element = $compile(html)(scope);
            scope.$digest();
            // as timeout is used, we need to flush it here
            $timeout.flush();
            form = scope.testForm;
            input = angular.element(element.children()[0]);
            messageContainer = angular.element(element.children()[1]);
        });

        it('should set a name according to model', function ()
        {
            expect(input.attr('name')).toBe('testInput');
        });

        it('should have a validation template appended', function ()
        {
            expect(messageContainer.length > 0).toBeTruthy();
        });

        it('display a validation message if invalid and no success message', function ()
        {
            // we have to use $setViewValue otherwise the formCtrl
            // will not update properly
            form.testInput.$setViewValue(null);

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });

        it('display success if valid and no error messages', function ()
        {
            form.testInput.$setViewValue('bla bla bla');

            var successMessage = messageContainer.find('div');
            expect(successMessage.length).toBe(1);
            expect(successMessage.hasClass('ng-hide')).toBe(false);

            var message = messageContainer.find('li');
            expect(message.length).toBe(0);
        });

        it('display messages according to option', function ()
        {
            scope.customFormOptions = {
                validationsTemplate: false
            };
            scope.$digest();
            form.testInput.$setViewValue(null);
            messageContainer = angular.element(element.children()[1]);
            expect(messageContainer).toEqual({});

            scope.customFormOptions.validationsTemplate = 'default-validation-msgs.html';
            form.testInput.$setViewValue(null);
            scope.$digest();
            messageContainer = angular.element(element.children()[1]);
            expect(messageContainer).not.toEqual({});

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });
    });

    it('should display a custom validation if set', function ()
    {
        var element = $compile('<form name="testForm">' +
        '<input type="text" ng-model="testInput" validation-msg-required ="some custom message" required>' +
        '</form>')(scope);
        scope.$digest();
        $timeout.flush();
        var form = scope.testForm;

        // we have to use $setViewValue otherwise the formCtrl
        // will not update properly
        form.testInput.$setViewValue(null);

        var messageContainer = angular.element(element.children()[1]);
        var message = messageContainer.find('li');

        expect(message.length).toBe(1);
        expect(message.attr('ng-message')).toBe('required');
        expect(message.text()).toBe('some custom message');
    });

    it('should work with nested model values', function ()
    {
        var element = $compile('<form name="testForm">' +
        '<input type="text" ng-model="testInput.deeper.andDeeper.andDeeper" required>' +
        '</form>')(scope);
        scope.$digest();
        $timeout.flush();

        var form = scope.testForm;
        var messageContainer = angular.element(element.children()[1]);

        form['testInput.deeper.andDeeper.andDeeper'].$setViewValue('test aa');

        var successMessage = messageContainer.find('div');
        expect(successMessage.length).toBe(1);
        expect(successMessage.hasClass('ng-hide')).toBe(false);

        var message = messageContainer.find('li');
        expect(message.length).toBe(0);
    });
});
<commit_msg>basic testing for non inputs<commit_after>describe('validations directive', function ()
{
    'use strict';

    var scope,
        $timeout,
        $rootScope,
        $compile;

    beforeEach(module('ngFabForm'));

    beforeEach(inject(function (_$rootScope_, _$compile_, _$timeout_)
    {
        $rootScope = _$rootScope_;
        $compile = _$compile_;
        $timeout = _$timeout_;

        scope = $rootScope.$new();
    }));

    describe('simple required input', function ()
    {
        // TODO run all tests for all kind of input elements

        var element,
            form,
            input,
            messageContainer;

        beforeEach(function ()
        {
            var html = '<form name="testForm" ng-fab-form-options="customFormOptions">' +
                '<input type="text" ng-model="testInput" required>' +
                '</form>';
            element = $compile(html)(scope);
            scope.$digest();
            // as timeout is used, we need to flush it here
            $timeout.flush();
            form = scope.testForm;
            input = angular.element(element.children()[0]);
            messageContainer = angular.element(element.children()[1]);
        });

        it('should set a name according to model', function ()
        {
            expect(input.attr('name')).toBe('testInput');
        });

        it('should have a validation template appended', function ()
        {
            expect(messageContainer.length > 0).toBeTruthy();
        });

        it('display a validation message if invalid and no success message', function ()
        {
            // we have to use $setViewValue otherwise the formCtrl
            // will not update properly
            form.testInput.$setViewValue(null);

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });

        it('display success if valid and no error messages', function ()
        {
            form.testInput.$setViewValue('bla bla bla');

            var successMessage = messageContainer.find('div');
            expect(successMessage.length).toBe(1);
            expect(successMessage.hasClass('ng-hide')).toBe(false);

            var message = messageContainer.find('li');
            expect(message.length).toBe(0);
        });

        it('display messages according to option', function ()
        {
            scope.customFormOptions = {
                validationsTemplate: false
            };
            scope.$digest();
            form.testInput.$setViewValue(null);
            messageContainer = angular.element(element.children()[1]);
            expect(messageContainer).toEqual({});

            scope.customFormOptions.validationsTemplate = 'default-validation-msgs.html';
            form.testInput.$setViewValue(null);
            scope.$digest();
            messageContainer = angular.element(element.children()[1]);
            expect(messageContainer).not.toEqual({});

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });
    });

    it('should display a custom validation if set', function ()
    {
        var element = $compile('<form name="testForm">' +
        '<input type="text" ng-model="testInput" validation-msg-required ="some custom message" required>' +
        '</form>')(scope);
        scope.$digest();
        $timeout.flush();
        var form = scope.testForm;

        // we have to use $setViewValue otherwise the formCtrl
        // will not update properly
        form.testInput.$setViewValue(null);

        var messageContainer = angular.element(element.children()[1]);
        var message = messageContainer.find('li');

        expect(message.length).toBe(1);
        expect(message.attr('ng-message')).toBe('required');
        expect(message.text()).toBe('some custom message');
    });

    it('should work with nested model values', function ()
    {
        var element = $compile('<form name="testForm">' +
        '<input type="text" ng-model="testInput.deeper.andDeeper.andDeeper" required>' +
        '</form>')(scope);
        scope.$digest();
        $timeout.flush();

        var form = scope.testForm;
        var messageContainer = angular.element(element.children()[1]);

        form['testInput.deeper.andDeeper.andDeeper'].$setViewValue('test aa');

        var successMessage = messageContainer.find('div');
        expect(successMessage.length).toBe(1);
        expect(successMessage.hasClass('ng-hide')).toBe(false);

        var message = messageContainer.find('li');
        expect(message.length).toBe(0);
    });

    describe('non inputs and checkboxes', function ()
    {
        it('textarea -display a validation message if invalid and no success message', function ()
        {
            var html = '<form name="testForm" ng-fab-form-options="customFormOptions">' +
                '<textarea ng-model="testInput" required></textarea>' +
                '</form>';
            var element = $compile(html)(scope);
            scope.$digest();
            // as timeout is used, we need to flush it here
            $timeout.flush();
            var form = scope.testForm;
            var messageContainer = angular.element(element.children()[1]);

            // we have to use $setViewValue otherwise the formCtrl
            // will not update properly
            form.testInput.$setViewValue(null);

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });

        it('textarea -display a validation message if invalid and no success message', function ()
        {
            var html = '<form name="testForm" ng-fab-form-options="customFormOptions">' +
                '<select ng-model="testInput" required><option value=""></option></select>' +
                '</form>';
            var element = $compile(html)(scope);
            scope.$digest();
            // as timeout is used, we need to flush it here
            $timeout.flush();
            var form = scope.testForm;
            var messageContainer = angular.element(element.children()[1]);

            // we have to use $setViewValue otherwise the formCtrl
            // will not update properly
            form.testInput.$setViewValue(null);

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });

        it('input:checkbox -display a validation message if invalid and no success message', function ()
        {
            var html = '<form name="testForm" ng-fab-form-options="customFormOptions">' +
                '<label>' +
                '<input type="checkbox" ng-model="testInput" required>' +
                '</label>' +
                '</form>';
            var element = $compile(html)(scope);
            scope.$digest();
            // as timeout is used, we need to flush it here
            $timeout.flush();
            var form = scope.testForm;
            var messageContainer = angular.element(element.children()[1]);

            // we have to use $setViewValue otherwise the formCtrl
            // will not update properly
            form.testInput.$setViewValue(false);

            var message = messageContainer.find('li');
            expect(message.length).toBe(1);
            expect(message.attr('ng-message')).toBe('required');
            expect(message.text()).toBe('This field is required');

            var successMessage = messageContainer.find('div');
            expect(successMessage.hasClass('ng-hide')).toBe(true);
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

var querystring = require('querystring');
var prequest = require('prequest');
var utils = require('./utils');
var clc = require('cli-color');
var logger = require('tracer').colorConsole({
  format: '{{timestamp}} <{{title}}> ({{path}}:{{line}}:{{pos}}:{{method}}) {{message}}',
  dateformat: 'mmm dd HH:MM:ss',
  preprocess:  function(data) {
    data.path = data.path.replace(process.cwd(), '');
  }
});

module.exports = function (config) {
  var blacklistGroups = config.meetupParams.blacklistGroups || [];

  function constructAddress(venue) {
    var address = '';

    if (venue) {
      address = [
        venue.name,
        ', ',
        venue.address_1 || '',
        (venue.address_2 ? ', ' + venue.address_2 : '')
      ].join('');
      address += address.indexOf(config.meetupParams.city) === -1 ? ', ' + config.meetupParams.city : '';
    } else {
      address = config.meetupParams.city;
    }

    return address;
  }

  function hasWord(phrase, word) {
    phrase && phrase.toLowerCase().includes(word) ? true : false;
  }

  function hasValidAddress(event) {
    var matchWords = [ 'tbd', 'to be decided' ];
    var countMatch = 0;

    [ event.venue.name,  event.venue.address_1, event.venue.address_2 ].forEach(function(eachAddressPhrase) {
      matchWords.forEach(function(eachMatchWord) {
        if (eachAddressPhrase && eachAddressPhrase.toLowerCase().includes(eachMatchWord)) {
          console.log('Remove event ' + event.name + ' for venue with TBD.')
          countMatch++;
        }
      })
    })

    return countMatch > 0 ? false : true;
  }

  function isValidGroup(row) {
    // console.log(row.category.id, row.country, row.id, row.name)
    var isValidCountry = row.country === (config.meetupParams.country || row.country)
    var isValidGroupId = !blacklistGroups.some(function(id) { return row.id === id });

    return isValidCountry && isValidGroupId;
  }

  function isFree(event) {
    return !event.fee;
  }

  function normalizeGroupEvents(events, row) {
    var eventTime;
    var event = {};

    if (!isFree(row)) {
      return events;
    }

    if (!row.hasOwnProperty('venue') || row.venue_visibility === 'members') {
      return events;
    }

    if (!hasValidAddress(row)) {
      return events;
    }

    if (row.duration === undefined) {
      row.duration = 7200000
    }

    eventTime = utils.localTime(row.time, config.timezone);

    event = {
      id: row.id,
      name: row.name,
      description: utils.htmlStrip(row.description),
      location: constructAddress(row.venue),
      rsvp_count: row.yes_rsvp_count,
      url: row.event_url,
      group_id: row.group.id,
      group_name: row.group.name,
      group_url: 'http://meetup.com/' + row.group.urlname,
      formatted_time: utils.formatLocalTime(row.time, config.timezone, config.displayTimeformat),
      start_time: eventTime.toISOString(),
      end_time: eventTime.add(row.duration, 'milliseconds').toISOString()
    }

    if (row.venue.lat !== 0 && row.venue.lon !== 0) {
      event.latitude = row.venue.lat;
      event.longitude = row.venue.lon
    }

    events.push(event);
    return events;
  }

  // getEventsByGroupIds returns an array of events
  // for the provided groups.
  function getEventsByGroupIds(groupIds) {
    var url = 'https://api.meetup.com/2/events/?' +
    querystring.stringify({
      key: config.meetupParams.key,
      group_id: groupIds.join(',')
    });

    return prequest(url).then(function(data) {
      var events = [];
      data.results.reduce(normalizeGroupEvents, events);
      logger.info('Info: Found ' + events.length + ' meetup.com group events with venues');
      return events;
    }).catch(function(err) {
      logger.error('Error: getEventsByGroupIds():');
      logger.error(err);
    });
  }

  // getGroupIds returns an array of group IDs
  // matching the given criteria.
  function getGroupIds(offset) {
    config.meetupParams.offset = offset
    var url = 'https://api.meetup.com/2/groups?' + querystring.stringify(config.meetupParams);

    return prequest(url).then(function(data) {
      logger.info(`Found ${data.results.length} meetup.com groups with offset=${offset}`);

      return data.results
        .filter(isValidGroup)
        .reduce(function(groupIds, row) {
          groupIds.push(row.id);
          return groupIds;
        }, []);
    }).catch(function(err) {
      logger.error(err);
    });
  }

  return {
    'get': function () {
      return getGroupIds(0).then(function(groupIdsOffset0) {
        return getGroupIds(1).then(function(groupsIdsOffset1) {
          return getEventsByGroupIds(groupIdsOffset0.concat(groupsIdsOffset1))
        }).catch(function(err) {
          logger.error(err)
        })
      }).catch(function(err) {
        logger.error(err)
      })
    }
  }
}
<commit_msg>fix: error of querying more than 200 group ids<commit_after>'use strict';

var querystring = require('querystring');
var prequest = require('prequest');
var utils = require('./utils');
var clc = require('cli-color');
var logger = require('tracer').colorConsole({
  format: '{{timestamp}} <{{title}}> ({{path}}:{{line}}:{{pos}}:{{method}}) {{message}}',
  dateformat: 'mmm dd HH:MM:ss',
  preprocess:  function(data) {
    data.path = data.path.replace(process.cwd(), '');
  }
});

module.exports = function (config) {
  var blacklistGroups = config.meetupParams.blacklistGroups || [];

  function constructAddress(venue) {
    var address = '';

    if (venue) {
      address = [
        venue.name,
        ', ',
        venue.address_1 || '',
        (venue.address_2 ? ', ' + venue.address_2 : '')
      ].join('');
      address += address.indexOf(config.meetupParams.city) === -1 ? ', ' + config.meetupParams.city : '';
    } else {
      address = config.meetupParams.city;
    }

    return address;
  }

  function hasWord(phrase, word) {
    phrase && phrase.toLowerCase().includes(word) ? true : false;
  }

  function hasValidAddress(event) {
    var matchWords = [ 'tbd', 'to be decided' ];
    var countMatch = 0;

    [ event.venue.name,  event.venue.address_1, event.venue.address_2 ].forEach(function(eachAddressPhrase) {
      matchWords.forEach(function(eachMatchWord) {
        if (eachAddressPhrase && eachAddressPhrase.toLowerCase().includes(eachMatchWord)) {
          console.log('Remove event ' + event.name + ' for venue with TBD.')
          countMatch++;
        }
      })
    })

    return countMatch > 0 ? false : true;
  }

  function isValidGroup(row) {
    // console.log(row.category.id, row.country, row.id, row.name)
    var isValidCountry = row.country === (config.meetupParams.country || row.country)
    var isValidGroupId = !blacklistGroups.some(function(id) { return row.id === id });

    return isValidCountry && isValidGroupId;
  }

  function isFree(event) {
    return !event.fee;
  }

  function normalizeGroupEvents(events, row) {
    var eventTime;
    var event = {};

    if (!isFree(row)) {
      return events;
    }

    if (!row.hasOwnProperty('venue') || row.venue_visibility === 'members') {
      return events;
    }

    if (!hasValidAddress(row)) {
      return events;
    }

    if (row.duration === undefined) {
      row.duration = 7200000
    }

    eventTime = utils.localTime(row.time, config.timezone);

    event = {
      id: row.id,
      name: row.name,
      description: utils.htmlStrip(row.description),
      location: constructAddress(row.venue),
      rsvp_count: row.yes_rsvp_count,
      url: row.event_url,
      group_id: row.group.id,
      group_name: row.group.name,
      group_url: 'http://meetup.com/' + row.group.urlname,
      formatted_time: utils.formatLocalTime(row.time, config.timezone, config.displayTimeformat),
      start_time: eventTime.toISOString(),
      end_time: eventTime.add(row.duration, 'milliseconds').toISOString()
    }

    if (row.venue.lat !== 0 && row.venue.lon !== 0) {
      event.latitude = row.venue.lat;
      event.longitude = row.venue.lon
    }

    events.push(event);
    return events;
  }

  // getEventsByGroupIds returns an array of events
  // for the provided groups.
  function getEventsByGroupIds(groupIds) {
    var url = 'https://api.meetup.com/2/events/?' +
    querystring.stringify({
      key: config.meetupParams.key,
      group_id: groupIds.join(',')
    });

    return prequest(url).then(function(data) {
      var events = [];
      data.results.reduce(normalizeGroupEvents, events);
      logger.info('Info: Found ' + events.length + ' meetup.com group events with venues');
      return events;
    }).catch(function(err) {
      logger.error(err.body);
    });
  }

  // getGroupIds returns an array of group IDs
  // matching the given criteria.
  function getGroupIds(offset) {
    config.meetupParams.offset = offset
    var url = 'https://api.meetup.com/2/groups?' + querystring.stringify(config.meetupParams);

    return prequest(url).then(function(data) {
      logger.info(`Found ${data.results.length} meetup.com groups with offset=${offset}`);

      return data.results
        .filter(isValidGroup)
        .reduce(function(groupIds, row) {
          groupIds.push(row.id);
          return groupIds;
        }, []);
    }).catch(function(err) {
      logger.error(err);
    });
  }

  return {
    'get': function () {
      return getGroupIds(0).then(function(groupIdsOffset0) {
        return getGroupIds(1).then(function(groupsIdsOffset1) {
          return getEventsByGroupIds(groupIdsOffset0).then(function(events0) {
            return getEventsByGroupIds(groupsIdsOffset1).then(function(events1) {
              return events0.concat(events1)
            })
          })
        }).catch(function(err) {
          logger.error(err)
        })
      }).catch(function(err) {
        logger.error(err)
      })
    }
  }
}
<|endoftext|>