sh做的js控件。

另外内部被scroller包裹的div不可以定位成absolute,会撑不出高度。

上面只是使用的注意事项。

很佩服人家能封装出这样的控件。

如果我也能写得出来就能毕业了,也不用担心现在公司有个万一,以后的营生问题。

全部源码:

(function($) {
    "use strict";
    
    var cache = {};
    var objId = function(obj) {
        if(!obj.afscrollerID) obj.afscrollerID = $.uuid();
        return obj.afscrollerID;
    };
    $.fn.scroller=function(opts){
        opts=opts||{};
        if(this.length===0) return;
        var tmp, id;
        for(var i = 0; i < this.length; i++) {
            //cache system
            id = objId(this[i]);
            if(!cache[id]) {
                if(!opts) opts = {};
                tmp = new Scroller(this[i], opts);
                cache[id] = tmp;
            } else {
                tmp = cache[id];
            }
        }
        return this.length == 1 ? tmp : this;
    };
    
    if(!$.mixin) {
        $.mixin = {};
    }
    
    if(!$.scroller) {
        $.scroller = {};
    }
    
    var mixin = $.mixin,
        scroller = $.scroller;
    
    mixin.scrollerMixin = {
        scrollerElement: null,
        scrollerContainerElement: null,
        direction: 'both',
        isAxisEnabledFlags: null,
        translatable: null,
        autoResize: true,
        isDragging: false,
        minPostion: null,
        outOfBoundRestrictFactor: 0.5,
        startMomentumResetTime: 300,
        maxAbsoluteVelocity: 6,
        containerSize: 'auto',
        size: 'auto',
        
        showIndicator: true,
        
        wrapper: '<div class="c-scroller">' + 
            '<div class="c-scroller__bar-wrapper">' + 
                '<div class="c-scroller__bar__table">' +
                    '<div class="c-scroller__bar__row">' +
                        '<div></div>' + 
                        '<div>' +
                            '<div class="c-scroller__bar--y">' + 
                                '<div class="c-scroller__bar--y__indicator"></div>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                    '<div class="c-scroller__bar__row">' +
                        '<div>' + 
                            '<div class="c-scroller__bar--x">' +
                                '<div class="c-scroller__bar--x__indicator"></div>' +
                            '</div>' +
                        '</div>' + 
                        '<div></div>' +
                    '</div>' +
                '</div>' +
            '</div>' +
            '<div class="c-scroller__scroller-container">' +
                '<div class="c-scroller__scroller-content"></div>' +
            '</div>' +
        '</div>',

        initScroller: function() {
            this.initData();
            
            this.addWrapper();
            
            this.initAxisEnabledFlag();
            
            this.addSizeChangedListener();
            
            this.addResizeListener();
            
            this.initTranslatable();
            
            this.addDragListener();
            
            this.addAirGestureListener();
        },
        
        initData: function() {
            this.dragStartPosition = {
                x: 0,
                y: 0
            };
            this.startPosition = {
                x: 0,
                y: 0
            };
            this.position = {
                x: 0,
                y: 0
            };
            this.dragDirection = {
                x: 0,
                y: 0
            };

            this.flickStartPosition = {
                x: 0,
                y: 0
            };
            this.flickStartTime = {
                x: 0,
                y: 0
            };

            this.lastDragPosition = {
                x: 0,
                y: 0
            };
        },
        
        getPosition: function() {
            return this.position;
        },
        
        addDragListener: function() {
            var $el = $(this.scrollerContainerElement);
            itu.event.on($el, "dragstart", this.dragStart, this);
            itu.event.on($el, "drag", this.drag, this);
            itu.event.on($el, "dragend", this.dragEnd, this);
            itu.event.on($el, "touch", this.touch, this);            
        },
        
        addAirGestureListener: function() {
            this.airGestureHandler = this.airGestureHandler.bind(this);
            window.addEventListener("keydown", this.airGestureHandler);
        },
        
        airGestureHandler: function(ev) {
            this.airGestureEvent(ev.keyCode);
        },
        
        airGestureEvent: function(keyCode) {
            console.warn("scroller :: receive the air gesture event start");
            
            console.warn("scroller :: ifInVRMode: " + ifInVRMode);
            if (ifInVRMode) {
                console.warn("scroller :: return directly because of in VR mode");
                return;
            }
            
            var event = new Object();
            event.data = new Object();
            event.data.gesture = new Object();
            event.data.gesture.srcEvent = new Object();
            event.data.gesture.srcEvent.changedTouches = new Array();
            event.data.gesture.srcEvent.changedTouches[0] = new Object();
            if ((keyCode === 0x102) || (keyCode === 0x103)) { //0x102,0x103
                event.data.gesture.srcEvent.changedTouches[0].pageX = this.lastDragPosition.x;
                event.data.gesture.srcEvent.changedTouches[0].pageY = this.dragStartPosition.y;
            }    
            else {
                return;
            }
                
            this.dragStart(event);
            var me = this;
            setTimeout(function() {
                me.modifyEvent(event, keyCode);
                me.drag(event);
            }, 50);
            
            setTimeout(function() {
                me.modifyEvent(event, keyCode);
                me.drag(event);
            }, 50);

            setTimeout(function() {
                me.modifyEvent(event, keyCode);
                me.dragEnd(event);
            }, 50);
            console.warn("scroller :: receive the air gesture event end");
        },
        
        modifyEvent: function(event, keyCode) {
            if (keyCode === 0x103) { //Up 0x103 -->38(keyboard)
                if (this.position.y == 0) {
                    event.data.gesture.srcEvent.changedTouches[0].pageY += 55;
                }
                else {
                    event.data.gesture.srcEvent.changedTouches[0].pageY += 30;
                }
            }
            else if (keyCode === 0x102) { //Down 0x102 -->40(keyboard)
                if (this.position.y == 0) {
                    event.data.gesture.srcEvent.changedTouches[0].pageY -= 55;
                }
                else {
                    event.data.gesture.srcEvent.changedTouches[0].pageY -= 30;
                }
            }

            return event;
        },
        
        addWrapper: function() {
            var wrapper = this.wrapper,
                element = this.element;
            this.$wrapper = $(wrapper).insertBefore($(element));
            
            this.scrollerElement = this.$wrapper.find('.c-scroller__scroller-content');
            this.scrollerContainerElement = this.$wrapper.find('.c-scroller__scroller-container');
            
            $(element).appendTo(this.scrollerElement);
        },
        
        deleteWrapper: function() {
            var $wrapper, element, $element;
            $wrapper = this.$wrapper;
            element = this.element;
            $element = $(element);
            
            //delete the list
            $element.remove();
            
            //make become siblings
            $element.insertBefore($wrapper);
            
            //delete the wrapper
            $wrapper.remove();
        },
        
        addResizeListener: function() {
            var autoResize = this.autoResize;
//            var scrollerElement = this.scrollerElement;
//            var scrollerContainerElement = this.scrollerContainerElement;

            if (autoResize) {
//                this.onScrollerResize = iAuto.Util.bind(this, this.onScrollerResize);
                this.setSize(this.size);
//                scrollerElement.resize(this.onScrollerResize);
            }

//            this.onScrollerContainerResize = iAuto.Util.bind(this, this.onScrollerContainerResize);
            this.setContainerSize(this.containerSize);
//            scrollerContainerElement.resize(this.onScrollerContainerResize);

            var autoResize = this.autoResize;

            if (autoResize) {

                this.setSize(this.size);

                this.lastSize = this.getSize();

            }

            this.setContainerSize(this.containerSize);

            this.lastContainerSize = this.getContainerSize();

            this.runLoopy();
        },
    
        loopyDelay: 250,

        loopyTimer: null,

        runLoopy: function() {

            var scrollerElement = this.scrollerElement;

            var scrollerContainerElement = this.scrollerContainerElement;

            var me = this;

            this.loopyTimer = setTimeout(function() {

                var scrollerElementHeight = parseInt(scrollerElement.height());

                var scrollerElementWidth = parseInt(scrollerElement.width());

                

                var scrollerElementLastHeight = me.lastSize.y;

                var scrollerElementLastWidth = me.lastSize.x;

                

                if(scrollerElementLastHeight !== scrollerElementHeight || scrollerElementLastWidth !== scrollerElementWidth) {

                    me.onScrollerResize();

                    me.lastSize = me.getSize();

                }

                var scrollerContainerElementHeight = parseInt(scrollerContainerElement.height());

                var scrollerContainerElementWidth = parseInt(scrollerContainerElement.width());

                

                var scrollerContainerElementLastHeight = me.lastContainerSize.y;

                var scrollerContainerElementLastWidth = me.lastContainerSize.x;

                

                if(scrollerContainerElementLastHeight !== scrollerContainerElementHeight || scrollerContainerElementLastWidth !== scrollerContainerElementWidth) {

                    me.onScrollerContainerResize();

                    me.lastContainerSize = me.getContainerSize();

                }

                me.runLoopy();

            }, me.loopyDelay);

        },
        
        onScrollerResize: function() {
            var scrollerElement = this.scrollerElement;
            this.setSize({
                x: scrollerElement.width(),
                y: scrollerElement.height()
            });
        },

        onScrollerContainerResize: function() {
            var scrollerContainerElement = this.scrollerContainerElement;
            this.setContainerSize({
                x: scrollerContainerElement.width(),
                y: scrollerContainerElement.height()
            });
        },

        initAxisEnabledFlag: function() {
            var direction, isAxisEnabledFlags;

            direction = this.direction;
            isAxisEnabledFlags = this.isAxisEnabledFlags;
            if (!isAxisEnabledFlags) {
                this.isAxisEnabledFlags = isAxisEnabledFlags = {};
            }
            if (direction === 'both') {
                isAxisEnabledFlags.x = true;
                isAxisEnabledFlags.y = true;
            } else if (direction === 'vertical') {
                isAxisEnabledFlags.y = true;
                this.$wrapper.addClass('c-vertical');
            } else if (direction === 'horizontal') {
                isAxisEnabledFlags.x = true;
                this.$wrapper.addClass('c-horizontal');
            }
        },

        addSizeChangedListener: function() {
            this.sizeChanged = iAuto.Util.bind(this, this.sizeChanged);
            $.bind(this, 'sizeChanged', this.sizeChanged);
            
            this.containerSizeChanged = iAuto.Util.bind(this, this.containerSizeChanged);
            $.bind(this, 'containerSizeChanged', this.containerSizeChanged);
            
            this.maxPositionChanged = iAuto.Util.bind(this, this.maxPositionChanged);
            $.bind(this, 'maxPositionChanged', this.maxPositionChanged);
        },

        containerSizeChanged: function() {
            this.refreshMaxPostion();
        },

        sizeChanged: function() {
            this.refreshMaxPostion();
        },

        refreshMaxPostion: function() {
            this.maxPosition = null;
            this.getMaxPosition();
        },

        maxPositionChanged: function() {
            this.snapToBoundary();
        },

        initTranslatable: function() {
            var translatable = this.translatable;
            var transformElement = this.scrollerElement[0];
            if (translatable) {
                var xclass = translatable.xclass;
                if (xclass) {
                    xclass = iAuto.resolveNamespace(xclass);
                }
                if (xclass) {
                    this.translatable = xclass.create({
                        transformElement: transformElement
                    });
                } else {
                    iAuto.Logger.error('translatable must be a valid class');
                }
            } else {
                this.translatable = new scroller.CssTranslate();
                this.translatable.init();
                this.translatable.transformElement = transformElement;
            }
            this.onAnimationFrame = iAuto.Util.bind(this, this.onAnimationFrame);
            $.bind(this.translatable, 'animationframe', this.onAnimationFrame);
            
            this.onAnimationEnd = iAuto.Util.bind(this, this.onAnimationEnd);
            $.bind(this.translatable, 'animationend', this.onAnimationEnd);
        },

        isAxisEnabled: function(axis) {
            return this.isAxisEnabledFlags[axis];
        },

        getMinPosition: function() {
            var minPosition = this.minPosition;
            if (!minPosition) {
                this.minPosition = minPosition = {
                    x: 0,
                    y: 0
                };
            }
            return minPosition;
        },

        getMaxPosition: function() {
            var maxPosition = this.maxPosition;
            if (!maxPosition) {
                var containerSize, size;
                containerSize = this.getContainerSize();
                size = this.getSize();
                
                if(typeof(containerSize.x) !== 'number') {
                    this.setContainerSize('auto');
                    containerSize = this.getContainerSize();
                }
                
                if(typeof(size.x) !== 'number') {
                    this.setSize('auto');
                    size = this.getSize();
                }
                
                maxPosition = this.maxPosition = {
                    x: Math.max(0, size.x - containerSize.x),
                    y: Math.max(0, size.y - containerSize.y)
                };
                
                $.trigger(this, 'maxPositionChanged', [maxPosition]);
            }
            return maxPosition;
        },

        touch: function() {
            this.translatable.stopAnimation();
        },

        dragStart: function(event) {
            var browserEvent, touch, dragDirection, dragStartPosition, startPosition;
            var flickStartPosition, flickStartTime, lastDragPosition, currentPosition, x, y, now;
            browserEvent = event.data.gesture.srcEvent;
            touch = browserEvent.changedTouches[0];
            dragDirection = this.dragDirection;
            dragStartPosition = this.dragStartPosition;
            startPosition = this.startPosition;
            flickStartPosition = this.flickStartPosition;
            flickStartTime = this.flickStartTime;
            lastDragPosition = this.lastDragPosition;
            currentPosition = this.position;
            x = currentPosition.x;
            y = currentPosition.y;
            now = Date.now();

            lastDragPosition.x = x;
            lastDragPosition.y = y;

            flickStartPosition.x = x;
            flickStartPosition.y = y;

            flickStartTime.x = now;
            flickStartTime.y = now;

            dragStartPosition.x = touch.pageX;
            dragStartPosition.y = touch.pageY;
            
            dragDirection.x = 0;
            dragDirection.y = 0;

            startPosition.x = x;
            startPosition.y = y;

            this.dragStartTime = now;

            this.isDragging = true;
            
            $.trigger(this, 'scrollstart', [x, y]);
        },

        onAxisDrag: function(axis, delta) {
            if (!this.isAxisEnabled(axis)) {
                return;
            }

            var flickStartPosition, flickStartTime, lastDragPosition, dragDirection, old;
            var min, max, start, last, current, lastDirection, restrictFactor, startMomentumResetTime;
            var now, distance;
            flickStartPosition = this.flickStartPosition;
            flickStartTime = this.flickStartTime;
            lastDragPosition = this.lastDragPosition;
            dragDirection = this.dragDirection;
            old = this.position[axis];
            min = this.getMinPosition()[axis];
            max = this.getMaxPosition()[axis];
            start = this.startPosition[axis];
            last = lastDragPosition[axis];
            current = start - delta;
            lastDirection = dragDirection[axis];
            restrictFactor = this.outOfBoundRestrictFactor;
            startMomentumResetTime = this.startMomentumResetTime;
            now = Date.now();

            if (current < min) {
                current *= restrictFactor;
            } else if (current > max) {
                distance = current - max;
                current = max + distance * restrictFactor;
            }
            if (current > last) {
                dragDirection[axis] = 1;
            } else if (current < last) {
                dragDirection[axis] = -1;
            }

            if ((lastDirection !== 0 && (dragDirection[axis] !== lastDirection)) || (now - flickStartTime[axis]) > startMomentumResetTime) {
                flickStartPosition[axis] = old;
                flickStartTime[axis] = now;
            }

            lastDragPosition[axis] = current;
        },

        scrollTo: function(x, y) {
            var translatable, position, positionChanged, translationX, translationY;
            translatable = this.translatable;
            position = this.position;
            positionChanged = false;
            
            if (this.isAxisEnabled('x')) {
                if (typeof x !== 'number') {
                    x = position.x;
                } else {
                    if (position.x !== x) {
                        position.x = x;
                        positionChanged = true;
                    }
                }

                translationX = -x;
            } else {
                translationX = -position.x;
            }

            if (this.isAxisEnabled('y')) {
                if (typeof y !== 'number') {
                    y = position.y;
                } else {
                    if (position.y !== y) {
                        position.y = y;
                        positionChanged = true;
                    }
                }

                translationY = -y;
            } else {
                translationY = -position.y;
            }

            if (positionChanged) {
                $.trigger(this, 'scroll', [position.x, position.y]);
                translatable.translate(translationX, translationY);
            }

            return this;
        },

        drag: function(event) {
            if (!this.isDragging) {
                return;
            }

            var lastDragPosition, browserEvent, touch, dragStartPosition;
            lastDragPosition = this.lastDragPosition;
            browserEvent = event.data.gesture.srcEvent;
            touch = browserEvent.changedTouches[0];
            dragStartPosition = this.dragStartPosition;

            this.onAxisDrag('x', touch.pageX - dragStartPosition.x);
            this.onAxisDrag('y', touch.pageY - dragStartPosition.y);

            this.scrollTo(lastDragPosition.x, lastDragPosition.y);
        },

        dragEnd: function(event) {
            var easingX, easingY;

            if (!this.isDragging) {
                return;
            }

            this.dragEndTime = new Date().getTime();

            this.drag(event);

            this.isDragging = false;

            easingX = this.getAnimationEasing('x');
            easingY = this.getAnimationEasing('y');

            if (easingX || easingY) {
                this.translatable.animate(easingX, easingY);
            } else {
                this.onScrollEnd();
            }
        },

        getAnimationEasing: function(axis) {
            if (!this.isAxisEnabled(axis)) {
                return null;
            }

            var currentPosition, flickStartPosition, flickStartTime, minPosition, maxPosition;
            var maxAbsVelocity, boundValue, dragEndTime, easing, velocity, duration;
            currentPosition = this.position[axis];
            flickStartPosition = this.flickStartPosition[axis];
            flickStartTime = this.flickStartTime[axis];
            minPosition = this.getMinPosition()[axis];
            maxPosition = this.getMaxPosition()[axis];
            maxAbsVelocity = this.maxAbsoluteVelocity;
            boundValue = null;
            dragEndTime = this.dragEndTime;

            if (currentPosition < minPosition) {
                boundValue = minPosition;
            } else if (currentPosition > maxPosition) {
                boundValue = maxPosition;
            }

            // Out of bound, to be pulled back
            if (boundValue !== null) {
                easing = this.getBounceEasing()[axis];
                easing.setStartTime(dragEndTime);
                easing.setStartValue(-currentPosition);
                easing.setEndValue(-boundValue);

                return easing;
            }

            // Still within boundary, start deceleration
            duration = dragEndTime - flickStartTime;

            if (duration === 0) {
                return null;
            }

            velocity = (currentPosition - flickStartPosition) / (dragEndTime - flickStartTime);

            if (velocity === 0) {
                return null;
            }

            if (velocity < -maxAbsVelocity) {
                velocity = -maxAbsVelocity;
            } else if (velocity > maxAbsVelocity) {
                velocity = maxAbsVelocity;
            }

            easing = this.getMomentumEasing()[axis];
            easing.setStartTime(dragEndTime);
            easing.setStartValue(-currentPosition);
            easing.setStartVelocity(-velocity);
            easing.setMinMomentumValue(-maxPosition);
            easing.setMaxMomentumValue(0);

            return easing;
        },

        getBounceEasing: function() {
            var easing = this.bounceEasing,
                defaultClass, easingX, easingY;
            if (!easing) {
                defaultClass = scroller.EaseOut;
                easingX = new defaultClass();
                easingY = new defaultClass();
                this.bounceEasing = {
                    x: easingX,
                    y: easingY
                };
                easingX.init();
                easingY.init();
                return this.bounceEasing;
            } else {
                return easing;
            }
        },

        getMomentumEasing: function() {
            var boundMomentum = this.momentumEasing,
                defaultClass, easingX, easingY;
            if (!boundMomentum) {
                defaultClass = scroller.BoundMomentum;
                easingX = new defaultClass();
                easingY = new defaultClass();
                this.momentumEasing = {
                    x: easingX,
                    y: easingY
                };
                easingX.init();
                easingY.init();
                return this.momentumEasing;
            } else {
                return boundMomentum;
            }
        },

        onAnimationFrame: function(x, y) {
            var position = this.position;

            position.x = -x;
            position.y = -y;
            
            $.trigger(this, 'scroll', [position.x, position.y]);
        },

        onAnimationEnd: function() {
            this.snapToBoundary();
            this.onScrollEnd();
        },

        snapToBoundary: function() {
            var position, minPosition, maxPosition, minX, minY, maxX, maxY, x, y;

            position = this.position;
            minPosition = this.getMinPosition();
            maxPosition = this.getMaxPosition();
            minX = minPosition.x;
            minY = minPosition.y;
            maxX = maxPosition.x;
            maxY = maxPosition.y;
            x = Math.round(position.x);
            y = Math.round(position.y);

            if (x < minX) {
                x = minX;
            } else if (x > maxX) {
                x = maxX;
            }

            if (y < minY) {
                y = minY;
            } else if (y > maxY) {
                y = maxY;
            }

            this.scrollTo(x, y);
        },

        onScrollEnd: function() {
            var position = this.position;
            $.trigger(this, 'scrollend', [position.x, position.y]);
        },

        setSize: function(size) {
            var scrollElement;

            if (size === 'auto') {
                scrollElement = this.scrollerElement[0];
                this.size = {
                    x: scrollElement.offsetWidth,
                    y: scrollElement.offsetHeight
                };
                $.trigger(this, 'sizeChanged', [this.size]);
            } else if (typeof size === 'number') {
                this.size = {
                    x: size,
                    y: size
                };
                $.trigger(this, 'sizeChanged', [this.size]);
            } else {
                this.size = size;
                $.trigger(this, 'sizeChanged', [this.size]);
            }
        },

        getSize: function() {
            return this.size;
        },

        setContainerSize: function(containerSize) {
            var containerElement;

            if (containerSize === 'auto') {
                containerElement = this.scrollerContainerElement[0];
                this.containerSize = containerSize = {
                    x: containerElement.offsetWidth,
                    y: containerElement.offsetHeight
                };
                $.trigger(this, 'containerSizeChanged', [this.containerSize]);
            } else if (typeof containerSize === 'number') {
                this.containerSize = {
                    x: containerSize,
                    y: containerSize
                };
                $.trigger(this, 'containerSizeChanged', [this.containerSize]);
            } else {
                this.containerSize = containerSize;
                $.trigger(this, 'containerSizeChanged', [this.containerSize]);
            }
        },

        getContainerSize: function() {
            return this.containerSize;
        },

        destroy: function() {
            var translatable = this.translatable;
            if (translatable) {
                translatable.destroy();
            }
            
            var el = this.el;
            if(el) {
                var id = el.afscrollerID;
                if(cache[id]) delete cache[id];
                this.deleteWrapper();
//                window.removeEventListener('keydown', this.airGestureHandler);
            }else {
                console.warn('error can not find sroller el');
            }
        }
    };
    
    mixin.IndicatorMixin = {
        axis: null,
        indicatorElement: null,

        malengthX: 0,

        ratioX: 1,

        ratioY: 1,

        //delay time when hidden indicator
        delayOnHidden: 100,

        indicatorX: null,

        indicatorXOffset: 0,

        indicatorXMinLength: 6,

        indicatorXBaseLength: 0,

        indicatorY: null,

        indicatorYOffset: 0,

        indicatorYMinLength: 6,

        indicatorYBaseLength: 0,

        initIndicator: function() {
            this.setIndicatorOnScrollStart = iAuto.Util.bind(this, this.setIndicatorOnScrollStart);
            $.bind(this, 'scrollstart', this.setIndicatorOnScrollStart);
            
            this.setIndicatorOnScroll = iAuto.Util.bind(this, this.setIndicatorOnScroll);
            $.bind(this, 'scroll', this.setIndicatorOnScroll);
            
            this.setIndicatorOnScrollEnd = iAuto.Util.bind(this, this.setIndicatorOnScrollEnd);
            $.bind(this, 'scrollend', this.setIndicatorOnScrollEnd);
            
            this.initIndicatorElement();
        },

        initIndicatorElement: function() {
            this.indicatorX = this.$wrapper.find('.c-scroller__bar--x__indicator');
            this.indicatorY = this.$wrapper.find('.c-scroller__bar--y__indicator');
        },

        setIndicatorOnScrollStart: function(x, y) {
            var containerSize = this.getContainerSize(),
                size = this.getSize();
            if (this.isAxisEnabled('x')) {
                var ratioX = this.ratioX = containerSize.x / size.x,
                    lengthX = this.indicatorXBaseLength = Math.round(ratioX * containerSize.x),
                    translateX = 'translate3d(' + Math.round(ratioX * x) + 'px, 0, 0)';
                if (this.hideTimerX) {
                    clearTimeout(this.hideTimerX);
                }
                this.indicatorX.css('opacity', 1);
                this.indicatorX.css('width', lengthX);
                this.indicatorX.css('webkitTransform', translateX);
            }
            if (this.isAxisEnabled('y')) {
                var ratioY = this.ratioY = containerSize.y / size.y,
                    lengthY = this.indicatorYBaseLength = Math.round(ratioY * containerSize.y),
                    translateY = 'translate3d(0, ' + Math.round(ratioY * y) + 'px, 0)';
                if (this.hideTimerY) {
                    clearTimeout(this.hideTimerY);
                }
                this.indicatorY.css('opacity', 1);
                this.indicatorY.css('height', lengthY);
                this.indicatorY.css('webkitTransform', translateY);
            }
        },

        setIndicatorOnScroll: function(x, y) {
            var maxPosition = this.getMaxPosition(),
                minPosition = this.getMinPosition(),
                minPositionX = minPosition.x,
                minPositionY = minPosition.y,
                maxPositionX = maxPosition.x,
                maxPositionY = maxPosition.y,
                newLength, translateX, translateY, extra;
            if (this.isAxisEnabled('x')) {
                if (x < minPositionX) {
                    newLength = this.indicatorXBaseLength + (x - minPositionX);
                    this.indicatorX.css('width', newLength);
                } else if (x > maxPositionX) {
                    extra = maxPositionX - x;
                    newLength = this.indicatorXBaseLength + extra;
                    newLength = Math.max(newLength, this.indicatorXMinLength);
                    extra = newLength - this.indicatorXBaseLength;
                    translateX = 'translate3d(' + (this.indicatorXOffset - extra) + 'px, 0, 0)';
                    this.indicatorX.css('webkitTransform', translateX);
                    this.indicatorX.css('width', newLength);
                } else {
                    this.indicatorXOffset = Math.round(x * this.ratioX);
                    translateX = 'translate3d(' + Math.round(x * this.ratioX) + 'px, 0, 0)';
                    this.indicatorX.css('webkitTransform', translateX);
                }
            }
            if (this.isAxisEnabled('y')) {
                if (y < minPositionY) {
                    newLength = this.indicatorYBaseLength + (y - minPositionY);
                    this.indicatorY.css('height', newLength);
                } else if (y > maxPositionY) {
                    extra = maxPositionY - y;
                    newLength = this.indicatorYBaseLength + extra;
                    newLength = Math.max(newLength, this.indicatorYMinLength);
                    extra = newLength - this.indicatorYBaseLength;
                    translateY = 'translate3d(0, ' + (this.indicatorYOffset - extra) + 'px, 0)';
                    this.indicatorY.css('webkitTransform', translateY);
                    this.indicatorY.css('height', newLength);
                } else {
                    this.indicatorYOffset = Math.round(y * this.ratioY);
                    translateY = 'translate3d(0, ' + this.indicatorYOffset + 'px, 0)';
                    this.indicatorY.css('webkitTransform', translateY);
                }
            }
        },

        setIndicatorOnScrollEnd: function() {
            var me = this;
            if (this.delayOnHidden) {
                if (this.isAxisEnabled('x')) {
                    this.hideTimerX = setTimeout(function() {
                        me.hideTimerX = null;
                        me.indicatorX.css('opacity', 0);
                    }, this.delayOnHidden);
                }
                if (this.isAxisEnabled('y')) {
                    this.hideTimerY = setTimeout(function() {
                        me.hideTimerY = null;
                        me.indicatorY.css('opacity', 0);
                    }, this.delayOnHidden);
                }
            } else {
                if (this.isAxisEnabled('x')) {
                    this.indicatorX.css('opacity', 0);
                }
                if (this.isAxisEnabled('y')) {
                    this.indicatorY.css('opacity', 0);
                }
            }
        }
    };
    
    var Scroller = function(el, opts) {
        this.el = el;
        this.$el = $(el);
        
        iAuto.copy(this, mixin.scrollerMixin);
        
        opts = opts || {};
        iAuto.copy(this, opts);
        
        this.initScroller();
        
        //閺勵垰鎯侀弰鍓с仛濠婃艾濮╅弶锟�
        if(this.showIndicator) {
            iAuto.copy(this, mixin.IndicatorMixin);
            this.initIndicator();
        }
        
        var me = this;
        this.$el.one('destroy', function(e) {
            var id = el.afscrollerID;
            if(cache[id]) delete cache[id];
            
            e.stopPropagation();
        });
    };
    
    Scroller.prototype = {
        element: null
    };
    
    var cssTranslate = scroller.CssTranslate = function() {}; 
    cssTranslate.prototype = {
        transformElement: null,
        activeEasingX: null,
        activeEasingY: null,
        lastX: null,
        lastY: null,
        isAnimating: false,
        x: 0,
        y: 0,
        animationFrameId: null,

        init: function() {
            this.doAnimationFrame = iAuto.Util.bind(this,
                this.doAnimationFrame);
        },

        setTransformElement: function(transformElement) {
            this.transformElement = transformElement;
        },

        translate: function(x, y) {
            if (this.isAnimating) {
                this.stopAnimation();
            }

            if (!isNaN(x) && typeof x === 'number') {
                this.x = x;
            }

            if (!isNaN(y) && typeof y === 'number') {
                this.y = y;
            }
            this.doTranslate();
        },

        doTranslate: function() {
            var element = this.transformElement;
            element.style.webkitTransform = 'translate3d(' + this.x + 'px, ' + this.y + 'px, 0px)';
        },

        animate: function(easingX, easingY) {
            this.activeEasingX = easingX;
            this.activeEasingY = easingY;

            this.isAnimating = true;
            this.lastX = null;
            this.lastY = null;

            this.animationFrameId = window.requestAnimationFrame(this.doAnimationFrame);
            
            $.trigger(this, 'animationstart', [this.x, this.y]);

            return this;
        },

        doAnimationFrame: function() {
            var me = this,
                easingX = me.activeEasingX,
                easingY = me.activeEasingY,
                now = Date
                    .now(),
                x, y;

            this.animationFrameId = window.requestAnimationFrame(this.doAnimationFrame);

            if (!me.isAnimating) {
                return;
            }
            me.lastRun = now;
            if (easingX === null && easingY === null) {
                me.stopAnimation();
                return;
            }
            if (easingX !== null) {
                me.x = x = Math.round(easingX.getValue());

                if (easingX.isEnded) {
                    me.activeEasingX = null;
                }
            } else {
                x = me.x;
            }
            if (easingY !== null) {
                me.y = y = Math.round(easingY.getValue());

                if (easingY.isEnded) {
                    me.activeEasingY = null;
                }
            } else {
                y = me.y;
            }
            if (me.lastX !== x || me.lastY !== y) {
                me.doTranslate(x, y);

                me.lastX = x;
                me.lastY = y;
            }
            $.trigger(me, 'animationframe', [x, y]);
        },

        stopAnimation: function() {
            if (!this.isAnimating) {
                return;
            }

            this.activeEasingX = null;
            this.activeEasingY = null;

            this.isAnimating = false;

            window.cancelAnimationFrame(this.animationFrameId);
            $.trigger(this, 'animationend', [this.x, this.y]);
        },

        destroy: function() {
            this.stopAnimation();
        }
    };
    
    var EaseOut = scroller.EaseOut = function() {};
    EaseOut.prototype = {
        startTime: 0,
        startValue: 0,
        isEasing: true,
        isEnded: false,

        endValue: 0,
        exponent: 4,
        duration: 400,

        init: function() {

        },

        setStartTime: function(startTime) {
            this.startTime = startTime;
            this.reset();
        },

        setStartValue: function(startValue) {
            this.distance = this.endValue - startValue;
            this.startValue = startValue;
        },

        reset: function() {
            this.isEnded = false;
        },

        setEndValue: function(endValue) {
            this.distance = endValue - this.startValue;
            this.endValue = endValue;
        },

        setDuration: function(duration) {
            this.duration = duration;
        },

        setExponent: function(exponent) {
            this.exponent = exponent;
        },

        getValue: function() {
            var deltaTime = new Date().getTime() - this.startTime,
                duration = this.duration,
                startValue = this.startValue,
                endValue = this.endValue,
                distance = this.distance,
                theta = deltaTime / duration,
                thetaC = 1 - theta,
                thetaEnd = 1 - Math.pow(thetaC, this.exponent),
                currentValue = startValue + (thetaEnd * distance);

            if (deltaTime >= duration) {
                this.isEnded = true;
                return endValue;
            }
            return currentValue;
        }
    };

    var Momentum = scroller.Momentum = function() {};
    Momentum.prototype = {
        acceleration: 30,
        friction: 0.5,
        startVelocity: 0,

        alpha: 0,

        startTime: 0,
        startValue: 0,
        isEasing: true,
        isEnded: false,

        init: function() {
            this.setFriction(this.friction);
            this.setStartVelocity(this.startVelocity);
            this.setAcceleration(this.acceleration);
        },

        setStartTime: function(startTime) {
            this.startTime = startTime;
            this.reset();
        },

        setStartValue: function(startValue) {
            this.startValue = startValue;
        },

        reset: function() {
            this.isEnded = false;
        },

        setFriction: function(friction) {
            var theta = Math.log(1 - (friction / 10));

            this.theta = theta;

            this.alpha = theta / this.acceleration;
            this.friction = friction;
        },

        setStartVelocity: function(startVelocity) {
            this.velocity = startVelocity * this.acceleration;
            this.startVelocity = startVelocity;
        },

        setAcceleration: function(acceleration) {
            this.velocity = this.startVelocity * acceleration;
            this.alpha = this.theta / acceleration;
            this.acceleration = acceleration;
        },

        getValue: function() {
            return this.startValue - this.velocity * (1 - this.getFrictionFactor()) / this.theta;
        },

        getFrictionFactor: function() {
            var deltaTime = new Date().getTime() - this.startTime;

            return Math.exp(deltaTime * this.alpha);
        },

        getVelocity: function() {
            return this.getFrictionFactor() * this.velocity;
        }
    };

    var Bounce = scroller.Bounce = function() {};
    Bounce.prototype = {
        startTime: 0,
        startValue: 0,
        isEasing: true,
        isEnded: false,

        springTension: 0.3,
        acceleration: 30,
        startVelocity: 0,

        init: function() {

        },

        setStartTime: function(startTime) {
            this.startTime = startTime;
            this.reset();
        },

        setStartValue: function(startValue) {
            this.startValue = startValue;
        },

        reset: function() {
            this.isEnded = false;
        },

        setSpringTension: function(springTension) {
            this.springTension = springTension;
        },

        setAcceleration: function(acceleration) {
            this.acceleration = acceleration;
        },

        setStartVelocity: function(startVelocity) {
            this.startVelocity = startVelocity;
        },

        getValue: function() {
            var deltaTime = new Date().getTime() - this.startTime,
                theta = (deltaTime / this.acceleration),
                powTime = theta * Math.pow(Math.E, -this.springTension * theta);

            return this.startValue + (this.startVelocity * powTime);
        }
    };

    var BoundMomentum = scroller.BoundMomentum = function() {};
    BoundMomentum.prototype = {
        startTime: 0,
        startValue: 0,
        isEasing: true,
        isEnded: false,
        /**
         * @cfg {Object} momentum
         * A valid config object for {@link Ext.fx.easing.Momentum}
         * @accessor
         */
        momentum: null,

        /**
         * @cfg {Object} bounce
         * A valid config object for {@link Ext.fx.easing.Bounce}
         * @accessor
         */
        bounce: null,

        minMomentumValue: 0,

        maxMomentumValue: 0,

        /**
         * @cfg {Number} minVelocity
         * The minimum velocity to end this easing
         * @accessor
         */
        minVelocity: 0.01,

        /**
         * @cfg {Number} startVelocity
         * The start velocity
         * @accessor
         */
        startVelocity: 0,

        init: function() {
            this.initMomentum();
            this.initBounce();
        },

        initMomentum: function() {
            this.momentum = new Momentum();
            this.momentum.init();
        },

        setMinMomentumValue: function(minMomentumValue) {
            this.minMomentumValue = minMomentumValue;
        },

        setMaxMomentumValue: function(maxMomentumValue) {
            this.maxMomentumValue = maxMomentumValue;
        },

        setMinVelocity: function(minVelocity) {
            this.minVelocity = minVelocity;
        },

        setMomentum: function(momentum) {
            this.momentum = momentum;
        },

        initBounce: function() {
            this.bounce = new Bounce();
            this.bounce.init();
        },

        setBounce: function(bounce) {
            this.bounce = new Bounce();
        },

        setStartTime: function(startTime) {
            this.startTime = startTime;
            this.reset();
            this.momentum.setStartTime(startTime);
        },

        setStartVelocity: function(startVelocity) {
            this.momentum.setStartVelocity(startVelocity);
        },

        setStartValue: function(startValue) {
            this.momentum.setStartValue(startValue);
            this.startValue = startValue;
        },

        reset: function() {
            this.lastValue = null;

            this.isBouncingBack = false;

            this.isOutOfBound = false;

            this.isEnded = false;
        },

        getValue: function() {
            var momentum = this.momentum,
                bounce = this.bounce,
                startVelocity = momentum.startVelocity,
                direction = startVelocity > 0 ? 1 : -1,
                minValue = this.minMomentumValue,
                maxValue = this.maxMomentumValue,
                boundedValue = (direction == 1) ? maxValue : minValue,
                lastValue = this.lastValue,
                value, velocity;

            if (startVelocity === 0) {
                return this.startValue;
            }

            if (!this.isOutOfBound) {
                value = momentum.getValue();
                velocity = momentum.getVelocity();
                if (Math.abs(velocity) < this.minVelocity) {
                    this.isEnded = true;
                }

                if (value >= minValue && value <= maxValue) {
                    return value;
                }

                this.isOutOfBound = true;

                bounce.setStartTime(new Date().getTime());
                bounce.setStartVelocity(velocity);
                bounce.setStartValue(boundedValue);
            }

            value = bounce.getValue();
            if (!this.isEnded) {
                if (!this.isBouncingBack) {
                    if (lastValue !== null) {
                        if ((direction == 1 && value < lastValue) || (direction == -1 && value > lastValue)) {
                            this.isBouncingBack = true;
                        }
                    }
                } else {
                    if (Math.round(value) == boundedValue) {
                        this.isEnded = true;
                    }
                }
            }

            this.lastValue = value;

            return value;
        }
    };
    
})(af);
Scroller.js

当然首先要领会人家的思路,模仿人家的结构,再自己独立去写。

顺便更深的去掌握appframework

;
if (!window.af || typeof(af) !== "function") {
    var af = (function(M) {
        var j, h = M.document, O = [], s = O.slice, P = {}, o = [], k = 1, m = [], c = 1, y = /<(\w+)[^>]*>/, J = /^\.([\w-]+)$/, K = /^[\w-]+$/, p = {}, x = {}, W = {
            columncount : true,
            fontweight : true,
            lineheight : true,
            "column-count" : true,
            "font-weight" : true,
            "line-height" : true,
            opacity : true,
            orphans : true,
            widows : true,
            zIndex : true,
            "z-index" : true,
            zoom : true
        }, N = (typeof(MSApp) === "object");
        function E(Z, Y) {
            return (typeof(Y) === "number") && !W[Z.toLowerCase()]
                    ? Y + "px"
                    : Y
        }
        function G(ab, Y, ac) {
            var ad = h.createDocumentFragment();
            if (ac) {
                for (var aa = ab.length - 1; aa >= 0; aa--) {
                    ad.insertBefore(ab[aa], ad.firstChild)
                }
                Y.insertBefore(ad, Y.firstChild)
            } else {
                for (var Z = 0; Z < ab.length; Z++) {
                    ad.appendChild(ab[Z])
                }
                Y.appendChild(ad)
            }
            ad = null
        }
        function T(Y) {
            return Y in P
                    ? P[Y]
                    : (P[Y] = new RegExp("(^|\\s)" + Y + "(\\s|$)"))
        }
        function e(Y) {
            for (var Z = 0; Z < Y.length; Z++) {
                if (Y.indexOf(Y[Z]) != Z) {
                    Y.splice(Z, 1);
                    Z--
                }
            }
            return Y
        }
        function R(Z, aa) {
            var Y = [];
            if (Z == j) {
                return Y
            }
            for (; Z; Z = Z.nextSibling) {
                if (Z.nodeType == 1 && Z !== aa) {
                    Y.push(Z)
                }
            }
            return Y
        }
        var i = function(aa, ab) {
            this.length = 0;
            if (!aa) {
                return this
            } else {
                if (aa instanceof i && ab == j) {
                    return aa
                } else {
                    if (af.isFunction(aa)) {
                        return af(h).ready(aa)
                    } else {
                        if (af.isArray(aa) && aa.length != j) {
                            for (var Z = 0; Z < aa.length; Z++) {
                                this[this.length++] = aa[Z]
                            }
                            return this
                        } else {
                            if (af.isObject(aa) && af.isObject(ab)) {
                                if (aa.length == j) {
                                    if (aa.parentNode == ab) {
                                        this[this.length++] = aa
                                    }
                                } else {
                                    for (var Y = 0; Y < aa.length; Y++) {
                                        if (aa[Y].parentNode == ab) {
                                            this[this.length++] = aa[Y]
                                        }
                                    }
                                }
                                return this
                            } else {
                                if (af.isObject(aa) && ab == j) {
                                    this[this.length++] = aa;
                                    return this
                                } else {
                                    if (ab !== j) {
                                        if (ab instanceof i) {
                                            return ab.find(aa)
                                        }
                                    } else {
                                        ab = h
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return this.selector(aa, ab)
        };
        var H = function(Y, Z) {
            return new i(Y, Z)
        };
        function U(Y, aa) {
            try {
                return aa.querySelectorAll(Y)
            } catch (Z) {
                return []
            }
        }
        function F(Y, aa) {
            Y = Y.trim();
            if (Y[0] === "#" && Y.indexOf(".") == -1 && Y.indexOf(",") == -1
                    && Y.indexOf(" ") === -1 && Y.indexOf(">") === -1) {
                if (aa == h) {
                    S(aa.getElementById(Y.replace("#", "")), this)
                } else {
                    S(U(Y, aa), this)
                }
            } else {
                if ((Y[0] === "<" && Y[Y.length - 1] === ">")
                        || (Y.indexOf("<") !== -1 && Y.indexOf(">") !== -1)) {
                    var Z = h.createElement("div");
                    if (N) {
                        MSApp.execUnsafeLocalFunction(function() {
                            Z.innerHTML = Y.trim()
                        })
                    } else {
                        Z.innerHTML = Y.trim()
                    }
                    S(Z.childNodes, this)
                } else {
                    S((U(Y, aa)), this)
                }
            }
            return this
        }
        function S(Y, aa) {
            if (!Y) {
                return
            }
            if (Y.nodeType) {
                aa[aa.length++] = Y;
                return
            }
            for (var Z = 0, ab = Y.length; Z < ab; Z++) {
                aa[aa.length++] = Y[Z]
            }
        }
        H.is$ = function(Y) {
            return Y instanceof i
        };
        H.map = function(ac, ad) {
            var ab, Y = [], aa, Z;
            if (H.isArray(ac)) {
                for (aa = 0; aa < ac.length; aa++) {
                    ab = ad.apply(ac[aa], [aa, ac[aa]]);
                    if (ab !== j) {
                        Y.push(ab)
                    }
                }
            } else {
                if (H.isObject(ac)) {
                    for (Z in ac) {
                        if (!ac.hasOwnProperty(Z) || Z == "length") {
                            continue
                        }
                        ab = ad(ac[Z], [Z, ac[Z]]);
                        if (ab !== j) {
                            Y.push(ab)
                        }
                    }
                }
            }
            return af(Y)
        };
        H.each = function(aa, ab) {
            var Z, Y;
            if (H.isArray(aa)) {
                for (Z = 0; Z < aa.length; Z++) {
                    if (ab(Z, aa[Z]) === false) {
                        return aa
                    }
                }
            } else {
                if (H.isObject(aa)) {
                    for (Y in aa) {
                        if (!aa.hasOwnProperty(Y) || Y == "length") {
                            continue
                        }
                        if (ab(Y, aa[Y]) === false) {
                            return aa
                        }
                    }
                }
            }
            return aa
        };
        H.extend = function(Z) {
            if (Z == j) {
                Z = this
            }
            if (arguments.length === 1) {
                for (var Y in Z) {
                    this[Y] = Z[Y]
                }
                return this
            } else {
                s.call(arguments, 1).forEach(function(ab) {
                    for (var aa in ab) {
                        Z[aa] = ab[aa]
                    }
                })
            }
            return Z
        };
        H.isArray = function(Y) {
            return Y instanceof Array && Y.push != j
        };
        H.isFunction = function(Y) {
            return typeof Y === "function" && !(Y instanceof RegExp)
        };
        H.isObject = function(Y) {
            return typeof Y === "object" && Y !== null
        };
        H.fn = i.prototype = {
            namepsace : "appframework",
            constructor : i,
            forEach : O.forEach,
            reduce : O.reduce,
            push : O.push,
            indexOf : O.indexOf,
            concat : O.concat,
            selector : F,
            oldElement : undefined,
            slice : O.slice,
            length : 0,
            setupOld : function(Y) {
                if (Y == j) {
                    return H()
                }
                Y.oldElement = this;
                return Y
            },
            map : function(aa) {
                var ab, Y = [], Z;
                for (Z = 0; Z < this.length; Z++) {
                    ab = aa.apply(this[Z], [Z, this[Z]]);
                    if (ab !== j) {
                        Y.push(ab)
                    }
                }
                return H(Y)
            },
            each : function(Y) {
                this.forEach(function(aa, Z) {
                    Y.call(aa, Z, aa)
                });
                return this
            },
            ready : function(Y) {
                if (h.readyState === "complete" || h.readyState === "loaded"
                        || (!H.os.ie && h.readyState === "interactive")) {
                    Y()
                } else {
                    h.addEventListener("DOMContentLoaded", Y, false)
                }
                return this
            },
            find : function(ab) {
                if (this.length === 0) {
                    return this
                }
                var Y = [];
                var ac;
                for (var aa = 0; aa < this.length; aa++) {
                    ac = (H(ab, this[aa]));
                    for (var Z = 0; Z < ac.length; Z++) {
                        Y.push(ac[Z])
                    }
                }
                return H(e(Y))
            },
            html : function(Z, aa) {
                if (this.length === 0) {
                    return this
                }
                if (Z === j) {
                    return this[0].innerHTML
                }
                for (var Y = 0; Y < this.length; Y++) {
                    if (aa !== false) {
                        H.cleanUpContent(this[Y], false, true)
                    }
                    if (N) {
                        var ab = this[Y];
                        MSApp.execUnsafeLocalFunction(function() {
                            ab.innerHTML = Z
                        })
                    } else {
                        this[Y].innerHTML = Z
                    }
                }
                return this
            },
            text : function(Z) {
                if (this.length === 0) {
                    return this
                }
                if (Z === j) {
                    return this[0].textContent
                }
                for (var Y = 0; Y < this.length; Y++) {
                    this[Y].textContent = Z
                }
                return this
            },
            css : function(ab, ac, ae) {
                var ad = ae != j ? ae : this[0];
                if (this.length === 0) {
                    return this
                }
                if (ac == j && typeof(ab) === "string") {
                    var aa = M.getComputedStyle(ad);
                    return ad.style[ab]
                            ? ad.style[ab]
                            : M.getComputedStyle(ad)[ab]
                }
                for (var Z = 0; Z < this.length; Z++) {
                    if (H.isObject(ab)) {
                        for (var Y in ab) {
                            this[Z].style[Y] = E(Y, ab[Y])
                        }
                    } else {
                        this[Z].style[ab] = E(ab, ac)
                    }
                }
                return this
            },
            vendorCss : function(Y, Z, aa) {
                return this.css(H.feat.cssPrefix + Y, Z, aa)
            },
            cssTranslate : function(Y) {
                return this
                        .vendorCss("Transform", "translate"
                                + H.feat.cssTransformStart + Y
                                + H.feat.cssTransformEnd)
            },
            computedStyle : function(Y) {
                if (this.length === 0 || Y == j) {
                    return
                }
                return M.getComputedStyle(this[0], "")[Y]
            },
            empty : function() {
                for (var Y = 0; Y < this.length; Y++) {
                    H.cleanUpContent(this[Y], false, true);
                    this[Y].textContent = ""
                }
                return this
            },
            hide : function() {
                if (this.length === 0) {
                    return this
                }
                for (var Y = 0; Y < this.length; Y++) {
                    if (this.css("display", null, this[Y]) != "none") {
                        this[Y].setAttribute("afmOldStyle", this.css("display",
                                null, this[Y]));
                        this[Y].style.display = "none"
                    }
                }
                return this
            },
            show : function() {
                if (this.length === 0) {
                    return this
                }
                for (var Y = 0; Y < this.length; Y++) {
                    if (this.css("display", null, this[Y]) == "none") {
                        this[Y].style.display = this[Y]
                                .getAttribute("afmOldStyle") ? this[Y]
                                .getAttribute("afmOldStyle") : "block";
                        this[Y].removeAttribute("afmOldStyle")
                    }
                }
                return this
            },
            toggle : function(Z) {
                if (this.length === 0) {
                    return this
                }
                var Y = !!(Z === true);
                for (var aa = 0; aa < this.length; aa++) {
                    if (this.css("display", null, this[aa]) != "none"
                            && (Z == j || Y === false)) {
                        this[aa].setAttribute("afmOldStyle", this.css(
                                "display", null, this[aa]));
                        this[aa].style.display = "none"
                    } else {
                        if (this.css("display", null, this[aa]) == "none"
                                && (Z == j || Y === true)) {
                            this[aa].style.display = this[aa]
                                    .getAttribute("afmOldStyle") ? this[aa]
                                    .getAttribute("afmOldStyle") : "block";
                            this[aa].removeAttribute("afmOldStyle")
                        }
                    }
                }
                return this
            },
            val : function(Z) {
                if (this.length === 0) {
                    return (Z === j) ? undefined : this
                }
                if (Z == j) {
                    return this[0].value
                }
                for (var Y = 0; Y < this.length; Y++) {
                    this[Y].value = Z
                }
                return this
            },
            attr : function(Y, ab) {
                if (this.length === 0) {
                    return (ab === j) ? undefined : this
                }
                if (ab === j && !H.isObject(Y)) {
                    var ac = (this[0].afmCacheId && p[this[0].afmCacheId][Y])
                            ? (this[0].afmCacheId && p[this[0].afmCacheId][Y])
                            : this[0].getAttribute(Y);
                    return ac
                }
                for (var aa = 0; aa < this.length; aa++) {
                    if (H.isObject(Y)) {
                        for (var Z in Y) {
                            H(this[aa]).attr(Z, Y[Z])
                        }
                    } else {
                        if (H.isArray(ab) || H.isObject(ab) || H.isFunction(ab)) {
                            if (!this[aa].afmCacheId) {
                                this[aa].afmCacheId = H.uuid()
                            }
                            if (!p[this[aa].afmCacheId]) {
                                p[this[aa].afmCacheId] = {}
                            }
                            p[this[aa].afmCacheId][Y] = ab
                        } else {
                            if (ab === null) {
                                this[aa].removeAttribute(Y);
                                if (this[aa].afmCacheId
                                        && p[this[aa].afmCacheId][Y]) {
                                    delete p[this[aa].afmCacheId][Y]
                                }
                            } else {
                                this[aa].setAttribute(Y, ab)
                            }
                        }
                    }
                }
                return this
            },
            removeAttr : function(Y) {
                var aa = this;
                for (var Z = 0; Z < this.length; Z++) {
                    Y.split(/\s+/g).forEach(function(ab) {
                        aa[Z].removeAttribute(ab);
                        if (aa[Z].afmCacheId && p[aa[Z].afmCacheId][Y]) {
                            delete p[aa[Z].afmCacheId][Y]
                        }
                    })
                }
                return this
            },
            prop : function(ad, ab) {
                if (this.length === 0) {
                    return (ab === j) ? undefined : this
                }
                if (ab === j && !H.isObject(ad)) {
                    var aa;
                    var ac = (this[0].afmCacheId && x[this[0].afmCacheId][ad])
                            ? (this[0].afmCacheId && x[this[0].afmCacheId][ad])
                            : !(aa = this[0][ad]) && ad in this[0]
                                    ? this[0][ad]
                                    : aa;
                    return ac
                }
                for (var Z = 0; Z < this.length; Z++) {
                    if (H.isObject(ad)) {
                        for (var Y in ad) {
                            H(this[Z]).prop(Y, ad[Y])
                        }
                    } else {
                        if (H.isArray(ab) || H.isObject(ab) || H.isFunction(ab)) {
                            if (!this[Z].afmCacheId) {
                                this[Z].afmCacheId = H.uuid()
                            }
                            if (!x[this[Z].afmCacheId]) {
                                x[this[Z].afmCacheId] = {}
                            }
                            x[this[Z].afmCacheId][ad] = ab
                        } else {
                            if (ab === null && ab !== undefined) {
                                H(this[Z]).removeProp(ad)
                            } else {
                                this[Z][ad] = ab
                            }
                        }
                    }
                }
                return this
            },
            removeProp : function(aa) {
                var Z = this;
                for (var Y = 0; Y < this.length; Y++) {
                    aa.split(/\s+/g).forEach(function(ab) {
                        if (Z[Y][ab]) {
                            Z[Y][ab] = undefined
                        }
                        if (Z[Y].afmCacheId && x[Z[Y].afmCacheId][aa]) {
                            delete x[Z[Y].afmCacheId][aa]
                        }
                    })
                }
                return this
            },
            remove : function(Y) {
                var Z = H(this).filter(Y);
                if (Z == j) {
                    return this
                }
                for (var aa = 0; aa < Z.length; aa++) {
                    H.cleanUpContent(Z[aa], true, true);
                    if (Z[aa] && Z[aa].parentNode) {
                        Z[aa].parentNode.removeChild(Z[aa])
                    }
                }
                return this
            },
            addClass : function(Z) {
                if (Z == j) {
                    return this
                }
                for (var aa = 0; aa < this.length; aa++) {
                    var Y = this[aa].className;
                    var ac = [];
                    var ab = this;
                    Z.split(/\s+/g).forEach(function(ad) {
                        if (!ab.hasClass(ad, ab[aa])) {
                            ac.push(ad)
                        }
                    });
                    this[aa].className += (Y ? " " : "") + ac.join(" ");
                    this[aa].className = this[aa].className.trim()
                }
                return this
            },
            removeClass : function(Y) {
                if (Y == j) {
                    return this
                }
                for (var Z = 0; Z < this.length; Z++) {
                    if (Y == j) {
                        this[Z].className = "";
                        return this
                    }
                    var aa = this[Z].className;
                    if (typeof this[Z].className == "object") {
                        aa = " "
                    }
                    Y.split(/\s+/g).forEach(function(ab) {
                        aa = aa.replace(T(ab), " ")
                    });
                    if (aa.length > 0) {
                        this[Z].className = aa.trim()
                    } else {
                        this[Z].className = ""
                    }
                }
                return this
            },
            toggleClass : function(Y, aa) {
                if (Y == j) {
                    return this
                }
                for (var Z = 0; Z < this.length; Z++) {
                    if (typeof aa != "boolean") {
                        aa = this.hasClass(Y, this[Z])
                    }
                    H(this[Z])[aa ? "removeClass" : "addClass"](Y)
                }
                return this
            },
            replaceClass : function(Z, Y) {
                if (Z == j || Y == j) {
                    return this
                }
                for (var aa = 0; aa < this.length; aa++) {
                    if (Z == j) {
                        this[aa].className = Y;
                        continue
                    }
                    var ab = this[aa].className;
                    Z.split(/\s+/g).concat(Y.split(/\s+/g))
                            .forEach(function(ac) {
                                ab = ab.replace(T(ac), " ")
                            });
                    ab = ab.trim();
                    if (ab.length > 0) {
                        this[aa].className = (ab + " " + Y).trim()
                    } else {
                        this[aa].className = Y
                    }
                }
                return this
            },
            hasClass : function(Y, Z) {
                if (this.length === 0) {
                    return false
                }
                if (!Z) {
                    Z = this[0]
                }
                return T(Y).test(Z.className)
            },
            append : function(Z, aa) {
                if (Z && Z.length != j && Z.length === 0) {
                    return this
                }
                if (H.isArray(Z) || H.isObject(Z)) {
                    Z = H(Z)
                }
                var Y;
                for (Y = 0; Y < this.length; Y++) {
                    if (Z.length && typeof Z != "string") {
                        Z = H(Z);
                        G(Z, this[Y], aa)
                    } else {
                        var ab = y.test(Z) ? H(Z) : undefined;
                        if (ab == j || ab.length === 0) {
                            ab = h.createTextNode(Z)
                        }
                        if (ab.nodeName != j
                                && ab.nodeName.toLowerCase() == "script"
                                && (!ab.type || ab.type.toLowerCase() === "text/javascript")) {
                            M["eval"](ab.innerHTML)
                        } else {
                            if (ab instanceof i) {
                                G(ab, this[Y], aa)
                            } else {
                                aa != j ? this[Y].insertBefore(ab,
                                        this[Y].firstChild) : this[Y]
                                        .appendChild(ab)
                            }
                        }
                    }
                }
                return this
            },
            appendTo : function(Y, aa) {
                var Z = H(Y);
                Z.append(this);
                return this
            },
            prependTo : function(Y) {
                var Z = H(Y);
                Z.append(this, true);
                return this
            },
            prepend : function(Y) {
                return this.append(Y, 1)
            },
            insertBefore : function(Z, aa) {
                if (this.length === 0) {
                    return this
                }
                Z = H(Z).get(0);
                if (!Z) {
                    return this
                }
                for (var Y = 0; Y < this.length; Y++) {
                    aa
                            ? Z.parentNode.insertBefore(this[Y], Z.nextSibling)
                            : Z.parentNode.insertBefore(this[Y], Z)
                }
                return this
            },
            insertAfter : function(Y) {
                this.insertBefore(Y, true)
            },
            get : function(Y) {
                Y = Y == j ? 0 : Y;
                if (Y < 0) {
                    Y += this.length
                }
                return (this[Y]) ? this[Y] : undefined
            },
            offset : function() {
                var Y;
                if (this.length === 0) {
                    return this
                }
                if (this[0] == M) {
                    return {
                        left : 0,
                        top : 0,
                        right : 0,
                        bottom : 0,
                        width : M.innerWidth,
                        height : M.innerHeight
                    }
                } else {
                    Y = this[0].getBoundingClientRect()
                }
                return {
                    left : Y.left + M.pageXOffset,
                    top : Y.top + M.pageYOffset,
                    right : Y.right + M.pageXOffset,
                    bottom : Y.bottom + M.pageYOffset,
                    width : Y.right - Y.left,
                    height : Y.bottom - Y.top
                }
            },
            height : function(Z) {
                if (this.length === 0) {
                    return this
                }
                if (Z != j) {
                    return this.css("height", Z)
                }
                if (this[0] == this[0].window) {
                    return M.innerHeight
                }
                if (this[0].nodeType == this[0].DOCUMENT_NODE) {
                    return this[0].documentElement.offsetheight
                } else {
                    var Y = this.css("height").replace("px", "");
                    if (Y) {
                        return Y
                    } else {
                        return this.offset().height
                    }
                }
            },
            width : function(Z) {
                if (this.length === 0) {
                    return this
                }
                if (Z != j) {
                    return this.css("width", Z)
                }
                if (this[0] == this[0].window) {
                    return M.innerWidth
                }
                if (this[0].nodeType == this[0].DOCUMENT_NODE) {
                    return this[0].documentElement.offsetwidth
                } else {
                    var Y = this.css("width").replace("px", "");
                    if (Y) {
                        return Y
                    } else {
                        return this.offset().width
                    }
                }
            },
            parent : function(Y, aa) {
                if (this.length === 0) {
                    return this
                }
                var Z = [];
                for (var ac = 0; ac < this.length; ac++) {
                    var ab = this[ac];
                    while (ab.parentNode && ab.parentNode != h) {
                        Z.push(ab.parentNode);
                        if (ab.parentNode) {
                            ab = ab.parentNode
                        }
                        if (!aa) {
                            break
                        }
                    }
                }
                return this.setupOld(H(e(Z)).filter(Y))
            },
            parents : function(Y) {
                return this.parent(Y, true)
            },
            children : function(Y) {
                if (this.length === 0) {
                    return this
                }
                var Z = [];
                for (var aa = 0; aa < this.length; aa++) {
                    Z = Z.concat(R(this[aa].firstChild))
                }
                return this.setupOld(H((Z)).filter(Y))
            },
            siblings : function(Y) {
                if (this.length === 0) {
                    return this
                }
                var Z = [];
                for (var aa = 0; aa < this.length; aa++) {
                    if (this[aa].parentNode) {
                        Z = Z
                                .concat(R(this[aa].parentNode.firstChild,
                                        this[aa]))
                    }
                }
                return this.setupOld(H(Z).filter(Y))
            },
            closest : function(Y, aa) {
                if (this.length === 0) {
                    return this
                }
                var Z = [], ab = this[0];
                var ac = H(Y, aa);
                if (ac.length === 0) {
                    return H()
                }
                while (ab && ac.indexOf(ab) == -1) {
                    ab = ab !== aa && ab !== h && ab.parentNode
                }
                return H(ab)
            },
            filter : function(Y) {
                if (this.length === 0) {
                    return this
                }
                if (Y == j) {
                    return this
                }
                var Z = [];
                for (var aa = 0; aa < this.length; aa++) {
                    var ab = this[aa];
                    if (ab.parentNode && H(Y, ab.parentNode).indexOf(ab) >= 0) {
                        Z.push(ab)
                    }
                }
                return this.setupOld(H(e(Z)))
            },
            not : function(Y) {
                if (this.length === 0) {
                    return this
                }
                var Z = [];
                for (var aa = 0; aa < this.length; aa++) {
                    var ab = this[aa];
                    if (ab.parentNode && H(Y, ab.parentNode).indexOf(ab) == -1) {
                        Z.push(ab)
                    }
                }
                return this.setupOld(H(e(Z)))
            },
            data : function(Y, Z) {
                return this.attr("data-" + Y, Z)
            },
            end : function() {
                return this.oldElement != j ? this.oldElement : H()
            },
            clone : function(Y) {
                Y = Y === false ? false : true;
                if (this.length === 0) {
                    return this
                }
                var Z = [];
                for (var aa = 0; aa < this.length; aa++) {
                    Z.push(this[aa].cloneNode(Y))
                }
                return H(Z)
            },
            size : function() {
                return this.length
            },
            serialize : function() {
                if (this.length === 0) {
                    return ""
                }
                var Z = [];
                for (var Y = 0; Y < this.length; Y++) {
                    this.slice.call(this[Y].elements).forEach(function(ac) {
                        var ab = ac.getAttribute("type");
                        if (ac.nodeName.toLowerCase() != "fieldset"
                                && !ac.disabled
                                && ab != "submit"
                                && ab != "reset"
                                && ab != "button"
                                && ((ab != "radio" && ab != "checkbox") || ac.checked)) {
                            if (ac.getAttribute("name")) {
                                if (ac.type == "select-multiple") {
                                    for (var aa = 0; aa < ac.options.length; aa++) {
                                        if (ac.options[aa].selected) {
                                            Z
                                                    .push(ac
                                                            .getAttribute("name")
                                                            + "="
                                                            + encodeURIComponent(ac.options[aa].value))
                                        }
                                    }
                                } else {
                                    Z.push(ac.getAttribute("name") + "="
                                            + encodeURIComponent(ac.value))
                                }
                            }
                        }
                    })
                }
                return Z.join("&")
            },
            eq : function(Y) {
                return H(this.get(Y))
            },
            index : function(Y) {
                return Y ? this.indexOf(H(Y)[0]) : this.parent().children()
                        .indexOf(this[0])
            },
            is : function(Y) {
                return !!Y && this.filter(Y).length > 0
            }
        };
        function a() {
        }
        H.ajaxSettings = {
            type : "GET",
            beforeSend : a,
            success : a,
            error : a,
            complete : a,
            context : undefined,
            timeout : 0,
            crossDomain : null
        };
        H.jsonP = function(Z) {
            if (N) {
                Z.type = "get";
                Z.dataType = null;
                return H.get(Z)
            }
            var ac = "jsonp_callback" + (++c);
            var ab = "", aa;
            var Y = h.createElement("script");
            var ad = function() {
                H(Y).remove();
                if (M[ac]) {
                    M[ac] = a
                }
            };
            M[ac] = function(ae) {
                clearTimeout(ab);
                H(Y).remove();
                delete M[ac];
                Z.success.call(aa, ae)
            };
            Y.src = Z.url.replace(/=\?/, "=" + ac);
            if (Z.error) {
                Y.onerror = function() {
                    clearTimeout(ab);
                    Z.error.call(aa, "", "error")
                }
            }
            H("head").append(Y);
            if (Z.timeout > 0) {
                ab = setTimeout(function() {
                    Z.error.call(aa, "", "timeout")
                }, Z.timeout)
            }
            return {}
        };
        H.ajax = function(Y) {
            var ag;
            try {
                var ab = Y || {};
                for (var ae in H.ajaxSettings) {
                    if (typeof(ab[ae]) == "undefined") {
                        ab[ae] = H.ajaxSettings[ae]
                    }
                }
                if (!ab.url) {
                    ab.url = M.location
                }
                if (!ab.contentType) {
                    ab.contentType = "application/x-www-form-urlencoded"
                }
                if (!ab.headers) {
                    ab.headers = {}
                }
                if (!("async" in ab) || ab.async !== false) {
                    ab.async = true
                }
                if (!ab.dataType) {
                    ab.dataType = "text/html"
                } else {
                    switch (ab.dataType) {
                        case "script" :
                            ab.dataType = "text/javascript, application/javascript";
                            break;
                        case "json" :
                            ab.dataType = "application/json";
                            break;
                        case "xml" :
                            ab.dataType = "application/xml, text/xml";
                            break;
                        case "html" :
                            ab.dataType = "text/html";
                            break;
                        case "text" :
                            ab.dataType = "text/plain";
                            break;
                        default :
                            ab.dataType = "text/html";
                            break;
                        case "jsonp" :
                            return H.jsonP(Y)
                    }
                }
                if (H.isObject(ab.data)) {
                    ab.data = H.param(ab.data)
                }
                if (ab.type.toLowerCase() === "get" && ab.data) {
                    if (ab.url.indexOf("?") === -1) {
                        ab.url += "?" + ab.data
                    } else {
                        ab.url += "&" + ab.data
                    }
                }
                if (/=\?/.test(ab.url)) {
                    return H.jsonP(ab)
                }
                if (ab.crossDomain === null) {
                    ab.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(ab.url)
                            && RegExp.$2 != M.location.host
                }
                if (!ab.crossDomain) {
                    ab.headers = H.extend({
                        "X-Requested-With" : "XMLHttpRequest"
                    }, ab.headers)
                }
                var ad;
                var aa = ab.context;
                var ah = /^([\w-]+:)\/\//.test(ab.url)
                        ? RegExp.$1
                        : M.location.protocol;
                ag = new M.XMLHttpRequest();
                ag.onreadystatechange = function() {
                    var ak = ab.dataType;
                    if (ag.readyState === 4) {
                        clearTimeout(ad);
                        var ai, aj = false;
                        if ((ag.status >= 200 && ag.status < 300)
                                || ag.status === 0) {
                            if (ak === "application/json"
                                    && !(/^\s*$/.test(ag.responseText))) {
                                try {
                                    ai = JSON.parse(ag.responseText)
                                } catch (al) {
                                    aj = al
                                }
                            } else {
                                if (ak === "application/xml, text/xml") {
                                    ai = ag.responseXML
                                } else {
                                    if (ak == "text/html") {
                                        ai = ag.responseText;
                                        H.parseJS(ai)
                                    } else {
                                        ai = ag.responseText
                                    }
                                }
                            }
                            if (ag.status === 0 && ai.length === 0) {
                                aj = true
                            }
                            if (aj) {
                                ab.error.call(aa, ag, "parsererror", aj)
                            } else {
                                ab.success.call(aa, ai, "success", ag)
                            }
                        } else {
                            aj = true;
                            ab.error.call(aa, ag, "error")
                        }
                        ab.complete.call(aa, ag, aj ? "error" : "success")
                    }
                };
                ag.open(ab.type, ab.url, ab.async);
                if (ab.withCredentials) {
                    ag.withCredentials = true
                }
                if (ab.contentType) {
                    ab.headers["Content-Type"] = ab.contentType
                }
                for (var Z in ab.headers) {
                    if (typeof ab.headers[Z] === "string") {
                        ag.setRequestHeader(Z, ab.headers[Z])
                    }
                }
                if (ab.beforeSend.call(aa, ag, ab) === false) {
                    ag.abort();
                    return false
                }
                if (ab.timeout > 0) {
                    ad = setTimeout(function() {
                        ag.onreadystatechange = a;
                        ag.abort();
                        ab.error.call(aa, ag, "timeout")
                    }, ab.timeout)
                }
                ag.send(ab.data)
            } catch (ac) {
                console.log(ac);
                ab.error.call(aa, ag, "error", ac)
            }
            return ag
        };
        H.get = function(Y, Z) {
            return this.ajax({
                url : Y,
                success : Z
            })
        };
        H.post = function(Z, aa, ab, Y) {
            if (typeof(aa) === "function") {
                ab = aa;
                aa = {}
            }
            if (Y === j) {
                Y = "html"
            }
            return this.ajax({
                url : Z,
                type : "POST",
                data : aa,
                dataType : Y,
                success : ab
            })
        };
        H.getJSON = function(Y, Z, aa) {
            if (typeof(Z) === "function") {
                aa = Z;
                Z = {}
            }
            return this.ajax({
                url : Y,
                data : Z,
                success : aa,
                dataType : "json"
            })
        };
        H.param = function(ac, aa) {
            var ad = [];
            if (ac instanceof i) {
                ac.each(function() {
                    var ag = aa ? aa + "[" + this.id + "]" : this.id, ae = this.value;
                    ad.push((ag) + "=" + encodeURIComponent(ae))
                })
            } else {
                for (var ab in ac) {
                    if (H.isFunction(ac[ab])) {
                        continue
                    }
                    var Z = aa ? aa + "[" + ab + "]" : ab, Y = ac[ab];
                    ad.push(H.isObject(Y) ? H.param(Y, Z) : (Z) + "="
                            + encodeURIComponent(Y))
                }
            }
            return ad.join("&")
        };
        H.parseJSON = function(Y) {
            return JSON.parse(Y)
        };
        H.parseXML = function(Y) {
            if (N) {
                MSApp.execUnsafeLocalFunction(function() {
                    return (new DOMParser()).parseFromString(Y, "text/xml")
                })
            } else {
                return (new DOMParser()).parseFromString(Y, "text/xml")
            }
        };
        function g(aa, Z) {
            aa.os = {};
            aa.os.webkit = Z.match(/WebKit\/([\d.]+)/) ? true : false;
            aa.os.android = Z.match(/(Android)\s+([\d.]+)/)
                    || Z.match(/Silk-Accelerated/) ? true : false;
            aa.os.androidICS = aa.os.android && Z.match(/(Android)\s4/)
                    ? true
                    : false;
            aa.os.ipad = Z.match(/(iPad).*OS\s([\d_]+)/) ? true : false;
            aa.os.iphone = !aa.os.ipad && Z.match(/(iPhone\sOS)\s([\d_]+)/)
                    ? true
                    : false;
            aa.os.ios7 = Z.match(/(iPhone\sOS)\s([7_]+)/) ? true : false;
            aa.os.webos = Z.match(/(webOS|hpwOS)[\s\/]([\d.]+)/) ? true : false;
            aa.os.touchpad = aa.os.webos && Z.match(/TouchPad/) ? true : false;
            aa.os.ios = aa.os.ipad || aa.os.iphone;
            aa.os.playbook = Z.match(/PlayBook/) ? true : false;
            aa.os.blackberry10 = Z.match(/BB10/) ? true : false;
            aa.os.blackberry = aa.os.playbook || aa.os.blackberry10
                    || Z.match(/BlackBerry/) ? true : false;
            aa.os.chrome = Z.match(/Chrome/) ? true : false;
            aa.os.opera = Z.match(/Opera/) ? true : false;
            aa.os.fennec = Z.match(/fennec/i) ? true : Z.match(/Firefox/)
                    ? true
                    : false;
            aa.os.ie = Z.match(/MSIE 10.0/i) ? true : false;
            aa.os.ieTouch = aa.os.ie && Z.toLowerCase().match(/touch/i)
                    ? true
                    : false;
            aa.os.supportsTouch = ((M.DocumentTouch && h instanceof M.DocumentTouch) || "ontouchstart" in M);
            aa.feat = {};
            var Y = h.documentElement.getElementsByTagName("head")[0];
            aa.feat.nativeTouchScroll = typeof(Y.style["-webkit-overflow-scrolling"]) !== "undefined"
                    && (aa.os.ios || aa.os.blackberry10);
            aa.feat.cssPrefix = aa.os.webkit ? "Webkit" : aa.os.fennec
                    ? "Moz"
                    : aa.os.ie ? "ms" : aa.os.opera ? "O" : "";
            aa.feat.cssTransformStart = !aa.os.opera ? "3d(" : "(";
            aa.feat.cssTransformEnd = !aa.os.opera ? ",0)" : ")";
            if (aa.os.android && !aa.os.webkit) {
                aa.os.android = false
            }
        }
        g(H, navigator.userAgent);
        H.__detectUA = g;
        H.uuid = function() {
            var Y = function() {
                return (((1 + Math.random()) * 65536) | 0).toString(16)
                        .substring(1)
            };
            return (Y() + Y() + "-" + Y() + "-" + Y() + "-" + Y() + "-" + Y()
                    + Y() + Y())
        };
        H.getCssMatrix = function(ac) {
            if (H.is$(ac)) {
                ac = ac.get(0)
            }
            var ab = M.WebKitCSSMatrix || M.MSCSSMatrix;
            if (ac === j) {
                if (ab) {
                    return new ab()
                } else {
                    return {
                        a : 0,
                        b : 0,
                        c : 0,
                        d : 0,
                        e : 0,
                        f : 0
                    }
                }
            }
            var Y = M.getComputedStyle(ac);
            var Z = Y.webkitTransform || Y.transform
                    || Y[H.feat.cssPrefix + "Transform"];
            if (ab) {
                return new ab(Z)
            } else {
                if (Z) {
                    var aa = Z.replace(/[^0-9\-.,]/g, "").split(",");
                    return {
                        a : +aa[0],
                        b : +aa[1],
                        c : +aa[2],
                        d : +aa[3],
                        e : +aa[4],
                        f : +aa[5]
                    }
                } else {
                    return {
                        a : 0,
                        b : 0,
                        c : 0,
                        d : 0,
                        e : 0,
                        f : 0
                    }
                }
            }
        };
        H.create = function(aa, Z) {
            var ab;
            var ac = new i();
            if (Z || aa[0] !== "<") {
                if (Z.html) {
                    Z.innerHTML = Z.html, delete Z.html
                }
                ab = h.createElement(aa);
                for (var Y in Z) {
                    ab[Y] = Z[Y]
                }
                ac[ac.length++] = ab
            } else {
                ab = h.createElement("div");
                if (N) {
                    MSApp.execUnsafeLocalFunction(function() {
                        ab.innerHTML = selector.trim()
                    })
                } else {
                    ab.innerHTML = aa
                }
                S(ab.childNodes, ac)
            }
            return ac
        };
        H.query = function(Z, aa) {
            if (!Z) {
                return new i()
            }
            aa = aa || h;
            var Y = new i();
            return Y.selector(Z, aa)
        };
        var b = {}, w = 1;
        function u(Y) {
            return Y._afmid || (Y._afmid = w++)
        }
        function L(Z, ab, aa, Y) {
            ab = t(ab);
            if (ab.ns) {
                var ac = D(ab.ns)
            }
            return (b[u(Z)] || []).filter(function(ad) {
                return ad
                        && (!ab.e || ad.e == ab.e)
                        && (!ab.ns || ac.test(ad.ns))
                        && (!aa || ad.fn == aa || (typeof ad.fn === "function"
                                && typeof aa === "function" && ad.fn === aa))
                        && (!Y || ad.sel == Y)
            })
        }
        function t(Y) {
            var Z = ("" + Y).split(".");
            return {
                e : Z[0],
                ns : Z.slice(1).sort().join(" ")
            }
        }
        function D(Y) {
            return new RegExp("(?:^| )" + Y.replace(" ", " .* ?") + "(?: |$)")
        }
        function r(Y, aa, Z) {
            if (H.isObject(Y)) {
                H.each(Y, Z)
            } else {
                Y.split(/\s/).forEach(function(ab) {
                    Z(ab, aa)
                })
            }
        }
        function f(ab, aa, ac, Z, Y) {
            var ae = u(ab), ad = (b[ae] || (b[ae] = []));
            r(aa, ac, function(aj, ai) {
                var ah = Y && Y(ai, aj), al = ah || ai;
                var ak = function(an) {
                    var am = al.apply(ab, [an].concat(an.data));
                    if (am === false) {
                        an.preventDefault()
                    }
                    return am
                };
                var ag = H.extend(t(aj), {
                    fn : ai,
                    proxy : ak,
                    sel : Z,
                    del : ah,
                    i : ad.length
                });
                ad.push(ag);
                ab.addEventListener(ag.e, ak, false)
            })
        }
        function z(aa, Z, ab, Y) {
            var ac = u(aa);
            r(Z || "", ab, function(ae, ad) {
                L(aa, ae, ad, Y).forEach(function(ag) {
                    delete b[ac][ag.i];
                    aa.removeEventListener(ag.e, ag.proxy, false)
                })
            })
        }
        H.event = {
            add : f,
            remove : z
        };
        H.fn.bind = function(Z, aa) {
            for (var Y = 0; Y < this.length; Y++) {
                f(this[Y], Z, aa)
            }
            return this
        };
        H.fn.unbind = function(Z, aa) {
            for (var Y = 0; Y < this.length; Y++) {
                z(this[Y], Z, aa)
            }
            return this
        };
        H.fn.one = function(Y, Z) {
            return this.each(function(ab, aa) {
                f(this, Y, Z, null, function(ad, ac) {
                    return function() {
                        z(aa, ac, ad);
                        var ae = ad.apply(aa, arguments);
                        return ae
                    }
                })
            })
        };
        var Q = function() {
            return true
        };
        var X = function() {
            return false
        };
        var v = {
            preventDefault : "isDefaultPrevented",
            stopImmediatePropagation : "isImmediatePropagationStopped",
            stopPropagation : "isPropagationStopped"
        };
        function C(Z) {
            var Y = H.extend({
                originalEvent : Z
            }, Z);
            H.each(v, function(ab, aa) {
                Y[ab] = function() {
                    this[aa] = Q;
                    if (ab == "stopImmediatePropagation"
                            || ab == "stopPropagation") {
                        Z.cancelBubble = true;
                        if (!Z[ab]) {
                            return
                        }
                    }
                    return Z[ab].apply(Z, arguments)
                };
                Y[aa] = X
            });
            return Y
        }
        function A(Z, aa, ab, Y) {
            f(Z, aa, ab, Y, function(ac) {
                return function(ag) {
                    var ad, ae = H(ag.target).closest(Y, Z).get(0);
                    if (ae) {
                        ad = H.extend(C(ag), {
                            currentTarget : ae,
                            liveFired : Z
                        });
                        return ac.apply(ae, [ad].concat([].slice.call(
                                arguments, 1)))
                    }
                }
            })
        }
        H.fn.delegate = function(Y, aa, ab) {
            for (var Z = 0; Z < this.length; Z++) {
                A(this[Z], aa, ab, Y)
            }
            return this
        };
        H.fn.undelegate = function(Y, aa, ab) {
            for (var Z = 0; Z < this.length; Z++) {
                z(this[Z], aa, ab, Y)
            }
            return this
        };
        H.fn.on = function(Z, Y, aa) {
            return Y === j || H.isFunction(Y) ? this.bind(Z, Y) : this
                    .delegate(Y, Z, aa)
        };
        H.fn.off = function(Z, Y, aa) {
            return Y === j || H.isFunction(Y) ? this.unbind(Z, Y) : this
                    .undelegate(Y, Z, aa)
        };
        H.fn.trigger = function(aa, ab, Z) {
            if (typeof aa == "string") {
                aa = H.Event(aa, Z)
            }
            aa.data = ab;
            for (var Y = 0; Y < this.length; Y++) {
                this[Y].dispatchEvent(aa)
            }
            return this
        };
        H.Event = function(ab, aa) {
            var ac = h.createEvent("Events"), Y = true;
            if (aa) {
                for (var Z in aa) {
                    (Z == "bubbles") ? (Y = !!aa[Z]) : (ac[Z] = aa[Z])
                }
            }
            ac.initEvent(ab, Y, true, null, null, null, null, null, null, null,
                    null, null, null, null, null);
            return ac
        };
        H.bind = function(ab, Z, aa) {
            if (!ab) {
                return
            }
            if (!ab.__events) {
                ab.__events = {}
            }
            if (!H.isArray(Z)) {
                Z = [Z]
            }
            for (var Y = 0; Y < Z.length; Y++) {
                if (!ab.__events[Z[Y]]) {
                    ab.__events[Z[Y]] = []
                }
                ab.__events[Z[Y]].push(aa)
            }
        };
        H.trigger = function(ae, ad, ab) {
            if (!ae) {
                return
            }
            var aa = true;
            if (!ae.__events) {
                return aa
            }
            if (!H.isArray(ad)) {
                ad = [ad]
            }
            if (!H.isArray(ab)) {
                ab = []
            }
            for (var ac = 0; ac < ad.length; ac++) {
                if (ae.__events[ad[ac]]) {
                    var Y = ae.__events[ad[ac]].slice(0);
                    for (var Z = 0; Z < Y.length; Z++) {
                        if (H.isFunction(Y[Z]) && Y[Z].apply(ae, ab) === false) {
                            aa = false
                        }
                    }
                }
            }
            return aa
        };
        H.unbind = function(ad, ab, ac) {
            if (!ad.__events) {
                return
            }
            if (!H.isArray(ab)) {
                ab = [ab]
            }
            for (var aa = 0; aa < ab.length; aa++) {
                if (ad.__events[ab[aa]]) {
                    var Y = ad.__events[ab[aa]];
                    for (var Z = 0; Z < Y.length; Z++) {
                        if (ac == j) {
                            delete Y[Z]
                        }
                        if (Y[Z] == ac) {
                            Y.splice(Z, 1);
                            break
                        }
                    }
                }
            }
        };
        H.proxy = function(Z, aa, Y) {
            return function() {
                if (Y) {
                    return Z.apply(aa, Y)
                }
                return Z.apply(aa, arguments)
            }
        };
        function n(aa, Z) {
            if (Z && aa.dispatchEvent) {
                var ab = H.Event("destroy", {
                    bubbles : false
                });
                aa.dispatchEvent(ab)
            }
            var ac = u(aa);
            if (ac && b[ac]) {
                for (var Y in b[ac]) {
                    aa.removeEventListener(b[ac][Y].e, b[ac][Y].proxy, false)
                }
                delete b[ac]
            }
        }
        function I(ab, aa) {
            if (!ab) {
                return
            }
            var Z = ab.childNodes;
            if (Z && Z.length > 0) {
                for (var Y; Y < Z.length; Y++) {
                    I(Z[Y], aa)
                }
            }
            n(ab, aa)
        }
        var q = function(aa, Z) {
            for (var Y = 0; Y < aa.length; Y++) {
                I(aa[Y], Z)
            }
        };
        H.cleanUpContent = function(aa, Y, Z) {
            if (!aa) {
                return
            }
            var ab = aa.childNodes;
            if (ab && ab.length > 0) {
                H.asap(q, {}, [s.apply(ab, [0]), Z])
            }
            if (Y) {
                n(aa, Z)
            }
        };
        var V = [];
        var B = [];
        var d = [];
        H.asap = function(aa, Z, Y) {
            if (!H.isFunction(aa)) {
                throw "$.asap - argument is not a valid function"
            }
            V.push(aa);
            B.push(Z ? Z : {});
            d.push(Y ? Y : []);
            M.postMessage("afm-asap", "*")
        };
        M.addEventListener("message", function(Y) {
            if (Y.source == M && Y.data == "afm-asap") {
                Y.stopPropagation();
                if (V.length > 0) {
                    (V.shift()).apply(B.shift(), d.shift())
                }
            }
        }, true);
        var l = {};
        H.parseJS = function(ac) {
            if (!ac) {
                return
            }
            if (typeof(ac) == "string") {
                var aa = h.createElement("div");
                if (N) {
                    MSApp.execUnsafeLocalFunction(function() {
                        aa.innerHTML = ac
                    })
                } else {
                    aa.innerHTML = ac
                }
                ac = aa
            }
            var Y = ac.getElementsByTagName("script");
            ac = null;
            for (var Z = 0; Z < Y.length; Z++) {
                if (Y[Z].src.length > 0 && !l[Y[Z].src] && !N) {
                    var ab = h.createElement("script");
                    ab.type = Y[Z].type;
                    ab.src = Y[Z].src;
                    h.getElementsByTagName("head")[0].appendChild(ab);
                    l[Y[Z].src] = 1;
                    ab = null
                } else {
                    M["eval"](Y[Z].innerHTML)
                }
            }
        };
        ["click", "keydown", "keyup", "keypress", "submit", "load", "resize",
                "change", "select", "error"].forEach(function(Y) {
            H.fn[Y] = function(Z) {
                return Z ? this.bind(Y, Z) : this.trigger(Y)
            }
        });
        ["focus", "blur"].forEach(function(Y) {
            H.fn[Y] = function(ab) {
                if (this.length === 0) {
                    return
                }
                if (ab) {
                    this.bind(Y, ab)
                } else {
                    for (var Z = 0; Z < this.length; Z++) {
                        try {
                            this[Z][Y]()
                        } catch (aa) {
                        }
                    }
                }
                return this
            }
        });
        return H
    })(window);
    window.jq = af;
    "$" in window || (window.$ = af);
    if (typeof define === "function" && define.amd) {
        define("appframework", [], function() {
            return af
        })
    } else {
        if (typeof module !== "undefined" && module.exports) {
            module.exports.af = af;
            module.exports.$ = af
        }
    }
    if (!window.numOnly) {
        window.numOnly = function numOnly(a) {
            if (a === undefined || a === "") {
                return 0
            }
            if (isNaN(parseFloat(a))) {
                if (a.replace) {
                    a = a.replace(/[^0-9.-]/g, "")
                } else {
                    return 0
                }
            }
            return parseFloat(a)
        }
    }
}
/*! Hammer.JS - v1.0.6dev - 2013-11-18
 * http://eightmedia.github.com/hammer.js
 *
 * Copyright (c) 2013 Jorik Tangelder <j.tangelder@gmail.com>;
 * Licensed under the MIT license */
(function(B, j) {
    var w = function(M, L) {
        return new w.Instance(M, L || {})
    };
    w.defaults = {
        stop_browser_behavior : {
            userSelect : "none",
            touchAction : "none",
            touchCallout : "none",
            contentZooming : "none",
            userDrag : "none",
            tapHighlightColor : "rgba(0,0,0,0)"
        }
    };
    w.HAS_POINTEREVENTS = B.navigator.pointerEnabled
            || B.navigator.msPointerEnabled;
    w.HAS_TOUCHEVENTS = ("ontouchstart" in B);
    w.MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android|silk/i;
    w.NO_MOUSEEVENTS = w.HAS_TOUCHEVENTS
            && B.navigator.userAgent.match(w.MOBILE_REGEX);
    w.EVENT_TYPES = {};
    w.DIRECTION_DOWN = "down";
    w.DIRECTION_LEFT = "left";
    w.DIRECTION_UP = "up";
    w.DIRECTION_RIGHT = "right";
    w.POINTER_MOUSE = "mouse";
    w.POINTER_TOUCH = "touch";
    w.POINTER_PEN = "pen";
    w.EVENT_START = "start";
    w.EVENT_MOVE = "move";
    w.EVENT_END = "end";
    w.DOCUMENT = B.document;
    w.plugins = w.plugins || {};
    w.gestures = w.gestures || {};
    w.READY = false;
    function e() {
        if (w.READY) {
            return
        }
        w.event.determineEventTypes();
        w.utils.each(w.gestures, function(L) {
            w.detection.register(L)
        });
        w.event.onTouch(w.DOCUMENT, w.EVENT_MOVE, w.detection.detect);
        w.event.onTouch(w.DOCUMENT, w.EVENT_END, w.detection.detect);
        w.READY = true
    }
    w.utils = {
        extend : function i(L, N, O) {
            for (var M in N) {
                if (L[M] !== j && O) {
                    continue
                }
                L[M] = N[M]
            }
            return L
        },
        each : function(P, N, M) {
            if ("forEach" in P) {
                P.forEach(N, M)
            } else {
                if (P.length != j) {
                    for (var L = 0, O = P.length; L < O; L++) {
                        if (N.call(M, P[L], L, P) === false) {
                            return
                        }
                    }
                } else {
                    for (var L in P) {
                        if (P.hasOwnProperty(L)
                                && N.call(M, P[L], L, P) === false) {
                            return
                        }
                    }
                }
            }
        },
        hasParent : function(M, L) {
            while (M) {
                if (M == L) {
                    return true
                }
                M = M.parentNode
            }
            return false
        },
        getCenter : function x(M) {
            var N = [], L = [];
            w.utils.each(M, function(O) {
                N.push(typeof O.clientX !== "undefined" ? O.clientX : O.pageX);
                L.push(typeof O.clientY !== "undefined" ? O.clientY : O.pageY)
            });
            return {
                pageX : ((Math.min.apply(Math, N) + Math.max.apply(Math, N)) / 2),
                pageY : ((Math.min.apply(Math, L) + Math.max.apply(Math, L)) / 2)
            }
        },
        getVelocity : function a(L, N, M) {
            return {
                x : Math.abs(N / L) || 0,
                y : Math.abs(M / L) || 0
            }
        },
        getAngle : function n(N, M) {
            var O = M.pageY - N.pageY, L = M.pageX - N.pageX;
            return Math.atan2(O, L) * 180 / Math.PI
        },
        getDirection : function k(N, M) {
            var L = Math.abs(N.pageX - M.pageX), O = Math
                    .abs(N.pageY - M.pageY);
            if (L >= O) {
                return N.pageX - M.pageX > 0
                        ? w.DIRECTION_LEFT
                        : w.DIRECTION_RIGHT
            } else {
                return N.pageY - M.pageY > 0
                        ? w.DIRECTION_UP
                        : w.DIRECTION_DOWN
            }
        },
        getDistance : function m(N, M) {
            var L = M.pageX - N.pageX, O = M.pageY - N.pageY;
            return Math.sqrt((L * L) + (O * O))
        },
        getScale : function v(M, L) {
            if (M.length >= 2 && L.length >= 2) {
                return this.getDistance(L[0], L[1])
                        / this.getDistance(M[0], M[1])
            }
            return 1
        },
        getRotation : function t(M, L) {
            if (M.length >= 2 && L.length >= 2) {
                return this.getAngle(L[1], L[0]) - this.getAngle(M[1], M[0])
            }
            return 0
        },
        isVertical : function A(L) {
            return (L == w.DIRECTION_UP || L == w.DIRECTION_DOWN)
        },
        stopDefaultBrowserBehavior : function c(M, L) {
            var O, N = ["webkit", "khtml", "moz", "Moz", "ms", "o", ""];
            if (!L || !M || !M.style) {
                return
            }
            w.utils.each(N, function(P) {
                w.utils.each(L, function(Q) {
                    if (P) {
                        Q = N + Q.substring(0, 1).toUpperCase()
                                + Q.substring(1)
                    }
                    if (Q in M.style) {
                        M.style[Q] = Q
                    }
                })
            });
            if (L.userSelect == "none") {
                M.onselectstart = function() {
                    return false
                }
            }
            if (L.userDrag == "none") {
                M.ondragstart = function() {
                    return false
                }
            }
        }
    };
    w.Instance = function(N, M) {
        var L = this;
        e();
        this.element = N;
        this.enabled = true;
        this.options = w.utils.extend(w.utils.extend({}, w.defaults), M || {});
        if (this.options.stop_browser_behavior) {
            w.utils.stopDefaultBrowserBehavior(this.element,
                    this.options.stop_browser_behavior)
        }
        w.event.onTouch(N, w.EVENT_START, function(O) {
            if (L.enabled) {
                w.detection.startDetect(L, O)
            }
        });
        return this
    };
    w.Instance.prototype = {
        on : function C(L, M) {
            var N = L.split(" ");
            w.utils.each(N, function(O) {
                this.element.addEventListener(O, M, false)
            }, this);
            return this
        },
        off : function o(L, M) {
            var N = L.split(" ");
            w.utils.each(N, function(O) {
                this.element.removeEventListener(O, M, false)
            }, this);
            return this
        },
        trigger : function G(M, O) {
            if (!O) {
                O = {}
            }
            var N = w.DOCUMENT.createEvent("Event");
            N.initEvent(M, true, true);
            N.gesture = O;
            var L = this.element;
            if (w.utils.hasParent(O.target, L)) {
                L = O.target
            }
            L.dispatchEvent(N);
            return this
        },
        enable : function d(L) {
            this.enabled = L;
            return this
        }
    };
    var F = null;
    var l = false;
    var h = false;
    w.event = {
        bindDom : function(M, O, N) {
            var L = O.split(" ");
            w.utils.each(L, function(P) {
                M.addEventListener(P, N, false)
            })
        },
        onTouch : function z(N, M, O) {
            var L = this;
            this.bindDom(N, w.EVENT_TYPES[M], function P(R) {
                var S = R.type.toLowerCase();
                if (S.match(/mouse/) && h) {
                    return
                } else {
                    if (S.match(/touch/) || S.match(/pointerdown/)
                            || (S.match(/mouse/) && R.which === 1)) {
                        l = true
                    } else {
                        if (S.match(/mouse/) && !R.which) {
                            l = false
                        }
                    }
                }
                if (S.match(/touch|pointer/)) {
                    h = true
                }
                var Q = 0;
                if (l) {
                    if (w.HAS_POINTEREVENTS && M != w.EVENT_END) {
                        Q = w.PointerEvent.updatePointer(M, R)
                    } else {
                        if (S.match(/touch/)) {
                            Q = R.touches.length
                        } else {
                            if (!h) {
                                Q = S.match(/up/) ? 0 : 1
                            }
                        }
                    }
                    if (Q > 0 && M == w.EVENT_END) {
                        M = w.EVENT_MOVE
                    } else {
                        if (!Q) {
                            M = w.EVENT_END
                        }
                    }
                    if (Q || F === null) {
                        F = R
                    }
                    O.call(w.detection, L.collectEventData(N, M, L
                            .getTouchList(F, M), R));
                    if (w.HAS_POINTEREVENTS && M == w.EVENT_END) {
                        Q = w.PointerEvent.updatePointer(M, R)
                    }
                }
                if (!Q) {
                    F = null;
                    l = false;
                    h = false;
                    w.PointerEvent.reset()
                }
            })
        },
        determineEventTypes : function E() {
            var L;
            if (w.HAS_POINTEREVENTS) {
                L = w.PointerEvent.getEvents()
            } else {
                if (w.NO_MOUSEEVENTS) {
                    L = ["touchstart", "touchmove", "touchend touchcancel"]
                } else {
                    L = ["touchstart mousedown", "touchmove mousemove",
                            "touchend touchcancel mouseup"]
                }
            }
            w.EVENT_TYPES[w.EVENT_START] = L[0];
            w.EVENT_TYPES[w.EVENT_MOVE] = L[1];
            w.EVENT_TYPES[w.EVENT_END] = L[2]
        },
        getTouchList : function s(L) {
            if (w.HAS_POINTEREVENTS) {
                return w.PointerEvent.getTouchList()
            } else {
                if (L.touches) {
                    return L.touches
                } else {
                    L.indentifier = 1;
                    return [L]
                }
            }
        },
        collectEventData : function J(N, M, P, O) {
            var L = w.POINTER_TOUCH;
            if (O.type.match(/mouse/)
                    || w.PointerEvent.matchType(w.POINTER_MOUSE, O)) {
                L = w.POINTER_MOUSE
            }
            return {
                center : w.utils.getCenter(P),
                timeStamp : new Date().getTime(),
                target : O.target,
                touches : P,
                eventType : M,
                pointerType : L,
                srcEvent : O,
                preventDefault : function() {
                    if (this.srcEvent.preventManipulation) {
                        this.srcEvent.preventManipulation()
                    }
                    if (this.srcEvent.preventDefault) {
                        this.srcEvent.preventDefault()
                    }
                },
                stopPropagation : function() {
                    this.srcEvent.stopPropagation()
                },
                stopDetect : function() {
                    return w.detection.stopDetect()
                }
            }
        }
    };
    w.PointerEvent = {
        pointers : {},
        getTouchList : function() {
            var L = this;
            var M = [];
            w.utils.each(L.pointers, function(N) {
                M.push(N)
            });
            return M
        },
        updatePointer : function(M, L) {
            if (M == w.EVENT_END) {
                this.pointers = {}
            } else {
                L.identifier = L.pointerId;
                this.pointers[L.pointerId] = L
            }
            return Object.keys(this.pointers).length
        },
        matchType : function(L, N) {
            if (!N.pointerType) {
                return false
            }
            var O = N.pointerType, M = {};
            M[w.POINTER_MOUSE] = (O === N.MSPOINTER_TYPE_MOUSE || O === w.POINTER_MOUSE);
            M[w.POINTER_TOUCH] = (O === N.MSPOINTER_TYPE_TOUCH || O === w.POINTER_TOUCH);
            M[w.POINTER_PEN] = (O === N.MSPOINTER_TYPE_PEN || O === w.POINTER_PEN);
            return M[L]
        },
        getEvents : function() {
            return ["pointerdown MSPointerDown", "pointermove MSPointerMove",
                    "pointerup pointercancel MSPointerUp MSPointerCancel"]
        },
        reset : function() {
            this.pointers = {}
        }
    };
    w.detection = {
        gestures : [],
        current : null,
        previous : null,
        stopped : false,
        startDetect : function y(M, L) {
            if (this.current) {
                return
            }
            this.stopped = false;
            this.current = {
                inst : M,
                startEvent : w.utils.extend({}, L),
                lastEvent : false,
                name : ""
            };
            this.detect(L)
        },
        detect : function q(L) {
            if (!this.current || this.stopped) {
                return
            }
            L = this.extendEventData(L);
            var M = this.current.inst.options;
            w.utils.each(this.gestures, function(N) {
                if (!this.stopped && M[N.name] !== false) {
                    if (N.handler.call(N, L, this.current.inst) === false) {
                        this.stopDetect();
                        return false
                    }
                }
            }, this);
            if (this.current) {
                this.current.lastEvent = L
            }
            if (L.eventType == w.EVENT_END && !L.touches.length - 1) {
                this.stopDetect()
            }
            return L
        },
        stopDetect : function b() {
            this.previous = w.utils.extend({}, this.current);
            this.current = null;
            this.stopped = true
        },
        extendEventData : function u(O) {
            var P = this.current.startEvent;
            if (P
                    && (O.touches.length != P.touches.length || O.touches === P.touches)) {
                P.touches = [];
                w.utils.each(O.touches, function(T) {
                    P.touches.push(w.utils.extend({}, T))
                })
            }
            var M = O.timeStamp - P.timeStamp, S = O.center.pageX
                    - P.center.pageX, R = O.center.pageY - P.center.pageY, N = w.utils
                    .getVelocity(M, S, R), Q, L;
            if (O.eventType === "end") {
                Q = this.current.lastEvent
                        && this.current.lastEvent.interimAngle;
                L = this.current.lastEvent
                        && this.current.lastEvent.interimDirection
            } else {
                Q = this.current.lastEvent
                        && w.utils.getAngle(this.current.lastEvent.center,
                                O.center);
                L = this.current.lastEvent
                        && w.utils.getDirection(this.current.lastEvent.center,
                                O.center)
            }
            w.utils.extend(O, {
                deltaTime : M,
                deltaX : S,
                deltaY : R,
                velocityX : N.x,
                velocityY : N.y,
                distance : w.utils.getDistance(P.center, O.center),
                angle : w.utils.getAngle(P.center, O.center),
                interimAngle : Q,
                direction : w.utils.getDirection(P.center, O.center),
                interimDirection : L,
                scale : w.utils.getScale(P.touches, O.touches),
                rotation : w.utils.getRotation(P.touches, O.touches),
                startEvent : P
            });
            return O
        },
        register : function f(M) {
            var L = M.defaults || {};
            if (L[M.name] === j) {
                L[M.name] = true
            }
            w.utils.extend(w.defaults, L, true);
            M.index = M.index || 1000;
            this.gestures.push(M);
            this.gestures.sort(function(O, N) {
                if (O.index < N.index) {
                    return -1
                }
                if (O.index > N.index) {
                    return 1
                }
                return 0
            });
            return this.gestures
        }
    };
    w.gestures.Drag = {
        name : "drag",
        index : 50,
        defaults : {
            drag_min_distance : 10,
            correct_for_drag_min_distance : true,
            drag_max_touches : 1,
            drag_block_horizontal : false,
            drag_block_vertical : false,
            drag_lock_to_axis : false,
            drag_lock_min_distance : 25
        },
        triggered : false,
        handler : function r(M, N) {
            if (w.detection.current.name != this.name && this.triggered) {
                N.trigger(this.name + "end", M);
                this.triggered = false;
                return
            }
            if (N.options.drag_max_touches > 0
                    && M.touches.length > N.options.drag_max_touches) {
                return
            }
            switch (M.eventType) {
                case w.EVENT_START :
                    this.triggered = false;
                    break;
                case w.EVENT_MOVE :
                    if (M.distance < N.options.drag_min_distance
                            && w.detection.current.name != this.name) {
                        return
                    }
                    if (w.detection.current.name != this.name) {
                        w.detection.current.name = this.name;
                        if (N.options.correct_for_drag_min_distance
                                && M.distance > 0) {
                            var L = Math.abs(N.options.drag_min_distance
                                    / M.distance);
                            w.detection.current.startEvent.center.pageX += M.deltaX
                                    * L;
                            w.detection.current.startEvent.center.pageY += M.deltaY
                                    * L;
                            M = w.detection.extendEventData(M)
                        }
                    }
                    if (w.detection.current.lastEvent.drag_locked_to_axis
                            || (N.options.drag_lock_to_axis && N.options.drag_lock_min_distance <= M.distance)) {
                        M.drag_locked_to_axis = true
                    }
                    var O = w.detection.current.lastEvent.direction;
                    if (M.drag_locked_to_axis && O !== M.direction) {
                        if (w.utils.isVertical(O)) {
                            M.direction = (M.deltaY < 0)
                                    ? w.DIRECTION_UP
                                    : w.DIRECTION_DOWN
                        } else {
                            M.direction = (M.deltaX < 0)
                                    ? w.DIRECTION_LEFT
                                    : w.DIRECTION_RIGHT
                        }
                    }
                    if (!this.triggered) {
                        N.trigger(this.name + "start", M);
                        this.triggered = true
                    }
                    N.trigger(this.name, M);
                    N.trigger(this.name + M.direction, M);
                    if ((N.options.drag_block_vertical && w.utils
                            .isVertical(M.direction))
                            || (N.options.drag_block_horizontal && !w.utils
                                    .isVertical(M.direction))) {
                        M.preventDefault()
                    }
                    break;
                case w.EVENT_END :
                    if (this.triggered) {
                        N.trigger(this.name + "end", M)
                    }
                    this.triggered = false;
                    break
            }
        }
    };
    w.gestures.Hold = {
        name : "hold",
        index : 10,
        defaults : {
            hold_timeout : 500,
            hold_threshold : 1
        },
        timer : null,
        handler : function I(L, M) {
            switch (L.eventType) {
                case w.EVENT_START :
                    clearTimeout(this.timer);
                    w.detection.current.name = this.name;
                    this.timer = setTimeout(function() {
                        if (w.detection.current.name == "hold") {
                            M.trigger("hold", L)
                        }
                    }, M.options.hold_timeout);
                    break;
                case w.EVENT_MOVE :
                    if (L.distance > M.options.hold_threshold) {
                        clearTimeout(this.timer)
                    }
                    break;
                case w.EVENT_END :
                    clearTimeout(this.timer);
                    break
            }
        }
    };
    w.gestures.Release = {
        name : "release",
        index : Infinity,
        handler : function H(L, M) {
            if (L.eventType == w.EVENT_END) {
                M.trigger(this.name, L)
            }
        }
    };
    w.gestures.Swipe = {
        name : "swipe",
        index : 40,
        defaults : {
            swipe_min_touches : 1,
            swipe_max_touches : 1,
            swipe_velocity : 0.7
        },
        handler : function K(L, M) {
            if (L.eventType == w.EVENT_END) {
                if (M.options.swipe_max_touches > 0
                        && L.touches.length < M.options.swipe_min_touches
                        && L.touches.length > M.options.swipe_max_touches) {
                    return
                }
                if (L.velocityX > M.options.swipe_velocity
                        || L.velocityY > M.options.swipe_velocity) {
                    M.trigger(this.name, L);
                    M.trigger(this.name + L.direction, L)
                }
            }
        }
    };
    w.gestures.Tap = {
        name : "tap",
        index : 100,
        defaults : {
            tap_max_touchtime : 250,
            tap_max_distance : 10,
            tap_always : true,
            doubletap_distance : 20,
            doubletap_interval : 300
        },
        handler : function D(N, O) {
            if (N.eventType == w.EVENT_END && N.srcEvent.type != "touchcancel") {
                var M = w.detection.previous, L = false;
                if (N.deltaTime > O.options.tap_max_touchtime
                        || N.distance > O.options.tap_max_distance) {
                    return
                }
                if (M
                        && M.name == "tap"
                        && (N.timeStamp - M.lastEvent.timeStamp) < O.options.doubletap_interval
                        && N.distance < O.options.doubletap_distance) {
                    O.trigger("doubletap", N);
                    L = true
                }
                if (!L || O.options.tap_always) {
                    w.detection.current.name = "tap";
                    O.trigger(w.detection.current.name, N)
                }
            }
        }
    };
    w.gestures.Touch = {
        name : "touch",
        index : -Infinity,
        defaults : {
            prevent_default : false,
            prevent_mouseevents : false
        },
        handler : function g(L, M) {
            if (M.options.prevent_mouseevents
                    && L.pointerType == w.POINTER_MOUSE) {
                L.stopDetect();
                return
            }
            if (M.options.prevent_default) {
                L.preventDefault()
            }
            if (L.eventType == w.EVENT_START) {
                M.trigger(this.name, L)
            }
        }
    };
    w.gestures.Transform = {
        name : "transform",
        index : 45,
        defaults : {
            transform_min_scale : 0.01,
            transform_min_rotation : 1,
            transform_always_block : false
        },
        triggered : false,
        handler : function p(N, O) {
            if (w.detection.current.name != this.name && this.triggered) {
                O.trigger(this.name + "end", N);
                this.triggered = false;
                return
            }
            if (N.touches.length < 2) {
                return
            }
            if (O.options.transform_always_block) {
                N.preventDefault()
            }
            switch (N.eventType) {
                case w.EVENT_START :
                    this.triggered = false;
                    break;
                case w.EVENT_MOVE :
                    var M = Math.abs(1 - N.scale);
                    var L = Math.abs(N.rotation);
                    if (M < O.options.transform_min_scale
                            && L < O.options.transform_min_rotation) {
                        return
                    }
                    w.detection.current.name = this.name;
                    if (!this.triggered) {
                        O.trigger(this.name + "start", N);
                        this.triggered = true
                    }
                    O.trigger(this.name, N);
                    if (L > O.options.transform_min_rotation) {
                        O.trigger("rotate", N)
                    }
                    if (M > O.options.transform_min_scale) {
                        O.trigger("pinch", N);
                        O.trigger("pinch" + ((N.scale < 1) ? "in" : "out"), N)
                    }
                    break;
                case w.EVENT_END :
                    if (this.triggered) {
                        O.trigger(this.name + "end", N)
                    }
                    this.triggered = false;
                    break
            }
        }
    };
    if (typeof define == "function" && typeof define.amd == "object"
            && define.amd) {
        define(function() {
            return w
        })
    } else {
        if (typeof module === "object" && typeof module.exports === "object") {
            module.exports = w
        } else {
            B.Hammer = w
        }
    }
})(this);
iAuto.define("iAuto.ui.core.AMD", {
    singleton : true,
    _loadScript : function(c, d, a) {
        var b = document.createElement("script");
        b.type = "text/javascript";
        b.src = c;
        if (d) {
            b.onload = d
        }
        if (a) {
            b.onerror = a
        } else {
            b.onerror = function(f) {
                iAuto.Logger.error(f)
            }
        }
        document.body.appendChild(b)
    },
    linkCss : function(a) {
        var d = document.head.getElementsByTagName("link");
        for (var b = 0; b < d.length; ++b) {
            if (d[b].href.indexOf(a) >= 0) {
                return
            }
        }
        var c = document.createElement("link");
        c.rel = "stylesheet";
        c.type = "text/css";
        c.href = a;
        document.head.appendChild(c)
    },
    require : function(b, d, a) {
        try {
            this._loadScript(b, d, a)
        } catch (c) {
            iAuto.Logger.error(c)
        }
    }
});
iAuto.define("iAuto.ui.core.ClassManager", {
    singleton : true,
    _classes : {
        controller : {},
        xcontrol : {},
        fcontrol : {},
        model : {},
        glayer : {}
    },
    _package : {
        controller : "iAuto.ui.controller",
        xcontrol : "iAuto.ui.xcontrol",
        fcontrol : "iAuto.ui.fcontrol",
        model : "iAuto.ui.model",
        glayer : "iAuto.ui.glayer"
    },
    _directory : {},
    _baseCls : {
        controller : "iAuto.ui.base.Controller",
        xcontrol : "iAuto.ui.base.XControl",
        fcontrol : "iAuto.ui.base.FControl",
        model : "iAuto.ui.base.Model",
        glayer : "iAuto.ui.base.Glayer"
    },
    status : {},
    _state : {
        UNLOAD : 0,
        LOADING : 1,
        LOADERR : 2,
        LOADED : 3
    },
    _loadingQueue : {},
    get : function(b, a) {
        return this._classes[b][a]
    },
    isDefined : function(b) {
        var a = iAuto.ClassManager.get(b);
        return (a && b === a.$classname) ? true : false
    },
    getClassname : function(b, a) {
        return this._package[b] + "." + a
    },
    define : function(g, a, c, j, h) {
        var f = this, d = f._baseCls[g], k = c.requires, e = c.mixins, i = [], b = function(
                p, n, q) {
            var o = f.getClassname(p, n), m, l = f._loadingQueue[o];
            q.name = n;
            m = iAuto.define(o, q);
            if (Array.isArray(l)) {
                l.forEach(function(r) {
                    r.call(m, m)
                })
            }
            if (f._loadingQueue[m]) {
                delete f._loadingQueue[m]
            }
            if (j && j.call) {
                j.call(m, m)
            }
        };
        if (c.extend && c.extend !== d) {
            i.push({
                type : g,
                name : c.extend
            });
            c.extend = f._package[g] + "." + c.extend
        } else {
            c.extend = d
        }
        if (Array.isArray(e) && e.length > 0) {
            i = i.concat(e)
        }
        if (Array.isArray(k) && k.length > 0) {
            i = i.concat(k)
        }
        if (i.length > 0) {
            f.resolveDependences(i, function() {
                b(g, a, c)
            }, function() {
                iAuto.Logger.error("Define " + g + " [" + a + "] error!");
                if (h && h.call) {
                    h.call()
                }
                return false
            })
        } else {
            b(g, a, c)
        }
    },
    resolveDependences : function(e, b, a) {
        var d = this, f = e.length, c = 0, g = function(h) {
            if (++c >= f) {
                if (b && b.call) {
                    b.call(h, h)
                }
            }
        };
        e.forEach(function(h) {
            var k = h.type, j = h.name, i = d._package[k] + "." + j;
            if (d.isDefined(i)) {
                g()
            } else {
                d.loadClass(k, j, g, function() {
                    iAuto.Logger.error("[" + j + "] Load class error!");
                    if (a && a.call) {
                        a.call()
                    }
                })
            }
        })
    },
    loadClass : function(i, b, e, j) {
        var h = this, g = this.getClassname(i, b), c = h._classes[i], f = this.status[g]
                || this._state.UNLOAD, d = this._loadingQueue;
        if (f === this._state.UNLOAD) {
            d[g] = d[g] || [];
            d[g].push(function(m) {
                h.status[g] = h._state.LOADED;
                c[g] = m;
                if ($.isFunction(e)) {
                    e.call(m, m)
                }
            })
        } else {
            if (f === this._state.LOADERR) {
                if ($.isFunction(j)) {
                    j.call()
                }
                return this
            } else {
                if ($.isFunction(e)) {
                    if (f === this._state.LOADED) {
                        var l = iAuto.ClassManager.get(g);
                        if (l) {
                            e.call(null, l)
                        }
                    } else {
                        if (f === this._state.LOADING) {
                            d[g] = d[g] || [];
                            d[g].push(e)
                        }
                    }
                }
                return this
            }
        }
        var a = this.getUrl(i, b), k = iAuto.ui.core.AMD;
        h.status[g] = this._state.LOADING;
        k.require(a, null, function() {
            h.status[g] = h._state.LOADERR;
            if (h._loadingQueue[g]) {
                delete h._loadingQueue[g]
            }
        });
        return this
    },
    getUrl : function(b, c) {
        var a = this._directory;
        switch (b) {
            case "controller" :
                a.controller = a.controller
                        || iAuto.ui.framework.App.getControllersDir();
                return a.controller + c + ".js";
            case "xcontrol" :
                a.xcontrol = a.xcontrol
                        || iAuto.ui.framework.App.getXcontrolsDir();
                return a.xcontrol + c + "/" + c + ".js";
            case "fcontrol" :
                a.fcontrol = a.fcontrol
                        || iAuto.ui.framework.App.getFcontrolsDir();
                return a.fcontrol + c + "/" + c + ".js";
            case "model" :
                a.model = a.model || iAuto.ui.framework.App.getModelsDir();
                return a.model + c + "/" + c + ".js";
            case "glayer" :
                a.glayer = a.glayer || iAuto.ui.framework.App.getGlayersDir();
                return a.glayer + c + ".js"
        }
    }
});
iAuto.define("iAuto.ui.framework.App", {
    singleton : true,
    config : {
        controllersDir : "controllers/",
        modelsDir : "models/",
        viewsDir : "views/",
        xcontrolsDir : "resources/cc/",
        fcontrolsDir : "resources/fc/",
        glayersDir : "resources/gl/",
        cssDir : "resources/css/",
        currController : null,
        preActiveWin : null
    },
    _loadTimer : null,
    _loading : false,
    _modelsReady : true,
    _fcontrolsReady : true,
    _stmReady : true,
    _glayerReady : true,
    ready : function(a) {
        if (this._loading) {
            $(document).one("itumvc:loaded", a)
        } else {
            a()
        }
    },
    route : function(b, f, e) {
        var d = this, a = iAuto.ui.framework.Controller, c;
        if (!b || b.length < 1) {
            throw new Error("This is an empty winscape")
        }
        if ((c = d.getCurrController())) {
            a.leave(c);
            d.setPreActiveWin(c)
        }
        d.setCurrController(b);
        a.entry(b, f, null, e);
        return true
    },
    getCurrentController : function() {
        var a = iAuto.ui.framework.Controller;
        return a.get(this.getCurrController())
    },
    _startLoading : function() {
        if (!this._loading) {
            var b = this;
            b._loading = true;
            var c = $(document);
            var a = function() {
                if (b._modelsReady && b._fcontrolsReady && b._stmReady
                        && b._glayerReady) {
                    b._loading = false;
                    c.trigger("itumvc:loaded")
                }
            };
            c.one("model:loaded", a);
            c.one("fcontrol:loaded", a);
            c.one("stm:ready", a);
            c.one("glayer:ready", a);
            b._loadTimer = setTimeout(function() {
                c.trigger("itumvc:loaded");
                clearTimeout(b._loadTimer);
                c.off("model:loaded", a);
                c.off("fcontrol:loaded", a);
                c.off("stm:ready", a);
                c.off("glayer:ready", a)
            }, 1000)
        }
    },
    loadGlayers : function(a) {
        if ((!a) || (a.length === 0)) {
            return this
        }
        if (!this._loading) {
            this._startLoading()
        }
        this._glayerReady = false;
        if (typeof(a) === "string") {
            a = [a]
        }
        var f = this, e = a.length, c = 0, d = function() {
            if (++c >= e) {
                f._glayerReady = true;
                $(document).trigger("glayer:ready")
            }
        };
        for (var b = 0; b < e; b++) {
            iAuto.ui.framework.Glayer.load(a[b], d)
        }
        return this
    },
    loadModels : function(b) {
        if ((!b) || (b.length === 0)) {
            return this
        }
        var a = this;
        if (!this._loading) {
            this._startLoading()
        }
        this._modelsReady = false;
        $(document).ready(function() {
            if (typeof(b) === "string") {
                b = [b]
            }
            var c = b.length, e = 0;
            var g = function() {
                if (++e >= c) {
                    a._modelsReady = true;
                    $(document).trigger("model:loaded")
                }
            };
            for (var d = 0; d < c; d++) {
                var f = a.getModelsDir() + b[d] + ".js";
                iAuto.ui.core.AMD.require(f, g)
            }
        });
        return this
    },
    loadFcontrols : function(b) {
        if ((!b) || (b.length === 0)) {
            return this
        }
        var a = this;
        if (!this._loading) {
            this._startLoading()
        }
        a._fcontrolsReady = false;
        $(document).ready(function() {
            if (typeof(b) === "string") {
                b = [b]
            }
            var e = iAuto.ui.framework.FControl, g = b.length, c = 0, f = function() {
                if (++c >= g) {
                    a._fcontrolsReady = true;
                    $(document).trigger("fcontrol:loaded")
                }
            };
            for (var d = 0; d < g; d++) {
                if (e) {
                    e.load(b[d], f)
                }
            }
        });
        return this
    },
    registerSTM : function() {
        var e = this;
        this._stmReady = false;
        if (!this._loading) {
            this._startLoading()
        }
        var g = ["stm/lib/state-view.js", "stm/lib/state-router.js"];
        var d = g.length, a = 0;
        var f = function() {
            if (++a >= d) {
                e._stmReady = true;
                $(document).trigger("stm:ready")
            }
        };
        var c = function() {
            if (++a >= d) {
                e._stmReady = true;
                $(document).trigger("stm:ready")
            }
        };
        for (var b = 0; b < d; b++) {
            iAuto.ui.core.AMD.require(g[b], f, c)
        }
        window.addEventListener("keydown", function(h) {
            if (h.keyCode === 37 || h.keyCode === 8) {
                try {
                    StateRouter.trigger("Back")
                } catch (i) {
                    iAuto.Logger.error(i)
                }
                h.preventDefault()
            }
        }, false);
        this.routeSTM = function(l, n, k) {
            var i = this.getCurrController();
            if (!l || (!n && i)) {
                iAuto.Logger
                        .error("[iAuto.ui.framework.App] stmRoute parameters error.");
                return
            }
            if (!n) {
                this.route(l, null, k);
                return
            }
            var h = iAuto.ui.framework.Controller;
            function j() {
                var o = h.get(l);
                var p = "on" + n.charAt(0).toUpperCase() + n.substr(1);
                if (typeof(o[p]) === "function") {
                    o[p].apply(o)
                }
            }
            if (l !== i) {
                try {
                    this.route(l, j, k)
                } catch (m) {
                    iAuto.Logger.log(m)
                }
            } else {
                return j()
            }
        };
        return this
    },
    isStmDefined : function() {
        return (typeof(StateRouter) !== "undefined")
    },
    getActiveWinscape : function() {
        return this.isStmDefined() ? StateRouter.getCurrWinscapeName() : this
                .getCurrController()
    },
    getPreActiveWinscape : function() {
        return this.isStmDefined() ? StateRouter.getPreWinscapeName() : this
                .getPreActiveWin()
    },
    getAnimationList : function() {
        var a = {
            anim_fade : {
                duration : 800
            },
            anim_slide : {
                duration : 1000
            },
            anim_side : {
                duration : 500
            },
            anim_fall : {
                duration : 1000
            },
            anim_flip : {
                duration : 500,
                direction : "Top"
            },
            anim_carousel : {
                duration : 800,
                direction : "Left"
            },
            anim_move : {
                duration : 1000,
                direction : "Left"
            },
            anim_cube : {
                duration : 400,
                direction : "Left"
            }
        };
        return a
    }
});
iAuto.define("iAuto.ui.framework.ResourceManager", {
    singleton : true,
    _imageUrlPrefix : "resources/img/",
    _imageList : {},
    _stringList : {},
    _messageList : {},
    getMessage : function(c) {
        try {
            var a = this;
            return a._messageList[c]
        } catch (b) {
            iAuto.Logger.error(b)
        }
    },
    getString : function(b) {
        try {
            var a = this;
            return a._stringList[b]
        } catch (c) {
            iAuto.Logger.error(c)
        }
    },
    getImageUrl : function(b) {
        try {
            var c = this;
            var a = c._imageList[b];
            a = "url('" + c._imageUrlPrefix + a + "')";
            return a
        } catch (d) {
            iAuto.Logger.error(d)
        }
    },
    loadMessageList : function(c, d) {
        try {
            var a = this;
            $.getJSON(c, function(e) {
                a._messageList = e;
                if (typeof d === "function") {
                    d()
                }
            })
        } catch (b) {
            iAuto.Logger.error(b)
        }
    },
    loadStringList : function(c, d) {
        try {
            var a = this;
            $.getJSON(c, function(e) {
                a._stringList = e;
                if (typeof d === "function") {
                    d()
                }
            })
        } catch (b) {
            iAuto.Logger.error(b)
        }
    },
    loadJson : function(b, c) {
        try {
            $.getJSON(b, function(d) {
                if (typeof c === "function") {
                    c(d)
                }
            })
        } catch (a) {
            iAuto.Logger.error(a)
        }
    },
    loadImageList : function(c, d) {
        try {
            var a = this;
            $.getJSON(c, function(e) {
                a._imageList = e;
                if (typeof d === "function") {
                    d()
                }
            })
        } catch (b) {
            iAuto.Logger.error(b)
        }
    },
    setImageUrlPrefix : function(b) {
        try {
            var a = this;
            a._imageUrlPrefix = b
        } catch (c) {
            iAuto.Logger.error(c)
        }
    }
});
iAuto.define("iAuto.ui.framework.ScreenInfoManager", {
    singleton : true,
    __screenInfos : {},
    loadAllScreenInfo : function(c) {
        try {
            var a = this;
            $.getJSON(c, function(d) {
                a.__screenInfos = d
            })
        } catch (b) {
            iAuto.Logger.error(b)
        }
    },
    getScreenInfo : function(c) {
        try {
            var a = this;
            if (a.__screenInfos) {
                return a.__screenInfos[c]
            }
        } catch (b) {
            iAuto.Logger.error(b)
        }
    }
});
iAuto.define("iAuto.ui.framework.Controller", {
    singleton : true,
    _instances : {},
    animationObj : {},
    $viewport : $("#viewport"),
    entry : function(e, b, c, a) {
        var d = this.get(e);
        if ($.isObject(a)) {
            this.animationObj = a
        }
        if (d) {
            this._lifeEnter(d, b, c)
        } else {
            this._lifeLoad(e, b, c)
        }
        return this
    },
    leave : function(d, b, c) {
        var a = this.get(d);
        if (!a) {
            iAuto.Logger.warn("[" + d + "] haven't been defined!");
            if ($.isFunction(c)) {
                c()
            }
            return this
        }
        this._unbindEvent(a);
        try {
            a.onHide.call(a)
        } catch (f) {
            if ($.isFunction(c)) {
                c()
            }
            iAuto.Logger.error("[" + d
                    + "] Execute wrong in onHide() function.\n" + f)
        }
        this._removeCmp(a);
        try {
            a.onLeave.call(a)
        } catch (f) {
            iAuto.Logger.error("[" + d
                    + "] Execute wrong in onLeave() function.\n" + f)
        }
        a.items = [];
        a.events = [];
        a.$content = {};
        if (b && b.call) {
            b.call()
        }
        return this
    },
    load : function(c, l, i) {
        var j = iAuto.ui.framework.App, g = iAuto.ui.core.ClassManager, a = this._instances, k, f = 0, d = false, e = iAuto.ui.framework.View, h, b;
        g.loadClass("controller", c, function(r) {
            k = new r();
            k.name = c;
            a[c] = k;
            try {
                k.onLoad.call(k)
            } catch (s) {
                iAuto.Logger.error(s)
            }
            var t = function(x, w, v, y) {
                if ((h = w.getView())) {
                    b = j.getViewsDir() + h;
                    e.load(b, function(z) {
                        w.html = z;
                        x._lifeEnter.call(x, w, v, y)
                    }, function(z) {
                        iAuto.Logger
                                .error("[iAuto.ui.framework.Controller] Load View ["
                                        + h
                                        + "] Error in Controller ["
                                        + c
                                        + "]!");
                        iAuto.Logger.error(z)
                    })
                }
            };
            try {
                if (k.getPreImg()) {
                    var q = k.getPreImg();
                    var u = [];
                    var m = null;
                    f = q.length;
                    if (q.length === 0) {
                        t(me, k, l, i);
                        return
                    }
                    m = setTimeout(function() {
                        d = true;
                        t(me, k, l, i)
                    }, 20);
                    for (var p = 0, n = q.length, o; p < n; p++) {
                        o = new Image();
                        u[u.length] = o
                    }
                    for (p = 0, n = u.length; p < n; p++) {
                        u[p].src = "" + q[p];
                        u[p].onload = function() {
                            f--;
                            if (me.count === 0) {
                                if (d) {
                                    return
                                } else {
                                    clearTimeout(m);
                                    t(me, k, l, i)
                                }
                            }
                        };
                        u[p].onerror = function() {
                            f--;
                            if (f === 0) {
                                if (d) {
                                    return
                                } else {
                                    clearTimeout(m);
                                    t(me, k, l, i)
                                }
                            }
                        }
                    }
                }
            } catch (s) {
                iAuto.Logger.error("preImg not defined");
                t(me, k, l, i)
            }
        }, function() {
            iAuto.Logger
                    .error("[iAuto.ui.framework.Controller] Load Controller ["
                            + c + "] Error!");
            if ($.isFunction(i)) {
                i.call()
            }
        });
        return this
    },
    define : function(a, c) {
        var b = iAuto.ui.core.ClassManager;
        b.define("controller", a, c);
        return this
    },
    _lifeLoad : function(c, n, j) {
        var h = this, f = iAuto.ui.core.ClassManager, a = this._instances, m, d = iAuto.ui.framework.View, k = iAuto.ui.framework.App, i, b, l = iAuto.ui.core.AMD, g = iAuto.ui.framework.App
                .getCssDir(), e;
        f.loadClass("controller", c, function(o) {
            m = new o();
            m.name = c;
            a[c] = m;
            try {
                m.onLoad.call(m)
            } catch (p) {
                iAuto.Logger.error(p)
            }
            if ((i = m.getView())) {
                b = k.getViewsDir() + i;
                d.load(b, function(q) {
                    m.html = q;
                    h._lifeEnter.call(h, m, n, j)
                }, function(q) {
                    iAuto.Logger
                            .error("[iAuto.ui.framework.Controller] Load View ["
                                    + i + "] Error in Controller [" + c + "]!");
                    iAuto.Logger.error(q)
                })
            }
        }, function() {
            iAuto.Logger
                    .error("[iAuto.ui.framework.Controller] Load Controller ["
                            + c + "] Error!")
        });
        e = g + c + ".css";
        l.linkCss(e);
        return this
    },
    _lifeEnter : function(b, a, c) {
        var f = this, d = b.html;
        $content = b.$content = $.create(d());
        patch = iAuto.ui.framework.Patch;
        try {
            b.onEnter.apply(b)
        } catch (g) {
            iAuto.Logger.error("[" + b.name
                    + "] Execute wrong in onEnter() function.");
            iAuto.Logger.error(g)
        }
        if ($content) {
            this.$viewport.append($content)
        }
        patch.loadItems(b).loadEvents(b);
        this._createCmp(b, function(e) {
            f._lifeShow(e, a, c)
        })
    },
    _lifeShow : function(b, a, c) {
        var i = this.$viewport, f = i.children();
        try {
            b.onShowPre.call(b)
        } catch (g) {
            if (c && c.call) {
                c.call()
            }
            iAuto.Logger.error("[" + name
                    + "] Execute wrong in onShowPre() function.");
            iAuto.Logger.error(g);
            return this
        }
        i.addClass("pt-perspective");
        var h = this.animationObj.animationType;
        var d = this.animationObj.parameter;
        if (h) {
            this.setAnimation(h, d, f, i)
        } else {
            if (f.length >= 2) {
                f.get(0).remove()
            }
        }
        this._bindEvent(b);
        try {
            b.onShow.call(b)
        } catch (g) {
            if (c && c.call) {
                c.call()
            }
            iAuto.Logger.error("[" + name
                    + "] Execute wrong in onShow() function.");
            iAuto.Logger.error(g);
            return this
        }
        if ($.isFunction(a)) {
            a()
        }
    },
    _createCmp : function(j, m) {
        var g = this, i = iAuto.ui.framework, f = i.XControl, b = i.FControl, d = i.BControl, e = (j.items = j.items
                || []), k = (j._cmp = j._cmp || {}), l = e.length, a = 0, h, c;
        l = e.length || 0;
        if (l <= 0) {
            if ($.isFunction(m)) {
                m.call(g, j)
            }
            return this
        }
        h = function(n) {
            if (n) {
                k[n.id || n.name] = n
            }
            if (++a >= l) {
                if ($.isFunction(m)) {
                    m.call(g, j)
                }
            }
        };
        e.forEach(function(n) {
            switch (n.type) {
                case "xcontrol" :
                    c = j.$content.find("#" + n.id);
                    if (c.length >= 1) {
                        f._create(n, c, h, h)
                    }
                    break;
                case "bcontrol" :
                    c = j.$content.find("#" + n.id);
                    if (c.length >= 1) {
                        d._create(n, c, h, h)
                    }
                    break;
                case "fcontrol" :
                    b.start(n.name, h, h);
                    break;
                default :
                    h()
            }
        })
    },
    _removeCmp : function(a) {
        var e = iAuto.ui.framework.XControl, b = a._cmp, c, d;
        for (c in b) {
            if (b.hasOwnProperty(c)) {
                d = b[c];
                if (d && d.xtype === "xcontrol") {
                    e._destroy(d)
                }
            }
        }
        a._cmp = {}
    },
    _bindEvent : function(a) {
        var b = (a.events = a.events || []), d = iAuto.ui.framework.Event, c, e;
        b.forEach(function(f) {
            e = f.handler;
            if (!e) {
                e = f.handler = d._getHandler(f.callback, f.context, f.trigger)
            }
            c = a.getCmp(f.item);
            if (c && c.on) {
                c.on(f.name, e)
            } else {
                a.$content.find("#" + f.item).on(f.name, e)
            }
        });
        return this
    },
    _unbindEvent : function(a) {
        var b = (a.events = a.events || []), c, d;
        b.forEach(function(e) {
            d = null;
            c = a.getCmp(e.item);
            if (c && c.off) {
                c.off(e.name, d)
            } else {
                a.$content.find("#" + e.item).off(e.name, d)
            }
        });
        return this
    },
    get : function(a) {
        return this._instances[a]
    },
    setAnimation : function(j, b, m, e) {
        var k, f, a, n, g = "0s", d = "", h = "";
        var c = iAuto.ui.framework.App;
        var l = c.getAnimationList();
        if (l.hasOwnProperty(j) && l[j]) {
            h = l[j]["duration"] + "ms";
            if (l[j]["direction"]) {
                d = l[j]["direction"];
                d = d.substr(0, 1).toUpperCase() + d.substr(1)
            }
        }
        if (b) {
            if (b.duration) {
                h = b.duration + "ms"
            }
            if (b.direction) {
                d = b.direction;
                d = d.substr(0, 1).toUpperCase() + d.substr(1)
            }
        }
        switch (j) {
            case "anim_fade" :
                inCSS = "fadein " + h;
                outCSS = "fadeout " + h;
                var i = function() {
                    $(m.get(0)).css({
                        "-webkit-animation" : ""
                    });
                    $(m.get(1)).one("webkitAnimationEnd", function() {
                        $(m.get(1)).css({
                            "-webkit-animation" : ""
                        })
                    });
                    $(m.get(1)).css({
                        "-webkit-animation" : inCSS
                    });
                    m.get(0).remove();
                    e.get(0).removeChild(e.get(0).children[1])
                };
                if (m.length == 1) {
                    $(m.get(0)).one("webkitAnimationEnd", function() {
                        $(m.get(0)).css({
                            "-webkit-animation" : ""
                        })
                    });
                    $(m.get(0)).css({
                        "-webkit-animation" : inCSS
                    })
                } else {
                    $(m.get(0)).one("webkitAnimationStart", function() {
                        e
                                .append("<div id='mask' style='height:100%;width:100%;position:absolute;top:0;'></div>")
                    });
                    $(m.get(0)).one("webkitAnimationEnd", i);
                    $(m.get(0)).css({
                        "-webkit-animation" : outCSS
                    })
                }
                break;
            case "anim_side" :
                k = "pt-page pt-page-rotateSidesIn";
                f = "pt-page pt-page-rotateSidesOut";
                a = "rotateSidesIn both ease-out " + h;
                n = "rotateSidesOut both ease-out " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            case "anim_carousel" :
                k = "pt-page pt-page-rotateCarousel" + d + "In";
                f = "pt-page pt-page-rotateCarousel" + d + "Out";
                a = "rotateCarousel" + d + "In both ease " + h;
                n = "rotateCarousel" + d + "Out both ease " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            case "anim_flip" :
                g = h;
                k = "pt-page pt-page-flipIn" + d;
                f = "pt-page pt-page-flipOut" + d;
                a = "flipIn" + d + " both ease-out " + h;
                n = "flipOut" + d + " both ease-out " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            case "anim_fall" :
                k = "pt-page";
                f = "pt-page pt-page-rotateFall pt-page-ontop";
                a = "scaleUp ease both " + h;
                n = "rotateFall both ease-in " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            case "anim_slide" :
                k = "pt-page";
                f = "pt-page";
                a = "rotateSlideIn both ease " + h;
                n = "rotateSlideOut both ease " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            case "anim_move" :
                k = "pt-page";
                f = "pt-page pt-page-ontop";
                a = "scaleUp ease both " + h;
                n = "moveTo" + d + " ease both " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            case "anim_cube" :
                k = "pt-page pt-page-rotateCubeLeftIn";
                f = "pt-page pt-page-rotateCubeLeftOut pt-page-ontop";
                a = "rotateCube" + d + "In both ease-in " + h;
                n = "rotateCube" + d + "Out both ease-in " + h;
                this.SetOtherAnimation(k, f, m, a, n, g, e);
                break;
            default :
                if (m.length >= 2) {
                    m.get(0).remove()
                }
                break
        }
        this.animationObj = {}
    },
    SetOtherAnimation : function(d, b, e, g, c, a, f) {
        if (e.length == 1) {
            $(e.get(0)).one("webkitAnimationEnd", function() {
                $(e.get(0)).removeClass(d);
                if (g) {
                    $(e.get(0)).css({
                        "-webkit-animation" : ""
                    })
                }
            });
            $(e.get(0)).addClass(d);
            if (g) {
                $(e.get(0)).css({
                    "-webkit-animation" : g
                })
            }
        } else {
            $(e.get(0)).one("webkitAnimationStart", function() {
                f
                        .append("<div id='mask' style='height:100%;width:100%;position:absolute;top:0;'></div>")
            });
            $(e.get(0)).addClass(b);
            if (c) {
                $(e.get(0)).css({
                    "-webkit-animation" : c
                })
            }
            $(e.get(1)).addClass(d);
            if (g && a) {
                $(e.get(1)).css({
                    "-webkit-animation" : g
                });
                $(e.get(1)).css({
                    "-webkit-animation-delay" : a
                })
            }
            $(e.get(1)).one("webkitAnimationEnd", function() {
                $(e.get(0)).removeClass(b);
                $(e.get(1)).removeClass(d);
                if (g && c && a) {
                    $(e.get(0)).css({
                        "-webkit-animation" : ""
                    });
                    $(e.get(1)).css({
                        "-webkit-animation" : ""
                    });
                    $(e.get(1)).css({
                        "-webkit-animation-delay" : ""
                    })
                }
                e.get(0).remove();
                f.get(0).removeChild(f.get(0).children[1])
            })
        }
    }
});
iAuto.define("iAuto.ui.framework.Event", {
    singleton : "true",
    _hammerLoaded : false,
    events : {
        basic : ["touchstart", "touchmove", "touchend", "touchcancel"],
        hammer : ["tap", "hold", "drag", "dragstart", "dragend", "dragup",
                "dragdown", "dragleft", "dragright", "swipe", "swipeup",
                "swipedown", "swipeleft", "swiperight", "transform",
                "transformstart", "transformend", "rotate", "pinch", "pinchin",
                "pinchout", "touch", "release"]
    },
    $content : null,
    _eventCenter : {},
    _listeners : {},
    fireEvent : function(b) {
        try {
            var f = this;
            var c = [];
            for (var d = 1, a = arguments.length; d < a; d++) {
                c.push(arguments[d])
            }
            $.trigger(f._eventCenter, b, c)
        } catch (g) {
            iAuto.Logger.error(g)
        }
    },
    addEventListener : function(a, c) {
        try {
            var b = this;
            $.bind(b._eventCenter, a, c)
        } catch (d) {
            iAuto.Logger.error(d)
        }
    },
    removeEventListener : function(a, c) {
        iAuto.Logger.debug(
                "[iAuto.ui.framework.Event]-[removeEventListener]: ", [a, c]);
        try {
            var b = this;
            $.unbind(b._eventCenter, a, c)
        } catch (d) {
            iAuto.Logger.error(d)
        }
    },
    on : function(a, f, g, d, b) {
        if (arguments.length < 3 || typeof(g) !== "function") {
            return this
        }
        if (a.length < 1) {
            return this
        } else {
            if (a.length > 1) {
                for (var c = 0; c < a.length; c++) {
                    this.on($(a[c]), f, g, d, b)
                }
                return this
            }
        }
        var e = this;
        if (d) {
            g = $.proxy(g, d)
        }
        if (b) {
            g = e._setTrigger(g, b)
        }
        if (e.events.hammer.indexOf(f) >= 0) {
            if (!e._hammerLoaded) {
                e._setupHammer(window.Hammer, window.$);
                e._hammerLoaded = true
            }
            a.data("hammer", new Hammer(a, {}))
        }
        if ($.is$(a)) {
            a.bind(f, g)
        } else {
            if ($.isObject(a)) {
                if (a.on) {
                    a.on(f, g)
                } else {
                    $.bind(a, f, g)
                }
            }
        }
    },
    off : function(a, e, f, c, b) {
        if (arguments.length < 2) {
            return
        }
        if (typeof a === "string") {
            a = $(a)
        } else {
            if (Object.prototype.toString.call(a) === "[object Array]") {
                var d = this;
                a.forEach(function(g) {
                    d.off(g, e, f, c, b)
                });
                return this
            }
        }
        if ($.is$(a)) {
            a.unbind(e)
        } else {
            if ($.isObject(a)) {
                $.unbind(a, e)
            }
        }
        return this
    },
    addListener : function(a, b) {
        b = b || {};
        if (typeof(a) === "string") {
            if (this.$content) {
                a = this.$content.find("#" + a)
            } else {
                a = $("#" + a)
            }
            if (!a.length) {
                return this
            }
        }
        this.on(a, b.name, b.callback, b.context, b.trigger);
        return this
    },
    removeListeners : function(a, b) {
        if (typeof a === "string") {
            a = this.$content.find(a)
        }
        if ($.is$(a)) {
            a.unbind(b)
        }
    },
    bindHardKey : function() {
        window.addEventListener("keydown", function(c) {
            var b = iAuto.mvc.getCurrentController();
            if (b) {
                var a = "onHardKeyDown";
                if (b[a]) {
                    b[a].apply(b, arguments)
                }
            }
            if (c.keyCode === 37 || c.keyCode === 8) {
                if (StateRouter && typeof StateRouter.trigger === "function") {
                    try {
                        StateRouter.trigger("Back")
                    } catch (d) {
                        iAuto.Logger.warn(d)
                    }
                }
            }
        }, false)
    },
    _getHandler : function(b, d, a) {
        if (!$.isFunction(b)) {
            return function() {
            }
        }
        return function() {
            if (d) {
                b.apply(d, arguments)
            } else {
                b.apply(null, arguments)
            }
            if (a && StateRouter && StateRouter.trigger) {
                try {
                    StateRouter.trigger(a)
                } catch (c) {
                    iAuto.Logger.error(c)
                }
            }
        }
    },
    _setTrigger : function trigger(b, a) {
        return function() {
            b.apply(this, arguments);
            if (a && StateRouter && StateRouter.trigger) {
                try {
                    StateRouter.trigger(a)
                } catch (c) {
                    iAuto.Logger.error(c)
                }
            }
        }
    },
    _setupHammer : function(a, b) {
        a.event.bindDom = function(c, e, d) {
            b(c).on(e, function(f) {
                var g = f.originalEvent || f;
                if (g.pageX === undefined) {
                    g.pageX = f.pageX;
                    g.pageY = f.pageY
                }
                if (!g.target) {
                    g.target = f.target
                }
                if (g.which === undefined) {
                    g.which = g.button
                }
                if (!g.preventDefault) {
                    g.preventDefault = f.preventDefault
                }
                if (!g.stopPropagation) {
                    g.stopPropagation = f.stopPropagation
                }
                d.call(this, g)
            })
        };
        a.Instance.prototype.on = function(c, d) {
            return b(this.element).on(c, d)
        };
        a.Instance.prototype.off = function(c, d) {
            return b(this.element).off(c, d)
        };
        a.Instance.prototype.trigger = function(c, e) {
            var d = b(this.element);
            return d.trigger(c, {
                type : c,
                gesture : e
            })
        }
    }
});
iAuto.define("iAuto.ui.framework.BControl", {
    singleton : true,
    cache : {},
    _create : function(a, c, i, h) {
        var g = ($.is$(c) ? c : $("#" + c)), d = a.name, b = a.config, e = function() {
            if (h && h.call) {
                h.call()
            }
        };
        if (!g || !g.length) {
            iAuto.Logger
                    .error("[iAuto.ui.framework.BControl] cannot create control with none DOM element.");
            e();
            return this
        }
        if (typeof(d) !== "string") {
            iAuto.Logger.error("[iAuto.ui.framework.BControl] Unknown type.");
            e();
            return this
        } else {
            d = d.trim().toLowerCase()
        }
        if (!d || d.length < 2) {
            iAuto.Logger.error("[iAuto.ui.framework.BControl] Have no type.");
            e();
            return this
        }
        var f;
        switch (d) {
            case ("button") :
                f = new iAuto.ui.control.Button(g, b);
                break;
            case ("combobox") :
                f = new iAuto.ui.control.ComboBox(g, b);
                break;
            case ("searchbox") :
                f = new iAuto.ui.control.SearchBox(g, b);
                break;
            case ("toggle") :
                f = new iAuto.ui.control.Toggle(g, b);
                break;
            case ("spinner") :
                f = new iAuto.ui.control.Spinner(g, b);
                break;
            default :
                iAuto.Logger
                        .error("[iAuto.ui.framework.BControl] Unknown basic control type.");
                d = d.trim().toLowerCase();
                return this
        }
        f.id = a.id;
        if (i && i.call) {
            i.call(null, f)
        }
    },
    destroy : function(b) {
        var a = this.cache[b];
        if (!a) {
            return
        }
        if ($.isFunction(a.destroy)) {
            a.destroy()
        }
        delete this.cache[b];
        return this
    },
    create : function(d, a, c) {
        var e = $.is$(a) ? a : $("#" + a), b;
        d = d.trim().toLowerCase();
        if (!e || !e.length) {
            iAuto.Logger
                    .error("[iAuto.ui.framework.BControl] cannot create control with none DOM element.");
            return this
        }
        if (!d || d.length < 2) {
            iAuto.Logger.error("[iAuto.ui.framework.BControl] Have no type.");
            return this
        }
        switch (d) {
            case ("button") :
                b = new iAuto.ui.control.Button(e, c);
                break;
            case ("combobox") :
                b = new iAuto.ui.control.ComboBox(e, c);
                break;
            case ("searchbox") :
                b = new iAuto.ui.control.SearchBox(e, c);
                break;
            case ("toggle") :
                b = new iAuto.ui.control.Toggle(e, c);
                break;
            case ("spinner") :
                b = new iAuto.ui.control.Spinner(e, c);
                break;
            default :
                iAuto.Logger
                        .error("[iAuto.ui.framework.BControl] Unknown basic control type.");
                return this
        }
        this.cache[a] = b;
        return b
    },
    get : function(a) {
        return this.cache[a]
    },
    removeAll : function() {
        this.cache = {}
    }
});
iAuto.define("iAuto.ui.framework.FControl", {
    singleton : true,
    _instances : {},
    _status : {},
    _state : {
        UNLOAD : 0,
        LOADED : 1,
        STARTED : 2,
        STOPED : 1
    },
    load : function(f, c, e) {
        var g = this, b = iAuto.ui.core.ClassManager, h = this._instances, d = this._status, a;
        b.loadClass("fcontrol", f, function(j) {
            if (d[f] >= g._state.LOADED) {
                return
            }
            a = new j();
            h[f] = a;
            a.$name = f;
            try {
                a.onLoad.call(a)
            } catch (k) {
                var i = iAuto.Logger;
                i.error("Function Control [" + f
                        + "] onLoad method goes wrong.");
                if (e && e.call) {
                    e()
                }
            }
            d[f] = g._state.LOADED;
            if ($.isFunction(c)) {
                c.call(g, a)
            }
        }, e)
    },
    define : function(a, b) {
        iAuto.ui.core.ClassManager.define("fcontrol", a, b)
    },
    get : function(b, c) {
        var a = this._instances[b];
        if (a) {
            if ($.isFunction(c)) {
                c.call(a, a)
            }
            return a
        } else {
            if (typeof(c) === "function") {
                return this.load(b, function(d) {
                    c(d)
                }, function() {
                    iAuto.Logger
                            .warn("[iAuto.ui.framework.FControl] Get Function Control ["
                                    + b
                                    + "] failed! Check If you load the Function Control.")
                })
            } else {
                return this
            }
        }
    },
    start : function(d, b, c) {
        var f = this, a = this._instances[d], e = function(h) {
            if (f._status[d] >= f._state.STARTED) {
                if ($.isFunction(b)) {
                    b.call(h, h)
                }
                return f
            }
            try {
                h.onStart.call(h)
            } catch (i) {
                var g = iAuto.Logger;
                g.error("FunctionControl [" + d + "] start it error!");
                if ($.isFunction(c)) {
                    c.call(h, h)
                }
            }
            if ($.isFunction(b)) {
                b.call(h, h)
            }
            f._status[d] = f._state.STARTED
        };
        if (a) {
            e(a)
        } else {
            this.load(d, e)
        }
        return this
    },
    stop : function(c) {
        var a = this._instances[c];
        if (a) {
            try {
                a.onStop.call(a)
            } catch (d) {
                var b = iAuto.Logger;
                b.error("FunctionControl [" + c + "] stop it error!")
            }
        }
        this._status[c] = this._state.STOPED;
        return this
    },
    exist : function(a) {
        return this._instances.hasOwnProperty(a)
    }
});
iAuto.define("iAuto.ui.framework.Model", {
    singleton : true,
    state : {
        STATE_UNLOAD : 0,
        STATE_LOADING : 1,
        STATE_LOADED : 2,
        STATE_REMOVED : 0
    },
    _status : {},
    _instances : {},
    config : {
        baseUrl : iAuto.ui.framework.App.getModelsDir()
    },
    load : function(c, a) {
        var d = this;
        d._status[c] = d._status[c] || {};
        if (d._status[c].state >= d.state.STATE_LOADED) {
            if (typeof(a) === "function") {
                return a()
            } else {
                return null
            }
        }
        if (!d._status[c].state || d._status[c].state < d.state.STATE_LOADING) {
            d._status[c].state = d.state.STATE_LOADING;
            var b = d.getBaseUrl() + c + ".js";
            iAuto.ui.core.require(b)
        }
        d.one(c + ":loaded", function() {
            d._status[c].state = d._status[c].state | d.state.STATE_LOADED;
            if (typeof(a) === "function") {
                return a()
            } else {
                return true
            }
        })
    },
    define : function(a, b) {
        if (this[a]) {
            return this[a]
        }
        b.extend = b.extend || "iAuto.ui.base.Controller";
        iAuto.define("iAuto.ui.framework.Model." + a, b);
        this.trigger(a + ":loaded");
        return this
    },
    create : function(c, d, b) {
        if (!this[c]) {
            iAuto.Logger.error("[iAuto.ui.framework.Model] Model " + c
                    + " has not been failed!");
            return this[c]
        }
        var a = new this[c]();
        if (!a) {
            iAuto.Logger.error("[iAuto.ui.framework.Model] create Model [" + c
                    + "] failed!");
            return this
        }
        a.modelName = c;
        a.id = d || $.uuid();
        this._instances[c] = this._instances[c] || [];
        this._instances[c].push(a);
        return a
    },
    get : function(b, d) {
        if (!this._instances[b] || !d) {
            return
        }
        var c = this._instances[b];
        for (var a in c) {
            if (c[a].id === d) {
                return c[a]
            }
        }
        return
    },
    remove : function(b, d) {
        if (!this._instances[b] || !d) {
            return false
        }
        var c = this._instances[b];
        for (var a in c) {
            if (c[a].id === d) {
                c.split(a, 1)
            }
        }
        return false
    },
    getAll : function(a) {
        return this._instances[a]
    },
    removeAll : function(a) {
        delete this._instances[a]
    }
});
(function(c) {
    c.mvc = c.mvc || {};
    var a = {};
    c.mvc.model = function(e, h, g) {
        var i;
        if (this.__proto__) {
            i = {};
            g = g || this.__proto__;
            i.__proto__ = g
        } else {
            g = g || this;
            var f = {};
            for (var d in g) {
                f[d] = g[d]
            }
            i = Object.create(Object.getPrototypeOf(this))
        }
        h && h.modelName && delete h.modelName;
        h && h.id && delete h.id;
        c.extend(i, h);
        i.modelName = e;
        return i
    };
    c.mvc.model.clone = function(g, f, h) {
        if (h) {
            if (f.__proto__) {
                g.__proto__ = f.__proto__
            } else {
                var e = {};
                for (var d in f.prototype) {
                    e[d] = f.prototype[d]
                }
                g = Object.create(Object.getPrototypeOf(f))
            }
        }
        for (var d in f) {
            if (f.hasOwnProperty(d)) {
                g[d] = f[d]
            }
        }
        return g
    };
    c.mvc.model.prototype = {
        fetch : function(e, f) {
            if (typeof(e) == "string") {
                this.id = e
            }
            var d = this;
            this.storageAdapter().fetch(d, function(g) {
                var h = d._prepareModel(g);
                if (f) {
                    return f(h)
                }
                return h
            }, this.modelName)
        },
        fetchAll : function(e) {
            var d = this;
            this.storageAdapter().fetchAll(d, function(f) {
                var g = [];
                f.forEach(function(h) {
                    g.push(d._prepareModel(h))
                });
                if (e) {
                    return e(g)
                }
                return g
            })
        },
        save : function(d) {
            return this.storageAdapter().save(this, d)
        },
        remove : function(d) {
            return this.storageAdapter().remove(this, d)
        },
        get : function(d) {
            if (this.hasOwnProperty(d)) {
                return this[d]
            }
            return undefined
        },
        set : function(h, g, f) {
            var d = c.mvc.model.clone({}, this);
            if (c.isObject(h)) {
                h && h.modelName && delete h.modelName;
                h && h.id && delete h.id;
                for (var e in h) {
                    if (this.hasOwnProperty(e)) {
                        this[e] = h[e]
                    }
                }
                if (!this._validate(f)) {
                    c.mvc.model.clone(this, d);
                    return false
                }
                return true
            }
            if (h.toLowerCase() != "id" && h.toLowerCase() != "modelname") {
                this[h] = g
            }
            if (!this._validate(f)) {
                c.mvc.model.clone(this, d);
                return false
            }
            return true
        },
        storageAdapter : function() {
            return a[this.modelName]
        },
        valid : function(d) {
            return this.validate(d) === true
        },
        validate : function(d) {
            return true
        },
        _prepareModel : function(e) {
            var d = this;
            var f = c.mvc.model.clone({}, d, true);
            f = c.mvc.model.clone(f, e);
            return f
        },
        _validate : function(e) {
            if (e && e.silent) {
                return true
            }
            var d = this.validate(e);
            if (d === true) {
                return true
            }
            if (e && e.error) {
                e.error(this, d, e)
            }
            return false
        }
    };
    c.mvc.model.extend = function(e, g, d, f) {
        a[e] = d ? d : (b.linkerCache[e] = {}, b);
        return function() {
            return new c.mvc.model(e, g)
        }
    };
    var b = {
        linkerCache : {},
        save : function(d, e) {
            if (!d.id) {
                d.id = c.uuid()
            }
            window.localStorage[d.id] = JSON.stringify(d);
            this.linkerCache[d.modelName][d.id] = 1;
            window.localStorage[d.modelName + "_linker"] = JSON
                    .stringify(this.linkerCache[d.modelName]);
            c(document).trigger(d.modelName + ":save", d);
            if (e) {
                return e(d)
            }
        },
        fetch : function(g, i) {
            var h = g.id;
            var d = window.localStorage.getItem(h);
            try {
                d = JSON.parse(d)
            } catch (f) {
                d = {}
            }
            return i(d)
        },
        fetchAll : function(i, k) {
            var f = i.modelName;
            var h = JSON.parse(window.localStorage.getItem(f + "_linker"));
            var e = [];
            for (var d in h) {
                if (localStorage[d]) {
                    var g = JSON.parse(localStorage[d]);
                    g.id = d;
                    e.push(g)
                } else {
                    delete h[d]
                }
            }
            this.linkerCache[f] = h ? h : {};
            window.localStorage[f + "_linker"] = JSON
                    .stringify(this.linkerCache[f]);
            return k(e)
        },
        remove : function(d, e) {
            window.localStorage.removeItem(d.id);
            delete this.linkerCache[d.modelName][d.id];
            window.localStorage[d.modelName + "_linker"] = JSON
                    .stringify(this.linkerCache[d.modelName]);
            c(document).trigger(d.modelName + ":remove", d.id);
            if (e) {
                return e(d)
            }
        }
    }
})(af);
iAuto.define("iAuto.ui.framework.View", {
    singleton : true,
    views : {},
    state : {
        UNLOAD : 255,
        LOADING : 240,
        LOADED : 0
    },
    directory : {
        controller : "views/",
        xcontrol : "resources/cc/"
    },
    config : {
        dir : iAuto.ui.framework.App.getViewsDir()
    },
    load : function(c, a) {
        var d = this, b = this.views[c];
        if (b) {
            if (b.template) {
                if (a && a.call) {
                    a.call(null, b.template, c)
                }
            } else {
                if (a && a.call) {
                    b.waiting = b.waiting || [];
                    b.waiting.push(a)
                }
            }
        } else {
            $.get(c, function(f) {
                var e = d.template(f);
                b = (d.views[c] = d.views[c] || {});
                b.template = e;
                if (a && a.call) {
                    a.call(null, e, c)
                }
                if (b.waiting) {
                    b.waiting.forEach(function(g) {
                        g(e)
                    });
                    delete b.waiting
                }
            })
        }
    },
    get : function(b) {
        var a = this.views[b];
        if (a) {
            return a.template
        }
        return null
    }
});
(function() {
    var doT = {
        version : "1.0.0",
        templateSettings : {
            evaluate : /\{\{([\s\S]+?\}?)\}\}/g,
            interpolate : /\{\{=([\s\S]+?)\}\}/g,
            encode : /\{\{!([\s\S]+?)\}\}/g,
            use : /\{\{#([\s\S]+?)\}\}/g,
            useParams : /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,
            define : /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
            defineParams : /^\s*([\w$]+):([\s\S]+)/,
            conditional : /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
            iterate : /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
            varname : "it",
            strip : true,
            append : true,
            selfcontained : false
        },
        template : undefined,
        compile : undefined
    };
    if (typeof module !== "undefined" && module.exports) {
        module.exports = doT
    } else {
        if (typeof define === "function" && define.amd) {
            define(function() {
                return doT
            })
        } else {
            (function() {
                return this || (0, eval)("this")
            }()).doT = doT
        }
    }
    function encodeHTMLSource() {
        var encodeHTMLRules = {
            "&" : "&#38;",
            "<" : "&#60;",
            ">" : "&#62;",
            '"' : "&#34;",
            "'" : "&#39;",
            "/" : "&#47;"
        }, matchHTML = /&(?!#?\w+;)|<|>|"|'|\//g;
        return function() {
            return this ? this.replace(matchHTML, function(m) {
                return encodeHTMLRules[m] || m
            }) : this
        }
    }
    String.prototype.encodeHTML = encodeHTMLSource();
    var startend = {
        append : {
            start : "'+(",
            end : ")+'",
            endencode : "||'').toString().encodeHTML()+'"
        },
        split : {
            start : "';out+=(",
            end : ");out+='",
            endencode : "||'').toString().encodeHTML();out+='"
        }
    }, skip = /$^/;
    function resolveDefs(c, block, def) {
        return ((typeof block === "string") ? block : block.toString())
                .replace(c.define || skip, function(m, code, assign, value) {
                    if (code.indexOf("def.") === 0) {
                        code = code.substring(4)
                    }
                    if (!(code in def)) {
                        if (assign === ":") {
                            if (c.defineParams) {
                                value.replace(c.defineParams, function(m,
                                        param, v) {
                                    def[code] = {
                                        arg : param,
                                        text : v
                                    }
                                })
                            }
                            if (!(code in def)) {
                                def[code] = value
                            }
                        } else {
                            new Function("def", "def['" + code + "']=" + value)(def)
                        }
                    }
                    return ""
                }).replace(c.use || skip, function(m, code) {
                    if (c.useParams) {
                        code = code.replace(c.useParams, function(m, s, d,
                                param) {
                            if (def[d] && def[d].arg && param) {
                                var rw = (d + ":" + param)
                                        .replace(/'|\\/g, "_");
                                def.__exp = def.__exp || {};
                                def.__exp[rw] = def[d].text.replace(new RegExp(
                                        "(^|[^\\w$])" + def[d].arg
                                                + "([^\\w$])", "g"), "$1"
                                        + param + "$2");
                                return s + "def.__exp['" + rw + "']"
                            }
                        })
                    }
                    var v = new Function("def", "return " + code)(def);
                    return v ? resolveDefs(c, v, def) : v
                })
    }
    function unescape(code) {
        return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " ")
    }
    doT.template = function(tmpl, c, def) {
        c = c || doT.templateSettings;
        var cse = c.append ? startend.append : startend.split, needhtmlencode = false, sid = 0, indv, str = (c.use || c.define)
                ? resolveDefs(c, tmpl, def || {})
                : tmpl;
        str = ("var out='"
                + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g, " ")
                        .replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g, "") : str)
                        .replace(/'|\\/g, "\\$&").replace(
                                c.interpolate || skip, function(m, code) {
                                    return cse.start + unescape(code) + cse.end
                                }).replace(c.encode || skip, function(m, code) {
                            needhtmlencode = true;
                            return cse.start + unescape(code) + cse.endencode
                        }).replace(c.conditional || skip,
                                function(m, elsecase, code) {
                                    return elsecase ? (code
                                            ? "';}else if(" + unescape(code)
                                                    + "){out+='"
                                            : "';}else{out+='") : (code
                                            ? "';if(" + unescape(code)
                                                    + "){out+='"
                                            : "';}out+='")
                                }).replace(c.iterate || skip,
                                function(m, iterate, vname, iname) {
                                    if (!iterate) {
                                        return "';} } out+='"
                                    }
                                    sid += 1;
                                    indv = iname || "i" + sid;
                                    iterate = unescape(iterate);
                                    return "';var arr" + sid + "=" + iterate
                                            + ";if(arr" + sid + "){var "
                                            + vname + "," + indv + "=-1,l"
                                            + sid + "=arr" + sid
                                            + ".length-1;while(" + indv + "<l"
                                            + sid + "){" + vname + "=arr" + sid
                                            + "[" + indv + "+=1];out+='"
                                }).replace(c.evaluate || skip,
                                function(m, code) {
                                    return "';" + unescape(code) + "out+='"
                                }) + "';return out;").replace(/\n/g, "\\n")
                .replace(/\t/g, "\\t").replace(/\r/g, "\\r").replace(
                        /(\s|;|\}|^|\{)out\+='';/g, "$1").replace(/\+''/g, "")
                .replace(/(\s|;|\}|^|\{)out\+=''\+/g, "$1out+=");
        if (needhtmlencode && c.selfcontained) {
            str = "String.prototype.encodeHTML=(" + encodeHTMLSource.toString()
                    + "());" + str
        }
        try {
            return new Function(c.varname, str)
        } catch (e) {
            if (typeof iAuto.Logger !== "undefined") {
                iAuto.Logger
                        .log("Could not create a template function: " + str)
            }
            throw e
        }
    };
    doT.compile = function(tmpl, def) {
        return doT.template(tmpl, null, def)
    };
    iAuto.ui.framework.View.template = doT.template
}(iAuto));
iAuto.define("iAuto.ui.framework.XControl", {
    singleton : true,
    _instances : {},
    classes : {},
    classMgr : iAuto.ui.core.ClassManager,
    _parent : null,
    define : function(a, d) {
        var c = this.classes, b = iAuto.ui.core.ClassManager;
        b.define("xcontrol", a, d, function(e) {
            c[a] = e
        });
        return this
    },
    _create : function(b, e, m, i) {
        var h = this, k = iAuto.ui.core.AMD, j = iAuto.ui.framework.App
                .getXcontrolsDir(), f, a = b.name, d = b.config, g = this.classes[a], l, c = function(
                o, p, n) {
            l = new o();
            l.id = b.id;
            l.$element = ($.is$(p) ? p : $(p));
            h._lifeCreate(l, p, n, m, i)
        };
        if (!g) {
            iAuto.ui.core.ClassManager.loadClass("xcontrol", a, function(n) {
                h.classes[a] = n;
                c(n, e, d)
            });
            f = j + a + "/" + a + ".css";
            k.linkCss(f)
        } else {
            c(g, e, d)
        }
    },
    _lifeCreate : function(o, g, d, q, l) {
        var k = this, c = iAuto.ui.framework.Patch, f = iAuto.ui.framework.View, b = o.name, n, p = o.views, j = p.length, m = iAuto.ui.framework.App
                .getXcontrolsDir(), h = 0, a, i = function(r) {
            try {
                r.onCreate.call(r)
            } catch (s) {
                iAuto.Logger.error(s)
            }
            if (r.$element && r.$content) {
                c.loadItems(r).loadEvents(r);
                k._createCmp.call(k, r, function(t) {
                    k._lifeShow.call(k, t, q, l)
                }, l)
            }
        };
        for (n in d) {
            if (d.hasOwnProperty(n)) {
                var e = "set" + n.charAt(0).toUpperCase() + n.substr(1);
                if (typeof(o[e]) === "function") {
                    o[e](d[n])
                } else {
                    o.config[n] = d[n]
                }
            }
        }
        if (j > 0) {
            p.forEach(function(r) {
                a = m + b + "/" + r;
                (function(s) {
                    f.load(s, function(t) {
                        o._views[s] = t;
                        if (++h >= j) {
                            i(o, q, l)
                        }
                    })
                })(a)
            })
        } else {
            i(o, q, l)
        }
        return this
    },
    _lifeShow : function(b, a, c) {
        b.$element.children().remove();
        b.$element.append(b.$content);
        try {
            this._bindEvent(b);
            b.onShow.call(b)
        } catch (d) {
            if ($.isFunction(c)) {
                c()
            }
            iAuto.Logger.error(d)
        }
        if ($.isFunction(a)) {
            a(b)
        }
    },
    _createCmp : function(c, b, a) {
        iAuto.ui.framework.Controller._createCmp(c, b, a)
    },
    _removeCmp : function(a) {
        iAuto.ui.framework.Controller._removeCmp(a)
    },
    _bindEvent : function(a) {
        iAuto.ui.framework.Controller._bindEvent(a);
        return this
    },
    _unbindEvent : function(a) {
        iAuto.ui.framework.Controller._unbindEvent(a);
        return this
    },
    create : function(d, h, c) {
        var f = this, b = this.classes[d], g = this._instances, a, e = function(
                j, k, i) {
            a = new j();
            a.id = k;
            f._lifeCreate(a, k, i, function(l) {
                g[k] = l
            })
        };
        if (b) {
            e(b, h, c)
        } else {
            iAuto.ui.core.ClassManager.loadClass("xcontrol", d, function(i) {
                f.classes[d] = i;
                e(i, h, c)
            })
        }
    },
    get : function(a) {
        return iAuto.ui.framework.App.getCurrentController().getCmp(a)
                || this._instances[a]
    },
    destroy : function(c) {
        var a = this._instances[c];
        this._unbindEvent(a);
        if (a) {
            try {
                a.onHide(a);
                this._removeCmp(a);
                a.onDestroy(a)
            } catch (b) {
                iAuto.Logger.error(b)
            }
            return delete this._instances[c]
        }
        return false
    },
    _destroy : function(a) {
        this._unbindEvent(a);
        if (a) {
            try {
                if (typeof(a.onHide) === "function") {
                    a.onHide.call(a)
                }
                this._removeCmp(a);
                if (typeof(a.onDestroy) === "function") {
                    a.onDestroy.call(a)
                }
            } catch (b) {
                iAuto.Logger.error(b)
            }
            return delete a
        }
        return false
    },
    _getBaseUrl : function() {
        return iAuto.ui.framework.App.getXcontrolsDir()
    }
});
iAuto.define("iAuto.ui.framework.Glayer", {
    singleton : true,
    _instances : {},
    load : function(a, c) {
        var b = this;
        iAuto.ui.core.ClassManager.loadClass("glayer", a, function(f) {
            var d = new f();
            d.name = a;
            b._instances[a] = d;
            d.$content = $("#glayer");
            try {
                d.onLoad.call(d)
            } catch (g) {
                iAuto.Logger.error(g)
            }
            b._lifeEnter(d, c)
        });
        return this
    },
    define : function(a, c) {
        var b = iAuto.ui.core.ClassManager;
        c.singleton = c.singleton || "true";
        b.define("glayer", a, c);
        return this
    },
    _lifeEnter : function(a, c) {
        var b = this, d = iAuto.ui.framework.Patch;
        d.loadItems(a).loadEvents(a);
        this._createCmp(a, function() {
            b._lifeShow(a, c)
        });
        return this
    },
    _lifeShow : function(a, c) {
        this._bindEvent(a);
        try {
            a.onShow.call(a)
        } catch (b) {
            iAuto.Logger.error("Global Layer [" + name
                    + "] Execute wrong in onShow() function.");
            iAuto.Logger.error(b)
        }
        if ($.isFunction(c)) {
            c.call()
        }
        return this
    },
    _createCmp : function(c, b, a) {
        iAuto.ui.framework.Controller._createCmp(c, b, a)
    },
    _bindEvent : function(a) {
        iAuto.ui.framework.Controller._bindEvent(a)
    },
    getCmp : function(a) {
        return (this._instances && this._instances[a])
    },
    remove : function(b) {
        var a = this.get(b);
        if (!a) {
            iAuto.Logger
                    .error("[iAuto.ui.framework.Glayer] Remove an instance not exist");
            return false
        }
        try {
            a.onRemove.apply(a)
        } catch (c) {
            iAuto.Logger
                    .error("[iAuto.ui.framework.Glayer] error in onRemove method of ["
                            + b + "]");
            iAuto.Logger.error(c);
            return false
        }
        return delete this._instances[b]
    },
    show : function(a) {
        $("#" + a).toggle(true)
    },
    hide : function(a) {
        $("#" + a).toggle(false)
    }
});
iAuto.define("iAuto.ui.framework.Patch", {
    singleton : true,
    loadItems : function(i) {
        var g = iAuto.ui.framework, f = g.XControl, a = g.FControl, d = g.BControl, b = d.create, c = f.create, h = a.start, e = (i.items = i.items
                || []);
        d.create = function(k, l, j) {
            e.push({
                id : l,
                type : "bcontrol",
                name : k,
                config : j
            })
        };
        f.create = function(k, l, j) {
            e.push({
                id : l,
                type : "xcontrol",
                name : k,
                config : j
            })
        };
        a.start = function(j) {
            e.push({
                type : "fcontrol",
                name : j
            })
        };
        i._createCmp_.call(i, i);
        d.create = b;
        f.create = c;
        a.start = h;
        return this
    },
    loadEvents : function(a) {
        var c = (a.events = a.events || []), d = iAuto.ui.framework.Event, b = d.addListener;
        d.addListener = function(f, e) {
            e.item = f;
            c.push(e)
        };
        a._bindEvent_.call(a);
        d.addListener = b;
        return this
    }
});
iAuto.define("iAuto.ui.framework.System", {
    singleton : true,
    mixins : ["iAuto.core.event.Evented"],
    KEY_CODE_UNKNOWN : 0,
    KEY_CODE_HOME : 1,
    KEY_CODE_BACK : 2,
    KEY_CODE_VOLUMEUP : 3,
    KEY_CODE_VOLUMEDOWN : 4,
    KEY_CODE_TRACKUP : 5,
    KEY_CODE_TRACKDOWN : 6,
    KEY_CODE_MAP : 7,
    KEY_CODE_PHONE : 8,
    KEY_CODE_EJECT : 9,
    KEY_CODE_MENU : 10,
    KEY_CODE_ENTER : 11,
    KEY_CODE_POWER : 12,
    KEY_CODE_TONE : 13,
    KEY_CODE_INFO : 14,
    KEY_CODE_FAVORITES : 15,
    KEY_CODE_TAG1SWITCH : 16,
    KEY_CODE_TAG2SWITCH : 17,
    KEY_CODE_TAG3SWITCH : 18,
    KEY_CODE_TAG4SWITCH : 19,
    KEY_CODE_TAG5SWITCH : 20,
    KEY_CODE_TAG6SWITCH : 21,
    KEY_CODE_AUTOSTORE : 22,
    KEY_CODE_SEEKREV : 23,
    KEY_CODE_SEEKFWD : 24,
    KEY_CODE_CONFIG : 25,
    KEY_CODE_CDAUX : 26,
    KEY_CODE_RADIOBAND : 27,
    KEY_CODE_SEEKUP : 28,
    KEY_CODE_SEEKDOWN : 29,
    KEY_CODE_SRC : 30,
    KEY_CODE_VR : 31,
    KEY_CODE_HUNGUP : 32,
    KEY_CODE_RESERVE : 33,
    KEY_CODE_AUDIO : 34,
    KEY_CODE_UP : 35,
    KEY_CODE_DOWN : 36,
    KEY_CODE_TUNE : 37,
    KEY_CODE_NAVI : 38,
    KEY_CODE_DESTINATION : 39,
    KEY_CODE_ON_HOOK : 40,
    KEY_CODE_OFF_HOOK : 41,
    KEY_CODE_RPT : 42,
    KEY_CODE_MUTE : 43,
    KEY_CODE_INKA : 44,
    KEY_CODE_ICALL : 45,
    KEY_CODE_AV : 46,
    KEY_CODE_SOURCE : 47,
    KEY_CODE_HELP : 48,
    KEY_CODE_MUTEOFF : 49,
    KEY_CODE_LEFT : 50,
    KEY_CODE_RIGHT : 51,
    KEY_CODE_REARS : 52,
    KEY_CODE_TOPMENU : 53,
    KEY_CODE_JOYUP : 54,
    KEY_CODE_JOYLEFT : 55,
    KEY_CODE_JOYRIGHT : 56,
    KEY_CODE_JOYDOWN : 57,
    KEY_CODE_SUBTITLE : 58,
    KEY_CODE_ANGLE : 59,
    KEY_CODE_RETURN : 60,
    KEY_CODE_PREV : 61,
    KEY_CODE_PLAY_PAUSE : 62,
    KEY_CODE_NEXT : 63,
    KEY_CODE_STOP : 64,
    KEY_CODE_CAPTURE : 65,
    KEY_CODE_DIAG : 66,
    KEY_CODE_APPROACH : 67,
    KEY_CODE_FARAWAY : 68,
    DEVICE_TYPE_DEFAULT : 0,
    DEVICE_TYPE_MOST : 1,
    DEVICE_TYPE_REMOTE : 2,
    DEVICE_TYPE_STEERING : 3,
    __appId__ : null,
    __webServiceApi__ : null,
    __contentProviderApi__ : null,
    initSystem : function() {
        try {
            var a = this;
            if (a.__webServiceApi__ === null) {
                a.__webServiceApi__ = new iAuto.api.system.WebService(a.__appId__)
            }
            a.__webServiceApi__.one("apiReady", function() {
                a.__webServiceApi__.on("intentGot", function(c) {
                    try {
                        var f = JSON.parse(c);
                        a.trigger("intent", f)
                    } catch (d) {
                        iAuto.Logger.error(d.stack)
                    }
                })
            });
            a.__webServiceApi__.connect()
        } catch (b) {
            iAuto.Logger.error(b.stack)
        }
    },
    setAppId : function(a) {
        this.__appId__ = a
    },
    addTouchRegion : function(g, f, b, a) {
        try {
            var c = this;
            if (c.__webServiceApi__ === null) {
                c.__webServiceApi__ = new iAuto.api.system.WebService(c.__appId__)
            }
            c.__webServiceApi__.one("apiReady", function() {
                c.__webServiceApi__.addTouchRegion(f, g, b, a)
            });
            c.__webServiceApi__.connect()
        } catch (d) {
            iAuto.Logger.error(d.stack)
        }
    },
    removeTouchRegion : function(g, f, b, a) {
        try {
            var c = this;
            if (c.__webServiceApi__ === null) {
                c.__webServiceApi__ = new iAuto.api.system.WebService(c.__appId__)
            }
            c.__webServiceApi__.one("apiReady", function() {
                c.__webServiceApi__.rmTouchRegion(f, g, b, a)
            });
            c.__webServiceApi__.connect()
        } catch (d) {
            iAuto.Logger.error(d.stack)
        }
    },
    addKeyGuard : function(c, a) {
        try {
            var b = this;
            if (b.__webServiceApi__ === null) {
                b.__webServiceApi__ = new iAuto.api.system.WebService(b.__appId__)
            }
            b.__webServiceApi__.one("apiReady", function() {
                b.__webServiceApi__.addKeyGuard(c, a)
            });
            b.__webServiceApi__.connect()
        } catch (d) {
            iAuto.Logger.error(d.stack)
        }
    },
    removeKeyGuard : function(c, a) {
        try {
            var b = this;
            if (b.__webServiceApi__ === null) {
                b.__webServiceApi__ = new iAuto.api.system.WebService(b.__appId__)
            }
            b.__webServiceApi__.one("apiReady", function() {
                b.__webServiceApi__.rmKeyGuard(c, a)
            });
            b.__webServiceApi__.connect()
        } catch (d) {
            iAuto.Logger.error(d.stack)
        }
    },
    __fnQueryCompleted__ : null,
    queryContent : function(g, a, d, b, c) {
        try {
            var f = this;
            if (f.__contentProviderApi__ === null) {
                f.__contentProviderApi__ = new iAuto.api.system.ContentProvider()
            }
            if (f.__fnQueryCompleted__ === null) {
                f.__fnQueryCompleted__ = iAuto.Util.bind(f,
                        function(i, j, k, e) {
                            f.trigger("queryCompleted", i, j, k, e)
                        });
                f.__contentProviderApi__.on("queryCompleted",
                        f.__fnQueryCompleted__)
            }
            f.__contentProviderApi__.one("apiReady", function() {
                f.__contentProviderApi__.query(g, a, d, b, c)
            });
            f.__contentProviderApi__.connect()
        } catch (h) {
            iAuto.Logger.error(h.stack)
        }
    },
    __fnInsertCompleted__ : null,
    insertContent : function(c, a) {
        try {
            var b = this;
            if (b.__contentProviderApi__ === null) {
                b.__contentProviderApi__ = new iAuto.api.system.ContentProvider()
            }
            if (b.__fnInsertCompleted__ === null) {
                b.__fnInsertCompleted__ = iAuto.Util.bind(b, function(e, f) {
                    b.trigger("insertCompleted", e, f)
                });
                b.__contentProviderApi__.on("insertCompleted",
                        b.__fnInsertCompleted__)
            }
            b.__contentProviderApi__.one("apiReady", function() {
                b.__contentProviderApi__.insert(c, a)
            });
            b.__contentProviderApi__.connect()
        } catch (d) {
            iAuto.Logger.error(d.stack)
        }
    },
    __fnUpdateCompleted__ : null,
    updateContent : function(f, a, c, b) {
        try {
            var d = this;
            if (this.__contentProviderApi__ === null) {
                this.__contentProviderApi__ = new iAuto.api.system.ContentProvider()
            }
            if (d.__fnUpdateCompleted__ === null) {
                d.__fnUpdateCompleted__ = iAuto.Util.bind(d, function(h, e) {
                    d.trigger("updateCompleted", h, e)
                });
                d.__contentProviderApi__.on("updateCompleted",
                        d.__fnUpdateCompleted__)
            }
            d.__contentProviderApi__.one("apiReady", function() {
                d.__contentProviderApi__.update(f, a, c, b)
            });
            d.__contentProviderApi__.connect()
        } catch (g) {
            iAuto.Logger.error(g.stack)
        }
    },
    __fnRemoveCompleted__ : null,
    removeContent : function(d, b, a) {
        try {
            var c = this;
            if (c.__contentProviderApi__ === null) {
                c.__contentProviderApi__ = new iAuto.api.system.ContentProvider()
            }
            if (c.__fnRemoveCompleted__ === null) {
                c.__fnRemoveCompleted__ = iAuto.Util.bind(c, function(g, e) {
                    c.trigger("removeCompleted", g, e)
                });
                c.__contentProviderApi__.on("removeCompleted",
                        c.__fnRemoveCompleted__)
            }
            c.__contentProviderApi__.one("apiReady", function() {
                c.__contentProviderApi__.remove(d, b, a)
            });
            c.__contentProviderApi__.connect()
        } catch (f) {
            iAuto.Logger.error(f.stack)
        }
    },
    __fnTypeRetrieved__ : null,
    getContentUriType : function(b) {
        try {
            var a = this;
            if (a.__contentProviderApi__ === null) {
                a.__contentProviderApi__ = new iAuto.api.system.ContentProvider()
            }
            if (a.__fnTypeRetrieved__ === null) {
                a.__fnTypeRetrieved__ = iAuto.Util.bind(a, function(e, d) {
                    a.trigger("typeRetrieved", e, d)
                });
                a.__contentProviderApi__.on("typeRetrieved",
                        a.__fnTypeRetrieved__)
            }
            a.__contentProviderApi__.one("apiReady", function() {
                a.__contentProviderApi__.getType(b)
            });
            a.__contentProviderApi__.connect()
        } catch (c) {
            iAuto.Logger.error(c.stack)
        }
    }
});
iAuto.define("iAuto.ui.base.Controller", {
    xtype : "controller",
    config : {
        view : null,
        preImg : []
    },
    onLoad : function() {
    },
    onEnter : function() {
    },
    _createCmp_ : function() {
    },
    _bindEvent_ : function() {
    },
    onShowPre : function() {
    },
    onShow : function() {
    },
    onHide : function() {
    },
    onLeave : function() {
    },
    onRemove : function() {
    },
    getCmp : function(a) {
        return this._cmp[a]
    }
});
iAuto.define("iAuto.ui.base.FControl", {
    extend : "iAuto.core.event.Evented",
    xtype : "fcontrol",
    _baseUrl : iAuto.ui.framework.App.getFcontrolsDir(),
    config : {},
    onLoad : function() {
    },
    onStart : function() {
    },
    onStop : function() {
    },
    onRemove : function() {
    }
});
iAuto.define("iAuto.ui.base.XControl", {
    xtype : "xcontrol",
    views : null,
    _cmp : null,
    _status : null,
    _baseUrl : iAuto.ui.framework.App.getXcontrolsDir(),
    _views : [],
    $element : null,
    $content : null,
    name : null,
    id : null,
    events : null,
    config : {},
    constructor : function() {
        this._cmp = {};
        this._status = {};
        this._views = {};
        this.events = []
    },
    onCreate : function() {
    },
    _createCmp_ : function() {
    },
    _bindEvent_ : function() {
    },
    onShow : function() {
    },
    onHide : function() {
    },
    onDestroy : function() {
    },
    onRemove : function() {
    },
    getView : function(a) {
        var b = this._baseUrl + this.name + "/" + a;
        return this._views[b]
    },
    setView : function(a, c) {
        var d = this, b = this._baseUrl + this.name + "/" + a;
        iAuto.ui.framework.View.load(b, function(e) {
            d.$content = $.create(e(c))
        }, function() {
            iAuto.Logger.error("view [" + a + "] have not been loaded!")
        })
    },
    show : function() {
        if (this.$element && this.$content) {
            this.$element.append(this.$content)
        }
    },
    updateView : function(a, c) {
        var b = this.getView(a);
        this.$content = $.create(b(c));
        if (this.$element && this.$content) {
            this.$element.removeAll();
            this.$element.append(this.$content)
        }
    },
    hide : function() {
        this.$content = this.$element.children()
    },
    trigger : function() {
        this.$element.trigger.apply(this.$element, arguments)
    },
    on : function() {
        this.$element.on.apply(this.$element, arguments)
    },
    one : function() {
        this.$element.one.apply(this.$element, arguments)
    },
    off : function() {
        this.$element.off.apply(this.$element, arguments)
    },
    getCmp : function(a) {
        return this._cmp[a]
    }
});
iAuto.define("iAuto.ui.base.Model", {
    xtype : "model",
    _dataAdpter : null,
    id : null,
    modelName : null,
    config : {
        type : "localstorage"
    },
    fetch : function(b, c) {
        if (typeof(b) === "string") {
            this.id = b
        }
        var a = this;
        this._dataAdpter.fetch(a, function(d) {
            var e = a._prepareModel(d);
            if (c) {
                return c(e)
            }
            return e
        }, a.modelName)
    },
    fetchAll : function(b, c) {
        var a = this;
        if (this._dataAdpter) {
            this._dataAdpter.fetchAll(a, function(d) {
                var e = [];
                d.forEach(function(f) {
                    e.push(a._prepareModel(f))
                });
                if (c) {
                    return c(e)
                }
                return e
            })
        }
    },
    save : function(a) {
        return this._dataAdpter.save(this, a)
    },
    remove : function(a) {
        return this._dataAdpter.remove(this, a)
    },
    get : function(a) {
        if (this.hasOwnProperty(a)) {
            return this[a]
        }
        return undefined
    },
    set : function(e, d, c) {
        var a = $.extend({}, this);
        if ($.isObject(e)) {
            if (e && e.modelName) {
                delete e.modelName
            }
            if (e && e.id) {
                delete e.id
            }
            for (var b in e) {
                if (this.hasOwnProperty(b)) {
                    this[b] = e[b]
                }
            }
            if (!this._validate(c)) {
                $.extend(this, a);
                return false
            }
            return true
        }
        if (e.toLowerCase() !== "id" && e.toLowerCase() !== "modelname") {
            this[e] = d
        }
        if (!this._validate(c)) {
            $.extend(this, a);
            return false
        }
        return true
    },
    valid : function(a) {
        return this._validata(a) === true
    },
    _validation : function(a) {
        return a
    },
    _prepareModel : function(a) {
        var c = this;
        var b = $.extend({}, c);
        b = $.extend(b, a);
        return b
    }
});
iAuto.define("iAuto.ui.base.Glayer", {
    xtype : "glayer",
    _cmp : null,
    constructor : function() {
        this._cmp = {}
    },
    onLoad : function() {
    },
    _createCmp_ : function() {
    },
    _bindEvent_ : function() {
    },
    onShow : function() {
    },
    onHide : function() {
    },
    onRemove : function() {
    },
    show : function(a) {
        var b = this.$content.find("#" + a);
        b.toggle(true)
    },
    hide : function(a) {
        var b = this.$content.find("#" + a);
        b.toggle(false)
    },
    get : function(a) {
        return this._cmp[a]
    }
});
iAuto.define("iAuto.ui.control.Button", {
    $el : null,
    constructor : function(a, b) {
        var d = this;
        this.$el = a;
        var c = b.pressCls || "c-button-pressing";
        this.$el.on("touchstart", function() {
            d.$el.addClass(c)
        });
        this.$el.on("touchend", function() {
            d.$el.removeClass(c)
        })
    },
    setLabel : function(a) {
        this.$el.find("[data-role=lable]").html(a)
    }
});
iAuto.define("iAuto.ui.control.ComboBox", {
    $el : null,
    $select : null,
    constructor : function(a, b) {
        if (!a) {
            return
        }
        b = b || {};
        this.$el = a;
        this.$select = a.find("select");
        this.setOptions(b.options)
    },
    setOptions : function(a) {
        if (this.$select.length <= 0) {
            return this
        }
        a = a || [];
        for (var b = 0; b < a.length; b++) {
            var c = document.createElement("OPTION");
            c.innerText = a[b];
            this.$select.append(c)
        }
    }
});
iAuto.define("iAuto.ui.control.SearchBox", {
    $el : null,
    $clearbutton : null,
    $input : null,
    constructor : function(a, b) {
        if (!a) {
            return
        }
        b = b || {};
        var c = this;
        this.$el = a;
        this.$clearbutton = this.$el.find("div[data-role='clearbutton']");
        this.$input = this.$el.find("input[data-role='input']");
        itu.event.on(this.$clearbutton, "tap", c.clearValue, c)
    },
    clearValue : function() {
        if (this.$input) {
            this.$input.val("")
        }
    }
});
iAuto.define("iAuto.ui.control.Spinner", {
    $el : null,
    $label : null,
    $btnUp : null,
    $btnDown : null,
    config : {
        btnPressCls : "c-spinner-button-pressed",
        maxValue : 100,
        minValue : 0,
        scale : 1,
        value : 0
    },
    constructor : function(a, b) {
        if (!a || a.length < 1) {
            return
        }
        var d = this, c;
        this.$el = a;
        this.$label = a.find("label");
        this.$btnUp = a.find("div[data-role='up'");
        this.$btnDown = a.find("div[data-role='down']");
        for (c in (b = b || {})) {
            if (b.hasOwnProperty(c)) {
                var e = "set" + c.charAt(0).toUpperCase() + c.substr(1);
                if (this[e]) {
                    this[e](b[c])
                }
            }
        }
        this.showValue(this.getValue());
        itu.event.on(this.$btnUp, "tap", d.onUp, d);
        itu.event.on(this.$btnDown, "tap", d.onDown, d);
        itu.event.on(this.$btnUp, "touchstart", function() {
            d.$btnUp.addClass(d.getBtnPressCls())
        });
        itu.event.on(this.$btnUp, "touchend", function() {
            d.$btnUp.removeClass(d.getBtnPressCls())
        });
        itu.event.on(this.$btnDown, "touchstart", function() {
            d.$btnDown.addClass(d.getBtnPressCls())
        });
        itu.event.on(this.$btnDown, "touchend", function() {
            d.$btnDown.removeClass(d.getBtnPressCls())
        })
    },
    onUp : function() {
        var a = this.getValue();
        if ((a += this.getScale()) <= this.getMaxValue()) {
            this.setValue(a);
            this.showValue(a)
        }
    },
    onDown : function() {
        var a = this.getValue();
        if ((a -= this.getScale()) >= this.getMinValue()) {
            this.setValue(a);
            this.showValue(a)
        }
    },
    showValue : function() {
        this.$label.text(this.getValue())
    }
});
iAuto.define("iAuto.ui.control.Toggle", {
    $el : null,
    $thumb : null,
    config : {
        toggleOnCls : "c-toggle-on",
        thumbOnCls : "c-thumb-on",
        on : false
    },
    constructor : function(a, b) {
        if (!a || a.length < 1) {
            return
        }
        b = b || {};
        var c = this;
        this.$el = a;
        this.$thumb = a.find("div[data-role='thumb']");
        $.extend(this.config, b);
        itu.event.on(this.$el, "tap", c.toggle, c)
    },
    toggle : function() {
        if (this.getOn() === false || "false" === this.getOn().toString()) {
            this.setOn(true);
            this.$el.addClass(this.getToggleOnCls());
            this.$thumb.addClass(this.getThumbOnCls())
        } else {
            this.setOn(false);
            this.$el.removeClass(this.getToggleOnCls());
            this.$thumb.removeClass(this.getThumbOnCls())
        }
    },
    getStatus : function() {
        return this.getOn()
    }
});
var itu = (function() {
    var b = iAuto.ui.framework, a = {
        app : b.App,
        controller : b.Controller,
        view : b.View,
        model : b.Model,
        bcontrol : b.BControl,
        fcontrol : b.FControl,
        xcontrol : b.XControl,
        glayer : b.Glayer,
        event : b.Event,
        resource : b.ResourceManager
    };
    return a
})();
framework

记得我面试进这个公司的时候,考题里有个叫carousel.js

/**
 * af.web.carousel - a carousel library for App Framework apps
 * @copyright 2011 - Intel
 *
 */
(function($) {
    var cache = [];
    var objId=function(obj){
        if(!obj.afmCarouselId) obj.afmCarouselId=$.uuid();
        return obj.afmCarouselId;
    };
    $.fn.carousel = function(opts) {
        var tmp, id;
        for (var i = 0; i < this.length; i++) {
            //cache system
            id = objId(this[i]);
            if(!cache[id]){
                tmp = new carousel(this[i], opts);
                cache[id] = tmp;
            } else {
                tmp = cache[id];
            }
        }
        return this.length == 1 ? tmp : this;
    };

    var carousel = (function() {
        var translateOpen =$.feat.cssTransformStart;
        var translateClose = $.feat.cssTransformEnd;

        var carousel = function(containerEl, opts) {
            if (typeof containerEl === "string" || containerEl instanceof String) {
                this.container = document.getElementById(containerEl);
            } else {
                this.container = containerEl;
            }
            if (!this.container) {
                alert("Error finding container for carousel " + containerEl);
                return;
            }
            if (this instanceof carousel) {
                for (var j in opts) {
                    if (opts.hasOwnProperty(j)) {
                        this[j] = opts[j];
                    }
                }
            } else {

                return new carousel(containerEl, opts);
            }


            var that = this;
            af(this.container).bind('destroy', function(e){
                var id = that.container.afmCarouselId;
                //window event need to be cleaned up manually, remaining binds are automatically killed in the dom cleanup process
               window.removeEventListener("orientationchange", that.orientationHandler, false);
               if(cache[id]) delete cache[id];
               e.stopPropagation();
            });

            this.pagingDiv = this.pagingDiv ? document.getElementById(this.pagingDiv) : null;


            // initial setup
            this.container.style.overflow = "hidden";
            if (this.vertical) {
                this.horizontal = false;
            }

            var el = document.createElement("div");
            this.container.appendChild(el);
            var $el=$(el);
            var $container=$(this.container);
            var data = Array.prototype.slice.call(this.container.childNodes);
            while(data.length>0)
            {
                var myEl=data.splice(0,1);
                myEl=$container.find(myEl);
                if(myEl.get(0)===el)
                   continue;
                $el.append(myEl.get(0));
            }
            if (this.horizontal) {
                el.style.display = "block";
                el.style['float']="left";
            }
            else {
                el.style.display = "block";
            }

            this.el = el;
            this.refreshItems();
            var afEl = af(el);
            afEl.bind('touchmove', function(e) {that.touchMove(e);});
            afEl.bind('touchend', function(e) {that.touchEnd(e);});
            afEl.bind('touchstart', function(e) {that.touchStart(e);});
            this.orientationHandler = function() {that.onMoveIndex(that.carouselIndex,0);};
            window.addEventListener("orientationchange", this.orientationHandler, false);

        };

        carousel.prototype = {
            wrap:true,
            startX: 0,
            startY: 0,
            dx: 0,
            dy: 0,
            glue: false,
            myDivWidth: 0,
            myDivHeight: 0,
            cssMoveStart: 0,
            childrenCount: 0,
            carouselIndex: 0,
            vertical: false,
            horizontal: true,
            el: null,
            movingElement: false,
            container: null,
            pagingDiv: null,
            pagingCssName: "carousel_paging",
            pagingCssNameSelected: "carousel_paging_selected",
            pagingFunction: null,
            lockMove:false,
            okToMove: false,

            // handle the moving function
            touchStart: function(e) {
                this.okToMove = false;
                this.myDivWidth = numOnly(this.container.clientWidth);
                this.myDivHeight = numOnly(this.container.clientHeight);
                this.lockMove=false;
                if (e.touches[0].target && e.touches[0].target.type !== undefined) {
                    var tagname = e.touches[0].target.tagName.toLowerCase();
                    if (tagname === "select" || tagname === "input" || tagname === "button")  // stuff we need to allow
                    {
                        return;
                    }
                }
                if (e.touches.length === 1) {

                    this.movingElement = true;
                    this.startY = e.touches[0].pageY;
                    this.startX = e.touches[0].pageX;
                    var cssMatrix=$.getCssMatrix(this.el);

                    if (this.vertical) {
                        try {
                            this.cssMoveStart = numOnly(cssMatrix.f);
                        } catch (ex1) {
                            this.cssMoveStart = 0;
                        }
                    } else {
                        try {
                            this.cssMoveStart = numOnly(cssMatrix.e);
                        } catch (ex1) {
                            this.cssMoveStart = 0;
                        }
                    }
                }
            },
            touchMove: function(e) {
                if(!this.movingElement)
                   return;
                if (e.touches.length > 1) {
                    return this.touchEnd(e);
                }

                var rawDelta = {
                    x: e.touches[0].pageX - this.startX,
                    y: e.touches[0].pageY - this.startY
                };

                if (this.vertical) {
                    var movePos = { x: 0, y: 0 };
                    this.dy = e.touches[0].pageY - this.startY;

                    this.dy += this.cssMoveStart;
                    movePos.y = this.dy;

                    e.preventDefault();
                    //e.stopPropagation();
                } else {
                    if ((!this.lockMove&&isHorizontalSwipe(rawDelta.x, rawDelta.y))||Math.abs(this.dx)>5) {

                        var movePos = {x: 0,y: 0};
                        this.dx = e.touches[0].pageX - this.startX;
                        this.dx += this.cssMoveStart;
                        e.preventDefault();
                      //  e.stopPropagation();
                        movePos.x = this.dx;
                    }
                    else
                       return this.lockMove=true;
                }

                var totalMoved = this.vertical ? ((this.dy % this.myDivHeight) / this.myDivHeight * 100) * -1 : ((this.dx % this.myDivWidth) / this.myDivWidth * 100) * -1; // get a percentage of movement.

                if (!this.okToMove) {
                    oldStateOkToMove= this.okToMove;
                    this.okToMove = this.glue ? Math.abs(totalMoved) > this.glue  && Math.abs(totalMoved) < (100 - this.glue) : true;
                    if (this.okToMove && !oldStateOkToMove) {
                        $.trigger(this,"movestart",[this.el]);
                    }
                }

                if  (this.okToMove && movePos)
                   this.moveCSS3(this.el, movePos);

            },
            touchEnd: function(e) {
                if (!this.movingElement) {
                    return;
                }
                $.trigger(this,"movestop",[this.el]);
                // e.preventDefault();
                // e.stopPropagation();
                var runFinal = false;
              //  try {
                    var cssMatrix=$.getCssMatrix(this.el);
                    var endPos = this.vertical ? numOnly(cssMatrix.f) : numOnly(cssMatrix.e);

                    if (1==2&&endPos > 0) {
                        this.moveCSS3(this.el, {
                            x: 0,
                            y: 0
                        }, "300");
                    } else {
                        var totalMoved = this.vertical ? ((this.dy % this.myDivHeight) / this.myDivHeight * 100) * -1 : ((this.dx % this.myDivWidth) / this.myDivWidth * 100) * -1; // get a percentage of movement.
                        // Only need
                        // to drag 3% to trigger an event
                        var currInd = this.carouselIndex;
                        if (endPos < this.cssMoveStart && totalMoved > 3) {
                            currInd++; // move right/down
                        } else if ((endPos > this.cssMoveStart && totalMoved < 97)) {
                            currInd--; // move left/up
                        }
                        var toMove=currInd;
                        //Checks for infinite - moves to placeholders
                        if(this.wrap){
                            if (currInd > (this.childrenCount - 1)) {
                                currInd = 0;
                                toMove=this.childrenCount;
                            }
                            if (currInd < 0) {
                                currInd = this.childrenCount-1;
                                toMove=-1;
                            }
                        }
                        else {
                            if(currInd<0)
                                currInd=0;
                            if(currInd>this.childrenCount-1)
                                currInd=this.childrenCount-1;
                            toMove=currInd;
                        }

                        var movePos = {
                            x: 0,
                            y: 0
                        };
                        if (this.vertical) {
                            movePos.y = (toMove * this.myDivHeight * -1);
                        }
                        else {
                            movePos.x = (toMove * this.myDivWidth * -1);
                        }

                        this.moveCSS3(this.el, movePos, "150");

                        if (this.pagingDiv && this.carouselIndex !== currInd) {
                            document.getElementById(this.container.id + "_" + this.carouselIndex).className = this.pagingCssName;
                            document.getElementById(this.container.id + "_" + currInd).className = this.pagingCssNameSelected;
                        }
                        if (this.carouselIndex != currInd)
                            runFinal = true;
                        this.carouselIndex = currInd;

                        //This is for the infinite ends - will move to the correct position after animation
                        if(this.wrap){
                            if(toMove!=currInd){
                                var that=this;
                                window.setTimeout(function(){
                                    that.onMoveIndex(currInd,"1ms");
                                },155);
                           }
                        }
                    }
                //} catch (e) {
                //    console.log(e);
               // }
                this.dx = 0;
                this.movingElement = false;
                this.startX = 0;
                this.dy = 0;
                this.startY = 0;
                if (runFinal && this.pagingFunction && typeof this.pagingFunction == "function")
                    this.pagingFunction(this.carouselIndex);
            },
            onMoveIndex: function(newInd,transitionTime) {

                this.myDivWidth = numOnly(this.container.clientWidth);
                this.myDivHeight = numOnly(this.container.clientHeight);
                var runFinal = false;

                    if(document.getElementById(this.container.id + "_" + this.carouselIndex))
                        document.getElementById(this.container.id + "_" + this.carouselIndex).className = this.pagingCssName;

                    var newTime = Math.abs(newInd - this.carouselIndex);

                    var ind = newInd;
                    if (ind < 0)
                        ind = 0;
                    if (ind > this.childrenCount - 1) {
                        ind = this.childrenCount - 1;
                    }
                    var movePos = {
                        x: 0,
                        y: 0
                    };
                    if (this.vertical) {
                        movePos.y = (ind * this.myDivHeight * -1);
                    }
                    else {
                        movePos.x = (ind * this.myDivWidth * -1);
                    }

                    var time =transitionTime?transitionTime: 50 + parseInt((newTime * 20));
                    this.moveCSS3(this.el, movePos, time);
                    if (this.carouselIndex != ind)
                        runFinal = true;
                    this.carouselIndex = ind;
                    if (this.pagingDiv) {
                        var tmpEl = document.getElementById(this.container.id + "_" + this.carouselIndex);
                        if(tmpEl) tmpEl.className = this.pagingCssNameSelected;
                    }

                if (runFinal && this.pagingFunction && typeof this.pagingFunction == "function")
                    this.pagingFunction(currInd);
            },

            moveCSS3: function(el, distanceToMove, time, timingFunction) {
                if (!time)
                    time = 0;
                else
                    time = parseInt(time);
                if (!timingFunction)
                    timingFunction = "linear";
                el.style[$.feat.cssPrefix+"Transform"] = "translate" + translateOpen + distanceToMove.x + "px," + distanceToMove.y + "px" + translateClose;
                el.style[$.feat.cssPrefix+"TransitionDuration"] = time + "ms";
                el.style[$.feat.cssPrefix+"BackfaceVisibility"] = "hidden";
                el.style[$.feat.cssPrefix+"TransformStyle"] = "preserve-3d";
                el.style[$.feat.cssPrefix+"TransitionTimingFunction"] = timingFunction;
            },

            addItem: function(el) {
                if (el && el.nodeType) {

                    this.container.childNodes[0].appendChild(el);
                    this.refreshItems();
                }
            },
            refreshItems: function() {
                var childrenCounter = 0;
                var that = this;
                var el = this.el;
                $(el).children().find(".prevBuffer").remove();
                $(el).children().find(".nextBuffer").remove();
                n = el.childNodes[0];
                var widthParam;
                var heightParam = "100%";
                var elems = [];

                for (; n; n = n.nextSibling) {
                    if (n.nodeType === 1) {
                        elems.push(n);
                        childrenCounter++;
                    }
                }
                //Let's put the buffers at the start/end
                if(this.wrap){
                    var prep=$(elems[elems.length-1]).clone().get(0);
                    $(el).prepend(prep);
                    var tmp=$(elems[0]).clone().get(0);
                    $(el).append(tmp);
                    elems.push(tmp);
                    elems.unshift(prep);
                    tmp.style.position="absolute";
                    prep.style.position="absolute";
                }

                var param = (100 / childrenCounter) + "%";
                this.childrenCount = childrenCounter;
                widthParam = parseFloat(100 / childrenCounter) + "%";

                for (var i = 0; i < elems.length; i++) {
                    if (this.horizontal) {
                        elems[i].style.width = widthParam;
                        elems[i].style.height = "100%";
                        elems[i].style['float']="left";
                    }
                    else {
                        elems[i].style.height = widthParam;
                        elems[i].style.width = "100%";
                        elems[i].style.display = "block";
                    }
                }
                //Clone the first and put it at the end
                

                this.moveCSS3(el, {
                    x: 0,
                    y: 0
                });
                if (this.horizontal) {
                    el.style.width = Math.ceil((this.childrenCount) * 100) + "%";
                    el.style.height = "100%";
                    el.style['min-height'] = "100%"
                    if(this.wrap){
                        prep.style.left="-"+widthParam;
                        tmp.style.left="100%";
                    }
                }
                else {
                    el.style.width = "100%";
                    el.style.height = Math.ceil((this.childrenCount) * 100) + "%";
                    el.style['min-height'] = Math.ceil((this.childrenCount) * 100) + "%";
                    if(this.wrap){
                        prep.style.top="-"+widthParam;
                        tmp.style.top="100%";
                    }
                }
                // Create the paging dots
                if (this.pagingDiv) {
                    this.pagingDiv.innerHTML = ""
                    for (i = 0; i < this.childrenCount; i++) {

                        var pagingEl = document.createElement("div");
                        pagingEl.id = this.container.id + "_" + i;
                        pagingEl.pageId = i;
                        if (i !== this.carouselIndex) {
                            pagingEl.className = this.pagingCssName;
                        }
                        else {
                            pagingEl.className = this.pagingCssNameSelected;
                        }
                        pagingEl.onclick = function() {
                            that.onMoveIndex(this.pageId);
                        };
                        var spacerEl = document.createElement("div");

                        spacerEl.style.width = "20px";
                        if(this.horizontal){
                            spacerEl.style.display = "inline-block";
                            spacerEl.innerHTML = "&nbsp;";
                        }
                        else{
                           spacerEl.innerHTML="&nbsp;";
                           spacerEl.style.display="block";
                        }

                        this.pagingDiv.appendChild(pagingEl);
                        if (i + 1 < (this.childrenCount))
                            this.pagingDiv.appendChild(spacerEl);
                        pagingEl = null;
                        spacerEl = null;
                    }
                    if(this.horizontal){
                        this.pagingDiv.style.width = (this.childrenCount) * 50 + "px";
                        this.pagingDiv.style.height = "25px";
                    }
                    else {
                        this.pagingDiv.style.height = (this.childrenCount) * 50 + "px";
                        this.pagingDiv.style.width = "25px";
                    }
                }
                this.onMoveIndex(this.carouselIndex);

            }

        };
        return carousel;
    })();

    function isHorizontalSwipe(xAxis, yAxis) {
                var X = xAxis;
                var Y = yAxis;
                var Z = Math.round(Math.sqrt(Math.pow(X,2)+Math.pow(Y,2))); //the distance - rounded - in pixels
                var r = Math.atan2(Y,X); //angle in radians
                var swipeAngle = Math.round(r*180/Math.PI); //angle in degrees
                if ( swipeAngle < 0 ) { swipeAngle =  360 - Math.abs(swipeAngle); } // for negative degree values
                if (((swipeAngle <= 215) && (swipeAngle >= 155)) || ((swipeAngle <= 45) && (swipeAngle >= 0)) || ((swipeAngle <= 360) && (swipeAngle >= 315))) // horizontal angles with threshold
                {return true; }
                else {return false}
    }

})(af);
carousel.js

当时看源码觉得很多方法不知道哪里来的,也就是framework里面的东西。

采用的是目前流行的命名空间写法,整体结构大致上就是:

(function($) {
    "use strict";
    
    var cache = {};
    var ... = function(...) {};
    $.fn.scroller=function(...){
        return this.length == 1 ? tmp : this;
    };
    if(!$.mixin) {
        $.mixin = {};
    }
    if(!$.scroller) {
        $.scroller = {};
    }
    var mixin = $.mixin,
        scroller = $.scroller;
       mixin.scrollerMixin = {
        ...: ...,
        ...: ...,
         wrapper: '<div class="c-scroller">' +     
        '</div>',

        initScroller: function() {
            this.initData();
            this....();
        },
        ...: function() {
            this.... = {
                x: 0,
                y: 0
            };
        },
        ...: function() {
            return this.position;
        },
            var event = new Object();
            event.data = new Object();
            event.data.gesture = new Object();
            event.data.gesture.srcEvent = new Object();
            event.data.gesture.srcEvent.... = new Array();
            event.data.gesture.srcEvent....[0] = new Object();
            if ((... === ...) || (... === .....)) { 
                event.data.gesture.srcEvent....[0].pageX = this.....x;
                event.data.gesture.srcEvent....[0].pageY = this.....y;
            }    
            else {
                return;
            }
            this.dragStart(event);
            var ... = this;
            setTimeout(function() {
                me....(event, ...);
                me...(event);
            }, 50); 
            setTimeout(function() {
                me....(event, ...);
                me.drag(event);
            }, 50);
            setTimeout(function() {
                me....(event, ...);
                me....(event);
            }, 50);
        },
        modifyEvent: function(event, keyCode) {
            return event;
        },
        addWrapper: function() {
            var wrapper = this.wrapper,
                element = this.element;
            this.$wrapper = $(wrapper).insertBefore($(element));
            
            this.scrollerElement = this.$wrapper.find('.c-scroller__scroller-content');
            this.scrollerContainerElement = this.$wrapper.find('.c-scroller__scroller-container');
            
            $(element).appendTo(this.scrollerElement);
        },
         deleteWrapper: function() {
            var $wrapper, element, $element;
            $wrapper = this.$wrapper;
            element = this.element;
            $element = $(element);
            $element.remove();
            $element.insertBefore($wrapper);
            $wrapper.remove();
        },
        addResizeListener: function() {
            if ( ) {
            }
        },
        runLoopy: function() {},
        ...: function() {
            var .. = this...;
            this...({
                x: ...width(),
                y: ...height()
            });
        },...: function() {
            var ... = this....;
            this...({
                x: ...width(),
                y: ...height()
            });
        },
        ...: function() {
            var .., ...;
            .. = this....;
            ... = this...;
            if (!..) {
                this... = .. = {};
            }
            if (.. === '..') {
                ...x = true;
                ...y = true;
            } else if (.. === '..') {
                ...y = true;
                this.$wrapper.addClass('..');
            } else if (... === '..') {
                ...x = true;
                this.$wrapper.addClass('..');
            }
        },
        ...: function() {
            this... = iAuto.Util.bind(this, this...);
            $.bind(this, '..', this...);
            this... = iAuto.Util.bind(this, this...);
            $.bind(this, '..', this...);
            this... = iAuto.Util.bind(this, this...);
            $.bind(this, '..', this...);
        },
        ..: function() {
            this...();
        },
        ..: function() {
            this...();
        },
        ..: function(..) {
            return this...[..];
        },
    var Scroller = function(el, opts) {
        this.el = el;
        this.$el = $(el);
        iAuto.copy(this, mixin.scrollerMixin);
        opts = opts || {};
        iAuto.copy(this, opts);
        this.initScroller();
        if(this.showIndicator) {
            iAuto.copy(this, mixin.IndicatorMixin);
            this.initIndicator();
        }
        var me = this;
        this.$el.one('destroy', function(e) {
            var id = el.afscrollerID;
            if(cache[id]) delete cache[id];
            e.stopPropagation();
        });
    };
    Scroller.prototype = {
        element: null
    };
    var cssTranslate = scroller.CssTranslate = function() {}; 
    cssTranslate.prototype = {
        ...
        ...
        ...

        init: function() {},
        setTransformElement: function(transformElement) {},
        translate: function(x, y) {},
        doTranslate: function() {},
        animate: function(easingX, easingY) {},
        stopAnimation: function() {},
        destroy: function() {
            this.stopAnimation();
        }
    };
    var EaseOut = scroller.EaseOut = function() {};
    EaseOut.prototype = {
        ...: ..,
        ...: ..,
        ...: ..,
        init: function() {

        },
     setStartTime: function(startTime) {
            this.startTime = startTime;
            this.reset();
        },
     setStartValue: function(startValue) {},
     reset: function() {},
     setEndValue: function(endValue) {},
     setDuration: function(duration) {},
     setExponent: function(exponent) {},
     getValue: function() {
            ...: ..,
            ...: ..,
            ...: ..,
        if ( ) {}
            return ...;
        }
    };

    var Momentum = scroller.Momentum = function() {};
    Momentum.prototype = {
        ...: ..,
        ...: ..,
        ...: ..,

        init: function() {},
    };

    var Bounce = scroller.Bounce = function() {};
    Bounce.prototype = {
        ...: ..,
        ...: ..,
        ...: ..,
        init: function() {

        },
    };

    var BoundMomentum = scroller.BoundMomentum = function() {};
    BoundMomentum.prototype = {
        ...: ..,
        ...: ..,
        ...: ..,
        init: function() {
            this.initMomentum();
            this.initBounce();
        },
        initMomentum: function() {
            this.momentum = new Momentum();
            this.momentum.init();
        },
        initBounce: function() {
            this.bounce = new Bounce();
            this.bounce.init();
        },
        reset: function() {
            this... = null;
            this... = false;
            this... = false;
            this... = false;
        }
    };
    
})(af);

此处略去很多代码,为的是一目了然。

"use strict"

采用严谨模式的js

"use strict"; 被放在一个 JavaScript 文件或函数的起始位置时 (我不确定 script 标签开头是否可以),才可以开启严格模式。否则 - 在 JavaScript 文件的不是文件开头也不是函数开始的部位声明的话 - 就是一个不使用的一般的字符串,除了浪费几个字节,没什么别的用处。通常实践推荐在所有的函数 (或者所有最外层函数) 的开始处加入 "use strict"; 指令启动严格模式,而绝不推荐在文件的开头处写全局 "use strict" - 相反,这时一些 ES 校验器会给出警告。

全局 "use strict" 为什么不好? 一个重要的原因就是文件合并时,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge 后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。
注意事项

显然function($){}(document,window);是jquery系插件写法。

内部一开始先声明若干变量,把init方法摆出来。

然后有些对象内部的全局变量赋给局部变量,制造一些自定义事件用 new Object();

然后被包裹的内容,不可以定位为absolute,否则成不起来。

posted on 2014-11-05 18:11  meeming  阅读(734)  评论(0)    收藏  举报



Fork me on GitHub