jui.define("core", [ "util.base", "util.dom", "manager", "collection" ], function(_, $, UIManager, UICollection) { /** * @class core * Core classes for all of the components * * @alias UICore */ var UICore = function() { /** * @method emit * Generates a custom event. The first parameter is the type of a custom event. A function defined as an option or on method is called * * @param {String} type Event type * @param {Function} args Event Arguments * @return {Mixed} */ this.emit = function(type, args) { if(!_.typeCheck("string", type)) return; var result; for(var i = 0; i < this.event.length; i++) { var e = this.event[i]; if(e.type == type.toLowerCase()) { var arrArgs = _.typeCheck("array", args) ? args : [ args ]; result = e.callback.apply(this, arrArgs); } } return result; } /** * @method on * A callback function defined as an on method is run when an emit method is called * * @param {String} type Event type * @param {Function} callback */ this.on = function(type, callback) { if(!_.typeCheck("string", type) || !_.typeCheck("function", callback)) return; this.event.push({ type: type.toLowerCase(), callback: callback, unique: false }); } /** * @method off * Removes a custom event of an applicable type or callback handler * * @param {String} type Event type */ this.off = function(type) { var event = []; for(var i = 0; i < this.event.length; i++) { var e = this.event[i]; if ((_.typeCheck("function", type) && e.callback != type) || (_.typeCheck("string", type) && e.type != type.toLowerCase())) { event.push(e); } } this.event = event; } /** * @method addValid * Check the parameter type of a UI method and generates an alarm when a wrong value is entered * * @param {String} name Method name * @param {Array} params Parameters */ this.addValid = function(name, params) { if(!this.__proto__) return; var ui = this.__proto__[name]; this.__proto__[name] = function() { var args = arguments; for(var i = 0; i < args.length; i++) { if(!_.typeCheck(params[i], args[i])) { throw new Error("JUI_CRITICAL_ERR: the " + i + "th parameter is not a " + params[i] + " (" + name + ")"); } } return ui.apply(this, args); } } /** * @method callBefore * Sets a callback function that is called before a UI method is run * * @param {String} name Method name * @param {Function} callback * @return {Mixed} */ this.callBefore = function(name, callback) { if(!this.__proto__) return; var ui = this.__proto__[name]; this.__proto__[name] = function() { var args = arguments; if(_.typeCheck("function", callback)) { // before 콜백이 false가 아닐 경우에만 실행 한다. if(callback.apply(this, args) !== false) { return ui.apply(this, args); } } else { return ui.apply(this, args); } } } /** * @method callAfter * Sets a callback function that is called after a UI method is run * * @param {String} name Method name * @param {Function} callback * @return {Mixed} */ this.callAfter = function(name, callback) { if(!this.__proto__) return; var ui = this.__proto__[name]; this.__proto__[name] = function() { var args = arguments, obj = ui.apply(this, args); // 실행 함수의 리턴 값이 false일 경우에는 after 콜백을 실행하지 않는다. if(_.typeCheck("function", callback) && obj !== false) { callback.apply(this, args); } return obj; } } /** * @method callDelay * Sets a callback function and the delay time before/after a UI method is run * * @param {String} name Method name * @param {Function} callback */ this.callDelay = function(name, callObj) { // void 형의 메소드에서만 사용할 수 있음 if(!this.__proto__) return; var ui = this.__proto__[name], delay = (!isNaN(callObj.delay)) ? callObj.delay : 0; this.__proto__[name] = function() { var self = this, args = arguments; if(_.typeCheck("function", callObj.before)) { callObj.before.apply(self, args); } if(delay > 0) { setTimeout(function() { callFunc(self, args); }, delay); } else { callFunc(self, args); } } function callFunc(self, args) { var obj = ui.apply(self, args); if(_.typeCheck("function", callObj.after) && obj !== false) { // callAfter와 동일 callObj.after.apply(self, args); } } } /** * @method setTpl * Dynamically defines the template method of a UI * * @param {String} name Template name * @param {String} html Template markup */ this.setTpl = function(name, html) { this.tpl[name] = _.template(html); } /** * @method setOption * Dynamically defines the options of a UI * * @param {String} key * @param {Mixed} value */ this.setOption = function(key, value) { if(_.typeCheck("object", key)) { for(var k in key) { this.options[k] = key[k]; } } else { this.options[key] = value; } } /** * @method destroy * Removes all events set in a UI obejct and the DOM element * */ this.destroy = function() { if(this.__proto__) { for (var key in this.__proto__) { delete this.__proto__[key]; } } } }; UICore.build = function(UI) { return function(selector, options) { var list = [], elemList = []; if(_.typeCheck("string", selector)) { elemList = $.find(selector); } else if(_.typeCheck("object", selector)) { elemList.push(selector); } else { elemList.push(document.createElement("div")); } for(var i = 0, len = elemList.length; i < len; i++) { list[i] = jui.createUIObject(UI, selector, i, elemList[i], options); } // UIManager에 데이터 입력 UIManager.add(new UICollection(UI.type, selector, options, list)); // 객체가 없을 경우에는 null을 반환 (기존에는 빈 배열을 반환) if(list.length == 0) { return null; } else if(list.length == 1) { return list[0]; } return list; } } UICore.init = function(UI) { var uiObj = null; if(typeof(UI) === "object") { uiObj = UICore.build(UI); UIManager.addClass({ type: UI.type, "class": uiObj }); } return uiObj; } UICore.setup = function() { return { /** * @cfg {Object} [tpl={}] * Defines a template markup to be used in a UI */ tpl: {}, /** * @cfg {Object} [event={}] * Defines a DOM event to be used in a UI */ event: {} } } /** * @class jui * * @extends core.UIManager * @singleton */ window.jui = (typeof(jui) == "object") ? _.extend(jui, UIManager, true) : UIManager; return UICore; });