<commit_before>/**
 * The Pagination widget provides a set of controls to navigate through paged
 * data.
 *
 * @module aui-pagination
 */

var Lang = A.Lang,
    isBoolean = Lang.isBoolean,
    isFunction = Lang.isFunction,
    isNumber = Lang.isNumber,

    ACTIVE = 'active',
    BOUNDING_BOX = 'boundingBox',
    CHANGE_REQUEST = 'changeRequest',
    CIRCULAR = 'circular',
    CLICK = 'click',
    CONTENT_BOX = 'contentBox',
    CONTROL = 'control',
    DISABLED = 'disabled',
    FORMATTER = 'formatter',
    ITEMS = 'items',
    LI = 'li',
    NEXT = 'next',
    OFFSET = 'offset',
    PAGE = 'page',
    PAGINATION = 'pagination',
    PREV = 'prev',
    TOTAL = 'total',

    getCN = A.getClassName,

    CSS_ACTIVE = getCN(ACTIVE),
    CSS_DISABLED = getCN(DISABLED),
    CSS_PAGINATION_CONTROL = getCN(PAGINATION, CONTROL);

/**
 * A base class for Pagination, providing:
 *
 * - Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)
 * - Set of controls to navigate through paged data
 *
 * Check the [live demo](http://alloyui.com/examples/pagination/).
 *
 * @class A.Pagination
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 * @include http://alloyui.com/examples/pagination/basic-markup.html
 * @include http://alloyui.com/examples/pagination/basic.js
 */
var Pagination = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: PAGINATION,

    /**
     * Static property used to define the default attribute configuration for
     * the `A.Pagination`.
     *
     * @property ATTRS
     * @type {Object}
     * @static
     */
    ATTRS: {

        /**
         * When enabled this property allows the navigation to go back to the
         * beggining when it reaches the last page, the opposite behavior is
         * also true. Incremental page navigation could happen clicking the
         * control arrows or invoking `.next()` and `.prev()` methods.
         *
         * @attribute circular
         * @default true
         * @type {Boolean}
         */
        circular: {
            validator: isBoolean,
            value: true
        },

        /**
         * A formatter function to format each pagination item.
         *
         * @attribute formatter
         * @type {Function}
         */
        formatter: {
            validator: isFunction,
            valueFn: '_formatterValueFn'
        },

        /**
         * Holds the page items as a `NodeList`. The list could be queried from
         * the DOM trough Widget `HTML_PARSER` or generated if
         * [total](A.Pagination.html#attr_total) is specified.
         *
         * @attribute items
         * @default undefined
         * @type {NodeList}
         */
        items: {},

        /**
         * Initial page offset.
         *
         * @attribute offset
         * @default 1
         * @type {Number}
         */
        offset: {
            setter: '_setInt',
            value: 1
        },

        /**
         * Page to display on initial paint.
         *
         * @attribute page
         * @default 0
         * @type {Number}
         */
        page: {
            setter: '_setInt',
            value: 0
        },

        /**
         * Total number of page links available. If set, the new
         * [items](A.Pagination.html#attr_items) node list will be rendered.
         *
         * @attribute total
         * @default 0
         * @type {Number}
         */
        total: {
            setter: '_setInt',
            value: 0
        },

        /**
         * Collection of strings used to label elements of the UI.
         *
         * @attribute strings
         * @type {Object}
         */
        strings: {
            value: {
                next: 'Next',
                prev: 'Prev'
            }
        }
    },

    /**
     * Object hash, defining how attribute values are to be parsed from markup
     * contained in the widget's content box.
     *
     * @property HTML_PARSER
     * @type {Object}
     * @static
     */
    HTML_PARSER: {
        items: function(srcNode) {
            return this._queryItemsIfNotSet(srcNode);
        },
        total: function() {
            return this._countItemsInDoc();
        }
    },

    /**
     * Static property used to define the attributes for the bindUI lifecycle
     * phase.
     *
     * @property BIND_UI_ATTRS
     * @type {Array}
     * @static
     */
    BIND_UI_ATTRS: [OFFSET, TOTAL],

    /**
     * Static property used to define the UI attributes.
     *
     * @property UI_ATTRS
     * @type {Array}
     * @static
     */
    UI_ATTRS: [PAGE],

    prototype: {
        CONTENT_TEMPLATE: '

',
        ITEM_TEMPLATE: '
{content}
',
        TOTAL_CONTROLS: 2,

        items: null,
        lastState: null,

        /**
         * Sync the `A.Pagination` UI. Lifecycle.
         *
         * @method syncUI
         * @protected
         */
        syncUI: function() {
            var instance = this,
                page = instance.get(PAGE);

            if (page > 0) {
                instance._dispatchRequest({
                    page: page
                });
            }
        },

        /**
         * Bind the events on the `A.Pagination` UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this,
                boundingBox = instance.get(BOUNDING_BOX);

            instance.on('pageChange', instance._onPageChange);
            instance.publish(CHANGE_REQUEST, {
                defaultFn: instance._defChangeRequest
            });
            boundingBox.delegate(CLICK, instance._onClickItem, LI, instance);
        },

        /**
         * Render the `A.Pagination` component instance. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._renderItemsUI(instance.get(TOTAL));
        },

        /**
         * Retrieve the item node from the passesed item index parameter.
         * If passed item is a node instead of the index returns itself.
         *
         * @method getItem
         * @param {Node|Number} i Index or Node reference.
         * @return {Node} pagination item
         */
        getItem: function(i) {
            var instance = this;

            if (isNumber(i)) {
                var items = instance.get(ITEMS);
                if (items) {
                    i = items.item(i);
                }
            }

            return i;
        },

        /**
         * Retrieve page number including offset e.g., if offset
         * is 100 and active page is 5, this method returns 105.
         *
         * @method getOffsetPageNumber
         * @return {Number} current page number plus offset
         */
        getOffsetPageNumber: function() {
            var instance = this;

            return instance.get(OFFSET) + instance.get(PAGE);
        },

        /**
         * Retrieve total number of pages including offset e.g., if offset
         * is 100 and total 10, this method returns 110.
         *
         * @method getOffsetTotalPages
         * @return {Number} total page number plus offset
         */
        getOffsetTotalPages: function() {
            var instance = this;

            return instance.get(OFFSET) + instance.get(TOTAL);
        },

        /**
         * Retrieve total number of dom items representing the links,
         * including the arrow control items. Do not include the offset.
         *
         * @method getTotalItems
         * @return {Number} number of pagination items
         */
        getTotalItems: function() {
            var instance = this;

            return instance.get(TOTAL) + instance.TOTAL_CONTROLS;
        },

        /**
         * Navigate to the next page.
         *
         * @method next
         */
        next: function() {
            var instance = this,
                total = instance.get(TOTAL);

            if (total === 0) {
                return;
            }

            var page = instance.get(PAGE);

            instance._dispatchRequest({
                page: (instance.get(CIRCULAR) && (page === total)) ? 1 : Math.min(total, ++page)
            });

            return instance;
        },

        /**
         * Navigate to the previous page.
         *
         * @method prev
         */
        prev: function() {
            var instance = this,
                total = instance.get(TOTAL);

            if (total === 0) {
                return;
            }

            var page = instance.get(PAGE);

            instance._dispatchRequest({
                page: (instance.get(CIRCULAR) && (page === 1)) ? total : Math.max(1, --page)
            });

            return instance;
        },

        /**
         * Set the new pagination state. The state is a payload object
         * containing the page number, e.g. `{page:1}`.
         *
         * @method setState
         * @param {Object} state
         */
        setState: function(state) {
            var instance = this;

            instance.set(PAGE, state.page);
            instance.lastState = state;
        },

        /**
         * Returns number of items in doc.
         *
         * @method _countItemsInDoc
         * @protected
         * @return {Number} amount of items in doc
         */
        _countItemsInDoc: function() {
            var instance = this,
                srcNode = instance.get('srcNode');

            return Math.max(0, instance._queryItemsIfNotSet(srcNode).size() - instance.TOTAL_CONTROLS);
        },

        /**
         * Default `changeRequest` function, sets new state of pagination.
         *
         * @method _defChangeRequest
         * @param {EventFacade} event
         * @protected
         */
        _defChangeRequest: function(event) {
            var instance = this;

            instance.setState(event.state);
        },

        /**
         * Fires `changeRequest` event.
         *
         * @method _dispatchRequest
         * @param {Object} state
         * @protected
         */
        _dispatchRequest: function(state) {
            var instance = this;

            instance.fire(CHANGE_REQUEST, {
                lastState: instance.lastState,
                state: state
            });
        },

        /**
         * Formatter function that formats each pagination item.
         *
         * @method _formatterValueFn
         * @protected
         * @return {String} item template
         */
        _formatterValueFn: function() {
            return function(index) {
                var instance = this;

                return Lang.sub(
                    instance.ITEM_TEMPLATE, {
                        content: index,
                        cssClass: ''
                    }
                );
            };
        },

        /**
         * Returns all child list items of `srcNode`.
         *
         * @method _queryItemsIfNotSet
         * @param {Node} srcNode
         * @protected
         * @return {NodeList} list items
         */
        _queryItemsIfNotSet: function(srcNode) {
            var instance = this;

            if (!instance.items) {
                instance.items = srcNode.all(LI);
            }
            return instance.items;
        },

        /**
         * `onClick` handler for pagination items.
         *
         * @method _onClickItem
         * @param {EventFacade} event
         * @protected
         */
        _onClickItem: function(event) {
            var instance = this,
                item = event.currentTarget;

            event.preventDefault();

            if (item.hasClass(CSS_DISABLED) || item.hasClass(CSS_ACTIVE)) {
                return;
            }

            var items = instance.get(ITEMS),
                index = items.indexOf(item),
                lastIndex = items.size() - 1;

            switch (index) {
                case 0:
                    instance.prev();
                    break;
                case lastIndex:
                    instance.next();
                    break;
                default:
                    instance._dispatchRequest({
                        page: index
                    });
                    break;
            }
        },

        /**
         * Removes active class from previously selected item on page change.
         *
         * @method _onPageChange
         * @param {EventFacade} event
         * @protected
         */
        _onPageChange: function(event) {
            var instance = this;

            if (event.prevVal !== event.newVal) {
                var item = instance.getItem(event.prevVal);
                if (item) {
                    item.removeClass(CSS_ACTIVE);
                }
            }
        },

        /**
         * Renders pagination items UI.
         *
         * @method _renderItemsUI
         * @param {Number} total
         * @protected
         */
        _renderItemsUI: function(total) {
            var instance = this,
                tpl = instance.ITEM_TEMPLATE,
                formatter = instance.get(FORMATTER),
                offset = instance.get(OFFSET),
                i,
                buffer = '';

            buffer += Lang.sub(tpl, {
                content: instance.getString(PREV),
                cssClass: CSS_PAGINATION_CONTROL
            });

            for (i = offset; i <= (offset + total - 1); i++) {
                buffer += formatter.apply(instance, [i]);
            }

            buffer += Lang.sub(tpl, {
                content: instance.getString(NEXT),
                cssClass: CSS_PAGINATION_CONTROL
            });

            var items = A.NodeList.create(buffer);
            instance.set(ITEMS, items);
            instance.get(CONTENT_BOX).setContent(items);
        },

        /**
         * Setter for `offset`, `page`, and `total` attributes.
         *
         * @method _setInt
         * @param {Number} val
         * @protected
         */
        _setInt: function(val) {
            return Lang.toInt(val);
        },

        /**
         * Enables and disables next and prev items.
         *
         * @method _syncNavigationUI
         * @protected
         */
        _syncNavigationUI: function() {
            var instance = this,
                items = instance.get(ITEMS);

            items.first().toggleClass(
                CSS_DISABLED, instance.get(PAGE) === 1);

            items.last().toggleClass(
                CSS_DISABLED, instance.get(PAGE) === instance.get(TOTAL));
        },

        /**
         * Renders items UI based off current `total`.
         *
         * @method _uiSetOffset
         * @param {Number} val
         * @protected
         */
        _uiSetOffset: function(val) {
            var instance = this;

            instance._renderItemsUI(instance.get(TOTAL));
        },

        /**
         * Sets current page and syncs navigation UI.
         *
         * @method _uiSetPage
         * @param {Number} val
         * @protected
         */
        _uiSetPage: function(val) {
            var instance = this;

            if (!instance.get(CIRCULAR)) {
                instance._syncNavigationUI();
            }

            // Do not activate first and last items, they are used for controls.
            if (val === 0 || val === instance.getTotalItems()) {
                return;
            }

            var item = instance.getItem(val);

            if (item) {
                item.addClass(CSS_ACTIVE);
            }
        },

        /**
         * Setter for `total` attribute, renders pagination items UI.
         *
         * @method _uiSetTotal
         * @param {Number} val
         * @protected
         */
        _uiSetTotal: function(val) {
            var instance = this;

            instance._renderItemsUI(val);
        }
    }
});

A.Pagination = Pagination;
<commit_msg>AUI-1064 Source formatting<commit_after>/**
 * The Pagination widget provides a set of controls to navigate through paged
 * data.
 *
 * @module aui-pagination
 */

var Lang = A.Lang,
    isBoolean = Lang.isBoolean,
    isFunction = Lang.isFunction,
    isNumber = Lang.isNumber,

    ACTIVE = 'active',
    BOUNDING_BOX = 'boundingBox',
    CHANGE_REQUEST = 'changeRequest',
    CIRCULAR = 'circular',
    CLICK = 'click',
    CONTENT_BOX = 'contentBox',
    CONTROL = 'control',
    DISABLED = 'disabled',
    FORMATTER = 'formatter',
    ITEMS = 'items',
    LI = 'li',
    NEXT = 'next',
    OFFSET = 'offset',
    PAGE = 'page',
    PAGINATION = 'pagination',
    PREV = 'prev',
    TOTAL = 'total',

    getCN = A.getClassName,

    CSS_ACTIVE = getCN(ACTIVE),
    CSS_DISABLED = getCN(DISABLED),
    CSS_PAGINATION_CONTROL = getCN(PAGINATION, CONTROL);

/**
 * A base class for Pagination, providing:
 *
 * - Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)
 * - Set of controls to navigate through paged data
 *
 * Check the [live demo](http://alloyui.com/examples/pagination/).
 *
 * @class A.Pagination
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 * @include http://alloyui.com/examples/pagination/basic-markup.html
 * @include http://alloyui.com/examples/pagination/basic.js
 */
var Pagination = A.Component.create({
    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: PAGINATION,

    /**
     * Static property used to define the default attribute configuration for
     * the `A.Pagination`.
     *
     * @property ATTRS
     * @type {Object}
     * @static
     */
    ATTRS: {

        /**
         * When enabled this property allows the navigation to go back to the
         * beggining when it reaches the last page, the opposite behavior is
         * also true. Incremental page navigation could happen clicking the
         * control arrows or invoking `.next()` and `.prev()` methods.
         *
         * @attribute circular
         * @default true
         * @type {Boolean}
         */
        circular: {
            validator: isBoolean,
            value: true
        },

        /**
         * A formatter function to format each pagination item.
         *
         * @attribute formatter
         * @type {Function}
         */
        formatter: {
            validator: isFunction,
            valueFn: '_formatterValueFn'
        },

        /**
         * Holds the page items as a `NodeList`. The list could be queried from
         * the DOM trough Widget `HTML_PARSER` or generated if
         * [total](A.Pagination.html#attr_total) is specified.
         *
         * @attribute items
         * @default undefined
         * @type {NodeList}
         */
        items: {},

        /**
         * Initial page offset.
         *
         * @attribute offset
         * @default 1
         * @type {Number}
         */
        offset: {
            setter: '_setInt',
            value: 1
        },

        /**
         * Page to display on initial paint.
         *
         * @attribute page
         * @default 0
         * @type {Number}
         */
        page: {
            setter: '_setInt',
            value: 0
        },

        /**
         * Total number of page links available. If set, the new
         * [items](A.Pagination.html#attr_items) node list will be rendered.
         *
         * @attribute total
         * @default 0
         * @type {Number}
         */
        total: {
            setter: '_setInt',
            value: 0
        },

        /**
         * Collection of strings used to label elements of the UI.
         *
         * @attribute strings
         * @type {Object}
         */
        strings: {
            value: {
                next: 'Next',
                prev: 'Prev'
            }
        }
    },

    /**
     * Object hash, defining how attribute values are to be parsed from markup
     * contained in the widget's content box.
     *
     * @property HTML_PARSER
     * @type {Object}
     * @static
     */
    HTML_PARSER: {
        items: function(srcNode) {
            return this._queryItemsIfNotSet(srcNode);
        },
        total: function() {
            return this._countItemsInDoc();
        }
    },

    /**
     * Static property used to define the attributes for the bindUI lifecycle
     * phase.
     *
     * @property BIND_UI_ATTRS
     * @type {Array}
     * @static
     */
    BIND_UI_ATTRS: [OFFSET, TOTAL],

    /**
     * Static property used to define the UI attributes.
     *
     * @property UI_ATTRS
     * @type {Array}
     * @static
     */
    UI_ATTRS: [PAGE],

    prototype: {
        CONTENT_TEMPLATE: '

',
        ITEM_TEMPLATE: '
{content}
',
        TOTAL_CONTROLS: 2,

        items: null,
        lastState: null,

        /**
         * Sync the `A.Pagination` UI. Lifecycle.
         *
         * @method syncUI
         * @protected
         */
        syncUI: function() {
            var instance = this,
                page = instance.get(PAGE);

            if (page > 0) {
                instance._dispatchRequest({
                    page: page
                });
            }
        },

        /**
         * Bind the events on the `A.Pagination` UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this,
                boundingBox = instance.get(BOUNDING_BOX);

            instance.on('pageChange', instance._onPageChange);
            instance.publish(CHANGE_REQUEST, {
                defaultFn: instance._defChangeRequest
            });
            boundingBox.delegate(CLICK, instance._onClickItem, LI, instance);
        },

        /**
         * Render the `A.Pagination` component instance. Lifecycle.
         *
         * @method renderUI
         * @protected
         */
        renderUI: function() {
            var instance = this;

            instance._renderItemsUI(instance.get(TOTAL));
        },

        /**
         * Retrieve the item node from the passesed item index parameter.
         * If passed item is a node instead of the index returns itself.
         *
         * @method getItem
         * @param {Node|Number} i Index or Node reference.
         * @return {Node} pagination item
         */
        getItem: function(i) {
            var instance = this;

            if (isNumber(i)) {
                var items = instance.get(ITEMS);
                if (items) {
                    i = items.item(i);
                }
            }

            return i;
        },

        /**
         * Retrieve page number including offset e.g., if offset is 100 and
         * active page is 5, this method returns 105.
         *
         * @method getOffsetPageNumber
         * @return {Number} current page number plus offset
         */
        getOffsetPageNumber: function() {
            var instance = this;

            return instance.get(OFFSET) + instance.get(PAGE);
        },

        /**
         * Retrieve total number of pages including offset e.g., if offset is
         * 100 and total 10, this method returns 110.
         *
         * @method getOffsetTotalPages
         * @return {Number} total page number plus offset
         */
        getOffsetTotalPages: function() {
            var instance = this;

            return instance.get(OFFSET) + instance.get(TOTAL);
        },

        /**
         * Retrieve total number of dom items representing the links, including
         * the arrow control items. Do not include the offset.
         *
         * @method getTotalItems
         * @return {Number} number of pagination items
         */
        getTotalItems: function() {
            var instance = this;

            return instance.get(TOTAL) + instance.TOTAL_CONTROLS;
        },

        /**
         * Navigate to the next page.
         *
         * @method next
         */
        next: function() {
            var instance = this,
                total = instance.get(TOTAL);

            if (total === 0) {
                return;
            }

            var page = instance.get(PAGE);

            instance._dispatchRequest({
                page: (instance.get(CIRCULAR) && (page === total)) ? 1 : Math.min(total, ++page)
            });

            return instance;
        },

        /**
         * Navigate to the previous page.
         *
         * @method prev
         */
        prev: function() {
            var instance = this,
                total = instance.get(TOTAL);

            if (total === 0) {
                return;
            }

            var page = instance.get(PAGE);

            instance._dispatchRequest({
                page: (instance.get(CIRCULAR) && (page === 1)) ? total : Math.max(1, --page)
            });

            return instance;
        },

        /**
         * Set the new pagination state. The state is a payload object
         * containing the page number, e.g. `{page:1}`.
         *
         * @method setState
         * @param {Object} state
         */
        setState: function(state) {
            var instance = this;

            instance.set(PAGE, state.page);
            instance.lastState = state;
        },

        /**
         * Returns number of items in doc.
         *
         * @method _countItemsInDoc
         * @protected
         * @return {Number} amount of items in doc
         */
        _countItemsInDoc: function() {
            var instance = this,
                srcNode = instance.get('srcNode');

            return Math.max(0, instance._queryItemsIfNotSet(srcNode).size() - instance.TOTAL_CONTROLS);
        },

        /**
         * Default `changeRequest` function, sets new state of pagination.
         *
         * @method _defChangeRequest
         * @param {EventFacade} event
         * @protected
         */
        _defChangeRequest: function(event) {
            var instance = this;

            instance.setState(event.state);
        },

        /**
         * Fires `changeRequest` event.
         *
         * @method _dispatchRequest
         * @param {Object} state
         * @protected
         */
        _dispatchRequest: function(state) {
            var instance = this;

            instance.fire(CHANGE_REQUEST, {
                lastState: instance.lastState,
                state: state
            });
        },

        /**
         * Formatter function that formats each pagination item.
         *
         * @method _formatterValueFn
         * @protected
         * @return {String} item template
         */
        _formatterValueFn: function() {
            return function(index) {
                var instance = this;

                return Lang.sub(
                    instance.ITEM_TEMPLATE, {
                        content: index,
                        cssClass: ''
                    }
                );
            };
        },

        /**
         * Returns all child list items of `srcNode`.
         *
         * @method _queryItemsIfNotSet
         * @param {Node} srcNode
         * @protected
         * @return {NodeList} list items
         */
        _queryItemsIfNotSet: function(srcNode) {
            var instance = this;

            if (!instance.items) {
                instance.items = srcNode.all(LI);
            }
            return instance.items;
        },

        /**
         * `onClick` handler for pagination items.
         *
         * @method _onClickItem
         * @param {EventFacade} event
         * @protected
         */
        _onClickItem: function(event) {
            var instance = this,
                item = event.currentTarget;

            event.preventDefault();

            if (item.hasClass(CSS_DISABLED) || item.hasClass(CSS_ACTIVE)) {
                return;
            }

            var items = instance.get(ITEMS),
                index = items.indexOf(item),
                lastIndex = items.size() - 1;

            switch (index) {
                case 0:
                    instance.prev();
                    break;
                case lastIndex:
                    instance.next();
                    break;
                default:
                    instance._dispatchRequest({
                        page: index
                    });
                    break;
            }
        },

        /**
         * Removes active class from previously selected item on page change.
         *
         * @method _onPageChange
         * @param {EventFacade} event
         * @protected
         */
        _onPageChange: function(event) {
            var instance = this;

            if (event.prevVal !== event.newVal) {
                var item = instance.getItem(event.prevVal);
                if (item) {
                    item.removeClass(CSS_ACTIVE);
                }
            }
        },

        /**
         * Renders pagination items UI.
         *
         * @method _renderItemsUI
         * @param {Number} total
         * @protected
         */
        _renderItemsUI: function(total) {
            var instance = this,
                tpl = instance.ITEM_TEMPLATE,
                formatter = instance.get(FORMATTER),
                offset = instance.get(OFFSET),
                i,
                buffer = '';

            buffer += Lang.sub(tpl, {
                content: instance.getString(PREV),
                cssClass: CSS_PAGINATION_CONTROL
            });

            for (i = offset; i <= (offset + total - 1); i++) {
                buffer += formatter.apply(instance, [i]);
            }

            buffer += Lang.sub(tpl, {
                content: instance.getString(NEXT),
                cssClass: CSS_PAGINATION_CONTROL
            });

            var items = A.NodeList.create(buffer);
            instance.set(ITEMS, items);
            instance.get(CONTENT_BOX).setContent(items);
        },

        /**
         * Setter for `offset`, `page`, and `total` attributes.
         *
         * @method _setInt
         * @param {Number} val
         * @protected
         */
        _setInt: function(val) {
            return Lang.toInt(val);
        },

        /**
         * Enables and disables next and prev items.
         *
         * @method _syncNavigationUI
         * @protected
         */
        _syncNavigationUI: function() {
            var instance = this,
                items = instance.get(ITEMS);

            items.first().toggleClass(
                CSS_DISABLED, instance.get(PAGE) === 1);

            items.last().toggleClass(
                CSS_DISABLED, instance.get(PAGE) === instance.get(TOTAL));
        },

        /**
         * Renders items UI based off current `total`.
         *
         * @method _uiSetOffset
         * @param {Number} val
         * @protected
         */
        _uiSetOffset: function(val) {
            var instance = this;

            instance._renderItemsUI(instance.get(TOTAL));
        },

        /**
         * Sets current page and syncs navigation UI.
         *
         * @method _uiSetPage
         * @param {Number} val
         * @protected
         */
        _uiSetPage: function(val) {
            var instance = this;

            if (!instance.get(CIRCULAR)) {
                instance._syncNavigationUI();
            }

            // Do not activate first and last items, they are used for controls.
            if (val === 0 || val === instance.getTotalItems()) {
                return;
            }

            var item = instance.getItem(val);

            if (item) {
                item.addClass(CSS_ACTIVE);
            }
        },

        /**
         * Setter for `total` attribute, renders pagination items UI.
         *
         * @method _uiSetTotal
         * @param {Number} val
         * @protected
         */
        _uiSetTotal: function(val) {
            var instance = this;

            instance._renderItemsUI(val);
        }
    }
});

A.Pagination = Pagination;
<|endoftext|>


<commit_before>const path    = require('path');
const qforms = require('../../../qforms');
const Helper = require('../../../Helper');
const Model  = require('../Model');

class Field extends Model {
    static async create(data, parent) {
        return new Field(data, parent);
    }

    // constructor(data, parent) {
    //     super(data, parent);
    // }

    getDirPath() {
        return path.join(this.parent.getDirPath(), 'fields', this.getName());
    }

    fillDefaultValue(context, row) {
        const column = this.getAttr('column');
        if (!column) return;
        const defaultValue = this.getForm().replaceThis(context, this.getAttr('defaultValue'));
        const params = qforms.Application.getParams(context);
        const js = Helper.templateToJsString(defaultValue, params);
        let value;
        try {
            value = eval(js);
            if (value !== undefined) {
                row[column] = Helper.encodeValue(value);
            }
        } catch (e) {
            throw new Error(`[${this.getFullName()}] fillDefaultValue: ${e.toString()}`);
        }

    }

    dumpRowValueToParams(row, params) {
        // console.log('Field.dumpRowValueToParams', this.getFullName());
        const fullName = this.getFullName();
        const column   = this.getAttr('column');
        params[fullName] = Helper.decodeValue(row[column]);
    }

    getFullName() {
        return [
            this.getForm().getPage().getName(),
            this.getForm().getName(),
            this.getName()
        ].join('.');
    }

    calcValue(row) {
        row[this.getAttr('column')] = eval(this.getAttr('value'));
    }

    getApp() {
        return this.parent.parent.parent;
    }

    getPage() {
        return this.parent.parent;
    }

    getForm() {
        return this.parent;
    }
    isParam() {
        return this.isAttr('param') && this.getAttr('param') === 'true';
    }

}

module.exports = Field;
<commit_msg>dumpRowValueToParams fixed<commit_after>const path    = require('path');
const qforms = require('../../../qforms');
const Helper = require('../../../Helper');
const Model  = require('../Model');

class Field extends Model {
    static async create(data, parent) {
        return new Field(data, parent);
    }

    // constructor(data, parent) {
    //     super(data, parent);
    // }

    getDirPath() {
        return path.join(this.parent.getDirPath(), 'fields', this.getName());
    }

    fillDefaultValue(context, row) {
        const column = this.getAttr('column');
        if (!column) return;
        const defaultValue = this.getForm().replaceThis(context, this.getAttr('defaultValue'));
        const params = qforms.Application.getParams(context);
        const js = Helper.templateToJsString(defaultValue, params);
        let value;
        try {
            value = eval(js);
            if (value !== undefined) {
                row[column] = Helper.encodeValue(value);
            }
        } catch (e) {
            throw new Error(`[${this.getFullName()}] fillDefaultValue: ${e.toString()}`);
        }

    }

    dumpRowValueToParams(row, params) {
        // console.log('Field.dumpRowValueToParams', this.getFullName());
        const fullName = this.getFullName();
        try {
            const column = this.getAttr('column');
            if (!column) throw new Error('no column attr');
            const value = row[column];
            // console.log('value:', value);
            params[fullName] = value !== undefined ? Helper.decodeValue(value) : value;
        } catch (err) {
            // console.log('row:', row);
            err.message = `${fullName}: ${err.message}`;
            throw err;
        }
    }

    getFullName() {
        return [
            this.getForm().getPage().getName(),
            this.getForm().getName(),
            this.getName()
        ].join('.');
    }

    calcValue(row) {
        row[this.getAttr('column')] = eval(this.getAttr('value'));
    }

    getApp() {
        return this.parent.parent.parent;
    }

    getPage() {
        return this.parent.parent;
    }

    getForm() {
        return this.parent;
    }
    isParam() {
        return this.isAttr('param') && this.getAttr('param') === 'true';
    }

}

module.exports = Field;
<|endoftext|>


<commit_before>
/* ==========================================================================
   Table Row Links

   Mixin for adding row link click functionality to table organism.

   ========================================================================== */

'use strict';

var closest = require( 'atomic-component/src/utilities/dom-closest' ).closest;

var TableRowLinks = {

  events: {
    'click tbody tr': 'onRowLinkClick'
  },

  ui: {
    base: '.o-table__row-links'
  },

  /**
   * Handle a click of the table.
   *
   * @param {Object} event Mouse event for click on the table.
   */
  onRowLinkClick: function( event ) {
    var target = event.target;
    if( target && target.tagName === 'A' ) {
      return
    }
    target = closest( event.target, 'tr' );
    var link = target.querySelector( 'a' );
    if( link ) window.location = link.getAttribute( 'href' );
  },

  /**
   * Handle initilization of Table Row Links. Added for standalone
   * use cases.
   *
   */
  init: function() {
    var elements = document.querySelector( TableRowLinks.ui.base );
    for ( var i = 0; i < elements.length; ++i ) {
      if( elements[i].hasAttribute( 'data-bound' ) === false ) {
        elements[i].addEventListener( 'click', table,
        TableRowLinks.onRowLinkClick );
      }
    }
  }
};

module.exports = TableRowLinks;
<commit_msg>Remove table row links init method<commit_after>
/* ==========================================================================
   Table Row Links

   Mixin for adding row link click functionality to table organism.

   ========================================================================== */

'use strict';

var closest = require( 'atomic-component/src/utilities/dom-closest' ).closest;

var TableRowLinks = {

  events: {
    'click tbody tr': 'onRowLinkClick'
  },

  ui: {
    base: '.o-table__row-links'
  },

  /**
   * Handle a click of the table.
   *
   * @param {Object} event Mouse event for click on the table.
   */
  onRowLinkClick: function( event ) {
    var target = event.target;
    if( target && target.tagName === 'A' ) {
      return
    }
    target = closest( event.target, 'tr' );
    var link = target.querySelector( 'a' );
    if( link ) window.location = link.getAttribute( 'href' );
  }
};

module.exports = TableRowLinks;
<|endoftext|>


<commit_before>import {createStore} from "redux";
import {httpAsync} from "./networking";

const defaultState = {
    config: {},
    locations: {},
    learning: undefined,
    location: "home"
};

function updateConfig(obj) {
    if (PRODUCTION)
        httpAsync("/config", null, "POST", JSON.stringify(obj));
}

function appStore(state = defaultState, action) {
    switch (action.type) {
        case 'UPDATE_CFG':
            state.config = Object.assign(state.config, action.config);
            if (!action.noUpdate)
                updateConfig(action.config);
            break;
        case 'UPDATE_LOCATIONS':
            state.locations = action.locations;
            break;
        case 'LEARN':
            state.learning = action.room;
            break;
        case 'STOP_LEARNING':
            state.learning = undefined;
            break;
        case 'NAVIGATE':
            state.location = action.location;
            break;
        case 'TRACKED':
            state.trackedLocation = action.location;
    }

    console.log(action.type, state);

    return state;
}

export let store = createStore(appStore);
let locationSocket;
let trackedLocationReset;

export function reloadConfig(cb) {
    if (!PRODUCTION) {
        store.dispatch({
            type: 'UPDATE_CFG',
            config: {
                "auth": "supersecret2",
                "wifiReconnectionInterval": 60000,
                "SSID": "SomeSSID",
                "passphrase": "supersecret",
                "hostname": "FINDTracker",
                "active": false,
                "bufferSize": 10,
                "trackingHost": "10.0.0.38:18003",
                "trackingGroup": "Family",
                "trackingUser": "Til"
            },
            noUpdate: true
        });
        cb();
    }
    if (PRODUCTION) {
        httpAsync("/config", (cfg) => {
            cfg = JSON.parse(cfg);
            store.dispatch({
                type: 'UPDATE_CFG',
                config: cfg,
                noUpdate: true
            });
            if (typeof cb === 'function') cb();
        });
        if (locationSocket) locationSocket.close();
        locationSocket = new WebSocket("ws://" + location.hostname + ":81");
        locationSocket.onmessage = (msg) => {
            const newLocation = JSON.parse(msg.data).location;

            if (trackedLocationReset) clearTimeout(trackedLocationReset);
            trackedLocationReset = setTimeout(() => store.dispatch({ type: 'TRACKED', location: undefined }), 15000);

            if (newLocation != store.getState().trackedLocation)
                store.dispatch({
                    type: 'TRACKED',
                    location: newLocation.capitalizeFirstLetter()
                });
        }
    }
}<commit_msg>Added tracking websocket watchdog<commit_after>import {createStore} from "redux";
import {httpAsync} from "./networking";

const defaultState = {
    config: {},
    locations: {},
    learning: undefined,
    location: "home"
};

function updateConfig(obj) {
    if (PRODUCTION)
        httpAsync("/config", null, "POST", JSON.stringify(obj));
}

function appStore(state = defaultState, action) {
    switch (action.type) {
        case 'UPDATE_CFG':
            state.config = Object.assign(state.config, action.config);
            if (!action.noUpdate)
                updateConfig(action.config);
            break;
        case 'UPDATE_LOCATIONS':
            state.locations = action.locations;
            break;
        case 'LEARN':
            state.learning = action.room;
            break;
        case 'STOP_LEARNING':
            state.learning = undefined;
            break;
        case 'NAVIGATE':
            state.location = action.location;
            break;
        case 'TRACKED':
            state.trackedLocation = action.location;
    }

    return state;
}

export let store = createStore(appStore);
let locationSocket;
let trackedLocationReset;
let wsWatchdog;

function connectTrackingSocket() {
    if (locationSocket) locationSocket.close();
    locationSocket = new WebSocket("ws://" + location.hostname + ":81");

    locationSocket.onmessage = (msg) => {
        if (msg.data == "watchdog") {
            if (wsWatchdog) clearTimeout(wsWatchdog);
            wsWatchdog = setTimeout(() => {
                console.warn("Lost tracking connection!");
                connectTrackingSocket();
            }, 15000);
        } else {
            const newLocation = JSON.parse(msg.data).location;

            if (trackedLocationReset) clearTimeout(trackedLocationReset);
            trackedLocationReset = setTimeout(() => store.dispatch({ type: 'TRACKED', location: undefined }), 15000);

            if (newLocation != store.getState().trackedLocation)
                store.dispatch({
                    type: 'TRACKED',
                    location: newLocation.capitalizeFirstLetter()
                });
        }
    }
}

export function reloadConfig(cb) {
    if (!PRODUCTION) {
        store.dispatch({
            type: 'UPDATE_CFG',
            config: {
                "auth": "supersecret2",
                "wifiReconnectionInterval": 60000,
                "SSID": "SomeSSID",
                "passphrase": "supersecret",
                "hostname": "FINDTracker",
                "active": false,
                "bufferSize": 10,
                "trackingHost": "10.0.0.38:18003",
                "trackingGroup": "Family",
                "trackingUser": "Til"
            },
            noUpdate: true
        });
        cb();
    }
    if (PRODUCTION) {
        connectTrackingSocket();
        httpAsync("/config", (cfg) => {
            cfg = JSON.parse(cfg);
            store.dispatch({
                type: 'UPDATE_CFG',
                config: cfg,
                noUpdate: true
            });
            if (typeof cb === 'function') cb();
        });
    }
}<|endoftext|>


<commit_before>Element.prototype.toggleClass = function(name) {
	if (this.classList.contains(name)) {
		this.classList.remove(name);
	} else {
		this.classList.add(name);
	}
};

Element.prototype.removeClass = function(name) {
	if (this.classList.contains(name)) {
		this.classList.remove(name);
	}
};

Element.prototype.addClass = function(name) {
	if (this.classList.contains(name) === false) {
		this.classList.add(name);
	}
}

function scrollToElement(parentElement, childElement) {
	var x = 0;
    var y = 0;
	var element = childElement;
    while( element && element !== parentElement && !isNaN( element.offsetLeft ) && !isNaN( element.offsetTop ) ) {
        x += element.offsetLeft - element.scrollLeft;
        y += element.offsetTop - element.scrollTop;
        element = element.offsetParent;
    }

	parentElement.scrollTop = y;
	parentElement.scrollLeft = x;
}

function getJSON(url, onSuccess, onFail) {
	var xhr = new XMLHttpRequest();
	xhr.open('get', url);
	xhr.onreadystatechange = function() {
		if (xhr.readyState !== 4) {
			return;
		}

		if (xhr.status === 200) {
			if (onSuccess instanceof Function) {
				var obj = JSON.parse(xhr.responseText);
				(onSuccess)(obj);
			}
		} else {
			if(onFail instanceof Function) {
				(onFail)(xhr);
			} else {
				try {
					var json = JSON.parse(xhr.responseText);
					var error = json.error;
					var message = json.message;
					alert(error + '\n' + message);
				}catch(err) {
					alert(xhr.statusText);
				}
			}
		}
	}
	xhr.send();
}

function post(url, parameter, onSuccess, onFail) {
	var xhr = new XMLHttpRequest();
	xhr.open('post', url);
	xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
	xhr.onreadystatechange = function() {
		if (xhr.readyState !== 4) {
			return;
		}

		if (xhr.status === 200) {
			if (onSuccess instanceof Function) {
				var obj = JSON.parse(xhr.responseText);
				(onSuccess)(obj);
			}
		} else {
			if(onFail instanceof Function) {
				(onFail)(xhr);
			}
		}
	}

	xhr.send(parameter);
}

function serializeForm(form) {
	var elements = form.querySelectorAll('input, textarea, select');
	var serialized = [];

	for (var i=0; i<elements.length; i++) {
		if (elements[i].name) {
			var name = encodeURIComponent(elements[i].name);
			var value = encodeURIComponent(elements[i].value);
			serialized.push(name + '=' + value);
		}
	}

	return serialized.join('&');
}

function resizer(event) {
	var name = event.animationName;

	if (name === "big") {
		document.body.removeClass('menu-open');
	} else if (name === "small") {
		document.body.removeClass('menu-open');
		document.body.removeClass('side-open');
	}
}

function clickPersistentMenu(event) {
	var target = event.target;
	while (target.getAttribute('data-action') == null) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	var action = target.getAttribute('data-action');
	closeMenu();

	if (action === 'all') {
		getAllEntries();
	}
}

function toggleMenu(event) {
	var target = event.target;
	while (target.classList.contains('off-canvas-menu') == false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	closeSide();
	document.body.toggleClass('menu-open');
}

function toggleSide(event) {
	var target = event.target;
	while (target.classList.contains('off-canvas-side') == false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	closeMenu();
	document.body.toggleClass('side-open');
}

function toggleFolding(event) {
	var target = event.target;
	while (target.classList.contains('header') == false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	target.toggleClass('closed');
}

function closeMenu() {
	document.body.removeClass('menu-open');
}

function closeSide() {
	document.body.removeClass('side-open');
}

function processForm(event) {
	var target = event.target;
	event.preventDefault();

	var data = serializeForm(target);
	var after = target.getAttribute('data-after');
	if (after === "makeFeedList") {
		var action = target.action;
		try {
			var current = document.querySelector('[role=navigation] .feedlist .current');
			if (target.getAttribute('data-action') === 'addFeed') {
				action = current.getAttribute('data-add-feed-url');
			} else if (target.getAttribute('data-action') === 'addCategory') {
				action = current.getAttribute('data-add-category-url');
			}
		} catch (err) {
		}
		post(action, data, function(res) {
			if (current == null) {
				makeFeedList(res);
			} else {
				var fold = current.nextElementSibling;
				fold.innerHTML = "";
				makeCategory(fold, res);
			}
			target.reset();
		});
	} else {
		post(target.action, data, function(res) {
			alert(res);
			target.reset();
		});
	}
}

var makeCategory = function(parentObj, obj) {
	var header = document.createElement('li');
	var list = document.createElement('li');

	header.addClass('header');
	header.addClass('feed');
	header.setAttribute('role', 'link');
	header.setAttribute('data-entries', obj.entries_url);
	header.setAttribute('data-add-category-url', obj.add_category_url);
	header.setAttribute('data-add-feed-url', obj.add_feed_url);
	header.setAttribute('data-remove-feed-url', obj.remove_feed_url);
	header.setAttribute('data-remove-category-url', obj.remove_category_url);
	console.log(obj);
	header.textContent = obj.title;

	list.addClass('fold');

	var ul = document.createElement('ul');
	getJSON(obj.feeds_url, function(obj) {
		for (var i=0; i<obj.categories.length; i++) {
			makeCategory(ul, obj.categories[i]);
		}
		for (var i=0; i<obj.feeds.length; i++) {
			makeFeed(ul, obj.feeds[i]);
		}
	});

	list.appendChild(ul);

	parentObj.appendChild(header);
	parentObj.appendChild(list);
};

var makeFeed = function(parentObj, obj) {
	var elem = document.createElement('li');
	elem.addClass('feed');
	elem.setAttribute('data-entries', obj.entries_url);
	elem.setAttribute('data-remove-feed-url', obj.remove_feed_url);
	elem.setAttribute('role', 'link');
	elem.textContent = obj.title;

	parentObj.appendChild(elem);
};

function makeFeedList(obj) {
	var feedList = document.querySelector('.feedlist');
	feedList.innerHTML = "";

	for (var i=0; i<obj.categories.length; i++) {
		makeCategory(feedList, obj.categories[i]);
	}
	for (var i=0; i<obj.feeds.length; i++) {
		makeFeed(feedList, obj.feeds[i]);
	}
}

function refreshFeedList() {
	getJSON('/feeds/', makeFeedList);
}

function getAllEntries() {
	var all_feed = document.querySelector('[role=navigation] [data-action=all]');
	var list = document.querySelectorAll('[role=navigation] .current');
	for (var i=0; i<list.length; i++) {
		list[i].removeClass('current');
	}
	all_feed.addClass('current');
	getEntries('/entries/');
}

function getEntries(feed_url) {
	var main = document.querySelector('[role=main]');
	main.innerHTML = "";

	getJSON(feed_url, function(obj) {
		var feed_title = obj.title;
		var entries = obj.entries;

		var header = document.createElement('header');
		var h2 = document.createElement('h2');
		header.appendChild(h2);
		h2.textContent = feed_title;

		main.appendChild(header);

		for (var i=0; i<entries.length; i++) {
			var entry = entries[i];
			var article = document.createElement('article');
			var header = document.createElement('div');
			var time = document.createElement('time');
			var title = document.createElement('span');

			article.addClass('entry');
			article.setAttribute('data-entries', entry.entry_url);

			header.addClass('entry-title');
			header.setAttribute('role', 'button');

			if (entry.feed) {
				var category = document.createElement('span');
				category.addClass('feed');
				category.textContent = entry.feed.title;
				header.appendChild(category);
			}

			title.textContent = entry.title;
			header.appendChild(title);

			time.textContent = entry.updated;
			header.appendChild(time);

			article.appendChild(header);
			main.appendChild(article);
		}
	});
}

function clickFeed(event) {
	var target = event.target;
	var navi = document.querySelector('[role=navigation]');

	while (target.classList.contains('feed') === false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	//set current marker
	var list = navi.querySelectorAll('.current');
	for (var i=0; i<list.length; i++) {
		list[i].removeClass('current');
	}
	target.addClass('current');

	var url = target.getAttribute('data-entries');

	closeMenu();

	getEntries(url);
}

function clickEntry(event) {
	var target = event.target;
	var main = document.querySelector('[role=main]');

	while (target.classList.contains('entry-title') === false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	var entry = target.parentElement;
	var entry_url = entry.getAttribute('data-entries');

	getJSON(entry_url, function(obj) {
		//set current marker
		var list = main.querySelectorAll('.current');
		for (var i=0; i<list.length; i++) {
			list[i].removeClass('current');
		}
		target.parentElement.addClass('current');

		//close content
		var content = entry.querySelector('.entry-content');
		if (content) {
			entry.removeChild(content);
			return;
		}

		//remove content
		contents = main.querySelectorAll('.entry-content');
		for (var i=0; i<contents.length; i++) {
			contents[i].parentElement.removeChild(contents[i]);
		}

		var wrapper = document.createElement('div');
		var title = document.createElement('h1');
		var content = document.createElement('div');

		title.innerHTML = obj.title.link(obj.permalink);
		content.innerHTML = obj.content;

		wrapper.addClass('entry-content');
		wrapper.appendChild(title);
		wrapper.appendChild(content);
		entry.appendChild(wrapper);

		scrollToElement(main, entry);
	});
}

function keyboardShortcut(event) {
	if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
		return;
	}

	var main = document.querySelector('[role=main]');

	switch (event.keyCode) {
		case 74: //j
			var entry = main.querySelector('.current');
			if (entry == null) {
				main.querySelector('.entry').querySelector('.entry-title').click();
				return;
			}
			var next = entry.nextElementSibling;
			if (next == null) {
				return;
			}
			next.querySelector('.entry-title').click();
			break;
		case 75: //k
			var entry = main.querySelector('.current');
			if (entry == null) {
				main.querySelector('.entry').querySelector('.entry-title').click();
				return;
			}
			var prev = entry.previousElementSibling;
			if (prev == null) {
				return;
			}
			prev.querySelector('.entry-title').click();
			break;
	}
}

function init() {
	var navi = document.querySelector('[role=navigation]');
	var persistent = navi.querySelector('.persistent');
	navi.addEventListener('click', clickFeed, false);
	persistent.addEventListener('click', clickPersistentMenu, false);
	persistent.addEventListener('click', toggleFolding, false);

	var main = document.querySelector('[role=main]');
	main.addEventListener('click', clickEntry, false);

	document.addEventListener('click', toggleMenu, false);
	document.addEventListener('click', toggleSide, false);

	window.addEventListener('submit', processForm, false);
	window.addEventListener('keydown', keyboardShortcut, false);

    var animationEnd;
    if (document.body.style.animation !== undefined) {
        animationEnd = 'animationend';
    } else if (document.body.style.MozAnimation !== undefined) {
        animationEnd = 'animaionend';
    } else if (document.body.style.webkitAnimation !== undefined) {
        animationEnd = 'webkitAnimationEnd';
    } else if (document.body.style.OAnimtion !== undefined) {
        animationEnd = 'oAnimationEnd';
    } else if (document.body.style.msAnimation !== undefined) {
        animationEnd = 'MSAnimaionEnd';
    }
    document.body.addEventListener(animationEnd, resizer, false);

	refreshFeedList();
	getAllEntries();
}

window.addEventListener('DOMContentLoaded', init, false);
<commit_msg>fix make category in category<commit_after>Element.prototype.toggleClass = function(name) {
	if (this.classList.contains(name)) {
		this.classList.remove(name);
	} else {
		this.classList.add(name);
	}
};

Element.prototype.removeClass = function(name) {
	if (this.classList.contains(name)) {
		this.classList.remove(name);
	}
};

Element.prototype.addClass = function(name) {
	if (this.classList.contains(name) === false) {
		this.classList.add(name);
	}
}

function scrollToElement(parentElement, childElement) {
	var x = 0;
    var y = 0;
	var element = childElement;
    while( element && element !== parentElement && !isNaN( element.offsetLeft ) && !isNaN( element.offsetTop ) ) {
        x += element.offsetLeft - element.scrollLeft;
        y += element.offsetTop - element.scrollTop;
        element = element.offsetParent;
    }

	parentElement.scrollTop = y;
	parentElement.scrollLeft = x;
}

function getJSON(url, onSuccess, onFail) {
	var xhr = new XMLHttpRequest();
	xhr.open('get', url);
	xhr.onreadystatechange = function() {
		if (xhr.readyState !== 4) {
			return;
		}

		if (xhr.status === 200) {
			if (onSuccess instanceof Function) {
				var obj = JSON.parse(xhr.responseText);
				(onSuccess)(obj);
			}
		} else {
			if(onFail instanceof Function) {
				(onFail)(xhr);
			} else {
				try {
					var json = JSON.parse(xhr.responseText);
					var error = json.error;
					var message = json.message;
					alert(error + '\n' + message);
				}catch(err) {
					alert(xhr.statusText);
				}
			}
		}
	}
	xhr.send();
}

function post(url, parameter, onSuccess, onFail) {
	var xhr = new XMLHttpRequest();
	xhr.open('post', url);
	xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
	xhr.onreadystatechange = function() {
		if (xhr.readyState !== 4) {
			return;
		}

		if (xhr.status === 200) {
			if (onSuccess instanceof Function) {
				var obj = JSON.parse(xhr.responseText);
				(onSuccess)(obj);
			}
		} else {
			if(onFail instanceof Function) {
				(onFail)(xhr);
			}
		}
	}

	xhr.send(parameter);
}

function serializeForm(form) {
	var elements = form.querySelectorAll('input, textarea, select');
	var serialized = [];

	for (var i=0; i<elements.length; i++) {
		if (elements[i].name) {
			var name = encodeURIComponent(elements[i].name);
			var value = encodeURIComponent(elements[i].value);
			serialized.push(name + '=' + value);
		}
	}

	return serialized.join('&');
}

function resizer(event) {
	var name = event.animationName;

	if (name === "big") {
		document.body.removeClass('menu-open');
	} else if (name === "small") {
		document.body.removeClass('menu-open');
		document.body.removeClass('side-open');
	}
}

function clickPersistentMenu(event) {
	var target = event.target;
	while (target.getAttribute('data-action') == null) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	var action = target.getAttribute('data-action');
	closeMenu();

	if (action === 'all') {
		getAllEntries();
	}
}

function toggleMenu(event) {
	var target = event.target;
	while (target.classList.contains('off-canvas-menu') == false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	closeSide();
	document.body.toggleClass('menu-open');
}

function toggleSide(event) {
	var target = event.target;
	while (target.classList.contains('off-canvas-side') == false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	closeMenu();
	document.body.toggleClass('side-open');
}

function toggleFolding(event) {
	var target = event.target;
	while (target.classList.contains('header') == false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	target.toggleClass('closed');
}

function closeMenu() {
	document.body.removeClass('menu-open');
}

function closeSide() {
	document.body.removeClass('side-open');
}

function processForm(event) {
	var target = event.target;
	event.preventDefault();

	var data = serializeForm(target);
	var after = target.getAttribute('data-after');
	if (after === "makeFeedList") {
		var action = target.action;
		try {
			var current = document.querySelector('[role=navigation] .feedlist .current');
			if (target.getAttribute('data-action') === 'addFeed') {
				action = current.getAttribute('data-add-feed-url');
			} else if (target.getAttribute('data-action') === 'addCategory') {
				action = current.getAttribute('data-add-category-url');
			}
		} catch (err) {
		}
		post(action, data, function(res) {
			if (current == null) {
				makeFeedList(res);
			} else {
				var fold = current.nextElementSibling;
				fold.innerHTML = "";
				//makeCategory(fold, res);
				makeFeedList(res, fold);
			}
			target.reset();
		});
	} else {
		post(target.action, data, function(res) {
			alert(res);
			target.reset();
		});
	}
}

var makeCategory = function(parentObj, obj) {
	var header = document.createElement('li');
	var list = document.createElement('li');

	header.addClass('header');
	header.addClass('feed');
	header.setAttribute('role', 'link');
	header.setAttribute('data-entries', obj.entries_url);
	header.setAttribute('data-add-category-url', obj.add_category_url);
	header.setAttribute('data-add-feed-url', obj.add_feed_url);
	header.setAttribute('data-remove-feed-url', obj.remove_feed_url);
	header.setAttribute('data-remove-category-url', obj.remove_category_url);
	console.log(obj);
	header.textContent = obj.title;

	list.addClass('fold');

	var ul = document.createElement('ul');
	getJSON(obj.feeds_url, function(obj) {
		for (var i=0; i<obj.categories.length; i++) {
			makeCategory(ul, obj.categories[i]);
		}
		for (var i=0; i<obj.feeds.length; i++) {
			makeFeed(ul, obj.feeds[i]);
		}
	});

	list.appendChild(ul);

	parentObj.appendChild(header);
	parentObj.appendChild(list);
};

var makeFeed = function(parentObj, obj) {
	var elem = document.createElement('li');
	elem.addClass('feed');
	elem.setAttribute('data-entries', obj.entries_url);
	elem.setAttribute('data-remove-feed-url', obj.remove_feed_url);
	elem.setAttribute('role', 'link');
	elem.textContent = obj.title;

	parentObj.appendChild(elem);
};

function makeFeedList(obj, target) {
	var feedList;
	if (target !== undefined) {
		feedList = target;
	} else {
		feedList = document.querySelector('.feedlist');
	}
	feedList.innerHTML = "";

	for (var i=0; i<obj.categories.length; i++) {
		makeCategory(feedList, obj.categories[i]);
	}
	for (var i=0; i<obj.feeds.length; i++) {
		makeFeed(feedList, obj.feeds[i]);
	}
}

function refreshFeedList() {
	getJSON('/feeds/', makeFeedList);
}

function getAllEntries() {
	var all_feed = document.querySelector('[role=navigation] [data-action=all]');
	var list = document.querySelectorAll('[role=navigation] .current');
	for (var i=0; i<list.length; i++) {
		list[i].removeClass('current');
	}
	all_feed.addClass('current');
	getEntries('/entries/');
}

function getEntries(feed_url) {
	var main = document.querySelector('[role=main]');
	main.innerHTML = "";

	getJSON(feed_url, function(obj) {
		var feed_title = obj.title;
		var entries = obj.entries;

		var header = document.createElement('header');
		var h2 = document.createElement('h2');
		header.appendChild(h2);
		h2.textContent = feed_title;

		main.appendChild(header);

		for (var i=0; i<entries.length; i++) {
			var entry = entries[i];
			var article = document.createElement('article');
			var header = document.createElement('div');
			var time = document.createElement('time');
			var title = document.createElement('span');

			article.addClass('entry');
			article.setAttribute('data-entries', entry.entry_url);

			header.addClass('entry-title');
			header.setAttribute('role', 'button');

			if (entry.feed) {
				var category = document.createElement('span');
				category.addClass('feed');
				category.textContent = entry.feed.title;
				header.appendChild(category);
			}

			title.textContent = entry.title;
			header.appendChild(title);

			time.textContent = entry.updated;
			header.appendChild(time);

			article.appendChild(header);
			main.appendChild(article);
		}
	});
}

function clickFeed(event) {
	var target = event.target;
	var navi = document.querySelector('[role=navigation]');

	while (target.classList.contains('feed') === false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	//set current marker
	var list = navi.querySelectorAll('.current');
	for (var i=0; i<list.length; i++) {
		list[i].removeClass('current');
	}
	target.addClass('current');

	var url = target.getAttribute('data-entries');

	closeMenu();

	getEntries(url);
}

function clickEntry(event) {
	var target = event.target;
	var main = document.querySelector('[role=main]');

	while (target.classList.contains('entry-title') === false) {
		target = target.parentElement;
		if (target === null) {
			return;
		}
	}

	var entry = target.parentElement;
	var entry_url = entry.getAttribute('data-entries');

	getJSON(entry_url, function(obj) {
		//set current marker
		var list = main.querySelectorAll('.current');
		for (var i=0; i<list.length; i++) {
			list[i].removeClass('current');
		}
		target.parentElement.addClass('current');

		//close content
		var content = entry.querySelector('.entry-content');
		if (content) {
			entry.removeChild(content);
			return;
		}

		//remove content
		contents = main.querySelectorAll('.entry-content');
		for (var i=0; i<contents.length; i++) {
			contents[i].parentElement.removeChild(contents[i]);
		}

		var wrapper = document.createElement('div');
		var title = document.createElement('h1');
		var content = document.createElement('div');

		title.innerHTML = obj.title.link(obj.permalink);
		content.innerHTML = obj.content;

		wrapper.addClass('entry-content');
		wrapper.appendChild(title);
		wrapper.appendChild(content);
		entry.appendChild(wrapper);

		scrollToElement(main, entry);
	});
}

function keyboardShortcut(event) {
	if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {
		return;
	}

	var main = document.querySelector('[role=main]');

	switch (event.keyCode) {
		case 74: //j
			var entry = main.querySelector('.current');
			if (entry == null) {
				main.querySelector('.entry').querySelector('.entry-title').click();
				return;
			}
			var next = entry.nextElementSibling;
			if (next == null) {
				return;
			}
			next.querySelector('.entry-title').click();
			break;
		case 75: //k
			var entry = main.querySelector('.current');
			if (entry == null) {
				main.querySelector('.entry').querySelector('.entry-title').click();
				return;
			}
			var prev = entry.previousElementSibling;
			if (prev == null) {
				return;
			}
			prev.querySelector('.entry-title').click();
			break;
	}
}

function init() {
	var navi = document.querySelector('[role=navigation]');
	var persistent = navi.querySelector('.persistent');
	navi.addEventListener('click', clickFeed, false);
	persistent.addEventListener('click', clickPersistentMenu, false);
	persistent.addEventListener('click', toggleFolding, false);

	var main = document.querySelector('[role=main]');
	main.addEventListener('click', clickEntry, false);

	document.addEventListener('click', toggleMenu, false);
	document.addEventListener('click', toggleSide, false);

	window.addEventListener('submit', processForm, false);
	window.addEventListener('keydown', keyboardShortcut, false);

    var animationEnd;
    if (document.body.style.animation !== undefined) {
        animationEnd = 'animationend';
    } else if (document.body.style.MozAnimation !== undefined) {
        animationEnd = 'animaionend';
    } else if (document.body.style.webkitAnimation !== undefined) {
        animationEnd = 'webkitAnimationEnd';
    } else if (document.body.style.OAnimtion !== undefined) {
        animationEnd = 'oAnimationEnd';
    } else if (document.body.style.msAnimation !== undefined) {
        animationEnd = 'MSAnimaionEnd';
    }
    document.body.addEventListener(animationEnd, resizer, false);

	refreshFeedList();
	getAllEntries();
}

window.addEventListener('DOMContentLoaded', init, false);
<|endoftext|>


<commit_before>/**
 * RightJS UI Internationalization: German module
 *
 * Copyright (C) Nikolay V. Nemshilov aka St.
 */
if (self.Calendar) {
  $ext(Calendar.i18n, {
    Done:           'Getan',
    Now:            'Jetzt',
    Next:           'Nächste Monat',
    Prev:           'Vorhergehende Monat',
    NextYear:       'Nächste Jahr',
    PrevYear:       'Vorhergehende Jahr',

    dayNames:        $w('Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag'),
    dayNamesShort:   $w('Son Mon Die Mit Don Fre Sam'),
    dayNamesMin:     $w('So Mo Di Mi Do Fr Sa'),
    monthNames:      $w('Januar Februar März April Mai Juni Juli August September Oktober November Dezember'),
    monthNamesShort: $w('Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez')
  });
}

if (self.Lightbox) {
  $ext(Lightbox.i18n, {
    CloseTitle: 'Abschluss',
    PrevTitle:  'Vorhergehende Abbildung',
    NextTitle:  'Folgende Abbildung'
  });
}
<commit_msg>Fix some typos in the German locale. Three letter day shorts are not really used in German, it's better to use two letters for dayNamesShort, too.<commit_after>/**
 * RightJS UI Internationalization: German module
 *
 * Copyright (C) Nikolay V. Nemshilov aka St.
 */
if (self.Calendar) {
  $ext(Calendar.i18n, {
    Done:           'Erledigt',
    Now:            'Jetzt',
    Next:           'Nächster Monat',
    Prev:           'Vorhergehender Monat',
    NextYear:       'Nächstes Jahr',
    PrevYear:       'Vorhergehendes Jahr',

    dayNames:        $w('Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag'),
    dayNamesShort:   $w('So Mo Di Mi Do Fr Sa'),
    dayNamesMin:     $w('So Mo Di Mi Do Fr Sa'),
    monthNames:      $w('Januar Februar März April Mai Juni Juli August September Oktober November Dezember'),
    monthNamesShort: $w('Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez')
  });
}

if (self.Lightbox) {
  $ext(Lightbox.i18n, {
    CloseTitle: 'Abschluss',
    PrevTitle:  'Vorhergehende Abbildung',
    NextTitle:  'Folgende Abbildung'
  });
}
<|endoftext|>


<commit_before>function SpriteManager() {

	var sprites = new Array();

	/**
	 * add sprite to collection
	 *
	 * @return void
	 */
	this.addSprite = function(sprite) {
		sprite.setManager(this);
		sprites.push(sprite);
	};

	/**
	 * set player sprite that reacts on the mouse
	 *
	 * @return void
	 */
	this.setPlayer = function(next_player) {

		$.each(sprites, function(k, v) {
			v.setPlayer(false);
		});
		sprites[next_player].setPlayer(true);
	}

	/**
	 * print out manager status
	 *
	 * @return void
	 */
	this.status = function() {
		var status = {sprites: {}};
		$.each(sprites, function(k, sprite) {
			status.sprites[k] = {isPlayer: sprite.isPlayer(), object: sprite};
		});
		console.log(status);
	}

	/**
	 * update loop
	 *
	 * @return void
	 */
	this.updateSprites = function() {
		var self = this;
		window.setTimeout(function() {
			$.each(sprites, function(k, sprite) {
				sprite.update();
			});
			self.updateSprites();
		}, 1000 / 25);
	}

}
<commit_msg>change set player to accept an object<commit_after>function SpriteManager() {

	var sprites = new Array();

	/**
	 * add sprite to collection
	 *
	 * @return void
	 */
	this.addSprite = function(sprite) {
		sprite.setManager(this);
		sprites.push(sprite);
	};

	/**
	 * set player sprite that reacts on the mouse
	 *
	 * @param {Sprite} next_player
	 * @return void
	 */
	this.setPlayer = function(next_player) {
		$.each(sprites, function(k, v) {
			v.setPlayer(false);

			if (v == next_player) {
				next_player = k;
			}
		});

		sprites[next_player].setPlayer(true);
	}

	/**
	 * print out manager status
	 *
	 * @return void
	 */
	this.status = function() {
		var status = {sprites: {}};
		$.each(sprites, function(k, sprite) {
			status.sprites[k] = {isPlayer: sprite.isPlayer(), object: sprite};
		});
		console.log(status);
	}

	/**
	 * update loop
	 *
	 * @return void
	 */
	this.updateSprites = function() {
		var self = this;
		window.setTimeout(function() {
			$.each(sprites, function(k, sprite) {
				sprite.update();
			});
			self.updateSprites();
		}, 1000 / 25);
	}

}
<|endoftext|>


<commit_before>var noble = require('../index');

noble.on('stateChange', function(state) {
  if (state === 'poweredOn') {
    noble.startScanning();
  } else {
    noble.stopScanning();
  }
});

noble.on('discover', function(peripheral) {
  console.log('peripheral discovered (' + peripheral.uuid + ' with address ' + peripheral.address + ':');
  console.log('\thello my local name is:');
  console.log('\t\t' + peripheral.advertisement.localName);
  console.log('\tcan I interest you in any of the following advertised services:');
  console.log('\t\t' + JSON.stringify(peripheral.advertisement.serviceUuids));

  var serviceData = peripheral.advertisement.serviceData;
  if (serviceData && serviceData.length) {
    console.log('\there is my service data:');
    for (var i in serviceData) {
      console.log('\t\t' + JSON.stringify(serviceData[i].uuid) + ': ' + JSON.stringify(serviceData[i].data.toString('hex')));
    }
  }
  if (peripheral.advertisement.manufacturerData) {
    console.log('\there is my manufacturer data:');
    console.log('\t\t' + JSON.stringify(peripheral.advertisement.manufacturerData.toString('hex')));
  }
  if (peripheral.advertisement.txPowerLevel !== undefined) {
    console.log('\tmy TX power level is:');
    console.log('\t\t' + peripheral.advertisement.txPowerLevel);
  }

  console.log();
});

<commit_msg>- clearer formatting for address<commit_after>var noble = require('../index');

noble.on('stateChange', function(state) {
  if (state === 'poweredOn') {
    noble.startScanning();
  } else {
    noble.stopScanning();
  }
});

noble.on('discover', function(peripheral) {
  console.log('peripheral discovered (' + peripheral.uuid + ' with address <' + peripheral.address + '>:');
  console.log('\thello my local name is:');
  console.log('\t\t' + peripheral.advertisement.localName);
  console.log('\tcan I interest you in any of the following advertised services:');
  console.log('\t\t' + JSON.stringify(peripheral.advertisement.serviceUuids));

  var serviceData = peripheral.advertisement.serviceData;
  if (serviceData && serviceData.length) {
    console.log('\there is my service data:');
    for (var i in serviceData) {
      console.log('\t\t' + JSON.stringify(serviceData[i].uuid) + ': ' + JSON.stringify(serviceData[i].data.toString('hex')));
    }
  }
  if (peripheral.advertisement.manufacturerData) {
    console.log('\there is my manufacturer data:');
    console.log('\t\t' + JSON.stringify(peripheral.advertisement.manufacturerData.toString('hex')));
  }
  if (peripheral.advertisement.txPowerLevel !== undefined) {
    console.log('\tmy TX power level is:');
    console.log('\t\t' + peripheral.advertisement.txPowerLevel);
  }

  console.log();
});

<|endoftext|>


<commit_before>var app = angular.module('makeithappen');
app.run(['RenderService', 'PathResolver', '$rootScope', function(RenderService, PathResolver, $rootScope) {

    function PolymerControl() {

        var instance;
        var path;

        // set-up event binding
        document.addEventListener('WebComponentsReady', function() {
            var input = document.querySelector('paper-input');
            input.addEventListener('keyup', function() {
               instance[path] = input.value;
                $rootScope.$digest();
            });
        });

        return {
            priority: 100,
            render: function(element, schema, schemaPath, services) {
                var control = JSONForms.RenderDescriptionFactory.createControlDescription(schemaPath, services, element);
                var data = services.get(JSONForms.ServiceId.DataProvider).getData();
                path = PathResolver.toInstancePath(schemaPath);
                instance = data;
                control['template'] =
                 '
' +
                    '<paper-input type="text" value="{{element.instance[\'' + path + '\']}}" data-jsonforms-model label="Last name goes here"></paper-input>' +
                 '
';
                return control;
            },

            isApplicable: function (element, subSchema, schemaPath) {
                return element.type == "Control" && schemaPath.endsWith("lastName");
            }
        }
    }

    RenderService.register(new PolymerControl());
}]);<commit_msg>Fix  polymer example<commit_after>var app = angular.module('makeithappen');
app.run(['RenderService', 'PathResolver', '$rootScope', function(RenderService, PathResolver, $rootScope) {

    function PolymerControl() {

        var instance;
        var path;

        // set-up event binding
        document.addEventListener('WebComponentsReady', function() {
            var input = document.querySelector('paper-input');
            if (input) {
                input.addEventListener('keyup', function () {
                    instance[path] = input.value;
                    $rootScope.$digest();
                });
            }
        });

        return {
            priority: 100,
            render: function(element, schema, schemaPath, services) {
                var control = JSONForms.RenderDescriptionFactory.createControlDescription(schemaPath, services, element);
                var data = services.get(JSONForms.ServiceId.DataProvider).getData();
                path = PathResolver.toInstancePath(schemaPath);
                instance = data;
                control['template'] =
                 '
' +
                    '<paper-input type="text" value="{{element.instance[\'' + path + '\']}}" data-jsonforms-model label="Last name goes here"></paper-input>' +
                 '
';
                return control;
            },

            isApplicable: function (element, subSchema, schemaPath) {
                return element.type == "Control" && schemaPath.endsWith("lastName");
            }
        }
    }

    RenderService.register(new PolymerControl());
}]);<|endoftext|>


<commit_before>module.exports = (function () {
  'use strict';
  // body...
  return {
            db: {
                  development: {
                    connection: {
                      'user': 'tams',
                      'database': 'users'
                    }
                  },

                  test: {
                    'client': 'pg',
                    'connection': {
                      'host': 'localhost',
                      'user': 'tams',
                      'database': 'users-test'
                    }
                  }

                },

          };
})();<commit_msg>create local development and test database connections<commit_after>module.exports = (function () {
  'use strict';
  // body...
  return {
            db: {
                  development: {
                    'client': 'pg',
                    'connection': {
                      'host': 'localhost',
                      'user': 'tams',
                      'database': 'users'
                    }
                  },

                  test: {
                    'client': 'pg',
                    'connection': {
                      'host': 'localhost',
                      'user': 'tams',
                      'database': 'users-test'
                    }
                  }

                },

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


<commit_before>var sys = require('sys');
var spawn = require('child_process').spawn;
var os = require('os');
var path = require('path');
var fs = require('fs');
var commands = require('../commands/shadow');

exports.cliVersion = '>=3.2.0';
exports.version = '1.0';
exports.title = 'TiShadow Express';
exports.desc  = 'For very basic and quick tishadow usage';
exports.extendedDesc = 'Requires tishadow: `[sudo] npm install -g tishadow`';

exports.init = init;
var logger;
function init(_logger, config, cli) {
  if (process.argv.indexOf('--shadow') !== -1 || process.argv.indexOf('--tishadow') !== -1) {
    cli.addHook('build.pre.compile', preCompileHook(true));
  } else if (process.argv.indexOf('--appify') !== -1) {
    cli.addHook('build.pre.compile', preCompileHook(false));
  }
  logger = _logger;
}
function preCompileHook(isExpress) {
  return function (build, finished) {
    var new_project_dir = path.join(build.projectDir, 'build', 'appify');

    // get ip address

    var ifaces=os.networkInterfaces();
    var ip_address;
    for (var dev in ifaces) {
      ifaces[dev].forEach(function(details){
        if (details.family=='IPv4' && !details.internal) {
          ip_address = details.address;
        }
      });
    }

    var args = build.cli.argv.$_
         .filter(function(el) { return el !== "--shadow" && el !== "--tishadow" && el !== "--appify"})
         .concat(["--project-dir", new_project_dir]);
    commands.startAppify(logger, new_project_dir, build.cli.argv.platform, ip_address, function() {
      commands.buildApp(logger,args)
      if (isExpress) {
        commands.startServer(logger);
        commands.startWatch(logger, build.cli.argv.platform, ip_address);
      }
    });
  }
}
<commit_msg>Fix an issue where TiShadow just fails to work<commit_after>var sys = require('sys');
var spawn = require('child_process').spawn;
var os = require('os');
var path = require('path');
var fs = require('fs');
var commands = require('../commands/shadow');

exports.cliVersion = '>=3.2.0';
exports.version = '1.0';
exports.title = 'TiShadow Express';
exports.desc  = 'For very basic and quick tishadow usage';
exports.extendedDesc = 'Requires tishadow: `[sudo] npm install -g tishadow`';

exports.init = init;
var logger;
function init(_logger, config, cli) {
  // users who are on the wrong SDK without this being set... TiShadow would just fail to work at all
  cli.config.cli.failOnWrongSDK = true;
  if (process.argv.indexOf('--shadow') !== -1 || process.argv.indexOf('--tishadow') !== -1) {
    cli.addHook('build.pre.compile', preCompileHook(true));
  } else if (process.argv.indexOf('--appify') !== -1) {
    cli.addHook('build.pre.compile', preCompileHook(false));
  }
  logger = _logger;
}
function preCompileHook(isExpress) {
  return function (build, finished) {
    var new_project_dir = path.join(build.projectDir, 'build', 'appify');

    // get ip address

    var ifaces=os.networkInterfaces();
    var ip_address;
    for (var dev in ifaces) {
      ifaces[dev].forEach(function(details){
        if (details.family=='IPv4' && !details.internal) {
          ip_address = details.address;
        }
      });
    }

    var args = build.cli.argv.$_
         .filter(function(el) { return el !== "--shadow" && el !== "--tishadow" && el !== "--appify"})
         .concat(["--project-dir", new_project_dir]);
    commands.startAppify(logger, new_project_dir, build.cli.argv.platform, ip_address, function() {
      commands.buildApp(logger,args)
      if (isExpress) {
        commands.startServer(logger);
        commands.startWatch(logger, build.cli.argv.platform, ip_address);
      }
    });
  }
}
<|endoftext|>