示例#1
0
文件: view.js 项目: CyberAgent/beez
 setVisible: function setVisible(visible) {
     if (typeof visible !== 'boolean') {
         throw beez.Error('typeof visible invalid. should be boolean.');
     }
     this.visible = visible;
     return this;
 },
示例#2
0
文件: controller.js 项目: fkei/beez
                loadI18n: function loadI18n(callback) {
                    if (!beez.i18n) {
                        beez.createI18n();
                    }

                    var self = this;
                    if (beez.utils.is('Object', this.i18n)) { // dynamic load

                        var langs = [];
                        var paths = [];
                        _.each(this.i18n, function (path, lang) {
                            langs.push(lang);
                            paths.push(path);
                        });

                        require(paths, function () {
                            var list = Array.prototype.slice.call(arguments);
                            for (var i = 0; i < list.length; i++) {
                                var data = {};
                                data[langs[i]] = list[i];
                                beez.i18n.add(data);
                                logger.debug('i18n file loaded. path:', paths[i]);
                            }
                            callback && callback(null);
                        }, function (err) {
                            callback && callback(err);
                        });

                    } else if (beez.utils.is('Function', this.i18n)) { // static load
                        new beez.Bucks()
                            .add(function (err, res, next) {
                                if (0 < self.i18n.length) {
                                    self.i18n(function (err, res) {
                                        next(err, res);
                                    });
                                } else {
                                    next(null, self.i18n());
                                }
                            })
                            .add(function (err, res) {
                                if (res) {
                                    beez.i18n.add(res);
                                }
                                callback && callback(err, res);
                            })
                            .end();

                    } else {
                        callback && callback(new Error('The Controller.i18n, please be defined in Function.'));
                    }
                    return this;

                },
示例#3
0
文件: beez.i18n.js 项目: Layzie/beez
    define('beez.i18n',['require','exports','module','beez.core','beez.utils','handlebars'],function (require, exports, module) {
        

        var beez = require('beez.core');
        require('beez.utils');

        var logger = beez.getLogger('beez.i18n');
        var _ = beez.vendor._;

        if (beez.i18n) {
            logger.warn('beez.i18n is already loaded.');
            return beez.i18n;
        }

        var __I18n__ = {

            setup: function setup() {
                logger.warn('Setup has already been. beez.i18n');
                return this;
            },

            /**
             * Constructor
             * WARN: run only once from beez.i18n.setup
             *
             * @memberof I18n
             * @param {Object} options
             * @see beez.i18n.setup
             */
            initialize: function initialize(options) {
                /**
                 * @name lang
                 * @memberof I18n
                 * @type {Object}
                 */
                this.lang = {
                    base: 'en', // default lang
                    use: undefined // use lang
                };

                /**
                 * @name message
                 * @memberof I18n
                 * @type {Object}
                 */
                this.message = {};

                /**
                 * Regular expression extract string substitution.
                 *
                 * @name parseReg
                 * @memberof I18n
                 * @type {RegExp}
                 */
                //this.parseReg = new RegExp(/\{\{[(0-9a-zA-Z)]*\}\}/);
                this.parseReg = new RegExp(/\{#{1}[(0-9a-zA-Z)]*\}/);


                this.lang.use = beez.utils.browser.getLanguage();

                // override options
                options = options || {};
                options.lang = options.lang || {};

                if (options.lang.base) {
                    this.lang.base = options.lang.base;
                }
                if (options.lang.use) {
                    this.lang.use = options.lang.use;
                }

                //
                if (!this.lang.use) {
                    this.lang.use = this.lang.base;
                }

                if (options.message) {
                    this.message = options.message;
                }
            },

            /**
             * Name of the current language
             *
             * @memberof I18n
             * @instance
             * @public
             * @return {String}
             */
            getCurrentLang: function getCurrentLang() {
                return this.lang.use || this.lang.base;
            },

            /**
             * Replacement character string extraction.
             *
             * @memberof I18n
             * @instance
             * @public
             * @param {String} message
             * @param {Array} vars
             * @return {String}
             */
            parse: function (message, vars) {
                //var list = message.split(/\{\{[(0-9a-zA-Z)]*\}\}/);
                var list = message.split(this.parseReg);
                if (list.length === 1 && list[0] === '') {
                    return message;
                }

                var res = '';
                _.each(list, function (val, idx) {
                    res += val + (vars[idx] || '');
                });
                return res;
            },

            /**
             * Alias: I18n.getMessage()
             *
             * @memberof I18n
             * @instance
             * @public
             * @return {String}
             */
            __: function __(key) {
                return this.getMessage(key);
            },

            /**
             * I get the message corresponding to the current language
             *
             * @memberof I18n
             * @instance
             * @public
             * @return {String}
             */
            getMessage: function getMessage(key) {
                var lang = this.getCurrentLang();
                if (!this.message[lang]) {
                    lang = this.lang.base; // set default lang
                }
                if (!this.message[lang]) {
                    return ''; // not set!!
                }

                var message = this.message[lang][key] || '';
                if (!message && this.message[this.lang.base]) {
                    message = this.message[this.lang.base][key] || '';
                }
                var vars = Array.prototype.slice.call(arguments, 1);
                return this.parse(message, vars);
            },

            /**
             * Add data to a different message for the current language
             *
             * @memberof I18n
             * @instance
             * @public
             * @param {Object} obj
             * @return {Object}
             * @example
             * var res = beez.i18n.add({ja: {"taro": "太郎"}})
             * console.log(res)
             * >> {ja: {"taro": "太郎"}}
             */
            add: function add(obj) {
                return beez.utils.copyr(this.message, obj);
            },

            /**
             * Rewrite the message of one language
             *
             * @memberof I18n
             * @instance
             * @public
             * @param {String} lang example) 'en'
             * @param {Object} obj
             * @return {Object}
             * @example
             * var res = beez.i18n.addMessage(ja, {"taro": "太郎"});
             * console.log(res)
             * >> {"taro": "太郎"}
             */
            addMessage: function addMessage(lang, obj) {
                this.message[lang] = this.message[lang] || {};
                return beez.utils.copyr(this.message[lang], obj);
            },

            /**
             * Delete the message in another language
             *
             * @memberof I18n
             * @instance
             * @public
             * @param {String} lang example) 'en'
             * @param {String} key
             */
            remove: function remove(lang, key) {
                var obj = this.message[lang];
                if (obj && obj[key]) {
                    this.message[lang][key] = null;

                } else if (obj) {
                    this.message[lang] = null;

                } else {
                    this.message = {};
                }
            },

            /**
             * remove i18n data
             *
             * @memberof I18n
             * @instance
             * @public
             */
            dispose: function dispose() {
                delete this.lang;
                delete this.message;
                delete this.parseReg;
            }
        };

        var I18n = beez.extend(
            'beez.i18n',
            function constructor() {
                return this.initialize.apply(this, arguments);
            }, __I18n__);

        /**
         * beez.extendThis
         *
         * @memberof I18n
         * @instance
         * @public
         */
        I18n.extend = beez.extendThis;

        /**
         * @see I18n
         * @memberof beez
         * @instance
         * @public
         */
        beez.I18n = I18n;

        beez.i18n = {

            /**
             * i18n initialize
             *
             * @memberof I18n
             * @instance
             * @name setup
             * @param {I18n} I18n Class
             * @param {Object} options constructor/initialize arguments
             * @public
             * @example
             * beez.i18n.setup(null, {lang: {base: 'ja', use: 'ja'}});
             *
             */
            setup: function (options, Obj) {
                if (beez.i18n.initialize) {
                    logger.warn('Setup has already been. beez.i18n');
                    return beez.i18n;
                }

                // clear
                delete beez.i18n.setup;
                delete beez.i18n;

                if (!Obj) {
                    Obj = I18n;
                }

                /**
                 * i18n instance
                 * @memberof beez
                 * @instance
                 * @name i18n
                 * @public
                 */
                beez.i18n = new Obj(options);

                return beez.i18n;

            }
        };

        // ---
        // Add Handlebars Register Helper
        var Handlebars = require('handlebars');

        /**
         * i18n Handlebars Register Helper (escape OFF)
         *
         * @memberof beez.vendor.Handlebars.Helper
         * @instance
         * @name __
         * @public
         */
        Handlebars.registerHelper('__', function __(key) {
            if (beez.i18n) {
                var vars = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
                return new Handlebars.SafeString(beez.i18n.getMessage.apply(beez.i18n, vars));
            }
            return '';
        });

        /**
         * i18n Handlebars Register Helper (escape ON)
         *
         * @memberof beez.vendor.Handlebars.Helper
         * @instance
         * @name __
         * @public
         */
        Handlebars.registerHelper('__e', function __e(key) {
            if (beez.i18n) {
                var vars = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
                return beez.i18n.getMessage.apply(beez.i18n, vars);
            }
            return '';
        });

        return beez.I18n;
    });
示例#4
0
文件: base.js 项目: CyberAgent/beez
    define(function (require, exports, module) {
        'use strict';

        var beez = require('beez.core');
        var _ = beez.vendor._;

        var jsonPath = require('beez-mvcr/jsonpath');

        var logger = beez.getLogger('beez.mvcr.base');

        // -------------------
        // ManagerBase

        /**
         * It provides a set of methods to deal with it and tree structure simple of Object.
         * Object of ManagerBase has properties of specific management
         *
         * @class
         * @name ManagerBase
         *
         * @example
         * var manager = new ManagerBase('idx');
         *
         * manager.add('/', {idx:'someObj'});
         * manager.get('/someObj') // => {idx:'someObj'}
         *
         * manager.add('/', [{idx:'button', name:'a'}, {idx:'button', name:'b'}]);
         * manager.get('/button') // => [{idx:'button', name:'a'}, {idx:'button', name:'b'}]
         * manager.get('/button[0]') // => {idx:'button', name:'a'}
         */
        var ManagerBase = beez.extend(
            'beez.manager.ManagerBase',
            function ManagerBase() {},
            {

                /**
                 * @constructor
                 * @memberof ManagerBase
                 * @param {String} idxProp base index name
                 */
                constructor: function constructor(idxProp) {

                    /**
                     * Objects that are managed
                     */
                    this.objs = {};

                    /**
                     * The assignment to the $ indicates the root
                     */
                    this.objs[idxProp] = '$';

                    /**
                     * Index for management
                     */
                    this._idxProp = idxProp || '';

                    /**
                     * Run initialize
                     */
                    this.initialize.apply(this, arguments);
                },

                /**
                 * Constructor
                 *
                 * @memberof ManagerBase
                 */
                initialize: function initialize() {},

                /**
                 * Get idx of object
                 *
                 * @memberof ManagerBase
                 * @param {ManagerBase} obj
                 * @public
                 * @returns {String} idx
                 */
                getIdx: function getIdx(obj) {
                    return obj[this._idxProp];
                },


                /**
                 * put under control the specified Object
                 *
                 * @memberof ManagerBase
                 * @instance
                 * @param {String} prefix
                 * @param {Object|Array<Object>} obj
                 *
                 * @example
                 * var mainModel = {
                 *   follower: [
                 *     followerModel1,
                 *     folloewrModel2
                 *   ]
                 * }
                 *
                 * var followerModel3, followingModel, buttonModel;
                 * followerModel3.midx = 'follower';
                 * followingModel.midx = 'following';
                 * buttonModel.midx = 'button';
                 *
                 * manager.model.add('/main', [followerModel, followingModel]);
                 *
                 * -> mainModel : {
                 *   follower:[
                 *     followerModel1
                 *     folloewrModel2,
                 *     folloewrModel3
                 *   ],
                 *   following:[
                 *     followingModel
                 *   ]
                 * }
                 *
                 * manager.model.add('/main', button);
                 * -> mainModel : {
                 *   follower:[
                 *     followerModel1,
                 *     folloewrModel2,
                 *     folloewrModel3
                 *   ],
                 *   following:[
                 *     followingModel
                 *   ],
                 *   button: buttonModel
                 * }
                 */
                add: function add(prefix, obj) {
                    var parent = this.get(prefix); // search parent from root object

                    // get parent or create waiting object
                    if (!parent) { throw new beez.Error('no parent exists. path: ' + prefix); }
                    if (_.isArray(parent)) { throw new beez.Error('parent is Array. Specify one by using `[number]` selector. parent: ' + parent); }

                    if (_.isArray(obj)) { // add as the children
                        _.each(obj, function (_obj) {
                            _obj.prefix = prefix; // keep prefix
                            var idx = this.getIdx(_obj);
                            if (!parent[idx]) { // make array
                                parent[idx] = [];
                            }
                            parent[idx].push(_obj);

                        }, this);
                    } else {
                        obj.prefix = prefix; // keep prefix
                        var idx = this.getIdx(obj);
                        if (parent[idx]) {
                            throw new beez.Error(
                                'Obj: adding object to same parent with same index. Add obj as Array to add several objs into same index. idx: ' + this.getIdx(obj));
                        }
                        parent[idx] = obj;
                    }

                    return this;
                },


                /**
                 * will remove from management the object that is specified in the path
                 *
                 * @memberof ManagerBase
                 * @instance
                 * @param {String} path
                 */
                remove: function remove(path) {
                    var objs = this.get(path);
                    // get all children
                    var children = [];
                    var deletes;

                    if (!objs) { return; }

                    // now `views` is always Array
                    if (!_.isArray(objs)) { objs = [objs]; } // array-nize

                    _.each(objs, function (v) {
                        var c = this.getChildrenAll(v);
                        children = children.concat(c);
                    }, this);

                    // list to delete
                    // is children and this views
                    deletes = children.concat(objs);
                    // remove parent's reference
                    _.each(deletes, function (del) {
                        this.deleteFromParent(del);
                    }, this);

                    // call dispose of each views
                    _.each(deletes, function (v) {
                        //v.remove();
                        v.dispose && v.dispose();
                    });
                },

                /**
                 * Returns whether the object can be added to the manager.
                 *
                 * @memberof ManagerBase
                 * @instance
                 * @param {Object} obj
                 * @returns {boolean}
                 */
                isAddable: function (obj) {
                    return !!this.getIdx(obj);
                },


                /**
                 * get an Object that is specified in the path
                 * Warnning: which was replaced by the '/' '.'.
                 *           no need for root $
                 *
                 * @see https://github.com/s3u/JSONPath
                 * @memberof ManagerBase
                 * @instance
                 * @param {String} path
                 * @returns {Object}
                 */
                get: function get(path) {
                    if (path === undefined || typeof(path) !== 'string') {
                        return undefined;
                    }

                    if (/^\/$/.test(path)) {
                        return this.objs;
                    }

                    var self = this;
                    path = '$' + path.replace(/\//g, '.');
                    var result = jsonPath(
                        this.objs,
                        path,
                        {wrap: false},
                        function testAddable(obj) {
                            return self.isAddable(obj);
                        });
                    if (!result) {
                        return undefined;
                    }
                    return result;
                },


                /**
                 * get the parent. If obj is an array: I get the information from the parent of the first element
                 *
                 * @memberof ManagerBase
                 * @instance
                 * @param {Object|Array.<Object>} obj
                 */
                getParent: function getParent(obj) {
                    if (_.isArray(obj)) {
                        return this.get(obj[0].prefix);
                    }
                    return this.get(obj.prefix);
                },


                /**
                 * will remove from the parent, a reference to objct specified.
                 *
                 * @memberof ManagerBase
                 * @instance
                 * @param {Object|Array.<Object>} obj
                 */
                deleteFromParent: function deleteFromParent(obj) {
                    if (!obj) {
                        return;
                    }

                    var parent = this.getParent(obj);
                    if (_.isArray(obj)) {
                        delete parent[this.getIdx(obj[0])];
                    } else {
                        delete parent[this.getIdx(obj)];
                    }
                },


                /**
                 * get the child list of just under
                 *
                 * @memberof ManagerBase
                 * @instance
                 * @param {Object} obj
                 * @return {Array.<Object>}
                 */
                getChildren: function getChildren(obj) {
                    var result = [];
                    var self = this;

                    var _walk = function _walk(list) {
                        _.each(list, function (item) {
                            if (!item) {
                                return;
                            }

                            if (_.isArray(item)) {
                                _walk(item);
                            } else if (self.getIdx(item)) {
                                result.push(item);
                            }
                        });
                    };

                    _walk(obj);
                    return result;
                },


                /**
                 * You get as an array all the specified Object (recursively)
                 *
                 * @memberof ManagerBase
                 * @param {Object} data
                 * @return {Array.<Object>}
                 */
                getChildrenAll: function getChildrenAll(data) {
                    var result = [];
                    var self = this;

                    var _walk = function _walk(obj) {
                        var list = obj;
                        if (!_.isArray(obj)) {
                            list = _.values(obj);
                        }
                        _.each(list, function (item, idx) {
                            if (!item) {
                                return;
                            }
                            if (_.isArray(item)) {
                                _walk(item);

                            } else if (self.getIdx(item)) {

                                if (!item.prefix || !item.manager) { // Item that is not managed to ignore
                                    logger.warn("Manager ignore the Object haven't been manaegd.", item);
                                    // result.push(item); // Do not ignore
                                    return;
                                }

                                // Ignore the member variable Object has set manually by user.
                                if (obj[self._idxProp] !== '$' && !_.isArray(obj) && item.getParent()[self._idxProp] !== obj[self._idxProp]) {
                                    logger.warn("Manager ignore the Object haven't been manaegd.",
                                                'Path that is managed:', self.pathOf(item), // The paths managed the Object of interest
                                                'Path to the specified:', self.pathOf(obj) // The actual path
                                                );
                                    return;
                                }
                                _walk(item); // Child is at the beginning of the Array
                                result.push(item);

                            }
                        });
                    };

                    // walk start
                    _walk(data);
                    return result;
                },


                /**
                 * Returns the path of the Object being managed. If the Object is array, returns the first element.
                 *
                 * @memberof ManagerBase
                 * @param {String} prefix
                 * @param {Object|Array} obj
                 * @throw {Error} obj is empty array
                 * @throw {Error} object.prefix does not exist
                 * @return {String}
                 */
                pathOf: function pathOf(obj) {
                    var prefix = '';
                    if (_.isArray(obj)) {
                        if (_.isEmpty(obj)) {
                            throw new beez.Error('pathOf: obj is empty array.');
                        }
                        obj = obj[0];
                    }

                    prefix = obj.prefix;

                    if (!prefix) {
                        throw new beez.Error('pathOf: object.prefix does not exist.');
                    }
                    return prefix + ((/^\/$/.test(prefix)) ? '' : '/') + this.getIdx(obj);
                },


                /**
                 * Returns the information Objects are managed.
                 *
                 * @memberof ManagerBase
                 * @return {Object}
                 */
                trace: function trace() {

                    var pairs = {};

                    // all children
                    var all = this.getChildrenAll(this.objs || {});

                    // for each child, make path & store
                    var self = this;
                    _.each(all, function (obj) {

                        if (!obj) {
                            return;
                        }

                        // make path
                        var key;
                        if (obj.prefix === '/') { // if parent is root
                            key = obj.prefix + self.getIdx(obj);
                        } else {
                            key = obj.prefix + '/' + self.getIdx(obj);
                        }

                        // store
                        if (pairs[key]) { // if already exists
                            if (!_.isArray(pairs[key])) {
                                // at first time, make array
                                pairs[key] = [pairs[key]];
                            }
                            pairs[key].push(obj); // push
                        } else {
                            // as sigle object
                            pairs[key] = obj;
                        }
                    });

                    return pairs;
                },
                dispose: function dispose() {
                    delete this.objs;
                    delete this._idxProp;
                }
            }
        );

        // -------------------
        // Base

        /**
         * This is the base class of an Object managed by the Manager.
         *
         * @class
         * @name Base
         */
        var Base = beez.extend(
            'beez.mvcr.Base',
            function Base() {},
            {
                /**
                 * get the first element. Gets the parent. If object is an array, sets the first
                 *
                 * @memberof Base
                 * @instance
                 */
                getParent: function getParent() {
                    return this.manager.getParent(this);
                },

                /**
                 * delete the reference of Object from a parent
                 *
                 * @memberof Base
                 * @instance
                 */
                deleteFromParent: function deleteFroParent() {
                    return this.manager.deleteFromParent(this);
                },

                /**
                 * I acquire a list of children underneath.
                 *
                 * @memberof Base
                 * @instance
                 * @return {Array.<Object>}
                 */
                getChildren: function getChildren() {
                    return this.manager.getChildren(this);
                },

                /**
                 * I acquire all Object of the descendant as an arrangement.
                 *
                 * @memberof Base
                 * @instance
                 * @return {Array.<Object>}
                 */
                getChildrenAll: function getChildrenAll() {
                    return this.manager.getChildrenAll(this);
                },


                /**
                 * Sets the object beneath the specified prefix.
                 *
                 * @memberof Base
                 * @param {String} prefix prefix name
                 */
                alias: function alias(prefix) {
                    return this.manager.add(prefix, this);
                }
            }
        );

        return {
            ManagerBase: ManagerBase,
            Base: Base
        };

    });
示例#5
0
文件: controller.js 项目: fkei/beez
    define(function __Controller__(require, exports, module) {
        'use strict';

        var beez = require('beez.core');
        require('beez.mvcr');
        require('beez.i18n');

        var logger = beez.getLogger('beez.mvcr.controller');

        var _ = beez.vendor._;

        // -------------------
        // ControllerManagerAsync

        /**
         * Controller management class, asynchronous
         *
         * @class
         * @name ControllerManagerAsync
         * @private
         * @param {ControllerManager} manager
         * @extends {Bucks}
         */
        var ControllerManagerAsync = beez.Bucks.extend(
            'beez.mvcr.ControllerManagerAsync',
            {
                /**
                 * Constructor
                 *
                 * @memberof ControllerManagerAsync
                 * @instance
                 */
                initialize: function initialize(manager) {
                    this.manager = manager;
                },

                /**
                 * Generation of the Controller
                 *
                 * @memberof ControllerManagerAsync
                 * @instance
                 * @param {String} prefix
                 * @param {Controller|Array<Controller>} Controller Controller Object
                 * @param {Object|Array<Object>} [options] Arguments to the Controller
                 * @return {Controller}
                 */
                create: function create(name, Controller, options) {
                    var self = this;
                    return this.then(function createWrap(result, next) {

                        if (!Controller || typeof Controller !== 'function') {
                            throw new beez.Error('Controller does not exist / does not be funciton. Specified name: ' + name);
                        }
                        if (self.manager.controllers[name]) {
                            throw new beez.Error('It is a singleton in the module. name:' + name);
                        }

                        var controller = new Controller();
                        self.manager.controllers[name] = controller;
                        next(result, self.manager.controllers[name]);

                    }).then(function (controller, next) {
                        controller.loadCSS(function () { // initialize css load
                            next(null, controller);
                        });

                    }).then(function (controller, next) {
                        controller.loadI18n(function (err) { // initialize i18n load
                            if (err) {
                                logger.error('i18n load error. ', err.message);
                                logger.debug(err.stack);
                            }
                            next(err, controller);
                        });
                    });
                },

                /**
                 * Disposes of the instance
                 *
                 * @memberof ControllerManagerAsync
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');
                    delete this.manager;
                }
            }
        );

        // -------------------
        // ControllerManager

        /**
         * Controller management class.
         *
         * @class
         * @name ControllerManager
         */
        var ControllerManager = beez.extend(
            'beez.mvcr.ControllerManager',
            function constructor() {
                return this.initialize();
            },
            {
                /**
                 * Constructor
                 *
                 * @memberof ControllerManager
                 * @instance
                 */
                initialize: function initialize() {
                    this.controllers = {};
                },

                /**
                 * Generating ControllerManagerAsync
                 *
                 * @memberof ControllerManager
                 * @instance
                 * @return {ControllerAsync}
                 */
                async: function async() {
                    return new ControllerManagerAsync(this);
                },

                /**
                 * Remove controller
                 *
                 * @memberof ControllerManager
                 * @instance
                 * @param {String} name jsonPath name
                 * @return {ControllerManager}
                 */
                remove: function remove(name) {
                    var obj = this.get(name);
                    if (!obj) {
                        return this;
                    }
                    delete this.controllers[name];
                    return this;
                },

                /**
                 * From path, acquire Controller.
                 *
                 * @memberof ControllerManager
                 * @instance
                 * @param {String} name jsonPath name
                 * @return {Controller}
                 */
                get: function get(name) {
                    return this.controllers[name];
                },

                /**
                 * Disposes of the instance
                 *
                 * @memberof ControllerManager
                 * @instance
                 */
                dispose: function () {
                    logger.trace(this.constructor.name, 'dispose');
                    delete this.controllers;
                }
            });


        // -------------------
        // Controller

        /**
         * Controller class.
         *
         * @namespace beez.mvcr
         * @class
         * @name Controller
         */
        var Controller = beez.extend(
            'beez.mvcr.Controller',
            function constructor() {
                this.initialize.apply(this, arguments);
            },
            {

                /**
                 * Constructor
                 *
                 * @memberof Controller
                 * @instance
                 */
                initialize: function initialize() {
                },

                /**
                 * automatic loading of i18n data.
                 * @memberof Controller
                 * @param {function} callback
                 */
                i18n: function i18n() {},

                /**
                 * automatic loading of i18n.
                 *
                 * @memberof Controller
                 * @param {function} callback Completion callback
                 * @instance
                 * @return {Controller}
                 */
                loadI18n: function loadI18n(callback) {
                    if (!beez.i18n) {
                        beez.createI18n();
                    }

                    var self = this;
                    if (beez.utils.is('Object', this.i18n)) { // dynamic load

                        var langs = [];
                        var paths = [];
                        _.each(this.i18n, function (path, lang) {
                            langs.push(lang);
                            paths.push(path);
                        });

                        require(paths, function () {
                            var list = Array.prototype.slice.call(arguments);
                            for (var i = 0; i < list.length; i++) {
                                var data = {};
                                data[langs[i]] = list[i];
                                beez.i18n.add(data);
                                logger.debug('i18n file loaded. path:', paths[i]);
                            }
                            callback && callback(null);
                        }, function (err) {
                            callback && callback(err);
                        });

                    } else if (beez.utils.is('Function', this.i18n)) { // static load
                        new beez.Bucks()
                            .add(function (err, res, next) {
                                if (0 < self.i18n.length) {
                                    self.i18n(function (err, res) {
                                        next(err, res);
                                    });
                                } else {
                                    next(null, self.i18n());
                                }
                            })
                            .add(function (err, res) {
                                if (res) {
                                    beez.i18n.add(res);
                                }
                                callback && callback(err, res);
                            })
                            .end();

                    } else {
                        callback && callback(new Error('The Controller.i18n, please be defined in Function.'));
                    }
                    return this;

                },

                /**
                 * automatic loading of css.
                 *
                 * @memberof Controller
                 * @param {function} callback Completion callback
                 * @instance
                 * @return {Controller}
                 */
                loadCSS: function loadCSS(callback) {
                    var paths = this.css;
                    if (!paths || paths.length < 1) {
                        return callback && callback();
                    }

                    var self = this;
                    var tasks = _.map(paths, function task(p) {
                        return function t(err, res, next) {
                            beez.manager.css.async()
                                .load(p)
                                .end(function (err1, res1) {
                                    next(err, res1[0]);
                                }, function (err2) {
                                    next(err2);
                                });
                        };
                    });

                    var b = new beez.Bucks();
                    b.parallel(tasks)
                        .end(function (err, ress) {
                            callback && callback(err, ress);
                        });

                    return this;
                },

                /**
                 * Disposes of the instance
                 *
                 * @memberof Controller
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');
                    delete this.constructor.prototype.css;
                }
            }
        );


        /**
         * extend function
         *
         * @memberof Controller
         * @function
         * @param {String} [name] instance name
         * @param {Object} childProto prototypes
         * @borrows beez.extendThis as extend
         * @example
         * var MyController = Controller.extend(
         *     'myapp.MyController',
         *     {
         *         bar: function bar() {}
         *     }
         * );
         */
        Controller.extend = beez.extendThis;

        return {
            Controller: Controller,
            ControllerManager: ControllerManager,
            ControllerManagerAsync: ControllerManagerAsync
        };
    });
示例#6
0
文件: beez.utils.js 项目: Layzie/beez
    define('beez-utils/browser',['require','exports','module','beez.core','backbone','beez.ua'],function (require, exports, module) {
        

        var beez = require('beez.core');
        var global = beez.global || global;

        var _ = beez.vendor._;
        var $ = beez.vendor.$;

        var Backbone = require('backbone');

        /**
         * ブラウザの情報を取得するchainです。
         * ブラウザの情報は取得するためにdelayが必要な場合があり、
         * そのような情報をasync chainの形で取得できるようになっています
         * @class
         * @name BrowserAsync
         */
        var BrowserAsync = beez.Bucks.extend(
            'beez.utils.BrowserAsync',
            {
                initialize: function initialize(browser) {
                    this.browser = browser;
                },

                dispose: function dispose() {
                    delete this.browser;
                },

                /**
                 * アドレスバーを隠します
                 * delayをかけるのでonload時などに呼んでも動作します
                 * @memberof BrowserAsync
                 * @param {int} delay delay time(ms)
                 * @instance
                 * @return {BrowserAsync}
                 */
                hideAddress: function hideAddress(delay) {
                    delay = delay || 100;
                    return this
                        .delay(delay) // delayを挟む
                        .then(function scroll() {
                            window.scroll(0, 0);
                        });
                }

                /**
                 * 指定したelementのcomputedStyleを返します
                 * @memberof BrowserAsync
                 * @instance
                 * @param {HTMLElement} elem
                 * @return {BrowserAsync}
                 */
                //getComputedStyle: function getComputedStyle(elem) {
                //    var self = this;
                //    return this.then(function chainValue() {
                //        return self.browser.getComputedStyleSync(elem);
                //    });
                //},

                /**
                 * windowサイズを返します
                 * @memberof BrowserAsync
                 * @instance
                 * @return {BrowserAsync}
                 */
                //getWindowSize: function getWindowSize() {
                //    var self = this;
                //    return this.then(function chainValue() {
                //        return self.browser.getWindowSizeSync();
                //    });
                //}
            });

        var __Browser__ = {
            _prevOrientation: global.orientation,
            _initOrientation: global.orientation,

            /**
             * @memberof Browser
             * @instance
             */
            initialize: function initialize() {
                this.startHandleOrientation();
            },

            /**
             * 画面の回転イベントのbindを開始します。
             * @memberof Browser
             * @instance
             */
            startHandleOrientation: function startHandleOrientation() {
                // Androids don't have orientation change event
                var evName = ('onorientationchange' in window) ? 'orientationchange' : 'resize';
                // listen window's event
                var self = this;
                $(global).on(evName, function (ev) {
                    var o = global.orientation;

                    if (self._prevOrientation !== o) {
                        // trigger event
                        self.trigger(
                            'change:orientation',
                            {
                                prev: self._prevOrientation,
                                current: o,
                                init: self._initOrientation === o ? true : false
                            }
                        );
                        self._prevOrientation = o;
                    }
                });
            },

            /**
             * 指定されたelementのcomputedStyleを返します
             */
            getComputedStyle: function getComputedStyle(elem) {
                return document.defaultView.getComputedStyle(elem, '');
            },

            /**
             * 指定されたelementのcomputedStyleを返すchainを返します
             * then(callback)で値を受け取れます
             */
            //getComputedStyle: function getComputedStyle(elem) {
            //    return new BrowserAsync(this).getComputedStyle(elem);
            //},
            async: function async() {
                return new BrowserAsync(this);
            },

            /**
             * Addressbarを隠すchainを返します
             */
            hideAddress: function hideAddress(delay) {
                return new BrowserAsync(this).hideAddress(delay);
            },

            /**
             * windowサイズを返すchainを返します。
             * then(callback)で値を受け取れます
             *
             */
            //getWindowSize: function getWindowSize() {
            //    return new BrowserAsync(this).getWindowSize();
            //},

            /**
             * windowサイズを返します
             */
            getWindowSize: function getWindowSize() {
                return {width: window.innerWidth, height: window.innerHeight};
            },

            /**
             * @memberof Browser
             * @borrows Browser~ua as Browser#ua
             * @type {Browser~ua}
             */
            ua: {}, // injected below

            /**
             * Navigator Language default) 'en'
             * @memberof Browser
             * @return  {String}
             */
            getLanguage: function getLanguage() {
                var lang = navigator.language || navigator.browserLanguage || navigator.systemLanguage || navigator.userLanguage;

                // android 2.3 only!!!!
                if (this.ua.android23 && ua.browser.lang) {
                    return ua.browser.lang;
                }

                if (!lang) {
                    return undefined;
                }
                return lang.substr(0, 2);
            }
            //ua: require('beez.ua')
        };

        var ua = require('beez.ua');
        ua.setup(); // default browser useragent

        __Browser__.ua = ua;

        /**
         * ブラウザ情報の取得のためのクラスです。
         * 画面方向が変わるとchange:orientation イベントを発します
         * @class
         * @name Browser
         * @extends {Backbone.Events}
         */
        var Browser = beez.extend(
            'beez.utils.Browser',
            function Browser() {},
            Backbone.Events,
            __Browser__
        );

        return Browser;

    });
示例#7
0
文件: beez.utils.js 项目: Layzie/beez
    define('beez.utils',['require','exports','module','beez.core','beez-utils/browser','beez-utils/timer'],function (require, module, exports) {
        

        var beez = require('beez.core');
        var _ = beez.vendor._;

        var logger = beez.getLogger('beez.utils');

        // double load check
        if (beez.utils) {
            logger.warn('beez.utils already defined.');
            return beez.utils;
        }

        var __Utils__ = {
            initialize: function initialize(opts) {
                var Browser = require('beez-utils/browser');
                var Timers = require('beez-utils/timer');

                /**
                 * instance of Browser
                 * @name browser
                 * @memberof beez.utils
                 * @type {Browser}
                 */
                this.browser = new Browser();

                /**
                 * class of Timers
                 * @name Timers
                 * @memberof beez.utils
                 * @type {Timers}
                 */
                this.Timers = Timers;

                this.none = beez.none;

                /**
                 * pixel ratio
                 *
                 * @name pixelRatio
                 * @memberof beez.utils
                 * @type {Timers}
                 */
                this.pixelRatio = global.devicePixelRatio || 1;
                //this.htmlRatio = this.pixelRatio;
            },
            /**
             * recursively copy the properties of src to dst
             * dst properties = object : merge
             * other properties (array, string, number .. ) : override
             *
             * @name copyr
             * @memberof beez.utils
             * @param {Object} dst
             * @param {Object} src
             * @return Object
             */
            copyr: function copyr(dst, src) {

                // for each props in src
                for (var k in src) {
                    var dstProp = dst[k];
                    var srcProp = src[k];
                    if (_.isObject(dstProp) && !_.isArray(srcProp)) {
                        copyr(dst[k], src[k]); // cp recursively
                    } else {
                        dst[k] = src[k]; // override/add property 'k'
                    }
                }
                return dst;
            },
            /**
             * To determine the type.
             *
             * @name is
             * @memberof beez.utils
             * @param {String} type
             * @param {Object} obj
             * @return boolean
             * @example
             * > beez.utils.is('Null'null) => true
             * > beez.utils.is('Array', []) => true
             * > beez.utils.is('Function', function () {}) => true
             * > beez.utils.is('String', "") => true
             * > beez.utils.is('Number', 1) => true
             * > beez.utils.is('Boolean', true) => true
             * > beez.utils.is('Number', Date.now()) => true
             * > beez.utils.is('RegExp', /^$/) => true
             * > beez.utils.is('Null', null) => true
             * > beez.utils.is('Undefined', undefined) => true
             *
             */
            is: function is(type, obj) {
                var clas = Object.prototype.toString.call(obj).slice(8, -1);
                return obj !== undefined && obj !== null && clas === type;
            }
        };


        var Utils = beez.extend(
            'beez.Utils',
            function constructor() {
                return this.initialize();
            }, __Utils__);

        // shortcut funciton os 'underscore.js#isXXX' function
        _.each(['Equal', 'Empty', 'Element', 'Arguments', 'Function', 'String', 'Number', 'Finite', 'Boolean', 'Date', 'RegExp', 'NaN', 'Null', 'Undefined'], function (type) {
            Utils.prototype['is' + type] = _['is' + type];
        });

        // shortcut function of 'is()' function
        _.each(['Object', 'Array'], function (type) {
            Utils.prototype['is' + type] = function (obj) {
                return this.is.apply(this, [type, obj]);
            };
        });

        beez.utils = new Utils();

        return beez.utils;
    });
示例#8
0
文件: beez.utils.js 项目: Layzie/beez
    define('beez-utils/timer',['require','exports','module','beez.core','beez-utils/uid'],function (require, exports, module) {
        

        var beez = require('beez.core');
        var _ = beez.vendor._;
        var logger = beez.getLogger('timer');

        var UID = require('beez-utils/uid');
        var uid = new UID();

        var BEEZ_TIMER_ID_PROP = 'beez_utils_timer_id';

        /**
         * setIntervalひとつに複数のtimerを設定できる仕組みです。
         * 現在は誤差100msとなっています
         */
        var Timers = function () {
            this.running = false;
            this._callbacks = {};
            this._timerId = 0;
        };

        Timers.prototype = {

            /**
             * timeoutを追加する。
             * @param {Function} callback
             * @param {int} ms millisecond to timeout
             * @param {Object} context
             * @return {string} timerId
             */
            addTimeout: function addTimeout(callback, ms, context) {
                var id = uid.create();
                callback[BEEZ_TIMER_ID_PROP] = id;
                var callbackInfo = {

                    timer_id: id,
                    callback: callback,
                    interval: ms,
                    time: Date.now() + ms,
                    context: context,
                    type: 'timeout',
                    canceller: function canceller() {
                        this.type = 'canceled';
                    }
                };

                //_.bindAll(callbackInfo);
                _.bindAll.apply(this, [callbackInfo].concat(_.methods(callbackInfo)));

                this._callbacks[id] = callbackInfo;
                this.start();

                return id;
            },

            /**
             * intervalを追加する。
             * @param {Function} callback
             * @param {Object} context
             * @return {String} timerId
             */
            addInterval: function addInterval(callback, ms, context) {
                var id = uid.create();
                callback[BEEZ_TIMER_ID_PROP] = id;
                var callbackInfo = {
                    timer_id: id,
                    callback: callback,
                    interval: ms,
                    time: Date.now() + ms,
                    context: context,
                    type: 'interval',
                    canceller: function canceller() {
                        this.type = 'canceled';
                    }
                };

                //_.bindAll(callbackInfo);
                _.bindAll.apply(this, [callbackInfo].concat(_.methods(callbackInfo)));

                this._callbacks[id] = callbackInfo;
                this.start();

                return id;
            },

            /**
             * intervalを解除します
             * @param {Function|String} fnOrId addIntervalしたfunction, もしくは
             * その際に返ったtimer_id
             */
            clearInterval: function clearInterval(fnOrId) {
                var id;
                if (typeof fnOrId === 'function' && fnOrId[BEEZ_TIMER_ID_PROP]) {
                    id = fnOrId[BEEZ_TIMER_ID_PROP];
                } else {
                    id = fnOrId;
                }

                var callbackInfo = this._callbacks[id];
                if (!callbackInfo) {
                    throw new Error('no callback to clear');
                }
                callbackInfo.canceller();
            },

            /**
             * timeoutを解除します。clearIntervalと違うのは
             * すでにtimeoutしているなどしてclearしようとしたタイマーが
             * 存在しなかった場合も静かに無視します。
             * @param {Function|String} fnOrId addTimerしたfunction, もしくは
             * その際に返ったtimer_id
             */
            clearTimeout: function clearInterval(fnOrId) {
                var id;
                if (typeof fnOrId === 'function' && fnOrId[BEEZ_TIMER_ID_PROP]) {
                    id = fnOrId[BEEZ_TIMER_ID_PROP];
                } else {
                    id = fnOrId;
                }

                var callbackInfo = this._callbacks[id];
                if (!callbackInfo) {
                    return;
                }
                callbackInfo.canceller();

            },

            _tick: function _tick() {

                var now = Date.now();

                var self = this;
                _.each(this._callbacks, function (info) {
                    if (info.time < now) { // fire
                        if (info.type !== 'canceled') {
                            if (info.context) {
                                info.callback.call(null, info.context);
                            } else {
                                info.callback.call();
                            }
                        }
                        if (info.type !== 'interval') {
                            delete self._callbacks[info.timer_id];
                        }

                        info.time = now + info.interval;
                    }

                    return true;
                });

                if (!_.keys(this._callbacks).length) {
                    this.stop();
                }
            },

            /**
             * timerをstartします。通常はaddTimeout/addIntervalした際に
             * 自動的に実行されるので直接実行する必要はありません
             */
            start: function start() {
                if (this.running) {
                    return;
                }

                this.running = true;
                var self = this;

                var tickWrapper = function tickWrapper() {
                    if (self.running) {
                        self._tick();
                        self._timerId = setTimeout(tickWrapper, 100); // @TODO
                    }
                };
                tickWrapper();
            },

            /**
             * timerをstopします。またtimeoutが実行され終わったり
             * clearTimeout/clearIntervalによって実行待ちのコールバックが
             * ひとつも無くなった場合は自動的にstopが実行されます
             */
            stop: function stop() {
                this.running = false;
                clearTimeout(this._timerId);
            }
        };

        return Timers;
    });
示例#9
0
文件: view.js 项目: CyberAgent/beez
    define(function __View__(require, exports, module) {
        'use strict';

        var beez = require('beez.core');
        require('beez.utils');

        var _ = beez.vendor._;
        var Backbone = require('backbone');

        var base = require('beez-mvcr/base');
        var Base = base.Base;
        var ManagerBase = base.ManagerBase;

        var logger = beez.getLogger('beez.mvcr.view');


        /**
         * View management class, asynchronous
         *
         * @class
         * @name Creator
         * @extends {Bucks}
         */
        var ViewManagerAsync = beez.Bucks.extend(
            'beez.mvcr.ViewManagerAsync',
            {
                initialize: function initialize(manager) {
                    this.manager = manager;
                },

                /**
                 * set root
                 *
                 * @memberof ViewManagerAsync
                 * @instance
                 * @param {View} root vidx is '@' must
                 * @return {ViewManagerAsync}
                 */
                root: function root(root) {
                    var self = this;
                    return this.then(function () {
                        return self.manager.root(root);
                    });
                },

                /**
                 * Generate View.
                 *
                 * @memberof ViewManagerAsync
                 * @instance
                 * @param {String} prefix parent prefix
                 * @param {View|Array<View>} View Generate View object(s).
                 * @param {Object} [options] Argument of the View object.
                 * @return {ViewManagerAsync}
                 */
                create: function create(prefix, View, options) {
                    var self = this;
                    return this.then(function () {
                        var v =  self.manager.create(prefix, View, options);
                        var current = _.isArray(v) ? v[0] : v;
                        return current;
                    });
                },

                /**
                 * View is generated as a child of the View object generated before the chain.
                 *
                 * @memberof ViewManagerAsync
                 * @instance
                 * @param {View|Array<View>} View Generate View object.
                 * @param {Object} [options] Argument of the View object.
                 * @return {ViewManagerAsync}
                 */
                child: function child(View, options) {
                    var self = this;
                    return this.then(function (current) {
                        var prefix = self.manager.pathOf(current);
                        var v = self.manager.create(prefix, View, options);
                        current = _.isArray(v) ? v[0] : v;
                        return current;
                    });
                },

                /**
                 * Get the parent View.
                 *
                 * @memberof ViewManagerAsync
                 * @instance
                 * @return {ViewManagerAsync}
                 */
                parent: function parent() {
                    var self = this;
                    return this.then(function (current) {
                        var parent = self.manager.getParent(current);
                        if (parent) {
                            throw new beez.Error('get parent failed. current: ' + current);
                        }
                        current = parent;
                        return current;
                    });
                },

                /**
                 * The child and its brother of the parents of View.
                 *
                 * @memberof ViewManagerAsync
                 * @instance
                 * @param {object} [options] Argument of the View object.
                 * @return {Creator}
                 */
                bro: function bro(brother, options) {
                    return this.parent().child(brother, options);
                },

                /**
                 * Disposes of the instance
                 *
                 * @memberof ViewManagerAsync
                 * @override called when this chain ended
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');
                    delete this.manager;
                    delete this.current;
                    delete this.root;
                }
            }
        );

        /**
         * ViewManager Class
         *
         * @class
         * @name ViewManager
         */
        var ViewManager = beez.extend(
            'beez.mvcr.ViewManager',
            ManagerBase,
            {

                /**
                 * Constructor
                 *
                 * @memberof ViewManager
                 * @instance
                 */
                initialize: function initialize() {
                    ViewManager.__super__.initialize.apply(this, arguments);
                },

                /**
                 * Generating ViewManagerAsync
                 *
                 * @memberof ViewManager
                 * @instance
                 * @return {ViewManagerAsync}
                 */
                async: function async() {
                    return new ViewManagerAsync(this);
                },

                /**
                 * Set the Root View
                 *
                 * @memberof ViewManager
                 * @instance
                 * @param {View} RootView vidx is '@' must
                 * @return {View}
                 */
                root: function root(RootView) {
                    this.add('/', new function DummyRootView() { this.vidx = '@'; });
                    var rootView = new RootView(this);
                    var rootChildren = this.getChildren(this.get("/@")); // save
                    this.remove('/@');

                    var root = this.get('/@');
                    if (root) {
                        throw new beez.Error('root already exists!');
                    }

                    if (rootView.vidx !== '@') {
                        throw new beez.Error('roots vidx must be "@"');
                    }

                    this.add('/', rootView);

                    // re-save
                    for (var i = 0; i < rootChildren.length; i++) {
                        this.add('/@', rootChildren[i]);
                    }

                    return rootView;
                },


                /**
                 * Generate View.
                 *
                 * @memberof ViewManager
                 * @instance
                 * @param {String} prefix parent prefix
                 * @param {View|Array<View>} View Generate View object(s).
                 * @param {Object} [options] Argument of the View object.
                 * @return {Array}
                 */
                create: function create(prefix, View, options) {
                    if (!View || (!_.isArray(View) && typeof View !== 'function')) {
                        throw new beez.Error('View does not exist / does not be funciton. Specified prefix: ' + prefix);
                    }

                    if (!prefix) {
                        throw new beez.Error('No prefix specified. Creating:' + View.name);
                    }

                    if (prefix.indexOf('/@') < 0) {
                        throw new beez.Error('prefix must started by "/@". Creating:' + View.name);
                    }

                    if (!this.get(prefix)) { // no parent
                        throw new beez.Error('no parent exists. prefix: ' + prefix + ' ,  Please consider constructing view in Controller, or in #beforeOnce and so on.');
                    }


                    if (_.isArray(View)) {
                        return this._createArray(prefix, View, options);
                    }

                    return this._createObj(prefix, View, options);
                },

                /**
                 * Generate View(Object).
                 *
                 * @memberof ViewManager
                 * @instance
                 * @private
                 */
                _createObj: function _createObj(prefix, View, options) {
                    var v = new View(this, options);
                    if (!this.isAddable(v)) {
                        throw new beez.Error('index does not exists in the View. :' + v);
                    }
                    this.add(prefix, v);
                    return v;
                },


                /**
                 * Generate View(Array).
                 *
                 * @memberof ViewManager
                 * @instance
                 * @private
                 */
                _createArray: function _createArray(prefix, Views, options) {
                    var self = this;
                    // forced array
                    if (options && !_.isArray(options)) {
                        options = [options];
                    }

                    var instances = [];
                    _.each(Views, function (C, idx) {  // new
                        var params = options ? options[idx] : undefined;
                        var v = new C(self, params);
                        instances.push(v);
                    });

                    _.each(instances, function (view) { // check
                        if (!this.isAddable(view)) {
                            throw new beez.Error('index does not exists in the View. :' + view);
                        }
                    }, this);

                    this.add(prefix, instances);
                    return instances;
                },

                /**
                 * remove
                 *
                 * @name remove
                 * @memberof ViewManager
                 * @instance
                 * @param {String} path
                 */
                remove: function remove(path) {
                    ViewManager.__super__.remove.apply(this, arguments);
                },

                /**
                 * Dispose view and self from management.
                 *
                 * @memberof ViewManager
                 * @instance
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');

                    var managedChildren = this.getChildrenAll(this.objs);

                    _.each(managedChildren, function (key) {
                        key.dispose();
                    });

                    ViewManager.__super__.dispose.apply(this, arguments);
                }
            }
        );

        // -------------------
        // View

        /**
         * View class Asynchronous
         *
         * @class
         * @name ViewAsync
         * @extends {Bucks}
         * @private
         */
        var ViewAsync = beez.Bucks.extend(
            'beez.mvcr.ViewAsync',
            {

                /**
                 * @memberof ViewAsync
                 * @param {View} root Root View
                 */
                initialize: function initialize(root) {
                    this._root = root;
                },

                /**
                 * Processing is performed by the flow of [beforeOnce -> before -> render -> after -> afterOnce].
                 *
                 * @memberof Renderer
                 * @instance
                 * @param {BeezView} view
                 * @param {boolen} [renderChildren=true]
                 */
                _render: function _render(view) {

                    // start with view
                    this.then(function () {
                        return view;
                    });

                    if (!view.state.isBeforeOnce) { // check flag
                        // call beforeOnce
                        this.then(function beforeOnce(view, next) {
                            if (!view.visible) {
                                logger.debug('view', view.vidx, 'is not visible. skip `beforeOnce`.');
                                next(null, view); // skip
                                return;
                            }

                            // if `beforeOnce` have `done` as a param
                            if (view.beforeOnce.length > 0) {
                                view.beforeOnce(function wrappedDone() {
                                    view.state.isBeforeOnce = true;
                                    next(null, view);
                                });
                                return;
                            }

                            // else exec as sync
                            view.beforeOnce();
                            view.state.isBeforeOnce = true;
                            next(null, view);
                        });
                    }


                    // call before
                    this.then(function before(view, next) {
                        if (!view.visible) {
                            logger.debug('view', view.vidx, 'is not visible. skip `before`.');
                            next(null, view); // skip
                            return;
                        }

                        // if `before` have `done` as a param
                        if (view.before.length > 0) {
                            view.before(function wrappedDone() {
                                next(null, view);
                            });
                            return;
                        }
                        // else exec as sync
                        view.before();
                        next(null, view);

                    });


                    // call render
                    this.then(function render(view, next) {
                        if (!view.visible) {
                            logger.debug('view', view.vidx, 'is not visible. skip `render`.');
                            next(null, view); // skil
                            return;
                        }

                        // if `render` have `done` as a param
                        if (view.render.length > 0) {
                            view.render(function wrappedDone() {
                                next(null, view);
                            });
                            return;
                        }

                        // else exec as sync
                        view.render();
                        next(null, view);
                        return;
                    });

                    // call after
                    this.then(function after(view, next) {
                        if (!view.visible) {
                            logger.debug('view', view.vidx, 'is not visible. skip `after`.');
                            next(null, view); // skip
                            return;
                        }

                        // if `afterOnce` have `done` as a param
                        if (view.after.length > 0) {
                            view.after(function wrappedDone() {
                                next(null, view);
                            });
                            return;
                        }

                        // else exec as sync
                        view.after();
                        next(null, view);
                        return;
                    });

                    if (!view.state.isAfterOnce) { // check flag

                        // call afterOnce
                        this.then(function afterOnce(view, next) {
                            if (!view.visible) {
                                logger.debug('view', view.vidx, 'is not visible. skip `afterOnce`.');
                                next(null, view); // skip
                                return;
                            }

                            // if `afterOnce` have `done` as a param
                            if (view.afterOnce.length > 0) {
                                view.afterOnce(function wrappedDone() {
                                    view.state.isAfterOnce = true;
                                    next(null, view);
                                });

                                return;
                            }

                            // else exec as sync
                            view.afterOnce();
                            view.state.isAfterOnce = true;
                            next(null, view);
                            return;
                        });
                    }

                    this.then(function rendered(view, next) {
                        if (!view.visible) {
                            logger.debug('view', view.vidx, 'is not visible. skip trigger events beez:view:render');
                            next(null, view);
                            return;
                        }
                        logger.debug('view', view.vidx, 'is rendered. trigger beez:view:render');
                        view.trigger('beez:view:render');
                        next(null, view);
                        return;
                    });

                    return this;
                },


                /**
                 * Delete the View.
                 *
                 * @memberof ViewAsync
                 * @instance
                 * @param {View} view
                 * @return {View}
                 */
                _remove: function _remove(view) {

                    this.then(function () {
                        return view;
                    });

                    this.then(function conceal(view, next) {
                        // if `conceal` have `done` as a param
                        if (view.conceal.length > 0) {
                            view.conceal(function wrappedDone() {
                                next(null, view);
                            });
                            return;
                        }
                        // else exec as sync
                        view.conceal();
                        next(null, view);
                        return;
                    });

                    this.then(function remove(view, next) {
                        view.remove();
                        logger.debug('view', view.vidx, 'is removed. trigger beez:view:remove');
                        view.trigger('beez:view:remove');
                        next(null, view);
                        return;
                    });

                    return this;

                },


                /**
                 * Handles the rendering of the View.
                 * Child elements are rendered.
                 *
                 * visible=false : Skip the rendering, including the child elements.
                 * showChildren=false : Only the specified view is rendered, child elements are not rendered.
                 *
                 * @memberof ViewAsync
                 * @instance
                 * @public
                 * @param {boolean} [options.showChildren=true] if not show children, set false
                 * @param {Function} options.filter show filtered view by the function 
                 * @return {ViewAsync}
                 * @throws {beez.Error} render root is not set
                 */
                show: function show(options) {
                    if (!this._root) {
                        throw new beez.Error('render root is not set. initialize renderer with root view parameter.');
                    }
                    options = options || {};

                    // TODO: Put out in the future 
                    if (beez.utils.isBoolean(options)) {
                        options = {
                            showChildren: options
                        };
                    }

                    if (options.showChildren === undefined) {
                        options.showChildren = true;
                    }

                    return this._show(this._root, options);
                },


                /**
                 * Handles the rendering of the View.
                 * Child elements are rendered.
                 *
                 * visible=false : Skip the rendering, including the child elements.
                 * showChildren=false : Only the specified view is rendered, child elements are not rendered.
                 *
                 *
                 * @memberof ViewAsync
                 * @instance
                 * @private
                 * @param {View} view view to show
                 * @param {boolean} [options.showChildren=true] if not show children, set false
                 * @param {Function} options.filter show filtered view by the function 
                 * @return {ViewAsync}
                 */
                _show: function _show(view, options) {
                    logger.debug('showing', view.vidx);

                    var self = this;
                    var children = view.getChildren();

                    if (options.filter) {
                        logger.debug('filtering', view.vidx);
                        children = _.filter(children, options.filter);
                    }

                    this._render(view);

                    if (children.length > 0 && options.showChildren) {
                        children.sort(function (a, b) {
                            if (a.order < b.order) {
                                return -1;
                            }
                            if (a.order > b.order) {
                                return 1;
                            }

                            return 0;
                        });

                        _.each(children, function (v) {
                            self._show(v, options);
                        });
                    }

                    return this;
                },


                /**
                 * Handles the rendering of the View.
                 * Child elements are rendered.
                 *
                 * want to hide the View. And hide also to the child element
                 * hideChildren=false: Child element is not hidden.
                 *
                 * @memberof ViewAsync
                 * @instance
                 * @private
                 * @param {View} view view to hide
                 * @param {boolean} [options.hideChildren=true] if set false, children not be removed
                 * @param {Function} options.filter hide filetered view by the function 
                 * @return {ViewAsync}
                 */
                hide: function hide(options) {
                    if (!this._root) {
                        throw new beez.Error('render root is not set. initialize renderer with root view parameter.');
                    }
                    options = options || {};

                    // TODO: Put out in the future 
                    if (beez.utils.isBoolean(options)) {
                        options = {
                            hideChildren: options
                        };
                    }

                    if (options.hideChildren === undefined) {
                        options.hideChildren = true;
                    }
                    return this._hide(this._root, options);
                },


                /**
                 * Handles the rendering of the View.
                 * Child elements are rendered.
                 *
                 * want to hide the View. And hide also to the child element
                 * hideChildren=false: Child element is not hidden.
                 *
                 * @memberof ViewAsync
                 * @instance
                 * @private
                 * @param {View} view view to hide
                 * @param {boolean} [options.hideChildren=true] if set false, children not be removed
                 * @param {Function} options.filter hide filetered view by the function 
                 * @return {ViewAsync}
                 */
                _hide: function _hide(view, options) {
                    logger.debug('hiding', view.vidx);

                    var self = this;
                    var children = view.getChildren();

                    if (options.filter) {
                        logger.debug('filtering', view.vidx);
                        children = _.filter(children, options.filter);
                    }

                    if (children.length > 0 && options.hideChildren) {
                        children.sort(function (a, b) {
                            if (a.order < b.order) {
                                return 1;
                            }
                            if (a.order > b.order) {
                                return -1;
                            }

                            return 0;
                        });
                        _.each(children, function (v) {
                            self._hide(v, options);
                        });
                    }

                    // case of single view
                    logger.debug('hiding', view.vidx);
                    this._remove(view);

                    return this;
                },

                /**
                 * Disposes of the instance
                 *
                 * @memberof ViewAsync
                 * @instance
                 */
                dispose: function dispopse() {
                    logger.trace(this.constructor.name, 'dispose');
                    delete this._root;
                }

            }
        );

        /**
         * View class
         *
         * @namespace beez.mvcr
         * @class
         * @name View
         * @extends {Backbone.View}
         * @see Backbone.View
         */
        var View = beez.extend(
            'beez.mvcr.View',
            Base,
            Backbone.View.prototype,
            {

                /**
                 * Constructor
                 *
                 * @memberof View
                 */
                constructor: function constructor() {
                    if (arguments.length < 1) {
                        throw new beez.Error('In order to create a View, requires one arguments.');
                    }
                    this.manager = arguments[0];

                    /**
                     * Management flag
                     * @memberof View
                     */
                    this.state = {
                        isBeforeOnce: false,
                        isAfterOnce: false
                    };

                    /**
                     * Skip rendering flag
                     *
                     * @memberof View
                     * @instance
                     * @property visible
                     * @type {boolean}
                     */
                    this.visible = true;

                    View.__super__.constructor.apply(this, Array.prototype.slice.call(arguments, 1));
                },

                /**
                 * call initialize method
                 *
                 * @memberof View
                 * @name initialize
                 * @override Backbone.View.initialize()
                 */
                initialize: function initialize() {
                    // call Backbone.View.initialize()
                    View.__super__.initialize.apply(this, arguments);
                },
                /**
                 * Index for View management.
                 *
                 * @memberof View
                 * @instance
                 * @property vidx
                 */
                vidx: undefined, // View Index key

                /**
                 * HTMLElement
                 * @see Backbone#View
                 *
                 * @memberof View
                 * @instance
                 * @property el
                 */
                el: undefined,

                /**
                 * The order from the parent View
                 *
                 * @memberof View
                 * @instance
                 * @property order
                 */
                order: 0,

                /**
                 * The function performed before render is performed when a show function is performed. (only once)
                 * Until next runs to waiting after that function, to define a next as an argument, to delay the process.
                 *
                 * @memberof View
                 * @instance
                 * @function
                 * @param {Function} [next]
                 * @example
                 * beforeOnce: function beforeOnce(next) {
                 *     somethingAsync(function() {
                 *         next();
                 *     });
                 * }
                 *
                 */
                beforeOnce: beez.none,


                /**
                 * The function performed before render is performed when a show function is performed.
                 * Until next runs to waiting after that function, to define a next as an argument, to delay the process.
                 *
                 * @memberof View
                 * @instance
                 * @function
                 * @param {Function} [next]
                 * @example
                 * before: function before(next) {
                 *     somethingAsync(function() {
                 *         next();
                 *     });
                 * }
                 */
                before: beez.none,

                /**
                 * Execute after this view have been rendered.
                 * You can delay processes to give `next` in arugument, then processes made to be delayed untill for call `next`.
                 *
                 * @memberof View
                 * @instance
                 * @function
                 * @param {Function} [next]
                 * @example
                 * after: function after(next) {
                 *     somethingAsync(function() {
                 *         next();
                 *     });
                 * }
                 */
                after: beez.none,


                /**
                 * Execute once after this view have been rendered.
                 * You can delay processes to give `next` in arugument, then processes made to be delayed untill for call `next`.
                 *
                 * @memberof View
                 * @instance
                 * @function
                 * @param {Function} [next]
                 * @example
                 * afterOnce: function afterOnce(next) {
                 *     somethingAsync(function() {
                 *         next();
                 *     });
                 * }
                 */
                afterOnce: beez.none,

                /**
                 * Generate async class
                 *
                 * @memberof View
                 * @instance
                 * @return {ViewAsync}
                 */
                async: function async() {
                    return new ViewAsync(this);
                },

                /**
                 * Return existence of HTMLElement on DOM tree in this view.
                 *
                 * @memberof View
                 * @instance
                 * @function
                 * @return {boolean}
                 */
                isRendered: function isRendered() {
                    return !!this.el && !!this.el.parentElement;
                },

                /**
                 * set visible
                 *
                 * @memberof View
                 *
                 * @param {boolean} visible
                 * @throw {Error} typeof visible invalid. should be boolean
                 * @return {View} this
                 */
                setVisible: function setVisible(visible) {
                    if (typeof visible !== 'boolean') {
                        throw beez.Error('typeof visible invalid. should be boolean.');
                    }
                    this.visible = visible;
                    return this;
                },


                /**
                 * Disposes of the instance and remove HTMLElement
                 * and undelegate event on all view.
                 *
                 * @memberof View
                 * @instance
                 * @override Backbone.View.undelegateEvents
                 * @return
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');

                    this.remove();

                    // call Backbone.undelegateEvents method
                    View.__super__.undelegateEvents.apply(this, arguments);

                    delete this.manager;
                    delete this.state;
                    delete this.visible;
                    delete this.cid;
                    delete this.options;
                    delete this.$el;
                    delete this.model;
                    delete this.collection;
                    delete this.el;
                    // delete this.id;
                    delete this.attributes;
                    delete this.className;
                    delete this.tagName;
                    // delete this.events;

                    // call Base.dispose()
                    // View.__super__.dispose.call(this);
                },

                /**
                 * The function performed before remove is performed
                 * Until next runs to waiting after that function, to define a next as an argument, to delay the process.
                 *
                 * @memberof View
                 * @instance
                 * @function
                 * @param {Function} [next]
                 * @example
                 * conceal: function conceal(next) {
                 *     somethingAsync(function() {
                 *         next();
                 *     });
                 * }
                 */
                conceal: beez.none,

                /**
                 * Remove HTMLElement.
                 *
                 * @memberof View
                 * @function
                 * @override Backbone.View.remove
                 * @return
                 */
                remove: function remove() {
                    // call Backbone.remove
                    View.__super__.remove.apply(this, arguments);
                }
            }
        );


        /**
         * @memberof View
         * @function
         * @param {String} [name]
         * @param {Object} childProto
         * @borrows beez.extendThis as extend
         * @example
         * var MyView = View.extend(
         *     'myapp.MyView',
         *     {
         *         vidx: 'foo',
         *         bar: function bar() {}
         *     }
         * );
         */
        View.extend = beez.extendThis;

        return {
            View: View,
            ViewAsync: ViewAsync,
            ViewManager: ViewManager,
            ViewManagerAsync: ViewManagerAsync
        };
    });
示例#10
0
文件: index.js 项目: CyberAgent/beez
    define(function __MVCR__(require, exports, module) {
        'use strict';

        var beez = require('beez.core');
        var logger = beez.getLogger('beez.mvcr');

        if (beez.mvcr) {
            logger.debug('beez.mvcr already defined.');
            return beez.mvcr;
        }

        var Handlebars = require('handlebars');

        /**
         * Shortcut function
         *   Handlebars.templates[]
         * @memberof beez
         * @function
         * @name getTemplate
         * @param {String} name
         * @returns {Function} handlebars template function
         */
        beez.getTemplate = function getTemplate(name) {
            return Handlebars.templates[name];
        };

        var __MVCR__ = {
            initialize: function () {

                var model = require('beez-mvcr/model');
                var modic = require('beez-mvcr/modic');
                var view = require('beez-mvcr/view');
                var controller = require('beez-mvcr/controller');
                var router = require('beez-mvcr/router');
                var css = require('beez-mvcr/cssmanager');
                var image = require('beez-mvcr/imagemanager');
                var base = require('beez-mvcr/base');


                /**
                 * @name Model
                 * @memberof beez.mvcr
                 * @borrows Model
                 * @type {Model}
                 */
                this.Model = model.Model;

                /**
                 * @name ModelManager
                 * @memberof beez.mvcr
                 * @borrows ModelManager
                 * @type {ModelManager}
                 */
                this.ModelManager = model.ModelManager; // if you want to extend

                /**
                 * @name ModelManagerAsync
                 * @memberof beez.mvcr
                 * @borrows ModelManagerAsync
                 * @type {ModelManagerAsync}
                 */
                this.ModelManagerAsync = model.ModelManagerAsync; // if you want to extend

                /**
                 * @name Collection
                 * @memberof beez.mvcr
                 * @borrows Collection
                 * @type {Collection}
                 */
                this.Collection = model.Collection;

                /**
                 * @name Modic
                 * @memberof beez.mvcr
                 * @borrows Modic
                 * @type {Modic}
                 */
                this.Modic = modic.Modic;

                /**
                 * @name View
                 * @memberof beez.mvcr
                 * @borrows View
                 * @type {View}
                 */
                this.View = view.View;

                /**
                 * @name View
                 * @memberof beez.mvcr
                 * @borrows ViewAsync
                 * @type {ViewAsync}
                 */
                this.ViewAsync = view.ViewAsync;

                /**
                 * @name View
                 * @memberof beez.mvcr
                 * @borrows ViewManager
                 * @type {View}
                 */
                this.ViewManager = view.ViewManager; // if you want to extend

                /**
                 * @name View
                 * @memberof beez.mvcr
                 * @borrows ViewManagerAsync
                 * @type {ViewManagerAsync}
                 */
                this.ViewManagerAsync = view.ViewManagerAsync; // if you want to extend


                /**
                 * @name Controller
                 * @memberof beez.mvcr
                 * @borrows Controller
                 * @type {Controller}
                 */
                this.Controller = controller.Controller;

                /**
                 * @name Controller
                 * @memberof beez.mvcr
                 * @borrows ControllerManager
                 * @type {Controller}
                 */
                this.ControllerManager = controller.ControllerManager; // if you want to extend

                /**
                 * @name Controller
                 * @memberof beez.mvcr
                 * @borrows ControllerManagerAsync
                 * @type {ControllerAsync}
                 */
                this.ControllerManagerAsync = controller.ControllerManagerAsync; // if you want to extend

                /**
                 * @name Router
                 * @memberof beez.mvcr
                 * @borrows Router
                 * @type {Router}
                 */
                this.Router = router.Router;

                /**
                 * @name RouterManager
                 * @memberof beez.mvcr
                 * @borrows RouterManager
                 * @type {RouterManager}
                 */
                this.RouterManager = router.RouterManager; // if you want to extend

                /**
                 * @name CSSManager
                 * @memberof beez.mvcr
                 * @borrows CSSManager
                 * @type {CSSManager}
                 */
                this.CSSManager = css.CSSManager;     // if you want to extend
                /**
                 * @name CSSManagerAsync
                 * @memberof beez.mvcr
                 * @borrows CSSManagerAsync
                 * @type {CSSManagerAsync}
                 */
                this.CSSManagerAsync = css.CSSManagerAsync;     // if you want to extend
                /**
                 * @name ImageManager
                 * @memberof beez.mvcr
                 * @borrows ImageManager
                 * @type {ImageManager}
                 */
                this.ImageManager = image.ImageManager; // if you want to extend
                /**
                 * @name ImageManagerAsync
                 * @memberof beez.mvcr
                 * @borrows ImageManagerAsync
                 * @type {ImageManagerAsync}
                 */
                this.ImageManagerAsync = image.ImageManagerAsync; // if you want to extend
                /**
                 * @name ManagerBase
                 * @memberof beez.mvcr
                 * @borrows ManagerBase
                 * @type {ManagerBase}
                 */
                this.ManagerBase = base.ManagerBase;
                /**
                 * @name Base
                 * @memberof beez.mvcr
                 * @borrows Base
                 * @type {Base}
                 */
                this.Base = base.Base;

            }
        };

        var MVCR = beez.extend(
            'beez.MVCR',
            function constructor() {
                return this.initialize();
            }, __MVCR__);

        var mvcr = new MVCR();


        // Add to beez object.
        beez.mvcr = mvcr;

        beez.Model = mvcr.Model;
        beez.Collection = mvcr.Collection;
        beez.Modic = mvcr.Modic;
        beez.View = mvcr.View;
        beez.Controller = mvcr.Controller;
        beez.Router = mvcr.Router;

        // Backbone shortcut
        var Backbone = require('backbone');
        /**
         * Backbone.history short cut.
         * @name history
         * @memberof beez
         */
        beez.history = Backbone.history;

        //
        // ----
        // Managers
        //

        var mconfig = beez.config.manager || {};

        var __Manager__ = {
            initialize: function () {
                /**
                 * setuped flag
                 * @memberof beez.manager
                 * @name setuped
                 * @type {Boolean}
                 */
                this.setuped = false;

                /**
                 * ModelManager instance
                 * @memberof beez.manager
                 * @name model
                 * @alias m
                 * @type {ModelManager}
                 */
                this.model = undefined;

                /**
                 * shortcut for model
                 * @memberof beez.manager
                 * @name m
                 * @type {ModelManager}
                 */
                this.m = undefined;

                /**
                 * ViewManager instance
                 * @memberof beez.manager
                 * @name view
                 * @type {ViewManager}
                 */
                this.view = undefined;

                /**
                 * shortcut for view
                 * @memberof beez.manager
                 * @name v
                 * @type {ViewManager}
                 */
                this.v = undefined;

                /**
                 * ControllerManager instance
                 * @memberof beez.manager
                 * @name controller
                 * @type {ControllerManager}
                 */
                this.controller = undefined;

                /**
                 * shortcut for controller
                 * @memberof beez.manager
                 * @name c
                 * @type {ControllerManager}
                 */
                this.c = undefined;

                /**
                 * RouterManager instance
                 * @memberof beez.manager
                 * @name router
                 * @type {RouterManager}
                 */
                this.router = undefined;

                /**
                 * shortcut for router
                 * @memberof beez.manager
                 * @name r
                 * @type {RouterManager}
                 */
                this.r = undefined;

                /**
                 * CSSManager instance
                 * @memberof beez.manager
                 * @name css
                 * @type {CSSManager}
                 */
                this.css = undefined;

                /**
                 * ImageManager instance
                 * @memberof beez.manager
                 * @name image
                 * @type {ImageManager}
                 */
                this.image = undefined;
            },

            /**
             * Beez MVCR Manager Setup
             *
             * @memberof MVCR
             * @instance
             * @public
             * @param {Object} objs It sets up to overwrite a management class.
             * @return {MVCR}
             */
            setup: function setup(objs) {
                if (this.setuped) {
                    return this;
                }

                objs = objs || {};
                this.setuped = true;

                // Initialize ModelManager
                if (objs.model) {
                    this.model = objs.model;
                } else {
                    var model = require('beez-mvcr/model');
                    this.model = new model.ModelManager('midx');
                }
                this.m = this.model; // shortcut


                // Initialize ViewManager
                if (objs.view) {
                    this.view = objs.view;
                } else {
                    var view = require('beez-mvcr/view');
                    this.view = new view.ViewManager('vidx');
                }
                this.v = this.view; // shortcut

                // Initialize ControllerManager
                if (objs.controller) {
                    this.controller = objs.controller;
                } else {
                    var controller = require('beez-mvcr/controller');
                    this.controller = new controller.ControllerManager();
                }
                this.c = this.controller; // shortcut


                // Initialize RouterManager
                if (objs.router) {
                    this.router = objs.router;
                } else {
                    var router = require('beez-mvcr/router');
                    this.router = new router.RouterManager();
                }
                this.r = this.router; // shortcut

                // Initialize CSSManager
                if (objs.css) {
                    this.css = objs.css;
                } else {
                    var css = require('beez-mvcr/cssmanager');
                    this.css = new css.CSSManager();
                }

                // Initialize ImageManager
                if (objs.image) {
                    this.image = objs.image;
                } else {
                    var image = require('beez-mvcr/imagemanager');
                    this.image = new image.ImageManager(mconfig.image);
                }
                return this;
            }
        };

        var Manager = beez.extend(
            'beez.Manager',
            function constructor() {
                return this.initialize();
            }, __Manager__);

        var manager = new Manager();
        mvcr.manager = manager;
        beez.manager = mvcr.manager; // shortcut

        return beez.mvcr;
    });
示例#11
0
    define(function (require, exports, module) {
        'use strict';

        var beez = require('beez.core');
        var utils = require('beez.utils');
        var _ = beez.vendor._;
        var $ = beez.vendor.$;

        var logger = beez.getLogger('beez.mvcr.imagemanager');

        /**
         * transparent-1px image data
         * @type {String}
         */
        var transparentImageDataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAABlBMVEX///8AAABVwtN+AAAAAXRSTlMAQObYZgAAAA1JREFUeNoBAgD9/wAAAAIAAVMrnDAAAAAASUVORK5CYII=';

        var _uid = 0;
        var uid = function uid() {
            return '__beez_manager_image_uid_' + _uid++;
        };

        /**
         * Class that manages multiple Image Object. re-use function of <img>.
         *
         * @class
         * @name ImangePool
         * @private
         * @param {int} size Pool size. Throw Error when exceeds the specified size. Setting "0", unlimited.
         * @throw {Error}
         */
        var ImangePool = beez.extend(
            'beez.mvcr.ImagePool',
            function constructor(size, options) {
                return this.initialize(size, options);
            },
            {
                /**
                 * Constructor
                 *
                 * @memberof ImangePool
                 * @instance
                 * @param {int} size Pool size. Throw Error when exceeds the specified size. Setting "0", unlimited.
                 * @param {Object} options for creating image
                 */
                initialize: function initialize(size, options) {
                    /**
                     * for creating image
                     *
                     * @memberof ImangePool
                     * @instance
                     * @property {Object} options
                     */
                    this.options = options || {};

                    /**
                     * pool limit
                     *
                     * @memberof ImangePool
                     * @instance
                     * @property {int} limit
                     */
                    this.limit = size;

                    /**
                     * The total number of generated HTMLImageElement
                     *
                     * @memberof ImangePool
                     * @instance
                     * @private
                     */
                    this._total = 0;

                    /**
                     * HTMLImageElement total number in use.
                     *
                     * @memberof ImangePool
                     * @instance
                     * @private
                     */
                    this._num_used = 0;

                    /**
                     * HTMLImageElement hash in use.
                     *
                     * @memberof ImangePool
                     * @instance
                     * @private
                     */
                    this._using = {};

                    /**
                     * Waiting for reuse HTMLImageElement
                     *
                     * @memberof ImangePool
                     * @instance
                     * @private
                     * @return {Array}
                     */
                    this._unused = [];
                },


                /**
                 * Generate HTMLImageElement.
                 *
                 * It is returned when there is recyclable HTMLImageElement.
                 * release() is given to HTMLImageElement.
                 * Please call release () to always While destroying HTMLImageElement.
                 *
                 * @memberof ImangePool
                 * @instance
                 * @param {Object} options for creating image
                 * @return {HTMLImageElement}
                 */
                create: function create(options) {
                    var elem;
                    //options = options || this.options || {}; // default) not "Anonymous"
                    options = options || {}; // default) not "Anonymous"

                    if (this._unused.length > 0) {
                        elem = this._unused.pop();
                    } else {
                        if (this.limit > 0 && this._total >= this.limit) {
                            throw new beez.Error('image pool limit exceeds!');
                        }
                        elem = new Image();
                        elem.__beez_manager_image_uid = uid();
                        this._total++;
                    }

                    //elem.crossOrigin = options.crossOrigin ? options.crossOrigin : elem.crossOrigin;
                    //elem.crossOrigin = options.crossOrigin ? options.crossOrigin : options.crossOrigin;

                    if (options.crossOrigin) {
                        elem.crossOrigin = options.crossOrigin;
                    } else if (this.options.crossOrigin) {
                        elem.crossOrigin = this.options.crossOrigin;
                    }

                    this._num_used++;
                    this._using[elem.__beez_manager_image_uid] = elem;

                    var self = this;

                    /**
                     * The HTMLImageelement waiting for reuse.
                     * This function will be removed in the release() timing.
                     */
                    elem.release = function release() {
                        this.crossOrigin = null; // force null!!
                        this.src = transparentImageDataURI;
                        self._using && delete self._using[this.__beez_manager_image_uid];
                        self._unused && self._unused.push(this);
                        self._num_used && self._num_used--;
                        delete this.release;
                    };

                    return elem;
                },


                /**
                 * It is the number of HTMLImageElement(s) during use.
                 *
                 * @memberof ImangePool
                 * @instance
                 * @returns {int}
                 */
                living: function living() {
                    return this._num_used;
                },


                /**
                 * The total number of HTMLImageElement
                 *
                 * @memberof ImangePool
                 * @instance
                 * @returns {int}
                 */
                peak: function peak() {
                    return this._total;
                },


                /**
                 * Waiting for reuse of HTMLImageElement
                 *
                 * @memberof ImangePool
                 * @instance
                 * @returns {int}
                 */
                waiting: function waiting() {
                    return this._unused.length;
                },

                /**
                 * Disposes of the instance
                 *
                 * @memberof ImangePool
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');
                    // release all of using images
                    for (var id in this._using) {
                        this._using[id].release();
                    }
                    delete this._using;

                    while (this._unused.length > 0) {
                        var e = this._unused.pop();
                        delete e.__beez_manager_image_uid;
                    }
                    delete this._unused;

                    delete this._num_used;
                    delete this._total;
                    delete this._limit;
                }
            }
        );



        /**
         * Image management class. asynchronous
         *
         * @class
         * @name ImageManagerAsync
         * @private
         * @extends Bucks
         * @example
         * var l = new ImageManagerAsync();
         * l.load('http://...').then(res, next) {
         *     // res[0] is loaded image
         * }).end();
         */
        var ImageManagerAsync = beez.Bucks.extend(
            'beez.mvcr.ImageManagerAsync',
            {
                /**
                 * Constructor
                 * @memberof ImageManagerAsync
                 */
                initialize: function initialize(imageManager) {
                    this.imageManager = imageManager;
                },

                /**
                 * Load the image.
                 *
                 * @memberof ImageManagerAsync
                 * @instance
                 * @param {String} url
                 * @param {Object} options for creating image
                 * @return {Bucks}
                 * @example
                 * loader.loadOne('http://...').then(function onload(res, next) {
                 *     // res is a loaded-image
                 *     // next(null, ...)
                 * }).error(function onError(err, next) {
                 *     // on error
                 * }).end();
                 */
                loadOne: function loadOne(url, options) {

                    var img = this.imageManager.create(options);
                    var self = this;

                    return this.add(function loadTask(err, res, next) {

                        var $img = $(img);

                        var onLoad = function onLoad() {
                            $img.off();
                            next(null, img);
                        };
                        var onError = function onError(ev) {
                            var src = img.src;

                            $img.off();
                            img.release();
                            next(new beez.Error('error on load image. src:' + src));
                        };
                        var onAbort = function onAbort(ev) {
                            var src = img.src;

                            $img.off();
                            img.release();
                            next(new beez.Error('image loading aborted. src:' + src));
                        };

                        $img.on('load', onLoad);
                        $img.on('error', onError);
                        $img.on('abort', onAbort);

                        // start loading
                        var _url = self.imageManager.imageUrl(url); // replace ${ratio}
                        img.src = _url;
                    });
                },

                /**
                 * Load the image(s).
                 *
                 * @memberof ImageManagerAsync
                 * @instance
                 * @param {String|Array} url ex) Array: ['hoge.png', 'foo.png']
                 * @param {Object|Array} options ex) Array: [{crossOrigin: "Anonymous"}, {crossOrigin: ""}]
                 * @return {Bucks} ex.) {res:[HTMLImageElement, null, null, HTMLImageElement], err:[null, Error, Error, HTMLImageElement]}
                 */
                load: function load(url, options) {

                    // param check and Array-nize
                    if (_.isString(url)) {
                        url = [url];
                    } else if (!_.isArray(url)) {
                        throw new beez.Error('url can be String or Array of string.');
                    }

                    // param check and Array-nize

                    options = options || {};
                    if (!_.isArray(options)) {
                        if (_.isObject(options)) {
                            options = [options];
                        } else {
                            throw new beez.Error('options can be Object or Array of object.');
                        }
                    }

                    // make tasks
                    var self = this;
                    var tasks = _.map(url, function makeTask(u, idx) {
                        return function loadTask(err, res, next) {
                            new ImageManagerAsync(self.imageManager)
                                .loadOne(u, options[idx])
                                .end(function complete(err, res) {
                                    next(err, res[0]);
                                }, function onError(e) {
                                    next(e);
                                });
                        };
                    });

                    // parallel load
                    return this.parallel(tasks);
                },

                /**
                 * dispose this ImageManagerAsync
                 *
                 * @memberof ImageManagerAsync
                 * @instance
                 * @private
                 */
                dispose: function dispose() {
                    delete this.imageManager;
                }
            }
        );



        /**
         * Image management class. synchronism
         *
         * @class
         * @name ImageManager
         * @param {Object} [options]
         * @param {int} [options.size] Pool size. Throw Error when exceeds the specified size. Setting "0", unlimited.
         */
        var ImageManager = beez.extend(
            'beez.mvcr.ImageManager',
            function constructor(options) {
                return this.initialize(options);
            },
            {
                /**
                 * Constructor
                 *
                 * @memberof ImageManager
                 * @param {Object} options for creating image
                 * @example
                 * var options = {
                 *     size: 10,
                 *     pool: {
                 *         crossOrigin: 'Anonymous'
                 *     }
                 * };
                 *     var manager = new ImageManager(options);
                 *
                 *
                 */
                initialize: function initialize(options) {
                    var size = (options && options.size) ? options.size : 0;
                    var pool = (options && options.pool) ? options.pool : {};
                    this.pool = new ImangePool(size, pool);
                },

                /**
                 * Replaced by pixcelRatio of the URL $ {ratio}
                 *
                 * @memberof ImageManager
                 */
                imageUrl: function imageUrl(url) {
                    return url.replace('${ratio}', beez.utils.pixelRatio * 10);
                },

                /**
                 * Generate HTMLImageElement.
                 *
                 * It is returned when there is recyclable HTMLImageElement.
                 * release() is given to HTMLImageElement.
                 * Please call release () to always While destroying HTMLImageElement.
                 *
                 * @memberof ImageManager
                 * @param {Object} options for creating image
                 * @instance
                 */
                create: function create(options) {
                    return this.pool.create(options);
                },


                /**
                 * It is the number of HTMLImageElement(s) during use.
                 *
                 * @memberof ImageManager
                 * @instance
                 * @returns {int}
                 */
                living: function living() {
                    return this.pool.living();
                },


                /**
                 * The total number of HTMLImageElement
                 *
                 * @memberof ImageManager
                 * @instance
                 * @returns {int}
                 */
                peak: function peak() {
                    return this.pool.peak();
                },


                /**
                 * Waiting for reuse of HTMLImageElement
                 *
                 * @memberof ImageManager
                 * @instance
                 * @returns {int}
                 */
                waiting: function waiting() {
                    return this.pool.waiting();
                },


                /**
                 * Load the image(s).
                 *
                 * @memberof ImageManager
                 * @instance
                 * @param {String|Array} url
                 * @param {Object|Array} options ex) Array: [{crossOrigin: "Anonymous"}, {crossOrigin: ""}]
                 * @return {ImageManagerAsync}
                 * @see ImageManagerAsync#load
                 */
                load: function load(url, options) {
                    return new ImageManagerAsync(this).load(url, options);
                },


                /**
                 * Load the image(s).
                 *
                 * @memberof ImageManager
                 * @instance
                 * @param {String} url
                 * @param {Object} options
                 * @return {ImageManagerAsync}
                 * @see ImageManagerAsync#loadOne
                 */
                loadOne: function loadOne(url, options) {
                    return new ImageManagerAsync(this).loadOne(url, options);
                },

                /**
                 * dispose this ImageManagerAsync
                 *
                 * @memberof ImageManager
                 * @instance
                 * @private
                 */
                dispose: function dispose() {
                    logger.trace(this.constructor.name, 'dispose');
                    this.pool.dispose();
                    delete this.pool;
                }
            }
        );

        return {
            ImageManager: ImageManager,
            ImageManagerAsync: ImageManagerAsync
        };
    });