/**
* DataTable for JavaScript Data Editing
* jQuery Plugin
*
* jQuery 1.4 or higher
* jQueryUI 1.8 or higher
*
* @version 1.0
* @author bitofsky@neowiz.com 2012.07.13
* @encoding UTF-8
*/
// http://glat.info/jscheck/
/*global $, jQuery, confirm, console, alert, JSON */
// 명료한 Javascript 문법을 사용 한다.
"use strict";
(function($, window, document){
var DEFAULT_OPTION = {
/**
* @var {boolean} option.modifier=false 데이터 수정 모드 활성화 여부
*/
'modifier' : false,
/**
* @var {array} option.showPath=[] 보여줄 데이터 경로 명시. 명시된 경로의 데이터 노출.
*/
'showPath' : [],
/**
* @var {array} option.hidePath=[] 보여주지 않을 데이터 경로 명시. 명시된 경로의 데이터 미노출
*/
'hidePath' : [],
/**
* @var {string} option.editEvent='dblclick' 셀 에디터 이벤트 설정
*/
'editEvent' : 'dblclick',
/**
* @var {array} option.editAllowPath=[] 수정할 데이터 경로 명시. 명시된 경로의 데이터에만 수정 기능이 동작.
*/
'editAllowPath': [],
/**
* @var {array} option.editDenyPath=[] 수정을 금지할 데이터 경로 명시. 명시된 경로의 데이터에는 수정 기능이 미동작.
*/
'editDenyPath' : [],
/**
* @var {plainObject} option.pathName={} 경로의 노출 이름을 명시. Key=경로, Value=이름
*/
'pathName' : {},
/**
* @var {number} option.depth=0 몇 depth 까지 기본 노출할지에 대한 설정. 0은 모두 노출
*/
'depth' : 0,
/**
* @var {string} option.expandLabel='Detail'
*/
'expandLabel' : 'Detail',
/**
* @var {string} option.title=null 테이블 상단 제목 caption
*/
'title' : null,
/**
* @var {boolean} option.keyEdit=false Object/Array 의 서브키를 추가 또는 삭제하는 기능 사용 여부
*/
'keyEdit' : false,
/**
* @var {boolean} option.html=true String 값으로 들어온 태그를 HTML 로 사용할지 그냥 태그 자체를 보여줄지 설정
*/
'html' : true,
/**
* @var {boolean} option.allowElement 데이터 중 Element 가 있는 경우 처리 방법. true=append(), false=toString()
*/
'allowElement' : false,
'css' : {
'table' : {
'border-collapse': 'separate',
'border-spacing' : '5px 0',
'width' : '100%'
},
'key' : {
'padding' : '0 5px 0 5px',
'vertical-align' : 'top',
'text-align' : 'right',
'width' : '1px',
'white-space' : 'nowrap'
}
}
};
var TAG = {
table : '
',
thead : '',
tbody : '',
tr : '
',
td : ' | ',
div : '',
text : '',
textarea : '',
select : '',
option : '',
number : '',
button : '',
caption : ''
};
$.fn.dataTable = function(){
return this.append( $.dataTable.apply(null, arguments) );
};
/**
* ADM4 DataTable - bitofsky@neowiz.com 2012.07.11 Renewal
*
* @param {plainObject|array} data
* @option {plainObject} option=DEFAULT_OPTION
*/
$.dataTable = function( data, option, currentDepth, currentPath ){
// dataTable 은 PlainObject 또는 Array 가 아니면 구성을 할 수 없다.
if( !checkTableType( data ) ) return null;
/**
* @var opt DEFAULT_OPTION
*/
var opt = $.extend(true, {}, DEFAULT_OPTION, option);
currentDepth = +currentDepth || 0;
currentPath = currentPath || '';
var table = $( TAG.table ).addClass('ui-tabs ui-widget ui-widget-content ui-corner-all').css( opt.css.table ),
thead = $( TAG.thead ),
tbody = $( TAG.tbody );
if( !opt.depth || opt.depth > currentDepth ){
renderTable();
}
else{
var tr = $( TAG.tr ).appendTo( tbody ),
td = $( TAG.td ).appendTo( tr );
$( TAG.button ).text( opt.expandLabel ).appendTo( td ).click(function(){
renderTable();
});
}
return table.append( thead, tbody );
/**
* DataTable 을 실제로 그리는 기능
*/
function renderTable(){
$( thead ).add( tbody ).empty();
if( opt.title && currentDepth == 0 ){
$( TAG.caption ).text( opt.title ).addClass('ui-state-default ui-corner-all').appendTo( table );
}
// Key 추가 기능 버튼
if( opt.modifier && opt.keyEdit ){
$( TAG.tr ).append(
$( TAG.td ).attr('colspan', 2).append( $( TAG.button ).text('Add Key').button({icons:{primary:'ui-icon-plusthick'}}).click( fn_addKey ) )
).appendTo( thead );
}
// 각 Key 별 Row 처리
for( var key in data ){
// opt.showPath 가 명시된 상태에서 현재 Key 가 리스트에 없는 경우 노출 무시
if( checkPath('showPath', key) === false ) continue;
// opt.hidePath 가 명시된 상태에서 현재 Key 가 리스트에 있는 경우 노출 무시
if( checkPath('hidePath', key) === true ) continue;
var name = getKeyName( key );
var tr_line = $( TAG.tr ).appendTo( tbody ),
td_key = $( TAG.td ).text( name ).appendTo( tr_line ).addClass('ui-state-default ui-corner-all').css( opt.css.key ),
td_value = $( TAG.td ).appendTo( tr_line );
// value 랜더링
drawCell( key, td_key, td_value );
}
}
/**
* Data Key 추가 팝업
*/
function fn_addKey(){
var self = this,
i_key = null,
d_pop = $( TAG.div ),
ta_value = $( TAG.textarea ).width('100%');
if( $.type( data ) == 'array' )
i_key = $( TAG.number ).val( data.length );
else
i_key = $( TAG.text ).attr('required',true);
d_pop.dataTable({
'Key Name' : i_key,
'Value [Json]' : ta_value
}, {
allowElement: true
}).dialog({
title: 'Add Key',
width: 'auto',
height: 'auto',
buttons: {
'Add': function(){
if( i_key[0].checkValidity && !i_key[0].checkValidity() ) return alert( i_key[0].validationMessage );
try{
var value = JSON.parse( ta_value.val() || null );
}catch( e ){
return alert( e );
}
data[ i_key.val().trim() ] = value;
d_pop.dialog('close');
renderTable();
}
}
});
}
function fn_delKey( event ){
var key = event.data;
if( !confirm('Remove Key - ' + key + '\nContinue?') ) return;
if( $.type(data) === 'array' ) data.splice(key, 1);
else delete data[key];
renderTable();
}
/**
* 값의 유형에 따라 셀을 랜더링 한다.
* 수정 내역이 Data 에 직접 Set 되려면 참조(refference)를 유지해야 하며 이를 위해 Key 를 받아 내부에서 Data[key] 를 핸들링 함.
*
* @param {string|number} key 키 이름
* @param {jQueryObject} o_key Key TD 객체
* @param {jQueryObject} o_cell Value TD 객체
*/
function drawCell( key, o_key, o_cell ){
var value = data[key],
valueType = $.type(value);
o_key.unbind();
o_cell.empty();
// 재귀 DataTable 을 랜더링 한다.
if( checkTableType( value ) ){
o_cell.dataTable( value, option, currentDepth+1, currentPath+'.'+key );
}
// PlainObject 가 아닌 Object 는 Element 로 본다.
else if( valueType == 'object' ){
if( opt.allowElement )
o_cell.append( value );
else
o_cell.text( String(value) );
}
// 함수..
else if( valueType == 'function' ){
// 줄내림 노출등을 위해 HTML 로 보여줌..
o_cell.html( nl2br(String(value), true) );
}
// 기타 null/undefined/boolean/string/number
else{
if( opt.html )
o_cell.html( nl2br(String(value), true) );
else
$('').html( String(value).replace(/&/g,'&').replace(/');
if( whitespace ) str = str.replace(/\s/g, ' ');
return str;
}
define('jquery.datatable', ['jquery'], function(){ return $.dataTable; });
})(jQuery, this, this.document);