<commit_before>(function (root, factory) {
    // Using the Universal Module Definition pattern from
    // https://github.com/umdjs/umd/blob/master/returnExports.js
    if (typeof define === 'function' && define.amd) {
        define(['iscroll', 'platform'], factory);
    } else if (typeof exports === 'object') {
        module.exports = factory(require('iscroll'), require('platform'));
    } else {
        // Browser globals (root is window)
        root.angularIscroll = factory(root.IScroll, root.platform);
    }
}(this, function (IScroll, platform) {
    'use strict';

    var signals = {
            disabled: 'iscroll:disabled',
            enabled: 'iscroll:enabled',
            refresh: 'iscroll:refresh'
        },
        classes = {
            on: 'iscroll-on',
            off: 'iscroll-off'
        },
        iScrollEvents = [
            'beforeScrollStart',
            'scrollCancel',
            'scrollStart',
            'scroll',
            'scrollEnd',
            'flick',
            'zoomStart',
            'zoomEnd'
        ],
        iScrollEventHandlerMap = {},
        minIOSMajorVersion = 7,
        useNativeScroll = _useNativeScroll();

    function _osVersion() {
        var v = (platform.os.version).match(/(\d+).(\d+).?(\d+)?/);
        return [
            parseInt(v[1], 10),
            parseInt(v[2], 10),
            parseInt(v[3] || 0, 10)
        ];
    }

    function _isChromeMobile() {
        return platform.name === 'Chrome Mobile';
    }

    function _useNativeScroll() {
        if (platform.name === 'Opera Mini') {
            return false;
        }

        switch (platform.os.family) {
            case 'Android':
                // In Chrome we trust.
                return _isChromeMobile();
            case 'iOS':
                // Buggy handling in older iOS versions.
                return _osVersion()[0] > minIOSMajorVersion;
            default:
                // Assuming desktop or other browser.
                return true;
        }
    }

    /**
     * Add handler name to event name mapping.
     *
     * Please note that the 'scroll' event is only available when using
     * iscroll-probe.js (for example, through angular-iscroll-probe).
     *
     * For example, the handler for the 'scrollEnd' event can be configured
     * by supplying the onScrollEnd option.
     **/
    angular.forEach(iScrollEvents, function _addPair(event) {
        this['on' + _capitalizeFirst(event)] = event;
    }, iScrollEventHandlerMap);

    function _capitalizeFirst(str) {
        return str.substring(0, 1).toLocaleUpperCase() + str.substring(1);
    }

    function iScrollServiceProvider() {
        var defaultOptions = {
            iScroll: {
                /**
                 * The different options for iScroll are explained in
                 * detail at http://iscrolljs.com/#configuring
                 **/
                momentum: true,
                mouseWheel: true
            },
            directive: {
                /**
                 * Whether or not to initially enable the use of iScroll.
                 *
                 * The `useNativeScroll` flag is automatically determined
                 * by running _useNativeScroll();
                 **/
                initiallyEnabled: !useNativeScroll,
                /**
                 * Delay, in ms, before we asynchronously perform an
                 * iScroll.refresh().  If false, then no async refresh is
                 * performed.
                 **/
                asyncRefreshDelay: 0,
                /**
                 * Delay, in ms, between each iScroll.refresh().  If false,
                 * then no periodic refresh is performed.
                 **/
                refreshInterval: false,
                /**
                 * If `false`, skip `$digest()` cycle on iScroll.refresh().
                 */
                invokeApply: false
                /**
                 * Event handler options are added below.
                 **/
            }
        };

        angular.forEach(iScrollEventHandlerMap, function _default(event, handler) {
            this[handler] = undefined;
        }, defaultOptions.directive);

        function _configureDefaults(options) {
            /**
             * Since angular.extend is not performing a "deep" merge, we'll
             * do it in two steps.
             **/
            if (angular.isDefined(options.directive)) {
                angular.extend(defaultOptions.directive, options.directive);
            }
            if (angular.isDefined(options.iScroll)) {
                angular.extend(defaultOptions.iScroll, options.iScroll);
            }
        }

        // Export the auto-determined value of `useNativeScroll`.
        this.useNativeScroll = useNativeScroll;

        this.configureDefaults = _configureDefaults;
        function _getDefaults() {
            return defaultOptions;
        }

        //noinspection JSUnusedGlobalSymbols
        this.getDefaults = _getDefaults;

        /* @ngInject */
        function iScrollService($rootScope, iScrollSignals) {
            var _state = {
                useIScroll: defaultOptions.directive.initiallyEnabled
            };

            function _disable(signalOnly) {
                if (!signalOnly) {
                    _state.useIScroll = false;
                }
                //$log.debug('emit(iScrollSignals.disabled)',
                //    iScrollSignals.disabled);
                $rootScope.$emit(iScrollSignals.disabled);
            }

            function _enable(signalOnly) {
                if (!signalOnly) {
                    _state.useIScroll = true;
                }
                //$log.debug('emit(iScrollSignals.enabled)',
                //    iScrollSignals.enabled);
                $rootScope.$emit(iScrollSignals.enabled);
            }

            function _toggle(signalOnly) {
                (_state.useIScroll ^ signalOnly) ?  // XOR
                    _disable(signalOnly) : _enable(signalOnly);
            }

            function _refresh(name) {
                // The name parameter is not really used for now.
                $rootScope.$emit(iScrollSignals.refresh, name);
            }

            return {
                defaults: defaultOptions,
                state: _state,
                enable: _enable,
                disable: _disable,
                toggle: _toggle,
                refresh: _refresh
            };
        }

        //noinspection JSUnusedGlobalSymbols
        this.$get = iScrollService;
    }

    function _call(functor) {
        functor();
    }

    /* @ngInject */
    function iscroll($rootScope, $timeout, $interval, iScrollSignals,
                     iScrollService) {
        function asyncRefresh(instance, options) {
            $timeout(function _refreshAfterInitialRender() {
                instance.refresh();
            }, options.directive.asyncRefreshDelay, options.directive.invokeApply);
        }

        function _createInstance(scope, element, attrs, options) {
            var instance = new IScroll(element[0], options.iScroll),
                refreshEnabled = true,
                refreshInterval = null;

            angular.forEach(iScrollEventHandlerMap,
                function _addHandler(event, option) {
                    if (angular.isDefined(options.directive[option])) {
                        instance.on(event, options.directive[option]);
                    }
                });

            element.removeClass(classes.off).addClass(classes.on);

            if (angular.isDefined(attrs.iscrollInstance)) {
                scope.iscrollInstance = instance;
            }

            if (options.directive.asyncRefreshDelay !== false) {
                asyncRefresh(instance, options);
            }

            function _destroyInstance() {
                if (refreshInterval !== null) {
                    $interval.cancel(refreshInterval);
                }

                if (angular.isDefined(scope.iscrollInstance)) {
                    delete scope.iscrollInstance;
                }
                instance.destroy();

                element.removeClass(classes.on).addClass(classes.off);
                // Remove element's CSS transition values:
                element.children('.iscroll-scroller').attr('style', null);

                angular.forEach(deregistrators, _call);
                //$log.debug('angular-iscroll: destroyInstance');
            }

            function _refreshInstance() {
                if (refreshEnabled) {
                    //noinspection JSUnusedAssignment
                    refreshEnabled = false;
                    asyncRefresh(instance, options);
                    refreshEnabled = true;
                }
            }

            function _disableRefresh() {
                refreshEnabled = false;
            }

            function _enableRefresh() {
                refreshEnabled = true;
            }

            instance.on('scrollStart', _disableRefresh);
            instance.on('scrollEnd', _enableRefresh);

            if (options.directive.refreshInterval !== false) {
                refreshInterval = $interval(_refreshInstance,
                    options.directive.refreshInterval, 0, options.directive.invokeApply);
            }

            var deregistrators = [
                $rootScope.$on(iScrollSignals.disabled, _destroyInstance),
                $rootScope.$on(iScrollSignals.refresh, _refreshInstance),
                scope.$on('$destroy', _destroyInstance)
            ];

            return instance;
        }

        function _link(scope, element, attrs) {
            var options = {
                iScroll: angular.extend({}, scope.iscroll || {},
                    iScrollService.defaults.iScroll),
                directive: angular.extend({}, iScrollService.defaults.directive)
            };

            angular.forEach(options.iScroll,
                function _extractOptions(value, key) {
                    if (iScrollService.defaults.directive.hasOwnProperty(key) ||
                        iScrollEventHandlerMap.hasOwnProperty(key)) {
                        options.directive[key] = value;
                        delete options.iScroll[key];
                    }
                }
            );

            function _init() {
                if (!element.hasClass(classes.on)) {
                    _createInstance(scope, element, attrs, options);
                }
            }

            var enableHandlers = [$rootScope.$on(iScrollSignals.enabled, _init)];

            function _removeEnableHandlers() {
                angular.forEach(enableHandlers, _call);
            }

            if (iScrollService.state.useIScroll) {
                _init();
            } else {
                element.removeClass(classes.on).addClass(classes.off);
            }

            scope.$on('$destroy', _removeEnableHandlers);
        }

        return {
            restrict: 'A',
            link: _link,
            scope: {
                iscroll: '=',
                iscrollInstance: '='
            }
        };
    }

    return angular.module('angular-iscroll', [])
        .directive('iscroll', iscroll)
        .provider('iScrollService', iScrollServiceProvider)
        .constant('iScrollSignals', signals);
}));

<commit_msg>#25: Automatically detect the need for using iScroll.<commit_after>(function (root, factory) {
    // Using the Universal Module Definition pattern from
    // https://github.com/umdjs/umd/blob/master/returnExports.js
    if (typeof define === 'function' && define.amd) {
        define(['iscroll', 'platform'], factory);
    } else if (typeof exports === 'object') {
        module.exports = factory(require('iscroll'), require('platform'));
    } else {
        // Browser globals (root is window)
        root.angularIscroll = factory(root.IScroll, root.platform);
    }
}(this, function (IScroll, platform) {
    'use strict';

    var signals = {
            disabled: 'iscroll:disabled',
            enabled: 'iscroll:enabled',
            refresh: 'iscroll:refresh'
        },
        classes = {
            on: 'iscroll-on',
            off: 'iscroll-off'
        },
        iScrollEvents = [
            'beforeScrollStart',
            'scrollCancel',
            'scrollStart',
            'scroll',
            'scrollEnd',
            'flick',
            'zoomStart',
            'zoomEnd'
        ],
        iScrollEventHandlerMap = {},
        minIOSMajorVersion = 7,
        useNativeScroll = _useNativeScroll();

    function _osVersion() {
        var v = (platform.os.version).match(/(\d+).(\d+).?(\d+)?/);
        return [
            parseInt(v[1], 10),
            parseInt(v[2], 10),
            parseInt(v[3] || 0, 10)
        ];
    }

    function _isChromeMobile() {
        return platform.name === 'Chrome Mobile';
    }

    function _useNativeScroll() {
        if (platform.name === 'Opera Mini') {
            return false;
        }

        switch (platform.os.family) {
            case 'Android':
                // In Chrome we trust.
                return _isChromeMobile();
            case 'iOS':
                // Buggy handling in older iOS versions.
                return _osVersion()[0] > minIOSMajorVersion;
            default:
                // Assuming desktop or other browser.
                return true;
        }
    }

    /**
     * Add handler name to event name mapping.
     *
     * Please note that the 'scroll' event is only available when using
     * iscroll-probe.js (for example, through angular-iscroll-probe).
     *
     * For example, the handler for the 'scrollEnd' event can be configured
     * by supplying the onScrollEnd option.
     **/
    angular.forEach(iScrollEvents, function _addPair(event) {
        this['on' + _capitalizeFirst(event)] = event;
    }, iScrollEventHandlerMap);

    function _capitalizeFirst(str) {
        return str.substring(0, 1).toLocaleUpperCase() + str.substring(1);
    }

    function iScrollServiceProvider() {
        var defaultOptions = {
            iScroll: {
                /**
                 * The different options for iScroll are explained in
                 * detail at http://iscrolljs.com/#configuring
                 **/
                momentum: true,
                mouseWheel: true
            },
            directive: {
                /**
                 * Whether or not to initially enable the use of iScroll.
                 *
                 * The `useNativeScroll` flag is automatically determined
                 * by running _useNativeScroll();
                 **/
                initiallyEnabled: !useNativeScroll,
                /**
                 * Delay, in ms, before we asynchronously perform an
                 * iScroll.refresh().  If false, then no async refresh is
                 * performed.
                 **/
                asyncRefreshDelay: 0,
                /**
                 * Delay, in ms, between each iScroll.refresh().  If false,
                 * then no periodic refresh is performed.
                 **/
                refreshInterval: false,
                /**
                 * If `false`, skip `$digest()` cycle on iScroll.refresh().
                 */
                invokeApply: false
                /**
                 * Event handler options are added below.
                 **/
            }
        };

        angular.forEach(iScrollEventHandlerMap, function _default(event, handler) {
            this[handler] = undefined;
        }, defaultOptions.directive);

        function _configureDefaults(options) {
            /**
             * Since angular.extend is not performing a "deep" merge, we'll
             * do it in two steps.
             **/
            if (angular.isDefined(options.directive)) {
                angular.extend(defaultOptions.directive, options.directive);
            }
            if (angular.isDefined(options.iScroll)) {
                angular.extend(defaultOptions.iScroll, options.iScroll);
            }
        }

        // Export the auto-determined value of `useNativeScroll`.
        this.useNativeScroll = useNativeScroll;
        this.platform = platform;

        this.configureDefaults = _configureDefaults;
        function _getDefaults() {
            return defaultOptions;
        }

        //noinspection JSUnusedGlobalSymbols
        this.getDefaults = _getDefaults;

        /* @ngInject */
        function iScrollService($rootScope, iScrollSignals) {
            var _state = {
                useIScroll: defaultOptions.directive.initiallyEnabled,
                autoDetectedUseNativeScroll: useNativeScroll
            };

            function _disable(signalOnly) {
                if (!signalOnly) {
                    _state.useIScroll = false;
                }
                //$log.debug('emit(iScrollSignals.disabled)',
                //    iScrollSignals.disabled);
                $rootScope.$emit(iScrollSignals.disabled);
            }

            function _enable(signalOnly) {
                if (!signalOnly) {
                    _state.useIScroll = true;
                }
                //$log.debug('emit(iScrollSignals.enabled)',
                //    iScrollSignals.enabled);
                $rootScope.$emit(iScrollSignals.enabled);
            }

            function _toggle(signalOnly) {
                (_state.useIScroll ^ signalOnly) ?  // XOR
                    _disable(signalOnly) : _enable(signalOnly);
            }

            function _refresh(name) {
                // The name parameter is not really used for now.
                $rootScope.$emit(iScrollSignals.refresh, name);
            }

            return {
                defaults: defaultOptions,
                state: _state,
                enable: _enable,
                disable: _disable,
                toggle: _toggle,
                refresh: _refresh
            };
        }

        //noinspection JSUnusedGlobalSymbols
        this.$get = iScrollService;
    }

    function _call(functor) {
        functor();
    }

    /* @ngInject */
    function iscroll($rootScope, $timeout, $interval, iScrollSignals,
                     iScrollService) {
        function asyncRefresh(instance, options) {
            $timeout(function _refreshAfterInitialRender() {
                instance.refresh();
            }, options.directive.asyncRefreshDelay, options.directive.invokeApply);
        }

        function _createInstance(scope, element, attrs, options) {
            var instance = new IScroll(element[0], options.iScroll),
                refreshEnabled = true,
                refreshInterval = null;

            angular.forEach(iScrollEventHandlerMap,
                function _addHandler(event, option) {
                    if (angular.isDefined(options.directive[option])) {
                        instance.on(event, options.directive[option]);
                    }
                });

            element.removeClass(classes.off).addClass(classes.on);

            if (angular.isDefined(attrs.iscrollInstance)) {
                scope.iscrollInstance = instance;
            }

            if (options.directive.asyncRefreshDelay !== false) {
                asyncRefresh(instance, options);
            }

            function _destroyInstance() {
                if (refreshInterval !== null) {
                    $interval.cancel(refreshInterval);
                }

                if (angular.isDefined(scope.iscrollInstance)) {
                    delete scope.iscrollInstance;
                }
                instance.destroy();

                element.removeClass(classes.on).addClass(classes.off);
                // Remove element's CSS transition values:
                element.children('.iscroll-scroller').attr('style', null);

                angular.forEach(deregistrators, _call);
                //$log.debug('angular-iscroll: destroyInstance');
            }

            function _refreshInstance() {
                if (refreshEnabled) {
                    //noinspection JSUnusedAssignment
                    refreshEnabled = false;
                    asyncRefresh(instance, options);
                    refreshEnabled = true;
                }
            }

            function _disableRefresh() {
                refreshEnabled = false;
            }

            function _enableRefresh() {
                refreshEnabled = true;
            }

            instance.on('scrollStart', _disableRefresh);
            instance.on('scrollEnd', _enableRefresh);

            if (options.directive.refreshInterval !== false) {
                refreshInterval = $interval(_refreshInstance,
                    options.directive.refreshInterval, 0, options.directive.invokeApply);
            }

            var deregistrators = [
                $rootScope.$on(iScrollSignals.disabled, _destroyInstance),
                $rootScope.$on(iScrollSignals.refresh, _refreshInstance),
                scope.$on('$destroy', _destroyInstance)
            ];

            return instance;
        }

        function _link(scope, element, attrs) {
            var options = {
                iScroll: angular.extend({}, scope.iscroll || {},
                    iScrollService.defaults.iScroll),
                directive: angular.extend({}, iScrollService.defaults.directive)
            };

            angular.forEach(options.iScroll,
                function _extractOptions(value, key) {
                    if (iScrollService.defaults.directive.hasOwnProperty(key) ||
                        iScrollEventHandlerMap.hasOwnProperty(key)) {
                        options.directive[key] = value;
                        delete options.iScroll[key];
                    }
                }
            );

            function _init() {
                if (!element.hasClass(classes.on)) {
                    _createInstance(scope, element, attrs, options);
                }
            }

            var enableHandlers = [$rootScope.$on(iScrollSignals.enabled, _init)];

            function _removeEnableHandlers() {
                angular.forEach(enableHandlers, _call);
            }

            if (iScrollService.state.useIScroll) {
                _init();
            } else {
                element.removeClass(classes.on).addClass(classes.off);
            }

            scope.$on('$destroy', _removeEnableHandlers);
        }

        return {
            restrict: 'A',
            link: _link,
            scope: {
                iscroll: '=',
                iscrollInstance: '='
            }
        };
    }

    return angular.module('angular-iscroll', [])
        .directive('iscroll', iscroll)
        .provider('iScrollService', iScrollServiceProvider)
        .constant('iScrollSignals', signals);
}));

<|endoftext|>


<commit_before>import { Duration, isDuration } from './constructor';
import isNumber from '../utils/is-number';
import toInt from '../utils/to-int';
import absRound from '../utils/abs-round';
import hasOwnProp from '../utils/has-own-prop';
import { DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants';
import { cloneWithOffset } from '../units/offset';
import { createLocal } from '../create/local';
import { createInvalid as invalid } from './valid';

// ASP.NET json date format regex
var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;

// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
// and further modified to allow for strings containing both week and day
var isoRegex = /^(-|\+)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;

export function createDuration (input, key) {
    var duration = input,
        // matching against regexp is expensive, do it on demand
        match = null,
        sign,
        ret,
        diffRes;

    if (isDuration(input)) {
        duration = {
            ms : input._milliseconds,
            d  : input._days,
            M  : input._months
        };
    } else if (isNumber(input)) {
        duration = {};
        if (key) {
            duration[key] = input;
        } else {
            duration.milliseconds = input;
        }
    } else if (!!(match = aspNetRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
        duration = {
            y  : 0,
            d  : toInt(match[DATE])                         * sign,
            h  : toInt(match[HOUR])                         * sign,
            m  : toInt(match[MINUTE])                       * sign,
            s  : toInt(match[SECOND])                       * sign,
            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
        };
    } else if (!!(match = isoRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
        duration = {
            y : parseIso(match[2], sign),
            M : parseIso(match[3], sign),
            w : parseIso(match[4], sign),
            d : parseIso(match[5], sign),
            h : parseIso(match[6], sign),
            m : parseIso(match[7], sign),
            s : parseIso(match[8], sign)
        };
    } else if (duration == null) {// checks for null or undefined
        duration = {};
    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));

        duration = {};
        duration.ms = diffRes.milliseconds;
        duration.M = diffRes.months;
    }

    ret = new Duration(duration);

    if (isDuration(input) && hasOwnProp(input, '_locale')) {
        ret._locale = input._locale;
    }

    return ret;
}

createDuration.fn = Duration.prototype;
createDuration.invalid = invalid;

function parseIso (inp, sign) {
    // We'd normally use ~~inp for this, but unfortunately it also
    // converts floats to ints.
    // inp may be undefined, so careful calling replace on it.
    var res = inp && parseFloat(inp.replace(',', '.'));
    // apply sign while we're at it
    return (isNaN(res) ? 0 : res) * sign;
}

function positiveMomentsDifference(base, other) {
    var res = {milliseconds: 0, months: 0};

    res.months = other.month() - base.month() +
        (other.year() - base.year()) * 12;
    if (base.clone().add(res.months, 'M').isAfter(other)) {
        --res.months;
    }

    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));

    return res;
}

function momentsDifference(base, other) {
    var res;
    if (!(base.isValid() && other.isValid())) {
        return {milliseconds: 0, months: 0};
    }

    other = cloneWithOffset(other, base);
    if (base.isBefore(other)) {
        res = positiveMomentsDifference(base, other);
    } else {
        res = positiveMomentsDifference(other, base);
        res.milliseconds = -res.milliseconds;
        res.months = -res.months;
    }

    return res;
}
<commit_msg>Updated regex to support + sign in between the string<commit_after>import { Duration, isDuration } from './constructor';
import isNumber from '../utils/is-number';
import toInt from '../utils/to-int';
import absRound from '../utils/abs-round';
import hasOwnProp from '../utils/has-own-prop';
import { DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants';
import { cloneWithOffset } from '../units/offset';
import { createLocal } from '../create/local';
import { createInvalid as invalid } from './valid';

// ASP.NET json date format regex
var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;

// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
// and further modified to allow for strings containing both week and day
var isoRegex = /^(-|\+)?P(?:((?:-|\+)?[0-9,.]*)Y)?(?:((?:-|\+)?[0-9,.]*)M)?(?:((?:-|\+)?[0-9,.]*)W)?(?:((?:-|\+)?[0-9,.]*)D)?(?:T(?:((?:-|\+)?[0-9,.]*)H)?(?:((?:-|\+)?[0-9,.]*)M)?(?:((?:-|\+)?[0-9,.]*)S)?)?$/;

export function createDuration (input, key) {
    var duration = input,
        // matching against regexp is expensive, do it on demand
        match = null,
        sign,
        ret,
        diffRes;

    if (isDuration(input)) {
        duration = {
            ms : input._milliseconds,
            d  : input._days,
            M  : input._months
        };
    } else if (isNumber(input)) {
        duration = {};
        if (key) {
            duration[key] = input;
        } else {
            duration.milliseconds = input;
        }
    } else if (!!(match = aspNetRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
        duration = {
            y  : 0,
            d  : toInt(match[DATE])                         * sign,
            h  : toInt(match[HOUR])                         * sign,
            m  : toInt(match[MINUTE])                       * sign,
            s  : toInt(match[SECOND])                       * sign,
            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
        };
    } else if (!!(match = isoRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
        duration = {
            y : parseIso(match[2], sign),
            M : parseIso(match[3], sign),
            w : parseIso(match[4], sign),
            d : parseIso(match[5], sign),
            h : parseIso(match[6], sign),
            m : parseIso(match[7], sign),
            s : parseIso(match[8], sign)
        };
    } else if (duration == null) {// checks for null or undefined
        duration = {};
    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));

        duration = {};
        duration.ms = diffRes.milliseconds;
        duration.M = diffRes.months;
    }

    ret = new Duration(duration);

    if (isDuration(input) && hasOwnProp(input, '_locale')) {
        ret._locale = input._locale;
    }

    return ret;
}

createDuration.fn = Duration.prototype;
createDuration.invalid = invalid;

function parseIso (inp, sign) {
    // We'd normally use ~~inp for this, but unfortunately it also
    // converts floats to ints.
    // inp may be undefined, so careful calling replace on it.
    var res = inp && parseFloat(inp.replace(',', '.'));
    // apply sign while we're at it
    return (isNaN(res) ? 0 : res) * sign;
}

function positiveMomentsDifference(base, other) {
    var res = {milliseconds: 0, months: 0};

    res.months = other.month() - base.month() +
        (other.year() - base.year()) * 12;
    if (base.clone().add(res.months, 'M').isAfter(other)) {
        --res.months;
    }

    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));

    return res;
}

function momentsDifference(base, other) {
    var res;
    if (!(base.isValid() && other.isValid())) {
        return {milliseconds: 0, months: 0};
    }

    other = cloneWithOffset(other, base);
    if (base.isBefore(other)) {
        res = positiveMomentsDifference(base, other);
    } else {
        res = positiveMomentsDifference(other, base);
        res.milliseconds = -res.milliseconds;
        res.months = -res.months;
    }

    return res;
}
<|endoftext|>


<commit_before>
module.exports.entity = function(entity, serv) {
  entity.effects = {};
  for (let i = 1; i <= 23; i++) { // 23 in 1.8, 27 in 1.9
    entity.effects[i] = null; // Just so we know it's a real potion and not undefined/not existant
  }

  entity.sendEffect = (effectId, {amplifier=0,duration=30*20,particles=true,whitelist,blacklist=[]}={}) => {
    if (!whitelist) whitelist = serv.getNearby(entity);
    if (entity.type == 'player' && [1].indexOf(effectId) != -1) entity.sendAbilities();
    const sendTo = whitelist.filter(p => blacklist.indexOf(p) == -1);
    const data = {
      entityId: entity.id,
      effectId: effectId,
      amplifier: amplifier,
      duration: duration,
      hideParticles: !particles
    };
    serv._writeArray('entity_effect', data, sendTo);
  };

  entity.sendRemoveEffect = (effectId, {whitelist,blacklist=[]}={}) => {
    if (!whitelist) whitelist = serv.getNearby(entity);
    const sendTo = whitelist.filter(p => blacklist.indexOf(p) == -1);
    serv._writeArray('remove_entity_effect', {
      entityId: entity.id,
      effectId: effectId
    }, sendTo);
  };

  entity.addEffect = (effectId, opt={}) => {
    const amp = typeof opt.amplifier == 'undefined' ? 0 : opt.amplifier;
    if (!entity.effects[effectId] || opt.override || amp < entity.effects[effectId].amplifier) {
      entity.effects[effectId] = {
        amplifier: opt.amplifier || 0,
        duration: opt.duration || 30*20,
        particles: opt.particles || true,
        end: Date.now() + (opt.duration || 30*20)*1000/20 // 1000/20 == convert from ticks to milliseconds
      };
      entity.sendEffect(effectId, opt);
      return true;
    } else return false;
  };

  entity.removeEffect = (effectId, opt) => {
    entity.effects[effectId] = null;
    entity.sendRemoveEffect(effectId, opt);
  };

  serv.on('tick', () => {
    Object.keys(entity.effects).forEach(effectId => {
      const e = entity.effects[effectId];
      if (e && e.end <= Date.now()) entity.removeEffect(effectId);
    });
  });
};

module.exports.player = function(player) {
  player.commands.add({
    base: 'effect',
    info: 'Give player an effect',
    usage: '/effect <player> <effect> [seconds] [amplifier] [hideParticles]',
    parse(str) {
      return str.match(/(.+?) (\d+)(?: (\d+))?(?: (\d+))?(?: (true|false))?|.*? clear/) || false;
    },
    action(params) {
      const targets = player.selectorString(params[1]);
      if (params[2] == 'clear') {
        targets.forEach(e => Object.keys(e.effects).forEach(effectId => {
          if (e.effects[effectId] != null) e.removeEffect(effectId);
        }));
      } else {
        targets.forEach(e => {
          const effId = parseInt(params[2]);
          if (e.effects[effId]) {
            e.removeEffect(effId);
          }
          e.addEffect(effId, {
            amplifier: parseInt(params[4]) || 0,
            duration: parseInt(params[3]) * 20 || 30 * 20,
            particles: params[5] != 'true' // hidesParticles vs particles (i.e. "showParticles")
          });
        });
      }
      const chatSelect = (targets.length == 1 ? (targets[0].type == 'player' ? targets[0].username : 'entity') : 'entities');
      if (params[2] == 'clear') player.chat('Remove all effects from ' + chatSelect + '.' );
      else player.chat('Gave ' + chatSelect + ' effect ' + params[2] + '(' + (params[4] || 0) + ') for ' +
                        (parseInt(params[3]) || 30) + ' seconds');
    }
  });
};<commit_msg>don't rely on ticks to remove effect : ticks slow down the server and should only be used if strictly necessary<commit_after>
module.exports.entity = function(entity, serv) {
  entity.effects = {};
  for (let i = 1; i <= 23; i++) { // 23 in 1.8, 27 in 1.9
    entity.effects[i] = null; // Just so we know it's a real potion and not undefined/not existant
  }

  entity.sendEffect = (effectId, {amplifier=0,duration=30*20,particles=true,whitelist,blacklist=[]}={}) => {
    if (!whitelist) whitelist = serv.getNearby(entity);
    if (entity.type == 'player' && [1].indexOf(effectId) != -1) entity.sendAbilities();
    const sendTo = whitelist.filter(p => blacklist.indexOf(p) == -1);
    const data = {
      entityId: entity.id,
      effectId: effectId,
      amplifier: amplifier,
      duration: duration,
      hideParticles: !particles
    };
    serv._writeArray('entity_effect', data, sendTo);
  };

  entity.sendRemoveEffect = (effectId, {whitelist,blacklist=[]}={}) => {
    if (!whitelist) whitelist = serv.getNearby(entity);
    const sendTo = whitelist.filter(p => blacklist.indexOf(p) == -1);
    serv._writeArray('remove_entity_effect', {
      entityId: entity.id,
      effectId: effectId
    }, sendTo);
  };

  entity.addEffect = (effectId, opt={}) => {
    const amp = typeof opt.amplifier == 'undefined' ? 0 : opt.amplifier;
    if (!entity.effects[effectId] || opt.override || amp < entity.effects[effectId].amplifier) {
      entity.effects[effectId] = {
        amplifier: opt.amplifier || 0,
        duration: opt.duration || 30*20,
        particles: opt.particles || true,
        end: Date.now() + (opt.duration || 30*20)*1000/20, // 1000/20 == convert from ticks to milliseconds,
        timeout:setTimeout(() => entity.removeEffect(effectId),(opt.duration || 30*20)*1000/20)
      };
      entity.sendEffect(effectId, opt);
      return true;
    } else return false;
  };

  entity.removeEffect = (effectId, opt) => {
    clearTimeout(entity.effects[effectId].timeout);
    entity.effects[effectId] = null;
    entity.sendRemoveEffect(effectId, opt);
  };
};

module.exports.player = function(player) {
  player.commands.add({
    base: 'effect',
    info: 'Give player an effect',
    usage: '/effect <player> <effect> [seconds] [amplifier] [hideParticles]',
    parse(str) {
      return str.match(/(.+?) (\d+)(?: (\d+))?(?: (\d+))?(?: (true|false))?|.*? clear/) || false;
    },
    action(params) {
      const targets = player.selectorString(params[1]);
      if (params[2] == 'clear') {
        targets.forEach(e => Object.keys(e.effects).forEach(effectId => {
          if (e.effects[effectId] != null) e.removeEffect(effectId);
        }));
      } else {
        targets.forEach(e => {
          const effId = parseInt(params[2]);
          if (e.effects[effId]) {
            e.removeEffect(effId);
          }
          e.addEffect(effId, {
            amplifier: parseInt(params[4]) || 0,
            duration: parseInt(params[3]) * 20 || 30 * 20,
            particles: params[5] != 'true' // hidesParticles vs particles (i.e. "showParticles")
          });
        });
      }
      const chatSelect = (targets.length == 1 ? (targets[0].type == 'player' ? targets[0].username : 'entity') : 'entities');
      if (params[2] == 'clear') player.chat('Remove all effects from ' + chatSelect + '.' );
      else player.chat('Gave ' + chatSelect + ' effect ' + params[2] + '(' + (params[4] || 0) + ') for ' +
                        (parseInt(params[3]) || 30) + ' seconds');
    }
  });
};<|endoftext|>


<commit_before>// Dependencies

const {checkIsNotNull} = require('focus-core').util.object;
const {builder, types} = require('focus-core').component;
const find = require('lodash/collection/find');
const {omit} = require('lodash/object');
const {isArray} = require('lodash/lang');
import {clone} from 'lodash/lang';
import {reduce} from 'lodash/collection';

// Mixins

const translationMixin = require('../../common/i18n').mixin;
const infiniteScrollMixin = require('../mixin/infinite-scroll').mixin;
const referenceMixin = require('../../common/mixin/reference-property');

// Components

const Button = require('../../common/button/action').component;

const listMixin = {
    /**
    * Display name.
    */
    displayName: 'selection-list',

    /**
    * Mixin dependancies.
    */
    mixins: [translationMixin, infiniteScrollMixin, referenceMixin],

    /**
    * Default properties for the list.
    * @returns {{isSelection: boolean}} the default properties
    */
    getDefaultProps: function getListDefaultProps(){
        return {
            data: [],
            isSelection: true,
            selectionStatus: 'partial',
            selectionData: [],
            isLoading: false,
            operationList: [],
            idField: 'id'
        };
    },

    /**
    * list property validation.
    * @type {Object}
    */
    propTypes: {
        LineComponent: types('func'),
        buttonComponent: types('func'),
        data: types('array'),
        idField: types('string'),
        isLoading: types('bool'),
        isSelection: types('bool'),
        loader: types('func'),
        onLineClick: types('func'),
        onSelection: types('func'),
        operationList: types(['array', 'object']),
        selectionData: types('array'),
        selectionStatus: types('string')
    },

    getInitialState() {
        return {
            selectedItems: null
        }
    },

    /**
    * Return selected items in the list.
    * @return {Array} selected items
    */
    getSelectedItems() {
        const {selectedItems} = this.state;
        if (selectedItems !== null) {
            const selectedItems = [];
            for (let [item, isSelected] of this.state.selectedItems) {
                if (isSelected) selectedItems.push(item);
            }
            return selectedItems;
        } else {
            return reduce(this.refs, (acc, ref) => {
                if (ref.getValue) {
                    const {item, isSelected} = ref.getValue();
                    if (isSelected) acc.push(item);
                }
                return acc;
            }, []);
        }
    },

    _handleLineSelection(data, isSelected) {
        const {selectedItems} = this.state;
        const newSelectedItems = new Map();
        if (selectedItems !== null) {
            for (let [key, value] of selectedItems) {
                newSelectedItems.set(key, value);
            }
        }
        newSelectedItems.set(data, value);
        this.setState({selectedItems: newSelectedItems});
    },

    /**
    * Render lines of the list.
    * @returns {*} DOM for lines
    */
    _renderLines() {
        const {data, LineComponent: Line, selectionData, idField, selectionStatus, ...otherProps} = this.props;
        // LEGACY CODE
        const customLineComponent = otherProps.lineComponent;
        if (customLineComponent) {
            console.warn(`%c DEPRECATED : You are using the lineComponent prop in a list component, this will be removed in the next release of Focus Components. Please use LineComponent prop instead.`, `color: #FF9C00; font-weight: bold`);
        }
        const FinalLineComponent = customLineComponent || Line;
        // END OF LEGACY CODE
        if(!isArray(data)){
            console.error(
                'List: Lines: it seems data is not an array, please check the value in your store, it could also be related to your action in case of a load (have a look to shouldDumpStoreOnActionCall option).'
            );
        }
        return data.map((line, idx) => {
            let isSelected;
            const selection = find(selectionData, {[idField]: line[idField]});
            if (selection) {
                isSelected = selection.isSelected;
            } else {
                switch(selectionStatus){
                    case 'none':
                        isSelected = false;
                    break;
                    case 'selected':
                        isSelected = true;
                    break;
                    case 'partial':
                        isSelected = undefined;
                    break;
                    default:
                        isSelected = false;
                }
            }
            return (
                <FinalLineComponent
                    data={line}
                    isSelected={isSelected}
                    key={line[idField] || idx}
                    onSelection={this._handleLineSelection}
                    ref={`line${idx}`}
                    reference={this._getReference()}
                    {...otherProps}
                    />
            );
        });
    },
    /**
    * Render loading state
    * @return {HTML} the loading state
    */
    _renderLoading() {
        const {isLoading, loader} = this.props;
        if(isLoading){
            if(loader){
                return loader();
            }
            return (

{this.i18n('list.loading')} ...

            );
        }
    },
    /**
    * Render manual fetch state
    * @return {HTML} the rendered manual fetch state
    */
    _renderManualFetch() {
        const {isManualFetch, hasMoreData} = this.props;
        if(isManualFetch && hasMoreData){
            const style = {className: 'primary'};
            return (

                    <Button
                        handleOnClick={this.handleShowMore}
                        label='list.button.showMore'
                        style={style}
                        type='button'
                        />

            );
        }
    },

    /**
    * Render the list.
    * @returns {XML} DOM of the component
    */
    render() {
        return (

                {this._renderLines()}
                {this._renderLoading()}
                {this._renderManualFetch()}

        );
    }
};

module.exports = builder(listMixin);
<commit_msg>[selection line] Fix #798<commit_after>// Dependencies

const {checkIsNotNull} = require('focus-core').util.object;
const {builder, types} = require('focus-core').component;
const find = require('lodash/collection/find');
const {omit} = require('lodash/object');
const {isArray} = require('lodash/lang');
import {clone} from 'lodash/lang';
import {reduce} from 'lodash/collection';

// Mixins

const translationMixin = require('../../common/i18n').mixin;
const infiniteScrollMixin = require('../mixin/infinite-scroll').mixin;
const referenceMixin = require('../../common/mixin/reference-property');

// Components

const Button = require('../../common/button/action').component;

const listMixin = {
    /**
    * Display name.
    */
    displayName: 'selection-list',

    /**
    * Mixin dependancies.
    */
    mixins: [translationMixin, infiniteScrollMixin, referenceMixin],

    /**
    * Default properties for the list.
    * @returns {{isSelection: boolean}} the default properties
    */
    getDefaultProps: function getListDefaultProps(){
        return {
            data: [],
            isSelection: true,
            selectionStatus: 'partial',
            selectionData: [],
            isLoading: false,
            operationList: [],
            idField: 'id'
        };
    },

    /**
    * list property validation.
    * @type {Object}
    */
    propTypes: {
        LineComponent: types('func'),
        buttonComponent: types('func'),
        data: types('array'),
        idField: types('string'),
        isLoading: types('bool'),
        isSelection: types('bool'),
        loader: types('func'),
        onLineClick: types('func'),
        onSelection: types('func'),
        operationList: types(['array', 'object']),
        selectionData: types('array'),
        selectionStatus: types('string')
    },

    getInitialState() {
        return {
            selectedItems: null
        }
    },

    /**
    * Return selected items in the list.
    * @return {Array} selected items
    */
    getSelectedItems() {
        const {selectedItems} = this.state;
        if (selectedItems !== null) {
            const selectedItems = [];
            for (let [item, isSelected] of this.state.selectedItems) {
                if (isSelected) selectedItems.push(item);
            }
            return selectedItems;
        } else {
            return reduce(this.refs, (acc, ref) => {
                if (ref.getValue) {
                    const {item, isSelected} = ref.getValue();
                    if (isSelected) acc.push(item);
                }
                return acc;
            }, []);
        }
    },

    _handleLineSelection(data, isSelected) {
        const {selectedItems} = this.state;
        const newSelectedItems = new Map();
        if (selectedItems !== null) {
            for (let [key, value] of selectedItems) {
                newSelectedItems.set(key, value);
            }
        }
        newSelectedItems.set(data, isSelected);
        this.setState({selectedItems: newSelectedItems});
    },

    /**
    * Render lines of the list.
    * @returns {*} DOM for lines
    */
    _renderLines() {
        const {data, LineComponent: Line, selectionData, idField, selectionStatus, ...otherProps} = this.props;
        // LEGACY CODE
        const customLineComponent = otherProps.lineComponent;
        if (customLineComponent) {
            console.warn(`%c DEPRECATED : You are using the lineComponent prop in a list component, this will be removed in the next release of Focus Components. Please use LineComponent prop instead.`, `color: #FF9C00; font-weight: bold`);
        }
        const FinalLineComponent = customLineComponent || Line;
        // END OF LEGACY CODE
        if(!isArray(data)){
            console.error(
                'List: Lines: it seems data is not an array, please check the value in your store, it could also be related to your action in case of a load (have a look to shouldDumpStoreOnActionCall option).'
            );
        }
        return data.map((line, idx) => {
            let isSelected;
            const selection = find(selectionData, {[idField]: line[idField]});
            if (selection) {
                isSelected = selection.isSelected;
            } else {
                switch(selectionStatus){
                    case 'none':
                        isSelected = false;
                    break;
                    case 'selected':
                        isSelected = true;
                    break;
                    case 'partial':
                        isSelected = undefined;
                    break;
                    default:
                        isSelected = false;
                }
            }
            return (
                <FinalLineComponent
                    data={line}
                    isSelected={isSelected}
                    key={line[idField] || idx}
                    onSelection={this._handleLineSelection}
                    ref={`line${idx}`}
                    reference={this._getReference()}
                    {...otherProps}
                    />
            );
        });
    },
    /**
    * Render loading state
    * @return {HTML} the loading state
    */
    _renderLoading() {
        const {isLoading, loader} = this.props;
        if(isLoading){
            if(loader){
                return loader();
            }
            return (

{this.i18n('list.loading')} ...

            );
        }
    },
    /**
    * Render manual fetch state
    * @return {HTML} the rendered manual fetch state
    */
    _renderManualFetch() {
        const {isManualFetch, hasMoreData} = this.props;
        if(isManualFetch && hasMoreData){
            const style = {className: 'primary'};
            return (

                    <Button
                        handleOnClick={this.handleShowMore}
                        label='list.button.showMore'
                        style={style}
                        type='button'
                        />

            );
        }
    },

    /**
    * Render the list.
    * @returns {XML} DOM of the component
    */
    render() {
        return (

                {this._renderLines()}
                {this._renderLoading()}
                {this._renderManualFetch()}

        );
    }
};

module.exports = builder(listMixin);
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2020 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/iron-icons/iron-icons.js';
import '@vaadin/vaadin-grid/vaadin-grid.js';
import '@vaadin/vaadin-grid/vaadin-grid-filter.js';
import '@vaadin/vaadin-grid/vaadin-grid-sorter.js';
import '@vaadin/vaadin-grid/vaadin-grid-column-group.js';
import '@polymer/paper-toast/paper-toast.js';
import './style-element.js'

class bucketList extends PolymerElement {
	static get template() {
		return html`

			<vaadin-grid
					id="balanceBucketGrid"
					loading="{{loading}}"
					active-item="{{activeItem}}">
				<vaadin-grid-column width="15ex" flex-grow="5">
					<template class="header">
						<vaadin-grid-filter
								aria-label="Bucket Id"
								path="id"
								value="[[_filterBucId]]">
							<input
									placeholder="Bucket Id"
									value="{{_filterBucId::input}}"
									focus-target>
						</vaadin-grid-filter>
					</template>
					<template>[[item.id]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column width="15ex" flex-grow="5">
					<template class="header">
						<vaadin-grid-filter
								aria-label="Product Id"
								path="product"
								value="[[_filterProdId]]">
							<input
									placeholder="Product Id"
									value="{{_filterProdId::input}}"
									focus-target>
					</vaadin-grid-filter>
				</template>
				<template>[[item.product]]</template>
				<vaadin-grid-column-group>
					<template class="header">

Balance

					</template>
					<vaadin-grid-column width="12ex" flex-grow="2">
						<template class="header">
								Cents
						</template>
						<template>

[[item.cents]]

						</template>
					</vaadin-grid-column>
					<vaadin-grid-column width="12ex" flex-grow="2">
						<template class="header">
								Bytes
						</template>
						<template>

[[item.remainedAmount]]

						</template>
					</vaadin-grid-column>
					<vaadin-grid-column width="12ex" flex-grow="2">
						<template class="header">
								Seconds
						</template>
						<template>

[[item.seconds]]

						</template>
					</vaadin-grid-column>
				</vaadin-grid-column-group>
			</vaadin-grid>

				<paper-fab
						icon="add"
						on-tap = "showAddBucket">
				</paper-fab>

			<iron-ajax
					id="getBucketBalance"
					url="/balanceManagement/v1/bucket/"
					rejectWithRequest>
			</iron-ajax>
		`;
	}

	static get properties() {
		return {
			loading: {
				type: Boolean,
				notify: true
			},
			etag: {
				type: String,
				value: null
			},
			activeItem: {
				type: Object,
				notify: true,
				observer: '_activeItemChanged'
			},
			_filterBucId: {
				type: Boolean,
				observer: '_filterChanged'
			},
			_filterProdId: {
				type: Boolean,
				observer: '_filterChanged'
			}
		}
	}

	ready() {
		super.ready();
		var grid = this.shadowRoot.getElementById('balanceBucketGrid');
		grid.dataProvider = this._getBuckets;
	}

	_getBuckets(params, callback) {
		var grid = this;
		var bucketList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-bucket-list');
		var ajax = bucketList.shadowRoot.getElementById("getBucketBalance");
		delete ajax.params['filter'];
		function checkHead(param) {
			return param.path == "id" || param.path == "product";
		}
		params.filters.filter(checkHead).forEach(function(filter) {
			if (filter.value) {
				if(ajax.params['filter']) {
					ajax.params['filter'] += "]," + filter.path + ".like=[" + filter.value + "%";
				} else {
					ajax.params['filter'] = "\"[{" + filter.path + ".like=[" + filter.value + "%";
				}
			}
		});
		if (ajax.params['filter']) {
			ajax.params['filter'] += "]}]\"";
		}
		var handleAjaxResponse = function(request) {
			if(request) {
				bucketList.etag = request.xhr.getResponseHeader('ETag');
				var range = request.xhr.getResponseHeader('Content-Range');
				var range1 = range.split("/");
				var range2 = range1[0].split("-");
				if (range1[1] != "*") {
					grid.size = Number(range1[1]);
				} else {
					grid.size = Number(range2[1]) + grid.pageSize * 2;
				}
				var vaadinItems = new Array();
				function checkChar(characteristic){
					return characteristic.name == "id";
				}
				for (var index in request.response) {
					var newRecord = new Object();
					newRecord.id = request.response[index].id;
					if(request.response[index].product.id) {
						newRecord.product = request.response[index].product.id;
					}
					if(request.response[index].remainedAmount) {
						if(request.response[index].remainedAmount.units == "cents") {
							newRecord.cents = request.response[index].remainedAmount.amount;
						}
						if(request.response[index].remainedAmount.units == "seconds") {
							var Str = request.response[index].remainedAmount.amount;
							if(Str.includes("b")){
								var NewStrSec = Str.substring(0, Str.length - 1);
								newRecord.seconds = NewStrSec;
							}
						}
						if(request.response[index].remainedAmount.units == "octets") {
							var Str = request.response[index].remainedAmount.amount;
							if(Str.includes("b")){
								var NewStr = Str.substring(0, Str.length - 1);
								newRecord.remainedAmount = NewStr;
							}
						}
					}
					vaadinItems[index] = newRecord;
				}
				callback(vaadinItems);
			} else {
				grid.size = 0;
				callback([]);
			}
		};
		var handleAjaxError = function(error) {
			bucketList.etag = null;
			var toast = document.getElementById('userToastError');
			toast.text = error;
			toast.open();
			if(!grid.size) {
				grid.size = 0;
			}
			callback([]);
		}
		if (ajax.loading) {
			ajax.lastRequest.completes.then(function(request) {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (bucketList.etag && params.page > 0) {
				ajax.headers['If-Range'] = bucketList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			return ajax.generateRequest().completes;
			}, handleAjaxError).then(handleAjaxResponse, handleAjaxError);
		} else {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (bucketList.etag && params.page > 0) {
				ajax.headers['If-Range'] = bucketList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			ajax.generateRequest().completes.then(handleAjaxResponse, handleAjaxError);
		}
	}

	showAddBucket(event) {
		document.body.querySelector('sig-app').shadowRoot.querySelector('sig-bucket-add').shadowRoot.getElementById('addBucketModal').open();
	}
}

window.customElements.define('sig-bucket-list', bucketList);
<commit_msg>remove active-item<commit_after>/**
 * @license
 * Copyright (c) 2020 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/iron-icons/iron-icons.js';
import '@vaadin/vaadin-grid/vaadin-grid.js';
import '@vaadin/vaadin-grid/vaadin-grid-filter.js';
import '@vaadin/vaadin-grid/vaadin-grid-sorter.js';
import '@vaadin/vaadin-grid/vaadin-grid-column-group.js';
import '@polymer/paper-toast/paper-toast.js';
import './style-element.js'

class bucketList extends PolymerElement {
	static get template() {
		return html`

			<vaadin-grid
					id="balanceBucketGrid"
					loading="{{loading}}">
				<vaadin-grid-column width="15ex" flex-grow="5">
					<template class="header">
						<vaadin-grid-filter
								aria-label="Bucket Id"
								path="id"
								value="[[_filterBucId]]">
							<input
									placeholder="Bucket Id"
									value="{{_filterBucId::input}}"
									focus-target>
						</vaadin-grid-filter>
					</template>
					<template>[[item.id]]</template>
				</vaadin-grid-column>
				<vaadin-grid-column width="15ex" flex-grow="5">
					<template class="header">
						<vaadin-grid-filter
								aria-label="Product Id"
								path="product"
								value="[[_filterProdId]]">
							<input
									placeholder="Product Id"
									value="{{_filterProdId::input}}"
									focus-target>
					</vaadin-grid-filter>
				</template>
				<template>[[item.product]]</template>
				<vaadin-grid-column-group>
					<template class="header">

Balance

					</template>
					<vaadin-grid-column width="12ex" flex-grow="2">
						<template class="header">
								Cents
						</template>
						<template>

[[item.cents]]

						</template>
					</vaadin-grid-column>
					<vaadin-grid-column width="12ex" flex-grow="2">
						<template class="header">
								Bytes
						</template>
						<template>

[[item.remainedAmount]]

						</template>
					</vaadin-grid-column>
					<vaadin-grid-column width="12ex" flex-grow="2">
						<template class="header">
								Seconds
						</template>
						<template>

[[item.seconds]]

						</template>
					</vaadin-grid-column>
				</vaadin-grid-column-group>
			</vaadin-grid>

				<paper-fab
						icon="add"
						on-tap = "showAddBucket">
				</paper-fab>

			<iron-ajax
					id="getBucketBalance"
					url="/balanceManagement/v1/bucket/"
					rejectWithRequest>
			</iron-ajax>
		`;
	}

	static get properties() {
		return {
			loading: {
				type: Boolean,
				notify: true
			},
			etag: {
				type: String,
				value: null
			},
			_filterBucId: {
				type: Boolean,
				observer: '_filterChanged'
			},
			_filterProdId: {
				type: Boolean,
				observer: '_filterChanged'
			}
		}
	}

	ready() {
		super.ready();
		var grid = this.shadowRoot.getElementById('balanceBucketGrid');
		grid.dataProvider = this._getBuckets;
	}

	_getBuckets(params, callback) {
		var grid = this;
		var bucketList = document.body.querySelector('sig-app').shadowRoot.querySelector('sig-bucket-list');
		var ajax = bucketList.shadowRoot.getElementById("getBucketBalance");
		delete ajax.params['filter'];
		function checkHead(param) {
			return param.path == "id" || param.path == "product";
		}
		params.filters.filter(checkHead).forEach(function(filter) {
			if (filter.value) {
				if(ajax.params['filter']) {
					ajax.params['filter'] += "]," + filter.path + ".like=[" + filter.value + "%";
				} else {
					ajax.params['filter'] = "\"[{" + filter.path + ".like=[" + filter.value + "%";
				}
			}
		});
		if (ajax.params['filter']) {
			ajax.params['filter'] += "]}]\"";
		}
		var handleAjaxResponse = function(request) {
			if(request) {
				bucketList.etag = request.xhr.getResponseHeader('ETag');
				var range = request.xhr.getResponseHeader('Content-Range');
				var range1 = range.split("/");
				var range2 = range1[0].split("-");
				if (range1[1] != "*") {
					grid.size = Number(range1[1]);
				} else {
					grid.size = Number(range2[1]) + grid.pageSize * 2;
				}
				var vaadinItems = new Array();
				function checkChar(characteristic){
					return characteristic.name == "id";
				}
				for (var index in request.response) {
					var newRecord = new Object();
					newRecord.id = request.response[index].id;
					if(request.response[index].product.id) {
						newRecord.product = request.response[index].product.id;
					}
					if(request.response[index].remainedAmount) {
						if(request.response[index].remainedAmount.units == "cents") {
							newRecord.cents = request.response[index].remainedAmount.amount;
						}
						if(request.response[index].remainedAmount.units == "seconds") {
							var Str = request.response[index].remainedAmount.amount;
							if(Str.includes("b")){
								var NewStrSec = Str.substring(0, Str.length - 1);
								newRecord.seconds = NewStrSec;
							}
						}
						if(request.response[index].remainedAmount.units == "octets") {
							var Str = request.response[index].remainedAmount.amount;
							if(Str.includes("b")){
								var NewStr = Str.substring(0, Str.length - 1);
								newRecord.remainedAmount = NewStr;
							}
						}
					}
					vaadinItems[index] = newRecord;
				}
				callback(vaadinItems);
			} else {
				grid.size = 0;
				callback([]);
			}
		};
		var handleAjaxError = function(error) {
			bucketList.etag = null;
			var toast = document.getElementById('userToastError');
			toast.text = error;
			toast.open();
			if(!grid.size) {
				grid.size = 0;
			}
			callback([]);
		}
		if (ajax.loading) {
			ajax.lastRequest.completes.then(function(request) {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (bucketList.etag && params.page > 0) {
				ajax.headers['If-Range'] = bucketList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			return ajax.generateRequest().completes;
			}, handleAjaxError).then(handleAjaxResponse, handleAjaxError);
		} else {
			var startRange = params.page * params.pageSize + 1;
			var endRange = startRange + params.pageSize - 1;
			ajax.headers['Range'] = "items=" + startRange + "-" + endRange;
			if (bucketList.etag && params.page > 0) {
				ajax.headers['If-Range'] = bucketList.etag;
			} else {
				delete ajax.headers['If-Range'];
			}
			ajax.generateRequest().completes.then(handleAjaxResponse, handleAjaxError);
		}
	}

	showAddBucket(event) {
		document.body.querySelector('sig-app').shadowRoot.querySelector('sig-bucket-add').shadowRoot.getElementById('addBucketModal').open();
	}
}

window.customElements.define('sig-bucket-list', bucketList);
<|endoftext|>


<commit_before>var helper = function () {
};
helper.config = {
	baseUrl: ''
};
helper.page = {
};

(function($) {
	$.ajaxSetup({
		dataFilter: function(data, type){
			var rs = data;
			if(typeof rs === 'string'){
				rs = JSON.parse(rs);
			}
			if(rs.code && rs.code==='NOT_LOGIN'){
				$.messager.alert('提示！', rs.message, 'warning');
			}
			if(rs.error){
				console.log('错误提示:');
				console.dir(rs);
				$.messager.alert('错误提示！', rs.message, 'warning');
			}
			return data;
		},
		headers: {
			'x-response-view': 'easyui'
		},
		/*error: function (request, textStatus, errorThrown){
			alert(errorThrown)
			console.dir(request)
			console.dir(textStatus)
			console.dir(errorThrown)
		},*/
		complete: function(request, textStatus) {
			//textStatus : error
		    this; // 调用本次AJAX请求时传递的options参数
		    if(textStatus=='error'){
		    	console.log('error:');
		    	console.dir(this);
				$.messager.alert('提示！', '请求['+this.url+']出错！', 'warning');
		    }
		},
		statusCode: {
			500: function(){
				$.messager.alert('提示！', '服务器出错！', 'warning');
			},
			404: function(){
				$.messager.alert('提示！', '找不到路径!', 'warning');
			}
		}
	});

	//for $('e').extendMethod()
	$.extend($.fn, {

		isSelectedOne : function(){
            var selectedNodes = $(this).getGridSelections();
			return selectedNodes.length && selectedNodes.length==1;
		},

		getGridSelections: function(){
			return $(this).easyGrid('getSelections') || [];
		},

		easyGrid: function(dataName){
			var grid = null;
			if ($(this).data('treegrid')){
				grid = $(this).treegrid(dataName);
			} else {
				grid = $(this).datagrid(dataName);
			}
			return grid;
		},

		resetImg: function (maxWidth, maxHeight) {
	        var image = new Image();
	        var width, height;
	        $(this).each(function () {
	            image.src = $(this).attr('src');
	            width = image.width;
	            height = image.height;
	            if (width > height) {
	                $(this).css({width: maxWidth, height: 'auto'});
	            }
	            else if (width < height) {
	                $(this).css({width: 'auto', height: maxHeight});
	            }
	            else {
	                if (maxWidth > maxHeight) {
	                    $(this).css({width: maxWidth, height: 'auto'});
	                }
	                else {
	                    $(this).css({width: 'auto', height: maxHeight});
	                }
	            }
	        })
	    },

		getSelectedRow: function(){
		    var row = $(this).datagrid('getSelected');
		    return row;
		},

		selectRow: function(index){
			$(this).datagrid('selectRow',index);// 关键在这里
		    var row = $(this).datagrid('getSelected');
		    return row;
		}

	});

	$.extend($.fn.tree.methods, {
		getAllCheckedIds : function(jq){
			var ids = [];
			var nodes = $(jq).tree('getChecked', ['checked','indeterminate']);
			$.each(nodes, function(i, node){
				ids.push(node.id);
			});
			return ids;
		}
	});

	//for $.extendMethod()
	$.extend({

	});

	//for helper.extendMethod()
	helper.waitingMsgState = false;
	$.extend(helper, {
		/***
		 * config {
		 *  datagrid: '#dataGrid',
        	resetForm: '#dataForm',
        	closeDialog: '#addDataDialog',
        	callback: function(data){}
        }
		 */
		ajaxPut: function(url, config){
			config = config || {};
			var mergeParams = config.params || {};
			mergeParams['_method'] = 'put';
			helper.showWaitingMsg(config.waitingMsg);
			$.post(url, mergeParams, helper.processJsonDataResult(config));
		},

		gotoTopPage: function(){
			var current = window;
        	var url = location.href;
        	var hasParent = false;
        	while(current.parent!=null && current.parent!==current){
        		current = current.parent;
        		hasParent = true;
        	}
        	if(hasParent){
	        	current.location.href = url;
        	}
		},

		booleanFormatter: function(val, row, index){
			if(val===true || val=='true'){
				return '是';
			}else{
				return '否';
			}
		},

		addEmptyOptionForComboboxFilter: function(data){
			data.unshift({text:'全部', value:'', selected:true});
            return data;
		},

		defaultOnError: function(defResult){
			return function(data){
            	if(data.error && data.error===true){
            		return defResult || [];
            	}
            	return data;
            }
		},

		submitEasyForm: function(config){
	    	 var _config = $.extend({}, {
	    		 autoClear: true,
	    		 onSuccess: function(data){
	    			 if(data.success===true && !!_config.autoClear){
	                     $(_config.dataForm).form('reset');
	                     if(_config.dataDialog)
	                    	 $(_config.dataDialog).dialog('close');

	                     $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
	                     $(_config.datagrid || _config.treegrid).easyGrid('reload');
	    			 }
	    		 }
	    	 }, config);

	    	 $(_config.dataForm).form('submit',{
	    		 url: $(_config.dataForm).attr('action'),
	             onSubmit:function(){
	                 var valid = $(this).form('enableValidation').form('validate');
	                 if(valid==true){
	        	         helper.showWaitingMsg();
	                 }
	                 return valid;
	             },
	             success: function(data){
//                	 $.messager.progress('close');
	            	 helper.closeWaitingMsg();
	                 data = JSON.parse(data);
	                 if(!!!data.success){
	                	 $.messager.alert('提交操作出错！',data.message,'warning');
	                 }else{
	                     $.messager.alert('提交操作成功！',data.message,'info');
	                 }
	                 if(_config.onSuccess){
                    	 _config.onSuccess(data);
                     }
	             }
	         });
	     },

	     showWaitingMsg : function(msg){
	    	 var _msg = msg || '正在处理，请稍候……';
	    	 $.messager.progress({
	             title:'提示',
	             msg:_msg
	         });
	    	 helper.waitingMsgState = true;
	     },

	     closeWaitingMsg : function(){
        	 $.messager.progress('close');
	    	 helper.waitingMsgState = false;
	     },

	     selectOneHandler : function(datagrid, cb){
	    	 if(arguments.length==1 && typeof arguments[0] ==='object'){
	    		 var config = arguments[0];
	    		 return this.selectOneHandler(config.datagrid, function(row){
	    			 $.messager.confirm('提示', '确定要进行此操作？', function(rs){
	                     if (rs){
	                    	var params = (typeof config.params === 'object' && config.params) || (typeof config.params === 'function' && config.params(row)) || {};
	                    	$.extend(params, helper.getCsrfParams());
//	                    	console.log('params:'+params);
	                    	var url = (typeof config.url === 'string' && config.url) || (typeof config.url === 'function' && config.url(row)) || '';
//	                    	console.log('url:'+url);
	                     	helper.showWaitingMsg();
	                        $.post(url, params, helper.processJsonDataResult(config));
	                     }
	                 });
	    		 });
	    	 }

             return function(){
            	 if(!$(datagrid).isSelectedOne()){
                     $.messager.alert('警告','请选择一条数据！','warning');
                     return;
            	 }
            	 var selectedNodes = $(datagrid).getGridSelections();
                 if(cb)
                	 cb(selectedNodes[0]);
             };
	     },
	     //处理ajax的json结果，显示处理结果信息，如果没有callback，则清除选择和刷新列表
	     /***
	      * config: {
	      		datagrid:
	      		resetForm:
	      		closeDialog:
	      		callback:
	      * }
	      */
	     processJsonDataResult: function(config, cb){
	    	 var _config = config || {};
	    	 var cb = cb || config.callback;
	    	 return function(data){
	             if(!!!data.success){
	            	 $.messager.progress('close');
	            	 $.messager.alert('操作出错！',data.message,'warning');
	             }else{
	                 $.messager.progress('close');
	                 $.messager.alert('操作成功！',data.message,'info');
	             }
	             if(cb){
	            	 cb(data);
	             }else{
                     $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
                     $(_config.datagrid || _config.treegrid).easyGrid('reload');

                     $(_config.resetForm).form('reset');
                     if(_config.closeDialog)
                    	 $(_config.closeDialog).dialog('close');
	             }
		     }
	     },

	     remoteMessageHandler: function(cb){
	    	 return function(data){
	             if(cb){
	            	 cb(data);
	             }
	    		 if(data.success){
	    			 if(data.success===true){
		            	 $.messager.progress('close');
		                 $.messager.alert('操作成功！',data.message,'info');
		             }else{
		                 $.messager.progress('close');
		            	 $.messager.alert('操作出错！',data.message,'warning');
		             }
	    		 }
		     }
	     },

	     loadTreeErrorHandler: function(){
	    	 return function(node, data){
	    		 if(data.success){
	    			 if(data.success===true){
	    				 //
		             }else{
		                 $.messager.progress('close');
		            	 $.messager.alert('操作出错！',data.message,'warning');
		             }
	    		 }
	    	 }
	     },

	     loadGridErrorHandler: function(){
	    	 return function(data){
	    		 if(data.success){
	    			 if(data.success===true){
	    				 //
		             }else{
		                 $.messager.progress('close');
		            	 $.messager.alert('操作出错！',data.message,'warning');
		             }
	    		 }
	    	 }
	     },

	     deleteHandler : function(config){
	    	 return function(){
	    		 helper.__deleteHandler(config);
	    	 }
	     },

	     getCsrfParams : function(){
	    	 var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
             //var csrfHeader = $("meta[name='_csrf_header']").attr("content");
             var data = {};
             if(csrfParameter)
            	 data[csrfParameter] = $("meta[name='_csrf']").attr("content");
             return data;
	     },

	     __deleteHandler : function(config){
	    	 var _config = config || {};
             if(!_config.url){
                 $.messager.alert('警告','没有配置提交地址！','warning');
            	 return ;
             }

             var selectedNodes = $(_config.datagrid || _config.treegrid).getGridSelections();
             if(selectedNodes.length<1){
                 $.messager.alert('警告','请至少选择一条数据！','warning');
                 return ;
             }

         	var params = helper.getCsrfParams() || {};
             if(_config.idField){
            	 var idValues = $.map(selectedNodes, function(e){
                     return e[_config.idField];
                 });
            	 var paramIdName = _config.paramIdName || _config.idField+'s';
            	 params[paramIdName] = idValues;
             }
         	$.extend(params, config.params || {});

         	$.messager.confirm('警告', '确定要删除记录？', function(rs){
                 if (rs){
                	params._method =  'delete';
                	params = $.param(params, true);
                 	helper.showWaitingMsg();
                    $.post(_config.url, params, helper.processJsonDataResult(_config, function(){
                    	//clearSelections, easyui bug，删除子节点后，如果不清楚，getSelections依然会返回子节点
                        $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
	                    $(_config.datagrid || _config.treegrid).easyGrid('reload');
                    }));
                 }
             });
	     },

	     gridSelectionsRemoteHandler: function(config){
	    	return function(){
	    		helper.doGridSelectionsRemoteAction(config);
	    	}
	     },
	     /****
	      * config: {
	       		url: '',
	       		datagrid: '#dataGrid',
		       	idField: 'id',
		       	paramIdName: 'ids',
		       	params: {},
		       	confirmMessage: ''
	      * }
	      */
	     doGridSelectionsRemoteAction : function(config){
	    	 var _config = config || {};
             if(!_config.url){
                 $.messager.alert('警告','没有配置提交地址！','warning');
            	 return ;
             }

             var selectedNodes = $(_config.datagrid || _config.treegrid).getGridSelections();
             if(selectedNodes.length<1){
                 $.messager.alert('警告','请至少选择一条数据！','warning');
                 return ;
             }

         	var params = helper.getCsrfParams() || {};
             if(_config.idField){
            	 var idValues = $.map(selectedNodes, function(e){
                     return e[_config.idField];
                 });
            	 var paramIdName = _config.paramIdName || _config.idField+'s';
            	 params[paramIdName] = idValues;
             }
         	$.extend(params, config.params || {});

        	params._method = params._method || 'post';

         	$.messager.confirm('警告', config.confirmMessage || '确定要执行此操作？', function(rs){
                 if (rs){
                 	helper.showWaitingMsg();
                    /*$.post(_config.url, params, helper.processJsonDataResult(_config, function(){
                    	//clearSelections, easyui bug，删除子节点后，如果不清楚，getSelections依然会返回子节点
                        $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
	                    $(_config.datagrid || _config.treegrid).easyGrid('reload');
                    }));*/
                    var type = params._method.toLowerCase()==='get'?params._method:'post';
                	params = $.param(params, true);
                    $.ajax(_config.url, {
                    	type: type,
                    	data: params,
                    	success: helper.processJsonDataResult(_config)
                    });
                 }
             });
	     },

	     /****
	      * config: {
	       		url: '',
		       	params: {_method: 'put'},
		       	confirmMessage: ''
	      * }
	      */
	     doRemoteAction : function(config){
	    	 var _config = config || {};
             if(!_config.url){
                 $.messager.alert('警告','没有配置提交地址！','warning');
            	 return ;
             }

         	var params = helper.getCsrfParams() || {};
         	$.extend(params, config.params || {});

        	params._method = params._method || 'post';

         	$.messager.confirm('警告', config.confirmMessage || '确定要执行此操作？', function(rs){
                 if (rs){
                 	helper.showWaitingMsg();
                    var type = params._method.toLowerCase()==='get'?params._method:'post';
                	params = $.param(params, true);
                    $.ajax(_config.url, {
                    	type: type,
                    	data: params,
                    	success: helper.processJsonDataResult(_config)
                    });
                 }
             });
	     }
	});

})(jQuery);<commit_msg>封装kindeditor到helper<commit_after>var helper = function () {
};
helper.config = {
	baseUrl: ''
};
helper.page = {
};

(function($) {
	$.ajaxSetup({
		dataFilter: function(data, type){
			var rs = data;
			if(typeof rs === 'string'){
				rs = JSON.parse(rs);
			}
			if(rs.code && rs.code==='NOT_LOGIN'){
				$.messager.alert('提示！', rs.message, 'warning');
			}
			if(rs.error){
				console.log('错误提示:');
				console.dir(rs);
				$.messager.alert('错误提示！', rs.message, 'warning');
			}
			return data;
		},
		headers: {
			'x-response-view': 'easyui'
		},
		/*error: function (request, textStatus, errorThrown){
			alert(errorThrown)
			console.dir(request)
			console.dir(textStatus)
			console.dir(errorThrown)
		},*/
		complete: function(request, textStatus) {
			//textStatus : error
		    this; // 调用本次AJAX请求时传递的options参数
		    if(textStatus=='error'){
		    	console.log('error:');
		    	console.dir(this);
				$.messager.alert('提示！', '请求['+this.url+']出错！', 'warning');
		    }
		},
		statusCode: {
			500: function(){
				$.messager.alert('提示！', '服务器出错！', 'warning');
			},
			404: function(){
				$.messager.alert('提示！', '找不到路径!', 'warning');
			}
		}
	});

	//for $('e').extendMethod()
	$.extend($.fn, {

		isSelectedOne : function(){
            var selectedNodes = $(this).getGridSelections();
			return selectedNodes.length && selectedNodes.length==1;
		},

		getGridSelections: function(){
			return $(this).easyGrid('getSelections') || [];
		},

		easyGrid: function(dataName){
			var grid = null;
			if ($(this).data('treegrid')){
				grid = $(this).treegrid(dataName);
			} else {
				grid = $(this).datagrid(dataName);
			}
			return grid;
		},

		resetImg: function (maxWidth, maxHeight) {
	        var image = new Image();
	        var width, height;
	        $(this).each(function () {
	            image.src = $(this).attr('src');
	            width = image.width;
	            height = image.height;
	            if (width > height) {
	                $(this).css({width: maxWidth, height: 'auto'});
	            }
	            else if (width < height) {
	                $(this).css({width: 'auto', height: maxHeight});
	            }
	            else {
	                if (maxWidth > maxHeight) {
	                    $(this).css({width: maxWidth, height: 'auto'});
	                }
	                else {
	                    $(this).css({width: 'auto', height: maxHeight});
	                }
	            }
	        })
	    },

		getSelectedRow: function(){
		    var row = $(this).datagrid('getSelected');
		    return row;
		},

		selectRow: function(index){
			$(this).datagrid('selectRow',index);// 关键在这里
		    var row = $(this).datagrid('getSelected');
		    return row;
		},

		kindeditor: function(opts){
			var config = opts || {
				   items: ['source', '|', 'undo', 'redo', '|', 'preview','|',
				           'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', '|',
				           'formatblock', 'forecolor', 'bold', 'image'
				          ],
		           uploadJson : '${siteConfig.baseURL}/web-admin/kindeditor/upload',
		           fileManagerJson : '',
		           allowFileManager : false
			   };
			var e = $(this).get();
			KindEditor.ready(function(K) {
			   window.editor = K.create(e, config);
			});
		}

	});

	$.extend($.fn.tree.methods, {
		getAllCheckedIds : function(jq){
			var ids = [];
			var nodes = $(jq).tree('getChecked', ['checked','indeterminate']);
			$.each(nodes, function(i, node){
				ids.push(node.id);
			});
			return ids;
		}
	});

	//for $.extendMethod()
	$.extend({

	});

	//for helper.extendMethod()
	helper.waitingMsgState = false;
	$.extend(helper, {
		/***
		 * config {
		 *  datagrid: '#dataGrid',
        	resetForm: '#dataForm',
        	closeDialog: '#addDataDialog',
        	callback: function(data){}
        }
		 */
		ajaxPut: function(url, config){
			config = config || {};
			var mergeParams = config.params || {};
			mergeParams['_method'] = 'put';
			helper.showWaitingMsg(config.waitingMsg);
			$.post(url, mergeParams, helper.processJsonDataResult(config));
		},

		gotoTopPage: function(){
			var current = window;
        	var url = location.href;
        	var hasParent = false;
        	while(current.parent!=null && current.parent!==current){
        		current = current.parent;
        		hasParent = true;
        	}
        	if(hasParent){
	        	current.location.href = url;
        	}
		},

		booleanFormatter: function(val, row, index){
			if(val===true || val=='true'){
				return '是';
			}else{
				return '否';
			}
		},

		addEmptyOptionForComboboxFilter: function(data){
			data.unshift({text:'全部', value:'', selected:true});
            return data;
		},

		defaultOnError: function(defResult){
			return function(data){
            	if(data.error && data.error===true){
            		return defResult || [];
            	}
            	return data;
            }
		},

		submitEasyForm: function(config){
	    	 var _config = $.extend({}, {
	    		 autoClear: true,
	    		 onSuccess: function(data){
	    			 if(data.success===true && !!_config.autoClear){
	                     $(_config.dataForm).form('reset');
	                     if(_config.dataDialog)
	                    	 $(_config.dataDialog).dialog('close');

	                     $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
	                     $(_config.datagrid || _config.treegrid).easyGrid('reload');
	    			 }
	    		 }
	    	 }, config);

	    	 $(_config.dataForm).form('submit',{
	    		 url: $(_config.dataForm).attr('action'),
	             onSubmit:function(){
	                 var valid = $(this).form('enableValidation').form('validate');
	                 if(valid==true){
	        	         helper.showWaitingMsg();
	                 }
	                 return valid;
	             },
	             success: function(data){
//                	 $.messager.progress('close');
	            	 helper.closeWaitingMsg();
	                 data = JSON.parse(data);
	                 if(!!!data.success){
	                	 $.messager.alert('提交操作出错！',data.message,'warning');
	                 }else{
	                     $.messager.alert('提交操作成功！',data.message,'info');
	                 }
	                 if(_config.onSuccess){
                    	 _config.onSuccess(data);
                     }
	             }
	         });
	     },

	     showWaitingMsg : function(msg){
	    	 var _msg = msg || '正在处理，请稍候……';
	    	 $.messager.progress({
	             title:'提示',
	             msg:_msg
	         });
	    	 helper.waitingMsgState = true;
	     },

	     closeWaitingMsg : function(){
        	 $.messager.progress('close');
	    	 helper.waitingMsgState = false;
	     },

	     selectOneHandler : function(datagrid, cb){
	    	 if(arguments.length==1 && typeof arguments[0] ==='object'){
	    		 var config = arguments[0];
	    		 return this.selectOneHandler(config.datagrid, function(row){
	    			 $.messager.confirm('提示', '确定要进行此操作？', function(rs){
	                     if (rs){
	                    	var params = (typeof config.params === 'object' && config.params) || (typeof config.params === 'function' && config.params(row)) || {};
	                    	$.extend(params, helper.getCsrfParams());
//	                    	console.log('params:'+params);
	                    	var url = (typeof config.url === 'string' && config.url) || (typeof config.url === 'function' && config.url(row)) || '';
//	                    	console.log('url:'+url);
	                     	helper.showWaitingMsg();
	                        $.post(url, params, helper.processJsonDataResult(config));
	                     }
	                 });
	    		 });
	    	 }

             return function(){
            	 if(!$(datagrid).isSelectedOne()){
                     $.messager.alert('警告','请选择一条数据！','warning');
                     return;
            	 }
            	 var selectedNodes = $(datagrid).getGridSelections();
                 if(cb)
                	 cb(selectedNodes[0]);
             };
	     },
	     //处理ajax的json结果，显示处理结果信息，如果没有callback，则清除选择和刷新列表
	     /***
	      * config: {
	      		datagrid:
	      		resetForm:
	      		closeDialog:
	      		callback:
	      * }
	      */
	     processJsonDataResult: function(config, cb){
	    	 var _config = config || {};
	    	 var cb = cb || config.callback;
	    	 return function(data){
	             if(!!!data.success){
	            	 $.messager.progress('close');
	            	 $.messager.alert('操作出错！',data.message,'warning');
	             }else{
	                 $.messager.progress('close');
	                 $.messager.alert('操作成功！',data.message,'info');
	             }
	             if(cb){
	            	 cb(data);
	             }else{
                     $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
                     $(_config.datagrid || _config.treegrid).easyGrid('reload');

                     $(_config.resetForm).form('reset');
                     if(_config.closeDialog)
                    	 $(_config.closeDialog).dialog('close');
	             }
		     }
	     },

	     remoteMessageHandler: function(cb){
	    	 return function(data){
	             if(cb){
	            	 cb(data);
	             }
	    		 if(data.success){
	    			 if(data.success===true){
		            	 $.messager.progress('close');
		                 $.messager.alert('操作成功！',data.message,'info');
		             }else{
		                 $.messager.progress('close');
		            	 $.messager.alert('操作出错！',data.message,'warning');
		             }
	    		 }
		     }
	     },

	     loadTreeErrorHandler: function(){
	    	 return function(node, data){
	    		 if(data.success){
	    			 if(data.success===true){
	    				 //
		             }else{
		                 $.messager.progress('close');
		            	 $.messager.alert('操作出错！',data.message,'warning');
		             }
	    		 }
	    	 }
	     },

	     loadGridErrorHandler: function(){
	    	 return function(data){
	    		 if(data.success){
	    			 if(data.success===true){
	    				 //
		             }else{
		                 $.messager.progress('close');
		            	 $.messager.alert('操作出错！',data.message,'warning');
		             }
	    		 }
	    	 }
	     },

	     deleteHandler : function(config){
	    	 return function(){
	    		 helper.__deleteHandler(config);
	    	 }
	     },

	     getCsrfParams : function(){
	    	 var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
             //var csrfHeader = $("meta[name='_csrf_header']").attr("content");
             var data = {};
             if(csrfParameter)
            	 data[csrfParameter] = $("meta[name='_csrf']").attr("content");
             return data;
	     },

	     __deleteHandler : function(config){
	    	 var _config = config || {};
             if(!_config.url){
                 $.messager.alert('警告','没有配置提交地址！','warning');
            	 return ;
             }

             var selectedNodes = $(_config.datagrid || _config.treegrid).getGridSelections();
             if(selectedNodes.length<1){
                 $.messager.alert('警告','请至少选择一条数据！','warning');
                 return ;
             }

         	var params = helper.getCsrfParams() || {};
             if(_config.idField){
            	 var idValues = $.map(selectedNodes, function(e){
                     return e[_config.idField];
                 });
            	 var paramIdName = _config.paramIdName || _config.idField+'s';
            	 params[paramIdName] = idValues;
             }
         	$.extend(params, config.params || {});

         	$.messager.confirm('警告', '确定要删除记录？', function(rs){
                 if (rs){
                	params._method =  'delete';
                	params = $.param(params, true);
                 	helper.showWaitingMsg();
                    $.post(_config.url, params, helper.processJsonDataResult(_config, function(){
                    	//clearSelections, easyui bug，删除子节点后，如果不清楚，getSelections依然会返回子节点
                        $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
	                    $(_config.datagrid || _config.treegrid).easyGrid('reload');
                    }));
                 }
             });
	     },

	     gridSelectionsRemoteHandler: function(config){
	    	return function(){
	    		helper.doGridSelectionsRemoteAction(config);
	    	}
	     },
	     /****
	      * config: {
	       		url: '',
	       		datagrid: '#dataGrid',
		       	idField: 'id',
		       	paramIdName: 'ids',
		       	params: {},
		       	confirmMessage: ''
	      * }
	      */
	     doGridSelectionsRemoteAction : function(config){
	    	 var _config = config || {};
             if(!_config.url){
                 $.messager.alert('警告','没有配置提交地址！','warning');
            	 return ;
             }

             var selectedNodes = $(_config.datagrid || _config.treegrid).getGridSelections();
             if(selectedNodes.length<1){
                 $.messager.alert('警告','请至少选择一条数据！','warning');
                 return ;
             }

         	var params = helper.getCsrfParams() || {};
             if(_config.idField){
            	 var idValues = $.map(selectedNodes, function(e){
                     return e[_config.idField];
                 });
            	 var paramIdName = _config.paramIdName || _config.idField+'s';
            	 params[paramIdName] = idValues;
             }
         	$.extend(params, config.params || {});

        	params._method = params._method || 'post';

         	$.messager.confirm('警告', config.confirmMessage || '确定要执行此操作？', function(rs){
                 if (rs){
                 	helper.showWaitingMsg();
                    /*$.post(_config.url, params, helper.processJsonDataResult(_config, function(){
                    	//clearSelections, easyui bug，删除子节点后，如果不清楚，getSelections依然会返回子节点
                        $(_config.datagrid || _config.treegrid).easyGrid('clearSelections');
	                    $(_config.datagrid || _config.treegrid).easyGrid('reload');
                    }));*/
                    var type = params._method.toLowerCase()==='get'?params._method:'post';
                	params = $.param(params, true);
                    $.ajax(_config.url, {
                    	type: type,
                    	data: params,
                    	success: helper.processJsonDataResult(_config)
                    });
                 }
             });
	     },

	     /****
	      * config: {
	       		url: '',
		       	params: {_method: 'put'},
		       	confirmMessage: ''
	      * }
	      */
	     doRemoteAction : function(config){
	    	 var _config = config || {};
             if(!_config.url){
                 $.messager.alert('警告','没有配置提交地址！','warning');
            	 return ;
             }

         	var params = helper.getCsrfParams() || {};
         	$.extend(params, config.params || {});

        	params._method = params._method || 'post';

         	$.messager.confirm('警告', config.confirmMessage || '确定要执行此操作？', function(rs){
                 if (rs){
                 	helper.showWaitingMsg();
                    var type = params._method.toLowerCase()==='get'?params._method:'post';
                	params = $.param(params, true);
                    $.ajax(_config.url, {
                    	type: type,
                    	data: params,
                    	success: helper.processJsonDataResult(_config)
                    });
                 }
             });
	     }
	});

})(jQuery);<|endoftext|>