Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

aui-datatable-debug.js 48KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268
  1. AUI.add('aui-datatable-base', function(A) {
  2. // DataTable component is beta, over-writing buggy logic on it before they get fixed on YUI
  3. var Lang = A.Lang,
  4. compare = A.ArraySort.compare,
  5. isNumber = Lang.isNumber,
  6. isString = Lang.isString,
  7. CHANGE = 'change',
  8. CHILD_NODES = 'childNodes',
  9. COLUMNSET = 'columnset',
  10. DATA = 'data',
  11. HEADERS = 'headers',
  12. ID = 'id',
  13. RECORDSET = 'recordset',
  14. RECORDSET_CHANGE = 'recordsetChange',
  15. _HASH = '#',
  16. _SPACE = ' ';
  17. A.DataTable.Base = A.Base.create('datatable', A.DataTable.Base, [], {
  18. initializer: function() {
  19. var instance = this;
  20. instance.after(instance._uiSetRecordsetExt, instance, '_uiSetRecordset');
  21. },
  22. getCellNode: function(record, column) {
  23. var instance = this;
  24. return instance.getRowNode(record).get(CHILD_NODES).item(column.keyIndex);
  25. },
  26. getColNode: function(cell) {
  27. var instance = this;
  28. var columnset = instance.get(COLUMNSET);
  29. var index = columnset.getColumnIndex(columnset.getColumnByCell(cell));
  30. return instance._colgroupNode.get(CHILD_NODES).item(index);
  31. },
  32. getRowNode: function(record) {
  33. return A.one(_HASH+record.get(ID));
  34. },
  35. _fixPluginsUI: function() {
  36. var instance = this;
  37. var sort = instance.sort;
  38. var scroll = instance.scroll;
  39. if (sort && scroll) {
  40. scroll.syncUI();
  41. }
  42. },
  43. _uiSetRecordsetExt: function(recordset){
  44. var instance = this;
  45. instance._fixPluginsUI();
  46. }
  47. }, {});
  48. A.Column = A.Base.create('column', A.Column, [], {}, {
  49. ATTRS: {
  50. sortFn: {
  51. value: function(recA, recB, field, desc) {
  52. var sorted = compare(recA.getValue(field), recB.getValue(field), desc);
  53. if (sorted === 0) {
  54. sorted = compare(recA.get('id'), recB.get('id'), desc);
  55. }
  56. return sorted;
  57. }
  58. }
  59. }
  60. });
  61. A.Columnset = A.Base.create('columnset', A.Columnset, [], {
  62. getColumn: function(i) {
  63. var instance = this;
  64. if (isString(i)) {
  65. return this.idHash[i];
  66. }
  67. else if (isNumber(i)) {
  68. return instance.keys[i];
  69. }
  70. return null;
  71. },
  72. getColumnByCell: function(cell) {
  73. var instance = this;
  74. var dataHeaderId = cell.getAttribute(HEADERS).split(_SPACE).pop() || cell.get(ID);
  75. return instance.getColumn(dataHeaderId);
  76. },
  77. getColumnIndex: function(column) {
  78. return column.keyIndex;
  79. },
  80. getLength: function() {
  81. var instance = this;
  82. return instance.keys.length;
  83. },
  84. _setDefinitions: function(val) {
  85. return val;
  86. }
  87. }, {});
  88. A.Recordset = A.Base.create('recordset', A.Recordset, [], {
  89. getRecordByRow: function(row) {
  90. var instance = this;
  91. return instance.getRecord(row.get(ID));
  92. },
  93. getRecordIndex: function(record) {
  94. var instance = this;
  95. return A.Array.indexOf(instance._items, record);
  96. },
  97. updateRecordDataByKey: function(record, key, value) {
  98. var instance = this;
  99. var data = record.get(DATA);
  100. if (data) {
  101. data[key] = value;
  102. record.set(DATA, data);
  103. }
  104. instance.update(record, instance.getRecordIndex(record));
  105. }
  106. }, {});
  107. A.Plugin.RecordsetSort.prototype._defSortFn = function(event) {
  108. var instance = this;
  109. var host = instance.get("host");
  110. var items = host._items;
  111. A.Array.stableSort(
  112. items,
  113. function (a, b) {
  114. return event.sorter.call(items, a, b, event.field, event.desc);
  115. }
  116. );
  117. instance.set('lastSortProperties', event);
  118. };
  119. }, '@VERSION@' ,{requires:['aui-base','datatable','plugin'], skinnable:true});
  120. AUI.add('aui-datatable-events', function(A) {
  121. // TODO - optimize code
  122. var Lang = A.Lang,
  123. isArray = Lang.isArray,
  124. isObject = Lang.isObject,
  125. isValue = Lang.isValue,
  126. Aeach = A.Array.each,
  127. getObjectKeys = A.Object.keys,
  128. getObjectValues = A.Object.values,
  129. selectorTest = A.Selector.test,
  130. YgetClassName = A.ClassNameManager.getClassName,
  131. _toInitialCap = A.cached(function(str) {
  132. return str.substring(0, 1).toUpperCase() + str.substring(1);
  133. }),
  134. _getEvtType = A.cached(function(tagName, eventType) {
  135. return tagName + _toInitialCap(eventType.toLowerCase());
  136. }),
  137. BOUNDING_BOX = 'boundingBox',
  138. CELL = 'cell',
  139. CELL_SELECTOR = 'cellSelector',
  140. CLICK = 'click',
  141. COLUMN = 'column',
  142. DBLCLICK = 'dblclick',
  143. EVENTS = 'events',
  144. HEADER = 'header',
  145. HOST = 'host',
  146. IN_HEAD = 'inHead',
  147. KEYDOWN = 'keydown',
  148. KEYUP = 'keyup',
  149. LINER = 'liner',
  150. MOUSEDOWN = 'mousedown',
  151. MOUSEENTER = 'mouseenter',
  152. MOUSELEAVE = 'mouseleave',
  153. MOUSEUP = 'mouseup',
  154. RECORDSET = 'recordset',
  155. ROW = 'row',
  156. TABLE = 'table',
  157. TAGS = 'tags',
  158. TAG_NAME = 'tagName',
  159. TBODY = 'tbody',
  160. THEAD = 'thead',
  161. TR = 'tr',
  162. DATATABLE = 'datatable',
  163. COLUMNSET = 'columnset',
  164. _COMMA = ',',
  165. _DOT = '.',
  166. CSS_DATATABLE_LINER = YgetClassName(DATATABLE, LINER);
  167. var DataTableEvents = A.Base.create("dataTableEvents", A.Plugin.Base, [], {
  168. _bubbling: false,
  169. _handler: null,
  170. _tagsFilter: null,
  171. initializer: function(config) {
  172. var instance = this;
  173. var tags = instance.get(TAGS);
  174. instance._tagsFilter = getObjectKeys(tags).join(_COMMA);
  175. instance._initEvents();
  176. },
  177. destructor: function() {
  178. var instance = this;
  179. var handler = instance._handler;
  180. if (handler) {
  181. handler.detach();
  182. }
  183. },
  184. updateEventPayload: function(node, originalEvent) {
  185. var instance = this;
  186. var host = instance.get(HOST);
  187. var thead = host._theadNode;
  188. var inHead = node.getData(IN_HEAD);
  189. var liner = node.getData(LINER);
  190. var row = node.getData(ROW);
  191. if (!isValue(inHead)) {
  192. inHead = thead.contains(node);
  193. node.setData(IN_HEAD, inHead);
  194. }
  195. if (!isValue(liner)) {
  196. liner = node.one(_DOT+CSS_DATATABLE_LINER);
  197. node.setData(LINER, liner);
  198. }
  199. if (!isValue(row)) {
  200. row = node.ancestor(TR);
  201. node.setData(ROW, row);
  202. }
  203. return A.mix(
  204. originalEvent,
  205. {
  206. cell: node,
  207. column: host.get(COLUMNSET).getColumnByCell(node),
  208. inHead: inHead,
  209. liner: liner,
  210. originalEvent: originalEvent,
  211. row: row,
  212. record: host.get(RECORDSET).getRecordByRow(row)
  213. },
  214. true
  215. );
  216. },
  217. _filterBubble: function(target) {
  218. var instance = this;
  219. var host = instance.get(HOST);
  220. var container = host._tableNode.getDOM();
  221. var nodes = [];
  222. while (target) {
  223. var isContainer = (target === container);
  224. if (selectorTest(target, instance._tagsFilter, (isContainer ? null : container))) {
  225. nodes.push(target);
  226. }
  227. if (isContainer) {
  228. break;
  229. }
  230. target = target.parentNode;
  231. }
  232. // Adding respective col node to the nodes array in such a way
  233. // that the bubble order is: (td|th), tr, col, (tbody|thead) and table.
  234. if (nodes.length) {
  235. var column = host.getColNode(A.one(nodes[0]));
  236. if (column) {
  237. nodes.splice(2, 0, column.getDOM());
  238. }
  239. }
  240. return nodes;
  241. },
  242. _handleEvents: function(event) {
  243. var i, length;
  244. var instance = this;
  245. var host = instance.get(HOST);
  246. var tags = instance.get(TAGS);
  247. var currentTarget = event.currentTarget;
  248. var nodes = instance._filterBubble(currentTarget.getDOM());
  249. var payload = instance.updateEventPayload(currentTarget, event);
  250. instance._bubbling = true;
  251. for (i = 0, length = nodes.length; (i < length) && instance._bubbling; i++) {
  252. var node = A.one(nodes[i]);
  253. var propertyName = tags[node.get(TAG_NAME).toLowerCase()];
  254. payload.node = node;
  255. payload.property = propertyName;
  256. host.fire(
  257. _getEvtType(propertyName, event.type),
  258. payload
  259. );
  260. }
  261. },
  262. _initEvents: function() {
  263. var instance = this;
  264. var host = instance.get(HOST);
  265. var tags = instance.get(TAGS);
  266. var events = instance.get(EVENTS);
  267. var publish = {};
  268. Aeach(getObjectValues(tags), function(propertyName) {
  269. Aeach(events, function(eventType) {
  270. var newEventType = _getEvtType(propertyName, eventType);
  271. publish[newEventType] = {
  272. stoppedFn: A.bind(instance._stopBubble, instance)
  273. };
  274. });
  275. });
  276. host.publish(publish);
  277. instance._handler = host.get(BOUNDING_BOX).delegate(events, A.bind(instance._handleEvents, instance), instance.get(CELL_SELECTOR));
  278. },
  279. _stopBubble: function() {
  280. var instance = this;
  281. instance._bubbling = false;
  282. }
  283. },
  284. {
  285. NS: "events",
  286. NAME: "dataTableEvents",
  287. ATTRS: {
  288. cellSelector: {
  289. value: 'td,th',
  290. writeOnce: true
  291. },
  292. events: {
  293. validator: isArray,
  294. value: [ CLICK, DBLCLICK, KEYDOWN, KEYUP, MOUSEDOWN, MOUSEENTER, MOUSELEAVE, MOUSEUP ]
  295. },
  296. tags: {
  297. validator: isObject,
  298. value: {
  299. col: COLUMN,
  300. table: TABLE,
  301. thead: THEAD,
  302. tbody: TBODY,
  303. tr: ROW,
  304. th: HEADER,
  305. td: CELL
  306. },
  307. writeOnce: true
  308. }
  309. }
  310. });
  311. A.namespace("Plugin").DataTableEvents = DataTableEvents;
  312. }, '@VERSION@' ,{requires:['aui-datatable-base']});
  313. AUI.add('aui-datatable-edit', function(A) {
  314. var Lang = A.Lang,
  315. AArray = A.Array,
  316. AEscape = A.Escape,
  317. isArray = Lang.isArray,
  318. isBoolean = Lang.isBoolean,
  319. isFunction = Lang.isFunction,
  320. isObject = Lang.isObject,
  321. isString = Lang.isString,
  322. LString = Lang.String,
  323. _toInitialCap = A.cached(function(str) {
  324. return str.substring(0, 1).toUpperCase() + str.substring(1);
  325. }),
  326. isBaseEditor = function(val) {
  327. return (val instanceof A.BaseCellEditor);
  328. },
  329. WidgetStdMod = A.WidgetStdMod,
  330. AgetClassName = A.getClassName,
  331. ADD = 'add',
  332. ADD_OPTION = 'addOption',
  333. BASE_CELL_EDITOR = 'baseCellEditor',
  334. BOUNDING_BOX = 'boundingBox',
  335. CALENDAR = 'calendar',
  336. CANCEL = 'cancel',
  337. CELL = 'cell',
  338. CELLEDITOR = 'celleditor',
  339. CHECKBOX_CELL_EDITOR = 'checkboxCellEditor',
  340. CHECKED = 'checked',
  341. CLICK = 'click',
  342. COLUMNSET = 'columnset',
  343. CONTENT_BOX = 'contentBox',
  344. DATA = 'data',
  345. DATATABLE = 'datatable',
  346. DATE_CELL_EDITOR = 'dateCellEditor',
  347. DD = 'dd',
  348. DELETE = 'delete',
  349. DISK = 'disk',
  350. DOTTED = 'dotted',
  351. DROP_DOWN_CELL_EDITOR = 'dropDownCellEditor',
  352. EDIT = 'edit',
  353. EDITABLE = 'editable',
  354. EDITOR = 'editor',
  355. EDIT_EVENT = 'editEvent',
  356. EDIT_OPTIONS = 'editOptions',
  357. ELEMENT = 'element',
  358. ELEMENT_NAME = 'elementName',
  359. FIELD = 'field',
  360. GRIP = 'grip',
  361. HANDLE = 'handle',
  362. HIDE = 'hide',
  363. HIDE_ON_SAVE = 'hideOnSave',
  364. ICON = 'icon',
  365. ID = 'id',
  366. INIT_EDIT = 'initEdit',
  367. INIT_TOOLBAR = 'initToolbar',
  368. INIT_VALIDATOR = 'initValidator',
  369. INPUT = 'input',
  370. INPUT_FORMATTER = 'inputFormatter',
  371. KEY = 'key',
  372. LABEL = 'label',
  373. LINK = 'link',
  374. MOUSEDOWN = 'mousedown',
  375. MULTIPLE = 'multiple',
  376. NAME = 'name',
  377. OPTION = 'option',
  378. OPTIONS = 'options',
  379. OPTIONS_CELL_EDITOR = 'optionsCellEditor',
  380. OUTPUT_FORMATTER = 'outputFormatter',
  381. PENCIL = 'pencil',
  382. RADIO_CELL_EDITOR = 'radioCellEditor',
  383. RECORDS = 'records',
  384. RECORDSET = 'recordset',
  385. REMOVE = 'remove',
  386. RENDERED = 'rendered',
  387. RETURN = 'return',
  388. ROW = 'row',
  389. SAVE = 'save',
  390. SELECTED = 'selected',
  391. SELECTED_ATTR_NAME = 'selectedAttrName',
  392. SHOW_TOOLBAR = 'showToolbar',
  393. SUBMIT = 'submit',
  394. TEXT_AREA_CELL_EDITOR = 'textAreaCellEditor',
  395. TEXT_CELL_EDITOR = 'textCellEditor',
  396. TOOLBAR = 'toolbar',
  397. UNESCAPE_VALUE = 'unescapeValue',
  398. VALIDATOR = 'validator',
  399. VALUE = 'value',
  400. VERTICAL = 'vertical',
  401. VISIBLE = 'visible',
  402. WRAPPER = 'wrapper',
  403. _COMMA = ',',
  404. _DOT = '.',
  405. _EMPTY_STR = '',
  406. _HASH = '#',
  407. _NL = '\n',
  408. _SPACE = ' ',
  409. REGEX_BR = /<br\s*\/?>/gi,
  410. REGEX_NL = /[\r\n]/g,
  411. CSS_CELLEDITOR_EDIT = AgetClassName(CELLEDITOR, EDIT),
  412. CSS_CELLEDITOR_EDIT_ADD_OPTION = AgetClassName(CELLEDITOR, EDIT, ADD, OPTION),
  413. CSS_CELLEDITOR_EDIT_DD_HANDLE = AgetClassName(CELLEDITOR, EDIT, DD, HANDLE),
  414. CSS_CELLEDITOR_EDIT_DELETE_OPTION = AgetClassName(CELLEDITOR, EDIT, DELETE, OPTION),
  415. CSS_CELLEDITOR_EDIT_HIDE_OPTION = AgetClassName(CELLEDITOR, EDIT, HIDE, OPTION),
  416. CSS_CELLEDITOR_EDIT_INPUT_NAME = AgetClassName(CELLEDITOR, EDIT, INPUT, NAME),
  417. CSS_CELLEDITOR_EDIT_INPUT_VALUE = AgetClassName(CELLEDITOR, EDIT, INPUT, VALUE),
  418. CSS_CELLEDITOR_EDIT_LABEL = AgetClassName(CELLEDITOR, EDIT, LABEL),
  419. CSS_CELLEDITOR_EDIT_LINK = AgetClassName(CELLEDITOR, EDIT, LINK),
  420. CSS_CELLEDITOR_EDIT_OPTION_ROW = AgetClassName(CELLEDITOR, EDIT, OPTION, ROW),
  421. CSS_CELLEDITOR_ELEMENT = AgetClassName(CELLEDITOR, ELEMENT),
  422. CSS_CELLEDITOR_LABEL = AgetClassName(CELLEDITOR, LABEL),
  423. CSS_CELLEDITOR_OPTION = AgetClassName(CELLEDITOR, OPTION),
  424. CSS_CELLEDITOR_WRAPPER = AgetClassName(CELLEDITOR, WRAPPER),
  425. CSS_DATATABLE_EDITABLE = AgetClassName(DATATABLE, EDITABLE),
  426. CSS_ICON = AgetClassName(ICON),
  427. CSS_ICON_GRIP_DOTTED_VERTICAL = AgetClassName(ICON, GRIP, DOTTED, VERTICAL),
  428. TPL_BR = '<br/>';
  429. /**
  430. * An extension for A.DataTable.Base to support Cell Editing:
  431. *
  432. * Check the list of <a href="CellEditorSupport.html#configattributes">Configuration Attributes</a> available for
  433. * CellEditorSupport.
  434. *
  435. * @param config {Object} Object literal specifying widget configuration properties.
  436. *
  437. * @class CellEditorSupport
  438. * @constructor
  439. * @extends Base
  440. */
  441. var CellEditorSupport = function() {};
  442. CellEditorSupport.NAME = 'dataTableCellEditorSupport';
  443. CellEditorSupport.ATTRS = {
  444. editEvent: {
  445. setter: '_setEditEvent',
  446. validator: isString,
  447. value: CLICK
  448. }
  449. };
  450. A.mix(CellEditorSupport.prototype, {
  451. initializer: function() {
  452. var instance = this;
  453. instance.after({
  454. render: instance._afterRenderEditor
  455. });
  456. instance.on(instance.get(EDIT_EVENT), instance._onCellEdit);
  457. instance.after(instance._afterUiSetRecordset, instance, '_uiSetRecordset');
  458. },
  459. getCellEditor: function(record, column) {
  460. var instance = this;
  461. var columnEditor = column.get(EDITOR);
  462. var recordEditor = record.get(DATA).editor;
  463. if (columnEditor === false || recordEditor === false) {
  464. return null;
  465. }
  466. return recordEditor || columnEditor;
  467. },
  468. getRecordColumnValue: function(record, column) {
  469. return record.getValue(column.get(FIELD));
  470. },
  471. syncEditableColumnsUI: function() {
  472. var instance = this;
  473. var columnset = instance.get(COLUMNSET);
  474. var recordset = instance.get(RECORDSET);
  475. A.each(columnset.idHash, function(column) {
  476. var editor = column.get(EDITOR);
  477. if (isBaseEditor(editor)) {
  478. A.all('[headers='+column.get(ID)+']').addClass(CSS_DATATABLE_EDITABLE);
  479. }
  480. });
  481. A.each(recordset.get(RECORDS), function(record) {
  482. var editor = record.get(DATA).editor;
  483. var isBaseEditorInstance = isBaseEditor(editor);
  484. A.all(_HASH + record.get("id") + '>td').each(function(td, index) {
  485. var column = columnset.getColumn(index);
  486. if (editor === false) {
  487. td.removeClass(CSS_DATATABLE_EDITABLE);
  488. }
  489. else if (isBaseEditorInstance || (column.get(EDITOR) !== false)) {
  490. td.addClass(CSS_DATATABLE_EDITABLE);
  491. }
  492. });
  493. });
  494. },
  495. _afterUiSetRecordset: function(event) {
  496. var instance = this;
  497. instance.syncEditableColumnsUI();
  498. },
  499. _afterRenderEditor: function(event) {
  500. var instance = this;
  501. if (!instance.events) {
  502. instance.plug(A.Plugin.DataTableEvents);
  503. }
  504. },
  505. _editCell: function(event) {
  506. var instance = this;
  507. var columnset = instance.get(COLUMNSET);
  508. var recordset = instance.get(RECORDSET);
  509. var column = event.column;
  510. var record = event.record;
  511. instance.activeColumnIndex = columnset.getColumnIndex(column);
  512. instance.activeRecordIndex = recordset.getRecordIndex(record);
  513. var alignNode = event.alignNode || event.cell;
  514. var editor = instance.getCellEditor(record, column);
  515. if (isBaseEditor(editor)) {
  516. if (!editor.get(RENDERED)) {
  517. editor.on({
  518. visibleChange: A.bind(instance._onEditorVisibleChange, instance),
  519. save: A.bind(instance._onEditorSave, instance)
  520. });
  521. editor.render();
  522. }
  523. editor.set(
  524. VALUE,
  525. instance.getRecordColumnValue(record, column)
  526. );
  527. editor.show().move(alignNode.getXY());
  528. }
  529. },
  530. _onCellEdit: function(event) {
  531. var instance = this;
  532. instance._editCell(event);
  533. },
  534. _onEditorVisibleChange: function(event) {
  535. var instance = this;
  536. var editor = event.currentTarget;
  537. var selection = instance.selection;
  538. if (selection) {
  539. var activeRecord = selection.getActiveRecord();
  540. var activeColumn = selection.getActiveColumn();
  541. var cell = instance.getCellNode(activeRecord, activeColumn);
  542. var row = instance.getRowNode(activeRecord);
  543. if (event.newVal) {
  544. editor._syncFocus();
  545. }
  546. else {
  547. selection.select(cell, row);
  548. }
  549. }
  550. },
  551. _onEditorSave: function(event) {
  552. var instance = this;
  553. var editor = event.currentTarget;
  554. var recordset = instance.get(RECORDSET);
  555. editor.set(VALUE, event.newVal);
  556. var selection = instance.selection;
  557. if (selection) {
  558. var newVal = A.Escape.html(event.newVal);
  559. recordset.updateRecordDataByKey(
  560. selection.getActiveRecord(),
  561. selection.getActiveColumn().get(KEY),
  562. newVal
  563. );
  564. }
  565. },
  566. _setEditEvent: function(val) {
  567. return CELL + _toInitialCap(val);
  568. }
  569. });
  570. A.DataTable.CellEditorSupport = CellEditorSupport;
  571. // Augment A.DataTable.Base with A.DataTable.CellEditorSupport
  572. A.DataTable.Base = A.Base.create('dataTable', A.DataTable.Base, [A.DataTable.CellEditorSupport]);
  573. /**
  574. * Abstract class BaseCellEditor.
  575. *
  576. * Check the list of <a href="BaseCellEditor.html#configattributes">Configuration Attributes</a> available for
  577. * BaseCellEditor.
  578. *
  579. * @param config {Object} Object literal specifying widget configuration properties.
  580. *
  581. * @class BaseCellEditor
  582. * @abstract
  583. * @extends A.Overlay
  584. */
  585. var BaseCellEditor = A.Component.create({
  586. NAME: BASE_CELL_EDITOR,
  587. ATTRS: {
  588. editable: {
  589. value: false,
  590. validator: isBoolean
  591. },
  592. elementName: {
  593. value: VALUE,
  594. validator: isString
  595. },
  596. footerContent: {
  597. value: _EMPTY_STR
  598. },
  599. hideOnSave: {
  600. value: true,
  601. validator: isBoolean
  602. },
  603. inputFormatter: {
  604. value: function(val) {
  605. if (isString(val)) {
  606. val = val.replace(REGEX_NL, TPL_BR);
  607. }
  608. return val;
  609. }
  610. },
  611. outputFormatter: {
  612. value: function(val) {
  613. var instance = this;
  614. if (isString(val)) {
  615. if (instance.get(UNESCAPE_VALUE)) {
  616. val = LString.unescapeEntities(val);
  617. }
  618. // console.log(val);
  619. val = val.replace(REGEX_BR, _NL);
  620. }
  621. return val;
  622. }
  623. },
  624. showToolbar: {
  625. value: true,
  626. validator: isBoolean
  627. },
  628. strings: {
  629. value: {
  630. edit: 'Edit',
  631. save: 'Save',
  632. cancel: 'Cancel'
  633. }
  634. },
  635. tabIndex: {
  636. value: 1
  637. },
  638. toolbar: {
  639. setter: '_setToolbar',
  640. validator: isObject,
  641. value: null
  642. },
  643. unescapeValue: {
  644. value: true,
  645. validator: isBoolean
  646. },
  647. validator: {
  648. setter: '_setValidator',
  649. validator: isObject,
  650. value: null
  651. },
  652. value: {
  653. value: _EMPTY_STR
  654. },
  655. visible: {
  656. value: false
  657. }
  658. },
  659. EXTENDS: A.Overlay,
  660. UI_ATTRS: [ EDITABLE, SHOW_TOOLBAR, VALUE ],
  661. prototype: {
  662. CONTENT_TEMPLATE: '<form></form>',
  663. ELEMENT_TEMPLATE: null,
  664. elements: null,
  665. validator: null,
  666. _hDocMouseDownEv: null,
  667. initializer: function(config) {
  668. var instance = this;
  669. instance._initEvents();
  670. },
  671. destructor: function() {
  672. var instance = this;
  673. var hDocMouseDown = instance._hDocMouseDownEv;
  674. var toolbar = instance.toolbar;
  675. var validator = instance.validator;
  676. if (hDocMouseDown) {
  677. hDocMouseDown.detach();
  678. }
  679. if (toolbar) {
  680. toolbar.destroy();
  681. }
  682. if (validator) {
  683. validator.destroy();
  684. }
  685. },
  686. bindUI: function() {
  687. var instance = this;
  688. instance.get(BOUNDING_BOX).on(KEY, A.bind(instance._onEscKey, instance), 'down:27');
  689. },
  690. formatValue: function(formatter, val) {
  691. var instance = this;
  692. if (isFunction(formatter)) {
  693. val = formatter.call(instance, val);
  694. }
  695. return val;
  696. },
  697. getValue: function() {
  698. var instance = this;
  699. return instance.formatValue(
  700. instance.get(INPUT_FORMATTER),
  701. instance.getElementsValue()
  702. );
  703. },
  704. _initEvents: function() {
  705. var instance = this;
  706. instance.publish({
  707. cancel: {
  708. defaultFn: instance._defCancelFn
  709. },
  710. initEdit: {
  711. defaultFn: instance._defInitEditFn,
  712. fireOnce: true
  713. },
  714. initValidator: {
  715. defaultFn: instance._defInitValidatorFn,
  716. fireOnce: true
  717. },
  718. initToolbar: {
  719. defaultFn: instance._defInitToolbarFn,
  720. fireOnce: true
  721. },
  722. save: {
  723. defaultFn: instance._defSaveFn
  724. }
  725. });
  726. instance.after({
  727. render: instance._afterRender,
  728. visibleChange: A.debounce(instance._debounceVisibleChange, 350, instance)
  729. });
  730. instance.on({
  731. 'form-validator:submit': A.bind(instance._onSubmit, instance)
  732. });
  733. },
  734. _afterRender: function() {
  735. var instance = this;
  736. instance._handleInitValidatorEvent();
  737. instance._handleInitToolbarEvent();
  738. },
  739. _defCancelFn: function(event) {
  740. var instance = this;
  741. instance.hide();
  742. },
  743. _defInitValidatorFn: function(event) {
  744. var instance = this;
  745. instance.validator = new A.FormValidator(
  746. instance.get(VALIDATOR)
  747. );
  748. },
  749. _defInitToolbarFn: function(event) {
  750. var instance = this;
  751. var editable = instance.get(EDITABLE);
  752. instance.toolbar = new A.Toolbar(
  753. instance.get(TOOLBAR)
  754. )
  755. .render(instance.footerNode);
  756. if (editable) {
  757. instance._uiSetEditable(editable);
  758. }
  759. },
  760. _defSaveFn: function(event) {
  761. var instance = this;
  762. if (instance.get(HIDE_ON_SAVE)) {
  763. instance.hide();
  764. }
  765. },
  766. _debounceVisibleChange: function(event) {
  767. var instance = this;
  768. var hDocMouseDown = instance._hDocMouseDownEv;
  769. if (event.newVal) {
  770. if (!hDocMouseDown) {
  771. instance._hDocMouseDownEv = A.getDoc().on(MOUSEDOWN, A.bind(instance._onDocMouseDownExt, instance));
  772. }
  773. }
  774. else if (hDocMouseDown) {
  775. hDocMouseDown.detach();
  776. instance._hDocMouseDownEv = null;
  777. }
  778. },
  779. _handleCancelEvent: function() {
  780. var instance = this;
  781. instance.fire(CANCEL);
  782. },
  783. _handleEditEvent: function() {
  784. var instance = this;
  785. instance.fire(EDIT);
  786. },
  787. _handleInitEditEvent: function() {
  788. var instance = this;
  789. if (instance.get(RENDERED)) {
  790. this.fire(INIT_EDIT);
  791. }
  792. },
  793. _handleInitValidatorEvent: function() {
  794. var instance = this;
  795. if (instance.get(RENDERED)) {
  796. this.fire(INIT_VALIDATOR);
  797. }
  798. },
  799. _handleInitToolbarEvent: function() {
  800. var instance = this;
  801. if (instance.get(RENDERED) && instance.get(SHOW_TOOLBAR)) {
  802. this.fire(INIT_TOOLBAR);
  803. }
  804. },
  805. _handleSaveEvent: function() {
  806. var instance = this;
  807. if (!instance.validator.hasErrors()) {
  808. instance.fire(SAVE, {
  809. newVal: instance.getValue(),
  810. prevVal: instance.get(VALUE)
  811. });
  812. }
  813. },
  814. _onDocMouseDownExt: function(event) {
  815. var instance = this;
  816. var boundingBox = instance.get(BOUNDING_BOX);
  817. if (!boundingBox.contains(event.target)) {
  818. instance.set(VISIBLE, false);
  819. }
  820. },
  821. _onEscKey: function(event) {
  822. var instance = this;
  823. instance.hide();
  824. },
  825. _onSubmit: function(event) {
  826. var instance = this;
  827. var validator = event.validator;
  828. instance._handleSaveEvent();
  829. if (validator) {
  830. validator.formEvent.halt();
  831. }
  832. },
  833. _setToolbar: function(val) {
  834. var instance = this;
  835. var strings = instance.getStrings();
  836. return A.merge(
  837. {
  838. activeState: false,
  839. children: [
  840. {
  841. label: strings[SAVE],
  842. icon: DISK,
  843. type: SUBMIT
  844. },
  845. {
  846. handler: A.bind(instance._handleCancelEvent, instance),
  847. label: strings[CANCEL]
  848. }
  849. ]
  850. },
  851. val
  852. );
  853. },
  854. _setValidator: function(val) {
  855. var instance = this;
  856. return A.merge(
  857. {
  858. boundingBox: instance.get(CONTENT_BOX),
  859. bubbleTargets: instance
  860. },
  861. val
  862. );
  863. },
  864. _uiSetShowToolbar: function(val) {
  865. var instance = this;
  866. var footerNode = instance.footerNode;
  867. if (val) {
  868. footerNode.show();
  869. }
  870. else {
  871. footerNode.hide();
  872. }
  873. instance._handleInitToolbarEvent();
  874. },
  875. /*
  876. * NOTE FOR DEVELOPERS:
  877. *
  878. * Yoy *may* want to replace the methods from this section on your implementation.
  879. */
  880. getElementsValue: function() {
  881. var instance = this;
  882. var elements = instance.elements;
  883. if (elements) {
  884. return elements.get(VALUE);
  885. }
  886. return _EMPTY_STR;
  887. },
  888. renderUI: function() {
  889. var instance = this;
  890. if (instance.ELEMENT_TEMPLATE) {
  891. instance.elements = A.Node.create(instance.ELEMENT_TEMPLATE);
  892. instance._syncElementsName();
  893. instance.setStdModContent(WidgetStdMod.BODY, instance.elements);
  894. }
  895. },
  896. _defInitEditFn: function(event) {
  897. },
  898. _syncElementsFocus: function() {
  899. var instance = this;
  900. instance.elements.selectText();
  901. },
  902. _syncElementsName: function() {
  903. var instance = this;
  904. instance.elements.setAttribute(
  905. NAME,
  906. instance.get(ELEMENT_NAME)
  907. );
  908. },
  909. _syncFocus: function() {
  910. var instance = this;
  911. A.later(0, instance, instance._syncElementsFocus);
  912. },
  913. _uiSetEditable: function(val) {
  914. var instance = this;
  915. var toolbar = instance.toolbar;
  916. if (instance.get(RENDERED) && toolbar) {
  917. if (val) {
  918. toolbar.add(
  919. {
  920. handler: A.bind(instance._handleEditEvent, instance),
  921. icon: PENCIL,
  922. label: instance.getString(EDIT)
  923. },
  924. 1
  925. );
  926. }
  927. else {
  928. toolbar.remove(1);
  929. }
  930. }
  931. },
  932. _uiSetValue: function(val) {
  933. var instance = this;
  934. var elements = instance.elements;
  935. if (elements) {
  936. elements.val(
  937. instance.formatValue(instance.get(OUTPUT_FORMATTER), val)
  938. );
  939. }
  940. }
  941. /*
  942. * End of replaceable methods.
  943. */
  944. }
  945. });
  946. A.BaseCellEditor = BaseCellEditor;
  947. /**
  948. * Abstract class BaseOptionsCellEditor for options attribute support.
  949. *
  950. * Check the list of <a href="BaseOptionsCellEditor.html#configattributes">Configuration Attributes</a> available for
  951. * BaseCellEditor.
  952. *
  953. * @param config {Object} Object literal specifying widget configuration properties.
  954. *
  955. * @class BaseOptionsCellEditor
  956. * @abstract
  957. * @extends A.BaseCellEditor
  958. */
  959. var BaseOptionsCellEditor = A.Component.create({
  960. NAME: OPTIONS_CELL_EDITOR,
  961. ATTRS: {
  962. inputFormatter: {
  963. value: null
  964. },
  965. options: {
  966. setter: '_setOptions',
  967. value: {},
  968. validator: isObject
  969. },
  970. outputFormatter: {
  971. value: null
  972. },
  973. selectedAttrName: {
  974. value: SELECTED,
  975. validator: isString
  976. },
  977. strings: {
  978. value: {
  979. add: 'Add',
  980. cancel: 'Cancel',
  981. addOption: 'Add option',
  982. edit: 'Edit options',
  983. editOptions: 'Edit option(s)',
  984. name: 'Name',
  985. remove: 'Remove',
  986. save: 'Save',
  987. stopEditing: 'Stop editing',
  988. value: 'Value'
  989. }
  990. }
  991. },
  992. EXTENDS: A.BaseCellEditor,
  993. UI_ATTRS: [OPTIONS],
  994. prototype: {
  995. EDIT_TEMPLATE: '<div class="' + CSS_CELLEDITOR_EDIT + '"></div>',
  996. EDIT_OPTION_ROW_TEMPLATE: '<div class="' + CSS_CELLEDITOR_EDIT_OPTION_ROW + '">' +
  997. '<span class="' + [ CSS_CELLEDITOR_EDIT_DD_HANDLE, CSS_ICON, CSS_ICON_GRIP_DOTTED_VERTICAL ].join(_SPACE) + '"></span>' +
  998. '<input class="' + CSS_CELLEDITOR_EDIT_INPUT_NAME + '" size="7" placeholder="{titleName}" title="{titleName}" type="text" value="{valueName}" /> ' +
  999. '<input class="' + CSS_CELLEDITOR_EDIT_INPUT_VALUE + '" size="7" placeholder="{titleValue}" title="{titleValue}" type="text" value="{valueValue}" /> ' +
  1000. '<a class="' + [ CSS_CELLEDITOR_EDIT_LINK, CSS_CELLEDITOR_EDIT_DELETE_OPTION ].join(_SPACE) + '" href="javascript:void(0);">{remove}</a> ' +
  1001. '</div>',
  1002. EDIT_ADD_LINK_TEMPLATE: '<a class="' + [ CSS_CELLEDITOR_EDIT_LINK, CSS_CELLEDITOR_EDIT_ADD_OPTION ].join(_SPACE) + '" href="javascript:void(0);">{addOption}</a> ',
  1003. EDIT_LABEL_TEMPLATE: '<div class="' + CSS_CELLEDITOR_EDIT_LABEL + '">{editOptions}</div>',
  1004. editContainer: null,
  1005. editSortable: null,
  1006. options: null,
  1007. initializer: function() {
  1008. var instance = this;
  1009. instance.on(EDIT, instance._onEditEvent);
  1010. instance.on(SAVE, instance._onSave);
  1011. instance.after(INIT_TOOLBAR, instance._afterInitToolbar);
  1012. },
  1013. addNewOption: function(name, value) {
  1014. var instance = this;
  1015. var addOptionLink = instance.editContainer.one(_DOT+CSS_CELLEDITOR_EDIT_ADD_OPTION);
  1016. var newRow = A.Node.create(
  1017. instance._createEditOption(
  1018. name || _EMPTY_STR,
  1019. value || _EMPTY_STR
  1020. )
  1021. );
  1022. addOptionLink.placeBefore(newRow);
  1023. newRow.one(INPUT).focus();
  1024. },
  1025. removeOption: function(optionRow) {
  1026. optionRow.remove();
  1027. },
  1028. saveOptions: function() {
  1029. var instance = this;
  1030. var editContainer = instance.editContainer;
  1031. if (editContainer) {
  1032. var names = editContainer.all(_DOT+CSS_CELLEDITOR_EDIT_INPUT_NAME);
  1033. var values = editContainer.all(_DOT+CSS_CELLEDITOR_EDIT_INPUT_VALUE);
  1034. var options = {};
  1035. names.each(function(inputName, index) {
  1036. var name = inputName.val();
  1037. var value = values.item(index).val();
  1038. options[value] = name;
  1039. });
  1040. instance.set(OPTIONS, options);
  1041. instance._uiSetValue(
  1042. instance.get(VALUE)
  1043. );
  1044. instance.toggleEdit();
  1045. }
  1046. },
  1047. toggleEdit: function() {
  1048. var instance = this;
  1049. instance.editContainer.toggle();
  1050. },
  1051. // TODO - rewrite this method
  1052. _createOptions: function(val) {
  1053. var instance = this;
  1054. var elements = instance.elements;
  1055. var optionsBuffer = [];
  1056. var wrappersBuffer = [];
  1057. var optionTpl = instance.OPTION_TEMPLATE;
  1058. var optionWrapperTpl = instance.OPTION_WRAPPER;
  1059. A.each(val, function(oLabel, oValue) {
  1060. var values = {
  1061. id: A.guid(),
  1062. label: AEscape.html(oLabel),
  1063. name: AEscape.html(oValue),
  1064. value: AEscape.html(oValue)
  1065. };
  1066. if (optionTpl) {
  1067. optionsBuffer.push(Lang.sub(optionTpl, values));
  1068. }
  1069. if (optionWrapperTpl) {
  1070. wrappersBuffer.push(Lang.sub(optionWrapperTpl, values));
  1071. }
  1072. });
  1073. var options = A.NodeList.create(optionsBuffer.join(_EMPTY_STR));
  1074. var wrappers = A.NodeList.create(wrappersBuffer.join(_EMPTY_STR));
  1075. if (wrappers.size()) {
  1076. wrappers.each(function(wrapper, i) {
  1077. wrapper.prepend(options.item(i));
  1078. });
  1079. elements.setContent(wrappers);
  1080. }
  1081. else {
  1082. elements.setContent(options);
  1083. }
  1084. instance.options = options;
  1085. },
  1086. _createEditBuffer: function() {
  1087. var instance = this;
  1088. var strings = instance.getStrings();
  1089. var buffer = [];
  1090. buffer.push(
  1091. Lang.sub(instance.EDIT_LABEL_TEMPLATE, {
  1092. editOptions: strings[EDIT_OPTIONS]
  1093. })
  1094. );
  1095. A.each(instance.get(OPTIONS), function(name, value) {
  1096. buffer.push(instance._createEditOption(name, value));
  1097. });
  1098. buffer.push(
  1099. Lang.sub(instance.EDIT_ADD_LINK_TEMPLATE, {
  1100. addOption: strings[ADD_OPTION]
  1101. })
  1102. );
  1103. return buffer.join(_EMPTY_STR);
  1104. },
  1105. _createEditOption: function(name, value) {
  1106. var instance = this;
  1107. var strings = instance.getStrings();
  1108. return Lang.sub(
  1109. instance.EDIT_OPTION_ROW_TEMPLATE,
  1110. {
  1111. remove: strings[REMOVE],
  1112. titleName: AEscape.html(strings[NAME]),
  1113. titleValue: AEscape.html(strings[VALUE]),
  1114. valueName: AEscape.html(name),
  1115. valueValue: AEscape.html(value)
  1116. }
  1117. );
  1118. },
  1119. _defInitEditFn: function(event) {
  1120. var instance = this;
  1121. var editContainer = A.Node.create(instance.EDIT_TEMPLATE);
  1122. editContainer.delegate('click', A.bind(instance._onEditLinkClickEvent, instance), _DOT+CSS_CELLEDITOR_EDIT_LINK);
  1123. editContainer.delegate('keydown', A.bind(instance._onEditKeyEvent, instance), INPUT);
  1124. instance.editContainer = editContainer;
  1125. instance.setStdModContent(
  1126. WidgetStdMod.BODY,
  1127. editContainer.hide(),
  1128. WidgetStdMod.AFTER
  1129. );
  1130. instance.editSortable = new A.Sortable({
  1131. container: editContainer,
  1132. handles: [ _DOT+CSS_CELLEDITOR_EDIT_DD_HANDLE ],
  1133. nodes: _DOT+CSS_CELLEDITOR_EDIT_OPTION_ROW,
  1134. opacity: '.3'
  1135. })
  1136. .delegate.dd.plug(A.Plugin.DDConstrained, {
  1137. constrain: editContainer,
  1138. stickY: true
  1139. });
  1140. instance._syncEditOptionsUI();
  1141. },
  1142. _getSelectedOptions: function() {
  1143. var instance = this;
  1144. var options = [];
  1145. instance.options.each(function(option) {
  1146. if (option.get(instance.get(SELECTED_ATTR_NAME))) {
  1147. options.push(option);
  1148. }
  1149. });
  1150. return A.all(options);
  1151. },
  1152. _onEditEvent: function(event) {
  1153. var instance = this;
  1154. instance._handleInitEditEvent();
  1155. instance.toggleEdit();
  1156. instance._syncEditOptionsUI();
  1157. },
  1158. _onEditLinkClickEvent: function(event) {
  1159. var instance = this;
  1160. var currentTarget = event.currentTarget;
  1161. if (currentTarget.test(_DOT+CSS_CELLEDITOR_EDIT_ADD_OPTION)) {
  1162. instance.addNewOption();
  1163. }
  1164. else if (currentTarget.test(_DOT+CSS_CELLEDITOR_EDIT_HIDE_OPTION)) {
  1165. instance.toggleEdit();
  1166. }
  1167. else if (currentTarget.test(_DOT+CSS_CELLEDITOR_EDIT_DELETE_OPTION)) {
  1168. instance.removeOption(
  1169. currentTarget.ancestor(_DOT+CSS_CELLEDITOR_EDIT_OPTION_ROW)
  1170. );
  1171. }
  1172. event.halt();
  1173. },
  1174. _onEditKeyEvent: function(event) {
  1175. var instance = this;
  1176. var currentTarget = event.currentTarget;
  1177. if (event.isKey(RETURN)) {
  1178. var nextInput = currentTarget.next(INPUT);
  1179. if (nextInput) {
  1180. nextInput.selectText();
  1181. }
  1182. else {
  1183. instance.addNewOption();
  1184. }
  1185. event.halt();
  1186. }
  1187. },
  1188. _onSave: function(event) {
  1189. var instance = this;
  1190. instance.saveOptions();
  1191. },
  1192. _setOptions: function(val) {
  1193. var options = {};
  1194. if (isArray(val)) {
  1195. AArray.each(val, function(value) {
  1196. options[value] = value;
  1197. });
  1198. }
  1199. else if (isObject(val)) {
  1200. options = val;
  1201. }
  1202. return options;
  1203. },
  1204. _syncEditOptionsUI: function() {
  1205. var instance = this;
  1206. instance.editContainer.setContent(instance._createEditBuffer());
  1207. },
  1208. _uiSetOptions: function(val) {
  1209. var instance = this;
  1210. instance._uiSetValue(instance.get(VALUE));
  1211. instance._createOptions(val);
  1212. instance._syncElementsName();
  1213. },
  1214. _uiSetValue: function(val) {
  1215. var instance = this;
  1216. var options = instance.options;
  1217. if (options && options.size()) {
  1218. options.set(instance.get(SELECTED_ATTR_NAME), false);
  1219. if (val) {
  1220. if (!isArray(val)) {
  1221. val = val.split(_COMMA);
  1222. }
  1223. AArray.each(val, function(value) {
  1224. options.filter('[value="' + AEscape.html(Lang.trim(value)) + '"]').set(instance.get(SELECTED_ATTR_NAME), true);
  1225. });
  1226. }
  1227. }
  1228. return val;
  1229. }
  1230. }
  1231. });
  1232. A.BaseOptionsCellEditor = BaseOptionsCellEditor;
  1233. /**
  1234. * TextCellEditor class.
  1235. *
  1236. * Check the list of <a href="TextCellEditor.html#configattributes">Configuration Attributes</a> available for
  1237. * TextCellEditor.
  1238. *
  1239. * @param config {Object} Object literal specifying widget configuration properties.
  1240. *
  1241. * @class TextCellEditor
  1242. * @constructor
  1243. * @extends A.BaseCellEditor
  1244. */
  1245. var TextCellEditor = A.Component.create({
  1246. NAME: TEXT_CELL_EDITOR,
  1247. EXTENDS: A.BaseCellEditor,
  1248. prototype: {
  1249. ELEMENT_TEMPLATE: '<input autocomplete="off" class="' + CSS_CELLEDITOR_ELEMENT + '" type="text" />'
  1250. }
  1251. });
  1252. A.TextCellEditor = TextCellEditor;
  1253. /**
  1254. * TextAreaCellEditor class.
  1255. *
  1256. * Check the list of <a href="TextAreaCellEditor.html#configattributes">Configuration Attributes</a> available for
  1257. * TextAreaCellEditor.
  1258. *
  1259. * @param config {Object} Object literal specifying widget configuration properties.
  1260. *
  1261. * @class TextAreaCellEditor
  1262. * @constructor
  1263. * @extends A.TextAreaCellEditor
  1264. */
  1265. var TextAreaCellEditor = A.Component.create({
  1266. NAME: TEXT_AREA_CELL_EDITOR,
  1267. EXTENDS: A.BaseCellEditor,
  1268. prototype: {
  1269. ELEMENT_TEMPLATE: '<textarea class="' + CSS_CELLEDITOR_ELEMENT + '"></textarea>'
  1270. }
  1271. });
  1272. A.TextAreaCellEditor = TextAreaCellEditor;
  1273. /**
  1274. * DropDownCellEditor class.
  1275. *
  1276. * Check the list of <a href="DropDownCellEditor.html#configattributes">Configuration Attributes</a> available for
  1277. * DropDownCellEditor.
  1278. *
  1279. * @param config {Object} Object literal specifying widget configuration properties.
  1280. *
  1281. * @class DropDownCellEditor
  1282. * @constructor
  1283. * @extends A.DropDownCellEditor
  1284. */
  1285. var DropDownCellEditor = A.Component.create({
  1286. NAME: DROP_DOWN_CELL_EDITOR,
  1287. ATTRS: {
  1288. multiple: {
  1289. value: false,
  1290. validator: isBoolean
  1291. }
  1292. },
  1293. EXTENDS: A.BaseOptionsCellEditor,
  1294. UI_ATTRS: [MULTIPLE],
  1295. prototype: {
  1296. ELEMENT_TEMPLATE: '<select class="' + CSS_CELLEDITOR_ELEMENT + '"></select>',
  1297. OPTION_TEMPLATE: '<option value="{value}">{label}</option>',
  1298. getElementsValue: function() {
  1299. var instance = this;
  1300. if (instance.get(MULTIPLE)) {
  1301. return instance._getSelectedOptions().get(VALUE);
  1302. }
  1303. return instance.elements.get(VALUE);
  1304. },
  1305. _syncElementsFocus: function() {
  1306. var instance = this;
  1307. instance.elements.focus();
  1308. },
  1309. _uiSetMultiple: function(val) {
  1310. var instance = this;
  1311. var elements = instance.elements;
  1312. if (val) {
  1313. elements.setAttribute(MULTIPLE, MULTIPLE);
  1314. }
  1315. else {
  1316. elements.removeAttribute(MULTIPLE);
  1317. }
  1318. }
  1319. }
  1320. });
  1321. A.DropDownCellEditor = DropDownCellEditor;
  1322. /**
  1323. * CheckboxCellEditor class.
  1324. *
  1325. * Check the list of <a href="DropDownCellEditor.html#configattributes">Configuration Attributes</a> available for
  1326. * CheckboxCellEditor.
  1327. *
  1328. * @param config {Object} Object literal specifying widget configuration properties.
  1329. *
  1330. * @class CheckboxCellEditor
  1331. * @constructor
  1332. * @extends A.CheckboxCellEditor
  1333. */
  1334. var CheckboxCellEditor = A.Component.create({
  1335. NAME: CHECKBOX_CELL_EDITOR,
  1336. ATTRS: {
  1337. selectedAttrName: {
  1338. value: CHECKED
  1339. }
  1340. },
  1341. EXTENDS: A.BaseOptionsCellEditor,
  1342. prototype: {
  1343. ELEMENT_TEMPLATE: '<div class="' + CSS_CELLEDITOR_ELEMENT + '"></div>',
  1344. OPTION_TEMPLATE: '<input class="' + CSS_CELLEDITOR_OPTION + '" id="{id}" name="{name}" type="checkbox" value="{value}"/>',
  1345. OPTION_WRAPPER: '<label class="' + CSS_CELLEDITOR_WRAPPER + '" for="{id}"><span class="' + CSS_CELLEDITOR_LABEL + '">{label}</span></label>',
  1346. getElementsValue: function() {
  1347. var instance = this;
  1348. return instance._getSelectedOptions().get(VALUE);
  1349. },
  1350. _syncElementsFocus: function() {
  1351. var instance = this;
  1352. var options = instance.options;
  1353. if (options && options.size()) {
  1354. options.item(0).focus();
  1355. }
  1356. },
  1357. _syncElementsName: function() {
  1358. var instance = this;
  1359. var options = instance.options;
  1360. if (options) {
  1361. options.setAttribute(NAME, instance.get(ELEMENT_NAME));
  1362. }
  1363. }
  1364. }
  1365. });
  1366. A.CheckboxCellEditor = CheckboxCellEditor;
  1367. /**
  1368. * RadioCellEditor class.
  1369. *
  1370. * Check the list of <a href="RadioCellEditor.html#configattributes">Configuration Attributes</a> available for
  1371. * RadioCellEditor.
  1372. *
  1373. * @param config {Object} Object literal specifying widget configuration properties.
  1374. *
  1375. * @class RadioCellEditor
  1376. * @constructor
  1377. * @extends A.RadioCellEditor
  1378. */
  1379. var RadioCellEditor = A.Component.create({
  1380. NAME: RADIO_CELL_EDITOR,
  1381. EXTENDS: A.CheckboxCellEditor,
  1382. prototype: {
  1383. OPTION_TEMPLATE: '<input class="aui-field-input-choice" id="{id}" name="{name}" type="radio" value="{value}"/>',
  1384. getElementsValue: function() {
  1385. var instance = this;
  1386. return instance._getSelectedOptions().get(VALUE)[0];
  1387. }
  1388. }
  1389. });
  1390. A.RadioCellEditor = RadioCellEditor;
  1391. /**
  1392. * DateCellEditor class.
  1393. *
  1394. * Check the list of <a href="DateCellEditor.html#configattributes">Configuration Attributes</a> available for
  1395. * DateCellEditor.
  1396. *
  1397. * @param config {Object} Object literal specifying widget configuration properties.
  1398. *
  1399. * @class DateCellEditor
  1400. * @constructor
  1401. * @extends A.DateCellEditor
  1402. */
  1403. var DateCellEditor = A.Component.create({
  1404. NAME: DATE_CELL_EDITOR,
  1405. EXTENDS: A.BaseCellEditor,
  1406. ATTRS: {
  1407. bodyContent: {
  1408. value: _EMPTY_STR
  1409. },
  1410. calendar: {
  1411. setter: '_setCalendar',
  1412. validator: isObject,
  1413. value: null
  1414. }
  1415. },
  1416. prototype: {
  1417. ELEMENT_TEMPLATE: '<input class="' + CSS_CELLEDITOR_ELEMENT + '" type="hidden" />',
  1418. initializer: function() {
  1419. var instance = this;
  1420. instance.on('calendar:select', A.bind(instance._onDateSelect, instance));
  1421. },
  1422. getElementsValue: function() {
  1423. var instance = this;
  1424. return instance.calendar.getFormattedSelectedDates().join(_COMMA);
  1425. },
  1426. _afterRender: function() {
  1427. var instance = this;
  1428. A.DateCellEditor.superclass._afterRender.apply(instance, arguments);
  1429. instance.calendar = new A.Calendar(
  1430. instance.get(CALENDAR)
  1431. )
  1432. .render(instance.bodyNode);
  1433. },
  1434. _onDateSelect: function(event) {
  1435. var instance = this;
  1436. instance.elements.val(
  1437. event.date.formatted.join(_COMMA)
  1438. );
  1439. },
  1440. _setCalendar: function(val) {
  1441. var instance = this;
  1442. return A.merge(
  1443. {
  1444. bubbleTargets: instance
  1445. },
  1446. val
  1447. );
  1448. },
  1449. _uiSetValue: function(val) {
  1450. var instance = this;
  1451. var calendar = instance.calendar;
  1452. if (calendar) {
  1453. if (val && isString(val)) {
  1454. val = val.split(_COMMA);
  1455. }
  1456. instance.calendar.set('dates', val);
  1457. }
  1458. }
  1459. }
  1460. });
  1461. A.DateCellEditor = DateCellEditor;
  1462. }, '@VERSION@' ,{requires:['aui-calendar','aui-datatable-events','aui-toolbar','aui-form-validator','escape','overlay','sortable'], skinnable:true});
  1463. AUI.add('aui-datatable-selection', function(A) {
  1464. // TODO - add support for row/column selection
  1465. var Lang = A.Lang,
  1466. isBoolean = Lang.isBoolean,
  1467. isString = Lang.isString,
  1468. AgetClassName = A.getClassName,
  1469. _toInitialCap = A.cached(function(str) {
  1470. return str.substring(0, 1).toUpperCase() + str.substring(1);
  1471. }),
  1472. CELL = 'cell',
  1473. COLUMNSET = 'columnset',
  1474. COLUMNSET_CHANGE = 'columnsetChange',
  1475. DATATABLE = 'datatable',
  1476. DOWN = 'down',
  1477. ESC = 'esc',
  1478. FOCUSED = 'focused',
  1479. HOST = 'host',
  1480. ID = 'id',
  1481. KEYDOWN = 'keydown',
  1482. LEFT = 'left',
  1483. MOUSEDOWN = 'mousedown',
  1484. MOUSE_EVENT = 'mouseEvent',
  1485. MULTIPLE = 'multiple',
  1486. RECORDSET = 'recordset',
  1487. RECORDSET_CHANGE = 'recordsetChange',
  1488. RETURN = 'return',
  1489. RIGHT = 'right',
  1490. ROW = 'row',
  1491. SELECT = 'select',
  1492. SELECTED = 'selected',
  1493. SELECT_ROW = 'selectRow',
  1494. TAB = 'tab',
  1495. TABINDEX = 'tabindex',
  1496. TR = 'tr',
  1497. UP = 'up',
  1498. CSS_DATATABLE_CELL_SELECTED = AgetClassName(DATATABLE, CELL, SELECTED),
  1499. CSS_DATATABLE_ROW_SELECTED = AgetClassName(DATATABLE, ROW, SELECTED);
  1500. var DataTableSelection = A.Base.create("dataTableSelection", A.Plugin.Base, [], {
  1501. activeColumnIndex: -1,
  1502. activeRecordIndex: -1,
  1503. handlerKeyDown: null,
  1504. selectedCellHash: null,
  1505. selectedColumnHash: null,
  1506. selectedRowHash: null,
  1507. initializer: function() {
  1508. var instance = this;
  1509. instance.selectedCellHash = {};
  1510. instance.selectedColumnHash = {};
  1511. instance.selectedRowHash = {};
  1512. instance.publish({
  1513. select: {
  1514. defaultFn: instance._defSelectFn
  1515. }
  1516. });
  1517. instance.afterHostEvent(instance.get(MOUSE_EVENT), instance._afterMouseEvent);
  1518. instance.afterHostEvent(COLUMNSET_CHANGE, instance._afterHostColumnsetChange);
  1519. instance.afterHostEvent(RECORDSET_CHANGE, instance._afterHostRecordsetChange);
  1520. instance.handlerKeyDown = A.getDoc().on(KEYDOWN, A.bind(instance._afterKeyEvent, instance));
  1521. },
  1522. destroy: function() {
  1523. var instance = this;
  1524. var handlerKeyDown = instance.handlerKeyDown;
  1525. if (handlerKeyDown) {
  1526. handlerKeyDown.detach();
  1527. }
  1528. },
  1529. getActiveColumn: function() {
  1530. var instance = this;
  1531. var host = instance.get(HOST);
  1532. return host.get(COLUMNSET).getColumn(instance.activeColumnIndex);
  1533. },
  1534. getActiveRecord: function() {
  1535. var instance = this;
  1536. var host = instance.get(HOST);
  1537. return host.get(RECORDSET).getRecord(instance.activeRecordIndex);
  1538. },
  1539. isCellSelected: function(cell) {
  1540. var instance = this;
  1541. return instance.selectedCellHash[cell.get(ID)];
  1542. },
  1543. isColumnSelected: function(column) {
  1544. // TODO
  1545. },
  1546. isRowSelected: function(row) {
  1547. var instance = this;
  1548. return instance.selectedRowHash[row.get(ID)];
  1549. },
  1550. select: function(cell, row) {
  1551. var instance = this;
  1552. var host = instance.get(HOST);
  1553. var columnset = host.get(COLUMNSET);
  1554. var recordset = host.get(RECORDSET);
  1555. var column = columnset.getColumnByCell(cell);
  1556. var record = recordset.getRecordByRow(row || cell.ancestor(TR));
  1557. instance.activeColumnIndex = columnset.getColumnIndex(column);
  1558. instance.activeRecordIndex = recordset.getRecordIndex(record);
  1559. if (cell) {
  1560. instance.selectCell(cell);
  1561. }
  1562. if (instance.get(SELECT_ROW) && row) {
  1563. instance.selectRow(row);
  1564. }
  1565. },
  1566. selectCell: function(cell) {
  1567. var instance = this;
  1568. if (!instance.get(MULTIPLE)) {
  1569. instance.unselectAllCells();
  1570. }
  1571. instance.selectedCellHash[cell.get(ID)] = cell;
  1572. cell.setAttribute(TABINDEX, 0).focus();
  1573. cell.addClass(CSS_DATATABLE_CELL_SELECTED);
  1574. },
  1575. selectColumn: function(row) {
  1576. // TODO
  1577. },
  1578. selectRow: function(row) {
  1579. var instance = this;
  1580. if (!instance.get(MULTIPLE)) {
  1581. instance.unselectAllRows();
  1582. }
  1583. instance.selectedRowHash[row.get(ID)] = row;
  1584. row.addClass(CSS_DATATABLE_ROW_SELECTED);
  1585. },
  1586. toggleCell: function(cell, forceAdd) {
  1587. var instance = this;
  1588. if (forceAdd || !instance.isCellSelected(cell)) {
  1589. instance.selectCell(cell);
  1590. }
  1591. else {
  1592. instance.unselectCell(cell);
  1593. }
  1594. },
  1595. toggleColumn: function(column, forceAdd) {
  1596. // TODO
  1597. },
  1598. toggleRow: function(row, forceAdd) {
  1599. var instance = this;
  1600. if (forceAdd || !instance.isRowSelected(row)) {
  1601. instance.selectRow(row);
  1602. }
  1603. else {
  1604. instance.unselectRow(row);
  1605. }
  1606. },
  1607. unselectCell: function(cell) {
  1608. var instance = this;
  1609. delete instance.selectedCellHash[cell.get(ID)];
  1610. cell.removeAttribute(TABINDEX);
  1611. cell.removeClass(CSS_DATATABLE_CELL_SELECTED);
  1612. },
  1613. unselectColumn: function(column) {
  1614. // TODO
  1615. },
  1616. unselectRow: function(row) {
  1617. var instance = this;
  1618. delete instance.selectedRowHash[row.get(ID)];
  1619. row.removeClass(CSS_DATATABLE_ROW_SELECTED);
  1620. },
  1621. unselectAllCells: function() {
  1622. var instance = this;
  1623. A.each(instance.selectedCellHash, A.bind(instance.unselectCell, instance));
  1624. },
  1625. unselectAllColumns: function() {
  1626. // TODO
  1627. },
  1628. unselectAllRows: function() {
  1629. var instance = this;
  1630. A.each(instance.selectedRowHash, A.bind(instance.unselectRow, instance));
  1631. },
  1632. _afterHostColumnsetChange: function(event) {
  1633. var instance = this;
  1634. instance._cleanUp();
  1635. },
  1636. _afterHostRecordsetChange: function(event) {
  1637. var instance = this;
  1638. instance._cleanUp();
  1639. },
  1640. _afterMouseEvent: function(event) {
  1641. var instance = this;
  1642. instance._handleSelectEvent(event);
  1643. },
  1644. _afterKeyEvent: function(event) {
  1645. var instance = this;
  1646. var host = instance.get(HOST);
  1647. var column = instance.getActiveColumn();
  1648. var record = instance.getActiveRecord();
  1649. if (!host.get(FOCUSED) || !column || !record) {
  1650. // Don't process keys if the wigdet is not focused or column or record is undefined.
  1651. return;
  1652. }
  1653. if (host.events) {
  1654. // Update event with the new payload information for the next "cell" calculated by the "events" module.
  1655. host.events.updateEventPayload(
  1656. host.getCellNode(record, column),
  1657. event
  1658. );
  1659. }
  1660. if (event.isNavKey()) {
  1661. if (event.isKey(ESC)) {
  1662. instance._onEscKey(event);
  1663. }
  1664. else if (event.isKey(RETURN)) {
  1665. instance._onReturnKey(event);
  1666. }
  1667. else {
  1668. instance._navigate(event);
  1669. }
  1670. event.halt();
  1671. }
  1672. },
  1673. _cleanUp: function() {
  1674. var instance = this;
  1675. instance.selectedCellHash = {};
  1676. instance.selectedColumnHash = {};
  1677. instance.selectedRowHash = {};
  1678. },
  1679. _defSelectFn: function(event) {
  1680. var instance = this;
  1681. instance.select(event.cell, event.row);
  1682. },
  1683. _navigate: function(event) {
  1684. var instance = this;
  1685. instance._updateNavKeyInfo(event);
  1686. instance._handleSelectEvent(event);
  1687. },
  1688. _onEscKey: function(event) {
  1689. var instance = this;
  1690. var host = instance.get(HOST);
  1691. var editor = host.getCellEditor(event.record, event.column);
  1692. if (editor) {
  1693. editor.hide();
  1694. }
  1695. },
  1696. _onReturnKey: function(event) {
  1697. var instance = this;
  1698. var host = instance.get(HOST);
  1699. host._editCell(event);
  1700. },
  1701. _handleSelectEvent: function(event) {
  1702. var instance = this;
  1703. instance.fire(SELECT, {
  1704. cell: event.cell,
  1705. column: event.column,
  1706. inHead: event.inHead,
  1707. liner: event.liner,
  1708. originalEvent: event.originalEvent,
  1709. row: event.row,
  1710. record: event.record
  1711. });
  1712. },
  1713. _updateNavKeyInfo: function(event) {
  1714. var instance = this;
  1715. var host = instance.get(HOST);
  1716. var originalEvent = event.originalEvent;
  1717. var columnset = host.get(COLUMNSET);
  1718. var columnIndex = event.column.keyIndex;
  1719. var recordset = host.get(RECORDSET);
  1720. var recordIndex = recordset.getRecordIndex(event.record);
  1721. var ctrlKey = originalEvent.ctrlKey || originalEvent.metaKey;
  1722. var shiftKey = originalEvent.shiftKey;
  1723. if (originalEvent.isKey(LEFT) ||
  1724. (shiftKey && originalEvent.isKey(TAB))) {
  1725. if (ctrlKey) {
  1726. columnIndex = 0;
  1727. }
  1728. else {
  1729. columnIndex--;
  1730. }
  1731. }
  1732. else if (originalEvent.isKey(RIGHT) ||
  1733. (!shiftKey && originalEvent.isKey(TAB))) {
  1734. if (ctrlKey) {
  1735. columnIndex = columnset.getLength() - 1;
  1736. }
  1737. else {
  1738. columnIndex++;
  1739. }
  1740. }
  1741. else if (originalEvent.isKey(DOWN)) {
  1742. if (ctrlKey) {
  1743. recordIndex = recordset.getLength() - 1;
  1744. }
  1745. else {
  1746. recordIndex++;
  1747. }
  1748. }
  1749. else if (originalEvent.isKey(UP)) {
  1750. if (ctrlKey) {
  1751. recordIndex = 0;
  1752. }
  1753. else {
  1754. recordIndex--;
  1755. }
  1756. }
  1757. // Fixing indexes range
  1758. columnIndex = Math.max(Math.min(columnIndex, columnset.getLength() - 1), 0);
  1759. recordIndex = Math.max(Math.min(recordIndex, recordset.getLength() - 1), 0);
  1760. if (host.events) {
  1761. var newColumn = columnset.getColumn(columnIndex);
  1762. var newRecord = recordset.getRecord(recordIndex);
  1763. // Update event with the new payload information for the next "cell" calculated by the "events" module.
  1764. host.events.updateEventPayload(
  1765. host.getCellNode(newRecord, newColumn),
  1766. event
  1767. );
  1768. }
  1769. },
  1770. _setMouseEvent: function(val) {
  1771. return CELL + _toInitialCap(val);
  1772. }
  1773. },
  1774. {
  1775. NS: "selection",
  1776. NAME: "dataTableSelection",
  1777. ATTRS: {
  1778. selectRow: {
  1779. value: false,
  1780. validator: isBoolean
  1781. },
  1782. multiple: {
  1783. value: false,
  1784. validator: isBoolean
  1785. },
  1786. mouseEvent: {
  1787. setter: '_setMouseEvent',
  1788. value: MOUSEDOWN,
  1789. validator: isString
  1790. }
  1791. }
  1792. });
  1793. A.namespace("Plugin").DataTableSelection = DataTableSelection;
  1794. }, '@VERSION@' ,{requires:['aui-datatable-base'], skinnable:true});
  1795. AUI.add('aui-datatable', function(A){}, '@VERSION@' ,{skinnable:true, use:['aui-datatable-base','aui-datatable-events','aui-datatable-edit','aui-datatable-selection']});