<commit_before>var has = require("has"),
    arrayMap = require("array-map"),
    indexOf = require("index_of"),
    isNull = require("is_null"),
    isString = require("is_string"),
    isArray = require("is_array"),
    isFunction = require("is_function"),
    extend = require("extend"),
    owner = require("./owner"),
    context = require("./context"),
    shouldUpdate = require("./utils/shouldUpdate"),
    componentState = require("./utils/componentState"),
    getComponentClassForType = require("./utils/getComponentClassForType"),
    View = require("./View"),
    getChildKey = require("./utils/getChildKey"),
    emptyObject = require("./utils/emptyObject"),
    diffChildren;

var NodePrototype,
    isPrimitiveView = View.isPrimitiveView;

module.exports = Node;

diffChildren = require("./utils/diffChildren");

function Node(parentId, id, currentView) {

    this.parent = null;
    this.parentId = parentId;
    this.id = id;

    this.context = null;

    this.root = null;

    this.ComponentClass = null;
    this.component = null;

    this.isBottomLevel = true;
    this.isTopLevel = false;

    this.renderedNode = null;
    this.renderedChildren = null;

    this.currentView = currentView;
}

NodePrototype = Node.prototype;

NodePrototype.appendNode = function(node) {
    var renderedChildren = this.renderedChildren;

    this.root.appendNode(node);
    node.parent = this;

    renderedChildren[renderedChildren.length] = node;
};

NodePrototype.removeNode = function(node) {
    var renderedChildren = this.renderedChildren,
        index;

    node.parent = null;

    index = indexOf(renderedChildren, node);
    if (index !== -1) {
        renderedChildren.splice(index, 1);
    }
};

NodePrototype.mountComponent = function() {
    var currentView = this.currentView,
        ComponentClass, component, props, children, context;

    if (isFunction(currentView.type)) {
        this.ComponentClass = ComponentClass = currentView.type;
    } else {
        this.ComponentClass = ComponentClass = getComponentClassForType(currentView.type, this.root.nativeComponents);
        this.isTopLevel = true;
    }

    props = this.__processProps(currentView.props);
    children = currentView.children;
    context = this.__processContext(currentView.__context);

    component = new ComponentClass(props, children, context);

    this.component = component;

    component.__node = this;
    component.props = component.props || props;
    component.children = component.children || children;
    component.context = component.context || context;
};

NodePrototype.mount = function(transaction) {
    transaction.mount(this.id, this.__mount(transaction));
};

NodePrototype.__mount = function(transaction) {
    var component, renderedView, renderedNode;

    this.context = context.current;
    this.mountComponent();

    renderedView = this.renderView();

    if (this.isTopLevel !== true) {
        renderedNode = this.renderedNode = new Node(this.parentId, this.id, renderedView);
        renderedNode.root = this.root;
        renderedNode.isBottomLevel = false;
        renderedView = renderedNode.__mount(transaction);
    } else {
        mountEvents(this.id, renderedView.props, this.root.eventManager, transaction);
        this.__mountChildren(renderedView, transaction);
    }

    component = this.component;
    component.__mountState = componentState.MOUNTING;
    component.componentWillMount();

    transaction.queue.enqueue(function onMount() {
        component.__mountState = componentState.MOUNTED;
        if (component.componentDidMount) {
            component.componentDidMount();
        }
    });

    this.__attachRefs();

    return renderedView;
};

NodePrototype.__mountChildren = function(renderedView, transaction) {
    var _this = this,
        parentId = this.id,
        renderedChildren = [];

    this.renderedChildren = renderedChildren;

    renderedView.children = arrayMap(renderedView.children, function(child, index) {
        var node, id;

        if (isPrimitiveView(child)) {
            return child;
        } else {
            id = getChildKey(parentId, child, index);
            node = new Node(parentId, id, child);
            _this.appendNode(node);
            return node.__mount(transaction);
        }
    });
};

NodePrototype.unmount = function(transaction) {
    this.__unmount(transaction);
    transaction.remove(this.parentId, this.id, 0);
};

NodePrototype.__unmount = function(transaction) {
    var component = this.component;

    if (this.isTopLevel !== true) {
        this.renderedNode.__unmount(transaction);
        this.renderedNode = null;
    } else {
        this.__unmountChildren(transaction);
        this.root.eventManager.allOff(this.id, transaction);
        this.renderedChildren = null;
    }

    component.__mountState = componentState.UNMOUNTING;

    if (component.componentWillUnmount) {
        component.componentWillUnmount();
    }

    if (this.isBottomLevel !== false) {
        this.root.removeNode(this);
    }

    this.__detachRefs();

    this.context = null;
    this.component = null;
    this.currentView = null;

    transaction.queue.enqueue(function onUnmount() {
        component.__mountState = componentState.UNMOUNTED;
    });
};

NodePrototype.__unmountChildren = function(transaction) {
    var renderedChildren = this.renderedChildren,
        i = -1,
        il = renderedChildren.length - 1;

    while (i++ < il) {
        renderedChildren[i].__unmount(transaction);
    }
};

NodePrototype.update = function(nextView, transaction) {
    this.receiveView(nextView, nextView.__context, transaction);
};

NodePrototype.receiveView = function(nextView, nextContext, transaction) {
    var prevView = this.currentView,
        prevContext = this.context;

    this.updateComponent(
        prevView,
        nextView,
        prevContext,
        nextContext,
        transaction
    );
};

NodePrototype.updateComponent = function(
    prevParentView, nextParentView, prevUnmaskedContext, nextUnmaskedContext, transaction
) {
    var component = this.component,

        nextProps = component.props,
        nextChildren = component.children,
        nextContext = component.context,

        nextState;

    component.__mountState = componentState.UPDATING;

    if (prevParentView !== nextParentView) {
        nextProps = this.__processProps(nextParentView.props);
        nextChildren = nextParentView.children;
        nextContext = this.__processContext(nextParentView.__context);

        if (component.componentWillReceiveProps) {
            component.componentWillReceiveProps(nextProps, nextChildren, nextContext);
        }
    }

    nextState = component.__nextState || component.state;

    if (component.shouldComponentUpdate ? component.shouldComponentUpdate(nextProps, nextChildren, nextState, nextContext) : true) {
        this.__updateComponent(
            nextParentView, nextProps, nextChildren, nextState, nextContext, nextUnmaskedContext, transaction
        );
    } else {
        this.currentView = nextParentView;
        this.context = nextUnmaskedContext;

        component.props = nextProps;
        component.children = nextChildren;
        component.state = nextState;
        component.context = nextContext;

        component.__mountState = componentState.MOUNTED;
    }
};

NodePrototype.__updateComponent = function(
    nextParentView, nextProps, nextChildren, nextState, nextContext, unmaskedContext, transaction
) {
    var component = this.component,

        prevProps = component.props,
        prevChildren = component.children,
        prevState = component.__previousState,
        prevContext = component.context,

        prevParentView;

    if (component.componentWillUpdate) {
        component.componentWillUpdate(nextProps, nextChildren, nextState, nextContext);
    }

    component.props = nextProps;
    component.children = nextChildren;
    component.state = nextState;
    component.context = nextContext;

    this.context = unmaskedContext;

    if (this.isTopLevel !== true) {
        this.currentView = nextParentView;
        this.__updateRenderedNode(unmaskedContext, transaction);
    } else {
        prevParentView = this.currentView;
        this.currentView = nextParentView;
        this.__updateRenderedView(prevParentView, unmaskedContext, transaction);
    }

    transaction.queue.enqueue(function onUpdate() {
        component.__mountState = componentState.UPDATED;
        if (component.componentDidUpdate) {
            component.componentDidUpdate(prevProps, prevChildren, prevState, prevContext);
        }
        component.__mountState = componentState.MOUNTED;
    });
};

NodePrototype.__updateRenderedNode = function(context, transaction) {
    var prevNode = this.renderedNode,
        prevRenderedView = prevNode.currentView,
        nextRenderedView = this.renderView(),
        renderedNode;

    if (shouldUpdate(prevRenderedView, nextRenderedView)) {
        prevNode.receiveView(nextRenderedView, this.__processChildContext(context), transaction);
    } else {
        prevNode.__unmount(transaction);

        renderedNode = this.renderedNode = new Node(this.parentId, this.id, nextRenderedView);
        renderedNode.root = this.root;
        renderedNode.isBottomLevel = false;

        transaction.replace(this.parentId, this.id, 0, renderedNode.__mount(transaction));
    }

    this.__attachRefs();
};

NodePrototype.__updateRenderedView = function(prevRenderedView, context, transaction) {
    var id = this.id,
        root = this.root,
        nextRenderedView = this.renderView(),
        propsDiff = root.diffProps(id, root.eventManager, transaction, prevRenderedView.props, nextRenderedView.props);

    if (!isNull(propsDiff)) {
        transaction.props(id, prevRenderedView.props, propsDiff);
    }

    diffChildren(this, prevRenderedView, nextRenderedView, transaction);
};

NodePrototype.renderView = function() {
    var currentView = this.currentView,
        previousContext = context.current,
        renderedView;

    context.current = this.__processChildContext(currentView.__context);
    owner.current = this.component;

    renderedView = this.component.render();

    renderedView.ref = currentView.ref;
    renderedView.key = currentView.key;

    context.current = previousContext;
    owner.current = null;

    return renderedView;
};

function warnError(error) {
    var i, il;

    if (isArray(error)) {
        i = -1;
        il = error.length - 1;
        while (i++ < il) {
            warnError(error[i]);
        }
    } else {
        console.warn(error);
    }
}

NodePrototype.__checkTypes = function(propTypes, props) {
    var localHas = has,
        displayName = this.__getName(),
        propName, error;

    if (propTypes) {
        for (propName in propTypes) {
            if (localHas(propTypes, propName)) {
                error = propTypes[propName](props, propName, displayName);
                if (error) {
                    warnError(error);
                }
            }
        }
    }
};

NodePrototype.__processProps = function(props) {
    var ComponentClass = this.ComponentClass,
        propTypes;

    if (process.env.NODE_ENV !== "production") {
        propTypes = ComponentClass.propTypes;

        if (propTypes) {
            this.__checkTypes(propTypes, props);
        }
    }

    return props;
};

NodePrototype.__maskContext = function(context) {
    var maskedContext = null,
        contextTypes, contextName, localHas;

    if (isString(this.ComponentClass)) {
        return emptyObject;
    } else {
        contextTypes = this.ComponentClass.contextTypes;

        if (contextTypes) {
            maskedContext = {};
            localHas = has;

            for (contextName in contextTypes) {
                if (localHas(contextTypes, contextName)) {
                    maskedContext[contextName] = context[contextName];
                }
            }
        }

        return maskedContext;
    }
};

NodePrototype.__processContext = function(context) {
    var maskedContext = this.__maskContext(context),
        contextTypes;

    if (process.env.NODE_ENV !== "production") {
        contextTypes = this.ComponentClass.contextTypes;

        if (contextTypes) {
            this.__checkTypes(contextTypes, maskedContext);
        }
    }

    return maskedContext;
};

NodePrototype.__processChildContext = function(currentContext) {
    var component = this.component,
        childContext = isFunction(component.getChildContext) ? component.getChildContext() : null,
        childContextTypes, localHas, contextName, displayName;

    if (childContext) {
        childContextTypes = this.ComponentClass.childContextTypes;

        if (process.env.NODE_ENV !== "production") {
            if (childContextTypes) {
                this.__checkTypes(childContextTypes, childContext);
            }
        }

        if (childContextTypes) {
            localHas = has;
            displayName = this.__getName();

            for (contextName in childContext) {
                if (!localHas(childContextTypes, contextName)) {
                    console.warn(new Error(
                        displayName + " getChildContext(): key " + contextName + " is not defined in childContextTypes"
                    ));
                }
            }
        }

        return extend({}, currentContext, childContext);
    } else {
        return currentContext;
    }
};

NodePrototype.__attachRefs = function() {
    var view = this.currentView,
        ref = view.ref;

    if (isString(ref)) {
        attachRef(this.component, ref, view.__owner);
    }
};

NodePrototype.__detachRefs = function() {
    var view = this.currentView,
        ref = view.ref;

    if (isString(ref)) {
        detachRef(ref, view.__owner);
    }
};

NodePrototype.__getName = function() {
    var type = this.currentView.type,
        constructor;

    if (isString(type)) {
        return type;
    } else {
        constructor = this.component && this.component.constructor;
        return type.displayName || (constructor && constructor.displayName) || null;
    }
};

function attachRef(component, ref, owner) {
    if (isString(ref)) {
        if (owner) {
            owner.refs[ref] = component;
        } else {
            throw new Error("cannot add ref to view without owner");
        }

    }
}

function detachRef(ref, owner) {
    var refs = owner.refs;
    delete refs[ref];
}

function mountEvents(id, props, eventManager, transaction) {
    var propNameToTopLevel = eventManager.propNameToTopLevel,
        localHas = has,
        key;

    for (key in props) {
        if (localHas(propNameToTopLevel, key)) {
            eventManager.on(id, propNameToTopLevel[key], props[key], transaction);
        }
    }
}
<commit_msg>updates<commit_after>var has = require("has"),
    arrayMap = require("array-map"),
    indexOf = require("index_of"),
    isNull = require("is_null"),
    isString = require("is_string"),
    isArray = require("is_array"),
    isFunction = require("is_function"),
    extend = require("extend"),
    owner = require("./owner"),
    context = require("./context"),
    shouldUpdate = require("./utils/shouldUpdate"),
    componentState = require("./utils/componentState"),
    getComponentClassForType = require("./utils/getComponentClassForType"),
    View = require("./View"),
    getChildKey = require("./utils/getChildKey"),
    emptyObject = require("./utils/emptyObject"),
    diffChildren;

var NodePrototype,
    isPrimitiveView = View.isPrimitiveView;

module.exports = Node;

diffChildren = require("./utils/diffChildren");

function Node(parentId, id, currentView) {

    this.parent = null;
    this.parentId = parentId;
    this.id = id;

    this.context = null;

    this.root = null;

    this.ComponentClass = null;
    this.component = null;

    this.isBottomLevel = true;
    this.isTopLevel = false;

    this.renderedNode = null;
    this.renderedChildren = null;

    this.currentView = currentView;
}

NodePrototype = Node.prototype;

NodePrototype.appendNode = function(node) {
    var renderedChildren = this.renderedChildren;

    this.root.appendNode(node);
    node.parent = this;

    renderedChildren[renderedChildren.length] = node;
};

NodePrototype.removeNode = function(node) {
    var renderedChildren = this.renderedChildren,
        index;

    node.parent = null;

    index = indexOf(renderedChildren, node);
    if (index !== -1) {
        renderedChildren.splice(index, 1);
    }
};

NodePrototype.mountComponent = function() {
    var currentView = this.currentView,
        ComponentClass, component, props, children, context;

    if (isFunction(currentView.type)) {
        this.ComponentClass = ComponentClass = currentView.type;
    } else {
        this.ComponentClass = ComponentClass = getComponentClassForType(currentView.type, this.root.nativeComponents);
        this.isTopLevel = true;
    }

    props = this.__processProps(currentView.props);
    children = currentView.children;
    context = this.__processContext(currentView.__context);

    component = new ComponentClass(props, children, context);

    this.component = component;

    component.__node = this;
    component.props = component.props || props;
    component.children = component.children || children;
    component.context = component.context || context;
};

NodePrototype.mount = function(transaction) {
    transaction.mount(this.id, this.__mount(transaction));
};

NodePrototype.__mount = function(transaction) {
    var component, renderedView, renderedNode;

    this.context = context.current;
    this.mountComponent();

    renderedView = this.renderView();

    if (this.isTopLevel !== true) {
        renderedNode = this.renderedNode = new Node(this.parentId, this.id, renderedView);
        renderedNode.root = this.root;
        renderedNode.isBottomLevel = false;
        renderedView = renderedNode.__mount(transaction);
    } else {
        mountEvents(this.id, renderedView.props, this.root.eventManager, transaction);
        this.__mountChildren(renderedView, transaction);
    }

    component = this.component;
    component.__mountState = componentState.MOUNTING;
    component.componentWillMount();

    transaction.queue.enqueue(function onMount() {
        component.__mountState = componentState.MOUNTED;
        if (component.componentDidMount) {
            component.componentDidMount();
        }
    });

    this.__attachRefs();

    return renderedView;
};

NodePrototype.__mountChildren = function(renderedView, transaction) {
    var _this = this,
        parentId = this.id,
        renderedChildren = [];

    this.renderedChildren = renderedChildren;

    renderedView.children = arrayMap(renderedView.children, function renderChild(child, index) {
        var node, id;

        if (isPrimitiveView(child)) {
            return child;
        } else {
            id = getChildKey(parentId, child, index);
            node = new Node(parentId, id, child);
            _this.appendNode(node);
            return node.__mount(transaction);
        }
    });
};

NodePrototype.unmount = function(transaction) {
    this.__unmount(transaction);
    transaction.remove(this.parentId, this.id, 0);
};

NodePrototype.__unmount = function(transaction) {
    var component = this.component;

    if (this.isTopLevel !== true) {
        this.renderedNode.__unmount(transaction);
        this.renderedNode = null;
    } else {
        this.__unmountChildren(transaction);
        this.root.eventManager.allOff(this.id, transaction);
        this.renderedChildren = null;
    }

    component.__mountState = componentState.UNMOUNTING;

    if (component.componentWillUnmount) {
        component.componentWillUnmount();
    }

    if (this.isBottomLevel !== false) {
        this.root.removeNode(this);
    }

    this.__detachRefs();

    this.context = null;
    this.component = null;
    this.currentView = null;

    transaction.queue.enqueue(function onUnmount() {
        component.__mountState = componentState.UNMOUNTED;
    });
};

NodePrototype.__unmountChildren = function(transaction) {
    var renderedChildren = this.renderedChildren,
        i = -1,
        il = renderedChildren.length - 1;

    while (i++ < il) {
        renderedChildren[i].__unmount(transaction);
    }
};

NodePrototype.update = function(nextView, transaction) {
    this.receiveView(nextView, nextView.__context, transaction);
};

NodePrototype.receiveView = function(nextView, nextContext, transaction) {
    var prevView = this.currentView,
        prevContext = this.context;

    this.updateComponent(
        prevView,
        nextView,
        prevContext,
        nextContext,
        transaction
    );
};

NodePrototype.updateComponent = function(
    prevParentView, nextParentView, prevUnmaskedContext, nextUnmaskedContext, transaction
) {
    var component = this.component,

        nextProps = component.props,
        nextChildren = component.children,
        nextContext = component.context,

        nextState;

    component.__mountState = componentState.UPDATING;

    if (prevParentView !== nextParentView) {
        nextProps = this.__processProps(nextParentView.props);
        nextChildren = nextParentView.children;
        nextContext = this.__processContext(nextParentView.__context);

        if (component.componentWillReceiveProps) {
            component.componentWillReceiveProps(nextProps, nextChildren, nextContext);
        }
    }

    nextState = component.__nextState || component.state;

    if (component.shouldComponentUpdate ? component.shouldComponentUpdate(nextProps, nextChildren, nextState, nextContext) : true) {
        this.__updateComponent(
            nextParentView, nextProps, nextChildren, nextState, nextContext, nextUnmaskedContext, transaction
        );
    } else {
        this.currentView = nextParentView;
        this.context = nextUnmaskedContext;

        component.props = nextProps;
        component.children = nextChildren;
        component.state = nextState;
        component.context = nextContext;

        component.__mountState = componentState.MOUNTED;
    }
};

NodePrototype.__updateComponent = function(
    nextParentView, nextProps, nextChildren, nextState, nextContext, unmaskedContext, transaction
) {
    var component = this.component,

        prevProps = component.props,
        prevChildren = component.children,
        prevState = component.__previousState,
        prevContext = component.context,

        prevParentView;

    if (component.componentWillUpdate) {
        component.componentWillUpdate(nextProps, nextChildren, nextState, nextContext);
    }

    component.props = nextProps;
    component.children = nextChildren;
    component.state = nextState;
    component.context = nextContext;

    this.context = unmaskedContext;

    if (this.isTopLevel !== true) {
        this.currentView = nextParentView;
        this.__updateRenderedNode(unmaskedContext, transaction);
    } else {
        prevParentView = this.currentView;
        this.currentView = nextParentView;
        this.__updateRenderedView(prevParentView, unmaskedContext, transaction);
    }

    transaction.queue.enqueue(function onUpdate() {
        component.__mountState = componentState.UPDATED;
        if (component.componentDidUpdate) {
            component.componentDidUpdate(prevProps, prevChildren, prevState, prevContext);
        }
        component.__mountState = componentState.MOUNTED;
    });
};

NodePrototype.__updateRenderedNode = function(context, transaction) {
    var prevNode = this.renderedNode,
        prevRenderedView = prevNode.currentView,
        nextRenderedView = this.renderView(),
        renderedNode;

    if (shouldUpdate(prevRenderedView, nextRenderedView)) {
        prevNode.receiveView(nextRenderedView, this.__processChildContext(context), transaction);
    } else {
        prevNode.__unmount(transaction);

        renderedNode = this.renderedNode = new Node(this.parentId, this.id, nextRenderedView);
        renderedNode.root = this.root;
        renderedNode.isBottomLevel = false;

        transaction.replace(this.parentId, this.id, 0, renderedNode.__mount(transaction));
    }

    this.__attachRefs();
};

NodePrototype.__updateRenderedView = function(prevRenderedView, context, transaction) {
    var id = this.id,
        root = this.root,
        nextRenderedView = this.renderView(),
        propsDiff = root.diffProps(id, root.eventManager, transaction, prevRenderedView.props, nextRenderedView.props);

    if (!isNull(propsDiff)) {
        transaction.props(id, prevRenderedView.props, propsDiff);
    }

    diffChildren(this, prevRenderedView, nextRenderedView, transaction);
};

NodePrototype.renderView = function() {
    var currentView = this.currentView,
        previousContext = context.current,
        renderedView;

    context.current = this.__processChildContext(currentView.__context);
    owner.current = this.component;

    renderedView = this.component.render();

    renderedView.ref = currentView.ref;
    renderedView.key = currentView.key;

    context.current = previousContext;
    owner.current = null;

    return renderedView;
};

function warnError(error) {
    var i, il;

    if (isArray(error)) {
        i = -1;
        il = error.length - 1;
        while (i++ < il) {
            warnError(error[i]);
        }
    } else {
        console.warn(error);
    }
}

NodePrototype.__checkTypes = function(propTypes, props) {
    var localHas = has,
        displayName = this.__getName(),
        propName, error;

    if (propTypes) {
        for (propName in propTypes) {
            if (localHas(propTypes, propName)) {
                error = propTypes[propName](props, propName, displayName);
                if (error) {
                    warnError(error);
                }
            }
        }
    }
};

NodePrototype.__processProps = function(props) {
    var ComponentClass = this.ComponentClass,
        propTypes;

    if (process.env.NODE_ENV !== "production") {
        propTypes = ComponentClass.propTypes;

        if (propTypes) {
            this.__checkTypes(propTypes, props);
        }
    }

    return props;
};

NodePrototype.__maskContext = function(context) {
    var maskedContext = null,
        contextTypes, contextName, localHas;

    if (isString(this.ComponentClass)) {
        return emptyObject;
    } else {
        contextTypes = this.ComponentClass.contextTypes;

        if (contextTypes) {
            maskedContext = {};
            localHas = has;

            for (contextName in contextTypes) {
                if (localHas(contextTypes, contextName)) {
                    maskedContext[contextName] = context[contextName];
                }
            }
        }

        return maskedContext;
    }
};

NodePrototype.__processContext = function(context) {
    var maskedContext = this.__maskContext(context),
        contextTypes;

    if (process.env.NODE_ENV !== "production") {
        contextTypes = this.ComponentClass.contextTypes;

        if (contextTypes) {
            this.__checkTypes(contextTypes, maskedContext);
        }
    }

    return maskedContext;
};

NodePrototype.__processChildContext = function(currentContext) {
    var component = this.component,
        childContext = isFunction(component.getChildContext) ? component.getChildContext() : null,
        childContextTypes, localHas, contextName, displayName;

    if (childContext) {
        childContextTypes = this.ComponentClass.childContextTypes;

        if (process.env.NODE_ENV !== "production") {
            if (childContextTypes) {
                this.__checkTypes(childContextTypes, childContext);
            }
        }

        if (childContextTypes) {
            localHas = has;
            displayName = this.__getName();

            for (contextName in childContext) {
                if (!localHas(childContextTypes, contextName)) {
                    console.warn(new Error(
                        displayName + " getChildContext(): key " + contextName + " is not defined in childContextTypes"
                    ));
                }
            }
        }

        return extend({}, currentContext, childContext);
    } else {
        return currentContext;
    }
};

NodePrototype.__attachRefs = function() {
    var view = this.currentView,
        ref = view.ref;

    if (isString(ref)) {
        attachRef(this.component, ref, view.__owner);
    }
};

NodePrototype.__detachRefs = function() {
    var view = this.currentView,
        ref = view.ref;

    if (isString(ref)) {
        detachRef(ref, view.__owner);
    }
};

NodePrototype.__getName = function() {
    var type = this.currentView.type,
        constructor;

    if (isString(type)) {
        return type;
    } else {
        constructor = this.component && this.component.constructor;
        return type.displayName || (constructor && constructor.displayName) || null;
    }
};

function attachRef(component, ref, owner) {
    if (isString(ref)) {
        if (owner) {
            owner.refs[ref] = component;
        } else {
            throw new Error("cannot add ref to view without owner");
        }

    }
}

function detachRef(ref, owner) {
    var refs = owner.refs;
    delete refs[ref];
}

function mountEvents(id, props, eventManager, transaction) {
    var propNameToTopLevel = eventManager.propNameToTopLevel,
        localHas = has,
        key;

    for (key in props) {
        if (localHas(propNameToTopLevel, key)) {
            eventManager.on(id, propNameToTopLevel[key], props[key], transaction);
        }
    }
}
<|endoftext|>


<commit_before>/* eslint-disable max-len */
import React from 'react';
import PropTypes from 'prop-types';

const PDCA = ({
  planDisabled,
  doDisabled,
  checkDisabled,
  actDisabled,
  planColor,
  doColor,
  checkColor,
  actColor,
  disabledColor,
}) => (
  <svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
    <defs>
      <circle id="path-1" cx="100" cy="100" r="100" />
      <filter x="-5.5%" y="-5.5%" width="111.0%" height="111.0%" filterUnits="objectBoundingBox" id="filter-2">
        <feMorphology radius="2" operator="erode" in="SourceAlpha" result="shadowSpreadInner1" />
        <feGaussianBlur stdDeviation="10" in="shadowSpreadInner1" result="shadowBlurInner1" />
        <feOffset dx="0" dy="0" in="shadowBlurInner1" result="shadowOffsetInner1" />
        <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1" />
        <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowInnerInner1" />
      </filter>
    </defs>
    <g id="PDCA">
      <g id="Plan">
        <path
          id="PlanSlice"
          fill={planDisabled ? disabledColor : planColor}
          d="M200,100 C200,44.771525 155.228475,7.10542736e-15 100,7.10542736e-15 L100,100 L200,100 L200,100 Z"
        />
        <path
          id="P"
          fill="#FFFFFF"
          d="M130.914062,55.8125 L130.914062,66.078125 L133.75,66.078125 C136.015636,66.078125 137.605464,65.6953163 138.519531,64.9296875 C139.433598,64.1640587 139.890625,62.835947 139.890625,60.9453125 C139.890625,59.054678 139.433598,57.7265663 138.519531,56.9609375 C137.605464,56.1953087 136.015636,55.8125 133.75,55.8125 L130.914062,55.8125 Z M124,50 L133.492188,50 C138.320337,50 141.792958,50.8593664 143.910156,52.578125 C146.027354,54.2968836 147.085938,57.0859182 147.085938,60.9453125 C147.085938,64.8047068 146.027354,67.5937414 143.910156,69.3125 C141.792958,71.0312586 138.320337,71.890625 133.492188,71.890625 L130.914062,71.890625 L130.914062,84.9921875 L124,84.9921875 L124,50 Z"
        />
      </g>
      <g id="Do">
        <path
          id="DoSlice"
          fill={doDisabled ? disabledColor : doColor}
          d="M100,200 C155.228475,200 200,155.228475 200,100 L100,100 L100,200 L100,200 Z"
        />
        <path
          id="D"
          fill="#FFFFFF"
          d="M130.914062,121.234375 L130.914062,143.757812 L132.789062,143.757812 C135.507826,143.757812 137.445307,142.902352 138.601562,141.191406 C139.757818,139.48046 140.335938,136.570333 140.335938,132.460938 C140.335938,128.382792 139.757818,125.492196 138.601562,123.789062 C137.445307,122.085929 135.507826,121.234375 132.789062,121.234375 L130.914062,121.234375 Z M124,115 L131.40625,115 C137.125029,115 141.242175,116.363268 143.757812,119.089844 C146.27345,121.81642 147.53125,126.273407 147.53125,132.460938 C147.53125,138.664094 146.27345,143.136705 143.757812,145.878906 C141.242175,148.621107 137.125029,149.992188 131.40625,149.992188 L124,149.992188 L124,115 Z"
        />
      </g>
      <g id="Check">
        <path
          id="CheckSlice"
          fill={checkDisabled ? disabledColor : checkColor}
          d="M1.42108547e-14,100 C2.84217094e-14,155.228475 44.771525,200 100,200 L100,100 L4.26325641e-14,100 L1.42108547e-14,100 Z"
        />
        <path
          id="C"
          fill="#FFFFFF"
          d="M73.7734375,148.617188 C72.679682,149.17969 71.531256,149.601561 70.328125,149.882812 C69.124994,150.164064 67.8593816,150.304688 66.53125,150.304688 C61.8124764,150.304688 58.2109499,148.750016 55.7265625,145.640625 C53.2421751,142.531234 52,138.039092 52,132.164062 C52,126.273408 53.2421751,121.773453 55.7265625,118.664062 C58.2109499,115.554672 61.8124764,114 66.53125,114 C67.8593816,114 69.1328064,114.140624 70.3515625,114.421875 C71.5703186,114.703126 72.7109322,115.124997 73.7734375,115.6875 L73.7734375,123.375 C72.5859316,122.281245 71.4335993,121.480471 70.3164062,120.972656 C69.1992132,120.464841 68.0468809,120.210938 66.859375,120.210938 C64.3281123,120.210938 62.4179752,121.214834 61.1289062,123.222656 C59.8398373,125.230479 59.1953125,128.210918 59.1953125,132.164062 C59.1953125,136.101582 59.8398373,139.074209 61.1289062,141.082031 C62.4179752,143.089854 64.3281123,144.09375 66.859375,144.09375 C68.0468809,144.09375 69.1992132,143.839846 70.3164062,143.332031 C71.4335993,142.824216 72.5859316,142.023443 73.7734375,140.929688 L73.7734375,148.617188 Z"
        />
      </g>
      <g id="Act">
        <path
          id="ActSlice"
          fill={actDisabled ? disabledColor : actColor}
          d="M100,4.73316543e-30 C44.771525,4.73316543e-30 -1.42108547e-14,44.771525 -4.73316543e-30,100 L100,100 L100,2.84217094e-14 L100,4.73316543e-30 Z"
        />
        <path
          id="A"
          fill="#FFFFFF"
          d="M63.6640625,56.328125 L60.40625,70.6484375 L66.9453125,70.6484375 L63.6640625,56.328125 Z M59.4453125,50 L67.90625,50 L77.3515625,84.9921875 L70.4375,84.9921875 L68.28125,76.34375 L59.0234375,76.34375 L56.9140625,84.9921875 L50,84.9921875 L59.4453125,50 Z"
        />
      </g>
    </g>
    <g id="Shadow" fillOpacity="1" fill="black">
      <use filter="url(#filter-2)" xlinkHref="#path-1" />
    </g>
  </svg >
);

PDCA.propTypes = {
  planDisabled: PropTypes.bool,
  doDisabled: PropTypes.bool,
  checkDisabled: PropTypes.bool,
  actDisabled: PropTypes.bool,
  planColor: PropTypes.string,
  doColor: PropTypes.string,
  checkColor: PropTypes.string,
  actColor: PropTypes.string,
  disabledColor: PropTypes.string,
};

PDCA.defaultProps = {
  planDisabled: false,
  doDisabled: false,
  checkDisabled: false,
  actDisabled: false,
  planColor: '#4990E2',
  doColor: '#D0011B',
  checkColor: '#F8E81C',
  actColor: '#7ED321',
  disabledColor: '#969696',
};

export default PDCA;
<commit_msg>Remove whitespace<commit_after>/* eslint-disable max-len */
import React from 'react';
import PropTypes from 'prop-types';

const PDCA = ({
  planDisabled,
  doDisabled,
  checkDisabled,
  actDisabled,
  planColor,
  doColor,
  checkColor,
  actColor,
  disabledColor,
}) => (
  <svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
    <defs>
      <circle id="path-1" cx="100" cy="100" r="100" />
      <filter x="-5.5%" y="-5.5%" width="111.0%" height="111.0%" filterUnits="objectBoundingBox" id="filter-2">
        <feMorphology radius="2" operator="erode" in="SourceAlpha" result="shadowSpreadInner1" />
        <feGaussianBlur stdDeviation="10" in="shadowSpreadInner1" result="shadowBlurInner1" />
        <feOffset dx="0" dy="0" in="shadowBlurInner1" result="shadowOffsetInner1" />
        <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1" />
        <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowInnerInner1" />
      </filter>
    </defs>
    <g id="PDCA">
      <g id="Plan">
        <path
          id="PlanSlice"
          fill={planDisabled ? disabledColor : planColor}
          d="M200,100 C200,44.771525 155.228475,7.10542736e-15 100,7.10542736e-15 L100,100 L200,100 L200,100 Z"
        />
        <path
          id="P"
          fill="#FFFFFF"
          d="M130.914062,55.8125 L130.914062,66.078125 L133.75,66.078125 C136.015636,66.078125 137.605464,65.6953163 138.519531,64.9296875 C139.433598,64.1640587 139.890625,62.835947 139.890625,60.9453125 C139.890625,59.054678 139.433598,57.7265663 138.519531,56.9609375 C137.605464,56.1953087 136.015636,55.8125 133.75,55.8125 L130.914062,55.8125 Z M124,50 L133.492188,50 C138.320337,50 141.792958,50.8593664 143.910156,52.578125 C146.027354,54.2968836 147.085938,57.0859182 147.085938,60.9453125 C147.085938,64.8047068 146.027354,67.5937414 143.910156,69.3125 C141.792958,71.0312586 138.320337,71.890625 133.492188,71.890625 L130.914062,71.890625 L130.914062,84.9921875 L124,84.9921875 L124,50 Z"
        />
      </g>
      <g id="Do">
        <path
          id="DoSlice"
          fill={doDisabled ? disabledColor : doColor}
          d="M100,200 C155.228475,200 200,155.228475 200,100 L100,100 L100,200 L100,200 Z"
        />
        <path
          id="D"
          fill="#FFFFFF"
          d="M130.914062,121.234375 L130.914062,143.757812 L132.789062,143.757812 C135.507826,143.757812 137.445307,142.902352 138.601562,141.191406 C139.757818,139.48046 140.335938,136.570333 140.335938,132.460938 C140.335938,128.382792 139.757818,125.492196 138.601562,123.789062 C137.445307,122.085929 135.507826,121.234375 132.789062,121.234375 L130.914062,121.234375 Z M124,115 L131.40625,115 C137.125029,115 141.242175,116.363268 143.757812,119.089844 C146.27345,121.81642 147.53125,126.273407 147.53125,132.460938 C147.53125,138.664094 146.27345,143.136705 143.757812,145.878906 C141.242175,148.621107 137.125029,149.992188 131.40625,149.992188 L124,149.992188 L124,115 Z"
        />
      </g>
      <g id="Check">
        <path
          id="CheckSlice"
          fill={checkDisabled ? disabledColor : checkColor}
          d="M1.42108547e-14,100 C2.84217094e-14,155.228475 44.771525,200 100,200 L100,100 L4.26325641e-14,100 L1.42108547e-14,100 Z"
        />
        <path
          id="C"
          fill="#FFFFFF"
          d="M73.7734375,148.617188 C72.679682,149.17969 71.531256,149.601561 70.328125,149.882812 C69.124994,150.164064 67.8593816,150.304688 66.53125,150.304688 C61.8124764,150.304688 58.2109499,148.750016 55.7265625,145.640625 C53.2421751,142.531234 52,138.039092 52,132.164062 C52,126.273408 53.2421751,121.773453 55.7265625,118.664062 C58.2109499,115.554672 61.8124764,114 66.53125,114 C67.8593816,114 69.1328064,114.140624 70.3515625,114.421875 C71.5703186,114.703126 72.7109322,115.124997 73.7734375,115.6875 L73.7734375,123.375 C72.5859316,122.281245 71.4335993,121.480471 70.3164062,120.972656 C69.1992132,120.464841 68.0468809,120.210938 66.859375,120.210938 C64.3281123,120.210938 62.4179752,121.214834 61.1289062,123.222656 C59.8398373,125.230479 59.1953125,128.210918 59.1953125,132.164062 C59.1953125,136.101582 59.8398373,139.074209 61.1289062,141.082031 C62.4179752,143.089854 64.3281123,144.09375 66.859375,144.09375 C68.0468809,144.09375 69.1992132,143.839846 70.3164062,143.332031 C71.4335993,142.824216 72.5859316,142.023443 73.7734375,140.929688 L73.7734375,148.617188 Z"
        />
      </g>
      <g id="Act">
        <path
          id="ActSlice"
          fill={actDisabled ? disabledColor : actColor}
          d="M100,4.73316543e-30 C44.771525,4.73316543e-30 -1.42108547e-14,44.771525 -4.73316543e-30,100 L100,100 L100,2.84217094e-14 L100,4.73316543e-30 Z"
        />
        <path
          id="A"
          fill="#FFFFFF"
          d="M63.6640625,56.328125 L60.40625,70.6484375 L66.9453125,70.6484375 L63.6640625,56.328125 Z M59.4453125,50 L67.90625,50 L77.3515625,84.9921875 L70.4375,84.9921875 L68.28125,76.34375 L59.0234375,76.34375 L56.9140625,84.9921875 L50,84.9921875 L59.4453125,50 Z"
        />
      </g>
    </g>
    <g id="Shadow" fillOpacity="1" fill="black">
      <use filter="url(#filter-2)" xlinkHref="#path-1" />
    </g>
  </svg>
);

PDCA.propTypes = {
  planDisabled: PropTypes.bool,
  doDisabled: PropTypes.bool,
  checkDisabled: PropTypes.bool,
  actDisabled: PropTypes.bool,
  planColor: PropTypes.string,
  doColor: PropTypes.string,
  checkColor: PropTypes.string,
  actColor: PropTypes.string,
  disabledColor: PropTypes.string,
};

PDCA.defaultProps = {
  planDisabled: false,
  doDisabled: false,
  checkDisabled: false,
  actDisabled: false,
  planColor: '#4990E2',
  doColor: '#D0011B',
  checkColor: '#F8E81C',
  actColor: '#7ED321',
  disabledColor: '#969696',
};

export default PDCA;
<|endoftext|>


<commit_before>;(function() {

    var Form = Backbone.Form,
        Base = Form.editors.Base,
        createTemplate = Form.helpers.createTemplate
        exports = {};

    /**
     * Additional editors that depend on jQuery UI
     */
    exports.Date = Base.extend({

        className: 'bbf-date',

        render: function() {
            var el = $(this.el);

            el.html('<input>');

            var input = $('input', el);

            input.datepicker({
                dateFormat: 'dd/mm/yy',
                showButtonPanel: true
            });

            input.datepicker('setDate', this.value);

            return this;
        },

        /**
        * @return {Date}   Selected date
        */
        getValue: function() {
            var input = $('input', this.el),
                date = input.datepicker('getDate');

            return date;
        }

    });

    exports.DateTime = exports.Date.extend({

        className: 'bbf-datetime',

        template: createTemplate('<select>{{hours}}</select> : <select>{{mins}}</select>'),

        render: function() {
            function pad(n) {
                return n < 10 ? '0' + n : n
            }

            //Render the date element first
            exports.Date.prototype.render.call(this);

            //Setup hour options
            var hours = _.range(0, 24),
                hoursOptions = [];

            _.each(hours, function(hour) {
                hoursOptions.push('<option value="'+hour+'">' + pad(hour) + '</option>');
            });

            //Setup minute options
            var mins = _.range(0, 60, 15),
                minsOptions = [];

            _.each(mins, function(min) {
                minsOptions.push('<option value="'+min+'">' + pad(min) + '</option>');
            });

            //Render time selects
            console.log(this.template)
            $(this.el).append(this.template({
                hours: hoursOptions.join(),
                mins: minsOptions.join()
            }));

            //Store references to selects
            this.$hours = $('select:eq(0)', this.el);
            this.$mins = $('select:eq(1)', this.el);

            //Set time
            var time = this.value;
            this.$hours.val(time.getHours());
            this.$mins.val(time.getMinutes());

            return this;
        },

        /**
        * @return {Date}   Selected datetime
        */
        getValue: function() {
            var input = $('input', this.el),
                date = input.datepicker('getDate');

            date.setHours(this.$hours.val());
            date.setMinutes(this.$mins.val());
            date.setMilliseconds(0);

            return date;
        }

    });

    exports.List = Base.extend({

        className: 'bbf-list',

        //Note: The extra div around the
 is used to limit the drag area
        template: createTemplate('\

\

<button class="add">Add
\
        '),

        itemTemplate: createTemplate('\

\
                {{text}}\

\
                    <button class="edit">Edit</button>\
                    <button class="del">Delete</button>\

\

\
        '),

        events: {
            'click .add':   'addNewItem',
            'click .edit':  'editItem',
            'click .del':   'deleteItem'
        },

        initialize: function(options) {
            Base.prototype.initialize.call(this, options);

            if (!this.schema) throw "Missing required option 'schema'";

            this.items = [];
        },

        render: function() {
            //Main element
            $(this.el).html(this.template());

            //Create list
            var self = this,
                data = this.value || [],
                schema = this.schema,
                itemToString = this.itemToString,
                itemTemplate = this.itemTemplate,
                listEl = $('ul', this.el);

            _.each(data, function(itemData) {
                var text = itemToString.call(self, itemData);

                //Create DOM element
                var li = $(itemTemplate({ text: text }));

                //Attach data
                $.data(li[0], 'data', itemData);

                listEl.append(li);
            });

            //Make sortable
            listEl.sortable({
                axis: 'y',
                cursor: 'move',
                containment: 'parent'
            });

            //jQuery UI buttonize
            $('button.add', this.el).button({
                text: false,
                icons: { primary: 'ui-icon-plus' }
            });
            $('button.edit', this.el).button({
                text: false,
                icons: { primary: 'ui-icon-pencil' }
            });
            $('button.del', this.el).button({
                text: false,
                icons: { primary: 'ui-icon-trash' }
            });

            return this;
        },

        /**
         * Formats an item for display in the list
         * For example objects, dates etc. can have a custom
         * itemToString method which says how it should be formatted.
         */
        itemToString: function(data) {
            if (!data) return data;

            var transform = this.schema.itemToString;

            return transform ? transform(data) : data;
        },

        /**
         * Add a new item to the list if it is completed in the editor
         */
        addNewItem: function() {
            var self = this;

            this.openEditor(null, function(value) {
                var text = self.itemToString(value);

                //Create DOM element
                var li = $(self.itemTemplate({ text: text }));

                //Store data
                $.data(li[0], 'data', value);

                $('ul', self.el).append(li);

                //jQuery UI buttonize
                $('button.edit', this.el).button({
                    text: false,
                    icons: { primary: 'ui-icon-pencil' }
                });
                $('button.del', this.el).button({
                    text: false,
                    icons: { primary: 'ui-icon-trash' }
                });
            });
        },

        /**
         * Edit an existing item in the list
         */
        editItem: function(event) {
            console.log('edit');

            var self = this,
                li = $(event.target).closest('li'),
                originalValue = $.data(li[0], 'data');

            this.openEditor(originalValue, function(newValue) {
                //Update display
                $('.text', li).html(self.itemToString(newValue));

                //Store data
                $.data(li[0], 'data', newValue);
            });
        },

        deleteItem: function(event) {
            console.log('delete');

            var li = $(event.target).closest('li');

            li.remove();
        },

        /**
         * Opens the sub editor dialog
         * @param {Mixed}       Data (if editing existing list item, null otherwise)
         * @param {Function}    Save callback. receives: value
         */
        openEditor: function(data, callback) {
            console.log('openEditor');

            var self = this,
                schema = this.schema;

            var editor = Form.createEditor(schema.listType, {
                key: '',
                schema: schema,
                value: data
            }).render();

            var close = function() {
                $(editor.el).dialog('close');

                editor.remove();
            };

            $(editor.el).dialog({
                resizable:  false,
                modal:      true,
                width:      500,
                title:      data ? 'Edit item' : 'New item',
                buttons: {
                    'OK': function() {
                        callback(editor.getValue());
                        close();
                    },
                    'Cancel': close
                }
            });
        },

        getValue: function() {
            var data = [];

            $('li', this.el).each(function(index, li) {
                data.push($.data(li, 'data'));
            });

            return data;
        }

    });

    //Exports
    _.extend(Backbone.Form.editors, exports);

})();
<commit_msg>Fix List not opening editor Make TextField default for List types<commit_after>;(function() {

    var Form = Backbone.Form,
        Base = Form.editors.Base,
        createTemplate = Form.helpers.createTemplate
        exports = {};

    /**
     * Additional editors that depend on jQuery UI
     */
    exports.Date = Base.extend({

        className: 'bbf-date',

        render: function() {
            var el = $(this.el);

            el.html('<input>');

            var input = $('input', el);

            input.datepicker({
                dateFormat: 'dd/mm/yy',
                showButtonPanel: true
            });

            input.datepicker('setDate', this.value);

            return this;
        },

        /**
        * @return {Date}   Selected date
        */
        getValue: function() {
            var input = $('input', this.el),
                date = input.datepicker('getDate');

            return date;
        }

    });

    exports.DateTime = exports.Date.extend({

        className: 'bbf-datetime',

        template: createTemplate('<select>{{hours}}</select> : <select>{{mins}}</select>'),

        render: function() {
            function pad(n) {
                return n < 10 ? '0' + n : n
            }

            //Render the date element first
            exports.Date.prototype.render.call(this);

            //Setup hour options
            var hours = _.range(0, 24),
                hoursOptions = [];

            _.each(hours, function(hour) {
                hoursOptions.push('<option value="'+hour+'">' + pad(hour) + '</option>');
            });

            //Setup minute options
            var mins = _.range(0, 60, 15),
                minsOptions = [];

            _.each(mins, function(min) {
                minsOptions.push('<option value="'+min+'">' + pad(min) + '</option>');
            });

            //Render time selects
            $(this.el).append(this.template({
                hours: hoursOptions.join(),
                mins: minsOptions.join()
            }));

            //Store references to selects
            this.$hours = $('select:eq(0)', this.el);
            this.$mins = $('select:eq(1)', this.el);

            //Set time
            var time = this.value;
            this.$hours.val(time.getHours());
            this.$mins.val(time.getMinutes());

            return this;
        },

        /**
        * @return {Date}   Selected datetime
        */
        getValue: function() {
            var input = $('input', this.el),
                date = input.datepicker('getDate');

            date.setHours(this.$hours.val());
            date.setMinutes(this.$mins.val());
            date.setMilliseconds(0);

            return date;
        }

    });

    exports.List = Base.extend({

        className: 'bbf-list',

        //Note: The extra div around the
 is used to limit the drag area
        template: createTemplate('\

\

<button class="add">Add
\
        '),

        itemTemplate: createTemplate('\

\
                {{text}}\

\
                    <button class="edit">Edit</button>\
                    <button class="del">Delete</button>\

\

\
        '),

        events: {
            'click .add':   'addNewItem',
            'click .edit':  'editItem',
            'click .del':   'deleteItem'
        },

        initialize: function(options) {
            Base.prototype.initialize.call(this, options);

            if (!this.schema) throw "Missing required option 'schema'";

            this.items = [];
        },

        render: function() {
            //Main element
            $(this.el).html(this.template());

            //Create list
            var self = this,
                data = this.value || [],
                schema = this.schema,
                itemToString = this.itemToString,
                itemTemplate = this.itemTemplate,
                listEl = $('ul', this.el);

            _.each(data, function(itemData) {
                var text = itemToString.call(self, itemData);

                //Create DOM element
                var li = $(itemTemplate({ text: text }));

                //Attach data
                $.data(li[0], 'data', itemData);

                listEl.append(li);
            });

            //Make sortable
            listEl.sortable({
                axis: 'y',
                cursor: 'move',
                containment: 'parent'
            });

            //jQuery UI buttonize
            $('button.add', this.el).button({
                text: false,
                icons: { primary: 'ui-icon-plus' }
            });
            $('button.edit', this.el).button({
                text: false,
                icons: { primary: 'ui-icon-pencil' }
            });
            $('button.del', this.el).button({
                text: false,
                icons: { primary: 'ui-icon-trash' }
            });

            return this;
        },

        /**
         * Formats an item for display in the list
         * For example objects, dates etc. can have a custom
         * itemToString method which says how it should be formatted.
         */
        itemToString: function(data) {
            if (!data) return data;

            var transform = this.schema.itemToString;

            return transform ? transform(data) : data;
        },

        /**
         * Add a new item to the list if it is completed in the editor
         */
        addNewItem: function(event) {
            var self = this;

            this.openEditor(null, function(value) {
                var text = self.itemToString(value);

                //Create DOM element
                var li = $(self.itemTemplate({ text: text }));

                //Store data
                $.data(li[0], 'data', value);

                $('ul', self.el).append(li);

                //jQuery UI buttonize
                $('button.edit', this.el).button({
                    text: false,
                    icons: { primary: 'ui-icon-pencil' }
                });
                $('button.del', this.el).button({
                    text: false,
                    icons: { primary: 'ui-icon-trash' }
                });
            });
        },

        /**
         * Edit an existing item in the list
         */
        editItem: function(event) {
            console.log('edit');

            var self = this,
                li = $(event.target).closest('li'),
                originalValue = $.data(li[0], 'data');

            this.openEditor(originalValue, function(newValue) {
                //Update display
                $('.text', li).html(self.itemToString(newValue));

                //Store data
                $.data(li[0], 'data', newValue);
            });
        },

        deleteItem: function(event) {
            console.log('delete');

            var li = $(event.target).closest('li');

            li.remove();
        },

        /**
         * Opens the sub editor dialog
         * @param {Mixed}       Data (if editing existing list item, null otherwise)
         * @param {Function}    Save callback. receives: value
         */
        openEditor: function(data, callback) {
            console.log('openEditor');

            var self = this,
                schema = this.schema,
                listType = schema.listType || 'TextField';

            var editor = Form.helpers.createEditor(listType, {
                key: '',
                schema: schema,
                value: data
            }).render();

            var close = function() {
                $(editor.el).dialog('close');

                editor.remove();
            };

            $(editor.el).dialog({
                resizable:  false,
                modal:      true,
                width:      500,
                title:      data ? 'Edit item' : 'New item',
                buttons: {
                    'OK': function() {
                        callback(editor.getValue());
                        close();
                    },
                    'Cancel': close
                }
            });
        },

        getValue: function() {
            var data = [];

            $('li', this.el).each(function(index, li) {
                data.push($.data(li, 'data'));
            });

            return data;
        }

    });

    //Exports
    _.extend(Form.editors, exports);

})();
<|endoftext|>


<commit_before>// iCountDown.js
// Version : v0.0.1

(function($){

    var methods = {
        init : function(options) {
            var defaults = {
                future      : new Date("June 30 2018 21:15:00 GMT+0200"),  // default date to count down
                seconds_sel : '#seconds',
                minutes_sel : '#minutes',
                hours_sel   : '#hours',
                days_sel    : '#days'
            };
            var options = $.extend(defaults, options);
            var o = options;
            setInterval(function(){
                newClock(o);
            }, 1000);
        },
    };

    $.fn.icountdown = function(methodOrOptions) {
        if(methods[methodOrOptions]){
            //Methods
            //this.data('icountdown', $.extend(true, {}, defaults, methodOrOptions));
            return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
        }else if(typeof methodOrOptions === 'object' || ! methodOrOptions){
            // Default to "init"

            //this.data('icountdown', $.extend(true, {}, defaults, methodOrOptions));
            //var arguments = $.extend(defaults, methodOrOptions); console.log();
            return methods.init.apply(this, arguments);
        }else{
            //Error
            $.error('Method ' +  methodOrOptions + ' does not exist on jQuery.icountdown');
        }
    };

    function newClock(params) {
        var future      = params.future;
        var now         = new Date();
        var difference  = Math.floor((future.getTime() - now.getTime()) / 1000);

        var seconds = fixIntegers(difference % 60);
        difference = Math.floor(difference / 60);

        var minutes = fixIntegers(difference % 60);
        difference = Math.floor(difference / 60);

        var hours = fixIntegers(difference % 24);
        difference = Math.floor(difference / 24);

        var days = difference;

        $(params.seconds_sel).text(seconds);
        $(params.minutes_sel).text(minutes);
        $(params.hours_sel).text(hours);
        $(params.days_sel).text(days);
    };

    function fixIntegers(integer){
        if (integer < 0){
            integer = 0;
        }
        if (integer < 10){
            return "0" + integer;
        }
        return "" + integer;
    }

})(jQuery);<commit_msg>Little fix on our icountdown credits<commit_after>/*!
 * jquery.icountdown.js | jQuery Count Down Plugin v0.0.1
 *
 * https://github.com/iJos/jquery.icountdown.js
 *
 * Copyright 2015 Jose Luis Jimenez | @iJos
 *
 * Released under MIT License
 */

(function($){

    var methods = {
        init : function(options) {
            var defaults = {
                future      : new Date("June 30 2018 21:15:00 GMT+0200"),  // default date to count down
                seconds_sel : '#seconds',
                minutes_sel : '#minutes',
                hours_sel   : '#hours',
                days_sel    : '#days'
            };
            var options = $.extend(defaults, options);
            var o = options;
            setInterval(function(){
                newClock(o);
            }, 1000);
        },
    };

    $.fn.icountdown = function(methodOrOptions) {
        if(methods[methodOrOptions]){
            //Methods
            //this.data('icountdown', $.extend(true, {}, defaults, methodOrOptions));
            return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
        }else if(typeof methodOrOptions === 'object' || ! methodOrOptions){
            // Default to "init"

            //this.data('icountdown', $.extend(true, {}, defaults, methodOrOptions));
            //var arguments = $.extend(defaults, methodOrOptions); console.log();
            return methods.init.apply(this, arguments);
        }else{
            //Error
            $.error('Method ' +  methodOrOptions + ' does not exist on jQuery.icountdown');
        }
    };

    function newClock(params) {
        var future      = params.future;
        var now         = new Date();
        var difference  = Math.floor((future.getTime() - now.getTime()) / 1000);

        var seconds = fixIntegers(difference % 60);
        difference = Math.floor(difference / 60);

        var minutes = fixIntegers(difference % 60);
        difference = Math.floor(difference / 60);

        var hours = fixIntegers(difference % 24);
        difference = Math.floor(difference / 24);

        var days = difference;

        $(params.seconds_sel).text(seconds);
        $(params.minutes_sel).text(minutes);
        $(params.hours_sel).text(hours);
        $(params.days_sel).text(days);
    };

    function fixIntegers(integer){
        if (integer < 0){
            integer = 0;
        }
        if (integer < 10){
            return "0" + integer;
        }
        return "" + integer;
    }

})(jQuery);<|endoftext|>


<commit_before>/*jslint browser:true, plusplus:true, vars:true */
/*jshint browser:true, jquery:true */
/*jshint -W040:false */ /* to don't alert on "this" in triggerLoad and triggerError */

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

    // options
    var options = {
            autoInit: true,
            selector: 'img',
            srcAttr: 'data-src',
            classNojs: 'lazy',
            blankImage: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
            edgeX: 0,
            edgeY: 0,
            throttle: 99,
            visibleOnly: true,
            loadEvent: 'pageshow', // check AJAX-loaded content in jQueryMobile
            updateEvent: 'load orientationchange resize scroll', // page-modified events
            forceEvent: '', // force loading of all elements
            oninit: null, // init handler
            onshow: null, // start loading handler
            onload: null, // load success handler
            onerror: null // error handler
        },
        $window = $(window),
        elements = [],
        viewportTop,
        viewportBottom,
        viewportLeft,
        viewportRight,
        topLazy = 0,
    /*
     waitingMode=0 : no setTimeout
     waitingMode=1 : setTimeout, no deferred events
     waitingMode=2 : setTimeout, deferred events
     */
        waitingMode = 0;

    $.lazyLoadXT = $.extend(options, $.lazyLoadXT);

    /**
     * Add new elements to lazy-load list:
     * $(elements).lazyLoadXT() or $(window).lazyLoadXT()
     */
    $.fn.lazyLoadXT = function (overrides) {
        overrides = overrides || {};

        var blankImage = overrides.blankImage || options.blankImage,
            classNojs = overrides.classNojs || options.classNojs;

        return this.each(function () {
            if (this === window) {
                $(options.selector).lazyLoadXT();
                return;
            }

            var $el = $(this);

            // prevent duplicates
            if ($el.data('lazied')) {
                return;
            }

            $el
                .data('lazied', 1)
                .removeClass(classNojs);

            if (blankImage && $el[0].tagName === 'IMG' && !$el.attr('src')) {
                $el.attr('src', blankImage);
            }

            triggerEvent('init', $el);

            var objdata = {o: $el};
            $.each(['srcAttr', 'edgeX', 'edgeY', 'visibleOnly'], function (i, name) {
                objdata[name] = overrides[name] || options[name];
            });
            elements.unshift(objdata); // push it in the first position as we iterate elements in reverse order
        });
    };

    /**
     * Save visible viewport boundary to viewportXXX variables
     */
    function calcViewport() {
        viewportTop = $window.scrollTop();
        viewportBottom = viewportTop + (window.innerHeight || $window.height());

        viewportLeft = window.pageXOffset || 0;
        viewportRight = viewportLeft + (window.innerWidth || $window.width());
    }

    /**
     * Process function/object event handler
     * @param {string} event suffix
     * @param {jQuery} $el
     */
    function triggerEvent(event, $el) {
        $el.trigger('lazy' + event);

        var handler = options['on' + event];
        if (handler) {
            if ($.isFunction(handler)) {
                handler.call($el[0]);
            } else {
                $el
                    .addClass(handler.addClass)
                    .removeClass(handler.removeClass);
            }
        }

        // queue next check as images may be resized after loading of actual file
        queueCheckLazyElements();
    }

    /**
     * Trigger onload handler
     */
    function triggerLoad() {
        triggerEvent('load', $(this));
    }

    /**
     * Trigger onerror handler
     */
    function triggerError() {
        triggerEvent('error', $(this));
    }

    /**
     * Load visible elements
     * @param {bool} [force] loading of all elements
     */
    function checkLazyElements(force) {
        if (!elements.length) {
            return;
        }

        topLazy = Infinity;
        calcViewport();

        for (var i = elements.length - 1; i >= 0; i--) {
            var objData = elements[i],
                $el = objData.o,
                el = $el[0];

            // remove items that are not in DOM
            if (!$.contains(document.body, el)) {
                elements.splice(i, 1);
            } else if (force || !objData.visibleOnly || el.offsetWidth > 0 || el.offsetHeight > 0) {
                var offset = $el.offset(),
                    elTop = offset.top,
                    elLeft = offset.left,
                    topEdge = elTop - objData.edgeY;

                if (force ||
                    ((topEdge < viewportBottom) && (elTop + $el.height() > viewportTop - objData.edgeY) &&
                        (elLeft < viewportRight + objData.edgeX) && (elLeft + $el.width() > viewportLeft - objData.edgeX))) {

                    triggerEvent('show', $el);

                    var srcAttr = objData.srcAttr,
                        src = $.isFunction(srcAttr) ? srcAttr($el) : $el.attr(srcAttr);
                    if (src) {
                        $el
                            .on('load', triggerLoad)
                            .on('error', triggerError)
                            .attr('src', src);
                    }

                    elements.splice(i, 1);
                } else {
                    if (topEdge < topLazy) {
                        topLazy = topEdge;
                    }
                }
            }
        }

        if (!elements.length) {
            $(document).trigger('lazyloadall');
        }
    }

    /**
     * Run check of lazy elements after timeout
     */
    function timeoutLazyElements() {
        if (waitingMode > 1) {
            waitingMode = 1;
            checkLazyElements();
            setTimeout(timeoutLazyElements, options.throttle);
        } else {
            waitingMode = 0;
        }
    }

    /**
     * Queue check of lazy elements because of event e
     * @param {Event} [e]
     */
    function queueCheckLazyElements(e) {
        if (!elements.length) {
            return;
        }

        // fast check for scroll event without new visible elements
        if (e && e.type === 'scroll') {
            calcViewport();
            if (topLazy >= viewportBottom) {
                return;
            }
        }

        if (!waitingMode) {
            setTimeout(timeoutLazyElements, 0);
        }

        waitingMode = 2;
    }

    /**
     * Initialize list of hidden elements
     */
    function initLazyElements() {
        $(window).lazyLoadXT();
    }

    /**
     * Loading of all elements
     */
    function forceLoadAll() {
        checkLazyElements(true);
    }

    /**
     * Initialization
     */
    $(document).ready(function () {
        $window
            .on(options.loadEvent, initLazyElements)
            .on(options.updateEvent, queueCheckLazyElements)
            .on(options.forceEvent, forceLoadAll);

        if (options.autoInit) {
            initLazyElements(); // standard initialization
        }
    });

})(window.jQuery || window.Zepto, window, document);
<commit_msg>fix triggering recheck after initLazyElements<commit_after>/*jslint browser:true, plusplus:true, vars:true */
/*jshint browser:true, jquery:true */
/*jshint -W040:false */ /* to don't alert on "this" in triggerLoad and triggerError */

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

    // options
    var options = {
            autoInit: true,
            selector: 'img',
            srcAttr: 'data-src',
            classNojs: 'lazy',
            blankImage: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
            edgeX: 0,
            edgeY: 0,
            throttle: 99,
            visibleOnly: true,
            loadEvent: 'pageshow', // check AJAX-loaded content in jQueryMobile
            updateEvent: 'load orientationchange resize scroll', // page-modified events
            forceEvent: '', // force loading of all elements
            oninit: null, // init handler
            onshow: null, // start loading handler
            onload: null, // load success handler
            onerror: null // error handler
        },
        $window = $(window),
        elements = [],
        viewportTop,
        viewportBottom,
        viewportLeft,
        viewportRight,
        topLazy = 0,
    /*
     waitingMode=0 : no setTimeout
     waitingMode=1 : setTimeout, no deferred events
     waitingMode=2 : setTimeout, deferred events
     */
        waitingMode = 0;

    $.lazyLoadXT = $.extend(options, $.lazyLoadXT);

    /**
     * Add new elements to lazy-load list:
     * $(elements).lazyLoadXT() or $(window).lazyLoadXT()
     */
    $.fn.lazyLoadXT = function (overrides) {
        overrides = overrides || {};

        var blankImage = overrides.blankImage || options.blankImage,
            classNojs = overrides.classNojs || options.classNojs;

        return this.each(function () {
            if (this === window) {
                $(options.selector).lazyLoadXT();
                return;
            }

            var $el = $(this);

            // prevent duplicates
            if ($el.data('lazied')) {
                return;
            }

            $el
                .data('lazied', 1)
                .removeClass(classNojs);

            if (blankImage && $el[0].tagName === 'IMG' && !$el.attr('src')) {
                $el.attr('src', blankImage);
            }

            triggerEvent('init', $el);

            var objdata = {o: $el};
            $.each(['srcAttr', 'edgeX', 'edgeY', 'visibleOnly'], function (i, name) {
                objdata[name] = overrides[name] || options[name];
            });
            elements.unshift(objdata); // push it in the first position as we iterate elements in reverse order
        });
    };

    /**
     * Save visible viewport boundary to viewportXXX variables
     */
    function calcViewport() {
        viewportTop = $window.scrollTop();
        viewportBottom = viewportTop + (window.innerHeight || $window.height());

        viewportLeft = window.pageXOffset || 0;
        viewportRight = viewportLeft + (window.innerWidth || $window.width());
    }

    /**
     * Process function/object event handler
     * @param {string} event suffix
     * @param {jQuery} $el
     */
    function triggerEvent(event, $el) {
        $el.trigger('lazy' + event);

        var handler = options['on' + event];
        if (handler) {
            if ($.isFunction(handler)) {
                handler.call($el[0]);
            } else {
                $el
                    .addClass(handler.addClass)
                    .removeClass(handler.removeClass);
            }
        }

        // queue next check as images may be resized after loading of actual file
        queueCheckLazyElements();
    }

    /**
     * Trigger onload handler
     */
    function triggerLoad() {
        triggerEvent('load', $(this));
    }

    /**
     * Trigger onerror handler
     */
    function triggerError() {
        triggerEvent('error', $(this));
    }

    /**
     * Load visible elements
     * @param {bool} [force] loading of all elements
     */
    function checkLazyElements(force) {
        if (!elements.length) {
            return;
        }

        topLazy = Infinity;
        calcViewport();

        for (var i = elements.length - 1; i >= 0; i--) {
            var objData = elements[i],
                $el = objData.o,
                el = $el[0];

            // remove items that are not in DOM
            if (!$.contains(document.body, el)) {
                elements.splice(i, 1);
            } else if (force || !objData.visibleOnly || el.offsetWidth > 0 || el.offsetHeight > 0) {
                var offset = $el.offset(),
                    elTop = offset.top,
                    elLeft = offset.left,
                    topEdge = elTop - objData.edgeY;

                if (force ||
                    ((topEdge < viewportBottom) && (elTop + $el.height() > viewportTop - objData.edgeY) &&
                        (elLeft < viewportRight + objData.edgeX) && (elLeft + $el.width() > viewportLeft - objData.edgeX))) {

                    triggerEvent('show', $el);

                    var srcAttr = objData.srcAttr,
                        src = $.isFunction(srcAttr) ? srcAttr($el) : $el.attr(srcAttr);
                    if (src) {
                        $el
                            .on('load', triggerLoad)
                            .on('error', triggerError)
                            .attr('src', src);
                    }

                    elements.splice(i, 1);
                } else {
                    if (topEdge < topLazy) {
                        topLazy = topEdge;
                    }
                }
            }
        }

        if (!elements.length) {
            $(document).trigger('lazyloadall');
        }
    }

    /**
     * Run check of lazy elements after timeout
     */
    function timeoutLazyElements() {
        if (waitingMode > 1) {
            waitingMode = 1;
            checkLazyElements();
            setTimeout(timeoutLazyElements, options.throttle);
        } else {
            waitingMode = 0;
        }
    }

    /**
     * Queue check of lazy elements because of event e
     * @param {Event} [e]
     */
    function queueCheckLazyElements(e) {
        if (!elements.length) {
            return;
        }

        // fast check for scroll event without new visible elements
        if (e && e.type === 'scroll') {
            calcViewport();
            if (topLazy >= viewportBottom) {
                return;
            }
        }

        if (!waitingMode) {
            setTimeout(timeoutLazyElements, 0);
        }

        waitingMode = 2;
    }

    /**
     * Initialize list of hidden elements
     */
    function initLazyElements() {
        $(window).lazyLoadXT();
        queueCheckLazyElements();
    }

    /**
     * Loading of all elements
     */
    function forceLoadAll() {
        checkLazyElements(true);
    }

    /**
     * Initialization
     */
    $(document).ready(function () {
        $window
            .on(options.loadEvent, initLazyElements)
            .on(options.updateEvent, queueCheckLazyElements)
            .on(options.forceEvent, forceLoadAll);

        if (options.autoInit) {
            initLazyElements(); // standard initialization
        }
    });

})(window.jQuery || window.Zepto, window, document);
<|endoftext|>


<commit_before>/*jslint browser:true, plusplus:true, vars:true */
/*jshint browser:true, jquery:true */
/*jshint -W040:false */ /* to don't alert on "this" in triggerLoadOrError */

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

    // options
    var lazyLoadXT = 'lazyLoadXT',
        dataLazied = 'lazied',
        load_error = 'load error',
        classLazyHidden = 'lazy-hidden',
        docElement = document.documentElement || document.body,
    //  force load all images in Opera Mini and some mobile browsers without scroll event or getBoundingClientRect()
        forceLoad = (window.onscroll === undefined || !!window.operamini || !docElement.getBoundingClientRect),
        options = {
            autoInit: true, // auto initialize in $.ready
            selector: 'img[data-src]', // selector for lazyloading elements
            blankImage: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
            throttle: 99, // interval (ms) for changes check
            forceLoad: forceLoad, // force auto load all images

            loadEvent: 'pageshow', // check AJAX-loaded content in jQueryMobile
            updateEvent: 'load orientationchange resize scroll touchmove', // page-modified events
            forceEvent: '', // force loading of all elements

            oninit: {removeClass: 'lazy'}, // init handler
            onshow: {addClass: classLazyHidden}, // start loading handler
            onload: {removeClass: classLazyHidden, addClass: 'lazy-loaded'}, // load success handler
            onerror: {removeClass: classLazyHidden}, // error handler
            oncomplete: null, // complete handler

            //scrollContainer: undefined,
            checkDuplicates: true
        },
        elementOptions = {
            srcAttr: 'data-src',
            edgeX: 0,
            edgeY: 0,
            visibleOnly: true
        },
        $window = $(window),
        $isFunction = $.isFunction,
        $extend = $.extend,
        $data = $.data || function (el, name) {
            return $(el).data(name);
        },
        elements = [],
        topLazy = 0,
    /*
     waitingMode=0 : no setTimeout
     waitingMode=1 : setTimeout, no deferred events
     waitingMode=2 : setTimeout, deferred events
     */
        waitingMode = 0;

    $[lazyLoadXT] = $extend(options, elementOptions, $[lazyLoadXT]);

    /**
     * Return options.prop if obj.prop is undefined, otherwise return obj.prop
     * @param {*} obj
     * @param {*} prop
     * @returns *
     */
    function getOrDef(obj, prop) {
        return obj[prop] === undefined ? options[prop] : obj[prop];
    }

    /**
     * Add new elements to lazy-load list:
     * $(elements).lazyLoadXT() or $(window).lazyLoadXT()
     *
     * @param {object} [overrides] override global options
     */
    $.fn[lazyLoadXT] = function (overrides) {
        overrides = overrides || {};

        var blankImage = getOrDef(overrides, 'blankImage'),
            checkDuplicates = getOrDef(overrides, 'checkDuplicates'),
            scrollContainer = getOrDef(overrides, 'scrollContainer'),
            elementOptionsOverrides = {},
            prop;

        // empty overrides.scrollContainer is supported by both jQuery and Zepto
        $(scrollContainer).on('scroll', queueCheckLazyElements);

        for (prop in elementOptions) {
            elementOptionsOverrides[prop] = getOrDef(overrides, prop);
        }

        return this.each(function () {
            if (this === window) {
                $(options.selector).lazyLoadXT(overrides);
            } else {
                // prevent duplicates
                if (checkDuplicates && $data(this, dataLazied)) {
                    return;
                }

                var $el = $(this).data(dataLazied, 1);

                if (blankImage && $el[0].tagName === 'IMG' && !this.src) {
                    this.src = blankImage;
                }

                // clone elementOptionsOverrides object
                $el[lazyLoadXT] = $extend({}, elementOptionsOverrides);

                triggerEvent('init', $el);

                elements.push($el);
            }
        });
    };

    /**
     * Process function/object event handler
     * @param {string} event suffix
     * @param {jQuery} $el
     */
    function triggerEvent(event, $el) {
        var handler = options['on' + event];
        if (handler) {
            if ($isFunction(handler)) {
                handler.call($el[0]);
            } else {
                $el
                    .addClass(handler.addClass || '')
                    .removeClass(handler.removeClass || '');
            }
        }

        $el.trigger('lazy' + event, [$el]);

        // queue next check as images may be resized after loading of actual file
        queueCheckLazyElements();
    }

    /**
     * Trigger onload/onerror handler
     * @param {Event} e
     */
    function triggerLoadOrError(e) {
        triggerEvent(e.type, $(this).off(load_error, triggerLoadOrError));
    }

    /**
     * Load visible elements
     * @param {bool} [force] loading of all elements
     */
    function checkLazyElements(force) {
        if (!elements.length) {
            return;
        }

        force = force || options.forceLoad;

        topLazy = Infinity;

        var viewportTop = $window.scrollTop(),
            viewportHeight = window.innerHeight || $window.height(),
            viewportWidth = window.innerWidth || $window.width(),
            i,
            length;

        for (i = 0, length = elements.length; i < length; i++) {
            var $el = elements[i],
                el = $el[0],
                objData = $el[lazyLoadXT],
                removeNode = false,
                visible = force,
                topEdge;

            // remove items that are not in DOM
            if (!$.contains(docElement, el)) {
                removeNode = true;
            } else if (force || !objData.visibleOnly || el.offsetWidth || el.offsetHeight) {

                if (!visible) {
                    var elPos = el.getBoundingClientRect(),
                        edgeX = objData.edgeX,
                        edgeY = objData.edgeY;

                    topEdge = (elPos.top + viewportTop - edgeY) - viewportHeight;

                    visible = (topEdge <= viewportTop && elPos.bottom > -edgeY &&
                        elPos.left <= viewportWidth + edgeX && elPos.right > -edgeX);
                }

                if (visible) {
                    triggerEvent('show', $el);

                    var srcAttr = objData.srcAttr,
                        src = $isFunction(srcAttr) ? srcAttr($el) : el.getAttribute(srcAttr);
                    if (src) {
                        $el.on(load_error, triggerLoadOrError);
                        el.src = src;
                    }

                    removeNode = true;
                } else {
                    if (topEdge < topLazy) {
                        topLazy = topEdge;
                    }
                }
            }

            if (removeNode) {
                elements.splice(i--, 1);
                length--;
            }
        }

        if (!length) {
            triggerEvent('complete', $(docElement));
        }
    }

    /**
     * Run check of lazy elements after timeout
     */
    function timeoutLazyElements() {
        if (waitingMode > 1) {
            waitingMode = 1;
            checkLazyElements();
            setTimeout(timeoutLazyElements, options.throttle);
        } else {
            waitingMode = 0;
        }
    }

    /**
     * Queue check of lazy elements because of event e
     * @param {Event} [e]
     */
    function queueCheckLazyElements(e) {
        if (!elements.length) {
            return;
        }

        // fast check for scroll event without new visible elements
        if (e && e.type === 'scroll' && e.currentTarget === window) {
            if (topLazy >= $window.scrollTop()) {
                return;
            }
        }

        if (!waitingMode) {
            setTimeout(timeoutLazyElements, 0);
        }
        waitingMode = 2;
    }

    /**
     * Initialize list of hidden elements
     */
    function initLazyElements() {
        $window.lazyLoadXT();
        queueCheckLazyElements();
    }

    /**
     * Loading of all elements
     */
    function forceLoadAll() {
        checkLazyElements(true);
    }

    /**
     * Initialization
     */
    $(document).ready(function () {
        $window
            .on(options.loadEvent, initLazyElements)
            .on(options.updateEvent, queueCheckLazyElements)
            .on(options.forceEvent, forceLoadAll);

        if (options.autoInit) {
            initLazyElements(); // standard initialization
        }
    });

})(window.jQuery || window.Zepto, window, document);
<commit_msg>comment oncomplete property to reduce minified size (currently null and undefined have identical effect)<commit_after>/*jslint browser:true, plusplus:true, vars:true */
/*jshint browser:true, jquery:true */
/*jshint -W040:false */ /* to don't alert on "this" in triggerLoadOrError */

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

    // options
    var lazyLoadXT = 'lazyLoadXT',
        dataLazied = 'lazied',
        load_error = 'load error',
        classLazyHidden = 'lazy-hidden',
        docElement = document.documentElement || document.body,
    //  force load all images in Opera Mini and some mobile browsers without scroll event or getBoundingClientRect()
        forceLoad = (window.onscroll === undefined || !!window.operamini || !docElement.getBoundingClientRect),
        options = {
            autoInit: true, // auto initialize in $.ready
            selector: 'img[data-src]', // selector for lazyloading elements
            blankImage: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
            throttle: 99, // interval (ms) for changes check
            forceLoad: forceLoad, // force auto load all images

            loadEvent: 'pageshow', // check AJAX-loaded content in jQueryMobile
            updateEvent: 'load orientationchange resize scroll touchmove', // page-modified events
            forceEvent: '', // force loading of all elements

            oninit: {removeClass: 'lazy'}, // init handler
            onshow: {addClass: classLazyHidden}, // start loading handler
            onload: {removeClass: classLazyHidden, addClass: 'lazy-loaded'}, // load success handler
            onerror: {removeClass: classLazyHidden}, // error handler
            //oncomplete: null, // complete handler

            //scrollContainer: undefined,
            checkDuplicates: true
        },
        elementOptions = {
            srcAttr: 'data-src',
            edgeX: 0,
            edgeY: 0,
            visibleOnly: true
        },
        $window = $(window),
        $isFunction = $.isFunction,
        $extend = $.extend,
        $data = $.data || function (el, name) {
            return $(el).data(name);
        },
        elements = [],
        topLazy = 0,
    /*
     waitingMode=0 : no setTimeout
     waitingMode=1 : setTimeout, no deferred events
     waitingMode=2 : setTimeout, deferred events
     */
        waitingMode = 0;

    $[lazyLoadXT] = $extend(options, elementOptions, $[lazyLoadXT]);

    /**
     * Return options.prop if obj.prop is undefined, otherwise return obj.prop
     * @param {*} obj
     * @param {*} prop
     * @returns *
     */
    function getOrDef(obj, prop) {
        return obj[prop] === undefined ? options[prop] : obj[prop];
    }

    /**
     * Add new elements to lazy-load list:
     * $(elements).lazyLoadXT() or $(window).lazyLoadXT()
     *
     * @param {object} [overrides] override global options
     */
    $.fn[lazyLoadXT] = function (overrides) {
        overrides = overrides || {};

        var blankImage = getOrDef(overrides, 'blankImage'),
            checkDuplicates = getOrDef(overrides, 'checkDuplicates'),
            scrollContainer = getOrDef(overrides, 'scrollContainer'),
            elementOptionsOverrides = {},
            prop;

        // empty overrides.scrollContainer is supported by both jQuery and Zepto
        $(scrollContainer).on('scroll', queueCheckLazyElements);

        for (prop in elementOptions) {
            elementOptionsOverrides[prop] = getOrDef(overrides, prop);
        }

        return this.each(function () {
            if (this === window) {
                $(options.selector).lazyLoadXT(overrides);
            } else {
                // prevent duplicates
                if (checkDuplicates && $data(this, dataLazied)) {
                    return;
                }

                var $el = $(this).data(dataLazied, 1);

                if (blankImage && $el[0].tagName === 'IMG' && !this.src) {
                    this.src = blankImage;
                }

                // clone elementOptionsOverrides object
                $el[lazyLoadXT] = $extend({}, elementOptionsOverrides);

                triggerEvent('init', $el);

                elements.push($el);
            }
        });
    };

    /**
     * Process function/object event handler
     * @param {string} event suffix
     * @param {jQuery} $el
     */
    function triggerEvent(event, $el) {
        var handler = options['on' + event];
        if (handler) {
            if ($isFunction(handler)) {
                handler.call($el[0]);
            } else {
                $el
                    .addClass(handler.addClass || '')
                    .removeClass(handler.removeClass || '');
            }
        }

        $el.trigger('lazy' + event, [$el]);

        // queue next check as images may be resized after loading of actual file
        queueCheckLazyElements();
    }

    /**
     * Trigger onload/onerror handler
     * @param {Event} e
     */
    function triggerLoadOrError(e) {
        triggerEvent(e.type, $(this).off(load_error, triggerLoadOrError));
    }

    /**
     * Load visible elements
     * @param {bool} [force] loading of all elements
     */
    function checkLazyElements(force) {
        if (!elements.length) {
            return;
        }

        force = force || options.forceLoad;

        topLazy = Infinity;

        var viewportTop = $window.scrollTop(),
            viewportHeight = window.innerHeight || $window.height(),
            viewportWidth = window.innerWidth || $window.width(),
            i,
            length;

        for (i = 0, length = elements.length; i < length; i++) {
            var $el = elements[i],
                el = $el[0],
                objData = $el[lazyLoadXT],
                removeNode = false,
                visible = force,
                topEdge;

            // remove items that are not in DOM
            if (!$.contains(docElement, el)) {
                removeNode = true;
            } else if (force || !objData.visibleOnly || el.offsetWidth || el.offsetHeight) {

                if (!visible) {
                    var elPos = el.getBoundingClientRect(),
                        edgeX = objData.edgeX,
                        edgeY = objData.edgeY;

                    topEdge = (elPos.top + viewportTop - edgeY) - viewportHeight;

                    visible = (topEdge <= viewportTop && elPos.bottom > -edgeY &&
                        elPos.left <= viewportWidth + edgeX && elPos.right > -edgeX);
                }

                if (visible) {
                    triggerEvent('show', $el);

                    var srcAttr = objData.srcAttr,
                        src = $isFunction(srcAttr) ? srcAttr($el) : el.getAttribute(srcAttr);
                    if (src) {
                        $el.on(load_error, triggerLoadOrError);
                        el.src = src;
                    }

                    removeNode = true;
                } else {
                    if (topEdge < topLazy) {
                        topLazy = topEdge;
                    }
                }
            }

            if (removeNode) {
                elements.splice(i--, 1);
                length--;
            }
        }

        if (!length) {
            triggerEvent('complete', $(docElement));
        }
    }

    /**
     * Run check of lazy elements after timeout
     */
    function timeoutLazyElements() {
        if (waitingMode > 1) {
            waitingMode = 1;
            checkLazyElements();
            setTimeout(timeoutLazyElements, options.throttle);
        } else {
            waitingMode = 0;
        }
    }

    /**
     * Queue check of lazy elements because of event e
     * @param {Event} [e]
     */
    function queueCheckLazyElements(e) {
        if (!elements.length) {
            return;
        }

        // fast check for scroll event without new visible elements
        if (e && e.type === 'scroll' && e.currentTarget === window) {
            if (topLazy >= $window.scrollTop()) {
                return;
            }
        }

        if (!waitingMode) {
            setTimeout(timeoutLazyElements, 0);
        }
        waitingMode = 2;
    }

    /**
     * Initialize list of hidden elements
     */
    function initLazyElements() {
        $window.lazyLoadXT();
        queueCheckLazyElements();
    }

    /**
     * Loading of all elements
     */
    function forceLoadAll() {
        checkLazyElements(true);
    }

    /**
     * Initialization
     */
    $(document).ready(function () {
        $window
            .on(options.loadEvent, initLazyElements)
            .on(options.updateEvent, queueCheckLazyElements)
            .on(options.forceEvent, forceLoadAll);

        if (options.autoInit) {
            initLazyElements(); // standard initialization
        }
    });

})(window.jQuery || window.Zepto, window, document);
<|endoftext|>


<commit_before>! function($) {
  $.fn.stylewords = function() {

    return this.each(function() {
      var words = $(this).text().split(' ');
      var wrapper = $('').text(words.shift());
      wrapper = $('
').append(wrapper).html();
      $(this).html(function() {
        return [wrapper].concat(words).join(' ');
      });
    });

  };

}(jQuery);<commit_msg>refactor plugin<commit_after>! function($) {
  $.fn.stylewords = function() {
    return this.each(function() {
      var el = $(this);
      el.html(function() {
        var words = el.text().split(' ');
        var wrapper = $('').text(words.shift());
        wrapper = $('
').append(wrapper).html();
        return [wrapper].concat(words).join(' ');
      });
    });
  };
}(jQuery);<|endoftext|>