/* * */ /* * @(#) du_ext.js * build version : 1.0.0 $Revision: 15341 $ * * Copyright ⓒ LG CNS, Inc. All rights reserved. * * devon@lgcns.com * http://www.dev-on.com * * Do Not Erase This Comment!!! (이 주석문을 지우지 말것) * * dujsf/license.txt를 반드시 읽어보고 사용하시기 바랍니다. * * 1. 사내 사용시 KAMS를 통해 요청하여 사용허가를 받아야만 소프트웨어 라이센스 계약서에 동의하는 것으로 간주됩니다. * 2. DevOn RUI가 포함된 제품을 판매할 경우에도 KAMS를 통해 요청하여 사용허가를 받아야만 합니다. * 3. KAMS를 통해 사용허가를 받지 않은 경우 소프트웨어 라이센스 계약을 위반한 것으로 간주됩니다. * 4. 별도로 판매될 경우 LGCNS의 소프트웨어 판매정책을 따릅니다. (KAMS에 문의 바랍니다.) * * (주의!) 원저자의 허락없이 재배포 할 수 없으며 * LG CNS 외부로의 유출을 하여서는 안 된다. */ /** * Form * @module widget_form * @title Form * @requires DU */ DU.namespace("DU.widget"); /** * LForm * @namespace DU.widget * @class LForm * @extends DU.widget.LUIComponent * @constructor LForm * @param {Object} oConfig The intial LForm. */ DU.widget.LForm = function(id, oConfig){ this.id = id; DU.widget.LForm.superclass.constructor.call(this, oConfig); var config = oConfig || {}; /** * @description DU.validate.LValidatorManager 객체 *
Sample: 보기
* @config validatorManager * @type {DU.validate.LValidatorManager} * @default null */ /** * @description DU.validate.LValidatorManager 객체 * @property validatorManager * @private * @type {DU.validate.LValidatorManager} */ this.validatorManager = null; DU.applyObject(this, config, true); // validatorManager 권장 안함. if(this.validatorManager == null && config.validators) { this.validatorManager = new DU.validate.LValidatorManager({ validators:config.validators }); } /** * @description DU.data.LTransactionManager 객체 * @property tm * @private * @type {DU.data.LTransactionManager} */ this.tm = new DU.data.LTransactionManager(); this.tm.on('success', this.onSuccess, this, true); this.tm.on('failure', this.onFailure, this, true); /** * @description sumbit 실행전 호출되는 이벤트, 이벤트 리턴값이 false면 submit이 호출되지 않는다. * @event beforesubmit */ this.createEvent('beforesubmit'); /** * @description invalid가 발생하는 발생하는 이벤트 * @event invalid * @param {Object} target this객체 * @param {Array} invalidList invalid 객체 List */ this.createEvent('invalid'); /** * @description sumbit이 성공하면 발생하는 이벤트 * @event success * @param {XMLHttpRequest} conn ajax response 객체 */ this.createEvent('success'); /** * @description sumbit이 실패하면 발생하는 이벤트 * @event failure * @param {XMLHttpRequest} conn ajax response 객체 */ this.createEvent('failure'); } DU.extend(DU.widget.LForm, DU.widget.LUIComponent, { /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ var elList = DU.select("form[name=" + this.id + "]"); if(elList.length > 0) this.el = elList.getAt(0); else this.el = DU.get(this.id); }, /** * @description LValidatorManager 객체를 설정하는 메소드 * @public * @method setValidatorManager * @param {DU.validate.LValidatorManager} validatorManager DU.validate.LValidatorManager 객체 * @return {void} */ setValidatorManager : function(validatorManager) { this.validatorManager = validatorManager; }, /** * @description submit 메소드 * @method submit * @public * @return void */ submit : function() { if (this.fireEvent('beforesubmit', this) == false) return; if(this.validate()) { this.tm.updateForm({ url : this.el.dom.action, form : this.id }); return true; } return false; }, /** * 성공시 발생하는 메소드 * @method onSuccess * @private * @param {Object} e 성공시 Response객체 * @return void */ onSuccess : function(e) { this.fireEvent('success', e); }, /** * 실패시 발생하는 메소드 * @method onFailure * @private * @param {Object} e 실패시 Response객체 * @return void */ onFailure : function(e) { this.fireEvent('failure', e); }, /** * reset시 발생하는 메소드 * @method onReset * @private * @return void */ onReset : function() { }, /** * validate 발생하는 메소드 * @method validate * @private * @return void */ validate : function() { if(this.validatorManager == null) return true; var isValid = this.validatorManager.validateGroup(this.id); if(isValid == false) { var invalidList = this.validatorManager.getInvalidList(); this.fireEvent('invalid', {target:this, invalidList:invalidList, isValid:isValid}); } return isValid; }, /** * form 객체의 invalid된 모든 객체를 초기화 하는 메소드 * @method clearInvalid * @public * @return void */ clearInvalid : function() { var children = this._getChildList(); var valid = true; DU.util.LArray.each(children, function(f) { var child = DU.get(f); child.valid(); }, this); }, /** * 배열 객체에 해당되는 모든 객체를 활성화 한다. * @method enable * @public * @param {Array} children enable할 배열 객체, 인수를 안 넘기면 모든 form객체 안의 child 모든 객체 자동 선택 * @return void */ enable : function(children) { children = DU.isUndefined(children) ? this._getChildList() : children; DU.util.LArray.each(children, function(f) { var child = DU.get(f); if(child) child.enable(); }, this); }, /** * 배열 객체에 해당되는 모든 객체를 비활성화 한다. * @method disable * @public * @param {Array} children enable할 배열 객체, 인수를 안 넘기면 모든 form객체 안의 child 모든 객체 자동 선택 * @return void */ disable : function(children) { children = DU.isUndefined(children) ? this._getChildList() : children; DU.util.LArray.each(children, function(f) { var child = DU.get(f); if(child) child.disable(); }, this); }, /** * 배열 객체에 해당되는 모든 객체중 비활성화가 하나라도 있으면 false를 리턴한다. * @method isDisable * @public * @param {Array} children enable할 배열 객체, 인수를 안 넘기면 모든 form객체 안의 child 모든 객체 자동 선택 * @return void */ isDisable : function(children) { var isDisable = false; children = DU.isUndefined(children) ? this._getChildList() : children; DU.util.LArray.each(children, function(f) { var child = DU.get(f); if(child) { isDisable = child.isDisable(); return; } }, this); return isDisable; }, /** * form 객체에 안에 있는 child객체 배열 * @method getValues * @public * @return {Array} */ getValues : function() { var obj = {}; var children = this._getChildList(); DU.util.LArray.each(children, function(child) { var f = DU.get(child); var element = f.dom; var name = element.name; var value = f.get("value"); if (typeof element.checked == "boolean") { if (/LRadio/.test(element.declaredClass)) { if (value !== false) { obj[name] = value; } } else { var ary = obj[name]; if (!ary) { ary = []; obj[name] = ary; } if (value !== false) { ary.push(value); } } } else { obj[name] = value; } }, this); return obj; }, /** * form 객체에 안에 있는 child객체에 모든 값 대입 * @method setValues * @public * @param {Array} children children에 해당되는 모든 객체에 값 대입 * @return void */ setValues : function(children) { for(var m in children) { var obj = DU.get(m); if(obj && obj instanceof DU.LElement) { obj.setValue(children[m]); } } }, /** * form 객체에 안에 있는 child객체중에 ID에 해당되는 객체를 찾아서 리턴한다. * @method findField * @public * @param {String} id 검색할 ID 값 * @return {HTMLElement} 검색된 결과 객체 */ findField : function(id) { var field = null; var children = this._getChildList(); DU.util.LArray.each(children, function(child) { var f = DU.get(child); if(f.dom.id == id || f.dom.name == id) { field = f.dom; return false; } }, this); return field; }, /** * form 객체에 안에 있는 child객체중에 invalid객체가 존재하면 false를 리턴한다. * @method isValid * @public * @return {Boolean} valid 여부 */ isValid : function() { var isValid = true; var children = this._getChildList(); DU.util.LArray.each(children, function(f) { var element = DU.get(f); if(element.isValid() == false) { isValid = false; return false; } }, this); return isValid; }, /** * form 객체 destroy * @method destroy * @public * @return {void} */ destroy : function(){ this.unOnAll(); }, /** * Record객체를 form 객체의 child객체에 반영한다. * @public * @method updateRecord * @param {DU.data.LRecord} record form객체에 반영할 Record객체 * @return {void} */ updateRecord : function(record) { var o = record.getValues(); this.setValues(o); }, /** * form 객체의 child 정보를 Record객체에 반영한다. * @public * @method updateRecord * @param {DU.data.LRecord} record form객체의 정보를 반영할 Record객체 * @return {DU.data.LRecord} 반영된 Record객체 */ loadRecord : function(record) { var o = this.getValues(); record.setValues(o); return record; }, /** * form 객체의 입력 가능한 child 정보를 리턴한다. * @private * @method _getChildList * @return {DU.LElementList} 반영된 ElementList객체 */ _getChildList : function() { return DU.util.LDomSelector.query('input,select,textarea', this.dom); } }); /** * Field * @module widget_form * @title Field * @requires DU */ DU.namespace("DU.widget"); /** * LField 객체 * @namespace DU.widget * @class LField * @extends DU.widget.LUIComponent * @constructor LField * @param {HTMLElement | String} id The html element that represents the Element. * @param {Object} oConfig The intial Field. */ DU.widget.LField = function(id, oConfig){ var config = oConfig || {}; DU.widget.LField.superclass.constructor.call(this, id, config); /** * @description changed 메소드가 호출되면 수행하는 이벤트 * @event changed */ this.changedEvent = this.createEvent('changed'); /** * @description valid 메소드가 호출되면 수행하는 이벤트 * @event valid */ this.validEvent = this.createEvent('valid'); /** * @description invalid 메소드가 호출되면 수행하는 이벤트 * @event invalid */ this.invalidEvent = this.createEvent('invalid'); /** * @description specialkey 메소드가 호출되면 수행하는 이벤트 * @event specialkey * @param {Object} e window event 객체 */ this.specialkeyEvent = this.createEvent('specialkey'); } DU.extend(DU.widget.LField, DU.widget.LUIComponent, { otype : 'DU.widget.LField', /** * @description field 객체 여부 * @property fieldObject * @private * @type {Boolean} */ fieldObject : true, /** * @description field의 name * @config name * @type {String} * @default null */ /** * @description field의 name * @property name * @private * @type {String} */ name : null, /** * @description field의 border width * @config borderWidth * @type {Int} * @default 4 */ /** * @description field의 border width * @property borderWidth * @private * @type {Int} */ borderWidth : 4, /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LField.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LField.superclass.initDefaultConfig.call(this); }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LField.superclass.afterRender.call(this, container); }, /** * @description Dom객체의 value값을 저장한다. * @method setValue * @param {Object} value 저장할 결과값 * @return void */ setValue : function(o) { this.el.setValue(o); }, /** * @description Dom객체의 value값을 리턴한다. * @method getValue * @return {Object} 객체에 들어 있는 값 */ getValue : function() { return this.el.getValue(); }, /** * @description 키 입력시 호출되는 이벤트 메소드 * @method onFireKey * @param {Object} e Event 객체 * @return {void} */ onFireKey : function(e){ if(DU.util.LEvent.isSpecialKey(e)) this.fireEvent("specialkey", e); }, /** * @description 이름을 셋팅하는 메소드 * @method setName * @param {String} name 이름 * @return {void} */ setName : function(name) { this.name = name; }, /** * @description 이름을 리턴하는 메소드 * @method getName * @return {String} */ getName : function() { return this.name; }, /** * @description 객체의 toString * @method toString * @public * @return {String} */ toString : function() { return 'DU.form.LField ' + this.id; } }); /** * LTextBox * @module widget_form * @title LTextBox * @requires DU */ DU.namespace("DU.widget"); (function(){ var Dom = DU.util.LDom; /** * LTextBox * @namespace DU.widget * @class LTextBox * @extends DU.widget.LField * @constructor LTextBox * @param {Object} oConfig The intial LTextBox. */ DU.widget.LTextBox = function(oConfig){ var config = oConfig || {}; config = Dom.applyIfProperties(config, '$.ext.textBox'); this.collapseIfDelegate = DU.util.LFunction.createDelegate(this.collapseIf, this); /** * @description displayField 명 * @config displayField * @type {String} * @default 'value' */ /** * @description displayField 명 * @property displayField * @private * @type {String} */ this.displayField = config.displayField || DU.getConfig().getFirst('$.ext.textBox.dataset.displayField'); this.isUseDataSet = this.isAutoComplete === true ? true : this.isUseDataSet; if(DU.isUndefined(config.isAddEmptyText) == false) config.isEmptyText = config.isAddEmptyText; DU.widget.LTextBox.superclass.constructor.call(this, config); if(this.isUseDataSet === true) { if(DU.isEmpty(this.dataSet) && DU.isEmpty(config.dataSet)) { this.createDataSet(); } } if (this.isUseDataSet === true) { if(this.dataSet) this.initDataSet(); if(config.url) { this.dataSet.load({ url: config.url }); } } /** * @description keydown 기능이 호출되면 수행하는 이벤트 * @event keydown */ this.keydownEvent = this.createEvent('keydown'); /** * @description keyup 기능이 호출되면 수행하는 이벤트 * @event keyup */ this.keyupEvent = this.createEvent('keyup'); /** * @description keypress 기능이 호출되면 수행하는 이벤트 * @event keypress */ this.keypressEvent = this.createEvent('keypress'); /** * @description cut 기능이 호출되면 수행하는 이벤트 * @event keypress */ this.cutEvent = this.createEvent('cut'); /** * @description copy 기능이 호출되면 수행하는 이벤트 * @event keypress */ this.copyEvent = this.createEvent('copy'); /** * @description paste 기능이 호출되면 수행하는 이벤트 * @event keypress */ this.pasteEvent = this.createEvent('paste'); /** * @description expand 기능이 호출되면 수행하는 이벤트 * @event expand */ this.createEvent('expand'); /** * @description collapse 기능이 호출되면 수행하는 이벤트 * @event collapse */ this.createEvent('collapse'); /** * @description changed 메소드가 호출되면 수행하는 이벤트 * @event changed * @param {Object} target this객체 * @param {String} value code값 * @param {String} displayValue displayValue값 */ } DU.extend(DU.widget.LTextBox, DU.widget.LField, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LTextBox', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-textbox', /** * @description placeholder CSS명 * @property CSS_PLACEHOLDER * @private * @type {String} */ CSS_PLACEHOLDER : 'L-placeholder', /** * @description type 종류 * text, password, email, url * @config type * @type {String} * @default true */ /** * @description type 종류 * text, password, email, url * @property type * @private * @type {String} */ type : 'text', /** * @description edit 가능 여부 *Sample: 보기
* @config editable * @type {Boolean} * @default true */ /** * @description edit 가능 여부 * @property editable * @private * @type {Boolean} */ editable : true, /** * @description 가로 길이 *Sample: 보기
* @config width * @type {Int} * @default 100 */ /** * @description 가로 길이 * @property width * @private * @type {String} */ width : 100, /** * @description 세로 길이 *Sample: 보기
* @config height * @type {Int} * @default -1 */ /** * @description 세로 길이 * @property height * @private * @type {Int} */ height : -1, /** * @description 목록창의 가로 길이 *Sample: 보기
* @config listWidth * @type {Int} * @default 200 */ /** * @description 목록창의 가로 길이 * @property listWidth * @private * @type {Int} */ listWidth : 200, /** * @description 기본 DataSet객체명, du_config.js에 따라 적용된다. * @property dataSetClassName * @private * @type {String} */ dataSetClassName : 'DU.data.LJsonDataSet', /** * @description filter시 메모리의 데이터로 처리할지 서버에서 load할지를 결정 *Sample: 보기
* @config filterMode * @type {String} * @default 'local' */ /** * @description filter시 메모리의 데이터로 처리할지 서버에서 load할지를 결정 * @property filterMode * @private * @type {String} */ filterMode : 'local', /** * @description local filter시 delayTime값 *Sample: 보기
* @config localDelayTime * @type {Int} * @default 30 */ /** * @description local filter시 delayTime값 * @property localDelayTime * @private * @type {Int} */ localDelayTime : 30, /** * @description remote filter시 delayTime값 *Sample: 보기
* @config remoteDelayTime * @type {Int} * @default 250 */ /** * @description remote filter시 delayTime값 * @property remoteDelayTime * @private * @type {Int} */ remoteDelayTime : 250, /** * @description remote filter시 url값 *Sample: 보기
* @config filterUrl * @type {String} * @default '' */ /** * @description remote filter시 url값 *Sample: 보기
* @property filterUrl * @private * @type {String} */ filterUrl : '', /** * @description dataSet 사용 여부 *Sample: 보기
* @config isUseDataSet * @type {Boolean} * @default false */ /** * @description dataSet 사용 여부 * @property isUseDataSet * @private * @type {Boolean} */ isUseDataSet : false, /** * @description 자동 완성 기능 사용 여부 *Sample: 보기
* @config isAutoComplete * @type {Boolean} * @default false */ /** * @description 자동 완성 기능 사용 여부 * @property isAutoComplete * @private * @type {Boolean} */ isAutoComplete : false, /** * @description 자동 완성 기능을 정보를 가지는 dataSet * @config dataSet * @type {DU.data.LDataSet} * @default null */ /** * @description 자동 완성 기능을 정보를 가지는 dataSet * @property dataSet * @private * @type {DU.data.LDataSet} */ dataSet : null, /** * @description 입력 가능한 문자열 * @config allowChars * @type {String} * @default null */ /** * @description 입력 가능한 문자열 * @property allowChars * @private * @type {String} */ allowChars : null, /** * @description ime-mode값 * @config imeMode * @type {boolean} * @default true */ /** * @description ime-mode값 * @property imeMode * @private * @type {boolean} */ imeMode: true, /** * @description 기본 '선택하세요.' 메시지 값 *Sample: 보기
* @config emptyText * @type {String} * @default Choose a state */ /** * @description 기본 '선택하세요.' 메시지 값 * @property emptyText * @private * @type {String} */ emptyText: 'Choose a state', /** * @description 기본 선택 항목 추가 여부 *Sample: 보기
* @config isEmptyText * @type {Boolean} * @default false */ /** * @description 기본 선택 항목 추가 여부 * @property isEmptyText * @private * @type {Boolean} */ isEmptyText : false, /** * @description mask 적용 * @config mask * @type {String} * @default null */ /** * @description mask 적용 * new DU.form.LTextBox({ mask: '999999-9999999' }); * @property mask * @private * @type {String} */ mask: null, /** * @description getValue시 적용된 mask값으로 리턴할지 여부 * @config isMaskValue * @type {Boolean} * @default false */ /** * @description 기본 선택 항목 추가 여부 * mask가 적용된 값 111-11-111111 * isMaskValue가 true 일경우 getValue()는 111-11-111111 값으로 리턴 * isMaskValue가 false 일경우 getValue()는 11111111111 값으로 리턴 * @property isMaskValue * @private * @type {Boolean} */ isMaskValue: false, /** * @description mask의 형식 정의 * @config definitions * @type {String} * @default { '9': "[0-9]", 'a': "[A-Za-z]", '*': "[A-Za-z0-9]" } */ /** * @description mask의 형식 정의 * @property definitions * @private * @type {String} */ definitions: { '9': "[0-9]", 'a': "[A-Za-z]", '*': "[A-Za-z0-9]" }, /** * @description mask가 적용된 값 입력시에 나오는 문자 * @config maskPlaceholder * @type {String} * @default '_' */ /** * @description mask가 적용된 값 입력시에 나오는 문자 * @property maskPlaceholder * @private * @type {String} */ maskPlaceholder: '_', /** * @description html5에 있는 placeholder 기능 * @config placeholder * @type {String} * @default null */ /** * @description mask가 적용된 값 입력시에 나오는 문자 * @property placeholder * @private * @type {String} */ placeholder: null, /** * @description invalid focus 여부 * @config invalidBlur * @type {boolean} * @default false */ /** * @description invalid시 blur를 할 수 있을지 여부 * @property invalidBlur * @private * @type {boolean} */ invalidBlur: false, /** * @description option div 객체 * @property optionDivEl * @private * @type {LElement} */ optionDivEl: null, /** * @description 목록이 펼쳐질 경우 출력할 갯수 * @config expandCount * @type {int} * @default 20 */ /** * @description 목록이 펼쳐질 경우 출력할 갯수 * @property expandCount * @private * @type {int} */ expandCount: 20, isStringFromChatCode: false, /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LTextBox.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LTextBox.superclass.initDefaultConfig.call(this); this.cfg.addProperty("editable", { handler: this._setEditable, value: this.editable, validator: DU.isBoolean }); this.cfg.addProperty("listWidth", { handler: this._setListWidth, value: this.listWidth, validator: DU.isNumber }); this.cfg.addProperty("isEmptyText", { handler: this._setAddEmptyText, value: this.isEmptyText, validator: DU.isBoolean }); }, /** * @description element Dom객체 생성 * @method createContainer * @protected * @param {HTMLElement} parentNode 부모 노드 * @return {HTMLElement} */ createContainer : function(parentNode) { if(this.el) { if(this.el.dom.tagName == 'INPUT') { this.id = this.id || this.el.id; this.oldDom = this.el.dom; this.name = this.name || this.oldDom.name; var parent = this.el.parent(); this.el = DU.get(this.createElement().cloneNode(false)); this.el.dom.id = this.id; Dom.replaceChild(parent.dom, this.el.dom, this.oldDom); this.el.appendChild(this.oldDom); Dom.removeNode(this.oldDom); delete this.oldDom; } } DU.widget.LTextBox.superclass.createContainer.call(this, parentNode); }, /** * @description render시 발생하는 메소드 * @method doRender * @protected * @param {HttpElement} appendToNode 부모 객체 * @return {void} */ doRender : function(container) { this.createTemplete(this.el); }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LTextBox.superclass.afterRender.call(this, container); var inputEl = this.getDisplayEl(); inputEl.on('click', function(e) { if(this.editable != true) this.expand(); }, this, true); inputEl.on('keydown', this.onFilterKey, this, true); /* if(DU.browser.webkit || DU.browser.msie) inputEl.on('keydown', this.onFilterKey, this, true); else inputEl.on('keypress', this.onFilterKey, this, true); */ if((this.allowChars != null && this.allowChars != '') || (this.imeMode === false)) inputEl.setStyle('ime-mode', 'disabled'); inputEl.on('keydown', this.onSpecialkeyEvent, this, true); inputEl.on('keydown', this.onKeydown, this, true); inputEl.on('keyup', this.onKeyup, this, true); inputEl.on('keypress', this.onKeypress, this, true); var keyEventName = DU.browser.msie || (DU.browser.safari && DU.browser.version == 3) ? "keydown" : "keypress"; inputEl.on(keyEventName, this.onKeyAutoComplete, this, true); inputEl.on(keyEventName, this.onFireKey, this, true); this.createOptionDiv(); if (this.optionDivEl) { if(this.isUseDataSet === true && DU.isEmpty(this.dataSet)) this.createDataSet(); this.doLoadDataSet(); } this.initFocus(); if(this.type != 'text') this.initType(); if(this.mask) this.initMask(); this.addPlaceholder(); }, createDataSet: function() { this.dataSet = new (eval(this.dataSetClassName))({ id: 'dataSet', fields:[ {id:this.displayField} ], focusFirstRow : false }) }, /** * @description type에 따른 기능 초기화 * @method initType * @protected * @return {void} */ initType: function() { if (this.type == 'url') { this.placeholder = 'http://'; this.inputEl.on('focus', function(){ if (this.inputEl.getValue() == '') this.inputEl.setValue(this.placeholder); }, this, true); } else if(this.type == 'email') { this.placeholder = DU.getMessageManager().get('$.base.msg111'); } }, /** * @description dataset을 초기화한다. * @method initDataSet * @protected * @return {void} */ initDataSet: function() { this.doSyncDataSet(); }, /** * @description dataSet의 sync 적용 메소드 * @method doSyncDataSet * @protected * @return void */ doSyncDataSet: function() { this.dataSet.on('beforeLoad', this.onBeforeLoadDataSet, this, true); this.dataSet.on('load', this.onLoadDataSet, this, true); this.dataSet.on('dataChanged', this.onDataChangedDataSet, this, true); this.dataSet.on('rowPosChanged', this.onRowPosChangedDataSet, this, true); this.dataSet.on("add", this.onAddData, this, true); this.dataSet.on("update", this.onUpdateData, this, true); this.dataSet.on("remove", this.onRemoveData, this, true); this.dataSet.on("undo", this.onUndoData, this, true); }, /** * @description dataSet의 unsync 적용 메소드 * @method doUnSyncDataSet * @protected * @return void */ doUnSyncDataSet: function(){ this.dataSet.unOn('beforeLoad', this.onBeforeLoadDataSet, this); this.dataSet.unOn('load', this.onLoadDataSet, this); this.dataSet.unOn('dataChanged', this.onDataChangedDataSet, this); this.dataSet.unOn('rowPosChanged', this.onRowPosChangedDataSet, this); this.dataSet.unOn("add", this.onAddData, this); this.dataSet.unOn("update", this.onUpdateData, this); this.dataSet.unOn("remove", this.onRemoveData, this); this.dataSet.unOn("undo", this.onUndoData, this); }, /** * @description container안의 content의 focus/blur 연결 설정 * @method initFocus * @protected * @return {void} */ initFocus: function() { var inputEl = this.getDisplayEl(); if(inputEl) { inputEl.on('focus', this.onCheckFocus, this, true); if(!this.isCheckContainBlur) { inputEl.on('blur', this.onBlur, this, true); } } }, /** * @description placeholder를 추가하는 메소드 * @method addPlaceholder * @protected * @return {void} */ addPlaceholder: function() { if(this.placeholder && this.getValue() == '') { this.setDisplayValue(this.placeholder); this.getDisplayEl().addClass(this.CSS_PLACEHOLDER); } }, /** * @description placeholder를 제거하는 메소드 * @method removePlaceholder * @protected * @return {void} */ removePlaceholder: function() { if (this.placeholder && this.getDisplayValue() == this.placeholder) { this.setDisplayValue(''); } this.getDisplayEl().removeClass(this.CSS_PLACEHOLDER); }, /** * @description 키 입력시 filter되는 메소드 * @method onFilterKey * @protected * @param {Object} e Event 객체 * @return {void} */ onFilterKey : function(e) { if(this.allowChars == null || this.allowChars == '') return true; var KEY = DU.util.LKeyListener.KEY; if(e.keyCode != KEY.SPACE && (DU.util.LEvent.isSpecialKey(e) || e.keyCode == KEY.BACKSPACE || e.keyCode == KEY.DELETE)) return; var c = e.charCode || e.keyCode; var charCode = null; charCode = (this.isStringFromChatCode === false) ? this.fromCharCode(c) : String.fromCharCode(c); var charCode = this.fromCharCode(c); if(this.allowChars.indexOf(charCode) === -1){ DU.util.LEvent.stopEvent(e); e.returnValue = false; } }, fromCharCode: function(c) { if(c >= 96 && c <= 105) c -= 48; var charCode = String.fromCharCode(c); switch(c) { case 105: break; case 106: charCode = '*'; break; case 107: charCode = '+'; break; case 109: charCode = '-'; break; case 110: charCode = '.'; break; case 111: charCode = '/'; break; case 190: charCode = '.'; break; case 191: charCode = '/'; break; } return charCode; }, /** * @description focus 이벤트 발생시 호출되는 메소드 * @method onFocus * @private * @param {Object} e Event 객체 * @return void */ onFocus : function(e) { DU.widget.LTextBox.superclass.onFocus.call(this, e); this.lastValue = this.getValue(); this.lastDisplayValue = this.getDisplayValue(); this.removePlaceholder(); this.doFocus(e); }, /** * @description focus 이벤트 발생시 호출되는 메소드, design 관련 * @method doFocus * @protected * @param {Object} e Event 객체 * @return void */ doFocus : function(e){ try { this.getDisplayEl().dom.select(); } catch(e) {} }, /** * @description blur 이벤트 발생시 defer를 연결하는 메소드 * @method deferOnBlur * @protected * @param {Object} e Event 객체 * @return {void} */ deferOnBlur : function(e) { var checkBlur = function(e) { if(e.deferCancelBubble == true) return; var target = e.target; if(this.iconDivEl && this.iconDivEl.dom == target) return; var isBlur = false; if(DU.isUndefined(this.optionDivEl)) { if(!this.el.isAncestor(target)) isBlur = true; } else { if(this.el.isAncestor(target) == false) { if(this.optionDivEl) { if((this.optionDivEl.dom !== target && !this.optionDivEl.isAncestor(target))) isBlur = true; } else isBlur = true; } } if(isBlur == true) { if(this.canBlur(e) === false) { this.focus(); return; } DU.util.LEvent.removeListener(DU.browser.msie ? document.body : document, "mousedown", this.deferOnBlurDelegate, this); this.onBlur.call(this, e); this.isFocus = null; } else { e.deferCancelBubble = true; } } DU.util.LFunction.defer(checkBlur, 10, this, [e]); }, /** * @description blur 이벤트 발생시 호출되는 메소드 * @method canBlur * @private * @param {Object} e Event 객체 * @return void */ canBlur: function(e) { var displayValue = this.getDisplayEl().getValue(); if (this.lastDisplayValue != displayValue && this.validateValue(displayValue) == false) { if(this.invalidBlur !== true) return false; this.setValue(this.lastValue); this.setDisplayValue(this.lastDisplayValue); } }, /** * @description blur 이벤트 발생시 호출되는 메소드 * @method onBlur * @private * @param {Object} e Event 객체 * @return void */ onBlur : function(e) { if(this.isExpand()) this.collapse(); if(DU.isUndefined(this.lastDisplayValue) == false && this.lastDisplayValue != this.getDisplayValue()) this.doChangedDisplayValue(this.getDisplayValue()); DU.widget.LTextBox.superclass.onBlur.call(this, e); this.addPlaceholder(); }, /** * @description 출력데이터가 변경되면 호출되는 메소드 * @method doChangedDisplayValue * @private * @param {String} o 적용할 값 * @return void */ doChangedDisplayValue : function(o) { this.setValue(o); }, /** * @description 객체를 destroy하는 메소드 *Sample: 보기
* @method destroy * @public * @return void */ destroy : function() { if(this.dataSet) this.doUnSyncDataSet(); var displayEl = this.getDisplayEl(); displayEl.unOnAll(); if (this.optionDivEl) { this.optionDivEl.unOnAll(); this.optionDivEl = null; } DU.widget.LTextBox.superclass.destroy.call(this); }, /** * @description Dom객체 생성 * @method createTemplete * @private * @param {String|Object} el 객체의 아이디나 객체 * @return {DU.LElement} Element 객체 */ createTemplete : function(el) { var elContainer = DU.get(el); elContainer.addClass(this.CSS_BASE); elContainer.addClass("L-fixed"); var input = document.createElement('input'); input.name = this.name || this.id; input.type = this.type; input.instance = this; elContainer.appendChild(input); this.inputEl = DU.get(input); return elContainer; }, /** * @description width 속성에 따른 실제 적용 메소드 * @method _setWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setWidth : function(type, args, obj) { var width = args[0]; this.el.setWidth(width); this.getDisplayEl().setWidth(width); this.width = width; this.cfg.setProperty('width', width, true); }, /** * @description height 속성에 따른 실제 적용 메소드 * @method _setHeight * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setHeight : function(type, args, obj) { var height = args[0]; if(height < 0) return; this.el.setHeight(height); this.getDisplayEl().setHeight(height); if(DU.browser.msie) this.getDisplayEl().setStyle('line-height', height + 'px'); this.height = height; }, /** * @description listWidth 속성에 따른 실제 적용 메소드 * @method _setListWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setListWidth : function(type, args, obj) { this.optionDivEl ? this.optionDivEl.setWidth(this.listWidth) : null; this.listWidth = args[0]; }, /** * @description width 값을 셋팅하는 메소드 *Sample: 보기
* @method setWidth * @public * @param {Int} w width 값 * @return void */ setWidth : function(w) { this.cfg.setProperty("width", w); }, /** * @description width 값을 리턴하는 메소드 *Sample: 보기
* @method getWidth * @public * @return {Int} width 값 */ getWidth : function() { return this.cfg.getProperty("width"); }, /** * @description listWidth 값을 셋팅하는 메소드 * @method listWidth * @param {Int} w width 값 * @return void */ setListWidth : function(w) { this.cfg.setProperty("listWidth", w); }, /** * @description listWidth 값을 리턴하는 메소드 * @method getWidth * @public * @return {Int} width 값 */ getListWidth : function() { return this.cfg.getProperty("listWidth"); }, /** * @description AddEmptyText 속성에 따른 실제 적용 메소드 * @method _setAddEmptyText * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setAddEmptyText : function(type, args, obj) { if(!this.optionDivEl) return; if(args[0] == true && this.hasEmptyText() == false) this.createEmptyText(); else this.removeEmptyText(); }, /** * @description isEmptyText 값을 변경하는 메소드 * @method setAddEmptyText * @public * @param {Boolean} isEmptyText 변경하고자 하는 값 * @return {void} */ setAddEmptyText : function(isEmptyText) { this.cfg.setProperty('isEmptyText', isEmptyText); }, /** * @description isEmptyText 값을 리턴하는 메소드 * @method getAddEmptyText * @public * @return {Boolean} */ getAddEmptyText : function() { return this.cfg.getProperty("isEmptyText"); }, /** * @description height 값을 셋팅하는 메소드 *Sample: 보기
* @method setHeight * @public * @param {String} w height 값 * @return void */ setHeight : function(h) { this.cfg.setProperty("height", h); }, /** * @description height 값을 리턴하는 메소드 *Sample: 보기
* @method getHeight * @public * @return {String} height 값 */ getHeight : function() { return this.cfg.getProperty("height"); }, /** * @description disabled 속성에 따른 실제 적용 메소드 * @method _setDisabled * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setDisabled : function(type, args, obj) { args = args[0]; if(args === false) { this.disabled = false; this.getDisplayEl().enable(); } else { this.disabled = true; this.getDisplayEl().disable(); } }, /** * @description editable 값을 셋팅하는 메소드 *Sample: 보기
* @method setEditable * @public * @param {Boolean} isEditable editable 셋팅 값 * @return void */ setEditable : function(isEditable) { this.cfg.setProperty("editable", isEditable); }, /** * @description editable 속성에 따른 실제 적용 메소드 * @method _setEditable * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setEditable : function(type, args, obj) { args = args[0]; if (args === false) { this.getDisplayEl().dom.readOnly = true; } else { this.getDisplayEl().dom.readOnly = false; } }, /** * @description 화면 출력되는 객체 리턴 * @method getDisplayEl * @protected * @return {DU.LElement} Element 객체 */ getDisplayEl : function() { return this.inputEl || this.el; }, /** * @description Tries to focus the element. Any exceptions are caught and ignored. *Sample: 보기
* @method focus * @public * @return {void} */ focus : function() { var displayEl = this.getDisplayEl(); displayEl.focus(); }, /** * @description Tries to blur the element. Any exceptions are caught and ignored. *Sample: 보기
* @method blur * @public * @return {void} */ blur : function() { this.getDisplayEl().blur(); }, /** * @description 객체를 유효여부를 확인하는 메소드 *Sample: 보기
* @method isValid * @public * @return {void} */ isValid : function() { return this.getDisplayEl().isValid(); }, /** * @description 객체를 유효한 상태로 설정하는 메소드 *Sample: 보기
* @method valid * @public * @return {void} */ valid : function(){ this.getDisplayEl().valid(); this.validEvent.fire(); }, /** * @description 객체를 유효하지 않은 상태로 설정하는 메소드 *Sample: 보기
* @method invalid * @public * @return {void} */ invalid : function(message) { this.getDisplayEl().invalid(message); this.invalidEvent.fire(message); }, /** * @description Keyup 이벤트가 발생하면 처리하는 메소드 * @method onKeyup * @private * @param {Object} e Event 객체 * @return {void} */ onKeyup : function(e) { this.keyupEvent.fire(e); }, /** * @description Keydown 이벤트가 발생하면 처리하는 메소드 * @method onKeydown * @private * @param {Object} e Event 객체 * @return {void} */ onKeydown : function(e){ this.keydownEvent.fire(e); }, /** * @description Keypress 이벤트가 발생하면 처리하는 메소드 * @method onKeypress * @private * @param {Object} e Event 객체 * @return {void} */ onKeypress : function(e) { this.keypressEvent.fire(e); }, /** * @description copy, cut, paste 같은 특별한 이벤트 기능 연결 메소드 * @method onSpecialkeyEvent * @private * @param {Object} e Event 객체 * @return {void} */ onSpecialkeyEvent : function(e) { if(this.isCheckContainBlur === true) { if (e.keyCode == DU.util.LKeyListener.KEY.TAB) { if (this.canBlur(e) == false) { this.focus(); return false; } } } if (e.ctrlKey && String.fromCharCode(e.keyCode) == "X") { this.cutEvent.fire(e); } else if (e.ctrlKey && String.fromCharCode(e.keyCode) == "C") { this.copyEvent.fire(e); } else if (e.ctrlKey && String.fromCharCode(e.keyCode) == "V") { this.pasteEvent.fire(e); } }, /** * @description autocomplete 기능을 수항하는 메소드 * @method onKeyAutoComplete * @private * @param {Object} e Event 객체 * @return {void} */ onKeyAutoComplete : function(e) { if (this.isUseDataSet === true && this.isAutoComplete === true) { this.doKeyMove(e); this.doKeyInput(e); } }, /** * @description 키 입력에 따른 이동 이벤트를 처리하는 메소드 * @method doKeyMove * @private * @param {Object} e Event 객체 * @return {void} */ doKeyMove : function(e) { var k = DU.util.LKeyListener.KEY; switch (e.keyCode) { case k.ENTER: var activeItem = this.getActive(); if(activeItem != null) { this.doChangedItem(activeItem.dom); } this.collapse(); break; case k.DOWN: this.expand(); this.nextActive(); break; case k.UP: DU.util.LEvent.stopPropagation(e); this.expand(); this.prevActive(); break; case k.ESCAPE: this.collapse(); break; default: break; } }, /** * @description 키 입력에 따른 filter를 처리하는 메소드 * @method doKeyInput * @private * @param {Object} e Event 객체 * @return {void} */ doKeyInput : function(e) { this.isForceCheck = false; if(DU.util.LKeyListener.KEY.ENTER == e.keyCode) e.preventDefault(); if (DU.util.LKeyListener.KEY.TAB == e.keyCode) this.collapse(); var k = DU.util.LKeyListener.KEY; switch (e.keyCode) { case k.ENTER: case k.DOWN: case k.UP: case k.ESCAPE: break; default: this.lastValue = this.getDisplayEl().getValue(); if(this.filterTask) return; if(e.altKey == true|| e.ctrlKey == true) return; this.expand(); if(this.isAutoComplete == true) { this.filterTask = new DU.util.LDelayedTask(DU.util.LFunction.createDelegate(this.doFilter, this)); this.filterTask.delay(this.filterMode == 'remove' ? this.remoteDelayTime : this.localDelayTime); } break; } }, /** * @description filter시 처리하는 메소드 * @method doFilter * @private * @param {Object} e Event 객체 * @return {void} */ doFilter : function(e){ this.filterTask.cancel(); this.filterTask = null; this.filter(this.getDisplayEl().getValue()); }, /** * @description list를 출력하는 메소드 * @method expand * @protected * @return {void} */ expand : function() { if(this.disabled === true) return; if(this.isLoad !== true) this.doLoadDataSet(); if(this.optionDivEl && this.optionDivEl.hasClass('L-hide-display')) { this.doExpand(); if(this.getActiveIndex() < 0) this.firstActive(); this.getDisplayEl().dom.focus(); } }, /** * @description option div 객체 생성 * @method createOptionDiv * @protected * @return {void} */ createOptionDiv : function() { if(this.isUseDataSet === true) { var inputEl = this.getDisplayEl(); var optionDiv = document.createElement('div'); optionDiv.id = DU.id(); this.optionDivEl = DU.get(optionDiv); this.optionDivEl.setWidth(this.listWidth); this.optionDivEl.addClass(this.CSS_BASE + '-list-wrapper'); this.optionDivEl.addClass('L-hide-display'); this.optionDivEl.on('click', function(e) { inputEl.focus(); }); document.body.appendChild(optionDiv); } }, /** * @description option div에 해당되는 객체를 리턴한다. * @method getOptionDiv * @protected * @return {DU.LElement} */ getOptionDiv: function() { return this.optionDivEl; }, /** * @description 현재 활성화되어 있는 객체를 리턴 * @method getActive * @protected * @return {DU.LElement} */ getActive : function() { var activeList = this.optionDivEl.select('.active'); if(activeList.length < 1) return; return activeList.getAt(0); }, /** * @description 현재 활성화되어 있는 객체의 index를 리턴 * @method getActiveIndex * @protected * @return {Int} */ getActiveIndex : function() { var optionList = this.optionDivEl.select('div'); var idx = -1; for(var i = 0 ; i < optionList.length ; i++){ if(optionList.getAt(i).hasClass('active')) { idx = i; break; } } return idx; }, /** * @description 목록중에 h와 같은 html을 찾아 객체의 index를 리턴 * @method getDataIndex * @protected * @param {String} h 비교할 html 내용 * @return {Int} */ getDataIndex : function(h) { var optionList = this.optionDivEl.select('div'); var idx = -1; for(var i = 0 ; i < optionList.length ; i++){ if(optionList.getAt(i).dom.firstChild.nodeValue == h) { idx = i; break; } } if(idx > -1 && this.isEmptyText === true) idx--; return idx; }, /** * @description 목록중에 첫번째를 활성화하는 메소드 * @method firstActive * @protected * @return {void} */ firstActive : function() { var firstChildElList = this.optionDivEl.select(':first-child'); if(firstChildElList.length > 0) firstChildElList.getAt(0).addClass('active'); }, /** * @description 다음 목록을 활성화하는 메소드 * @method nextActive * @protected * @return {void} */ nextActive : function(){ var activeEl = this.getActive(); if(activeEl == null) { this.firstActive(); } else { var nextDom = Dom.getNextSibling(activeEl.dom); if(nextDom == null) return; var nextEl = DU.get(nextDom); activeEl.removeClass('active'); nextEl.addClass('active'); this.scrollDown(); } }, /** * @description 이전 목록을 활성화하는 메소드 * @method prevActive * @protected * @return {void} */ prevActive : function() { var activeEl = this.getActive(); if(activeEl == null) { this.firstActive(); } else { var prevDom = Dom.getPreviousSibling(activeEl.dom); if(prevDom == null) return; var prevEl = DU.get(prevDom); activeEl.removeClass('active'); prevEl.addClass('active'); this.scrollUp(); } }, /** * @description 목록이 스크롤다운이 되게 하는 메소드 * @method scrollDown * @protected * @return {void} */ scrollDown : function() { if ("scroll" != this.optionDivEl.getStyle(this.overflowCSS)) return; var activeEl = this.getActive(); var activeIndex = this.getActiveIndex() + 1; var minScroll = activeIndex * activeEl.getHeight() - this.optionDivEl.getHeight(); if (this.optionDivEl.dom.scrollTop < minScroll) this.optionDivEl.dom.scrollTop = minScroll; }, /** * @description 목록이 스크롤업이 되게 하는 메소드 * @method scrollUp * @protected * @return {void} */ scrollUp : function() { if ("scroll" != this.optionDivEl.getStyle(this.overflowCSS)) return; var activeEl = this.getActive(); var maxScroll = this.getActiveIndex() * activeEl.getHeight(); if (this.optionDivEl.dom.scrollTop > maxScroll) this.optionDivEl.dom.scrollTop = maxScroll; }, /** * @description 목록을 펼치는 메소드 * @method doExpand * @protected * @return {void} */ doExpand : function() { this.optionDivEl.removeClass('L-hide-display'); this.optionDivEl.addClass('L-show-display'); var top = this.el.getTop() + this.el.getHeight() + this.el.getBorderWidth('tb') + this.el.getPadding('tb') + this.optionDivEl.getBorderWidth('tb') + this.optionDivEl.getPadding('tb'); // ie7에서 document.documentElement.getBoundingClientRect의 값이 이상하게 나와 -2값으로 처리. var marginTop = DU.browser.msie7 ? -2 : 0; var marginLeft = DU.browser.msie7 ? -2 : 0; this.optionDivEl.setTop(top + marginTop); var left = this.el.getLeft(); this.optionDivEl.setLeft(left + marginLeft); this.activeItem(); //DU.util.LEvent.addListener(document, 'mousewheel', this.collapseIfDelegate, this); DU.util.LEvent.addListener(document, 'mousedown', this.collapseIfDelegate, this); this.reOnDeferOnBlur(); var count = this.dataSet.getCount(); if(this.dataSet.getCount() > this.expandCount) count = this.expandCount; if(this.optionDivEl.dom.childNodes.length > 0) { var childEl = DU.get(this.optionDivEl.dom.childNodes[this.optionDivEl.dom.childNodes.length - 1]); var childViewCount = (count + (this.isEmptyText ? 1 : 0)); var height = (childEl.getHeight() * childViewCount) + childViewCount; if(height > 0) this.optionDivEl.setHeight(height); } else this.optionDivEl.setHeight(20); this.fireEvent("expand"); }, /** * @description 목록이 펼쳐저 있는지 여부 * @method isExpand * @return {Boolean} */ isExpand : function() { return this.optionDivEl && this.optionDivEl.hasClass('L-show-display'); }, /** * @description target과 비교하여 목록을 줄이는 메소드 * @method collapseIf * @protected * @param {Object} e Event 객체 * @return {void} */ collapseIf : function(e) { var target = e.target; if (((this.optionDivEl && this.optionDivEl.dom == target)) || ((this.iconDivEl && this.iconDivEl.dom == target)) || ((this.inputEl && this.inputEl.dom == target))) return; var targetEl = DU.get(target); if(targetEl.hasClass('L-list')) { targetEl.removeClass('active'); this.doChangedItem(e.target); } this.collapse(); }, /** * @description 목록을 줄이는 메소드 * @method collapse * @protected * @return {void} */ collapse : function() { this.optionDivEl.removeClass('L-show-display'); this.optionDivEl.addClass('L-hide-display'); //DU.util.LEvent.removeListener(document, 'mousewheel', this.collapseIfDelegate, this); DU.util.LEvent.removeListener(document, 'mousedown', this.collapseIfDelegate, this); this.getDisplayEl().focus(); this.fireEvent("collapse"); this.optionDivEl.select('.active').removeClass('active'); }, /** * @description 현재 값에 맞는 목록을 활성화하는 메소드 * @method activeItem * @protected * @return {void} */ activeItem : function() { this.isForceCheck = false; var value = this.getDisplayEl().getValue(); if(value == '') return; var listElList = this.optionDivEl.select('.L-list'); var thisObj = this; listElList.each(function(child){ if(child.dom.firstChild.nodeValue == value) { child.addClass('active'); thisObj.scrollDown(); return false; } }); }, /** * @description 데이터셋이 Load 메소드가 호출되면 수행하는 이벤트 메소드 * @method doLoadDataSet * @private * @param {Object} e event 객체 * @return {void} */ doLoadDataSet: function() { if(this.optionDivEl) { this.onDataChangedDataSet(); this.focusDefaultValue(); } }, /** * @description 데이터셋이 beforeLoad 메소드가 호출되면 수행하는 이벤트 메소드 * @method onBeforeLoadDataSet * @private * @param {Object} e event 객체 * @return {void} */ onBeforeLoadDataSet: function(e) { this.dataSet.setRow(-1); }, /** * @description 데이터셋이 Load 메소드가 호출되면 수행하는 이벤트 메소드 * @method onLoadDataSet * @private * @return {void} */ onLoadDataSet : function(e) { this.doLoadDataSet(); this.isLoad = true; }, /** * @description 기본 값을 셋팅하는 메소드 * @method focusDefaultValue * @private * @return {void} */ focusDefaultValue : function() { this.setValue(this.defaultValue); }, /** * @description 목록에서 선택되면 출력객체에 값을 반영하는 메소드 * @method doChangedItem * @private * @param {HTMLElement} dom Dom 객체 * @return {void} */ doChangedItem : function(dom) { if(dom.innerHTML) { this.setValue(dom.childNodes[0].nodeValue); this.getDisplayEl().focus(); } }, /** * @description 데이터셋이 RowPosChanged 메소드가 호출되면 수행하는 이벤트 메소드 * @method onRowPosChangedDataSet * @private * @return {void} */ onRowPosChangedDataSet : function(e) { }, /** * @description 데이터셋이 add 메소드가 호출되면 수행하는 이벤트 메소드 * @method onAddData * @private * @return {void} */ onAddData : function(e) { var row = e.row, record = e.record, dataSet = e.target; var optionEl = this.createItem({ record : this.dataSet.getAt(row) }); if(dataSet.getCount(true) > 1) { var beforeRow = row - 1; if(beforeRow < 0) { var nextRow = row + 1; var nextRowEl = this.getRowEl(nextRow); if(nextRowEl == null) return; nextRowEl.insertBefore(optionEl.dom); } else { var beforeRowEl = this.getRowEl(beforeRow); if(beforeRowEl == null) return; beforeRowEl.insertAfter(optionEl.dom); } } else { this.getOptionDiv().appendChild(optionEl.dom); } }, /** * @description 데이터셋이 update 메소드가 호출되면 수행하는 이벤트 메소드 * @method onUpdateData * @private * @return {void} */ onUpdateData : function(e) { var row = e.row, col = e.col, colId = e.colId, record = e.record, dataSet = e.target; var currentRowEl = this.getRowEl(row); if(currentRowEl) { var optionEl = this.createItem({ record : this.dataSet.getAt(row) }); currentRowEl.html(optionEl.getHtml()); } }, /** * @description 데이터셋이 remove 메소드가 호출되면 수행하는 이벤트 메소드 * @method onRemoveData * @private * @return {void} */ onRemoveData : function(e) { var row = e.row, record = e.record, dataSet = e.target; var currentRowEl = this.getRowEl(row); (currentRowEl != null) ? currentRowEl.remove() : ''; }, /** * @description 데이터셋이 undo 메소드가 호출되면 수행하는 이벤트 메소드 * @method onUndoData * @private * @return {void} */ onUndoData : function(e) { var state = e.beforeState, row = e.row, record = e.record, dataSet = e.target; if(state == DU.data.LRecord.STATE_INSERT) { this.onRemoveData(e); } }, /** * @description 데이터셋이 DataChanged 메소드가 호출되면 수행하는 메소드 * @method onDataChangedDataSet * @private * @return {void} */ onDataChangedDataSet : function(e) { this.removeAllItem(); if(this.isEmptyText === true) this.createEmptyText(); if(this.optionDivEl) { for(var i = 0 ; i < this.dataSet.getCount() ; i++) { var optionEl = this.createItem({ record : this.dataSet.getAt(i) }); this.appendOption(optionEl.dom); } } }, /** * @description option 객체를 붙인다. * @method appendOption * @private * @param {HTMLElement} dom option dom 객체 * @return {void} */ appendOption: function(dom) { this.optionDivEl.appendChild(dom); }, /** * @description emptyText가 존재하는지 여부를 리턴한다. * @method hasEmptyText * @private * @return {Boolean} */ hasEmptyText : function() { if(!this.optionDivEl) return this.isEmptyText; if(this.optionDivEl.dom.childNodes.length < 1) return false; return Dom.hasClass(this.optionDivEl.dom.childNodes[0], 'L-empty'); }, /** * @description emptyText 항목을 생성한다. * @method createEmptyText * @private * @return {void} */ createEmptyText : function() { //if(this._rendered !== true) return; try { if(!this.el) return; var data = {}; data[this.valueField] = ''; data[this.displayField] = this.emptyText; var record = this.dataSet.createRecord(data); var optionEl = this.createItem({ record: record }); optionEl.addClass("L-empty"); this.insertEmptyText(optionEl.dom); } catch(e){} }, /** * @description emptyText 항목의 객체를 첫번째에 추가한다. * @method insertEmptyText * @private * @param {HTMLElement} dom option Dom 객체 * @return {void} */ insertEmptyText: function(dom) { if(this.optionDivEl.dom.childNodes.length > 0) Dom.insertBefore(dom, this.optionDivEl.dom.childNodes[0]); else this.optionDivEl.appendChild(dom); }, /** * @description emptyText 항목을 제거한다. * @method removeEmptyText * @private * @return {void} */ removeEmptyText : function() { if(this.hasEmptyText()) Dom.removeNode(this.optionDivEl.dom.childNodes[0]); }, /** * @description row에 해당되는 Element를 리턴하는 메소드 * @method getRowEl * @private * @return {DU.Element} */ getRowEl : function(row) { var rowElList = this.optionDivEl.select(".L-list"); return rowElList.length > 0 ? rowElList.getAt(row) : null; }, /** * @description 목록의 Item을 생성 * @method createItem * @private * @param {Object} e Event 객체 * @return {void} */ createItem : function(e) { var record = e.record; var displayValue = record.get(this.displayField); var option = document.createElement('div'); var optionEl = DU.get(option); var optionDivEl = this.optionDivEl; optionEl.hover(function(){ this.addClass('active'); }, function(){ optionDivEl.select('.active').removeClass('active'); }); optionEl.addClass('L-list'); var txtNode = document.createTextNode(displayValue); optionEl.appendChild(txtNode); return optionEl; }, /** * @description DataSet에 o객체를 추가하는 메소드 * @method add * @protected * @param {Object} o Record의 데이터 객체 * @param {Object} option Record의 생성시 option * @return {void} */ add : function(o, option){ var record = this.dataSet.createRecord(o, { id: this.dataSet.getNewRecordId() }); this.dataSet.add(record, option); }, /** * @description DataSet에 배열로 o객체를 추가하는 메소드 * @method addAll * @protected * @param {Array} o Record의 데이터 객체 배열 * @param {Object} option Record의 생성시 option * @return {void} */ addAll : function(o, option) { for(var i = 0 ; i < o.length ; i++) { this.add(o[i], option); } }, /** * @description DataSet에 row 위치의 있는 o객체를 반영하는 메소드 * @method setData * @protected * @param {Int} row row의 위치 * @param {Object} o Record의 데이터 객체 * @return {void} */ setData : function(row, o) { if(row > this.dataSet.getCount() - 1 || row == 0) return; var record = this.dataSet.getAt(row); record.setValues(o); }, /** * @description Record객체 배력을 추가한다. * @method removeAt * @protected * @param {int} index 지우고자 하는 위치값 * @return void */ removeAt : function(row) { this.dataSet.removeAt(row); }, /** * @description 목록의 모든 item을 삭제한다. * @method removeAllItem * @protected * @return void */ removeAllItem : function(){ if(this.optionDivEl != null) this.optionDivEl.select('.L-list').remove(); }, /** * @description 데이터셋의 레코드 건수를 리턴한다. * @method getCount * @protected * @return {Int} 데이터셋의 레코드 건수 */ getCount : function(){ return this.dataSet.getCount(); }, /** * @description 값에 따라 filter 하는 메소드 * @method filter * @protected * @param {String} val filter시 비교하는 값 * @return {void} */ filter : function(val) { if(this.filterMode == 'remote') { var p = {}; p[this.displayField] = val; this.dataSet.load({ url:this.filterUrl, params:p }); } else { this.dataSet.filter(function(id, record) { var val2 = record.get(this.displayField); if(DU.util.LString.startsWith(val2.toLowerCase(), val.toLowerCase())) return true; }, this, false); } }, /** * @description DataSet에 적용된 filter를 지운다. *Sample: 보기
* @method clearFilter * @public * @return {void} */ clearFilter : function(){ if(this.dataSet) this.dataSet.clearFilter(false); }, /** * @description 현재 값을 리턴 *Sample: 보기
* @method getValue * @public * @return {String} 결과값 */ getValue : function() { var value = this.getDisplayEl().getValue(); if(this.mask && value != null && value != '' && this.isMaskValue == false) { value = this.getUnMaskValue(value); } return (value == this.placeholder) ? '' : value; }, /** * @description mask가 입력된 값을 mask를 제외한 값으로 리턴한다. * @method getUnMaskValue * @protected * @param {String} value 입력 값 * @return {String} 결과값 */ getUnMaskValue : function(value) { var realValue = []; var defs = this.definitions; DU.each(value.split(""), function(c,i){ if(this.tests[i] && this.tests[i].test(c)) { realValue.push(c); } }, this); return realValue.join(""); }, /** * @description 현재 값을 리턴 *Sample: 보기
* @method getDisplayValue * @public * @return {String} 결과값 */ getDisplayValue : function() { return this.getDisplayEl().getValue(); }, /** * @description 출력객체에 내용을 변경한다. * @method setDisplayValue * @protected * @param {String} o 출력객체에 내용을 변경할 값 * @return void */ setDisplayValue : function(o) { this.getDisplayEl().setValue(o); }, /** * @description 값을 변경한다. *Sample: 보기
* @method setValue * @public * @param {String} o 반영할 값 * @return {void} */ setValue : function(o) { if(DU.isUndefined(o) == true || this.lastValue == o) return; this.getDisplayEl().dom.value = o; var displayValue = this.checkVal().displayValue; this.getDisplayEl().dom.value = displayValue; this.lastDisplayValue = displayValue; this.fireEvent('changed', {target:this, value:this.getValue(), displayValue:this.getDisplayValue()}); this.lastValue = o; }, /** * @description dataset을 리턴한다. *Sample: 보기
* @method getDataSet * @public * @return {DU.data.DataSet} */ getDataSet : function() { return this.dataSet; }, /** * @description dataset을 변경한다. * @method setDataSet * @public * @param {DU.data.LDataSet} newDataSet 신규 DataSet * @return {DU.data.DataSet} */ setDataSet: function(d) { this.dataSet = d; this.initDataSet(); this.onLoadDataSet(); }, /** * @description 키 입력시 호출되는 메소드 * @method onFireKey * @protected * @param {Object} e Event 객체 * @return {void} */ onFireKey : function(e){ if(DU.util.LEvent.isSpecialKey(e) && !this.isExpand()) this.fireEvent("specialkey", e); }, /** * @description mask 적용시 초기화 * @method initMask * @protected * @return {void} */ initMask: function() { var displayEl = this.getDisplayEl(); var displayDom = displayEl.dom; var defs = this.definitions; var tests = []; this.partialPosition = this.mask.length; this.firstNonMaskPos = null; this.maskLength = this.mask.length; DU.each(this.mask.split(""), function(c, i) { if (c == '?') { this.maskLength--; this.partialPosition = i; } else if (defs[c]) { tests.push(new RegExp(defs[c])); if(this.firstNonMaskPos==null) this.firstNonMaskPos = tests.length - 1; } else { tests.push(null); } }, this); this.tests = tests; this.buffer = []; DU.each(this.mask.split(""), function(c, i) { if (c != '?') this.buffer.push(defs[c] ? this.maskPlaceholder : c); }, this); if (!this.cfg.getProperty("disabled")) { this.on("focus", function() { focusText = this.getDisplayValue(); var pos = this.checkVal().pos; this.writeBuffer(); setTimeout(DU.util.LFunction.createDelegate(function() { if (pos == this.mask.length) this.setCaret(0, pos); else this.setCaret(pos); }, this), 0); }, this, true) this.on("blur", function() { this.setDisplayValue(this.checkVal().displayValue); }) this.on("keydown", this.onKeyDownMask, this, true); this.on("keypress", this.onKeyPressMask, this, true); this.on("paste", function(e) { setTimeout(DU.util.LFunction.createDelegate(function() { this.setCaret(this.checkVal(true).pos); }, this), 0); }, this, true); this.setDisplayValue(this.checkVal().displayValue); //Perform initial check for existing values } }, /** * @description 입력 input 객체에 select 지정 * @method setCaret * @protected * @param {Int} begin 처음 * @param {Int} end [optional] 마지막 * @return {void} */ setCaret: function(begin, end) { var displayEl = this.getDisplayEl(); var displayDom = displayEl.dom; end = (typeof end == 'number') ? end : begin; if (displayDom.setSelectionRange) { displayDom.focus(); displayDom.setSelectionRange(begin, end); } else if (displayDom.createTextRange) { var range = displayDom.createTextRange(); range.collapse(true); range.moveEnd('character', end); range.moveStart('character', begin); range.select(); } }, /** * @description select 범위 정보를 가지는 객체 리턴 * @method getCaret * @protected * @return {Object} */ getCaret: function() { var displayEl = this.getDisplayEl(); var displayDom = displayEl.dom; if (displayDom.setSelectionRange) { begin = displayDom.selectionStart; end = displayDom.selectionEnd; } else if (document.selection && document.selection.createRange) { var range = document.selection.createRange(); begin = 0 - range.duplicate().moveStart('character', -100000); end = begin + range.text.length; } return { begin: begin, end: end }; }, /** * @description buffer에 가지고 있는 정보를 지우는 메소드 * @method clearBuffer * @protected * @param {Int} start 시작 * @param {Int} end 끝 * @return {void} */ clearBuffer: function(start, end) { for (var i = start; i < end && i < this.maskLength; i++) { if (this.tests[i]) this.buffer[i] = this.maskPlaceholder; } }, /** * @description buffer에 가지고 있는 정보를 출력하는 객체에 적용하는 메소드 * @method writeBuffer * @protected * @return {void} */ writeBuffer: function() { return this.setDisplayValue(this.buffer.join('')); }, /** * @description mask 적용시 keydown 이벤트 * @method onKeyDownMask * @protected * @param {Object} e event 객체 * @return {void} */ onKeyDownMask: function(e) { var pos = this.getCaret(); var k = e.keyCode; this.ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41)); //delete selection before proceeding if ((pos.begin - pos.end) != 0 && (!this.ignore || k == 8 || k == 46)) this.clearBuffer(pos.begin, pos.end); //backspace, delete, and escape get special treatment if (k == 8 || k == 46 || (DU.browser.iPhone && k == 127)) {//backspace/delete this.shiftL(pos.begin + (k == 46 ? 0 : -1)); DU.util.LEvent.stopEvent(e); return false; } else if (k == 27) {//escape this.setDisplayValue(focusText); this.setCaret(0, this.checkVal().pos); DU.util.LEvent.stopEvent(e); return false; } }, /** * @description mask 적용시 keypress 이벤트 * @method onKeyPressMask * @protected * @param {Object} e event 객체 * @return {void} */ onKeyPressMask: function(e) { if (this.ignore) { this.ignore = false; //Fixes Mac FF bug on backspace return (e.keyCode == 8) ? false : null; } e = e || window.event; var k = e.charCode || e.keyCode || e.which; var pos = this.getCaret(); if (e.ctrlKey || e.altKey || e.metaKey) {//Ignore return true; } else if ((k >= 32 && k <= 125) || k > 186) {//typeable characters var p = this.seekNext(pos.begin - 1); if (p < this.maskLength) { var c = String.fromCharCode(k); if (this.tests[p].test(c)) { this.shiftR(p); this.buffer[p] = c; this.writeBuffer(); var next = this.seekNext(p); this.setCaret(next); /* * 이벤트 처리 할까? 오히려 성능 저하 및 소스가 꼬일 확율이 있어서리... if (this.completed && next == this.maskLength) this.completed.call(input); */ } } } DU.util.LEvent.stopEvent(e); return false; }, /** * @description mask 적용시 buffer값중 현재 위치가 찾기 * @method seekNext * @protected * @param {Int} pos mask의 현재 위치값 * @return {void} */ seekNext: function(pos) { while (++pos <= this.maskLength && !this.tests[pos]); return pos; }, /** * @description mask 적용시 buffer를 지정하는 위치를 왼쪽으로 이동 * @method shiftL * @protected * @param {Int} pos 이동할 값 * @return {void} */ shiftL: function(pos) { while (!this.tests[pos] && --pos >= 0); for (var i = pos; i < this.maskLength; i++) { if (this.tests[i]) { this.buffer[i] = this.maskPlaceholder; var j = this.seekNext(i); if (j < this.maskLength && this.tests[i].test(this.buffer[j])) { this.buffer[i] = this.buffer[j]; } else break; } } this.writeBuffer(); this.setCaret(Math.max(this.firstNonMaskPos, pos)); }, /** * @description mask 적용시 buffer를 지정하는 위치를 오른쪽으로 이동 * @method shiftR * @protected * @param {Int} pos 이동할 값 * @return {void} */ shiftR: function(pos) { for (var i = pos, c = this.maskPlaceholder; i < this.maskLength; i++) { if (this.tests[i]) { var j = this.seekNext(i); var t = this.buffer[i]; this.buffer[i] = c; if (j < this.maskLength && this.tests[j].test(t)) c = t; else break; } } }, /** * @description mask 적용시 입력값의 유효성을 검사하여 실제 값에 대입하는 메소드 * @method checkVal * @protected * @param {boolean} allow 이동할 값 * @return {Int} */ checkVal: function(allow) { var test = this.getDisplayValue(); var lastMatch = -1; for (var i = 0, pos = 0; i < this.maskLength; i++) { if (this.tests[i]) { this.buffer[i] = this.maskPlaceholder; while (pos++ < test.length) { var c = test.charAt(pos - 1); if (this.tests[i].test(c)) { this.buffer[i] = c; lastMatch = i; break; } } if (pos > test.length) break; } else if (this.buffer[i] == test[pos] && i!=this.partialPosition) { pos++; lastMatch = i; } } if (!allow && lastMatch + 1 < this.partialPosition) { test = ""; this.clearBuffer(0, this.maskLength); } else if (allow || lastMatch + 1 >= this.partialPosition) { this.writeBuffer(); if (!allow) { test = this.getDisplayValue().substring(0, lastMatch + 1); }; } return { pos : (this.partialPosition ? i : this.firstNonMaskPos), displayValue: test } }, /** * @description 입력된 값의 유효성 체크 * @method validateValue * @protected * @param {String} value 입력된 값 * @return {boolean} */ validateValue: function(value) { if(this.vm) { if(this.vm.validateEl(this) !== true) return false; } if (this.type == 'email' && this.getValue() != '') return new DU.validate.LEmailValidator({id: this.id}).validate(this.getValue()); return true; } }); })(); /** * Form * @module widget_form * @title LCombo * @requires DU */ DU.namespace("DU.widget"); (function(){ var Dom = DU.util.LDom; /** * LCombo * @namespace DU.widget * @class LCombo * @extends DU.widget.LTextBox * @constructor LCombo * @param {HTMLElement | String} id The html element that represents the Element. * @param {Object} oConfig The intial LCombo. */ DU.widget.LCombo = function(oConfig){ var config = oConfig || {}; this.overflowCSS = DU.browser.opera ? "overflow" : "overflowY"; config = Dom.applyIfProperties(config, '$.ext.combo'); /** * @description valueField 명 *Sample: 보기
* @config valueField * @type {String} * @default 'code' */ /** * @description valueField 명 * @property valueField * @private * @type {String} */ this.valueField = config.valueField || DU.getConfig().getFirst('$.ext.combo.dataset.valueField'); /** * @description displayField 명 *Sample: 보기
* @config displayField * @type {String} * @default 'value' */ /** * @description displayField 명 * @property displayField * @private * @type {String} */ this.displayField = config.displayField || DU.getConfig().getFirst('$.ext.combo.dataset.displayField'); this.emptyText = config.emptyText || this.emptyText; DU.widget.LCombo.superclass.constructor.call(this, config); this.dataSet.focusFirstRow = DU.isUndefined(this.focusFirstRow) == false ? this.focusFirstRow : false; } DU.extend(DU.widget.LCombo, DU.widget.LTextBox, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LCombo', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-combo', /** * @description 기본 emptyText 메시지 코드값 * @property emptyTextMessageCode * @private * @type {String} */ emptyTextMessageCode : '$.base.msg108', /** * @description 값이 비였을때 출력할 text값 *Sample: 보기
* @config emptyText * @type {String} * @default '' */ /** * @description 값이 비였을때 출력할 text값 * @property emptyText * @private * @type {String} */ emptyText : null, /** * @description '선택하세요.' 항목 추가 여부 *Sample: 보기
* @config isEmptyText * @type {Boolean} * @default true */ /** * @description '선택하세요.' 항목 추가 여부 * @property isEmptyText * @private * @type {Boolean} */ isEmptyText : true, /** * @description 선택 필수 여부 *Sample: 보기
* @config forceSelection * @type {Boolean} * @default true */ /** * @description 선택 필수 여부 * @property forceSelection * @private * @type {Boolean} */ forceSelection : true, /** * @description 변경전 마지막 출력값 * @property lastDisplayValue * @private * @type {String} */ lastDisplayValue : '', /** * @description 값 변경 여부 * @property isChange * @private * @type {Boolean} */ isChange : false, /** * @description 기본 설정 값 *Sample: 보기
* @config defaultValue * @type {String} * @default '' */ /** * @description 기본 설정 값 * @property defaultValue * @private * @type {String} */ defaultValue : '', /** * @description 데이터 로딩시 combo의 row 위치 *Sample: 보기
* @config selectedIndex * @type {Int} * @default '' */ /** * @description 데이터 로딩시 combo의 row 위치 * @property selectedIndex * @private * @type {Int} */ selectedIndex : -1, /** * @description edit 가능 여부 *Sample: 보기
* @config editable * @type {Boolean} * @default false */ /** * @description edit 가능 여부 * @property editable * @private * @type {Boolean} */ editable : false, /** * @description dataSet 사용 여부 *Sample: 보기
* @config isUseDataSet * @type {Boolean} * @default true */ /** * @description dataSet 사용 여부 * @property isUseDataSet * @private * @type {Boolean} */ isUseDataSet : true, /** * @description item 선택시 row이동을 반드시 할 것인지여부 *Sample: 보기
* @config isForceRow * @type {Boolean} * @default false */ /** * @description item 선택시 row이동을 반드시 할 것인지여부 * @property isForceRow * @private * @type {Boolean} */ isForceRow : false, /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(id, oConfig) { this.emptyText = this.emptyText || DU.getMessageManager().get(this.emptyTextMessageCode); if(this.cfg.getProperty('isEmptyText') === true) this.forceSelection = false; }, /** * @description element Dom객체 생성 * @method createContainer * @protected * @param {HTMLElement} parentNode 부모 노드 * @return {HTMLElement} */ createContainer : function(parentNode) { if(this.el) { if(this.el.dom.tagName == 'SELECT') { this.id = this.id || this.el.id; this.oldDom = this.el.dom; if(this.oldDom.options && 0 < this.oldDom.options.length) { this.optionsData = []; for(var i = 0 ; this.oldDom.options && i < this.oldDom.options.length; i++) { if(Dom.hasClass(this.oldDom.options[i], 'empty')) { this.cfg.setProperty('isEmptyText', true); this.emptyText = this.oldDom.options[i].text; continue; } var option = { value: this.oldDom.options[i].value, text: this.oldDom.options[i].text }; this.optionsData.push(option); } } this.name = this.name || this.oldDom.name; var parent = this.el.parent(); this.el = DU.get(this.createElement().cloneNode(false)); this.el.dom.id = this.id; Dom.replaceChild(parent.dom, this.el.dom, this.oldDom); this.el.appendChild(this.oldDom); Dom.removeNode(this.oldDom); delete this.oldDom; } } DU.widget.LTextBox.superclass.createContainer.call(this, parentNode); }, /** * @description render시 발생하는 메소드 * @method doRender * @protected * @param {HttpElement} appendToNode 부모 객체 * @return {void} */ doRender : function(container) { this.createComboTemplete(this.el); }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LCombo.superclass.afterRender.call(this, container); if(this.dataSet.getCount() == 0 && this.optionsData) { for(var i = 0 ; i < this.optionsData.length ; i++) { var row = this.dataSet.newRecord(); if(row === false) break; this.dataSet.setNameValue(row, this.valueField, this.optionsData[i].value); this.dataSet.setNameValue(row, this.displayField, this.optionsData[i].text); this.dataSet.setState(row, DU.data.LRecord.STATE_NORMAL); } this.dataSet.setRow(this.forceSelection === true ? 0 : 1); delete this.optionsData; } if(this.iconDivEl) this.iconDivEl.on('click', this.doIconClick, this, true); this.applyEmptyText(); }, createDataSet: function() { this.dataSet = new (eval(this.dataSetClassName))({ id: 'dataSet', fields:[ {id:this.valueField}, {id:this.displayField} ], focusFirstRow : false }) }, /** * @description icon click 이벤트가 발생하면 호출되는 메소드 * @method doIconClick * @protected * @param {Object} e Event 객체 * @return {void} */ doIconClick : function(e) { this.expand(); }, /** * @description Dom객체 생성 * @method createComboTemplete * @private * @param {String|Object} el 객체의 아이디나 객체 * @return {DU.LElement} Element 객체 */ createComboTemplete : function(el) { var elContainer = el; elContainer.addClass(this.CSS_BASE); elContainer.addClass("L-fixed"); var input = document.createElement('input'); elContainer.appendChild(input); this.inputEl = DU.get(input); var hiddenInput = document.createElement('input'); hiddenInput.name = this.id; hiddenInput.style.display = "none"; hiddenInput.className = DU.widget.LCombo.CSS_HIDDEN_COMBO; hiddenInput.instance = this; elContainer.appendChild(hiddenInput); this.hiddenInputEl = DU.get(hiddenInput); var iconDiv = document.createElement('div'); iconDiv.className = 'icon'; iconDiv.id = DU.id(); this.iconDivEl = DU.get(iconDiv); elContainer.appendChild(iconDiv); return elContainer; }, /** * @description width 속성에 따른 실제 적용 메소드 * @method _setWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setWidth : function(type, args, obj) { var width = args[0]; if (!DU.isBorderBox) { this.el.setWidth(width); this.getDisplayEl().setWidth(width - 16); this.iconDivEl.setLeft(width - 16); } else { this.el.setWidth(width - this.borderWidth); this.getDisplayEl().setWidth(width - (16 + this.borderWidth)); this.iconDivEl.setLeft(width - (16 + this.borderWidth)); } this.width = width; this.cfg.setProperty('width', this.width, true); }, /** * @description Index 위치를 변경한다. * @method setSelectedIndex * @public * @param {Int} idx 위치를 변경할 값 * @return void */ setSelectedIndex : function(idx) { if(this.dataSet.getCount() - 1 < idx) return; this.dataSet.setRow(idx, {isForce:this.isForceRow}); }, /** * @description DataSet이 load후 기본으로 셋팅될 값을 변경한다. * @method setDefaultValue * @public * @param {String} o 기본 코드 값 * @return void */ setDefaultValue: function(o) { this.defaultValue = o; }, /** * @description 기본 값을 셋팅하는 메소드 * @method focusDefaultValue * @private * @return {void} */ focusDefaultValue : function() { if(this.isLoad !== true && !this.defaultValue) this.defaultValue = this.getValue(); if(this.defaultValue) this.setValue(this.defaultValue); else if(this.selectedIndex >= 0) { if(this.dataSet.getCount() - 1 >= this.selectedIndex) this.setValue(this.dataSet.getNameValue(this.selectedIndex, this.valueField)); } }, /** * @description 출력객체에 내용을 변경한다. * @method setDisplayValue * @protected * @param {String} o 출력객체에 내용을 변경할 값 * @return void */ setDisplayValue : function(o) { if(o != this.getDisplayValue()) { o = this.forceSelection === true ? (this.isForceSelectValue(o) ? o : this.lastDisplayValue ) : o; this.inputEl.setValue(o); this.applyEmptyText(); this.bindDataSet(); } this.lastDisplayValue = this.inputEl.getValue(); if(this.lastDisplayValue == this.emptyText) this.lastDisplayValue = ''; }, /** * @description 목록에서 선택된 항목에 대한 값을 값객체에 반영한다. * @method bindDataSet * @private * @return void */ bindDataSet : function() { if(this.dataSet) { var dataIndex = this.getDataIndex(this.getDisplayValue()); if(dataIndex > -1) { this.dataSet.setRow(dataIndex, {isForce:this.dataSet.isFilter()}); if(dataIndex > -1) { var record = this.dataSet.getAt(dataIndex); this.hiddenInputEl.setValue(record.get(this.valueField)); } else { this.hiddenInputEl.setValue(''); } } else { this.hiddenInputEl.setValue(''); } } this.isChange = true; }, /** * @description 목록에서 선택되었는지 여부 * @method isForceSelectValue * @private * @param {String} o 비교할 값 * @return void */ isForceSelectValue : function(o) { var listElList = this.optionDivEl.select('.L-list'); var isSelection = false; listElList.each(function(child){ if(child.dom.firstChild.nodeValue == o) { isSelection = true; return false; } }); return isSelection; }, /** * @description 값이 없으면 기본 메시지를 출력하는 메소드 * @method applyEmptyText * @private * @return void */ applyEmptyText : function() { if(this.inputEl.getValue() == '' || this.inputEl.getValue() == this.emptyText) { this.inputEl.setValue(this.emptyText); this.inputEl.addClass('empty'); } else { this.inputEl.removeClass('empty'); } }, /** * @description 출력 객체의 값을 리턴 * @method getDisplayValue * @return {String} 출력값 */ getDisplayValue : function() { var o = this.inputEl.getValue(); o = (o == this.emptyText) ? '' : o; return o; }, /** * @description 현재 DataSet의 fieldName에 해당되는 값을 리턴 * @method getBindValue * @param {String} fieldName [optional] 필드이름 * @return {Object} 출력값 */ getBindValue : function(fieldName) { fieldName = fieldName || this.valueField; var val = this.getValue(); var row = this.dataSet.findRow(this.valueField, val); if(row < 0) return ""; return this.dataSet.getAt(row).get(fieldName); }, /** * @description 객체를 destroy하는 메소드 * @method destroy * @public * @return void */ destroy : function() { DU.widget.LCombo.superclass.destroy.call(this); this.iconDivEl = null; this.hiddenInputEl = null; }, /** * @description DataSet의 내용으로 목록을 재생성하는 메소드 * @method repaint * @public * @return void */ repaint : function() { this.onLoadDataSet(); this.applyEmptyText(); }, /** * @description 목록에서 선택되면 출력객체에 값을 반영하는 메소드 * @method doChangedItem * @private * @param {HTMLElement} dom Dom 객체 * @return {void} */ doChangedItem : function(dom) { var displayValue = dom.childNodes[0].nodeValue; var row = this.dataSet.findRow(this.displayField, displayValue); this.setValue(this.dataSet.getNameValue(row, this.valueField)); this.getDisplayEl().focus(); }, /** * @description 데이터셋이 RowPosChanged 메소드가 호출되면 수행하는 메소드 * @method onRowPosChangedDataSet * @private * @return {void} */ onRowPosChangedDataSet : function(e) { if(!this.hiddenInputEl) return; if(e.row < 0) { this.setDisplayValue(''); } else { var record = this.dataSet.getAt(e.row); var value = record.get(this.valueField); if(value) { this.hiddenInputEl.setValue(value); var displayValue = record.get(this.displayField); this.inputEl.setValue(displayValue); } } }, /** * @description 현재 값을 리턴 * @method getValue * @public * @return {String} 결과값 */ getValue : function() { return this.hiddenInputEl.getValue(); }, /** * @description 값을 변경한다. * @method setValue * @public * @param {String} o 반영할 값 * @return {void} */ setValue : function(o) { if(this.hiddenInputEl.dom.value === o) return; var row = this.dataSet.findRow(this.valueField, o); this.dataSet.setRow(row); if(this.forceSelection === true && row < 0) this.hiddenInputEl.dom.value = ""; this.fireEvent('changed', {target:this, value:this.getValue(), displayValue:this.getDisplayValue()}); }, /** * @description disabled 속성에 따른 실제 적용 메소드 * @method _setDisabled * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setDisabled : function(type, args, obj) { if(this.isExpand()) this.collapse(); args = args[0]; if(args === false) { this.disabled = false; var displayEl = this.getDisplayEl(); if(displayEl) { displayEl.enable(); if(this.iconDivEl) this.iconDivEl.enable(); } this.enableEvent.fire(); } else { this.disabled = true; var displayEl = this.getDisplayEl(); if(displayEl) { displayEl.disable(); if(this.iconDivEl) this.iconDivEl.disable(); } this.disableEvent.fire(); } }, /** * @description height 속성에 따른 실제 적용 메소드 * @method _setHeight * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setHeight : function(type, args, obj) { DU.widget.LCombo.superclass._setHeight.call(this, type, args, obj); var height = args[0]; if(height < 0) return; if(this.iconDivEl) this.iconDivEl.setHeight(height); }, /** * @description display renderer * @method displayRenderer * @param {DU.widget.LCombo} combo 콤보 객체 * @return {String} */ displayRenderer : function(combo) { var dataSet = combo.getDataSet(); return function(val, p, record, row, i) { var displayValue = null; if(record.state == DU.data.LRecord.STATE_NORMAL) { displayValue = record.get(combo.displayField); } else { var row = dataSet.findRow(combo.valueField, val); displayValue = (row > -1) ? dataSet.getAt(row).get(combo.displayField) : val; } return displayValue ; } }, /** * @description focus 이벤트 발생시 호출되는 메소드 * @method onFocus * @private * @param {Object} e Event 객체 * @return void */ onFocus : function(e) { DU.widget.LCombo.superclass.onFocus.call(this, e); var inputEl = this.getDisplayEl(); inputEl.removeClass('empty'); if(inputEl.getValue() == this.emptyText) { if(this.editable === true) inputEl.setValue(''); } }, /** * @description blur 이벤트 발생시 호출되는 메소드 * @method onBlur * @private * @param {Object} e Event 객체 * @return void */ onBlur : function(e) { DU.widget.LCombo.superclass.onBlur.call(this, e); this.doForceSelection(); this.applyEmptyText(); }, /** * @description 출력데이터가 변경되면 호출되는 메소드 * @method doChangedDisplayValue * @private * @param {String} o 적용할 값 * @return void */ doChangedDisplayValue : function(o) { this.bindDataSet(); }, /** * @description 필수 선택 메소드 * @method doForceSelection * @private * @return void */ doForceSelection : function() { if(this.forceSelection === true) { if(this.isChange == true) { var inputEl = this.getDisplayEl(); var row = this.dataSet.findRow(this.displayField, inputEl.getValue()); if(row < 0) this.setDisplayValue(this.lastDisplayValue); else this.bindDataSet(); } } }, /** * @description 객체의 toString * @method toString * @public * @return {String} */ toString : function() { return 'DU.form.LCombo ' + this.id; } }); DU.widget.LCombo.CSS_HIDDEN_COMBO = "L-combo-hidden"; })(); /** * Form * @module widget_form * @title LBasicCombo * @requires DU */ DU.namespace("DU.widget"); /** * LBasicCombo * @namespace DU.widget * @class LBasicCombo * @extends DU.widget.LUIComponent * @constructor LBasicCombo * @param {Object} oConfig The intial LBasicCombo. */ DU.widget.LBasicCombo = function(id, oConfig){ DU.widget.LBasicCombo.superclass.constructor.call(this, id, oConfig); } DU.extend(DU.widget.LBasicCombo, DU.widget.LCombo, { /** * @description 선택 필수 여부 * @config forceSelection * @type {Boolean} * @default false */ /** * @description 선택 필수 여부 * @property forceSelection * @private * @type {Boolean} */ forceSelection : false, /** * @description Dom객체 생성 * @method createComboTemplete * @private * @param {String|Object} el 객체의 아이디나 객체 * @return {DU.LElement} Element 객체 */ createComboTemplete : function(el) { var elContainer = el; var parent = null; if(elContainer.dom.tagName == 'DIV') { parent = elContainer.parent(); var select = document.createElement('select'); parent.appendChild(select); elContainer.removeNode(); elContainer = DU.get(select); } elContainer.addClass(this.CSS_BASE); elContainer.addClass("L-fixed"); this.el = elContainer; this.inputEl = elContainer; this.hiddenInputEl = elContainer; return elContainer; }, /** * @description container안의 content의 focus/blur 연결 설정 * @method initFocus * @protected * @return {void} */ initFocus: function() { }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LCombo.superclass.afterRender.call(this, container); this.inputEl.on('change', function(e){ var row = this.inputEl.dom.selectedIndex; row = (this.isEmptyText === true) ? row - 1 : row; this.dataSet.setRow(row); }, this, true); this.applyEmptyText(); }, /** * @description width 속성에 따른 실제 적용 메소드 * @method _setWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setWidth : function(type, args, obj) { var width = args[0]; if (!DU.isBorderBox) { this.el.setWidth(width); } else { this.el.setWidth(width - 4); } this.width = width; this.cfg.setProperty('width', this.width, true); }, /** * @description option 객체를 붙인다. * @method appendOption * @private * @param {HTMLElement} dom option dom 객체 * @return {void} */ appendOption: function(dom) { this.getDisplayEl().appendChild(dom); }, /** * @description 목록의 모든 item을 삭제한다. * @method removeAllItem * @protected * @return void */ removeAllItem : function(){ this.getDisplayEl().html(''); }, /** * @description 목록의 Item을 생성 * @method createItem * @private * @param {Object} e Event 객체 * @return {void} */ createItem : function(e) { var record = e.record; var codeValue = record.get(this.valueField); var displayValue = record.get(this.displayField); var option = document.createElement('option'); var optionEl = DU.get(option); option.value = codeValue; var txtNode = document.createTextNode(displayValue); optionEl.appendChild(txtNode); return optionEl; }, /** * @description emptyText 항목의 객체를 첫번째에 추가한다. * @method insertEmptyText * @private * @param {HTMLElement} dom option Dom 객체 * @return {void} */ insertEmptyText: function(dom) { if(this.optionDivEl.dom.childNodes.length > 0) DU.util.LDom.insertBefore(dom, this.inputEl.dom.childNodes[0]); else this.inputEl.appendChild(dom); }, /** * @description 현재 값을 리턴 * @method getValue * @public * @return {String} 결과값 */ getValue : function() { return this.inputEl.dom[this.inputEl.dom.selectedIndex].value; }, /** * @description 현재 값을 리턴 *Sample: 보기
* @method getDisplayValue * @public * @return {String} 결과값 */ getDisplayValue : function() { return this.inputEl.dom[this.inputEl.dom.selectedIndex].text; }, /** * @description 데이터셋이 RowPosChanged 메소드가 호출되면 수행하는 이벤트 메소드 * @method onRowPosChangedDataSet * @private * @return {void} */ onRowPosChangedDataSet : function(e) { var row = (this.isEmptyText === true) ? e.row + 1 : e.row; this.setValue(row < 0 ? '' : this.inputEl.dom[row].value); this.fireEvent('changed', {target:this, value:this.getValue(), displayValue:this.getDisplayValue()}); }, /** * @description 값을 변경한다. * @method setValue * @public * @param {String} o 반영할 값 * @return {void} */ setValue : function(o) { var row = this.dataSet.findRow(this.valueField, o); this.dataSet.setRow(row); row = (this.isEmptyText === true) ? row + 1 : row; this.inputEl.dom[row].selected = true; }, /** * @description row에 해당되는 Element를 리턴하는 메소드 * @method getRowEl * @private * @return {DU.Element} */ getRowEl : function(row) { row = (this.isEmptyText === true) ? row + 1 : row; return DU.get(this.inputEl.dom[row]); }, /** * @description option div에 해당되는 객체를 리턴한다. * @method getOptionDiv * @protected * @return {DU.LElement} */ getOptionDiv: function() { return this.inputEl; }, /** * @description 목록중에 h와 같은 html을 찾아 객체의 index를 리턴 * @method getDataIndex * @protected * @param {String} h 비교할 html 내용 * @return {Int} */ getDataIndex : function(h) { var optionList = this.inputEl.dom.options; var idx = -1; for(var i = 0 ; i < optionList.length ; i++){ if(optionList[i].text == h) { idx = i; break; } } if(idx > -1 && this.isEmptyText === true) idx--; return idx; } }); /** * LCheckBox * @module widget_form * @title LCheckBox * @requires DU */ DU.namespace("DU.widget"); /** * LCheckBox * @namespace DU.widget * @class LCheckBox * @extends DU.widget.LField * @constructor LCheckBox * @param {Object} oConfig The intial LCheckBox. */ DU.widget.LCheckBox = function(oConfig){ var config = oConfig || {}; config = DU.util.LDom.applyIfProperties(config, '$.ext.checkBox'); DU.applyObject(this, config, true); DU.widget.LCheckBox.superclass.constructor.call(this, config); this.deferOnBlurDelegate = DU.util.LFunction.createDelegate(this.deferOnBlur, this); } DU.extend(DU.widget.LCheckBox, DU.widget.LField, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LCheckBox', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-checkbox', /** * @description label로 출력할 값 * @config label * @type {String} * @default null */ /** * @description label로 출력할 값 * @property label * @private * @type {String} */ label : '', /** * @description 선택시 값 * @config value * @type {String} * @default null */ /** * @description 선택시 값 * @property value * @private * @type {String} */ value : null, /** * @description 체크 여부 *Sample: 보기
* @config checked * @type {Boolean} * @default false */ /** * @description 체크 여부 * @property checked * @private * @type {Boolean} */ checked : false, /** * @description value checkbox 선택시 dataset에 bind할 값 *Sample: 보기
* @config bindValues * @type {Array} * @default null */ /** * @description checkbox 선택시 dataset에 bind할 값 * @property bindValues * @private * @type {Array} */ bindValues : null, /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ DU.widget.LCheckBox.superclass.initComponent.call(this); if(!this.id) { this.id = DU.id(); } this.createTemplate(); }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LCheckBox.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LCheckBox.superclass.initDefaultConfig.call(this); /** * Specifies whether the Module is visible on the page. * @config visible * @type Boolean * @default true */ this.cfg.addProperty("checked", { handler: this.configChecked, value: this.checked }); }, /** * @description disabled 속성에 따른 실제 적용 메소드 * @method configChecked * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return {void} */ configChecked : function(type, args, obj) { var val = args[0]; this.checked = val; this.getDisplayEl().dom.checked = val; if(val) this.el.addClass("L-checked"); else this.el.removeClass("L-checked"); this.fireEvent('changed', {target:this, value:val}); }, /** * @description disabled 속성에 따른 실제 적용 메소드 * @method _setDisabled * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return {void} */ _setDisabled : function(type, args, obj) { if(args[0] === false) { this.getDisplayEl().enable(); } else { this.getDisplayEl().disable(); } DU.widget.LCheckBox.superclass._setDisabled.call(this, type, args, obj); }, /** * @description render시 호출되는 메소드 * @method doRender * @public * @param {String|Object} container 부모객체 정보 * @return void */ doRender : function(appendToNode) { this.el.addClass(this.CSS_BASE + "-panel"); this.el.addClass("L-fixed"); if(this.width) this.el.setWidth(!DU.isBorderBox ? this.width - 1 : this.width - 2); var html = this.getRenderBody(); this.el.html(html); }, /** * @description template 생성 * @method createTemplate * @protected * @return {void} */ createTemplate : function() { var ts = this.templates || {}; ts = new DU.LTemplate( '' ); this.templates = ts; }, /** * @description body html을 생성하여 리턴하는 메소드 * @method getRenderBody * @return {String} */ getRenderBody : function() { var ts = this.templates || {}; var p = { id : DU.id(), name : this.name, value : this.value, label : this.label, checked : this.checked ? 'checked=""' : '' }; return ts.apply(p); }, /** * @description render후 호출되는 메소드 * @method afterRender * @protected * @param {HTMLElement} container 부모 객체 * @return void */ afterRender : function(container) { DU.widget.LCheckBox.superclass.afterRender.call(this, container); if(this.checked) this.el.addClass("L-checked"); else this.el.removeClass("L-checked"); var displayEl = this.getDisplayEl(); this.el.on('click', function(e) { displayEl.focus(); DU.util.LEvent.stopPropagation(e); }); if(displayEl) { displayEl.on('focus', this.onCheckFocus, this, true); displayEl.on('click', this.onClick, this, true); } }, onClick : function(e) { this.cfg.setProperty('checked', e.target.checked); }, /** * @description 화면 출력되는 객체 리턴 * @method getDisplayEl * @protected * @return {DU.LElement} Element 객체 */ getDisplayEl : function() { if(!this.displayEl) { this.displayEl = this.el.select("input:checkbox").getAt(0); } return this.displayEl; }, /** * @description 객체를 유효한 상태로 설정하는 메소드 * @method valid * @public * @return {void} */ valid : function(){ this.el.valid(); this.validEvent.fire(); }, /** * @description 객체를 유효하지 않은 상태로 설정하는 메소드 * @method invalid * @public * @return {void} */ invalid : function(message) { this.el.invalid(message); this.invalidEvent.fire(message); }, /** * @description 객체를 focus한다. * @method focus * @public * @return {void} */ focus : function() { this.getDisplayEl().focus(); }, /** * @description 객체를 blur한다. * @method blur * @public * @return {void} */ blur : function() { this.getDisplayEl().blur(); }, /** * @description 객체를 destroy하는 메소드 * @method destroy * @public * @return void */ destroy : function() { var displayEl = this.getDisplayEl(); this.displayEl.unOnAll(); this.displayEl = null; DU.widget.LCheckBox.superclass.destroy.call(this); }, /** * @description 값을 변경한다. * @method setValue * @public * @param {String} o 반영할 값 * @return {void} */ setValue : function(val) { val = (this.bindValues) ? this.bindValues[0] == val ? true : false : val; var checked = (val === true || val == '1' || String(val).toLowerCase() == 'on'); this.cfg.setProperty('checked', checked); }, /** * @description 현재 값을 리턴 * @method getValue * @public * @return {String} 결과값 */ getValue : function() { return (this.bindValues) ? this.bindValues[this.checked ? 0 : 1] : this.checked; }, /** * @description 화면 출력객체의 실제 value값을 값을 리턴 * @method getRawValue * @public * @return {String} 결과값 */ getRawValue : function() { if(this.checked) return this.getDisplayEl().getValue(); else return ""; }, /** * @description blur 이벤트 발생시 호출되는 메소드 * @method onBlur * @private * @param {Object} e Event 객체 * @return void */ onBlur : function(e) { if(this.cfg.getProperty("checked") != this.getDisplayEl().dom.checked) this.cfg.setProperty("checked", this.getDisplayEl().dom.checked); DU.widget.LCheckBox.superclass.onBlur.call(this); }, /** * @description item객체가 focus되면 호출되는 메소드 * @method onCheckFocus * @protected * @param {Object} e event 객체 * @return {void} */ onCheckFocus : function(e) { if(!this.isFocus) { this.doFocus(this, e); this.isFocus = true; } }, /** * @description focus 메소드가 호출되면 수행되는 메소드 * @method doFocus * @protected * @param {Object} e event 객체 * @return {void} */ doFocus : function(e) { DU.widget.LCheckBox.superclass.onFocus.call(this, e); DU.util.LEvent.addListener(DU.browser.msie ? document.body : document, "mousedown", this.deferOnBlurDelegate, this); }, /** * @description blur 호출 지연 메소드 * @method deferOnBlur * @protected * @param {Object} e event 객체 * @return {void} */ deferOnBlur : function(e) { DU.util.LFunction.defer(this.onBlurContains, 10, this, [e]); }, /** * @description container에 포함된 객체를 선택했는지 판단하는 메소드 * @method onBlurContains * @protected * @param {Object} e event 객체 * @return {void} */ onBlurContains : function(e) { if(e.deferCancelBubble == true) return; var target = e.target; if (this.el.dom !== target && !this.el.isAncestor(target)) { DU.util.LEvent.removeListener(DU.browser.msie ? document.body : document, "mousedown", this.deferOnBlurDelegate, this); this.onBlur(e); this.isFocus = null; } else e.deferCancelBubble = true; } }); /** * LCheckBoxGroup * @module widget_form * @title LCheckBoxGroup * @requires DU */ DU.namespace("DU.widget"); /** * LCheckBoxGroup * @namespace DU.widget * @class LCheckBoxGroup * @extends DU.widget.LField * @constructor LCheckBoxGroup * @param {Object} oConfig The intial LCheckBoxGroup. */ DU.widget.LCheckBoxGroup = function(oConfig){ var config = oConfig || {}; DU.applyObject(this, config, true); DU.widget.LCheckBoxGroup.superclass.constructor.call(this, config); this.deferOnBlurDelegate = DU.util.LFunction.createDelegate(this.deferOnBlur, this); } DU.extend(DU.widget.LCheckBoxGroup, DU.widget.LField, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LCheckBoxGroup', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-checkbox-group', /** * @description checkbox item 배열 * @property items * @private * @type {Array} */ items : [], /** * @description 가로길이 * @property width * @private * @type {String} */ width : '', /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ DU.widget.LCheckBoxGroup.superclass.initComponent.call(this); this.name = this.name || DU.id(); }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LCheckBoxGroup.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LCheckBoxGroup.superclass.initDefaultConfig.call(this); }, /** * @description render시 호출되는 메소드 * @method doRender * @public * @param {String|Object} container 부모객체 정보 * @return void */ doRender : function(appendToNode) { this.el.addClass(this.CSS_BASE); this.el.addClass("L-fixed"); if(this.width) { this.el.setWidth(!DU.isBorderBox ? this.width - 1 : this.width - 2); } DU.util.LArray.each(this.items, function(item, i){ if((item instanceof DU.widget.LCheckBox) == false) { item.name = this.name; item = new DU.widget.LCheckBox(item); this.items[i] = item; } item.render(this.el.dom); }, this); }, /** * @description render후 호출되는 메소드 * @method afterRender * @protected * @param {HTMLElement} container 부모 객체 * @return void */ afterRender : function(container) { DU.widget.LCheckBoxGroup.superclass.afterRender.call(this, container); var me = this; this.el.on('click', function(e){ if(me.items.length > 0) me.items[0].focus(); DU.util.LEvent.stopPropagation(e); }); DU.util.LArray.each(this.items, function(item){ item.on('changed', this.onChanged, this, true); item.on('focus', this.onItemFocus, this, true); }, this); }, /** * @description LCheckBox에서 구현한 메소드를 호출해주는 기능 * @method invoke * @protected * @param {Function} fn function 객체 * @param {Array} args 인수 배열 * @return {DU.widget.LCheckBoxGroup} */ invoke : function(fn, args){ var els = this.items; DU.each(els, function(e) { DU.widget.LCheckBox.prototype[fn].apply(e, args); }, this); return this; }, /** * @description 값이 변경되면 호출되는 메소드 * @method onChanged * @protected * @param {Object} e event 객체 * @return {void} */ onChanged : function(e) { this.fireEvent('changed', e); }, /** * @description item객체가 focus되면 호출되는 메소드 * @method onItemFocus * @protected * @param {Object} e event 객체 * @return {void} */ onItemFocus : function(e) { if(!this.isFocus) { this.doFocus(this, e); this.isFocus = true; } }, /** * @description focus 메소드가 호출되면 수행되는 메소드 * @method doFocus * @protected * @param {Object} e event 객체 * @return {void} */ doFocus : function(e) { this.onFocus(e); DU.util.LEvent.addListener(DU.browser.msie ? document.body : document, "mousedown", this.deferOnBlurDelegate, this); }, onFocus : function(e) { DU.widget.LCheckBoxGroup.superclass.onFocus.call(this, e); }, onBlur : function(e) { DU.widget.LCheckBoxGroup.superclass.onBlur.call(this, e); }, /** * @description blur 호출 지연 메소드 * @method deferOnBlur * @protected * @param {Object} e event 객체 * @return {void} */ deferOnBlur : function(e) { DU.util.LFunction.defer(this.onBlurContains, 10, this, [e]); }, /** * @description container에 포함된 객체를 선택했는지 판단하는 메소드 * @method onBlurContains * @protected * @param {Object} e event 객체 * @return {void} */ onBlurContains : function(e) { var target = e.target; if(e.deferCancelBubble == true) return; if(this.el.dom !== target && !this.el.isAncestor(target)) { DU.util.LEvent.removeListener(DU.browser.msie ? document.body : document, "mousedown", this.deferOnBlurDelegate, this); this.onBlur(e); this.isFocus = null; } else e.deferCancelBubble = true; }, /** * @description 객체를 focus한다. * @method focus * @public * @return {void} */ focus : function() { if(this.items.length > 0) this.items[0].focus(); }, /** * @description 객체를 destroy하는 메소드 * @method destroy * @public * @return void */ destroy : function() { DU.util.LArray.each(this.items, function(item){ item.destroy(); }, this); DU.widget.LCheckBoxGroup.superclass.destroy.call(this); }, /** * @description item중에 value 맞는 항목을 선택하는 메소드 * @method setValue * @public * @param {String} val item의 value 값 * @return void */ setValue : function(val) { DU.util.LArray.each(this.items, function(item){ item.setValue(val); }, this); }, /** * @description 선택된 item의 값을 리턴하는 메소드 * @method getValue * @public * @return {String} */ getValue : function() { var val = []; DU.util.LArray.each(this.items, function(item){ val.push(item.getValue()); }, this); return val; } }); (function(){ var fnName, CbProto = DU.widget.LCheckBox.prototype, CbgProto = DU.widget.LCheckBoxGroup.prototype; for(var fnName in CbProto){ if(DU.isFunction(CbProto[fnName])){ (function(fnName){ CbgProto[fnName] = CbgProto[fnName] || function(){ return this.invoke(fnName, arguments); }; }).call(CbgProto, fnName); } }; })(); /** * LRadio * @module widget_form * @title LRadio * @requires DU */ DU.namespace("DU.widget"); /** * LRadio * @namespace DU.widget * @class LRadio * @extends DU.widget.LField * @constructor LRadio * @param {Object} oConfig The intial LRadio. */ DU.widget.LRadio = function(oConfig){ var config = oConfig || {}; config = DU.util.LDom.applyIfProperties(config, '$.ext.radio'); DU.applyObject(this, config, true); DU.widget.LRadio.superclass.constructor.call(this, config); } DU.extend(DU.widget.LRadio, DU.widget.LCheckBox, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LRadio', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-radio', /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ DU.widget.LRadio.superclass.initComponent.call(this); if(!this.id) { this.id = DU.id(); } }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LRadio.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LRadio.superclass.initDefaultConfig.call(this); }, /** * @description Template을 생성하는 메소드 * @method createTemplate * @private * @return {void} */ createTemplate : function() { var ts = this.templates || {}; ts = new DU.LTemplate( '' ); this.templates = ts; }, /** * @description 화면 출력되는 객체 리턴 * @method getDisplayEl * @protected * @return {DU.LElement} Element 객체 */ getDisplayEl : function() { if(!this.displayEl) { this.displayEl = this.el.select("input:radio").getAt(0); } return this.displayEl; } }); /** * LRadioGroup * @module widget_form * @title LRadioGroup * @requires DU */ DU.namespace("DU.widget"); /** * LRadioGroup * @namespace DU.widget * @class LRadioGroup * @extends DU.widget.LField * @constructor LRadioGroup * @param {Object} oConfig The intial LRadioGroup. */ DU.widget.LRadioGroup = function(oConfig){ var config = oConfig || {}; DU.applyObject(this, config, true); DU.widget.LRadioGroup.superclass.constructor.call(this, config); } DU.extend(DU.widget.LRadioGroup, DU.widget.LCheckBoxGroup, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LRadioGroup', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-radio-group', /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig){ DU.widget.LRadioGroup.superclass.initComponent.call(this); }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LRadioGroup.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LRadioGroup.superclass.initDefaultConfig.call(this); }, /** * @description render시 발생하는 메소드 * @method doRender * @protected * @param {HttpElement} appendToNode 부모 객체 * @return {void} */ doRender : function(appendToNode) { this.el.addClass(this.CSS_BASE); this.el.addClass("L-fixed"); this.el.setWidth(!DU.isBorderBox ? this.width - 5 : this.width - 2); DU.util.LArray.each(this.items, function(item, i){ if((item instanceof DU.widget.LRadio) == false) { item.name = this.name; item = new DU.widget.LRadio(item); this.items[i] = item; } item.render(this.el.dom); }, this); }, /** * @description Check를 취소하는 메소드 * @method cancelChecked * @param {Object} e Event객체 * @return {void} */ cancelChecked : function(e) { var target = e.target; DU.util.LArray.each(this.items, function(item){ if(item !== target) { item.checked = false; item.el.removeClass('L-checked'); } }, this); }, /** * @description Check를 모두 취소하는 메소드 * @method clearAllChecked * @param {Object} e Event객체 * @return {void} */ clearAllChecked : function(e) { DU.util.LArray.each(this.items, function(item, i){ item.setValue(false); }, this); }, /** * @description change 이벤트가 발생하면 호출되는 메소드 * @method onChanged * @param {Object} e Event객체 * @return {void} */ onChanged : function(e) { this.cancelChecked(e); DU.widget.LRadioGroup.superclass.onChanged.call(this, e); }, /** * @description check된 radio 객체를 리턴하는 메소드 * @method getCheckedItem * @return {DU.widget.LRadio} */ getCheckedItem : function() { var checkedItem = null; DU.util.LArray.each(this.items, function(item, i){ if(item.checked === true) { checkedItem = item; return false; } }, this); return checkedItem; }, /** * @description val 해당되는 radio를 선택하는 메소드 * @method setValue * @param {String} val radio의 value값에 해당되는 값 * @return {DU.widget.LRadio} */ setValue : function(val) { var radio = this.getRadioElByVal(val); if(radio == null) return; radio.setValue(true); }, /** * @description 선택된 raio의 값을 리턴하는 메소드 * @method getValue * @return {String} */ getValue : function() { var item = this.getCheckedItem(); return (item != null) ? item.getRawValue() : null; }, /** * @description 값에 해당되는 radio를 리턴하는 메소드 * @method getRadioElByVal * @return {String} */ getRadioElByVal : function(val) { var retItem = null; DU.util.LArray.each(this.items, function(item, i){ if(item.getDisplayEl().dom.value == val) { retItem = item; return false; } }, this); return retItem; }, onBlur : function(e) { DU.widget.LRadioGroup.superclass.onBlur.call(this, e); } }); (function(){ var fnName, CbProto = DU.widget.LRadio.prototype, groupProto = DU.widget.LRadioGroup.prototype; for(var fnName in CbProto){ if(DU.isFunction(CbProto[fnName])){ (function(fnName){ groupProto[fnName] = groupProto[fnName] || function(){ return this.invoke(fnName, arguments); }; }).call(groupProto, fnName); } }; })(); /** * Form * @module widget_form * @title LTextArea * @requires DU */ DU.namespace("DU.widget"); /** * LTextArea * @namespace DU.widget * @class LTextArea * @extends DU.widget.LTextBox * @constructor LTextArea * @param {HTMLElement | String} id The html element that represents the Element. * @param {Object} oConfig The intial LTextArea. */ DU.widget.LTextArea = function(oConfig){ var config = oConfig || {}; config = DU.util.LDom.applyIfProperties(config, '$.ext.textArea'); DU.widget.LTextArea.superclass.constructor.call(this, oConfig); } DU.extend(DU.widget.LTextArea, DU.widget.LTextBox, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LTextArea', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-textarea', /** * @description 목록창의 가로 길이 *Sample: 보기
* @config width * @type {String} * @default '100px' */ /** * @description 목록창의 가로 길이 * @property width * @private * @type {String} */ width : '100px', /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(id, oConfig) { }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LTextArea.superclass.initEvents.call(this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig : function() { DU.widget.LTextArea.superclass.initDefaultConfig.call(this); }, /** * @description render시 발생하는 메소드 * @method doRender * @protected * @param {HttpElement} appendToNode 부모 객체 * @return {void} */ doRender : function(container) { this.el.addClass(this.CSS_BASE); this.el.addClass("L-fixed"); this.el.setWidth(this.width); this.createTemplate(); var html = this.getRenderBody(); this.el.html(html); }, /** * @description template객체 생성 * @method createTemplate * @protected * @return {void} */ createTemplate : function() { var ts = this.templates || {}; ts = new DU.LTemplate( '' ); this.templates = ts; }, /** * @description body html을 리턴하는 메소드 * @method getRenderBody * @return {String} */ getRenderBody : function() { var ts = this.templates || {}; var id = this.id ? this.id + '_hi' : DU.id(); var p = { id : id, name : this.name || this.id, value : this.value || '' }; return ts.apply(p); }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LTextArea.superclass.afterRender.call(this, container); }, /** * @description 화면 출력되는 객체 리턴 * @method getDisplayEl * @return {DU.LElement} Element 객체 */ getDisplayEl : function() { if(!this.displayEl) { this.displayEl = this.el.select("textarea").getAt(0); } return this.displayEl; }, /** * @description 키 입력시 호출되는 메소드 * @method onFireKey * @param {Object} e Event 객체 * @return {void} */ onFireKey : function(e){ if(DU.util.LEvent.isSpecialKey(e) && e.keyCode != DU.util.LKeyListener.KEY.ENTER) this.fireEvent("specialkey", e); } }); /** * Form * @module widget_form * @title LNumberBox * @requires DU */ DU.namespace("DU.widget"); (function(){ /** * LNumberBox * @namespace DU.widget * @class LNumberBox * @extends DU.widget.LTextBox * @constructor LNumberBox * @param {HTMLElement | String} id The html element that represents the Element. * @param {Object} oConfig The intial LNumberBox. */ DU.widget.LNumberBox = function(oConfig){ var config = oConfig || {}; config = DU.util.LDom.applyIfProperties(config, '$.ext.numberBox'); DU.widget.LNumberBox.superclass.constructor.call(this, oConfig); } DU.extend(DU.widget.LNumberBox, DU.widget.LTextBox, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LNumberBox', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-numberBox', /** * @description 입력 가능한 문자열 *Sample: 보기
* @config allowChars * @type {String} * @default '0123456789' */ /** * @description 입력 가능한 문자열 * @property allowChars * @private * @type {String} */ allowChars : '0123456789.', /** * @description 소수점 허용 자리수 *Sample: 보기
* @config decimalPrecision * @type {Int} * @default 0 */ /** * @description 소수점 허용 자리수 * @property decimalPrecision * @private * @type {Int} */ decimalPrecision : 0, /** * @description 입력 가능 최소값 정의 (미지원) * @config minValue * @type {Int} * @default null */ /** * @description 입력 가능 최소값 정의 * @property minValue * @private * @type {Int} */ minValue : null, /** * @description 입력 가능 최대값 정의 (미지원) * @config maxValue * @type {Int} * @default null */ /** * @description 입력 가능 최대값 정의 * @property maxValue * @private * @type {Int} */ maxValue : null, /** * @description 천단위 구분자 출력 여부 * @config thousandsSeparator * @type {boolean} * @default true */ /** * @description 입력 가능 최대값 정의 * @property thousandsSeparator * @private * @type {boolean} */ thousandsSeparator: true, /** * @description 값 변경을 할 수 있는 spin 기능 출력 여부 * @config isShowSpin * @type {boolean} * @default false */ /** * @description 값 변경을 할 수 있는 spin 기능 출력 여부 * @property isShowSpin * @private * @type {boolean} */ isShowSpin: false, /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent : function(oConfig) { if(this.decimalPrecision > 0) this.allowChars += '.'; if (this.minValue != null && this.minValue < 0) this.allowChars += "-"; }, /** * @description Dom객체 생성 * @method createTimeTemplete * @private * @param {String|Object} el 객체의 아이디나 객체 * @return {DU.LElement} Element 객체 */ createTemplete : function(el) { DU.widget.LNumberBox.superclass.createTemplete.call(this, el); var elContainer = el; var hiddenInput = document.createElement('input'); hiddenInput.name = this.id; hiddenInput.style.display = "none"; hiddenInput.className = DU.widget.LNumberBox.CSS_HIDDEN_NUMBERBOX; hiddenInput.instance = this; el.appendChild(hiddenInput); this.hiddenInputEl = DU.get(hiddenInput); if(this.isShowSpin) { var iconDiv = document.createElement('div'); iconDiv.className = 'icon'; iconDiv.id = DU.id(); this.iconDivEl = DU.get(iconDiv); elContainer.appendChild(iconDiv); var spinUpDiv = document.createElement('div'); spinUpDiv.className = "L-spin-up"; this.spinUpDivEl = DU.get(spinUpDiv); this.iconDivEl.appendChild(spinUpDiv); var spinDownDiv = document.createElement('div'); spinDownDiv.className = "L-spin-down"; this.spinDownDivEl = DU.get(spinDownDiv); this.iconDivEl.appendChild(spinDownDiv); } return elContainer; }, /** * @description width 속성에 따른 실제 적용 메소드 * @method _setWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setWidth : function(type, args, obj) { if(this.isShowSpin) { var width = args[0]; if (!DU.isBorderBox) { this.el.setWidth(width); this.getDisplayEl().setWidth(width - 16); this.iconDivEl.setLeft(width - 16); } else { this.el.setWidth(width - 4); this.getDisplayEl().setWidth(width - 20); this.iconDivEl.setLeft(width - 20); } this.width = width; this.cfg.setProperty('width', this.width, true); } else DU.widget.LNumberBox.superclass._setWidth.call(this, type, args, obj); }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LNumberBox.superclass.afterRender.call(this, container); if(this.isShowSpin) { this.spinUpDivEl.on('mousedown', function(e){ this.spinUpDivEl.addClass('L-spin-up-click'); }, this, true); this.spinUpDivEl.on('mouseup', function(e){ this.spinUpDivEl.removeClass('L-spin-up-click'); }, this, true); this.spinDownDivEl.on('mousedown', function(e){ this.spinDownDivEl.addClass('L-spin-down-click'); }, this, true); this.spinDownDivEl.on('mouseup', function(e){ this.spinDownDivEl.removeClass('L-spin-down-click'); }, this, true); this.spinUpDivEl.on('click', function(e){ this.upValue(); DU.util.LEvent.stopEvent(e); }, this, true); this.spinDownDivEl.on('click', function(e){ this.downValue(); DU.util.LEvent.stopEvent(e); }, this, true); } }, /** * @description 값을 올리는 메소드 * @method upValue * @protected * @return void */ upValue: function() { var value = parseFloat(this.getValue(), 10) || 0; if(!DU.isUndefined(this.maxValue) && this.maxValue <= value) return; this.setValue(++value); }, /** * @description 값을 내리는 메소드 * @method downValue * @protected * @return void */ downValue: function() { var value = parseFloat(this.getValue(), 10) || 0; if(!DU.isUndefined(this.minValue) && this.minValue >= value) return; this.setValue(--value); }, /** * @description 유효성을 검증하는 메소드 * @method validateValue * @protected * @param {object} value 값 * @return {Boolean} */ validateValue : function(value) { if(value === this.lastValue) return true; value = String(value); value = value.replace(/,/g, ''); var isValid = true; isValid = new DU.validate.LNumberValidator({id: this.id}).validate(value); if(isValid == false) return false; if(!DU.isUndefined(value) && !DU.isNull(value)) { if(this.isNumberValue(value) == false) return false; if(this.minValue != null && this.minValue > value) { this.invalid(DU.getMessageManager().get("$.base.msg011", [this.minValue])); this.setValue(this.lastValue); return false; } if(this.maxValue != null && this.maxValue < value) { this.invalid(DU.getMessageManager().get("$.base.msg012", [this.maxValue])); this.setValue(this.lastValue); return false; } } this.valid(); return isValid; }, /** * @description 숫자 유효성을 검증하는 메소드 * @method isNumberValue * @protected * @param {object} value 값 * @return {Boolean} */ isNumberValue: function(value) { if(DU.isUndefined(value) || DU.isNull(value) || value === false) return false; value = value == '' ? 0 : value; if(value != parseFloat(value, 10)) return false; return true; }, /** * @description 값을 리턴하는 메소드 * @method getValue * @return {Int|Float} */ getValue : function() { var value = this.hiddenInputEl.getValue(); if(DU.isUndefined(this.lastValue) || value == this.lastValue) return value; if(DU.isEmpty(value)) return null; return parseFloat(value, 10); }, /** * @description decimal값을 리턴하는 메소드 * @method getDecimalValue * @return {Int|Float} */ getDecimalValue: function(value) { var newValue = value; var sValue = value + ''; var pos = sValue.indexOf(".") || 0; if (pos > 0) { var dpValue = sValue.substring(pos + 1); if (dpValue.length > this.decimalPrecision) dpValue = dpValue.substring(0, this.decimalPrecision); dpValue = DU.util.LString.rPad(dpValue, '0', this.decimalPrecision); newValue = value.substring(0, pos + 1) + dpValue; } else newValue += '.' + DU.util.LString.rPad('', '0', this.decimalPrecision); return newValue; }, /** * @description 출력데이터가 변경되면 호출되는 메소드 * @method doChangedDisplayValue * @private * @param {String} o 적용할 값 * @return void */ doChangedDisplayValue : function(o) { var val = String(o); val = val.replace(/,/g, ''); if(this.isNumberValue(val)) this.setValue(val); }, /** * @description 값을 변경한다. * @method setValue * @public * @param {Int} val 반영할 값 * @return {void} */ setValue : function(val) { if(DU.isUndefined(val) == true || DU.isNull(val)) return; this.hiddenInputEl.setValue(val); if(!DU.isEmpty(val)) { if(this.thousandsSeparator === true) val = DU.util.LNumber.format(parseFloat(val, 10), {thousandsSeparator: ','}); if (this.decimalPrecision > 0) val = this.getDecimalValue(val); } this.getDisplayEl().setValue(val); this.fireEvent('changed', {target:this, value:this.getValue(), displayValue:this.getDisplayValue()}); } }); DU.widget.LNumberBox.CSS_HIDDEN_NUMBERBOX = "L-number-hidden"; })(); /** * DateBox * @module widget_form * @title LDateBox * @requires DU */ DU.namespace("DU.widget"); /** * LDateBox * @namespace DU.widget * @class LDateBox * @extends DU.widget.LField * @constructor LDateBox * @param {Object} oConfig The intial LDateBox. */ DU.widget.LDateBox = function(oConfig){ var config = oConfig ||{}; config = DU.util.LDom.applyIfProperties(config, '$.ext.dateBox'); this.onIconClickDelegate = DU.util.LFunction.createDelegate(this.onIconClick, this); DU.widget.LDateBox.superclass.constructor.call(this, config); } DU.extend(DU.widget.LDateBox, DU.widget.LTextBox, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LDateBox', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-datebox', /** * @description 입출력 type * @property dateType * @private * @type {String} */ dateType : 'date', /** * @description 편집시, form submit시 적용되는 format * @property valueFormat * @private * @type {String} */ valueFormat : '%q', /** * @description calendar show할때 입력된 날짜를 calendar에서 선택할지 여부 * @property selectingInputDate * @type {boolean} */ selectingInputDate : true, /** * @description width * @property width * @type {int} * @default 100 */ width : 100, /** * @description height * @property height * @type {int} * @default 21 */ height : 21, /** * @description iconWidth * @property iconWidth * @type {int} * @default 18 */ iconWidth : 18, /** * @description iconMarginLeft, input과 달력 icon간의 간격 * @property iconMarginLeft * @type {int} * @default 2 */ iconMarginLeft : 2, /** * @description editableTextbox, 사용자가 input text box를 편집할 수 있는지 여부, 즉 달력으로만 입력할 것인가 여부 * @config editableTextbox * @type {boolean} * @default true */ /** * @description editableTextbox, 사용자가 input text box를 편집할 수 있는지 여부, 즉 달력으로만 입력할 것인가 여부 * @property editableTextbox * @type {boolean} * @default true */ editableTextbox : true, /** * @description mask 적용 * @config mask * @type {String} * @default null */ /** * @description mask 적용 * new DU.form.LTextBox({ mask: '999999-9999999' }); * @property mask * @private * @type {String} */ mask: '9999-99-99', /** * @description afterRender * @method afterRender * @private * @return void */ afterRender : function(container) { DU.widget.LDateBox.superclass.afterRender.call(this, container); this.doRenderCalendar(); if(!this.editableTextbox) this.getDisplayEl().dom.readOnly = true; }, /** * @description doRenderCalendar * @method doRenderCalendar * @private * @return void */ doRenderCalendar : function(){ var config = this.calendarConfig || {width:150}; config.applyTo = this.calendarDivEl.id; this.calendarDivEl.addClass('L-dateBox-calendar'); this.calendar = new DU.widget.LCalendar(config); this.calendar.render(); this.calendar.hide(); this.iconDivEl.on('click', this.onIconClickDelegate); }, /** * @description blur 이벤트 발생시 defer를 연결하는 메소드 * @method deferOnBlur * @protected * @param {Object} e Event 객체 * @return {void} */ deferOnBlur : function(e) { if (this.calendarDivEl.isAncestor(e.target)) { var el = DU.get(e.target); if (el.dom.tagName.toLowerCase() == "a" && el.hasClass("selector")) { var selectedDate = this.calendar.getProperty("pagedate"); selectedDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), parseInt(el.getHtml())); this.setValue(selectedDate); this.calendar.hide(); } } var checkBlur = function(e) { if(e.deferCancelBubble == true) return; var target = e.target; if (target !== this.el.dom && !this.el.isAncestor(target) && target !== this.calendarDivEl.dom && !this.calendarDivEl.isAncestor(target)) { DU.util.LEvent.removeListener(DU.browser.msie ? document.body : document, "mousedown", this.deferOnBlurDelegate, this); this.onBlur.call(this, e); this.isFocus = false; } else { e.deferCancelBubble = true; } } DU.util.LFunction.defer(checkBlur, 10, this, [e]); }, /** * @description onBlur * @method onBlur * @param {Object} e event object * @private * @return void */ onBlur : function(e){ DU.widget.LDateBox.superclass.onBlur.call(this, e); this.calendar.hide(); }, /** * @description 출력데이터가 변경되면 호출되는 메소드 * @method doChangedDisplayValue * @private * @param {String} o 적용할 값 * @return void */ doChangedDisplayValue : function(o) { this.setValue(o); }, /** * @description string convert to date object * @method getDate * @param {string} sDate * @private * @return {Date} */ getDate : function(sDate){ if (sDate instanceof Date) { return sDate; } var formatType = this.displayValue ? this.displayValue : "%x"; var oDate = DU.util.LFormat.stringToDate(sDate,{format:formatType}); if (!(oDate instanceof Date)) { oDate = DU.util.LFormat.stringToDate(sDate,{format:"%q"}); } if (!(oDate instanceof Date)) { oDate = DU.util.LFormat.stringToDate(sDate,{format:"%Q"}); } if (oDate instanceof Date) { return oDate; } else { return false; } }, /** * @description date convert to formatted string * @method getDateString * @param {Date} oDate * @param {String} format * @private * @return {String} */ getDateString : function(oDate, format){ //mask를 사용하므로 구분자가 없는 날짜 8자가 기본이다. format = format ? format : '%Y%m%d'; var value = oDate ? DU.util.LFormat.dateToString(oDate, { format: format }) : ""; return value ? value : ""; }, /** * @description calendar 전시 위치 설정 * @method setCalendarXY * @private */ setCalendarXY : function(){ var h = this.calendarDivEl.getHeight() || 0; var t = this.getDisplayEl().getTop() + this.getDisplayEl().getHeight(); var l = this.getDisplayEl().getLeft(); var visible = DU.util.LDom.isVisibleSide(h+t-40);//padding+border 빼기(22), ie borderbox 처리 필요. if(!visible){ t = this.getDisplayEl().getTop() - h; } this.calendarDivEl.setTop(t); this.calendarDivEl.setLeft(l); }, /** * @description onIconClick * @method onIconClick * @private * @param {Object} e */ onIconClick : function(e) { this.showCalendar(); this.inputEl.focus(); }, /** * @description * @method showCalendar * @private */ showCalendar : function(){ if(this.editable === false || this.disabled === true) return; this.setCalendarXY(); if (this.selectingInputDate) this.selectCalendarDate(); this.calendar.show(); this.setCalendarXY(); }, /** * @description 입력된 날짜 선택하기 * @method selectCalendarDate * @param {string} date */ selectCalendarDate : function(date){ date = date ? date : this.getDateString(this.getValue(),"%x"); if (date) { this.calendar.clear(); var selDates = this.calendar.select(date,false); if (selDates.length > 0) { var firstDate = selDates[0]; this.calendar.cfg.setProperty("pagedate", firstDate.getFullYear() + this.calendar.cfg.getProperty(DU.widget.LCalendar._DEFAULT_CONFIG.DATE_FIELD_DELIMITER.key) + (firstDate.getMonth() + 1)); this.calendar.render(); } } }, /** * @description Dom객체 생성 * @method createTemplete * @private * @param {String|Object} el 객체의 아이디나 객체 * @return {DU.LElement} Element 객체 */ createTemplete : function(el) { var elContainer = DU.get(el); elContainer.addClass(this.CSS_BASE); elContainer.addClass("L-fixed"); var input = document.createElement('input'); elContainer.appendChild(input); this.inputEl = DU.get(input); var iconDiv = document.createElement('div'); iconDiv.className = 'icon'; elContainer.appendChild(iconDiv); this.iconDivEl = DU.get(iconDiv); //form submit var hiddenInput = document.createElement('input'); hiddenInput.name = this.name || this.id; hiddenInput.instance = this; hiddenInput.className = "hiddenInput"; elContainer.appendChild(hiddenInput); this.hiddenInputEl = DU.get(hiddenInput); //calendar container 만들기 var calendarDiv = document.createElement('div'); calendarDiv.className = "L-cal-container"; this.calendarDivEl = DU.get(calendarDiv); //ie의 layer z-index문제로 body에 붙임 document.body.appendChild(calendarDiv); return elContainer; }, /** * @description width 속성에 따른 실제 적용 메소드 * @method _setWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setWidth : function(type, args, obj) { this.width = DU.util.LDom.toPixelNumber(args[0]); this._computeWidth(); }, /** * @description 넓이 계산, space는 input과 달력아이콘간의 간격이다. * @method _computeWidth * @protected */ _computeWidth : function(){ this.el.setWidth(this.width); this.iconDivEl.setWidth(this.iconWidth); var inputWidth = this.width - this.iconWidth - this.iconMarginLeft; this.getDisplayEl().setWidth(inputWidth); this.iconDivEl.setStyle("left",(inputWidth + this.iconMarginLeft) + "px"); }, /** * @description height 속성에 따른 실제 적용 메소드 * @method _setHeight * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setHeight : function(type, args, obj) { if(args[0] != "auto" && args[0] != "") { this.height = DU.util.LDom.toPixelNumber(args[0]); this._computeHeight(); } else { this._computeHeight(true); } }, /** * @description 높이 계산 * @method _computeHeight * @protected * @param {boolean} isAuto */ _computeHeight : function(isAuto) { if (!isAuto) { this.el.setHeight(this.height); this.getDisplayEl().setHeight(this.height-2); this.iconDivEl.setHeight(this.height); } else { this.el.setStyle("height",""); this.getDisplayEl().setStyle("height",""); this.iconDivEl.setStyle("height",""); } }, /** * @description disabled 속성에 따른 실제 적용 메소드 * @method _setDisabled * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setDisabled : function(type, args, obj) { args = args[0]; if(args === false) { this.disabled = false; this.inputEl.enable(); this.hiddenInputEl.enable(); this.iconDivEl.enable(); this.calendarDivEl.enable(); } else { this.disabled = true; this.inputEl.disable(); this.hiddenInputEl.disable(); this.iconDivEl.disable(); this.calendarDivEl.disable(); } }, /** * @description 날짜 설정 * @method setValue * @param {Date} oDate * @return void */ setValue : function(oDate){ //빈값을 입력하면 null, 잘못입력하면 이전값을 넣는다. if(typeof oDate === "string"){ //getUnMaskValue는 자리수로 검사하므로 mask안된 값이 들어오면 값을 잘라낸다. oDate = oDate.length == 8 ? oDate : this.getUnMaskValue(oDate); oDate = DU.isEmpty(oDate) ? null : this.getDate(oDate); } if (oDate === false) { this.getDisplayEl().dom.value = this.lastDisplayValue; } else { var hiddenValue = oDate === null ? "" : this.getDateString(oDate, this.valueFormat); var displayValue = oDate === null ? "" : this.getDateString(oDate); this.getDisplayEl().dom.value = displayValue; displayValue = this.checkVal().displayValue; this.getDisplayEl().dom.value = displayValue; if (this.hiddenInputEl.dom.value !== hiddenValue) { this.hiddenInputEl.setValue(hiddenValue); this.lastDisplayValue = displayValue; //값이 달라질 경우만 발생. this.fireEvent('changed', { target: this, value: this.getValue(), displayValue: this.getDisplayValue() }); } } }, /** * @description 입력된 날짜 가져오기 * @method getValue * @return {Date} */ getValue : function(){ var value = DU.widget.LDateBox.superclass.getValue.call(this); var oDate = this.getDate(value); return this.dateType == "date" ? (oDate ? oDate : null) : this.getDateString(oDate, this.valueFormat); }, /** * @description 달력 숨기기 * @method hide * @return void */ hide : function(anim) { this.calendar.hide(); DU.widget.LDateBox.superclass.hide.call(this,anim); }, /** * @description 객체를 destroy하는 메소드 * @method destroy * @public * @return void */ destroy : function() { DU.widget.LDateBox.superclass.destroy.call(this); this.iconDivEl.unOnAll(); this.inputEl = null; this.hiddenInputEl = null; this.iconDivEl = null; this.calendar.destroy(); this.calendarDivEl = null; } }); /** * Form * @module widget_form * @title LTimeBox * @requires DU */ DU.namespace("DU.widget"); /** * LTimeBox * @namespace DU.widget * @class LTimeBox * @extends DU.widget.LTextBox * @constructor LTimeBox * @param {HTMLElement | String} id The html element that represents the Element. * @param {Object} oConfig The intial LTimeBox. */ DU.widget.LTimeBox = function(oConfig){ var config = oConfig || {}; config = DU.util.LDom.applyIfProperties(config, '$.ext.timeBox'); DU.widget.LTimeBox.superclass.constructor.call(this, oConfig); } DU.extend(DU.widget.LTimeBox, DU.widget.LTextBox, { /** * @description 객체의 문자열 * @property otype * @private * @type {String} */ otype : 'DU.widget.LTimeBox', /** * @description 기본 CSS명 * @property CSS_BASE * @private * @type {String} */ CSS_BASE : 'L-timeBox', /** * @description 입력 가능한 문자열 * @config allowChars * @type {String} * @default '0123456789' */ /** * @description 입력 가능한 문자열 * @property allowChars * @private * @type {String} */ allowChars : '0123456789', /** * @description mask 적용 * @property mask * @private * @type {String} */ mask: '99:99', /** * @description 가로 길이 * @config width * @type {Int} * @default 60 */ /** * @description 가로 길이 * @property width * @private * @type {String} */ width: 60, /** * @description Dom객체 생성 * @method createTimeTemplete * @private * @param {String|Object} el 객체의 아이디나 객체 * @return {DU.LElement} Element 객체 */ createTemplete : function(el) { DU.widget.LTimeBox.superclass.createTemplete.call(this, el); var elContainer = el; var iconDiv = document.createElement('div'); iconDiv.className = 'icon'; iconDiv.id = DU.id(); this.iconDivEl = DU.get(iconDiv); elContainer.appendChild(iconDiv); var spinUpDiv = document.createElement('div'); spinUpDiv.className = "L-spin-up"; this.spinUpDivEl = DU.get(spinUpDiv); this.iconDivEl.appendChild(spinUpDiv); var spinDownDiv = document.createElement('div'); spinDownDiv.className = "L-spin-down"; this.spinDownDivEl = DU.get(spinDownDiv); this.iconDivEl.appendChild(spinDownDiv); return elContainer; }, /** * @description render 후 호출하는 메소드 * @method afterRender * @protected * @param {HttpElement} container 부모 객체 * @return {String} */ afterRender : function(container) { DU.widget.LTimeBox.superclass.afterRender.call(this, container); this.spinUpDivEl.on('mousedown', function(){ this.spinUpDivEl.addClass('L-spin-up-click'); }, this, true); this.spinUpDivEl.on('mouseup', function(){ this.spinUpDivEl.removeClass('L-spin-up-click'); }, this, true); this.spinDownDivEl.on('mousedown', function(){ this.spinDownDivEl.addClass('L-spin-down-click'); }, this, true); this.spinDownDivEl.on('mouseup', function(){ this.spinDownDivEl.removeClass('L-spin-down-click'); }, this, true); this.spinUpDivEl.on('click', function(){ this.upValue(); }, this, true); this.spinDownDivEl.on('click', function(){ this.downValue(); }, this, true); }, /** * @description 1분 올리는 메소드 * @method upValue * @protected * @return void */ upValue: function() { if(this.disabled) return; var value = this.getValue() || '0000'; var hh = parseInt(value.substring(0, 2), 10); var mm = parseInt(value.substring(2, 4), 10); if(mm == 59) { hh = hh == 23 ? 0: (hh + 1); mm = 0; } else mm++; this.setValue(DU.util.LString.lPad(hh, '0', 2) + DU.util.LString.lPad(mm, '0', 2)); }, /** * @description 1분 내리는 메소드 * @method downValue * @protected * @return void */ downValue: function() { if(this.disabled) return; var value = this.getValue() || '0000'; var hh = parseInt(value.substring(0, 2), 10); var mm = parseInt(value.substring(2, 4), 10); if(mm == 00) { hh = hh == 0 ? 23: (hh - 1); mm = 59; } else mm--; this.setValue(DU.util.LString.lPad(hh, '0', 2) + DU.util.LString.lPad(mm, '0', 2)); }, /** * @description width 속성에 따른 실제 적용 메소드 * @method _setWidth * @protected * @param {String} type 속성의 이름 * @param {Array} args 속성의 값 배열 * @param {Object} obj 적용된 객체 * @return void */ _setWidth : function(type, args, obj) { var width = args[0]; if (!DU.isBorderBox) { this.el.setWidth(width); this.getDisplayEl().setWidth(width - 16); this.iconDivEl.setLeft(width - 16); } else { this.el.setWidth(width - 4); this.getDisplayEl().setWidth(width - 20); this.iconDivEl.setLeft(width - 20); } this.width = width; this.cfg.setProperty('width', this.width, true); }, /** * @description 유효성을 검증하는 메소드 * @method validateValue * @protected * @param {object} value 값 * @return {Boolean} */ validateValue : function(val) { return DU.isEmpty(val) ? true : DU.util.LString.isTime(val); }, /** * @description 값을 변경한다. * @method setValue * @public * @param {String} o 반영할 값 * @return {void} */ setValue: function(val) { DU.widget.LTimeBox.superclass.setValue.call(this, val); if(this.getDisplayValue().length > 0 && this.getDisplayValue().length != 5) this.setDisplayValue(val.substring(0, 2) + ":" + val.substring(2, 4)); } }); /** * The LCalendar component * @module widget_calendar * @title LCalendar * @namespace DU.widget * @requires DU,dom,event */ (function() { var Dom = DU.util.LDom, Event = DU.util.LEvent, Lang = DU; /** * 달력 * @namespace DU.widget * @class LCalendar * @constructor * @param {String} id [optional] 달력 아이디 * @param {String | HTMLElement} container 달력 컨테이너 dom 객체 아이디 * @param {Object} config [optional] config 객체 */ function LCalendar(id, containerId, config) { this.init.apply(this, arguments); config = config || {}; } /** * The path to be used for images loaded for the LCalendar * @property DU.widget.LCalendar.IMG_ROOT * @static * @deprecated You can now customize images by overriding the calclose, calnavleft and calnavright default CSS classes for the close icon, left arrow and right arrow respectively * @type String */ LCalendar.IMG_ROOT = null; /** * Type constant used for renderers to represent an individual date (M/D/Y) * @property DU.widget.LCalendar.DATE * @static * @final * @type String */ LCalendar.DATE = "D"; /** * Type constant used for renderers to represent an individual date across any year (M/D) * @property DU.widget.LCalendar.MONTH_DAY * @static * @final * @type String */ LCalendar.MONTH_DAY = "MD"; /** * Type constant used for renderers to represent a weekday * @property DU.widget.LCalendar.WEEKDAY * @static * @final * @type String */ LCalendar.WEEKDAY = "WD"; /** * Type constant used for renderers to represent a range of individual dates (M/D/Y-M/D/Y) * @property DU.widget.LCalendar.RANGE * @static * @final * @type String */ LCalendar.RANGE = "R"; /** * Type constant used for renderers to represent a month across any year * @property DU.widget.LCalendar.MONTH * @static * @final * @type String */ LCalendar.MONTH = "M"; /** * Constant that represents the total number of date cells that are displayed in a given month * @property DU.widget.LCalendar.DISPLAY_DAYS * @static * @final * @type Number */ LCalendar.DISPLAY_DAYS = 42; /** * Constant used for halting the execution of the remainder of the render stack * @property DU.widget.LCalendar.STOP_RENDER * @static * @final * @type String */ LCalendar.STOP_RENDER = "S"; /** * Constant used to represent short date field string formats (e.g. Tu or Feb) * @property DU.widget.LCalendar.SHORT * @static * @final * @type String */ LCalendar.SHORT = "short"; /** * Constant used to represent long date field string formats (e.g. Monday or February) * @property DU.widget.LCalendar.LONG * @static * @final * @type String */ LCalendar.LONG = "long"; /** * Constant used to represent medium date field string formats (e.g. Mon) * @property DU.widget.LCalendar.MEDIUM * @static * @final * @type String */ LCalendar.MEDIUM = "medium"; /** * Constant used to represent single character date field string formats (e.g. M, T, W) * @property DU.widget.LCalendar.ONE_CHAR * @static * @final * @type String */ LCalendar.ONE_CHAR = "1char"; /** * The set of default Config property keys and values for the LCalendar * @property DU.widget.LCalendar._DEFAULT_CONFIG * @final * @static * @private * @type Object */ LCalendar._DEFAULT_CONFIG = { // Default values for pagedate and selected are not class level constants - they are set during instance creation PAGEDATE: { key: "pagedate", value: null }, SELECTED: { key: "selected", value: null }, TITLE: { key: "title", value: "" }, CLOSE: { key: "close", value: false }, IFRAME: { key: "iframe", value: (DU.browser.msie && DU.browser.msie <= 6) ? true : false }, MINDATE: { key: "mindate", value: null }, MAXDATE: { key: "maxdate", value: null }, MULTI_SELECT: { key: "multi_select", value: false }, START_WEEKDAY: { key: "start_weekday", value: 0 }, SHOW_WEEKDAYS: { key: "show_weekdays", value: true }, SHOW_WEEK_HEADER: { key: "show_week_header", value: false }, SHOW_WEEK_FOOTER: { key: "show_week_footer", value: false }, HIDE_BLANK_WEEKS: { key: "hide_blank_weeks", value: false }, NAV_ARROW_LEFT: { key: "nav_arrow_left", value: null }, NAV_ARROW_RIGHT: { key: "nav_arrow_right", value: null }, MONTHS_SHORT: { key: "months_short", value: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] }, MONTHS_LONG: { key: "months_long", value: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] }, WEEKDAYS_1CHAR: { key: "weekdays_1char", value: ["S", "M", "T", "W", "T", "F", "S"] }, WEEKDAYS_SHORT: { key: "weekdays_short", value: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] }, WEEKDAYS_MEDIUM: { key: "weekdays_medium", value: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] }, WEEKDAYS_LONG: { key: "weekdays_long", value: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] }, LOCALE_MONTHS: { key: "locale_months", value: "long" }, LOCALE_WEEKDAYS: { key: "locale_weekdays", value: "short" }, DATE_DELIMITER: { key: "date_delimiter", value: "," }, DATE_FIELD_DELIMITER: { key: "date_field_delimiter", value: "/" }, DATE_RANGE_DELIMITER: { key: "date_range_delimiter", value: "~" }, MY_MONTH_POSITION: { key: "my_month_position", value: 1 }, MY_YEAR_POSITION: { key: "my_year_position", value: 2 }, MD_MONTH_POSITION: { key: "md_month_position", value: 1 }, MD_DAY_POSITION: { key: "md_day_position", value: 2 }, MDY_MONTH_POSITION: { key: "mdy_month_position", value: 1 }, MDY_DAY_POSITION: { key: "mdy_day_position", value: 2 }, MDY_YEAR_POSITION: { key: "mdy_year_position", value: 3 }, MY_LABEL_MONTH_POSITION: { key: "my_label_month_position", value: 1 }, MY_LABEL_YEAR_POSITION: { key: "my_label_year_position", value: 2 }, MY_LABEL_MONTH_SUFFIX: { key: "my_label_month_suffix", value: " " }, MY_LABEL_YEAR_SUFFIX: { key: "my_label_year_suffix", value: "" }, NAV: { key: "navigator", value: null }, STRINGS: { key: "strings", value: { previousMonth: "Previous Month", nextMonth: "Next Month", previousYear: "Previous Year", nextYear: "Next Year", close: "Close" }, supercedes: ["close", "title"] } }; var DEF_CFG = LCalendar._DEFAULT_CONFIG; /** * The set of Custom Event types supported by the LCalendar * @property DU.widget.LCalendar._EVENT_TYPES * @final * @static * @private * @type Object */ LCalendar._EVENT_TYPES = { BEFORE_SELECT: "beforeSelect", SELECT: "select", BEFORE_DESELECT: "beforeDeselect", DESELECT: "deselect", CHANGE_PAGE: "changePage", BEFORE_RENDER: "beforeRender", RENDER: "render", RENDER_CELL: "renderCell", BEFORE_DESTROY: "beforeDestroy", DESTROY: "destroy", RESET: "reset", CLEAR: "clear", BEFORE_HIDE: "beforeHide", HIDE: "hide", BEFORE_SHOW: "beforeShow", SHOW: "show", BEFORE_HIDE_NAV: "beforeHideNav", HIDE_NAV: "hideNav", BEFORE_SHOW_NAV: "beforeShowNav", SHOW_NAV: "showNav", BEFORE_RENDER_NAV: "beforeRenderNav", RENDER_NAV: "renderNav" }; /** * The set of default style constants for the LCalendar * @property DU.widget.LCalendar._STYLES * @final * @static * @private * @type Object */ LCalendar._STYLES = { CSS_ROW_HEADER: "calrowhead", CSS_ROW_FOOTER: "calrowfoot", CSS_CELL: "calcell", CSS_CELL_SELECTOR: "selector", CSS_CELL_SELECTED: "selected", CSS_CELL_SELECTABLE: "selectable", CSS_CELL_RESTRICTED: "restricted", CSS_CELL_TODAY: "today", CSS_CELL_OOM: "oom", CSS_CELL_OOB: "previous", CSS_HEADER: "calheader", CSS_HEADER_TEXT: "calhead", CSS_BODY: "calbody", CSS_WEEKDAY_CELL: "calweekdaycell", CSS_WEEKDAY_ROW: "calweekdayrow", CSS_FOOTER: "calfoot", CSS_CALENDAR: "L-calendar", CSS_SINGLE: "single", CSS_CONTAINER: "L-calcontainer", CSS_NAV_YEAR_LEFT: "calnavyearleft", CSS_NAV_YEAR_RIGHT: "calnavyearright", CSS_NAV_LEFT: "calnavleft", CSS_NAV_RIGHT: "calnavright", CSS_NAV: "calnav", CSS_CLOSE: "calclose", CSS_CELL_TOP: "calcelltop", CSS_CELL_LEFT: "calcellleft", CSS_CELL_RIGHT: "calcellright", CSS_CELL_BOTTOM: "calcellbottom", CSS_CELL_HOVER: "calcellhover", CSS_CELL_HIGHLIGHT1: "highlight1", CSS_CELL_HIGHLIGHT2: "highlight2", CSS_CELL_HIGHLIGHT3: "highlight3", CSS_CELL_HIGHLIGHT4: "highlight4" }; LCalendar.prototype = { /** * config 객체 * @property Config * @private * @deprecated LConfiguration properties should be set by calling LCalendar.cfg.setProperty. * @type Object */ Config: null, /** * parent LCalendarGroup * @property parent * @type LCalendarGroup */ parent: null, /** * calendar group의 index * @property index * @type Number */ index: -1, /** * calendar table의 배열 * @property cells * @type HTMLTableCellElement[] */ cells: null, /** * calendar table의 배열의 날짜값, format은 [YYYY, M, D]. * @property cellDates * @type Array[](Number[]) */ cellDates: null, /** * 아이디 * @property id * @type String */ id: null, /** * 컨테이너 아이디 * @property containerId * @type String */ containerId: null, /** * 컨테이너 dom 객체 * @property oDomContainer * @type HTMLElement */ oDomContainer: null, /** * 오늘 날짜 * @property today * @type Date */ today: null, /** * cells을 render할 때 사용하는 내부배열 * @property renderStack * @type Array[] */ renderStack: null, /** * cells을 render할 때 사용하는 내부배열 사본 * @property _renderStack * @private * @type Array */ _renderStack: null, /** * LCalendarNavigator 객체 * @property oNavigator * @type LCalendarNavigator */ oNavigator: null, /** * 선택된 날짜 배열 * @property _selectedDates * @private * @type Array */ _selectedDates: null, /** * 이벤트 맵 * @property domEventMap * @type Object */ domEventMap: null, /** * 생성자 파라미터 파서 * @protected * @method _parseArgs * @param {Array} Function "arguments" array * @return {Object} Object with id, container, config properties containing * the reconciled argument values. **/ _parseArgs: function(args) { /* 2.4.0 Constructors signatures new LCalendar(String) new LCalendar(HTMLElement) new LCalendar(String, ConfigObject) new LCalendar(HTMLElement, ConfigObject) Pre 2.4.0 Constructor signatures new LCalendar(String, String) new LCalendar(String, HTMLElement) new LCalendar(String, String, ConfigObject) new LCalendar(String, HTMLElement, ConfigObject) */ var nArgs = { id: null, container: null, config: null }; if (args && args.length && args.length > 0) { switch (args.length) { case 1: nArgs.id = args[0].id ? args[0].id : null; nArgs.container = args[0].applyTo ? args[0].applyTo : args[0]; nArgs.config = typeof args[0] == 'object' ? args[0] : null; break; case 2: if (Lang.isObject(args[1]) && !args[1].tagName && !(args[1] instanceof String)) { nArgs.id = null; nArgs.container = args[0]; nArgs.config = args[1]; } else { nArgs.id = args[0]; nArgs.container = args[1]; nArgs.config = null; } break; default: // 3+ nArgs.id = args[0]; nArgs.container = args[1]; nArgs.config = args[2]; break; } } else { } return nArgs; }, /** * LCalendar init 메소드. * @method init * @private * @param {String} id optional The id of the table element that will represent the LCalendar widget. As of 2.4.0, this argument is optional. * @param {String | HTMLElement} container The id of the container div element that will wrap the LCalendar table, or a reference to a DIV element which exists in the document. * @param {Object} config optional The configuration object containing the initial configuration values for the LCalendar. */ init: function(id, container, config) { // Normalize 2.4.0, pre 2.4.0 args var nArgs = this._parseArgs(arguments); id = nArgs.id; container = nArgs.container; config = nArgs.config; //du_config설정 config = DU.util.LDom.applyIfProperties(config, '$.ext.calendar'); this.oDomContainer = Dom.get(container); if (!this.oDomContainer.id) { this.oDomContainer.id = Dom.generateId(); } if (!id) { id = this.oDomContainer.id + "_t"; } this.id = id; this.containerId = this.oDomContainer.id; this.initEvents(); this.today = new Date(); DU.util.LDate.clearTime(this.today); /** * The Config object used to hold the configuration variables for the LCalendar * @property cfg * @type DU.widget.LConfig */ this.cfg = new DU.widget.LConfig(this); /** * The local object which contains the LCalendar's options * @property Options * @type Object */ this.Options = {}; /** * The local object which contains the LCalendar's locale settings * @property Locale * @type Object */ this.Locale = {}; this.initStyles(); Dom.addClass(this.oDomContainer, this.Style.CSS_CONTAINER); Dom.addClass(this.oDomContainer, this.Style.CSS_SINGLE); Dom.addClass(this.oDomContainer, "L-fixed"); this.cellDates = []; this.cells = []; this.renderStack = []; this._renderStack = []; this.setupConfig(); if (config) { this.cfg.applyConfig(config, true); } this.cfg.fireQueue(); //du_config읽어서 local 설정하기 this._setDefaultLocale(); }, /** * @description 사용자가 직접 .cfg.setProperty 를 호출하지 않도록 사용성을 위해 wrapping * @method setProperty * @param key {object} * @param value {object} */ setProperty : function(key,value){ this.cfg.setProperty(key,value); }, /** * @description 사용자가 직접 .cfg.setProperty 를 호출하지 않도록 사용성을 위해 wrapping * @method getProperty * @param key {object} * @return {object} */ getProperty : function(key){ return this.cfg.getProperty(key); }, _setDefaultLocale: function(config) { var locale = DU.getConfig().getFirst("$.core.defaultLocale"); //LDateLocale값을 사용. var aLocale = DU.util.LDate.getLocale(locale); var configLocale = DU.getConfig().getFirst('$.ext.calendar.locale.' + locale); var x = aLocale["x"]; var order = x.split('%'); var posY = 1; var posM = 2; var posD = 3; var c = ""; for(var i=1;i* Setting this property to null (default value) or false, will disable the LCalendarNavigator UI. *
** Setting this property to true will enable the CalendarNavigatior UI with the default LCalendarNavigator configuration values. *
** This property can also be set to an object literal containing configuration properties for the LCalendarNavigator UI. * The configuration object expects the the following case-sensitive properties, with the "strings" property being a nested object. * Any properties which are not provided will use the default values (defined in the LCalendarNavigator class). *
*E.g.
** var navConfig = { * strings: { * month:"LCalendar Month", * year:"LCalendar Year", * submit: "Submit", * cancel: "Cancel", * invalidYear: "Please enter a valid year" * }, * monthFormat: DU.widget.LCalendar.SHORT, * initialFocus: "month" * } ** @config navigator * @type {Object|Boolean} * @default null */ cfg.addProperty(DEF_CFG.NAV.key, { value: DEF_CFG.NAV.value, handler: this.configNavigator }); /** * The map of UI strings which the LCalendar UI uses. * * @config strings * @type {Object} * @default An object with the properties shown below: *
* The returned index can be used to lookup the cell HTMLElement * using the LCalendar's cells array or passed to selectCell to select * cells by index. *
* * See cells, selectCell. * * @method getCellIndex * @param {Date} date JavaScript Date object, for which to find a cell index. * @return {Number} The index of the date in Calendars cellDates/cells arrays, or -1 if the date * is not on the curently rendered LCalendar page. */ getCellIndex: function(date) { var idx = -1; if (date) { var m = date.getMonth(), y = date.getFullYear(), d = date.getDate(), dates = this.cellDates; for (var i = 0; i < dates.length; ++i) { var cellDate = dates[i]; if (cellDate[0] === y && cellDate[1] === m + 1 && cellDate[2] === d) { idx = i; break; } } } return idx; }, /** * Given the id used to mark each LCalendar cell, this method * extracts the index number from the id. * * @param {String} strId The cell id * @return {Number} The index of the cell, or -1 if id does not contain an index number */ getIndexFromId: function(strId) { var idx = -1, li = strId.lastIndexOf("_cell"); if (li > -1) { idx = parseInt(strId.substring(li + 5), 10); } return idx; }, // BEGIN BUILT-IN TABLE CELL RENDERERS /** * Renders a cell that falls before the minimum date or after the maximum date. * widget class. * @method renderOutOfBoundsDate * @param {Date} workingDate The current working Date object being used to generate the calendar * @param {HTMLTableCellElement} cell The current working cell in the calendar * @return {String} DU.widget.LCalendar.STOP_RENDER if rendering should stop with this style, null or nothing if rendering * should not be terminated */ renderOutOfBoundsDate: function(workingDate, cell) { Dom.addClass(cell, this.Style.CSS_CELL_OOB); cell.innerHTML = workingDate.getDate(); return LCalendar.STOP_RENDER; }, /** * Renders the row header for a week. * @method renderRowHeader * @param {Number} weekNum The week number of the current row * @param {Array} cell The current working HTML array */ renderRowHeader: function(weekNum, html) { html[html.length] = '* NOTE: As of 2.4.0, the constructor's ID argument is optional. * The LCalendarGroup can be constructed by simply providing a container ID string, * or a reference to a container DIV HTMLElement (the element needs to exist * in the document). * * E.g.: *
* If not provided, the ID will be generated from the container DIV ID by adding an "_t" suffix. * For example if an ID is not provided, and the container's ID is "calContainer", the LCalendarGroup's ID will be set to "calContainer_t". *
* * @module widget_calendar * @namespace DU.widget * @class LCalendarGroup * @constructor * @param {String} id optional The id of the table element that will represent the LCalendarGroup widget. As of 2.4.0, this argument is optional. * @param {String | HTMLElement} container The id of the container div element that will wrap the LCalendarGroup table, or a reference to a DIV element which exists in the document. * @param {Object} config optional The configuration object containing the initial configuration values for the LCalendarGroup. */ function LCalendarGroup(id, containerId, config) { if (arguments.length > 0) { this.init.apply(this, arguments); } } /** * The set of default Config property keys and values for the LCalendarGroup * @property DU.widget.LCalendarGroup._DEFAULT_CONFIG * @final * @static * @private * @type Object */ LCalendarGroup._DEFAULT_CONFIG = LCalendar._DEFAULT_CONFIG; LCalendarGroup._DEFAULT_CONFIG.PAGES = { key: "pages", value: 2 }; var DEF_CFG = LCalendarGroup._DEFAULT_CONFIG; LCalendarGroup.prototype = { /** * Initializes the calendar group. All subclasses must call this method in order for the * group to be initialized properly. * @method init * @param {String} id optional The id of the table element that will represent the LCalendarGroup widget. As of 2.4.0, this argument is optional. * @param {String | HTMLElement} container The id of the container div element that will wrap the LCalendarGroup table, or a reference to a DIV element which exists in the document. * @param {Object} config optional The configuration object containing the initial configuration values for the LCalendarGroup. */ init: function(id, container, config) { // Normalize 2.4.0, pre 2.4.0 args var nArgs = this._parseArgs(arguments); id = nArgs.id; container = nArgs.container; config = nArgs.config; this.oDomContainer = Dom.get(container); if (!this.oDomContainer.id) { this.oDomContainer.id = Dom.generateId(); } if (!id) { id = this.oDomContainer.id + "_t"; } /** * The unique id associated with the LCalendarGroup * @property id * @type String */ this.id = id; /** * The unique id associated with the LCalendarGroup container * @property containerId * @type String */ this.containerId = this.oDomContainer.id; this.initEvents(); this.initStyles(); /** * The collection of LCalendar pages contained within the LCalendarGroup * @property pages * @type DU.widget.LCalendar[] */ this.pages = []; Dom.addClass(this.oDomContainer, LCalendarGroup.CSS_CONTAINER); Dom.addClass(this.oDomContainer, LCalendarGroup.CSS_MULTI_UP); Dom.addClass(this.oDomContainer, "L-fixed"); /** * The Config object used to hold the configuration variables for the LCalendarGroup * @property cfg * @type DU.widget.LConfig */ this.cfg = new DU.widget.LConfig(this); /** * The local object which contains the LCalendarGroup's options * @property Options * @type Object */ this.Options = {}; /** * The local object which contains the LCalendarGroup's locale settings * @property Locale * @type Object */ this.Locale = {}; this.setupConfig(); if (config) { this.cfg.applyConfig(config, true); } this.cfg.fireQueue(); // OPERA HACK FOR MISWRAPPED FLOATS if (DU.browser.opera) { this.renderEvent.on(this._fixWidth, this, true); this.showEvent.on(this._fixWidth, this, true); } }, setupConfig: function() { var cfg = this.cfg; /** * The number of pages to include in the LCalendarGroup. This value can only be set once, in the LCalendarGroup's constructor arguments. * @config pages * @type Number * @default 2 */ cfg.addProperty(DEF_CFG.PAGES.key, { value: DEF_CFG.PAGES.value, validator: cfg.checkNumber, handler: this.configPages }); /** * The month/year representing the current visible LCalendar date (mm/yyyy) * @config pagedate * @type String | Date * @default today's date */ cfg.addProperty(DEF_CFG.PAGEDATE.key, { value: new Date(), handler: this.configPageDate }); /** * The date or range of dates representing the current LCalendar selection * * @config selected * @type String * @default [] */ cfg.addProperty(DEF_CFG.SELECTED.key, { value: [], handler: this.configSelected }); /** * The title to display above the LCalendarGroup's month header * @config title * @type String * @default "" */ cfg.addProperty(DEF_CFG.TITLE.key, { value: DEF_CFG.TITLE.value, handler: this.configTitle }); /** * Whether or not a close button should be displayed for this LCalendarGroup * @config close * @type Boolean * @default false */ cfg.addProperty(DEF_CFG.CLOSE.key, { value: DEF_CFG.CLOSE.value, handler: this.configClose }); /** * Whether or not an iframe shim should be placed under the LCalendar to prevent select boxes from bleeding through in Internet Explorer 6 and below. * This property is enabled by default for IE6 and below. It is disabled by default for other browsers for performance reasons, but can be * enabled if required. * * @config iframe * @type Boolean * @default true for IE6 and below, false for all other browsers */ cfg.addProperty(DEF_CFG.IFRAME.key, { value: DEF_CFG.IFRAME.value, handler: this.configIframe, validator: cfg.checkBoolean }); /** * The minimum selectable date in the current LCalendar (mm/dd/yyyy) * @config mindate * @type String | Date * @default null */ cfg.addProperty(DEF_CFG.MINDATE.key, { value: DEF_CFG.MINDATE.value, handler: this.delegateConfig }); /** * The maximum selectable date in the current LCalendar (mm/dd/yyyy) * @config maxdate * @type String | Date * @default null */ cfg.addProperty(DEF_CFG.MAXDATE.key, { value: DEF_CFG.MAXDATE.value, handler: this.delegateConfig }); // Options properties /** * True if the LCalendar should allow multiple selections. False by default. * @config MULTI_SELECT * @type Boolean * @default false */ cfg.addProperty(DEF_CFG.MULTI_SELECT.key, { value: DEF_CFG.MULTI_SELECT.value, handler: this.delegateConfig, validator: cfg.checkBoolean }); /** * The weekday the week begins on. Default is 0 (Sunday). * @config START_WEEKDAY * @type number * @default 0 */ cfg.addProperty(DEF_CFG.START_WEEKDAY.key, { value: DEF_CFG.START_WEEKDAY.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * True if the LCalendar should show weekday labels. True by default. * @config SHOW_WEEKDAYS * @type Boolean * @default true */ cfg.addProperty(DEF_CFG.SHOW_WEEKDAYS.key, { value: DEF_CFG.SHOW_WEEKDAYS.value, handler: this.delegateConfig, validator: cfg.checkBoolean }); /** * True if the LCalendar should show week row headers. False by default. * @config SHOW_WEEK_HEADER * @type Boolean * @default false */ cfg.addProperty(DEF_CFG.SHOW_WEEK_HEADER.key, { value: DEF_CFG.SHOW_WEEK_HEADER.value, handler: this.delegateConfig, validator: cfg.checkBoolean }); /** * True if the LCalendar should show week row footers. False by default. * @config SHOW_WEEK_FOOTER * @type Boolean * @default false */ cfg.addProperty(DEF_CFG.SHOW_WEEK_FOOTER.key, { value: DEF_CFG.SHOW_WEEK_FOOTER.value, handler: this.delegateConfig, validator: cfg.checkBoolean }); /** * True if the LCalendar should suppress weeks that are not a part of the current month. False by default. * @config HIDE_BLANK_WEEKS * @type Boolean * @default false */ cfg.addProperty(DEF_CFG.HIDE_BLANK_WEEKS.key, { value: DEF_CFG.HIDE_BLANK_WEEKS.value, handler: this.delegateConfig, validator: cfg.checkBoolean }); /** * The image that should be used for the left navigation arrow. * @config NAV_ARROW_LEFT * @type String * @deprecated You can customize the image by overriding the default CSS class for the left arrow - "calnavleft" * @default null */ cfg.addProperty(DEF_CFG.NAV_ARROW_LEFT.key, { value: DEF_CFG.NAV_ARROW_LEFT.value, handler: this.delegateConfig }); /** * The image that should be used for the right navigation arrow. * @config NAV_ARROW_RIGHT * @type String * @deprecated You can customize the image by overriding the default CSS class for the right arrow - "calnavright" * @default null */ cfg.addProperty(DEF_CFG.NAV_ARROW_RIGHT.key, { value: DEF_CFG.NAV_ARROW_RIGHT.value, handler: this.delegateConfig }); // Locale properties /** * The short month labels for the current locale. * @config MONTHS_SHORT * @type String[] * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] */ cfg.addProperty(DEF_CFG.MONTHS_SHORT.key, { value: DEF_CFG.MONTHS_SHORT.value, handler: this.delegateConfig }); /** * The long month labels for the current locale. * @config MONTHS_LONG * @type String[] * @default ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" */ cfg.addProperty(DEF_CFG.MONTHS_LONG.key, { value: DEF_CFG.MONTHS_LONG.value, handler: this.delegateConfig }); /** * The 1-character weekday labels for the current locale. * @config WEEKDAYS_1CHAR * @type String[] * @default ["S", "M", "T", "W", "T", "F", "S"] */ cfg.addProperty(DEF_CFG.WEEKDAYS_1CHAR.key, { value: DEF_CFG.WEEKDAYS_1CHAR.value, handler: this.delegateConfig }); /** * The short weekday labels for the current locale. * @config WEEKDAYS_SHORT * @type String[] * @default ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] */ cfg.addProperty(DEF_CFG.WEEKDAYS_SHORT.key, { value: DEF_CFG.WEEKDAYS_SHORT.value, handler: this.delegateConfig }); /** * The medium weekday labels for the current locale. * @config WEEKDAYS_MEDIUM * @type String[] * @default ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] */ cfg.addProperty(DEF_CFG.WEEKDAYS_MEDIUM.key, { value: DEF_CFG.WEEKDAYS_MEDIUM.value, handler: this.delegateConfig }); /** * The long weekday labels for the current locale. * @config WEEKDAYS_LONG * @type String[] * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] */ cfg.addProperty(DEF_CFG.WEEKDAYS_LONG.key, { value: DEF_CFG.WEEKDAYS_LONG.value, handler: this.delegateConfig }); /** * The setting that determines which length of month labels should be used. Possible values are "short" and "long". * @config LOCALE_MONTHS * @type String * @default "long" */ cfg.addProperty(DEF_CFG.LOCALE_MONTHS.key, { value: DEF_CFG.LOCALE_MONTHS.value, handler: this.delegateConfig }); /** * The setting that determines which length of weekday labels should be used. Possible values are "1char", "short", "medium", and "long". * @config LOCALE_WEEKDAYS * @type String * @default "short" */ cfg.addProperty(DEF_CFG.LOCALE_WEEKDAYS.key, { value: DEF_CFG.LOCALE_WEEKDAYS.value, handler: this.delegateConfig }); /** * The value used to delimit individual dates in a date string passed to various LCalendar functions. * @config DATE_DELIMITER * @type String * @default "," */ cfg.addProperty(DEF_CFG.DATE_DELIMITER.key, { value: DEF_CFG.DATE_DELIMITER.value, handler: this.delegateConfig }); /** * The value used to delimit date fields in a date string passed to various LCalendar functions. * @config DATE_FIELD_DELIMITER * @type String * @default "/" */ cfg.addProperty(DEF_CFG.DATE_FIELD_DELIMITER.key, { value: DEF_CFG.DATE_FIELD_DELIMITER.value, handler: this.delegateConfig }); /** * The value used to delimit date ranges in a date string passed to various LCalendar functions. * @config DATE_RANGE_DELIMITER * @type String * @default "-" */ cfg.addProperty(DEF_CFG.DATE_RANGE_DELIMITER.key, { value: DEF_CFG.DATE_RANGE_DELIMITER.value, handler: this.delegateConfig }); /** * The position of the month in a month/year date string * @config MY_MONTH_POSITION * @type Number * @default 1 */ cfg.addProperty(DEF_CFG.MY_MONTH_POSITION.key, { value: DEF_CFG.MY_MONTH_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the year in a month/year date string * @config MY_YEAR_POSITION * @type Number * @default 2 */ cfg.addProperty(DEF_CFG.MY_YEAR_POSITION.key, { value: DEF_CFG.MY_YEAR_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the month in a month/day date string * @config MD_MONTH_POSITION * @type Number * @default 1 */ cfg.addProperty(DEF_CFG.MD_MONTH_POSITION.key, { value: DEF_CFG.MD_MONTH_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the day in a month/year date string * @config MD_DAY_POSITION * @type Number * @default 2 */ cfg.addProperty(DEF_CFG.MD_DAY_POSITION.key, { value: DEF_CFG.MD_DAY_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the month in a month/day/year date string * @config MDY_MONTH_POSITION * @type Number * @default 1 */ cfg.addProperty(DEF_CFG.MDY_MONTH_POSITION.key, { value: DEF_CFG.MDY_MONTH_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the day in a month/day/year date string * @config MDY_DAY_POSITION * @type Number * @default 2 */ cfg.addProperty(DEF_CFG.MDY_DAY_POSITION.key, { value: DEF_CFG.MDY_DAY_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the year in a month/day/year date string * @config MDY_YEAR_POSITION * @type Number * @default 3 */ cfg.addProperty(DEF_CFG.MDY_YEAR_POSITION.key, { value: DEF_CFG.MDY_YEAR_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the month in the month year label string used as the LCalendar header * @config MY_LABEL_MONTH_POSITION * @type Number * @default 1 */ cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_POSITION.key, { value: DEF_CFG.MY_LABEL_MONTH_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The position of the year in the month year label string used as the LCalendar header * @config MY_LABEL_YEAR_POSITION * @type Number * @default 2 */ cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_POSITION.key, { value: DEF_CFG.MY_LABEL_YEAR_POSITION.value, handler: this.delegateConfig, validator: cfg.checkNumber }); /** * The suffix used after the month when rendering the LCalendar header * @config MY_LABEL_MONTH_SUFFIX * @type String * @default " " */ cfg.addProperty(DEF_CFG.MY_LABEL_MONTH_SUFFIX.key, { value: DEF_CFG.MY_LABEL_MONTH_SUFFIX.value, handler: this.delegateConfig }); /** * The suffix used after the year when rendering the LCalendar header * @config MY_LABEL_YEAR_SUFFIX * @type String * @default "" */ cfg.addProperty(DEF_CFG.MY_LABEL_YEAR_SUFFIX.key, { value: DEF_CFG.MY_LABEL_YEAR_SUFFIX.value, handler: this.delegateConfig }); /** * LConfiguration for the Month Year Navigation UI. By default it is disabled * @config NAV * @type Object * @default null */ cfg.addProperty(DEF_CFG.NAV.key, { value: DEF_CFG.NAV.value, handler: this.configNavigator }); /** * The map of UI strings which the LCalendarGroup UI uses. * * @config strings * @type {Object} * @default An object with the properties shown below: ** The method is also registered as an HTMLElement resize listener on the Calendars container element. *
* @protected * @method _syncMask */ _syncMask: function() { var c = this.cal.oDomContainer; if (c && this.maskEl) { var r = DU.util.LDom.getRegion(c); DU.util.LDom.setStyle(this.maskEl, "width", r.right - r.left + "px"); DU.util.LDom.setStyle(this.maskEl, "height", r.bottom - r.top + "px"); } }, /** * Renders the contents of the navigator * * @method renderNavContents * * @param {Array} html The HTML buffer to append the HTML to. * @return {Array} A reference to the buffer passed in. */ renderNavContents: function(html) { var NAV = DU.widget.LCalendarNavigator, C = NAV.CLASSES, h = html; // just to use a shorter name h[h.length] = '* The method will call applyKeyListeners, to setup keyboard specific * listeners *
* @method applyListeners */ applyListeners: function() { var E = DU.util.LEvent; function yearUpdateHandler() { if (this.validate()) { this.setYear(this._getYearFromUI()); } } function monthUpdateHandler() { this.setMonth(this._getMonthFromUI()); } E.on(this.submitEl, "click", this.submit, this, true); E.on(this.cancelEl, "click", this.cancel, this, true); E.on(this.yearEl, "blur", yearUpdateHandler, this, true); E.on(this.monthEl, "change", monthUpdateHandler, this, true); if (this.__isIEQuirks) { DU.util.LEvent.on(this.cal.oDomContainer, "resize", this._syncMask, this, true); } this.applyKeyListeners(); }, /** * Removes/purges DOM event listeners from the rendered elements * * @method purgeListeners */ purgeListeners: function() { var E = DU.util.LEvent; E.removeListener(this.submitEl, "click", this.submit); E.removeListener(this.cancelEl, "click", this.cancel); E.removeListener(this.yearEl, "blur"); E.removeListener(this.monthEl, "change"); if (this.__isIEQuirks) { E.removeListener(this.cal.oDomContainer, "resize", this._syncMask); } this.purgeKeyListeners(); }, /** * Attaches DOM listeners for keyboard support. * Tab/Shift-Tab looping, Enter Key Submit on Year element, * Up/Down/PgUp/PgDown year increment on Year element ** NOTE: MacOSX Safari 2.x doesn't let you tab to buttons and * MacOSX Gecko does not let you tab to buttons or select controls, * so for these browsers, Tab/Shift-Tab looping is limited to the * elements which can be reached using the tab key. *
* @method applyKeyListeners */ applyKeyListeners: function() { var E = DU.util.LEvent, ua = DU.browser; // IE/Safari 3.1 doesn't fire keypress for arrow/pg keys (non-char keys) var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress"; // - IE/Safari 3.1 doesn't fire keypress for non-char keys // - Opera doesn't allow us to cancel keydown or keypress for tab, but // changes focus successfully on keydown (keypress is too late to change focus - opera's already moved on). var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress"; // Everyone likes keypress for Enter (char keys) - whoo hoo! E.on(this.yearEl, "keypress", this._handleEnterKey, this, true); E.on(this.yearEl, arrowEvt, this._handleDirectionKeys, this, true); E.on(this.lastCtrl, tabEvt, this._handleTabKey, this, true); E.on(this.firstCtrl, tabEvt, this._handleShiftTabKey, this, true); }, /** * Removes/purges DOM listeners for keyboard support * * @method purgeKeyListeners */ purgeKeyListeners: function() { var E = DU.util.LEvent, ua = DU.browser; var arrowEvt = (ua.ie || ua.webkit) ? "keydown" : "keypress"; var tabEvt = (ua.ie || ua.opera || ua.webkit) ? "keydown" : "keypress"; E.removeListener(this.yearEl, "keypress", this._handleEnterKey); E.removeListener(this.yearEl, arrowEvt, this._handleDirectionKeys); E.removeListener(this.lastCtrl, tabEvt, this._handleTabKey); E.removeListener(this.firstCtrl, tabEvt, this._handleShiftTabKey); }, /** * Updates the LCalendar/LCalendarGroup's pagedate with the currently set month and year if valid. ** If the currently set month/year is invalid, a validation error will be displayed and the * LCalendar/LCalendarGroup's pagedate will not be updated. *
* @method submit */ submit: function() { if (this.validate()) { this.hide(); this.setMonth(this._getMonthFromUI()); this.setYear(this._getYearFromUI()); var cal = this.cal; // Artificial delay, just to help the user see something changed var delay = DU.widget.LCalendarNavigator.UPDATE_DELAY; if (delay > 0) { var nav = this; window.setTimeout(function() { nav._update(cal); }, delay); } else { this._update(cal); } } }, /** * Updates the LCalendar rendered state, based on the state of the LCalendarNavigator * @method _update * @param cal The LCalendar instance to update * @protected */ _update: function(cal) { cal.setYear(this.getYear()); cal.setMonth(this.getMonth()); cal.render(); }, /** * Hides the navigator and mask, without updating the LCalendar/LCalendarGroup's state * * @method cancel */ cancel: function() { this.hide(); }, /** * Validates the current state of the UI controls * * @method validate * @return {Boolean} true, if the current UI state contains valid values, false if not */ validate: function() { if (this._getYearFromUI() !== null) { this.clearErrors(); return true; } else { this.setYearError(); this.setError(this.__getCfg("invalidYear", true)); return false; } }, /** * Displays an error message in the Navigator's error panel * @method setError * @param {String} msg The error message to display */ setError: function(msg) { if (this.errorEl) { this.errorEl.innerHTML = msg; this._show(this.errorEl, true); } }, /** * Clears the navigator's error message and hides the error panel * @method clearError */ clearError: function() { if (this.errorEl) { this.errorEl.innerHTML = ""; this._show(this.errorEl, false); } }, /** * Displays the validation error UI for the year control * @method setYearError */ setYearError: function() { DU.util.LDom.addClass(this.yearEl, DU.widget.LCalendarNavigator.CLASSES.INVALID); }, /** * Removes the validation error UI for the year control * @method clearYearError */ clearYearError: function() { DU.util.LDom.removeClass(this.yearEl, DU.widget.LCalendarNavigator.CLASSES.INVALID); }, /** * Clears all validation and error messages in the UI * @method clearErrors */ clearErrors: function() { this.clearError(); this.clearYearError(); }, /** * Sets the initial focus, based on the configured value * @method setInitialFocus */ setInitialFocus: function() { var el = this.submitEl, f = this.__getCfg("initialFocus"); if (f && f.toLowerCase) { f = f.toLowerCase(); if (f == "year") { el = this.yearEl; try { this.yearEl.select(); } catch (selErr) { // Ignore; } } else if (f == "month") { el = this.monthEl; } } if (el && DU.isFunction(el.focus)) { try { el.focus(); } catch (focusErr) { // TODO: Fall back if focus fails? } } }, /** * Removes all renderered HTML elements for the Navigator from * the DOM, purges event listeners and clears (nulls) any property * references to HTML references * @method erase */ erase: function() { if (this.__rendered) { this.purgeListeners(); // Clear out innerHTML references this.yearEl = null; this.monthEl = null; this.errorEl = null; this.submitEl = null; this.cancelEl = null; this.firstCtrl = null; this.lastCtrl = null; if (this.navEl) { this.navEl.innerHTML = ""; } var p = this.navEl.parentNode; if (p) { p.removeChild(this.navEl); } this.navEl = null; var pm = this.maskEl.parentNode; if (pm) { pm.removeChild(this.maskEl); } this.maskEl = null; this.__rendered = false; } }, /** * Destroys the Navigator object and any HTML references * @method destroy */ destroy: function() { this.erase(); this._doc = null; this.cal = null; this.id = null; }, /** * Protected implementation to handle how UI elements are * hidden/shown. * * @method _show * @protected */ _show: function(el, bShow) { if (el) { DU.util.LDom.setStyle(el, "display", (bShow) ? "block" : "none"); } }, /** * Returns the month value (index), from the month UI element * @protected * @method _getMonthFromUI * @return {Number} The month index, or 0 if a UI element for the month * is not found */ _getMonthFromUI: function() { if (this.monthEl) { return this.monthEl.selectedIndex; } else { return 0; // Default to Jan } }, /** * Returns the year value, from the Navitator's year UI element * @protected * @method _getYearFromUI * @return {Number} The year value set in the UI, if valid. null is returned if * the UI does not contain a valid year value. */ _getYearFromUI: function() { var NAV = DU.widget.LCalendarNavigator; var yr = null; if (this.yearEl) { var value = this.yearEl.value; value = value.replace(NAV.TRIM, "$1"); if (NAV.YR_PATTERN.test(value)) { yr = parseInt(value, 10); } } return yr; }, /** * Updates the Navigator's year UI, based on the year value set on the Navigator object * @protected * @method _updateYearUI */ _updateYearUI: function() { if (this.yearEl && this._year !== null) { this.yearEl.value = this._year; } }, /** * Updates the Navigator's month UI, based on the month value set on the Navigator object * @protected * @method _updateMonthUI */ _updateMonthUI: function() { if (this.monthEl) { this.monthEl.selectedIndex = this._month; } }, /** * Sets up references to the first and last focusable element in the Navigator's UI * in terms of tab order (Naviagator's firstEl and lastEl properties). The references * are used to control modality by looping around from the first to the last control * and visa versa for tab/shift-tab navigation. ** See applyKeyListeners *
* @protected * @method _setFirstLastElements */ _setFirstLastElements: function() { this.firstCtrl = this.monthEl; this.lastCtrl = this.cancelEl; // Special handling for MacOSX. // - Safari 2.x can't focus on buttons // - Gecko can't focus on select boxes or buttons if (this.__isMac) { if (DU.browser.webkit && DU.browser.webkit < 420) { this.firstCtrl = this.monthEl; this.lastCtrl = this.yearEl; } if (DU.browser.gecko) { this.firstCtrl = this.yearEl; this.lastCtrl = this.yearEl; } } }, /** * Default Keyboard event handler to capture Enter * on the Navigator's year control (yearEl) * * @method _handleEnterKey * @protected * @param {Event} e The DOM event being handled */ _handleEnterKey: function(e) { var KEYS = DU.util.LKeyListener.KEY; if (DU.util.LEvent.getCharCode(e) == KEYS.ENTER) { DU.util.LEvent.preventDefault(e); this.submit(); } }, /** * Default Keyboard event handler to capture up/down/pgup/pgdown * on the Navigator's year control (yearEl). * * @method _handleDirectionKeys * @protected * @param {Event} e The DOM event being handled */ _handleDirectionKeys: function(e) { var E = DU.util.LEvent, KEYS = DU.util.LKeyListener.KEY, NAV = DU.widget.LCalendarNavigator; var value = (this.yearEl.value) ? parseInt(this.yearEl.value, 10) : null; if (isFinite(value)) { var dir = false; switch (E.getCharCode(e)) { case KEYS.UP: this.yearEl.value = value + NAV.YR_MINOR_INC; dir = true; break; case KEYS.DOWN: this.yearEl.value = Math.max(value - NAV.YR_MINOR_INC, 0); dir = true; break; case KEYS.PAGE_UP: this.yearEl.value = value + NAV.YR_MAJOR_INC; dir = true; break; case KEYS.PAGE_DOWN: this.yearEl.value = Math.max(value - NAV.YR_MAJOR_INC, 0); dir = true; break; default: break; } if (dir) { E.preventDefault(e); try { this.yearEl.select(); } catch (err) { // Ignore } } } }, /** * Default Keyboard event handler to capture Tab * on the last control (lastCtrl) in the Navigator. * * @method _handleTabKey * @protected * @param {Event} e The DOM event being handled */ _handleTabKey: function(e) { var E = DU.util.LEvent, KEYS = DU.util.LKeyListener.KEY; if (E.getCharCode(e) == KEYS.TAB && !e.shiftKey) { try { E.preventDefault(e); this.firstCtrl.focus(); } catch (err) { // Ignore - mainly for focus edge cases } } }, /** * Default Keyboard event handler to capture Shift-Tab * on the first control (firstCtrl) in the Navigator. * * @method _handleShiftTabKey * @protected * @param {Event} e The DOM event being handled */ _handleShiftTabKey: function(e) { var E = DU.util.LEvent, KEYS = DU.util.LKeyListener.KEY; if (e.shiftKey && E.getCharCode(e) == KEYS.TAB) { try { E.preventDefault(e); this.lastCtrl.focus(); } catch (err) { // Ignore - mainly for focus edge cases } } }, /** * Retrieve Navigator configuration values from * the parent LCalendar/LCalendarGroup's config value. ** If it has not been set in the user provided configuration, the method will * return the default value of the configuration property, as set in _DEFAULT_CFG *
* @private * @method __getCfg * @param {String} Case sensitive property name. * @param {Boolean} true, if the property is a string property, false if not. * @return The value of the configuration property */ __getCfg: function(prop, bIsStr) { var DEF_CFG = DU.widget.LCalendarNavigator._DEFAULT_CFG; var cfg = this.cal.cfg.getProperty("navigator"); if (bIsStr) { return (cfg !== true && cfg.strings && cfg.strings[prop]) ? cfg.strings[prop] : DEF_CFG.strings[prop]; } else { return (cfg !== true && cfg[prop]) ? cfg[prop] : DEF_CFG[prop]; } }, /** * Private flag, to identify MacOS * @private * @property __isMac */ __isMac: (navigator.userAgent.toLowerCase().indexOf("macintosh") != -1) }; /** * @description LColumn * @module widget_grid * @namespace DU.widget * @class LColumn * @constructor * @param {Object} oConfigs 생성자 Config 객체 */ DU.widget.LColumn = function(oConfigs) { var config = oConfigs || {}; this.id = config.id || config.field || this.id; DU.applyObject(this, config, true); this.label = this.label || this.field || this.id; /** * @description hidden 기능이 호출되면 수행하는 이벤트 * @event hidden * @param {Object} target this객체 * @param {Boolean} hidden hidden값 */ this.createEvent('hidden'); /** * @description sortable 기능이 호출되면 수행하는 이벤트 * @event sortable * @param {Object} target this객체 * @param {Boolean} sortable sortable값 */ this.createEvent('sortable'); /** * @description label일 변경되면 호출되면 수행하는 이벤트 * @event label * @param {Object} target this객체 * @param {Boolean} label sortable값 */ this.createEvent('label'); /** * @description panel이 columnresize 되면 호출되는 이벤트 * @event columnresize * @param {Object} target this객체 * @param {Int} oldWidth pixel * @param {Int} newWidth pixel */ this.createEvent("columnresize"); this.init(); this.editable = DU.isUndefined(config.editable) == false ? config.editable : DU.isUndefined(config.customEditor) == false ? config.customEditor : !this.editor ? false : true; }; DU.extend(DU.widget.LColumn, DU.util.LEventProvider, { /** * @description 객체의 id * @config id * @type {String} * @default null */ /** * @description 객체의 id * @property id * @private * @type {String} */ id : null, /** * @description Column Model * @property columnModel * @private * @type {DU.widget.LColumnModel} */ columnModel: null, /** * @description Column label * @config label * @type {String} * @default null */ /** * @description Column label * @property label * @private * @type {String} */ label: null, /** * @description dataSet의 field 명 * @config field * @type {String} * @default null */ /** * @description dataSet의 field 명 * @property field * @private * @type {String} */ field: null, /** * @description Column width * @config width * @type {Int} * @default null */ /** * @description Column width * @property width * @private * @type {Int} */ width: null, /** * @description Column의 최소 width * @config minWidth * @type {Int} * @default 10 */ /** * @description Column의 최소 width * @property minWidth * @private * @type {Int} */ minWidth: 10, /** * @description Column 자동 max width * @config maxAutoWidth * @type {Int} * @default null */ /** * @description Column 자동 max width * @property maxAutoWidth * @private * @type {Int} */ maxAutoWidth: null, /** * @description Column hidden 속성 * @config hidden * @type {Boolean} * @default false */ /** * @description Column hidden 속성 * @property hidden * @private * @type {Boolean} */ hidden: false, /** * @description Column selected 속성 * @config selected * @type {Boolean} * @default true */ /** * @description Column selected 속성 * @property selected * @private * @type {Boolean} */ selected: true, /** * @description Column resizable 속성 * @config resizable * @type {Boolean} * @default true */ /** * @description Column resizable 속성 * @property resizable * @private * @type {Boolean} */ resizable: true, /** * @description Column fixed 속성 * @config fixed * @type {Boolean} * @default false */ /** * @description Column fixed 속성 * @property fixed * @private * @type {Boolean} */ fixed: false, /** * @description Column 정렬 속성 * @config sortable * @type {Boolean} * @default false */ /** * @description Column 정렬 속성 * @property sortable * @private * @type {Boolean} */ sortable: false, /** * @description 내용의 Column 가로 정렬 속성 * @config align * @type {String} * @default '' */ /** * @description 내용의 Column 가로 정렬 속성 * @property align * @private * @type {String} */ align:'', /** * @description Column draggable 속성 * @config draggable * @type {Boolean} * @default true */ /** * @description Column draggable 속성 * @property draggable * @private * @type {Boolean} */ draggable: true, /** * @description Column editable 속성 * @config editable * @type {Boolean} * @default true */ /** * @description Column editable 속성 * @property editable * @private * @type {Boolean} */ editable: true, /** * @description Column vertical merge 속성 * @config verticalMerge * @type {Boolean} * @default false */ /** * @description Column vertical merge 속성 * @property verticalMerge * @private * @type {Boolean} */ verticalMerge: false, /** * @description Column editor 속성 * @property editor * @private * @type {Object} */ editor: null, /** * @description Column style 속성 * @config cellStyle * @type {String} * @default null */ /** * @description Column style 속성 * @property cellStyle * @private * @type {String} */ cellStyle: null, /** * @description Column 의 디자인이나 값을 변경할 수 있는 function ** var col1Renderer = function(val, param, record, row, i) { * param.css.push('L-grid-cell-editable'); * return val; * } * --------------------------------------------------------- * { field: "col1", label: "Col1", renderer: col1Renderer }, ** @config renderer * @type {Function} * @default null */ /** * @description Column style 속성 * @property renderer * @private * @type {Function} */ renderer: null, /** * @description Column 의 row의 값이 바뀌면 무조건 render를 할지 여부 * @config renderRow * @type {boolean} * @default null */ /** * @description Column 의 row의 값이 바뀌면 무조건 render를 할지 여부 * @property renderRow * @private * @type {boolean} */ renderRow: false, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @return void */ init : function() { this.initEvents(); }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { }, /** * @description gridview의 event를 연결하는 메소드 * @method bindEvent * @protected * @param {DU.widget.LGridPanel} gridPanel gridPanel 객체 * @return {void} */ bindEvent : function(gridPanel) { }, /** * @description 객체의 Id값을 리턴하는 메소드 * @method getId * @return {String} */ getId: function() { return this.id; }, /** * @description 객체의 field값을 리턴하는 메소드 * @method getField * @return {String} */ getField: function() { return this.field; }, /** * @description 객체의 column model값을 리턴하는 메소드 * @method getColumnModel * @return {DU.widget.LColumnModel} */ getColumnModel: function() { return this.columnModel; }, /** * @description 객체의 column model값을 셋팅하는 메소드 * @method setColumnModel * @private * @param {DU.widget.LColumnModel} columnModel column model 객체 * @return {void} */ setColumnModel: function(columnModel) { this.columnModel = columnModel; }, /** * @description 객체의 lable값을 셋팅하는 메소드 * @method getLabel * @return {String} */ getLabel: function() { return this.label; }, /** * @description 객체의 column lable값을 셋팅하는 메소드 * @method setLabel * @param {String} lable column lable값 * @return {void} */ setLabel: function(label) { this.label = label; this.fireEvent('label', {target:this, label:label}); }, /** * @description 객체의 width값을 리턴하는 메소드 * @method getWidth * @return {Int} */ getWidth: function() { return this.width; }, /** * @description 객체의 column width값을 셋팅하는 메소드 * @method setWidth * @param {Int} lable width lable값 * @return {void} */ setWidth: function(width) { if (this.isResizable() && !this.isFixed()) { var oldWidth = this.width; this.width = width; if (this.columnModel !== null) { this.columnModel.totalWidth = null; if (this.columnModel.gridView !== null && this.columnModel.gridView.enableColumnResize) { this.fireEvent("columnresize", { target: this, oldWidth: oldWidth, newWidth: width }); } } } }, /** * @description 객체의 minWidth값을 셋팅하는 메소드 * @method getMinWidth * @return {Int} */ getMinWidth: function() { return this.minWidth; }, /** * @description 객체의 column minWidth값을 셋팅하는 메소드 * @method setMinWidth * @param {Int} lable minWidth lable값 * @return {void} */ setMinWidth: function(minWidth) { this.minWidth = minWidth; }, /** * @description 객체의 width값을 셋팅하는 메소드 * @method getMaxAutoWidth * @return {Int} */ getMaxAutoWidth: function() { return this.maxAutoWidth; }, /** * @description 객체의 column maxAutoWidth값을 셋팅하는 메소드 * @method setMaxAutoWidth * @param {Int} lable maxAutoWidth lable값 * @return {void} */ setMaxAutoWidth: function(maxAutoWidth) { this.maxAutoWidth = maxAutoWidth; }, /** * @description 객체의 hidden값을 리턴하는 메소드 * @method isHidden * @return {Boolean} */ isHidden: function() { return this.hidden; }, /** * @description 객체의 column hidden 값을 셋팅하는 메소드 * @method setHidden * @param {Boolean} hidden hidden값 * @return {void} */ setHidden: function(hidden) { this.hidden = hidden; this.columnModel.totalWidth = null; this.fireEvent('hidden', {target:this, hidden:hidden}); }, /** * @description 객체의 selected값을 리턴하는 메소드 * @method isSelected * @return {Boolean} */ isSelected: function() { return this.selected; }, /** * @description 객체의 column selected 값을 셋팅하는 메소드 * @method setSelected * @param {Boolean} selected selected 값 * @return {void} */ setSelected: function(selected) { this.selected = selected; }, /** * @description 객체의 resizable값을 리턴하는 메소드 * @method isResizable * @return {Boolean} */ isResizable: function() { return this.resizable; }, /** * @description 객체의 column resizable 값을 셋팅하는 메소드 * @method setResizable * @param {Boolean} resizable resizable 값 * @return {void} */ setResizable: function(resizable) { this.resizable = resizable; }, /** * @description 객체의 fixed값을 리턴하는 메소드 * @method isFixed * @return {Boolean} */ isFixed: function() { return this.fixed; }, /** * @description 객체의 column fixed 값을 셋팅하는 메소드 * @method setFixed * @param {Boolean} fixed fixed 값 * @return {void} */ setFixed: function(fixed) { this.fixed = fixed; }, /** * @description 객체의 sortable값을 리턴하는 메소드 * @method isSortable * @return {Boolean} */ isSortable: function() { return this.sortable; }, /** * @description 객체의 column sortable 값을 셋팅하는 메소드 * @method setSortable * @param {Boolean} sortable sortable 값 * @return {void} */ setSortable: function(sortable) { this.fireEvent('sortable', {target:this, sortable:sortable}); this.sortable = sortable; }, /** * @description 객체의 editable값을 리턴하는 메소드 * @method isEditable * @return {Boolean} */ isEditable: function() { return this.editable; }, /** * @description 객체의 column editable 값을 셋팅하는 메소드 * @method setEditable * @param {Boolean} editable editable 값 * @return {void} */ setEditable : function(editable){ this.editable = editable; }, /** * @description 객체의 editor값을 리턴하는 메소드 * @method getEditor * @return {Object} */ getEditor: function() { return this.editor; }, /** * @description 객체의 column editor 값을 셋팅하는 메소드 * @method setEditor * @param {Object} editor editor 값 * @return {void} */ setEditor: function(editor) { this.editor = editor; }, /** * @description 객체의 draggable값을 리턴하는 메소드 * @method isDraggable * @return {Boolean} */ isDraggable: function() { return this.draggable; }, /** * @description 객체의 column draggable 값을 셋팅하는 메소드 * @method setDraggable * @param {Boolean} draggable draggable 값 * @return {void} */ setDraggable : function(draggable){ this.draggable = draggable; }, /** * @description 객체의 toString * @method toString * @public * @return {String} */ toString : function() { return 'DU.widget.LColumn ' + this.id; } }); /** * @description LColumnModel * @namespace DU.widget * @class LColumnModel * @constructor * @param {Object} oConfigs 생성자 config 객체 */ DU.widget.LColumnModel = function(oConfigs) { var config = oConfigs || {}; DU.applyObject(this, config, true); this.init(config); /** * @description columnmove 되면 호출되는 이벤트 * @event columnmove * @param {Object} target this * @param {Int} oldIndex * @param {Int} newIndex */ this.createEvent("columnmove"); }; DU.extend(DU.widget.LColumnModel, DU.util.LEventProvider, { /** * @description LColumn default width 속성 * @config defaultWidth * @type {Int} * @default 100 */ /** * @description LColumn default width 속성 * @property defaultWidth * @private * @type {Int} */ defaultWidth: 100, /** * @description LColumn total width 속성 * @config totalWidth * @type {Int} * @default null */ /** * @description LColumn total width 속성 * @property totalWidth * @private * @type {Int} */ totalWidth: null, /** * @description LColumn default sortable 속성 * @config defaultSortable * @type {Boolean} * @default false */ /** * @description LColumn default sortable 속성 * @property defaultSortable * @private * @type {Boolean} */ defaultSortable: false, /** * @description Column group vertical merge 속성으로 해당 컬럼의 앞의 값과 동일한지 비교한다. * @config verticalGroupMerge * @type {Boolean} * @default false */ /** * @description Column group vertical merge 속성으로 해당 컬럼의 앞의 값과 동일한지 비교한다. * @property verticalGroupMerge * @private * @type {Boolean} */ verticalGroupMerge: false, /** * @description LColumn List 배열 속성 * @property columnList * @private * @type {Array} */ columnList: null, /** * @description LColumn Map 속성 * @property columnMap * @private * @type {Object} */ columnMap: null, /** * @description grid view 객체 속성 * @property gridPanel * @private * @type {DU.widget.LGridPanel} */ gridPanel : null, /** * @description multiheader 구성정보 html td의 id에는 column의 index를 넣으면 되고, 단순 출력용 column은 id를 넣지 않으면 된다. * html에는 colspan, rowspan정보와 출력용 label정보만 확인해서 처리한다. * @property multiheaderHtml * @private * @type {String} */ multiheaderHtml : null, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @param {Object} oConfig 환경정보 객체 * @return void */ init: function(config) { this.columnList = []; this.columnMap = {}; for (var i = 0; i < config.columns.length; i++) { var column = null; if(config.columns[i] instanceof DU.widget.LColumn) column = config.columns[i]; else column = new DU.widget.LColumn(config.columns[i]); if (column.type == 'number' && column.defaultValue == null) column.defaultValue = 0; if(column.renderer && DU.widget.LColumnModel.rendererMapper[column.renderer]) column.renderer = DU.widget.LColumnModel.rendererMapper[column.renderer]; column.setColumnModel(this); if (!column.sortable) column.sortable = this.defaultSortable; if (!column.width) column.width = this.defaultWidth; this.columnList.push(column); this.columnMap[column.getId()] = column; } }, /** * @description LColumn의 이벤트를 연결하는 메소드 * @method bindEvent * @protected * @param {DU.widget.LGridPanel} gridPanel gridPanel 객체 * @return void */ bindEvent : function(gridPanel) { this.gridPanel = gridPanel; this.gridView = gridPanel.getView(); for (var i = 0; i < this.getColumnCount(); i++) { var column = this.getColumnAt(i); if(column.bindEvent) column.bindEvent(gridPanel); } }, /** * @description id에 해당되는 LColumn을 리턴하는 메소드 * @method getColumnById * @param {String} id column의 id값 * @return {DU.widget.LColumn} */ getColumnById: function(id) { return this.columnMap[id]; }, /** * @description idx 위치에 해당되는 LColumn을 리턴하는 메소드 * @method getColumnAt * @param {Int} idx 위치값 * @param {Boolean} isVisibleOnly [optional] 보이는 컬럼만 선택 여부 * @return {DU.widget.LColumn} */ getColumnAt: function(idx, isVisibleOnly) { if (isVisibleOnly === true) { var column = null; var curIdx = -1; var totalCount = this.getColumnCount(false); for (var i = 0; idx < totalCount && i < totalCount; i++) { column = this.columnList[i]; if (!column.isHidden()) curIdx++; if (curIdx == idx) return column; } return null; } else { return this.columnList[idx]; } }, /** * @description idx에 해당되는 LColumn이 hidden인지를 리턴하는 메소드 * @method isHidden * @param {Int} idx 위치값 * @return {Boolean} */ isHidden : function(idx){ return this.getColumnAt(idx).isHidden(); }, /** * @description id에 해당되는 LColumn의 index를 리턴하는 메소드 * @method getIndexById * @param {String} id id명 * @return {Int} */ getIndexById: function(id) { return this.getIndex(this.getColumnById(id)); }, /** * @description LColumn의 index를 리턴하는 메소드 * @method getIndex * @param {DU.widget.LColumn} column * @return {Int} */ getIndex: function(column){ for (var i = 0; i < this.getColumnCount(); i++) { if (this.getColumnAt(i) === column) return i; } return -1; }, /** * @description field에 해당되는 LColumn을 리턴하는 메소드 * @method getColumnByField * @param {String} field field명 * @return {DU.widget.LColumn} */ getColumnByField: function(field) { for (var i = 0; i < this.getColumnCount(); i++) { var column = this.getColumnAt(i); if (column.field == field) { return column; } } return null; }, /** * @description oldIndex의 LColumn을 newIndex위치로 이동하는 메소드 * @method moveColumn * @param {Int} oldIndex 이동할 LColumn의 위치 * @param {Int} newIndex 이동될 LColumn의 위치 * @return {void} */ moveColumn: function(oldIndex,newIndex) { this.columnList = DU.util.LArray.moveItem(this.columnList,oldIndex,newIndex); this.fireEvent("columnmove",{target:this,oldIndex:oldIndex,newIndex:newIndex}); }, /** * @description 전체 column의 width를 리턴하는 메소드 * @method getTotalWidth * @param {Boolean} isVisibleOnly [optional] 보이는 컬럼만 선택 여부 * @return {Int} */ getTotalWidth: function(isVisibleOnly) { if (!this.totalWidth) { this.totalWidth = 0; for (var i = 0; i < this.getColumnCount(isVisibleOnly); i++) { this.totalWidth += this.getColumnAt(i, isVisibleOnly).getWidth(); } } return this.totalWidth; }, /** * @description 전체 LColumn의 갯수를 리턴하는 메소드 * @method getColumnCount * @param {Boolean} isVisibleOnly [optional] 보이는 컬럼만 선택 여부 * @return {Int} */ getColumnCount: function(isVisibleOnly) { if (isVisibleOnly === true) { var count = 0; for (var i = 0; i < this.columnList.length; i++) { var column = this.getColumnAt(i, true); if (column == null) return count; count++; } return count; } else { return this.columnList.length; } }, /** * @description 객체의 toString * @method toString * @public * @return {String} */ toString : function() { return 'DU.widget.LColumnModel ' + this.id; }, /** * @description 개발자가 직접 구현한 editor 객체 * @method getEditorName * @return {Object} */ getEditorName : DU.emptyFn }); DU.widget.LColumnModel.rendererMapper = []; /** * @description LColumnResizer * @namespace DU.widget * @class LColumnResizer * @constructor * @private * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LColumnResizer = function(grid) { this.grid = grid; var id = this.grid.el.id + "columnResizerProxy"; DU.widget.LColumnResizer.superclass.constructor.call(this, this.grid.headerEl.dom.id, id, { dragElId:this.grid.resizeProxyEl.id, resizeFrame:false }); }; DU.extend(DU.widget.LColumnResizer, DU.dd.LDDProxy, { //selected header cell index cellIndex:null, startX:null, b4StartDrag : function(x,y){ //drag동안 header click안되게 등. this.grid.headerDisabled = true; var height = this.grid.el.getHeight(); //grid에 출력된 cell은 보이는 cell이다. var width = this.grid.columnModel.getColumnAt(this.cellIndex).getWidth(); var minWidth = (width - this.grid.getMinColumnWidth()); //drag 가능한 범위 minWidth = minWidth > 0 ? minWidth : 0; this.grid.resizeProxyEl.setHeight(height); this.resetConstraints(); this.setXConstraint(minWidth, 1000); this.setYConstraint(0, 0); this.minX = x - minWidth; this.maxX = x + 1000; this.startX = x; DU.dd.LDDProxy.prototype.b4StartDrag.call(this, x, y); }, handleMouseDown : function(e){ var headerCellDom = this.grid.findHeaderCell(e.target); if(headerCellDom){ var headerCellEl = DU.get(headerCellDom); var xy = headerCellEl.getXY(), x = xy[0], y = xy[1]; var exy = DU.util.LEvent.getXY(e); var ex = exy[0]; var w = headerCellEl.getWidth(), adjust = false; if((ex - x) <= this.grid.resizeHandleWidth){ adjust = -1; }else if((x+w) - ex <= this.grid.resizeHandleWidth){ adjust = 0; } if(adjust !== false){ var ci = this.grid.getCellIndex(headerCellEl.dom);//headerCellEl.dom.cellIndex; this.cellIndex = ci+adjust; //-1한것이 hidden이면 다음 컬럼 if (adjust == -1) { while (this.cellIndex >= 0) { if (this.grid.columnModel.isHidden(this.cellIndex)) { this.cellIndex--; } else { break; } } } var column = this.grid.columnModel.getColumnAt(this.cellIndex); //this.split = headerCellEl.dom; if(column && column.isResizable() && !column.isFixed()){ DU.widget.LColumnResizer.superclass.handleMouseDown.apply(this, arguments); } }else if(this.grid.columnDD){ //범위가 아니면 columnDD호출 this.grid.columnDD.callHandleMouseDown(e); } } }, endDrag : function(e){ var pX = DU.util.LEvent.getPageX(e); var endX = (this.minX >= pX) ? this.minX : pX; var diff = endX - this.startX; var column = this.grid.columnModel.getColumnAt(this.cellIndex); column.setWidth(column.getWidth() + diff); this.grid.headerDisabled = false; }, autoOffset : function(){ this.setDelta(0,0); } }); (function() { var Dom = DU.util.LDom; /** * @description LColumnDD column을 drag drop으로 이동을 위한 class * @module widget_grid * @title LColumnDD * @requires DU.dd.LDDProxy */ DU.namespace("DU.widget"); /** * @description LColumnDD column을 drag drop으로 이동을 위한 class * @namespace DU.widget * @class LColumnDD * @extends DU.dd.LDDProxy * @constructor LColumnDD * @param {DU.widget.LGridView} grid column dd를 적용할 gridview */ DU.widget.LColumnDD = function(grid) { this.grid = grid; this.cellIndex = null; this.newCellIndex = null; this.headerCellEl = null; var id = this.grid.el.id + "columnDDProxy"; DU.widget.LColumnDD.superclass.constructor.call(this, this.grid.headerEl.dom.id, id, { dragElId:this.grid.ddProxyEl.id, resizeFrame:false }); }; DU.extend(DU.widget.LColumnDD, DU.dd.LDDProxy, { /** * @description drag start전에 실행되는 method * @private * @method b4StartDrag * @param {int} x drag 시작 좌표 * @param {int} y drag 시작 좌표 * @return {void} */ b4StartDrag : function(x,y){ //drag동안 header click안되게 등. this.grid.headerDisabled = true; var height = this.grid.el.getHeight(); //grid에 출력된 cell은 보이는 cell이다. var width = this.grid.columnModel.getColumnAt(this.cellIndex).getWidth(); var containerWidth = this.grid.el.getWidth(); var region = this.grid.el.getRegion(); this.grid.ddProxyEl.setHeight(height); this.grid.ddProxyEl.setWidth(width); this.grid.ddTargetEl.setHeight(height); var minWidth = region.left; var maxWidth = region.right; this.resetConstraints(); this.setXConstraint(minWidth, maxWidth); this.setYConstraint(0, this.grid.headerEl.getHeight()); //var xy = this.headerCellEl.getXY(); //this.setDelta(x-xy[0],y-xy[1]); DU.dd.LDDProxy.prototype.b4StartDrag.call(this, x, y); }, /** * @description click시 drag할 상황인지 판단하는 method * @private * @method clickValidator * @param {object} e event object * @return {void} */ clickValidator: function(e) { var headerCellDom = this.grid.findHeaderCell(e.target); if (headerCellDom) { this.headerCellEl = DU.get(headerCellDom); this.cellIndex = this.grid.getCellIndex(headerCellDom); this.newCellIndex = this.cellIndex; var column = this.grid.columnModel.getColumnAt(this.cellIndex); if (this.grid.enableColumnDD && column.isDraggable() && !column.isFixed()) { //A tag는 기본적으로 drag가능하므로 isValidHandleChild에서 검사하도록 되어있다. 통과되도록 뺀다. var target = DU.util.LEvent.getTarget(e);// this.isValidHandleChild(target) && return (this.id == this.handleElId || this.LDDM.handleWasClicked(target, this.id)); } } }, /** * @description drag시 실행되는 event handler * @private * @method onDrag * @param {object} e event object * @return {void} */ onDrag: function(e) { var headerCellDom = this.grid.findHeaderCell(e.target); if(headerCellDom) { var headerCellEl = DU.get(headerCellDom); var newCellIndex = this.grid.getCellIndex(headerCellEl.dom); var column = this.grid.columnModel.getColumnAt(newCellIndex); if (column.isDraggable() && !column.isFixed()) { //target위치 잡기 var xy = headerCellEl.getXY(); this.grid.ddTargetEl.setXY([xy[0], xy[1] - 5]);//-5는 target의 width this.grid.ddTargetEl.show(); //이동할 곳 표시선 표시 //이동할 곳이 this.cellIndex가 아니고 이전 또는 이후면서 //이전일 경우는 +상태, 이후일 경우는 -상태일 경우 var adjuust = ""; var ex = DU.util.LEvent.getPageX(e); var targetX = headerCellEl.getX(); var midX = targetX + (headerCellEl.getWidth() / 2); if (ex < midX) { this.grid.ddTargetEl.setX(targetX); adjust = "front"; } else { var targetWidth = headerCellEl.getWidth(); this.grid.ddTargetEl.setX(targetX + targetWidth); adjust = "back"; } var colCount = this.grid.columnModel.getColumnCount(); if (this.cellIndex > newCellIndex) { if (adjust == "back") { newCellIndex++; while (newCellIndex < colCount && this.cellIndex > newCellIndex) { if (this.grid.columnModel.isHidden(newCellIndex)) { newCellIndex++; } else { break; } } } this.newCellIndex = newCellIndex; } else if (this.cellIndex < newCellIndex) { if (adjust == "front") { newCellIndex--; while (newCellIndex >= 0 && this.cellIndex < newCellIndex) { if (this.grid.columnModel.isHidden(newCellIndex)) { newCellIndex--; } else { break; } } } this.newCellIndex = newCellIndex; } } } }, /** * @description drag시 종료시 실행되는 method * @private * @method endDrag * @return {void} */ endDrag: function() { this.grid.ddTargetEl.hide(); this.grid.columnModel.moveColumn(this.cellIndex, this.newCellIndex); this.newCellIndex = null; this.grid.headerDisabled = false; }, /** * @description autoOffset * @private * @method autoOffset * @return {void} */ autoOffset : function(){ this.setDelta(0,-5); }, /** * @description callHandleMouseDown * @private * @method callHandleMouseDown * @return {void} */ callHandleMouseDown : function(e){ DU.widget.LColumnDD.superclass.handleMouseDown.call(this, e); } }); })(); /** * @description LGridView * @module widget_grid * @title LGridView * @requires DU * */ DU.namespace("DU.widget"); (function() { /** * @description LGridView * @namespace DU.widget * @class LGridView * @extends DU.widget.LUIComponent * @constructor LGridView * @param {Object} oConfig The intial LGridView. */ DU.widget.LGridView = function(oConfig) { var config = oConfig || {}; DU.applyObject(this, config, true); config = DU.util.LDom.applyIfProperties(config, '$.ext.grid'); this.onBeforeLoadDelegate = DU.util.LFunction.createDelegate(this.onBeforeLoad, this); this.onRenderDataDelegate = DU.util.LFunction.createDelegate(this.onRenderData, this); this.onChangeRenderDataDelegate = DU.util.LFunction.createDelegate(this.onChangeRenderData, this); this.onAddDataDelegate = DU.util.LFunction.createDelegate(this.onAddData, this); this.onCellUpdateDataDelegate = DU.util.LFunction.createDelegate(this.onCellUpdateData, this); this.onRemoveDataDelegate = DU.util.LFunction.createDelegate(this.onRemoveData, this); this.onUndoDataDelegate = DU.util.LFunction.createDelegate(this.onUndoData, this); this.onCommitDataDelegate = DU.util.LFunction.createDelegate(this.onCommitData, this); this.onRowPosChangedDataDelegate = DU.util.LFunction.createDelegate(this.onRowPosChangedData, this); this.onClearAllSelectMarkDelegate = DU.util.LFunction.createDelegate(this.onClearAllSelectMark, this); this.bodyScrollDelegate = DU.util.LFunction.createDelegate(this.onBodyScroll,this); this.deferOnBlurDelegate = DU.util.LFunction.createDelegate(this.deferOnBlur, this); this.onColumnResizeDelegate = DU.util.LFunction.createDelegate(this.onColumnResize, this); this.onColumnMoveDelegate = DU.util.LFunction.createDelegate(this.onColumnMove, this); this.onInvalidDelegate = DU.util.LFunction.createDelegate(this.onInvalid, this); this.onValidDelegate = DU.util.LFunction.createDelegate(this.onValid, this); /** * @description renderBody 메소드가 호출되면 수행하는 이벤트 * @event renderBody */ this.renderBodyEvent = this.createEvent("renderBody"); /** * @description setSyncDataSet 메소드가 호출되면 수행하는 이벤트 * @event syncDataSet * @param {Object} target this객체 * @param {Boolean} isSync sync 여부 */ this.syncDataSetEvent = this.createEvent("syncDataSet"); /** * @description getRenderRow 메소드가 호출되면 수행하는 이벤트 * @event renderRow * @param {Object} css css객체 * @param {Int} row row값 * @param {DU.data.LRecord} record record 객체 * */ this.renderRowEvent = this.createEvent("renderRow"); /** * @description getRenderCell 메소드가 호출되면 수행하는 이벤트 * @event renderCell * @param {Object} css css객체 * @param {Int} row row값 * @param {Int} col col값 * @param {DU.data.LRecord} record record 객체 */ this.renderCellEvent = this.createEvent("renderCell"); /** * @description sortField 메소드가 호출되면 수행하는 이벤트 * @event sortFieldEvent * @param {Object} target this 객체 * @param {String} sortField sortField값 * @param {String} sortDir sortDir값 */ this.sortFieldEvent = this.createEvent("sortField"); DU.widget.LGridView.superclass.constructor.call(this, oConfig); }; var Dom = DU.util.LDom; var Ev = DU.util.LEvent; var GV = DU.widget.LGridView; DU.applyObject(DU.widget.LGridView, { /*************field member***********/ //*********CSS Class CLASS_GRIDVIEW : "L-grid", CLASS_GRIDVIEW_SCROLLER : "L-grid-scroller", CLASS_GRIDVIEW_FOCUS : "L-grid-focus", CLASS_GRIDVIEW_RESIZE_PROXY : "L-grid-resize-proxy", CLASS_GRIDVIEW_DD_PROXY : "L-grid-dd-proxy", CLASS_GRIDVIEW_DD_TARGET : "L-grid-dd-target", CLASS_GRIDVIEW_COL : "L-grid-col", CLASS_GRIDVIEW_HEADER : "L-grid-header", CLASS_GRIDVIEW_HEADER_OFFSET : "L-grid-header-offset", CLASS_GRIDVIEW_HEADER_ROW : "L-grid-header-row", CLASS_GRIDVIEW_HEADER_CELL : "L-grid-header-cell", CLASS_GRIDVIEW_HEADER_INNER : "L-grid-header-inner", CLASS_GRIDVIEW_HEADER_BTN : "L-grid-header-btn", CLASS_GRIDVIEW_HEADER_OVER : "L-grid-header-over", CLASS_GRIDVIEW_BODY : "L-grid-body", CLASS_GRIDVIEW_BODY_EMPTY : "L-grid-body-empty", CLASS_GRIDVIEW_ROW : "L-grid-row", CLASS_GRIDVIEW_ROW_FIRST : "L-grid-row-first", CLASS_GRIDVIEW_ROW_LAST : "L-grid-row-last", CLASS_GRIDVIEW_ROW_ODD : "L-grid-row-odd", CLASS_GRIDVIEW_ROW_EVEN : "L-grid-row-even", CLASS_GRIDVIEW_ROW_OVER : "L-grid-row-over", CLASS_GRIDVIEW_CELL : "L-grid-cell", CLASS_GRIDVIEW_CELL_FIRST : "L-grid-cell-first", CLASS_GRIDVIEW_CELL_LAST : "L-grid-cell-last", CLASS_GRIDVIEW_CELL_INNER : "L-grid-cell-inner", CLASS_GRIDVIEW_SORT_ASC : "L-grid-sort-asc", CLASS_GRIDVIEW_SORT_DESC : "L-grid-sort-desc", CLASS_GRIDVIEW_ROW_SELECTED : "L-grid-row-selected", CLASS_GRIDVIEW_ROW_SELECT_MARK : "L-grid-row-select-mark", CLASS_GRIDVIEW_CELL_SELECTED : "L-grid-cell-selected" }); DU.extend(DU.widget.LGridView, DU.widget.LUIComponent, { ///////////////////////////////////////////////////////////////////////////// // // Private member variables // ///////////////////////////////////////////////////////////////////////////// /** * @description object type * @property otype * @type {String} * @private */ otype: 'DU.widget.LGridView', /** * @description LColumnModel 객체 * @config columnModel * @type {DU.widget.LColumnModel} * @default null */ /** * @description LColumnModel 객체 * @property columnModel * @type {DU.widget.LColumnModel} * @private */ columnModel: null, /** * @description template 객체 * @property templates * @type {DU.LTemplate} * @private */ templates: null, /** * @description DataSet 객체 * @config columnModel * @type {DU.data.LDataSet} * @default null */ /** * @description DataSet 객체 * @property dataSet * @type {DU.data.LDataSet} * @private */ dataSet: null, /** * @description DataSet과 sync 여부 객체 * @config syncDataSet * @type {Boolean} * @default true */ /** * @description DataSet과 sync 여부 객체 * @property syncDataSet * @type {Boolean} * @private */ syncDataSet: true, /** * @description load message * @config loadingMessage * @type {String} * @default 'Loading...' */ /** * @description load message * @property loadingMessage * @type {String} * @private */ loadingMessage : "Loading...", /** * @description empty data message * @config emptyDataMessageCode * @type {String} * @default 'No Data' */ /** * @description empty data message * @property emptyDataMessageCode * @type {String} * @private */ emptyDataMessageCode : null, /** * @description scrollBar의 width값 * @config scrollBarWidth * @type {Int} * @default 19 */ /** * @description scrollBar의 width값 * @property scrollBarWidth * @type {Int} * @private */ scrollBarWidth:19, /** * @description scrollBar의 가로 출력 여부 * @config scrollingX * @type {Boolean} * @default true */ /** * @description scrollBar의 가로 출력 여부 * @property scrollingX * @type {Boolean} * @private */ scrollingX: true, /** * @description scrollBar의 세로 출력 여부 * @config scrollingY * @type {Boolean} * @default true */ /** * @description scrollBar의 세로 출력 여부 * @property scrollingY * @type {Boolean} * @private */ scrollingY: true, /** * @description boder의 width 값 * 나머지 모두는 cell div에 border를 할당했지만, right border는 td에 할당 => 내부 div에 할당시 padding에 의해 우측 border가 td범위 넘어서서 출력되지 않음 * @config borderWidth * @type {Int} * @default 1 */ /** * @description boder의 width 값 * 나머지 모두는 cell div에 border를 할당했지만, right border는 td에 할당 => 내부 div에 할당시 padding에 의해 우측 border가 td범위 넘어서서 출력되지 않음 * @property borderWidth * @type {Int} * @private */ borderWidth: 1, /** * @description 그리드가 render시 row와 cell render event를 skip할지 여부(성능과 연관되므로 대량건 처리시는 false로 처리) * @config skipRowCellEvent * @type {Boolean} * @default true */ /** * @description 그리드가 render시 row와 cell render event를 skip할지 여부(성능과 연관되므로 대량건 처리시는 false로 처리) * @property skipRowCellEvent * @type {Boolean} * @private */ skipRowCellEvent: true, /** * @description scroller LElement object * @property scrollerEl * @type {DU.LElement} * @private */ scrollerEl:null, /** * @description header LElement object * @property headerEl * @type {DU.LElement} * @private */ headerEl:null, /** * @description focus LElement object * @property focusEl * @type {DU.LElement} * @private */ focusEl:null, /** * @description header offset LElement object * @property headerOffsetEl * @type {DU.LElement} * @private */ headerOffsetEl:null, /** * @description header offset LElement object * @property bodyEl * @type {DU.LElement} * @private */ bodyEl:null, /** * @description resize proxy LElement object * @property resizeProxyEl * @type {DU.LElement} * @private */ resizeProxyEl:null, /** * @description resize handle width * @config resizeHandleWidth * @type {int} * @default 5 */ /** * @description resize handle width * @property resizeHandleWidth * @type {int} * @private */ resizeHandleWidth: 5, /** * @description minimum column width * @config minColumnWidth * @type {int} * @default 10 */ /** * @description minimum column width * @property minColumnWidth * @type {int} * @private */ minColumnWidth: 10, /** * @description cell selector class name * @property cellSelector * @type {string} * @private */ cellSelector:"td." + GV.CLASS_GRIDVIEW_CELL, /** * @description cell selector search depth * @property cellSelectorDepth * @type {int} * @private */ cellSelectorDepth:10, /** * @description row selector class name * @property rowSelector * @type {string} * @private */ rowSelector:"div." + GV.CLASS_GRIDVIEW_ROW, /** * @description row selector search depth * @property rowSelectorDepth * @type {int} * @private */ rowSelectorDepth:10, /** * @description if header is disabled * @property headerDisabled * @type {boolean} * @private */ headerDisabled:false, /** * @description can resize column * @property enableColumnResize * @type {boolean} * @private */ enableColumnResize : true, /** * @description can drag and drop column * @property enableColumnDD * @type {boolean} * @private */ enableColumnDD : true, /** * @description header tool 사용 여부 * @property enableHeaderTools * @type {boolean} * @private */ enableHeaderTools : false, /** * @description mouse over시 활성화된 header cell저장 * @property activeHeaderEl * @type {DU.LElement} * @private */ activeHeaderEl : null, /** * @description colum resizer object * @property columnResizer * @type {DU.widget.LColumnResizer} * @private */ columnResizer : null, /** * @description regular expression for finding cell * @property cellRe * @type {string} * @private */ cellRe : new RegExp("L-grid-cell-([^\\s]+)", ""), /** * @description regular expression for finding row * @property rowRe * @type {string} * @private */ rowRe : new RegExp("L-grid-row-r([^\\s]+)", ""), /** * @description drag and drop proxy element object * @property ddProxyEl * @type {DU.LElement} * @private */ ddProxyEl : null, /** * @description drag and drop target element object * @property ddTargetEl * @type {DU.LElement} * @private */ ddTargetEl : null, /** * @description grid panel object * @property gridPanel * @type {DU.widget.LGridPanel} * @private */ gridPanel : null, /** * @description sort field name * @property sortFieldName * @type {string} * @private */ sortField : null, /** * @description sort direction asc, desc * @property sortDirection * @type {string} * @private */ sortDir : null, /** * @description remote sort 여부 * @property isRemoteSort * @type {Boolean} * @private */ isRemoteSort : false, /** * @description multi header의 경우 ie6/7의 버그를 해결하기 위해 보정값을 둠. * @property colWidthAdjustValues * @type {Array} * @private */ colWidthAdjustValues : new Array(), ///////////////////////////////////////////////////////////////////////////// // // Public member variables // ///////////////////////////////////////////////////////////////////////////// /** * @description Dom객체 생성 및 초기화하는 메소드 * @method initComponent * @protected * @param {String|Object} el 객체의 아이디나 객체 * @param {Object} oConfig 환경정보 객체 * @return void */ initComponent: function(oConfig) { //Y축 scroll이 없으면 scrollbar width는 필요없다. this.scrollbarWidth = (this.scrollingY == true)? this.scrollBarWidth : 0; }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents: function() { DU.widget.LGridView.superclass.initEvents.call(this); this._setSyncDataSet('syncDataSet', [this.syncDataSet]); // renderBody 처리후 메시지 출력 this.renderBodyEvent.unOnAll(); this.renderEvent.on(this.onRender, this); // Add the document level click listener // blur에 관련해서 초기화 할 필요가 있을 경우 구현 필요 //DU.util.LEvent.addListener(document, "click", this._onDocumentClick, this); }, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig: function() { DU.widget.LGridView.superclass.initDefaultConfig.call(this); this.cfg.addProperty("syncDataSet", { handler: this._setSyncDataSet, value: this.syncDataSet, validator: DU.isBoolean }); }, /** * @description panel에서 필요한 정보 가져오기 * @method setPanel * @private * @param {DU.widget.LGridPanel} gridPanel * @return void */ setPanel : function(gridPanel) { gridPanel.on('headerclick', this.onHeaderClick, this, true); gridPanel.on("widthResize",this.onWidthResize,this,true); this.gridPanel = gridPanel; //필요한 속성 copy this.columnModel = this.gridPanel.columnModel; this.selectionModel = this.gridPanel.selectionModel; }, /** * @description dataset return * @method getDataSet * @public * @return {DU.data.LDataSet} */ getDataSet : function() { return this.dataSet; }, /** * @description rendering * @method doRender * @protected * @return {void} */ doRender: function(appendToNode) { this.createTemplate(); this.renderMaster(this.getRenderHeader()); this.headerEl = DU.get(this.el.dom.childNodes[0]); this.headerToolEl = this.headerEl.select('.L-grid-header-tool').getAt(0); this.headerOffsetEl = DU.get(this.el.dom.childNodes[0].childNodes[0]); this.scrollerEl = DU.get(this.el.dom.childNodes[1]); this.bodyEl = DU.get(this.el.dom.childNodes[1].childNodes[0]); this.focusEl = DU.get(this.scrollerEl.dom.childNodes[1]); this.resizeProxyEl = DU.get(this.el.dom.childNodes[2]); this.ddProxyEl = DU.get(this.el.dom.childNodes[3]); this.ddTargetEl = DU.get(this.el.dom.childNodes[4]); this.loadMessageEl = DU.get(this.el.dom.childNodes[5]); this.headerEl.on("mouseover", this.onHeaderMouseOver, this, true); this.headerEl.on("mousemove", this.onHeaderMouseMove, this, true); this.headerEl.on("mouseout", this.onHeaderMouseOut, this, true); this.bodyEl.on("mouseover", this.onBodyMouseOver, this, true); this.bodyEl.on("mouseout", this.onBodyMouseOut, this, true); DU.util.LEvent.addListener(this.bodyEl.dom, 'selectstart', function(){ return false}, this, true); DU.util.LEvent.removeListener(this.scrollerEl.dom,"scroll",this.bodyScrollDelegate); DU.util.LEvent.addListener(this.scrollerEl.dom,"scroll",this.bodyScrollDelegate); DU.util.LEvent.addListener(this.el.dom, "mousedown", this.onCheckFocus, this, true); if(this.enableHeaderTools) { this.headerToolEl.on('click', function(e){ if(this.headerToolEl.dom == e.target) { if(!this.headerContextMenu) { this.headerContextMenu = new DU.widget.LHeaderContextMenu({gridView:this}); this.headerContextMenu.render(this.el.dom); } this.headerContextMenu.show(); this.headerContextMenu.setLeft(this.headerToolEl.getLeft() + this.headerToolEl.getWidth(true)); } }, this, true); this.on('blur', function(){ if(this.headerContextMenu) this.headerContextMenu.hide(); }, this, true); } //data를 rendering하기 전에 sizing을 해야지만 window scroll등이 발생하지 않음. this.updateSizes(); this.doRenderData(); //column에 columnresize event 걸기 if (this.enableColumnResize) { for (var i = 0; i < this.columnModel.getColumnCount(); i++) { this.columnModel.getColumnAt(i).unOn("columnresize", this.onColumnResizeDelegate); this.columnModel.getColumnAt(i).on("columnresize", this.onColumnResizeDelegate); } } if(this.enableColumnDD){ this.columnModel.unOn("columnmove",this.onColumnMoveDelegate); this.columnModel.on("columnmove",this.onColumnMoveDelegate); } }, /** * @description 구조 rendering * @method renderMaster * @param {String} headerHtml header rendering한 html * @protected * @return {void} */ renderMaster: function(headerHtml) { var contentWidth = this.columnModel.getTotalWidth(true); var offsetWidth = contentWidth + this.scrollBarWidth; var html = this.templates.master.apply({ header: headerHtml, ostyle: "width:" + offsetWidth + "px", bstyle: "width:" + contentWidth + "px" }); this.el.html(html); this.el.addClass(GV.CLASS_GRIDVIEW); this.el.addClass("L-fixed"); }, /** * @description column resize의 경우 multiheader의 경우 다시 그려야만 width가 정상 적용된다. * @method renderMultiHeader * @param {String} headerHtml header rendering한 html * @protected * @return {void} */ renderMultiHeader : function(){ this.headerOffsetEl.html(this.getRenderMultiheader()); }, /** * @description body content rendering * @method renderBody * @param {String} bodyHtml body rendering한 html * @protected * @return {void} */ renderBody: function(bodyHtml) { this.bodyEl.dom.innerHTML = ""; this.bodyEl.dom.innerHTML = bodyHtml; this.doEmptyDataMessage(); this.renderBodyEvent.fire(); }, /** * @description body content rendering * @method doRenderData * @private * @return {void} */ doRenderData: function() { this.renderBody(this.getRenderBody()); }, /** * @description dataset의 변경에 따른 body content rendering * @method setSyncDataSet * @param {boolean} isSync * @private * @return {void} */ setSyncDataSet : function(isSync) { this.cfg.setProperty("syncDataSet", isSync); this.doRenderData(); }, /** * @description dataset의 변경에 따른 body content rendering되었는지 여부 * @method isSyncDataSet * @private * @return {boolean} */ isSyncDataSet : function() { return this.syncDataSet; }, /** * @description grid의 최소 column width return * @method getMinColumnWidth * @param {int} idx column index * @private * @return {int} */ getMinColumnWidth : function(idx){ if (idx) { return this.cm.getColumnAt(idx).getMinWidth() || this.minColumnWidth; } else { return this.minColumnWidth; } }, /** * @description grid의 header cell return * @method getHeaderCellEl * @param {int} idx column index * @public * @return {DU.LElement} */ getHeaderCellEl : function(idx){ //지정한 index의 header td return, multi일 경우는 가장 마지막 행이 된다. Column resize용. var tbl = this.headerEl.select("table").getAt(0).dom; var tr = tbl.rows[tbl.rows.length-1]; var cell = tr.cells[idx]; return cell ? DU.get(cell) : null; }, /** * @description grid의 scroll영역의 height 설정하기, 안보이는 상태에서는 height할당되어있어도 getHeight는 0이다. * @method updateSizes * @protected * @return {void} */ updateSizes:function(){ var panelBodyEl = DU.get(this.gridPanel.body); var height = panelBodyEl.getHeight(); if (this.gridPanelBodyHeight !== height) { var headerHeight = this.headerEl.getHeight(); var bodyHeight = height - headerHeight; //header height에 border height가 빠져있으면 bodyHeight에 +1해줘야함.=> borderBox문제, 해결않되었음. this.scrollerEl.setStyle("height", bodyHeight + "px"); this.gridPanelBodyHeight = height; } var width = panelBodyEl.getWidth(); if (this.gridPanelBodyWidth !== width) { this.headerEl.setStyle("width", width + "px"); this.scrollerEl.setStyle("width", width + "px"); this.gridPanelBodyWidth = width; } }, /** * @description grid의 height 재설정하기 * @method _setHeight * @protected * @return {void} */ _setHeight : function(type, args, obj){ DU.widget.LGridView.superclass._setHeight.call(this,type, args, obj); this.updateSizes(); }, /** * @description grid의 width 재설정하기 * @method _setWidth * @protected * @return {void} */ _setWidth : function(type, args, obj){ DU.widget.LGridView.superclass._setWidth.call(this,type, args, obj); this.updateSizes(); }, /** * @description auto width의 경우 panel width가 조정될 경우 재계산 * @method onWidthResize * @protected * @return {void} */ onWidthResize : function(e){ this.updateSizes(); }, /** * @description column resize에 따른 column 넓이 설정 * @method updateColumnWidth * @protected * @param {int} cellIndex * @param {int} width * @return {void} */ updateColumnWidth : function(cellIndex,oldWidth,newWidth){ var diffWidth = newWidth - oldWidth; //column width가 변경될 경우 전체 cell에 적용, cell merge는 배제. var contentWidth = this.columnModel.getTotalWidth(true); var offsetWidth = contentWidth + this.scrollBarWidth; //width 변경해야할 것 : header offset, header table & cell width, grid-body, body table & cell width this.updateHeaderWidth(cellIndex,diffWidth,offsetWidth,contentWidth, newWidth); this.bodyEl.setWidth(contentWidth); //empty message div도 조정 var isEmpty = this.updateEmptyWidth(contentWidth); if (!isEmpty) { //성능을 위해 dom 직접 사용 var gridRows = this.bodyEl.dom.childNodes; var row = null; for (var i = 0; i < gridRows.length; i++) { row = gridRows[i]; if (row.firstChild && row.firstChild.tagName && row.firstChild.tagName.toLowerCase() == "table") { row.firstChild.style.width = contentWidth + "px"; row.firstChild.rows[0].childNodes[cellIndex].style.width = this.adjustColumnWidth(newWidth) + "px"; } row.style.width = contentWidth + "px"; } } }, /** * @description column resize에 따른 header column 넓이 설정 * @method updateHeaderWidth * @protected * @param {int} cellIndex * @param {int} diffWidth * @param {int} offsetWidth * @param {int} contentWidth * @param {int} newWidth * @return {void} */ updateHeaderWidth : function(cellIndex,diffWidth,offsetWidth,contentWidth, newWidth){ var tblEl = this.headerOffsetEl.select("table").getAt(0); var colListEl = this.headerOffsetEl.select("colgroup col"); if(this.columnModel.multiheaderHtml){ //multi header일 경우 hidden일 경우 colgroup에서 hidden인 col이 생성되지 않는다. index를 조정해야 한다. var columnCount = this.columnModel.getColumnCount(); var minus = 0; for(var i=0;i
Sample: 보기
* @config enterToMove * @type {Boolean} * @default true */ /** * @description editor상태에서 enter를 치면 다음 editor cell로 이동할지 여부 속성 * @property enterToMove * @private * @type {Boolean} */ enterToMove : true, /** * @description cell 선택 정보 * @property selection * @private * @type {Object} */ selection: {}, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @param {Object} oConfig 환경정보 객체 * @return void */ init : function(gridPanel) { this.oldRow = gridPanel.getView().getDataSet().getRow(); DU.widget.LCellSelectionModel.superclass.init.call(this, gridPanel); }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents : function() { DU.widget.LCellSelectionModel.superclass.initEvents.call(this); this.gridPanel.on('rowclick', this.onRowClick, this, true); this.gridPanel.on('cellclick', this.onCellClick, this, true); var dataSet = this.view.getDataSet(); var removeSelectionAll = function(e) { this.selection = {}; }; dataSet.on('load', removeSelectionAll, this, true); dataSet.on('dataChanged', removeSelectionAll, this, true); dataSet.on('add', removeSelectionAll, this, true); dataSet.on('remove', removeSelectionAll, this, true); dataSet.on('undo', removeSelectionAll, this, true); dataSet.on('commit', removeSelectionAll, this, true); this.gridPanel.columnModel.on('columnMove', removeSelectionAll, this, true); var view = this.gridPanel.getView(); view.on('renderCell', function(e){ if(this.hasSelectedCell(e.row, e.col)) e.css.push(GV.CLASS_GRIDVIEW_CELL_SELECTED); }, this, true); }, /** * @description row click 이벤트가 발생하면 호출되는 메소드 * @method onRowClick * @protected * @param {Object} e Event 객체 * @return void */ onRowClick : function(e) { }, /** * @description cell click 이벤트가 발생하면 호출되는 메소드 * @method onCellClick * @protected * @param {Object} e Event 객체 * @return void */ onCellClick : function(e) { //this.selectCell(e.row, e.col); }, /** * @description DataSet의 add 이벤트 발생시 호출되는 메소드 * @method onAdd * @private * @param {Object} e Event 객체 * @return void */ onAdd : function(e) { DU.widget.LCellSelectionModel.superclass.onAdd.call(this, e); var sm = this.sm; var row = e.row; var col = sm.currentCell; sm.doDeSelectCell(sm.oldRow, sm.oldCell); if(!this.delayTask) { this.delayTask = new DU.util.LDelayedTask(function(){ sm.doSelectCell(row, col); sm.oldRow = row; sm.oldCell = col; this.view.focusRow(row,col); this.delayTask = null; }, this); this.delayTask.delay(250); } }, /** * @description dataSet의 rowPosChanged 이벤트가 발생하면 호출되는 메소드 * @method onRowPosChanged * @protected * @param {Object} e Event 객체 * @return void */ onRowPosChanged : function(e) { DU.widget.LCellSelectionModel.superclass.onRowPosChanged.call(this, e); this.doMoveSelectRow(e.row); }, /** * @description row 위치를 select하는 메소드 * @method selectRow * @private * @param {Int} row row 위치 * @return void */ selectRow : function(row) { DU.widget.LCellSelectionModel.superclass.selectRow.call(this, row); var sm = this.sm; var col = sm.currentCell; sm.doSelectCell(row, col); }, /** * @description row 위치로 이동시키는 메소드 * @method doMoveSelectRow * @protected * @param {Int} row 이동 위치 * @return void */ doMoveSelectRow : function(row) { var sm = this.sm; var col = sm.currentCell; if(this.isMultiCell !== true) sm.doDeSelectCell(sm.oldRow, sm.oldCell); this.isMultiCell = false; sm.doSelectCell(row, col); sm.oldRow = row; sm.oldCell = col; this.view.focusRow(row,col); }, /** * @description row 위치로 이동시키는 메소드 * @method doMoveSelectCell * @protected * @param {Int} row 이동 위치 * @return void */ doMoveSelectCell : function(col) { var sm = this.sm; sm.doDeSelectCell(sm.oldRow, sm.oldCell); sm.doSelectCell(sm.oldRow, col); sm.oldCell = col; this.view.focusRow(sm.oldRow,col); }, /** * @description cell 위치로 이동시키는 메소드 * @method selectCell * @param {Int} row 이동 위치 * @param {Int} col 이동 위치 * @return void */ selectCell : function(row, col) { var sm = this.sm; var dataSet = this.view.getDataSet(); if(row < 0 || row > dataSet.getCount() - 1) return; sm.currentCell = col; if (dataSet.getRow() == row) { this.doMoveSelectCell(col); } }, /** * @description cell를 선택하는 메소드 * @method doSelectCell * @protected * @param {Int} row 이동 위치 * @param {Int} col 이동 위치 * @return void */ doSelectCell : function(row, cell) { var columnModel = this.gridPanel.columnModel; if(cell < 0 || cell > columnModel.getColumnCount() - 1) return; var dataSet = this.view.getDataSet(); this.view.onCellSelect(row, cell); if(row > -1) { var record = dataSet.getAt(row); if(record) { var rowId = record.id; var column = columnModel.getColumnAt(cell); var cellId = column.field; if(cellId) { if(!this.selection[rowId]) { this.selection[rowId] = {}; this.selection[rowId].cellCount = 0; } if(this.selection[rowId][cellId] !== true) { this.selection[rowId][cellId] = true; this.selection[rowId].cellCount++; } } } } this.fireEvent("selectCell", {target:this, row:row, col:cell}); }, /** * @description cell를 선택 취소하는 메소드 * @method doDeSelectCell * @protected * @param {Int} row 이동 위치 * @param {Int} col 이동 위치 * @return void */ doDeSelectCell : function(row, cell) { var columnModel = this.gridPanel.columnModel; if(cell < 0 || cell > columnModel.getColumnCount() - 1 || row < 0) return; this.view.onCellDeselect(row, cell); var dataSet = this.view.getDataSet(); if(row > -1) { var record = dataSet.getAt(row); if(record) { var rowId = record.id; var column = columnModel.getColumnAt(cell); var cellId = column.field; var selectionRow = this.selection[rowId]; if (selectionRow) { if(selectionRow[cellId] === true) { delete selectionRow[cellId]; selectionRow.cellCount--; if(selectionRow.cellCount == 0) delete this.selection[rowId]; } } } } this.fireEvent("deselectCell", {target:this, row:row, col:cell}); }, /** * @description cell이 선택되었는지 여부를 리턴하는 메소드 * @method hasSelectedCell * @protected * @param {Int} row 이동 위치 * @param {Int} col 이동 위치 * @return {boolean} */ hasSelectedCell: function(row, cell) { var dataSet = this.view.getDataSet(); if(row < 0 || cell < 0 || row > dataSet.getCount() - 1) return false; var rowId = dataSet.getAt(row).id; var cellId = 'col_' + cell; var selectionRow = this.selection[rowId]; if (selectionRow) { return (selectionRow[cellId] === true) } return false; }, /** * @description keydown 이벤트시 호출되는 메소드 * @method onKeydown * @protected * @param {Object} e Event 객체 * @return void */ onKeydown : function(e) { if(!Event.isNavKey(e) && !(e.ctrlKey == true || e.shiftKey == true)) return; var gridPanel = this.gridPanel; var sm = this.sm; var dataSet = this.view.getDataSet(); DU.widget.LCellSelectionModel.superclass.onKeydown.call(this, e); if(gridPanel.isEdit == true) gridPanel.stopEditor(); var k = DU.util.LKeyListener.KEY; switch (e.keyCode) { case k.DOWN: case k.UP: case k.PAGE_DOWN: case k.PAGE_UP: this.selectCell(dataSet.getRow(), sm.oldCell); break; case k.LEFT: case k.RIGHT: var dir = (e.keyCode == k.LEFT) ? -1 : 1; var moveCell = this.oldCell + dir; moveCell = this.getVisibleColIndex(moveCell, dir); if(moveCell < 0) return; this.selectCell(dataSet.getRow(), moveCell); break; case k.TAB: if(this.tabToMove === true) { this.onTabMoveCell(e); } break; case k.ENTER: if(gridPanel.isEdit != true) { gridPanel.startEditor(); } break; } if(e.ctrlKey === true || e.shiftKey === true) { switch (Event.getCharCode(e)) { case 97: //a case 65: //A var columnModel = gridPanel.columnModel; var startRow = 0, endRow = dataSet.getCount() - 1; if(e.ctrlKey === true && e.shiftKey === true) startRow = endRow = dataSet.getRow(); for(var row = startRow; row <= endRow ; row++) { for(var col = 0 ; col < dataSet.fields.length ; col++) { var column = columnModel.getColumnByField(dataSet.fields[col].id); if(column) { var gridCol = columnModel.getIndexById(column.field); this.doSelectCell(row, gridCol); } } } break; } } Event.stopEvent(e); }, /** * @description tab키 이동 이벤트시 호출되는 메소드 * @method onTabMoveCell * @protected * @param {Object} e Event 객체 * @return void */ onTabMoveCell : function(e) { var gridPanel = this.gridPanel; var dataSet = gridPanel.getView().getDataSet(); var dir = (e.shiftKey === true) ? -1 : 1; var moveCell = this.oldCell + dir; moveCell = this.getVisibleColIndex(moveCell, dir); var row = dataSet.getRow(); if(moveCell < 0) { var start = dir > 0 ? 0 : (this.view.columnModel.getColumnCount() - 1); moveCell = this.getVisibleColIndex(start, dir); row += dir; if(row > dataSet.getCount()) return; } if(moveCell < 0) return; this.selectCell(row, moveCell); Event.stopEvent(e); }, /** * @description col 위치에 해당되는 컬럼중 보이는 컬럼 index를 리턴하는 메소드 * @method getVisibleColIndex * @param {Int} col col 위치 * @param {Int} calCol 계산 값 * @return void */ getVisibleColIndex : function(col, calCol) { if(col < 0 || col > this.view.columnModel.getColumnCount() - 1) return -1; var column = this.view.columnModel.getColumnAt(col); if(column == null) return -1; if(column.isHidden()) return this.getVisibleColIndex(col + calCol); else return col; }, /** * @description Editor시 키 이벤트 처리 메소드 * @method onEditorKey * @protected * @param {Object} e Event 객체 * @return void */ onEditorKey : function(e) { var gridPanel = this.gridPanel; var k = DU.util.LKeyListener.KEY; if(e.keyCode == k.TAB || e.keyCode == k.ESCAPE || e.keyCode == k.ENTER) { if(gridPanel.currentCellEditor) { if(gridPanel.currentCellEditor.editor.canBlur.call(gridPanel.currentCellEditor.editor, e) == false) return; } } switch (e.keyCode) { case k.TAB: gridPanel.stopEditor(true); this.onTabMoveCell(e); break; case k.ESCAPE: gridPanel.stopEditor(false); gridPanel.focusRow(); Event.stopEvent(e); break; case k.ENTER: gridPanel.stopEditor(true); if(this.enterToMove === true) this.onTabMoveCell(e); Event.stopEvent(e); break; } }, /** * @description body mousedown 이벤트 발생시 호출되는 메소드 * @method onBodyMouseDown * @private * @param {Object} e Event 객체 * @return void */ onBodyMouseDown : function(e) { Event.preventDefault(e); if(this.isLocked()) return; DU.widget.LCellSelectionModel.superclass.onBodyMouseDown.call(this, e); var target = e.target; var gridPanel = this.gridPanel; var view = this.view; var row = view.findRowIndex(target); var col = view.findCellIndex(target); if(row < 0 || col < 0) return; if (e.ctrlKey !== true && e.shiftKey !== true) { view.getBodyEl().select('.' + GV.CLASS_GRIDVIEW_CELL_SELECTED).removeClass(GV.CLASS_GRIDVIEW_CELL_SELECTED); this.selection = {}; this.selectCell(row, col); } else { if(e.ctrlKey === true) { var cellEl = DU.get(view.getCell(row, col)); if(cellEl.hasClass(GV.CLASS_GRIDVIEW_CELL_SELECTED)) this.doDeSelectCell(row, col); else this.doSelectCell(row, col); } else if(e.shiftKey === true) { view.getBodyEl().select('.' + GV.CLASS_GRIDVIEW_CELL_SELECTED).removeClass(GV.CLASS_GRIDVIEW_CELL_SELECTED); this.selection = {}; var startRow = this.oldRow; var startCell = this.currentCell; var columnModel = view.getColumnModel(); this.isMultiCell = true; for(var currRow = startRow; currRow <= row; currRow++ ) { for(var currCol = startCell; currCol <= col ; currCol++) { this.doSelectCell(currRow, currCol); } } } } if(row >= 0 && col >= 0) this.view.focusRow(row,col); }, /** * @description 선택한 cell 정보를 리턴합니다. * @method getSelection * @return {Object} */ getSelection: function() { return this.selection; }, /** * @description 선택한 cell Index를 리턴합니다. * @method getCell * @return {int} */ getCell: function() { return this.currentCell; }, /** * @description focusRow 객체를 선택하는 메소드 * @method doFocusRow * @return void */ doFocusRow : function(){ //RowSelectionModel과 CellSelectionModel에서 순차적으로 두분 focusRow가 발생해서 과거 cell로 갔다가 선택된 cell로 오는 버그 발생 //CellSelectionModel일 경우는 RowSelectionModel의 focusRow를 작동시키지 않아, cell에 의해서만 focus이동하도록 설정 } }) })(); /** * @description LTriggerColumn * @module widget_grid * @namespace DU.widget * @class LTriggerColumn * @extends DU.widget.LStaticColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LTriggerColumn = function(oConfigs) { DU.widget.LTriggerColumn.superclass.constructor.call(this, oConfigs); this.onAddDelegate = DU.util.LFunction.createDelegate(this.onAdd, this); this.onUpdateDelegate = DU.util.LFunction.createDelegate(this.onUpdate, this); this.onRemoveDelegate = DU.util.LFunction.createDelegate(this.onRemove, this); this.onUndoDelegate = DU.util.LFunction.createDelegate(this.onUndo, this); this.renderer = this.doRenderer; }; DU.extend(DU.widget.LTriggerColumn, DU.widget.LColumn, { /** * @description gridPanel 객체 * @property gridPanel * @private * @type {DU.widget.LGridPanel} */ gridPanel : null, /** * @description gridView 객체 * @property gridView * @private * @type {DU.widget.LGridView} */ gridView : null, /** * @description gridview의 event를 연결하는 메소드 * @method bindEvent * @protected * @param {DU.widget.LGridPanel} gridPanel gridPanel 객체 * @return {void} */ bindEvent : function(gridPanel) { DU.widget.LTriggerColumn.superclass.bindEvent.call(this, gridPanel); this.gridPanel = gridPanel; this.gridPanel.on('columnmove', this.onColumnmove, this, true); this.gridView = gridPanel.getView(); this.gridView.on('syncDataSet', this.onSetSyncDataSet, this, true); this.doSetSyncDataSet(this.gridView.isSyncDataSet()); }, /** * @description ColumnMove 이벤트 발생시 호출되는 메소드 * @method onColumnmove * @private * @param {Object} e Event 객체 * @return void */ onColumnmove : function(e) { }, /** * @description DataSet의 syncDataSet 이벤트 발생시 호출되는 메소드 * @method onSetSyncDataSet * @private * @param {Object} e Event 객체 * @return void */ onSetSyncDataSet : function(e) { this.doSetSyncDataSet(e.isSync); }, /** * @description DataSet의 syncDataSet 이벤트 발생시 수행되는 메소드 * @method doSetSyncDataSet * @private * @param {Boolean} isSync sync 여부 * @return void */ doSetSyncDataSet : function(isSync) { this.gridView.dataSet.unOn("add", this.onAddDelegate); this.gridView.dataSet.unOn("update", this.onUpdateDelegate); this.gridView.dataSet.unOn("remove", this.onRemoveDelegate); this.gridView.dataSet.unOn("undo", this.onUndoDelegate); if(isSync) { this.gridView.dataSet.on("add", this.onAddDelegate); this.gridView.dataSet.on("update", this.onUpdateDelegate); this.gridView.dataSet.on("remove", this.onRemoveDelegate); this.gridView.dataSet.on("undo", this.onUndoDelegate); } }, /** * @description DataSet의 add 이벤트 발생시 호출되는 메소드 * @method onAdd * @private * @param {Object} e Event 객체 * @return void */ onAdd : function(e) { this.doAdd(e.row, e.target); }, /** * @description DataSet의 update 이벤트 발생시 호출되는 메소드 * @method onUpdate * @private * @param {Object} e Event 객체 * @return void */ onUpdate : function(e) { this.doUpdate(e.row, e.col, e.target); }, /** * @description DataSet의 remove 이벤트 발생시 호출되는 메소드 * @method onRemove * @private * @param {Object} e Event 객체 * @return void */ onRemove : function(e) { this.doRemove(e.row, e.target); }, /** * @description DataSet의 undo 이벤트 발생시 호출되는 메소드 * @method onUndo * @private * @param {Object} e Event 객체 * @return void */ onUndo : function(e) { this.doUndo(e.row, e.target); }, /** * @description DataSet의 add 이벤트 발생시 수행되는 메소드 * @method doAdd * @private * @param {Int} row row위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return void */ doAdd : function(row, dataSet) { }, /** * @description DataSet의 update 이벤트 발생시 수행되는 메소드 * @method doUpdate * @private * @param {Int} row row위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return void */ doUpdate : function(row, col, dataSet) { }, /** * @description DataSet의 remove 이벤트 발생시 수행되는 메소드 * @method doRemove * @private * @param {Int} row row위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return void */ doRemove : function(row, dataSet) { }, /** * @description DataSet의 undo 이벤트 발생시 수행되는 메소드 * @method doUndo * @private * @param {Int} row row위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return void */ doUndo : function(row, dataSet) { }, /** * @description renderer를 수행하는 메소드 * @method doRenderer * @protected * @return {String} */ doRenderer : function(val, p, record, row, i) { return val; } }); /** * @description LStaticColumn * @namespace DU.widget * @class LStaticColumn * @extends DU.widget.LColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LStaticColumn = function(oConfigs) { DU.widget.LStaticColumn.superclass.constructor.call(this, oConfigs); }; DU.extend(DU.widget.LStaticColumn, DU.widget.LTriggerColumn, { /** * @description selected 속성 * @config selected * @type {Boolean} * @default false */ /** * @description selected 속성 * @property selected * @private * @type {Boolean} */ selected : false, /** * @description resizable 속성 * @config resizable * @type {Boolean} * @default false */ /** * @description resizable 속성 * @property resizable * @private * @type {Boolean} */ resizable : false, /** * @description sortable 속성 * @config sortable * @type {Boolean} * @default false */ /** * @description sortable 속성 * @property sortable * @private * @type {Boolean} */ sortable : false, /** * @description editor 속성 * @config editor * @type {Object} * @default null */ /** * @description editor 속성 * @property editor * @private * @type {Object} */ editor : null, /** * @description style 속성 * @property style * @private * @type {Strinig} */ style : 'background-color:#D4D400' }); /** * @description LNumberColumn * @namespace DU.widget * @class LNumberColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LNumberColumn = function(oConfigs) { DU.widget.LNumberColumn.superclass.constructor.call(this, oConfigs); }; DU.extend(DU.widget.LNumberColumn, DU.widget.LStaticColumn, { /** * @description Column id 속성 * @config id * @type {String} * @default 'num' */ /** * @description Column id 속성 * @property id * @private * @type {Strinig} */ id : 'num', /** * @description Column과 mapping field 속성 * @config mappingField * @type {String} * @default null */ /** * @description Column과 mapping field 속성 * @property mappingField * @private * @type {Strinig} */ mappingField : null, /** * @description Column의 label 속성 * @config label * @type {String} * @default 'Num' */ /** * @description Column의 label 속성 * @property label * @private * @type {Strinig} */ label : "Num", /** * @description Column의 align 속성 * @config align * @type {String} * @default 'right' */ /** * @description Column의 align 속성 * @property align * @private * @type {Strinig} */ align : "right", /** * @description Column의 width 속성 * @config width * @type {Int} * @default 35 */ /** * @description Column의 width 속성 * @property width * @private * @type {Int} */ width : 35, /** * @description resizable 속성 * @config resizable * @type {Boolean} * @default true */ /** * @description resizable 속성 * @property resizable * @private * @type {Boolean} */ resizable : true, /** * @description reder시 출력해야하는 데이터를 리턴하는 메소드 * @method doRenderer * @protected * @return {String} */ doRenderer : function(val, p, record, row, i) { if(this.mappingField) return record.get(this.mappingField); else return row + 1; }, /** * @description DataSet add시 renderer를 호출하는 메소드 * @method doAdd * @protected * @param {Int} row row 위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return {void} */ doAdd : function(row, dataSet) { this.doNumberRender(row); }, /** * @description DataSet remove시 renderer를 호출하는 메소드 * @method doRemove * @protected * @param {Int} row row 위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return {void} */ doRemove: function(row, dataSet){ this.doNumberRender(row); }, /** * @description DataSet undo시 renderer를 호출하는 메소드 * @method doUndo * @protected * @param {Int} row row 위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return {void} */ doUndo: function(row, dataSet){ this.doNumberRender(row); }, /** * @description DataSet number를 update하는 메소드 * @method doNumberRender * @protected * @param {Int} row row 위치 * @return {void} */ doNumberRender : function(row) { var dataSet = this.gridView.getDataSet(); var cell = this.getColumnModel().getIndexById(this.id); for(var i = row; i < dataSet.getCount() ; i++) { var record = dataSet.getAt(i); var cellDom = this.gridView.getCell(i, cell); if(!cellDom) return; // BufferGridView 케이스 var val = this.doRenderer(i, {}, record, i, i); cellDom.firstChild.innerHTML = val + ' '; } } }); /** * @description LStateColumn * @namespace DU.widget * @class LStateColumn * @extends DU.widget.LStaticColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LStateColumn = function(oConfigs) { var config = oConfigs || {}; DU.widget.LStateColumn.superclass.constructor.call(this, oConfigs); }; DU.extend(DU.widget.LStateColumn, DU.widget.LStaticColumn, { /** * @description Column id 속성 * @config id * @type {String} * @default 'state' */ /** * @description Column id 속성 * @property id * @private * @type {Strinig} */ id : 'state', /** * @description Column의 label 속성 * @config label * @type {String} * @default 'S' */ /** * @description Column의 label 속성 * @property label * @private * @type {Strinig} */ label : 'S', /** * @description Column의 align 속성 * @config align * @type {String} * @default 'center' */ /** * @description Column의 align 속성 * @property align * @private * @type {Strinig} */ align : "center", /** * @description Column의 width 속성 * @config width * @type {Int} * @default 15 */ /** * @description Column의 width 속성 * @property width * @private * @type {Int} */ width : 15, /** * @description fixed 속성 * @config fixed * @type {Boolean} * @default true */ /** * @description fixed 속성 * @property fixed * @private * @type {Boolean} */ fixed : true, stateCol: -1, /** * @description gridview의 event를 연결하는 메소드 * @method bindEvent * @protected * @param {DU.widget.LGridPanel} gridPanel gridPanel 객체 * @return {void} */ bindEvent : function(gridPanel) { DU.widget.LStateColumn.superclass.bindEvent.call(this, gridPanel); this.gridView.dataSet.on('load', this.doChangeHeaderState, this, true); this.gridView.dataSet.on('add', this.doChangeHeaderState, this, true); this.gridView.dataSet.on('update', this.doChangeHeaderState, this, true); this.gridView.dataSet.on('remove', this.doChangeHeaderState, this, true); this.gridView.dataSet.on('undo', this.doChangeHeaderState, this, true); this.gridView.dataSet.on('dataChanged', this.doChangeHeaderState, this, true); this.gridView.dataSet.on('commit', this.doCommit, this, true); this.stateCol = this.columnModel.getIndexById(this.id); }, /** * @description renderer를 수행하는 메소드 * @method doRenderer * @protected * @return {String} */ doRenderer : function(val, p, record, row, i) { var state = this.getState(record); if(state != '') p.css.push('L-grid-cell-state-' + state); return ' '; }, /** * @description DataSet의 add 이벤트 발생시 호출되는 메소드 * @method onAdd * @private * @param {Object} e Event 객체 * @return void */ onAdd : function(e) { this.doChangeRowState(e.row, e.record); }, /** * @description DataSet의 update 이벤트 발생시 호출되는 메소드 * @method onUpdate * @private * @param {Object} e Event 객체 * @return void */ onUpdate : function(e) { this.doChangeRowState(e.row, e.record, e.record.state); }, /** * @description DataSet의 undo 이벤트 발생시 호출되는 메소드 * @method onUndo * @private * @param {Object} e Event 객체 * @return void */ onUndo : function(e) { this.doChangeRowState(e.row, e.record, e.beforeState); }, /** * @description row 위치값의 state cell의 값을 변경한다. * @method doChangeRowState * @private * @param {Int} row row 값 * @param {DU.data.LRecord} record record 객체 * @param {Int} beforeState before state 값 * @return void */ doChangeRowState: function(row, record, beforeState) { if(beforeState === DU.data.LRecord.STATE_INSERT) return; var cell = this.gridView.getCell(row, this.stateCol); if(cell) { var cellEl = DU.get(cell); if(cellEl.hasClass('L-grid-cell-state-I') || cellEl.hasClass('L-grid-cell-state-U') || cellEl.hasClass('L-grid-cell-state-D')) cellEl.removeClass('L-grid-cell-state-I').removeClass('L-grid-cell-state-U').removeClass('L-grid-cell-state-D'); cellEl.addClass('L-grid-cell-state-' + this.getState(record)); } }, /** * @description dataSet의 상태를 LStateColumn의 헤더에 반영한다. * @method doChangeHeaderState * @private * @return void */ doChangeHeaderState: function() { var cellEl = this.gridView.getHeaderCellEl(this.stateCol); this.gridView.dataSet.isUpdate() ? cellEl.addClass('L-grid-state-modified') : cellEl.removeClass('L-grid-state-modified'); }, /** * @description dataSet의 상태가 commit 될 경우 * @method doCommit * @private * @return void */ doCommit: function() { var dataSet = this.gridView.dataSet; var bodyEl = this.gridView.getBodyEl(); var cellList = bodyEl.select(".L-grid-cell-state-I,.L-grid-cell-state-U,.L-grid-cell-state-D"); cellList.removeClass(['L-grid-cell-state-I', 'L-grid-cell-state-U','L-grid-cell-state-D']); var cellEl = this.gridView.getHeaderCellEl(this.stateCol); cellEl.removeClass('L-grid-state-modified') }, /** * @description state값을 리턴하는 메소드 * @method getState * @protected * @return {String} */ getState : function(record) { switch (record.state) { case DU.data.LRecord.STATE_INSERT: return 'I'; break; case DU.data.LRecord.STATE_UPDATE: return 'U'; break; case DU.data.LRecord.STATE_DELETE: return 'D'; break; } return ''; } }); /** * @description LMergeColumn * @namespace DU.widget * @class LMergeColumn * @extends DU.widget.LStaticColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LMergeColumn = function(oConfigs) { var config = oConfigs || {}; DU.widget.LMergeColumn.superclass.constructor.call(this, oConfigs); }; DU.extend(DU.widget.LMergeColumn, DU.widget.LTriggerColumn, { /** * @description Column vertical merge 속성 * @config verticalMerge * @type {Boolean} * @default true */ /** * @description Column vertical merge 속성 * @property verticalMerge * @private * @type {Boolean} */ verticalMerge: true, /** * @description DataSet의 update 이벤트 발생시 호출되는 메소드 * @method onUpdate * @private * @param {Object} e Event 객체 * @return void */ onUpdate : function(e) { var col = this.columnModel.getIndexById(e.colId); this.updateVerticalMergeCss(e.row, col, e.colId); }, /** * @description DataSet의 update시 vertical merge css 적용 메소드 * @method updateVerticalMergeCss * @private * @param {Int} row row값 * @param {Int} col col값 * @param {String} colId col id * @return void */ updateVerticalMergeCss : function(row, col, colId) { var view = this.gridView; for(i = row - 1 ; i <= (row + 1); i++) { var cell = view.getCell(i, col); if(cell) { var mergeCss = view.getVerticalMergeCss(i, col, colId); var cellEl = DU.get(cell); cellEl.removeClass([DU.widget.LGridView.VM, DU.widget.LGridView.VMF, DU.widget.LGridView.VMM, DU.widget.LGridView.VML]); cellEl.addClass(mergeCss); } } } }); /** * @description LSelectionColumn * @namespace DU.widget * @class LSelectionColumn * @extends DU.widget.LStaticColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LSelectionColumn = function(oConfigs) { var config = oConfigs || {}; DU.widget.LSelectionColumn.superclass.constructor.call(this, oConfigs); }; DU.extend(DU.widget.LSelectionColumn, DU.widget.LStaticColumn, { /** * @description Column id 속성 * @config id * @type {String} * @default DU.id() */ /** * @description Column id 속성 * @property id * @private * @type {Strinig} */ id : 'selection', /** * @description Column의 selectionType 속성 * @config selectionType * @type {String} * @default 'checkBox' */ /** * @description Column의 selectionType 속성 * @property selectionType * @private * @type {Strinig} */ selectionType : 'checkBox', /** * @description Column의 label 속성 * @config label * @type {String} * @default '' */ /** * @description Column의 label 속성 * @property label * @private * @type {Strinig} */ label : null, /** * @description Column의 align 속성 * @config align * @type {String} * @default 'center' */ /** * @description Column의 align 속성 * @property align * @private * @type {String} */ align : "center", /** * @description Column의 width 속성 * @config width * @type {Int} * @default 28 */ /** * @description Column의 width 속성 * @property width * @private * @type {Int} */ width : 28, /** * @description fixed 속성 * @config fixed * @type {Boolean} * @default true */ /** * @description fixed 속성 * @property fixed * @private * @type {Boolean} */ fixed : true, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @return void */ init : function() { DU.widget.LSelectionColumn.superclass.init.call(this); this.label = this.label != 'selection' ? this.label : ''; }, /** * @description renderer를 수행하는 메소드 * @method doRenderer * @protected * @return {String} */ doRenderer : function(val, p, record, row, i) { return ''; } }); /** * @description Combo의 code값과 display값을 분리하여 처리하는 객체 * @namespace DU.widget * @class LEditComboColumn * @extends DU.widget.LStaticColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LEditComboColumn = function(oConfigs) { var config = oConfigs || {}; DU.widget.LEditComboColumn.superclass.constructor.call(this, oConfigs); // 반드시 row가 이동하게 설정 config.editor.isForceRow = true; if(config.displayField) config.rendererField = config.displayField; /** * @description Column renderer 속성 * @property renderer * @private * @type {Function} */ this.renderer = this.comboRenderer(config.editor); }; DU.extend(DU.widget.LEditComboColumn, DU.widget.LTriggerColumn, { /** * @description Combo 객체 * @config combo * @type {DU.widget.LCombo} * @default null */ /** * @description Combo 객체 * @property combo * @private * @type {DU.widget.LCombo} */ combo : null, /** * @description Combo의 DataSet 객체 * @property comboDataSet * @private * @type {DU.data.LDataSet} */ comboDataSet : null, /** * @description Combo의 value에 해당되는 dataSet의 field col 위치 * @property valueCol * @private * @type {Int} */ valueCol : -1, /** * @description dataSet의 code에 해당 value 필드명 * @config rendererField * @type {String} * @default null */ /** * @description dataSet의 code에 해당 value 필드명 * @property rendererField * @private * @type {String} */ rendererField : null, /** * @description gridview의 event를 연결하는 메소드 * @method bindEvent * @protected * @param {DU.widget.LGridView} gridView gridView 객체 * @return {void} */ bindEvent : function(gridView) { DU.widget.LEditComboColumn.superclass.bindEvent.call(this, gridView); this.syncComboCol(); }, /** * @description ComboColumn을 renderer하는 메소드 * @method comboRenderer * @param {DU.widget.LCombo} combo combo 객체 * @return {String} */ comboRenderer : function(combo) { var rendererField = this.rendererField; this.combo = combo; this.comboDataSet = combo.getDataSet(); return function(val, p, record, row, i) { if(DU.isEmpty(val)) return ''; var displayValue = ''; if(record.state == DU.data.LRecord.STATE_NORMAL) { displayValue = record.get(rendererField); } else { if(this.comboDataSet.getCount() > 0) { var row = this.comboDataSet.findRow(combo.valueField, val); if(row > -1) { var comboRecord = this.comboDataSet.getAt(row); displayValue = comboRecord.get(combo.displayField); } } } return (!DU.isUndefined(displayValue)) ? displayValue : val; } }, /** * @description ColumnMove 이벤트 발생시 호출되는 메소드 * @method onColumnmove * @private * @param {Object} e Event 객체 * @return void */ onColumnmove : function(e) { this.syncComboCol(); }, /** * @description 선택된 combo의 col값을 동기화 한다. * @method syncComboCol * @private * @return void */ syncComboCol : function() { var dataSet = this.gridView.getDataSet(); this.valueCol = dataSet.fieldIndex(this.field); }, /** * @description DataSet의 update 이벤트 발생시 수행되는 메소드 * @method doUpdate * @private * @param {Int} row row위치 * @param {Int} col col위치 * @param {DU.data.LDataSet} dataSet DataSet 객체 * @return void */ doUpdate : function(row, col, dataSet) { if(this.valueCol != col) return; if(this.rendererField) { var value = dataSet.getValue(row, col); var comboRow = this.comboDataSet.findRow(this.combo.valueField, value); if(comboRow > -1) { var comboRecord = this.comboDataSet.getAt(comboRow); var record = dataSet.getAt(dataSet.getRow()); record.set(this.rendererField, comboRecord != null ? comboRecord.get(this.combo.displayField) : null); } } } }); /** * @description LGridPanel * @module widget_grid * @title LGridPanel * @requires DU */ DU.namespace("DU.widget"); (function() { /** * @description LGridPanel * @namespace DU.widget * @class LGridPanel * @extends DU.widget.LUIComponent * @constructor LGridPanel * @param {Object} oConfig The intial LGridPanel. */ DU.widget.LGridPanel = function(oConfig) { var config = oConfig || {}; DU.applyIf(config, { id:DU.id(), appendtodocumentbody:true, visible:true, draggable:false, underlay:'', close:false, viewConfig : {} }); config = DU.util.LDom.applyIfProperties(config, '$.ext.gridPanel'); /* * autoWidth : false이고 width를 할당했다면 width 적용 * */ if(config.autoWidth !== false) delete config.width; DU.applyObject(config.viewConfig, config, true); DU.applyObject(this, config, true); DU.widget.LGridPanel.superclass.constructor.call(this, config.id, config); /** * @description panel이 click 되면 호출되는 이벤트 * @event click */ this.createEvent("click"); /** * @description panel이 dblclick 되면 호출되는 이벤트 * @event dblclick */ this.createEvent("dblclick"); /** * @description panel이 mousedown 되면 호출되는 이벤트 * @event mousedown */ this.createEvent("mousedown"); /** * @description panel이 mouseup 되면 호출되는 이벤트 * @event mouseup */ this.createEvent("mouseup"); /** * @description panel이 mouseover 되면 호출되는 이벤트 * @event mouseover */ this.createEvent("mouseover"); /** * @description panel이 mouseout 되면 호출되는 이벤트 * @event mouseout */ this.createEvent("mouseout"); /** * @description panel이 cellmousedown 되면 호출되는 이벤트 * @event cellmousedown */ this.createEvent("cellmousedown"); /** * @description panel이 rowmousedown 되면 호출되는 이벤트 * @event rowmousedown */ this.createEvent("rowmousedown"); /** * @description panel이 headermousedown 되면 호출되는 이벤트 * @event headermousedown */ this.createEvent("headermousedown"); /** * @description panel이 cellclick 되면 호출되는 이벤트 * @event cellclick * @param {Object} target this객체 * @param {Int} row row값 * @param {Int} col col값 * @param {Object} e event객체 */ this.createEvent("cellclick"); /** * @description panel이 celldblclick 되면 호출되는 이벤트 * @event celldblclick * @param {Object} target this객체 * @param {Int} row row값 * @param {Int} col col값 * @param {Object} e event객체 */ this.createEvent("celldblclick"); /** * @description panel이 rowclick 되면 호출되는 이벤트 * @event rowclick * @param {Object} target this객체 * @param {Int} row row값 * @param {Object} e event객체 */ this.createEvent("rowclick"); /** * @description panel이 rowdblclick 되면 호출되는 이벤트 * @event rowdblclick * @param {Object} target this객체 * @param {Int} row row값 * @param {Object} e event객체 */ this.createEvent("rowdblclick"); /** * @description panel이 headerclick 되면 호출되는 이벤트 * @event headerclick * @param {Object} target this객체 * @param {Int} col col값 * @param {Object} e event객체 */ this.createEvent("headerclick"); /** * @description panel이 headerdblclick 되면 호출되는 이벤트 * @event headerdblclick * @param {Object} target this객체 * @param {Int} col col값 * @param {Object} e event객체 */ this.createEvent("headerdblclick"); /** * @description panel이 bodyscroll 되면 호출되는 이벤트 * @event bodyscroll */ this.createEvent("bodyscroll"); /** * @description panel이 keydown 되면 호출되는 이벤트 * @event keydown */ this.createEvent("keydown"); /** * @description panel이 keypress 되면 호출되는 이벤트 * @event keypress */ this.createEvent("keypress"); /** * @description panel이 autoWidth !== false일 경우 resizing이 발생했을 경우 발생하는 event * @event widthResize */ this.createEvent("widthResize"); /** * @description copy시 호출되는 이벤트 * @event copy */ this.createEvent("copy"); /** * @description paste시 호출되는 이벤트 * @event paste */ this.createEvent("paste"); }; var Dom = DU.util.LDom; var Ev = DU.util.LEvent; var GV = DU.widget.LGridPanel; DU.applyObject(DU.widget.LGridPanel, { /*************field member***********/ //*********CSS Class CLASS_GRID_PANEL : "L-grid-panel" }); DU.extend(DU.widget.LGridPanel, DU.widget.LPanel, { /** * GridView * @property view * @type DU.widget.LGridView * @private */ view : null, /** * @description columnModel 객체 *Sample: 보기
* @config columnModel * @type {DU.widget.LColumnModel} * @default null */ /** * @description columnModel 객체 * @property columnModel * @type {DU.widget.LColumnModel} * @private */ columnModel: null, /** * @description selectionModel 객체 *Sample: 보기
* @config selectionModel * @type {DU.widget.LSelectionModel} * @default null */ /** * @description selectionModel 객체 * @property selectionModel * @type {DU.widget.LSelectionModel} * @private */ selectionModel: null, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig: function () { DU.widget.LGridPanel.superclass.initDefaultConfig.call(this); }, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @param {Object} oConfig 환경정보 객체 * @return void */ init: function(el, userConfig){ /* Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level */ DU.widget.LGridPanel.superclass.init.call(this, el/*, userConfig*/); this.beforeInitEvent.fire(DU.widget.LGridPanel); Dom.addClass(this.element, GV.CLASS_GRID_PANEL); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.setBody(""); this.initEvent.fire(DU.widget.LGridPanel); }, /** * override 구현시 사용자 이벤트 초기화 메소드 * @method initEvents */ initEvents: function(){ DU.widget.LGridPanel.superclass.initEvents.call(this); }, /** * @description render시 호출되는 메소드 * @method doRender * @protected * @param {HTMLElement} container 부모 객체 * @return void */ doRender : function(container) { //header footer가 먼저 render 되어야 gridview에서 height를 계산할 수 있다. var view = this.getView(); //buffered grid의 onRowPosChanged event가 먼저 작동해야 하므로 view.render 이후에 selection model 탑제 this.getSelectionModel().init(this); var bodyEl = DU.get(this.body); bodyEl.on("mousedown", this.onMouseDown, this, true); bodyEl.on("click", this.onClick, this, true); bodyEl.on("dblclick", this.onDblClick, this, true); bodyEl.on("contextmenu", this.onContextMenu, this, true); bodyEl.on("keydown", this.onKeyDown, this, true); bodyEl.on("keypress", this.onKeypress, this, true); bodyEl.on("keydown", this.onCopyPaste, this, true); view.setPanel(this); //config.width가 render후에 발생하므로, //render시 header/scroller width에 의해 width가 늘어난 상태에서 계산하므로 원하는 width가 생성되지 않는다. //따라서 render전에 config.width/height/fillHeight 처리를 해야한다. this.updateSizes(); view.render(this.body); this.columnModel.bindEvent(this); //100%일 경우 필요. if (this.autoWidth !== false) { this.onWidthResizeDelegate = DU.util.LFunction.createDelegate(this.onWidthResize, this); this.resizeMonitor = new DU.util.LResizeMonitor(); this.resizeMonitor.monitor(this.element); this.resizeMonitor.on("resized",this.onWidthResizeDelegate); //IE의 width auto일때 content size이하로 container width가 안줄어드는 버그(?) 해결 this.onWindowResizeDelegate = DU.util.LFunction.createDelegate(this.onWindowResize, this); DU.util.LEvent.removeListener(window, "resize", this.onWindowResizeDelegate); DU.util.LEvent.addListener(window, "resize", this.onWindowResizeDelegate); } }, /** * @description autoWidth !== false시 gridView header, scroller width 재계산 용도 * @private * @method onWidthResize * @return void */ onWidthResize : function(e){ if (!this.widthResizeEventLock) { //widthResize가 windowResize보다 먼저 작동되는 문제 해결위해 delay 설정. if (!this.delayTask) { this.delayTask = new DU.util.LDelayedTask(function(){ //안보였다가 보일때 처리. this.updateWidth(); this.fillHeight(); this.fireEvent("widthResize", { target: this, event: e }); this.delayTask = null; }, this); this.delayTask.delay(1); } } }, /** * @description window resize시 header, body, footer의 width를 100%일때의 px값으로 설정. IE문제 해결. * @private * @method onWidthResize * @return void */ onWindowResize : function(){ this.updateWidth(); }, /** ** Overlay fillHeight에서 container = this.element || this.innerElement, this.element가 우선이 되도록 순서 변경. * panel을 height를 부모의 나머지 공간까지 채우는 메소드 *
*NOTE: This method is not designed to work if an explicit * height has not been set on the container, since for an "auto" height container, * the heights of the header/body/footer will drive the height of the container.
* * @method fillHeight * @param {HTMLElement} el The element which should be resized to fill out the height * of the container element. */ fillHeight : function(el) { el = el ? el : this.body; var borderWidth = 1; if (el) { var container = this.element || this.innerElement, containerEls = [this.header, this.body, this.footer], containerEl, total = 0, filled = 0, remaining = 0, validEl = false; for (var i = 0, l = containerEls.length; i < l; i++) { containerEl = containerEls[i]; if (containerEl) { if (el !== containerEl) { filled += this._getPreciseHeight(containerEl); } else { validEl = true; } } } if (validEl) { if (DU.browser.msie || DU.browser.opera) { // Need to set height to 0, to allow height to be reduced Dom.setStyle(el, 'height', 0 + 'px'); } total = this._getComputedHeight(container); // Fallback, if we can't get computed value for content height if (total === null) { Dom.addClass(container, "L-override-padding"); total = container.clientHeight; // Content, No Border, 0 Padding (set by L-override-padding) Dom.removeClass(container, "L-override-padding"); } remaining = total - filled - borderWidth * 2;//border를 빼줘야 한다. remaining = remaining < 0 ? 0 : remaining; Dom.setStyle(el, "height", remaining + "px"); // Re-adjust height if required, to account for el padding and border //rendering 방식의 변화로 offsetHeight를 구할 수 없음. body rendering은 나중에 이루어지기 때문, 0일때 계산하지 않음 if (el.offsetHeight != 0 && el.offsetHeight != remaining) { remaining = remaining - (el.offsetHeight - remaining); Dom.setStyle(el, "height", remaining + "px"); } } } }, /** * LGridPanel Size를 재계산 * @method updateSizes * @public * @return void */ updateSizes : function(){ var el = DU.get(this.element); if(this.autoWidth !== false){ this.updateWidth(); }else{ var width = this.cfg.getProperty("width"); if (width) { el.setWidth(width); width = width - 2;//border를 뺀다. if (this.header) { hd = DU.get(this.header); hd.setWidth(width); } if (this.footer) { ft = DU.get(this.footer); ft.setWidth(width); } if (this.body) { bd = DU.get(this.body); bd.setWidth(width); } } } var height = this.cfg.getProperty("height"); if (height) { el.setHeight(height); //ie6에서 하단 선이 안나오는 버그 해결. border width 고려 필요. Dom.setStyle(this.innerElement, "height", (height-2) + "px"); } this.fillHeight(); }, /** * LGridPanel autoWidth !== false일 경우 동작 IE의 size 안 줄어드는 버그 해결. * @method updateSizes * @private * @return void */ updateWidth : function(){ //100%일 경우 이상증상으로 overflow되어 panel right border가 가려짐. 100%때의 width로 설정하면 해결됨. if (this.autoWidth !== false) { this.widthResizeEventLock = true; var hd, ft, bd; var width = 0; if (this.header) { hd = DU.get(this.header); hd.setStyle("width","100%"); } if (this.footer) { ft = DU.get(this.footer); ft.setStyle("width","100%"); } if (this.body) { bd = DU.get(this.body); bd.setStyle("width","100%"); width = bd.getWidth(); } if(hd) hd.setWidth(width); if(ft) ft.setWidth(width); this.widthResizeEventLock = false; if(bd) bd.setWidth(width); } }, /** * config의 height값을 적용하는 메소드 * LPanel처럼 innerElement로 계산하면 sizing이 안된다. * @method configHeight * @protected * @param {String} type 이벤트 종류 값 * @param {Object[]} args 이벤트 인수 * @param {Object} obj 호출할 scope 객체 */ configHeight: function (type, args, obj) { var height = args[0], el = this.element; Dom.setStyle(el, "height", height + "px"); this.cfg.refireEvent("iframe"); if(this._rendered) this.updateSizes(); this.getView().setHeight(height); }, /** * config의 width값을 적용하는 메소드 * @method configWidth * @protected * @param {String} type 이벤트 종류 값 * @param {Object[]} args 이벤트 인수 * @param {Object} obj 호출할 scope 객체 */ configWidth: function (type, args, obj) { var width = args[0], el = this.element; width = (typeof width == 'string' && DU.util.LString.endsWith(width, 'px'))? width: width + 'px'; Dom.setStyle(el, "width", width); this.cfg.refireEvent("iframe"); if(this._rendered) this.updateSizes(); this.getView().setWidth(width); }, /** * @description 엘리먼트의 넓이를 설정한다. * @method setWidth * @public * @param {Mixed} width 새로운 넓이. 다음 중 하나:
// 높이를 200px로 바꾸고 default configuration으로 동작한다.
DU.get('elementId').setHeight(200, true);
// 높이를 150px로 바꾸고 custom configuration으로 동작한다.
DU.get('elId').setHeight(150, {
duration : .5, // 동작이 .5초 동안 지속된다
// 내용을 "finished"로 변환한다
callback: function(){ this.{@link #update}("finished"); }
});
*
* @method setHeight
* @param {Mixed} height 새로운 높이. 다음 중 하나:Sample: 보기
* @config clickToEdit * @type {Boolean} * @default false */ /** * @description click시 edit상태로 전환할지 여부 속성 * @property clickToEdit * @private * @type {Boolean} */ clickToEdit : true, /** * @description cell focus시 자동 edit상태로 전환할지 여부 속성 *Sample: 보기
* @config autoToEdit * @type {Boolean} * @default false */ /** * @description cell focus시 자동 edit상태로 전환할지 여부 속성 * @property autoToEdit * @private * @type {Boolean} */ autoToEdit : false, /** * @description enter시 edit상태로 전환할지 여부 속성 *Sample: 보기
* @config enterToEdit * @type {Boolean} * @default true */ /** * @description enter시 edit상태로 전환할지 여부 속성 * @property enterToEdit * @private * @type {Boolean} */ enterToEdit : true, /** * @description editor상태에서 enter를 치면 다음 editor cell로 이동할지 여부 속성 *Sample: 보기
* @config enterToMove * @type {Boolean} * @default true */ /** * @description editor상태에서 enter를 치면 다음 editor cell로 이동할지 여부 속성 * @property enterToMove * @private * @type {Boolean} */ enterToMove : true, /** * @description editor 상태인지를 여부 속성 * @property isEdit * @private * @type {Boolean} */ isEdit : false, /** * @description edit가 가능한지 여부 속성 *Sample: 보기
* @config editable * @type {Boolean} * @default true */ /** * @description edit가 가능한지 여부 속성 * @property editable * @private * @type {Boolean} */ editable : true, /** * @description 그리드가 render시 row와 cell render event를 skip할지 여부(성능과 연관되므로 대량건 처리시는 false로 처리) *Sample: 보기
* @config skipRowCellEvent * @type {Boolean} * @default true */ /** * 그리드가 render시 row와 cell render event를 skip할지 여부(성능과 연관되므로 대량건 처리시는 false로 처리) * @property skipRowCellEvent * @type {Boolean} * @private */ skipRowCellEvent: true, /** * @description row 의 css가 editable이 적용될시 사용하는 CSS값 * @property CLASS_GRID_ROW_EDITABLE * @private * @type {String} */ CLASS_GRID_ROW_EDITABLE : "L-grid-row-editable", /** * @description cell 의 css가 editable이 적용될시 사용하는 CSS값 * @property CLASS_GRID_CELL_EDITABLE * @private * @type {String} */ CLASS_GRID_CELL_EDITABLE : "L-grid-cell-editable", /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig: function () { DU.widget.LEditGridPanel.superclass.initDefaultConfig.call(this); }, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @param {Object} oConfig 환경정보 객체 * @return void */ init: function(el, userConfig){ DU.widget.LEditGridPanel.superclass.init.call(this, el/*, userConfig*/); this.beforeInitEvent.fire(DU.widget.LEditGridPanel); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.setBody(""); var view = this.getView(); var selectionModel = this.getSelectionModel(); this.onEditorKeyDelegate = DU.util.LFunction.createDelegate(selectionModel.onEditorKey, selectionModel); this.initEvent.fire(DU.widget.LEditGridPanel); }, /** * @description 객체의 이벤트 초기화 메소드 * @method initEvents * @protected * @return void */ initEvents: function(){ DU.widget.LEditGridPanel.superclass.initEvents.call(this); }, /** * @description render시 호출되는 메소드 * @method doRender * @protected * @param {HTMLElement} container 부모 객체 * @return void */ doRender : function(container) { this.on('headermousedown', function() { this.stopEditor(true); }, this, true); this.on('headerclick', function() { this.stopEditor(true); }, this, true); DU.widget.LEditGridPanel.superclass.doRender.call(this); }, /** * @description render후 호출되는 메소드 * @method afterRender * @protected * @param {HTMLElement} container 부모 객체 * @return void */ afterRender : function(container) { DU.widget.LEditGridPanel.superclass.afterRender.call(this, container); var view = this.getView(); var sm = this.getSelectionModel(); var columnModel = view.getColumnModel(); var thisObj = this; this.on("headermousedown", this.onHeaderMouseDown); if(view.columnDD) { view.columnDD.on('startDragEvent', function(){ this.stopEditor(true); }, this, true); } sm.on("selectRow", function(e) { thisObj.currentRow = e.row, thisObj.currentCol = 0; }); sm.on("selectCell", function(e) { thisObj.oldRow = thisObj.currentRow, thisObj.olcCol = thisObj.currentCol; thisObj.currentRow = e.row, thisObj.currentCol = e.col; if(thisObj.autoToEdit === true) { thisObj.startEditor(); } }); sm.on("deselectCell", function(e) { thisObj.currentRow = e.row, thisObj.currentCol = e.col; thisObj.stopEditor(true); }); if(this.skipRowCellEvent !== true){ view.on('renderRow', function(e){ var css = e.css, row = e.row, record = e.record; css.push(thisObj.CLASS_GRID_ROW_EDITABLE); }); view.on('renderCell', function(e){ var css = e.css, col = e.col, row = e.row, record = e.record; var column = columnModel.getColumnAt(col); if(column.isEditable()) css.push(thisObj.CLASS_GRID_CELL_EDITABLE); }); } view.on('blur', this.onBlurStopEditor, this, true); this.on("cellclick", this.onCellclick); this.on("celldblclick", this.onCelldblclick); this.on("bodyscroll", this.onBodyscroll); //column resize시 event 걸기 for (var i = 0; i < columnModel.getColumnCount(); i++) { columnModel.getColumnAt(i).unOn("columnresize", this.onColumnResizeDelegate); columnModel.getColumnAt(i).on("columnresize", this.onColumnResizeDelegate); } view.getDataSet().on("canRowPosChange", this.onDataSetCanRowPosChanged, this, true); }, /** * @description headermousedown 이벤트 발생시 호출되는 메소드 * @method onHeaderMouseDown * @private * @param {Object} e Event 객체 * @return void */ onHeaderMouseDown : function(e) { this.stopEditor(true); }, /** * @description cellclick 이벤트 발생시 호출되는 메소드 * @method onCellclick * @private * @param {Object} e Event 객체 * @return void */ onCellclick : function(e) { var row = e.row, col = e.col; var column = this.getView().getColumnModel().getColumnAt(col); if(column) { if(DU.get(e.event.target).hasClass('L-popup-button-icon')) { this.fireEvent('popup', {target:this, row:row, col:col, colId: column.getId() }); DU.util.LEvent.stopPropagation(e); } } if(this.clickToEdit === true && e.event.shiftKey !== true && e.event.ctrlKey !== true) { this.startEditor(); } }, /** * @description celldbclick 이벤트 발생시 호출되는 메소드 * @method onCelldblclick * @private * @param {Object} e Event 객체 * @return void */ onCelldblclick : function(e) { this.startEditor(); }, /** * @description columnresize 이벤트 발생시 호출되는 메소드 * @method onColumnResize * @private * @param {Object} e Event 객체 * @return void */ onColumnResize : function(e) { this.stopEditor(true); }, /** * @description columnmove 이벤트 발생시 호출되는 메소드 * @method onColumnMove * @private * @param {Object} e Event 객체 * @return void */ onColumnMove : function(e) { this.stopEditor(true); }, /** * @description bodyscroll 이벤트 발생시 호출되는 메소드 * @method onBodyscroll * @private * @param {Object} e Event 객체 * @return void */ onBodyscroll : function(e) { this.stopEditor(true); }, /** * @description DataSet의 canRowPosChange 이벤트 발생시 호출되는 메소드 * @method onDataSetCanRowPosChanged * @private * @param {Object} e Event 객체 * @return void */ onDataSetCanRowPosChanged : function(e) { return this.stopEditor(true); }, /** * @description editor에서 changed 이벤트 발생시 호출되는 메소드 * @method onEditorChanged * @private * @param {Object} e Event 객체 * @return void */ onEditorChanged : function(e) { //this.applyValue(true, false); }, /** * @description editor에서 blur 이벤트 발생시 호출되는 메소드 * @method onEditorBlur * @private * @param {Object} e Event 객체 * @return void */ onEditorBlur : function(e) { var target = e; var isValid = this.stopEditor(true); if(isValid == false) target.focus(); else this.selectionModel.unlock(); }, /** * @description edit 상태로 시작하는 메소드 * @method startEditor * protected * @return void */ startEditor : function() { if(this.isEdit === true || this.editable == false) return; this.stopEditor(false); var row = this.currentRow, col = this.currentCol; var view = this.getView(); var columnModel = view.getColumnModel(); var column = columnModel.getColumnAt(col); if(column && column.isEditable()) { if(this.skipRowCellEvent !== true) { var rowDom = view.getRow(row); if(rowDom && Dom.hasClass(rowDom, this.CLASS_GRID_ROW_EDITABLE) == false) return; } if(column.isEditable() == false) return; columnModel.editors = columnModel.editors || {}; var record = view.getDataSet().getAt(row); var editorId = column.getId(); var customEditor = column.customEditor; var cellEditor = null; var editorType = null; if(customEditor === true) { var customEditorField = columnModel.customEditorField; editorType = record.get(customEditorField) || record.getAttribute(customEditorField); cellEditor = columnModel.editors[editorType || editorId]; } else { cellEditor = columnModel.editors[editorId]; } var applyValue = record.get(column.field); delete this.emptyValue; if(DU.isEmpty(applyValue)) { this.emptyValue = applyValue; applyValue = ''; } if(!cellEditor) { var editor = (customEditor === true) ? columnModel.customEditors[editorType] : column.editor; if(editor == null) return; column.editor = editor; editor.gridFieldId = column.id; editor.invalidBlur = false; cellEditor = new DU.widget.LEditorPanel({ editor: editor, column: column, view: view }); cellEditor.render(view.getScrollerEl().dom); columnModel.editors[editorType || editorId] = cellEditor; cellEditor.editor.on("changed", this.onEditorChangedDelegate); cellEditor.editor.on("blur", this.onEditorBlurDelegate); cellEditor.editor.on("specialkey", this.onEditorKeyDelegate); } var cellDom = view.getCell(row, col); var region = Dom.getRegion(cellDom); cellEditor.show(); cellEditor.setRegion(region); cellEditor.editor.valid(); cellEditor.editor.setValue(applyValue); this.currentCellEditor = cellEditor; view.reOnDeferOnBlur(); this.selectionModel.lock(); this.isEdit = true; } }, onBlurStopEditor: function(e) { this.stopEditor(true); }, /** * @description edit 상태로 종료하는 메소드 * @method stopEditor * @param {Boolean} isApply 종료시 dataSet에 반영 여부 * @return void */ stopEditor : function(isApply) { if(this.isEdit === false || this.editable == false) return; this.applyValue(isApply, true); this.isEdit = false; this.currentCellEditor = null; return true; }, /** * @description editor한 값을 반영하는 메소드 * @method applyValue * protected * @param {Boolean} isApply 종료시 dataSet에 반영 여부 * @param {Boolean} isStopEditor Editor를 stop할지 여부 * @return void */ applyValue: function(isApply, isStopEditor) { var row = this.currentRow, col = this.currentCol; var view = this.getView(); var columnModel = view.getColumnModel(); var column = columnModel.getColumnAt(col); if (column && column.isEditable() == true) { columnModel.editors = columnModel.editors || {}; var record = view.getDataSet().getAt(row); var editorId = column.getId(); var customEditor = column.customEditor; var cellEditor = null; var editorType = null; if(customEditor === true) { var customEditorField = columnModel.customEditorField; editorType = record.get(customEditorField) || record.getAttribute(customEditorField); cellEditor = columnModel.editors[editorType || editorId]; } else { cellEditor = columnModel.editors[editorId]; } if(!DU.isUndefined(cellEditor)) { if(cellEditor.isShow()) { if(isApply === true && cellEditor.editor.fieldObject === true) { if(record != null) { var val = null; val = cellEditor.editor.getValue(); if(DU.isEmpty(val) && !DU.isUndefined(this.emptyValue)) val = this.emptyValue; if(column.type == 'number' && typeof val == 'string') { val = (val == '') ? 0 : parseFloat(val, 10); } record.set(column.field, val); cellEditor.editor.setValue(undefined); } } if(isStopEditor) cellEditor.hide(); } } } }, /** * @description grid에서 focus되어야 할 위치 지정 메소드 * @protected * @method focusRow * @return void */ focusRow : function() { var gridPanel = this; var sm = gridPanel.getSelectionModel(); gridPanel.getView().onCellSelect(sm.oldRow, sm.oldCell); gridPanel.getView().focusRow(sm.oldRow); }, /** * @description select model을 리턴하는 메소드 * @method getSelectionModel * @return {DU.widget.LSelectModel} */ getSelectionModel : function() { if(this.selectionModel == null) { this.selectionModel = new DU.widget.LCellSelectionModel(); } return this.selectionModel; }, /** * @description 객체의 editable 값을 셋팅하는 메소드 * @method setEditable * @param {Boolean} isEditable editable값 * @return {void} */ setEditable : function(isEditable) { this.editable = editable; }, /** * @description 객체의 editable값을 리턴하는 메소드 * @method isEditable * @return {Boolean} */ isEditable : function() { return this.editable; }, /** * @description gridview를 리턴하는 메소드 * @method getView * @return {DU.widget.LGridView} */ getView : function() { if(this.view == null) { this.view = new DU.widget.LBufferGridView(this.viewConfig); var me = this; var canBlurDelegate = function(e) { if(me.isEdit == true) return me.currentCellEditor.editor.canBlur.call(me.currentCellEditor.editor, e); }; this.view.canBlur = canBlurDelegate; var getRenderRowClassDelegate = function(css, row, record){ css.push(me.CLASS_GRID_ROW_EDITABLE); return css; } this.view.getRenderRowClass = getRenderRowClassDelegate; var getRenderCellClassDelegate = function(css, row, i, record) { var column = me.columnModel.getColumnAt(i); if(column.isEditable()) { css.push(me.CLASS_GRID_CELL_EDITABLE); } return css; } this.view.getRenderCellClass = getRenderCellClassDelegate; } return this.view; } }); })(); /** * @description LEditorPanel * @module widget_grid * @title LEditorPanel * @requires DU */ DU.namespace("DU.widget"); (function() { /** * @description LEditorPanel * @namespace DU.widget * @class LEditorPanel * @extends DU.widget.LPanel * @constructor LEditorPanel * @param {Object} oConfig The intial LEditorPanel. */ DU.widget.LEditorPanel = function(oConfig) { var config = oConfig || {}; DU.applyIf(config, { appendtodocumentbody:true, visible:false, draggable:false, underlay:'', close:false }); DU.widget.LEditorPanel.superclass.constructor.call(this, DU.id(), config); DU.applyObject(this, config, true); }; DU.applyObject(DU.widget.LEditorPanel, { /*************field member***********/ //*********CSS Class CLASS_EDITOR_PANEL : "L-editor-panel" }); var Dom = DU.util.LDom; var Ev = DU.util.LEvent; var GV = DU.widget.LGridView; var EP = DU.widget.LEditorPanel; DU.extend(DU.widget.LEditorPanel, DU.widget.LPanel, { /** * @description editor 속성 * @config editor * @type {Object} * @default null */ /** * @description editor 속성 * @property editor * @private * @type {Object} */ editor: null, /** * @description column 속성 * @config otype * @type {DU.widget.LColumn} * @default null */ /** * @description column 속성 * @property otype * @private * @type {DU.widget.LColumn} */ column:null, /** * @description grid view 속성 * @property view * @private * @type {DU.widget.LGridView} */ view:null, /** * @description 객체를 Config정보를 초기화하는 메소드 * @method initDefaultConfig * @protected * @return void */ initDefaultConfig: function () { DU.widget.LEditorPanel.superclass.initDefaultConfig.call(this); }, /** * @description 객체를 초기화하는 메소드 * @method init * @private * @param {Object} oConfig 환경정보 객체 * @return void */ init: function(el, userConfig){ DU.widget.LEditorPanel.superclass.init.call(this, el/*, userConfig*/); this.beforeInitEvent.fire(DU.widget.LEditorPanel); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.setBody(""); this.initEvent.fire(DU.widget.LEditorPanel); }, /** * override 구현시 사용자 이벤트 초기화 메소드 * @method initEvents */ initEvents: function(){ DU.widget.LEditorPanel.superclass.initEvents.call(this); }, /** * @description render후 호출되는 메소드 * @method afterRender * @protected * @param {HTMLElement} container 부모 객체 * @return void */ afterRender : function(container) { this.cfg.setProperty("effect", false); this.cfg.setProperty("monitorresize", true); //this.cfg.setProperty("autofillheight", true); this.cfg.setProperty("close", false); this.cfg.setProperty("draggable", false); this.cfg.setProperty("dragonly", false); this.cfg.setProperty("underlay", ''); var el = DU.get(this.element); el.addClass(EP.CLASS_EDITOR_PANEL); var editor = this.column.getEditor(); editor.render(this.body); editor.on("keydown", DU.util.LEvent.stopPropagation); editor.on("keypress", DU.util.LEvent.stopPropagation); this.el = el; }, /** * @description editor의 region값을 셋팅하는 메소드 * @method setRegion * @param {DU.util.LRegion} region region값 * @return {void} */ setRegion : function(region) { var view = this.view; var editor = this.column.getEditor(); this.el.setRegion(region); var width = region.right - region.left; this.el.setWidth(width); editor.setWidth(width - 4); var height = region.bottom - region.top; this.el.setHeight(height); if(editor.setHeight) editor.setHeight(height - 4); }, /** * @description editor의 show 여부를 리턴하는 메소드 * @method isShow * @return {Boolean} */ isShow : function() { return this.el.isShow(); }, /** * @description editor를 출력하는 메소드 * @method show * @return {void} */ show : function() { this.el.show(); this.el.removeClass('L-hidden'); var editor = this.column.getEditor(); //editor.show(); if(!this.editorFocusTask) { var me = this; this.editorFocusTask = new DU.util.LDelayedTask(function() { editor.focus(); this.editorFocusTask = null; }, this); this.editorFocusTask.delay(50); } }, /** * @description editor를 숨기는 메소드 * @method hide * @return {void} */ hide : function() { //var editor = this.column.getEditor(); //editor.hide(); this.el.hide(); this.el.addClass('L-hidden'); } }); })(); /** * @description LBufferGridView 성능을 위해 보이는 부분만 rendering하는 grid, ie, ff만 지원. 나머지 browser는 테스트 필요. * @module widget_grid * @title LBufferGridView * @requires DU.widget.LGridView */ DU.namespace("DU.widget"); (function() { var Dom = DU.util.LDom; var Ev = DU.util.LEvent; var GV = DU.widget.LGridView; /** * @description LBufferGridView 성능을 위해 보이는 부분만 rendering하는 grid * @namespace DU.widget * @class LBufferGridView * @extends DU.widget.LGridView * @constructor LBufferGridView * @param {Object} oConfig The intial LBufferGridView. */ DU.widget.LBufferGridView = function(oConfig) { //oConfig = DU.util.LDom.applyIfProperties(oConfig, '$.ext.bufferGrid'); DU.widget.LBufferGridView.superclass.constructor.call(this,oConfig); this.onScrollYDelegate = DU.util.LFunction.createDelegate(this.onScrollY, this); this.onScrollXDelegate = DU.util.LFunction.createDelegate(this.onScrollX, this); this.onDataSetRowPosChangedDelegate = DU.util.LFunction.createDelegate(this.onDataSetRowPosChanged, this); }; DU.extend(DU.widget.LBufferGridView, DU.widget.LGridView, { /** * @description DU.widget.LScroller * @property scroller * @private * @type {DU.widget.LScroller} * @default null */ scroller : null, /** * @description 보여지는 범위 계산용 내부 변수 * @property visibleRange * @private * @type {int} * @default null */ visibleRange : null, /** * @description 보여지는 범위 계산용 내부 변수, 가상 높이 * @property virtualContentHeight * @private * @type {int} * @default null */ virtualContentHeight : null, /** * @description scroll시 이동하는 pixel값 * @property scrollStep * @private * @type {int} * @default null */ scrollStep : null, /** * @description 그리드가 render시 row와 cell render event를 skip할지 여부(성능과 연관되므로 대량건 처리시는 false로 처리) * @config skipRowCellEvent * @type {Boolean} * @default true */ /** * @description 그리드가 render시 row와 cell render event를 skip할지 여부(성능과 연관되므로 대량건 처리시는 false로 처리) * @property skipRowCellEvent * @type {Boolean} * @private */ skipRowCellEvent: false, /** * @description y scroll handler * @method onScrollY * @private * @return {void} */ onScrollY : function(){ this.updateRow(); this.onBodyScroll(); }, /** * @description x scroll handler * @method onScrollX * @private * @return {void} */ onScrollX : function(){ this.onBodyScroll(); }, /** * @description row position이 변경되었을 경우 범위 내인지 검사해서 범위 밖이면 해당 범위로 이동. * @method onDataSetRowPosChanged * @private * @return {void} */ onDataSetRowPosChanged : function(e){ if(this.visibleRange){ if(this.visibleRange.start > e.row || this.visibleRange.end < e.row){ this.setRowScrollTop(e.row); } } }, /** * @description auto width의 경우 panel width가 조정될 경우 재계산 * @method onWidthResize * @protected * @return {void} */ onWidthResize : function(e){ DU.widget.LBufferGridView.superclass.updateSizes.call(this,e); if(this.scroller){ this.scroller.onResize(); } }, /** * @description column resize하기 * @method onColumnResize * @private * @param {Object} e 이벤트 객체 * @return {void} */ onColumnResize: function(e) { DU.widget.LBufferGridView.superclass.onColumnResize.call(this,e); if(this.scroller){ this.scroller.onResize(); } }, /** * @description grid의 height 재설정하기 * @method _setHeight * @protected * @return {void} */ _setHeight : function(type, args, obj){ DU.widget.LBufferGridView.superclass._setHeight.call(this,type, args, obj); if(this.scroller){ this.scroller.onResize(); } }, /** * @description grid의 width 재설정하기 * @method _setWidth * @protected * @return {void} */ _setWidth : function(type, args, obj){ DU.widget.LBufferGridView.superclass._setWidth.call(this,type, args, obj); if(this.scroller){ this.scroller.onResize(); } }, /** * @description header의 scroll위치를 변경한다. * @method syncHeaderScroll * @protected * @return {void} */ syncHeaderScroll : function(){ this.headerEl.dom.scrollLeft = this.scroller.getScrollLeft(); this.headerEl.dom.scrollLeft = this.scroller.getScrollLeft(); }, /** * @description scroll 관련, buffergrid의 경우 body도 맞추어야 한다. * @method syncBodyScroll * @protected * @return {void} */ syncBodyScroll : function(){ if(this.scroller) this.scroller.onResize(); }, /** * @description Scroller를 생성한다. * @protected * @method makeScroll * @param {Boolean} initScroll * @return {void} */ makeScroll : function(initScroll){ var rowHeight = this.getRowHeight(); this.scrollStep = this.scrollStep ? this.scrollStep : rowHeight; var virtualContentHeight = this.dataSet.getCount() * rowHeight; //scroll 위치 초기화 if (this.scroller) { if(initScroll) this.scroller.initScroll(); if(this.virtualContentHeight != virtualContentHeight) this.scroller.setVirtualContentHeight(virtualContentHeight); } else { this.scroller = new DU.widget.LScroller({ scroller: this.scrollerEl, scrollStep: this.scrollStep, virtualContentHeight: virtualContentHeight }); this.scroller.on("scrollY", this.onScrollYDelegate); this.scroller.on("scrollX", this.onScrollXDelegate); this.scroller.render(); } this.virtualContentHeight = virtualContentHeight; }, /** * @description rendering * @method doRender * @protected * @return {void} */ doRender: function(appendToNode) { DU.widget.LBufferGridView.superclass.doRender.call(this,appendToNode); this.dataSet.on("rowPosChanged",this.onDataSetRowPosChangedDelegate); }, /** * @description body content rendering * @private * @method doRenderData * @return {void} */ doRenderData : function(){ //행높이를 알기 위해서 두번 그린다. this.renderBody(this.getRenderBody(true),{ignoreEvent : true}); DU.widget.LBufferGridView.superclass.doRenderData.call(this); this.makeScroll(true); }, /** * @description create,delete에 따라서 전체행 다시 그리기. * @private * @method redoRenderData * @return {void} */ redoRenderData : function(){ DU.widget.LBufferGridView.superclass.doRenderData.call(this); this.makeScroll(); }, /** * @description override getRenderBody * @private * @method getRenderBody * @return {String} */ getRenderBody: function(checkRowHeight) { //행높이를 알기 위해서 두번 그린다. var ts = this.templates || {}; var rowCount = this.dataSet.getCount(); var rows = ""; this.visibleRange = this.getVisibleRange(); if (this.visibleRange) { //행높이 측정용 if (checkRowHeight === true) { var record = this.dataSet.getAt(0); rows = this.getRenderRow(0, record, rowCount); } else { for (var row = this.visibleRange.start; row < this.visibleRange.end + 1; row++) { var record = this.dataSet.getAt(row); rows += this.getRenderRow(row, record, rowCount); } } } return ts.body.apply({ rows: rows }); }, /** * @description body content rendering * @method renderBody * @param {String} bodyHtml body rendering한 html * @param {Object} option [optional] 환경정보 객체 * @protected * @return {void} */ renderBody: function(bodyHtml,option) { //행높이를 알기 위해서 두번 그린다. 이때 event를 발생시키지 않기 위해서 option을 둔다. option = option || {}; this.bodyEl.dom.innerHTML = ""; this.bodyEl.dom.innerHTML = bodyHtml; if (option.ignoreEvent !== true) { this.bodyEl.on("mouseover", this.onBodyMouseOver, this, true); this.bodyEl.on("mouseout", this.onBodyMouseOut, this, true); } this.doEmptyDataMessage(); if(option.ignoreEvent !== true) { this.renderBodyEvent.fire(); } }, /** * @description 행높이 return * @private * @method getRowHeight * @return {int} */ getRowHeight : function(){ //border를 포함한 값 var rows = this.getRows(); var height = 30;//임의값 의미없음. if (rows.length > 0) height = DU.get(rows[0]).getHeight(); return height; }, /** * @description 보이는 행수 return * @private * @method getVisibleRowCount * @return {int} */ getVisibleRowCount : function(){ var height = this.scrollerEl.getHeight(); this.visibleRowCount = (height < 1) ? 0 : Math.ceil(height / this.getRowHeight()); //DU.log("height:" + height + ",row height:" + this.getRowHeight() + ",visible row count:" + this.visibleRowCount); return this.visibleRowCount; }, /** * @description rendering해야할 행 시작 index, 종료 index 계산후 return * @private * @method getVisibleRange * @return {object} start, end */ getVisibleRange : function(){ var top = this.scroller ? this.scroller.getScrollTop() : 0; var rowCount = this.dataSet.getCount(); var startIndex = 0; var endIndex = 0; var visibleRange = null; var visibleRowCount = null; if (rowCount > 0) { visibleRowCount = this.getVisibleRowCount(); startIndex = (top == 0 ? 0 : Math.floor(top / this.getRowHeight())); endIndex = (visibleRowCount == 0 ? startIndex : startIndex + visibleRowCount - 1); if(endIndex >= rowCount){ startIndex = rowCount - visibleRowCount; startIndex = startIndex > -1 ? startIndex : 0; endIndex = rowCount -1; } visibleRange = {start:startIndex, end:endIndex}; } else { visibleRange = null; } this.visibleRange = visibleRange; return visibleRange; }, /** * @description DataSet row에 해당하는 곳으로 scroll이동하기 * @public * @method setRowScrollTop * @return {void} */ setRowScrollTop : function(row){ var height = this.getRowHeight(); var scrollTop = row * height; //DU.log("행인덱스 : " + row + ",scrollTop : " + scrollTop); this.scroller.setScrollTop(scrollTop); }, /** * @description scroll 관련, 신규 또는 변경된 행으로 scroll 이동하기 위한 좌표 return * @method _moveBodyScroll * @protected * @param {string|HTMLElement} cellDom * @return {Array} */ _moveBodyScroll : function(cellDom){ var scrollerEl = this.scroller.getScrollerEl(); var targetEl = DU.get(cellDom); var topLeft = scrollerEl.getVisibleScrollXY(targetEl); scrollerEl.moveScroll(cellDom,false);//var xy = this.scroller.setScrollLeft(topLeft.left); return targetEl.getXY(); }, /** * @description 안보이는 행 삭제 및 보이는 행 생성의 timing 조절 * @private * @method updateRow * @return {void} */ updateRow : function(){ this.doUpdateRow(); }, /** * @description override getScrollerEl => Editor에 의해 마지막 가린줄 클릭할 경우 scroller.el이 scroll되는것을 방지. * @method getScrollerEl * @public * @return {DU.LElement} */ getScrollerEl : function() { return this.scroller.scrollerEl; }, /** * @description override getRow * @method getRow * @public * @param {int} row row index * @return {HTMLElement} */ getRow : function(row) { row = this.getVisibleRow(row); return row == null ? row : this.getRows()[row]; }, /** * @description 실제 dom으로 출력된 행인지 점검하고 출력된 행이면 실제 dom상의 index return * @method getVisibleRow * @public * @param {Int} row row index * @return {Int} */ getVisibleRow : function(row){ if(!this.visibleRange) return null; row = row - this.visibleRange.start; if(row < 0) return null; return row; }, /** * @description dataSet의 add 이벤트 발생시 호출되는 메소드 * @method onAddData * @private * @param {Object} e Event 객체 * @return void */ onAddData: function(e) { DU.widget.LBufferGridView.superclass.onAddData.call(this, e); this.redoRenderData(); }, /** * @description dataSet의 remove 이벤트 발생시 호출되는 메소드 * @method onRemoveData * @private * @param {Object} e Event 객체 * @return void */ onRemoveData: function(e) { DU.widget.LBufferGridView.superclass.onRemoveData.call(this, e); this.redoRenderData(); }, /** * @description dataSet의 undo 이벤트 발생시 호출되는 메소드 * @method onUndoData * @private * @param {Object} e Event 객체 * @return void */ onUndoData: function(e) { DU.widget.LBufferGridView.superclass.onUndoData.call(this, e); this.redoRenderData(); }, /** * @description 안보이는 행 삭제 및 보이는 행 생성 * @private * @method doUpdateRow * @return {void} */ doUpdateRow : function(){ //성능을 위해 dom 직접 사용 this.visibleRange = this.getVisibleRange(); if(!this.visibleRange) return; var row = this.visibleRange.start; if (this.oldStart != row) { var gridRows = this.bodyEl.dom.childNodes; var contentWidth = this.columnModel.getTotalWidth(true); var record = null; var rowCount = this.dataSet.getCount(); for (var i = 0; i < gridRows.length; i++) { record = this.dataSet.getAt(row); gridRows[i].className = this.getRenderRowClassName(row, record, rowCount); gridRows[i].innerHTML = this.getRenderRowBody(row, record, contentWidth); row++; } //DU.log("row dom count : " + gridRows.length + ",row count : " + rowCount + ",start : " + this.visibleRange.start + ",end : " + this.visibleRange.end); this.oldStart = this.visibleRange.start; } } }); })(); /** * @description button의 code값과 display값을 분리하여 처리하는 객체 * @namespace DU.widget * @class LEditButtonColumn * @extends DU.widget.LStaticColumn * @constructor * @param oConfigs {Object} Object literal of definitions. */ DU.widget.LEditButtonColumn = function(oConfigs) { var config = oConfigs || {}; DU.widget.LEditButtonColumn.superclass.constructor.call(this, oConfigs); /** * @description Column renderer 속성 * @property renderer * @private * @type {Function} */ this.renderer = this.buttonRenderer(config.editor); }; DU.extend(DU.widget.LEditButtonColumn, DU.widget.LTriggerColumn, { /** * @description ButtonColumn을 renderer하는 메소드 * @method buttonRenderer * @param {DU.widget.LButton} button button 객체 * @return {String} */ buttonRenderer : function(button) { var displayField = this.displayField; return function(val, p, record, row, i) { val = (DU.isEmpty(val)) ? ' ' : val; return ' '; } } }); /** * @description LPager * @module widget_grid * @title LPager * @requires DU.widget.LUIComponent */ DU.namespace("DU.widget"); (function(){ var Dom = DU.util.LDom; /** * @description LPager * @namespace DU.widget * @class LPager * @extends DU.widget.LUIComponent * @constructor LPager * @param {Object} oConfig The intial LPager. */ DU.widget.LPager = function(oConfig){ var config = oConfig || {}; config = DU.util.LDom.applyIfProperties(config, '$.ext.pager'); if (config.gridPanel) { config.gridView = config.gridPanel.getView(); config.dataSet = config.gridView.getDataSet(); } DU.applyObject(this, config, true); /** * @description page number 선택으로 dataset이 load된후 발생하는 event * @event changePage * @param {int} viewPageNumber 이동된 page 번호 */ this.changedPageEvent = this.createEvent('changedPage'); /** * @description page number 선택시 발생하는 event * @event changedPageNmber * @param {int} viewPageNumber 이동할 page 번호 */ this.changedPageNumberEvent = this.createEvent('changedPageNumber'); this.onLoadDataSetDelegate = DU.util.LFunction.createDelegate(this.onLoadDataSet, this); this.onSortFieldDelegate = DU.util.LFunction.createDelegate(this.onSortField, this); this.onDataChangedDelegate = DU.util.LFunction.createDelegate(this.onDataChanged, this); DU.widget.LPager.superclass.constructor.call(this); } DU.extend(DU.widget.LPager, DU.widget.LUIComponent, { /** * @description 현재 page number * @property viewPageNumber * @type {int} * @default 1 */ viewPageNumber: 1, /** * @description 한 page에 보일 행 수 * @property pageSize * @type {int} * @default 10 */ pageSize: 10, /** * @description 한번에 보여질 page group size * @property pageGroupSize * @type {int} * @default 10 */ pageGroupSize: 10, /** * @description 총 행수 * @property pageGroupSize * @type {int} * @default 0 */ totalCount: 0, /** * @description 총 page수 * @property pageCount * @type {int} * @private * @default 0 */ pageCount: 0, /** * @description 총 page group수 * @property pageGroupCount * @type {int} * @private * @default 0 */ pageGroupCount: 0, /** * @description 현재 group의 시작 page번호 * @property startPageNumber * @type {int} * @private * @default 1 */ startPageNumber: 1, /** * @description 현재 group 번호 * @property pageGroupNumber * @type {int} * @private * @default 1 */ pageGroupNumber: 1, /** * @description page번호는 기본적으로 숫자이지만 itemRenderer 함수를 정의해서 변경할 수 있다. 인자는 pageNumber가 넘어온다. * @property itemRenderer * @type {function} * @default null */ itemRenderer: null, /** * @description 페이지 구분자로 문자를 사용할 경우 문자 기술 * @property itemDividerText * @type {string} */ itemDividerText: " ", /** * @description 첫페이지 이동 표시에 문자를 사용할 경우 문자 기술 * @property firstPageText * @type {string} */ firstPageText: " ", /** * @description 이전 페이지 그룹 이동 표시에 문자를 사용할 경우 문자 기술 * @property prevPageGroupText * @type {string} */ prevPageGroupText: " ", /** * @description 이전 페이지 이동 표시에 문자를 사용할 경우 문자 기술 * @property prevPageText * @type {string} */ prevPageText: " ", /** * @description 다음 페이지 이동 표시에 문자를 사용할 경우 문자 기술 * @property nextPageText * @type {string} */ nextPageText: " ", /** * @description 다음 페이지 그룹 이동 표시에 문자를 사용할 경우 문자 기술 * @property nextPageGroupText * @type {string} */ nextPageGroupText: " ", /** * @description 마지막 페이지 이동 표시에 문자를 사용할 경우 문자 기술 * @property lastPageText * @type {string} */ lastPageText: " ", /** * @description 넓이 지정, 기본값 100% * @property width * @type {int} * @default null */ width: null, /** * @description 높이 지정, 기본값 24 * @property height * @type {int} * @default 30 */ height: 30, /** * @description paging dataset * @property dataSet * @type {DU.widget.LDataSet} * @default null */ dataSet: null, /** * @description 첫페이지 마지막 페이지 표시에 페이지 수 링크 표시 여부 * @property showPageCount * @type {boolean} * @default true */ showPageCount: true, /** * @description 페이지 이동시 page size에 대한 request name명, request후 제거됨, default값은 devOn것 사용 * @property pageSizeFieldName * @type {string} * @default PAGE_INDEX.NUMBER_OF_ROWS_OF_PAGE */ pageSizeFieldName: "NUMBER_OF_ROWS_OF_PAGE", /** * @description 페이지 이동시 이동할 page number에 대한 request name명, request후 제거됨, default값은 pageNumber * @property viewPageNumberFieldName * @type {string} * @default pageNumber */ viewPageNumberFieldName: "pageNumber", /** * @description 페이지 이동시 이동할 page에 대한 시작 행번호 request name명, devOn에서 필요해서 추가, default는 targetRow * @property viewPageNumberFieldName * @type {string} * @default pageNumber */ viewPageStartRowIndexFieldName: "targetRow", /** * @description sort field request name * @property sortFieldName * @type {string} * @default sortField */ sortFieldName: "sortField", /** * @description sort direction request name asc/desc * @property sortDirFieldName * @type {string} * @default sortDir */ sortDirFieldName: "sortDir", /** * @description sorting관련 정보 담을 field명, devOn의 경우는 "devonOrderBy" * @property sortQueryFieldName * @type {string} * @default devonOrderBy */ sortQueryFieldName: "devonOrderBy", /** * @description sort 정보등을 알아내기 위한것. * @property gridView * @type {DU.widget.LGridView} * @default null */ gridView: null, /** * @description sort 정보등을 알아내기 위한것. * @property gridPanel * @type {DU.widget.LGridPanel} * @default null */ gridPanel: null, /** * @description gridview가 있을 경우 gridpanel footer에 pager를 넣을지 여부 * @property addingGridFooter * @type {boolean} * @default true */ addingGridFooter: true, /** * @description pager에 의해 dataset이 load 되었는지 여부, pager에 의해 load되지 않았다면 1page로 이동한다. * @property loadDataSetByPager * @type {boolean} * @default false */ loadDataSetByPager : false, /** * @description 첫번째 load인지 검사 flag, 최초 load 이후에는 false가 된다. * @property isFirstLoading * @type {boolean} * @default true */ isFirstLoading : true, /************CSS Class Name**********/ CLASS_PAGER: "L-pager", CLASS_PAGER_WRAP: "L-pager-wrap", CLASS_PAGER_SELECTED: "L-pager-selected", CLASS_PAGER_FIRST: "L-pager-first", CLASS_PAGER_FIRST_WRAP: "L-pager-first-wrap", CLASS_PAGER_PREV_GROUP: "L-pager-prev-group", CLASS_PAGER_PREV_GROUP_WRAP: "L-pager-prev-group-wrap", CLASS_PAGER_PREV_WRAP: "L-pager-prev-wrap", CLASS_PAGER_PREV: "L-pager-prev", CLASS_PAGER_NEXT: "L-pager-next", CLASS_PAGER_NEXT_WRAP: "L-pager-next-wrap", CLASS_PAGER_NEXT_GROUP: "L-pager-next-group", CLASS_PAGER_NEXT_GROUP_WRAP: "L-pager-next-group-wrap", CLASS_PAGER_LAST: "L-pager-last", CLASS_PAGER_LAST_WRAP: "L-pager-last-wrap", CLASS_PAGER_ITEMS: "L-pager-items", CLASS_PAGER_ITEMS_WRAP: "L-pager-items-wrap", CLASS_PAGER_ITEM: "L-pager-item", CLASS_PAGER_ITEM_WRAP: "L-pager-item-wrap", CLASS_PAGER_ITEM_DIVIDER: "L-pager-item-divider", CLASS_PAGER_ITEM_DIVIDER_WRAP: "L-pager-item-divider-wrap", CLASS_HIDE_VISIBILITY : "L-hide-visibility", /** * @description page관련 숫자 계산 * @method computePage * @private * @param {int} viewPageNumber 현재 page번호 * @return void */ computePage: function(viewPageNumber){ if (this.dataSet != null) { this.setTotalCount(this.dataSet.getTotalCount(), false); } this.viewPageNumber = viewPageNumber || this.viewPageNumber || 1; this.pageCount = Math.floor(this.totalCount / this.pageSize) + 1; //행수가 딱 맞으면 -1 if (this.totalCount % this.pageSize == 0) { if (this.pageCount > 1) { this.pageCount = this.pageCount - 1; } } var boundary = 0; //경계부분이면 1을 빼준다. if (this.viewPageNumber % this.pageGroupSize == 0) { boundary = -1; } this.startPageNumber = (Math.floor(this.viewPageNumber / this.pageGroupSize) + boundary) * this.pageGroupSize + 1; this.pageGroupNumber = Math.floor(this.viewPageNumber / this.pageGroupSize) + 1 + boundary; this.pageGroupCount = Math.ceil(this.pageCount / this.pageGroupSize); }, /** * @description template 생성 * @method createTemplate * @protected * @return void */ createTemplate: function(){ var ts = this.templates || {}; if (!ts.master) { ts.master = new DU.LTemplate('{firstPage} | ',
'{prevPageGroup} | ',
'{prevPage} | ',
'{items} | ',
'{nextPage} | ',
'{nextPageGroup} | ',
'{lastPage} | ', '