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-tree-view-debug.js 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. AUI.add('aui-tree-view', function(A) {
  2. /**
  3. * The TreeView Utility
  4. *
  5. * @module aui-tree
  6. * @submodule aui-tree-view
  7. */
  8. var L = A.Lang,
  9. isBoolean = L.isBoolean,
  10. isString = L.isString,
  11. UA = A.UA,
  12. BOUNDING_BOX = 'boundingBox',
  13. CHILDREN = 'children',
  14. CONTAINER = 'container',
  15. CONTENT = 'content',
  16. CONTENT_BOX = 'contentBox',
  17. DOT = '.',
  18. FILE = 'file',
  19. HITAREA = 'hitarea',
  20. ICON = 'icon',
  21. INVALID = 'invalid',
  22. LABEL = 'label',
  23. LAST_SELECTED = 'lastSelected',
  24. LEAF = 'leaf',
  25. NODE = 'node',
  26. OWNER_TREE = 'ownerTree',
  27. ROOT = 'root',
  28. SELECT_ON_TOGGLE = 'selectOnToggle',
  29. SPACE = ' ',
  30. TREE = 'tree',
  31. TREE_NODE = 'tree-node',
  32. TREE_VIEW = 'tree-view',
  33. TYPE = 'type',
  34. VIEW = 'view',
  35. concat = function() {
  36. return Array.prototype.slice.call(arguments).join(SPACE);
  37. },
  38. isTreeNode = function(v) {
  39. return ( v instanceof A.TreeNode );
  40. },
  41. getCN = A.getClassName,
  42. CSS_TREE_HITAREA = getCN(TREE, HITAREA),
  43. CSS_TREE_ICON = getCN(TREE, ICON),
  44. CSS_TREE_LABEL = getCN(TREE, LABEL),
  45. CSS_TREE_NODE_CONTENT = getCN(TREE, NODE, CONTENT),
  46. CSS_TREE_NODE_CONTENT_INVALID = getCN(TREE, NODE, CONTENT, INVALID),
  47. CSS_TREE_ROOT_CONTAINER = getCN(TREE, ROOT, CONTAINER),
  48. CSS_TREE_VIEW_CONTENT = getCN(TREE, VIEW, CONTENT);
  49. /**
  50. * <p><img src="assets/images/aui-tree-view/main.png"/></p>
  51. *
  52. * A base class for TreeView, providing:
  53. * <ul>
  54. * <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
  55. * </ul>
  56. *
  57. * Quick Example:<br/>
  58. *
  59. * <pre><code>var tree2 = new A.TreeView({
  60. * width: 200,
  61. * type: 'normal',
  62. * boundingBox: '#tree',
  63. * children: [
  64. * { label: 'Folder 1', children: [ { label: 'file' }, { label: 'file' }, { label: 'file' } ] },
  65. * { label: 'Folder 2', expanded: true, children: [ { label: 'file' }, { label: 'file' } ] },
  66. * { label: 'Folder 3', children: [ { label: 'file' } ] },
  67. * { label: 'Folder 4', expanded: true, children: [ { label: 'Folder 4-1', expanded: true, children: [ { label: 'file' } ] } ] }
  68. * ]
  69. * })
  70. * .render();
  71. * </code></pre>
  72. *
  73. * Check the list of <a href="TreeView.html#configattributes">Configuration Attributes</a> available for
  74. * TreeView.
  75. *
  76. * @param config {Object} Object literal specifying widget configuration properties.
  77. *
  78. * @class TreeView
  79. * @constructor
  80. * @extends TreeData
  81. */
  82. var TreeView = A.Component.create(
  83. {
  84. /**
  85. * Static property provides a string to identify the class.
  86. *
  87. * @property TreeView.NAME
  88. * @type String
  89. * @static
  90. */
  91. NAME: TREE_VIEW,
  92. /**
  93. * Static property used to define the default attribute
  94. * configuration for the TreeView.
  95. *
  96. * @property TreeView.ATTRS
  97. * @type Object
  98. * @static
  99. */
  100. ATTRS: {
  101. /**
  102. * Type of the treeview (i.e. could be 'file' or 'normal').
  103. *
  104. * @attribute type
  105. * @default 'file'
  106. * @type String
  107. */
  108. type: {
  109. value: FILE,
  110. validator: isString
  111. },
  112. /**
  113. * Last selected TreeNode.
  114. *
  115. * @attribute lastSelected
  116. * @default null
  117. * @type TreeNode
  118. */
  119. lastSelected: {
  120. value: null,
  121. validator: isTreeNode
  122. },
  123. lazyLoad: {
  124. validator: isBoolean,
  125. value: true
  126. },
  127. selectOnToggle: {
  128. validator: isBoolean,
  129. value: false
  130. }
  131. },
  132. AUGMENTS: [A.TreeData, A.TreeViewPaginator, A.TreeViewIO],
  133. prototype: {
  134. CONTENT_TEMPLATE: '<ul></ul>',
  135. initializer: function() {
  136. var instance = this;
  137. var boundingBox = instance.get(BOUNDING_BOX);
  138. boundingBox.setData(TREE_VIEW, instance);
  139. instance.initTreeData();
  140. },
  141. /**
  142. * Bind the events on the TreeView UI. Lifecycle.
  143. *
  144. * @method bindUI
  145. * @protected
  146. */
  147. bindUI: function() {
  148. var instance = this;
  149. instance.after('childrenChange', A.bind(instance._afterSetChildren, instance));
  150. instance._delegateDOM();
  151. },
  152. /**
  153. * Create the DOM structure for the TreeView. Lifecycle.
  154. *
  155. * @method renderUI
  156. * @protected
  157. */
  158. renderUI: function() {
  159. var instance = this;
  160. instance._renderElements();
  161. },
  162. /**
  163. * Fires after set children.
  164. *
  165. * @method _afterSetChildren
  166. * @param {EventFacade} event
  167. * @protected
  168. */
  169. _afterSetChildren: function(event) {
  170. var instance = this;
  171. var paginator = instance.get('paginator');
  172. if (paginator && paginator.total) {
  173. var increment = -1;
  174. if (event.newVal.length > event.prevVal.length) {
  175. increment = 1;
  176. }
  177. paginator.total += increment;
  178. }
  179. instance._syncPaginatorUI();
  180. },
  181. /**
  182. * Create TreeNode from HTML markup.
  183. *
  184. * @method _createFromHTMLMarkup
  185. * @param {Node} container
  186. * @protected
  187. */
  188. _createFromHTMLMarkup: function(container) {
  189. var instance = this;
  190. container.all('> li').each(function(node) {
  191. // use firstChild as label
  192. var labelEl = node.one('> *').remove();
  193. var label = labelEl.outerHTML();
  194. var deepContainer = node.one('> ul');
  195. var treeNode = new A.TreeNode({
  196. boundingBox: node,
  197. container: deepContainer,
  198. label: label,
  199. leaf: !deepContainer,
  200. ownerTree: instance
  201. });
  202. if (instance.get('lazyLoad')) {
  203. A.setTimeout(function() {
  204. treeNode.render();
  205. }, 50);
  206. }
  207. else {
  208. treeNode.render();
  209. }
  210. // find the parent TreeNode...
  211. var parentNode = node.get(PARENT_NODE).get(PARENT_NODE);
  212. var parentInstance = parentNode.getData(TREE_NODE);
  213. if (!A.instanceOf(parentInstance, A.TreeNode)) {
  214. parentInstance = parentNode.getData(TREE_VIEW);
  215. }
  216. // and simulate the appendChild.
  217. parentInstance.appendChild(treeNode);
  218. if (deepContainer) {
  219. // propgating markup recursion
  220. instance._createFromHTMLMarkup(deepContainer);
  221. }
  222. });
  223. },
  224. _createNodeContainer: function() {
  225. var instance = this;
  226. var contentBox = instance.get(CONTENT_BOX);
  227. instance.set(CONTAINER, contentBox);
  228. return contentBox;
  229. },
  230. /**
  231. * Render elements.
  232. *
  233. * @method _renderElements
  234. * @protected
  235. */
  236. _renderElements: function() {
  237. var instance = this;
  238. var contentBox = instance.get(CONTENT_BOX);
  239. var children = instance.get(CHILDREN);
  240. var type = instance.get(TYPE);
  241. var CSS_TREE_TYPE = getCN(TREE, type);
  242. contentBox.addClass(CSS_TREE_VIEW_CONTENT);
  243. contentBox.addClass(
  244. concat(CSS_TREE_TYPE, CSS_TREE_ROOT_CONTAINER)
  245. );
  246. if (!children.length) {
  247. // if children not specified try to create from markup
  248. instance._createFromHTMLMarkup(contentBox);
  249. }
  250. },
  251. /**
  252. * Delegate events.
  253. *
  254. * @method _delegateDOM
  255. * @protected
  256. */
  257. _delegateDOM: function() {
  258. var instance = this;
  259. var boundingBox = instance.get(BOUNDING_BOX);
  260. // expand/collapse delegations
  261. boundingBox.delegate('click', A.bind(instance._onClickNodeEl, instance), DOT+CSS_TREE_NODE_CONTENT);
  262. boundingBox.delegate('dblclick', A.bind(instance._onClickHitArea, instance), DOT+CSS_TREE_ICON);
  263. boundingBox.delegate('dblclick', A.bind(instance._onClickHitArea, instance), DOT+CSS_TREE_LABEL);
  264. // other delegations
  265. boundingBox.delegate('mouseenter', A.bind(instance._onMouseEnterNodeEl, instance), DOT+CSS_TREE_NODE_CONTENT);
  266. boundingBox.delegate('mouseleave', A.bind(instance._onMouseLeaveNodeEl, instance), DOT+CSS_TREE_NODE_CONTENT);
  267. },
  268. /**
  269. * Fires on click the TreeView (i.e. set the select/unselect state).
  270. *
  271. * @method _onClickNodeEl
  272. * @param {EventFacade} event
  273. * @protected
  274. */
  275. _onClickNodeEl: function(event) {
  276. var instance = this;
  277. var treeNode = instance.getNodeByChild( event.currentTarget );
  278. if (treeNode) {
  279. if (event.target.test(DOT+CSS_TREE_HITAREA)) {
  280. treeNode.toggle();
  281. if (!instance.get(SELECT_ON_TOGGLE)) {
  282. return;
  283. }
  284. }
  285. if (!treeNode.isSelected()) {
  286. var lastSelected = instance.get(LAST_SELECTED);
  287. // select drag node
  288. if (lastSelected) {
  289. lastSelected.unselect();
  290. }
  291. treeNode.select();
  292. }
  293. }
  294. },
  295. /**
  296. * Fires on <code>mouseeneter</code> the TreeNode.
  297. *
  298. * @method _onMouseEnterNodeEl
  299. * @param {EventFacade} event
  300. * @protected
  301. */
  302. _onMouseEnterNodeEl: function(event) {
  303. var instance = this;
  304. var treeNode = instance.getNodeByChild( event.currentTarget );
  305. if (treeNode) {
  306. treeNode.over();
  307. }
  308. },
  309. /**
  310. * Fires on <code>mouseleave</code> the TreeNode.
  311. *
  312. * @method _onMouseLeaveNodeEl
  313. * @param {EventFacade} event
  314. * @protected
  315. */
  316. _onMouseLeaveNodeEl: function(event) {
  317. var instance = this;
  318. var treeNode = instance.getNodeByChild( event.currentTarget );
  319. if (treeNode) {
  320. treeNode.out();
  321. }
  322. },
  323. /**
  324. * Fires on <code>click</code> the TreeNode hitarea.
  325. *
  326. * @method _onClickHitArea
  327. * @param {EventFacade} event
  328. * @protected
  329. */
  330. _onClickHitArea: function(event) {
  331. var instance = this;
  332. var treeNode = instance.getNodeByChild( event.currentTarget );
  333. if (treeNode) {
  334. treeNode.toggle();
  335. }
  336. }
  337. }
  338. }
  339. );
  340. A.TreeView = TreeView;
  341. /*
  342. * TreeViewDD - Drag & Drop
  343. */
  344. var isNumber = L.isNumber,
  345. ABOVE = 'above',
  346. APPEND = 'append',
  347. BELOW = 'below',
  348. BLOCK = 'block',
  349. BODY = 'body',
  350. CLEARFIX = 'clearfix',
  351. DEFAULT = 'default',
  352. DISPLAY = 'display',
  353. DOWN = 'down',
  354. DRAG = 'drag',
  355. DRAGGABLE = 'draggable',
  356. DRAG_CURSOR = 'dragCursor',
  357. DRAG_NODE = 'dragNode',
  358. EXPANDED = 'expanded',
  359. HELPER = 'helper',
  360. INSERT = 'insert',
  361. OFFSET_HEIGHT = 'offsetHeight',
  362. PARENT_NODE = 'parentNode',
  363. SCROLL_DELAY = 'scrollDelay',
  364. STATE = 'state',
  365. TREE_DRAG_DROP = 'tree-drag-drop',
  366. UP = 'up',
  367. DDM = A.DD.DDM,
  368. CSS_HELPER_CLEARFIX = getCN(HELPER, CLEARFIX),
  369. CSS_ICON = getCN(ICON),
  370. CSS_TREE_DRAG_HELPER = getCN(TREE, DRAG, HELPER),
  371. CSS_TREE_DRAG_HELPER_CONTENT = getCN(TREE, DRAG, HELPER, CONTENT),
  372. CSS_TREE_DRAG_HELPER_LABEL = getCN(TREE, DRAG, HELPER, LABEL),
  373. CSS_TREE_DRAG_INSERT_ABOVE = getCN(TREE, DRAG, INSERT, ABOVE),
  374. CSS_TREE_DRAG_INSERT_APPEND = getCN(TREE, DRAG, INSERT, APPEND),
  375. CSS_TREE_DRAG_INSERT_BELOW = getCN(TREE, DRAG, INSERT, BELOW),
  376. CSS_TREE_DRAG_STATE_APPEND = getCN(TREE, DRAG, STATE, APPEND),
  377. CSS_TREE_DRAG_STATE_INSERT_ABOVE = getCN(TREE, DRAG, STATE, INSERT, ABOVE),
  378. CSS_TREE_DRAG_STATE_INSERT_BELOW = getCN(TREE, DRAG, STATE, INSERT, BELOW),
  379. HELPER_TPL = '<div class="'+CSS_TREE_DRAG_HELPER+'">'+
  380. '<div class="'+[CSS_TREE_DRAG_HELPER_CONTENT, CSS_HELPER_CLEARFIX].join(SPACE)+'">'+
  381. '<span class="'+CSS_ICON+'"></span>'+
  382. '<span class="'+CSS_TREE_DRAG_HELPER_LABEL+'"></span>'+
  383. '</div>'+
  384. '</div>';
  385. /**
  386. * A base class for TreeViewDD, providing:
  387. * <ul>
  388. * <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
  389. * <li>DragDrop support for the TreeNodes</li>
  390. * </ul>
  391. *
  392. * Quick Example:<br/>
  393. *
  394. * Check the list of <a href="TreeViewDD.html#configattributes">Configuration Attributes</a> available for
  395. * TreeViewDD.
  396. *
  397. * @param config {Object} Object literal specifying widget configuration properties.
  398. *
  399. * @class TreeViewDD
  400. * @constructor
  401. * @extends TreeView
  402. */
  403. var TreeViewDD = A.Component.create(
  404. {
  405. /**
  406. * Static property provides a string to identify the class.
  407. *
  408. * @property TreeViewDD.NAME
  409. * @type String
  410. * @static
  411. */
  412. NAME: TREE_DRAG_DROP,
  413. /**
  414. * Static property used to define the default attribute
  415. * configuration for the TreeViewDD.
  416. *
  417. * @property TreeViewDD.ATTRS
  418. * @type Object
  419. * @static
  420. */
  421. ATTRS: {
  422. /**
  423. * Dragdrop helper element.
  424. *
  425. * @attribute helper
  426. * @default null
  427. * @type Node | String
  428. */
  429. helper: {
  430. value: null
  431. },
  432. /**
  433. * Delay of the scroll while dragging the TreeNodes.
  434. *
  435. * @attribute scrollDelay
  436. * @default 100
  437. * @type Number
  438. */
  439. scrollDelay: {
  440. value: 100,
  441. validator: isNumber
  442. }
  443. },
  444. EXTENDS: A.TreeView,
  445. prototype: {
  446. /**
  447. * Direction of the drag (i.e. could be 'up' or 'down').
  448. *
  449. * @property direction
  450. * @type String
  451. * @protected
  452. */
  453. direction: BELOW,
  454. /**
  455. * Drop action (i.e. could be 'append', 'below' or 'above').
  456. *
  457. * @attribute dropAction
  458. * @default null
  459. * @type String
  460. */
  461. dropAction: null,
  462. /**
  463. * Last Y.
  464. *
  465. * @attribute lastY
  466. * @default 0
  467. * @type Number
  468. */
  469. lastY: 0,
  470. node: null,
  471. /**
  472. * Reference for the current drop node.
  473. *
  474. * @attribute nodeContent
  475. * @default null
  476. * @type Node
  477. */
  478. nodeContent: null,
  479. /**
  480. * Descructor lifecycle implementation for the TreeViewDD class.
  481. * Purges events attached to the node (and all child nodes).
  482. *
  483. * @method destructor
  484. * @protected
  485. */
  486. destructor: function() {
  487. var instance = this;
  488. var helper = instance.get(HELPER);
  489. if (helper) {
  490. helper.remove(true);
  491. }
  492. if (instance.ddDelegate) {
  493. instance.ddDelegate.destroy();
  494. }
  495. },
  496. /**
  497. * Bind the events on the TreeViewDD UI. Lifecycle.
  498. *
  499. * @method bindUI
  500. * @protected
  501. */
  502. bindUI: function() {
  503. var instance = this;
  504. A.TreeViewDD.superclass.bindUI.apply(this, arguments);
  505. instance._bindDragDrop();
  506. },
  507. /**
  508. * Create the DOM structure for the TreeViewDD. Lifecycle.
  509. *
  510. * @method renderUI
  511. * @protected
  512. */
  513. renderUI: function() {
  514. var instance = this;
  515. A.TreeViewDD.superclass.renderUI.apply(this, arguments);
  516. // creating drag helper and hiding it
  517. var helper = A.Node.create(HELPER_TPL).hide();
  518. // append helper to the body
  519. A.one(BODY).append(helper);
  520. instance.set(HELPER, helper);
  521. // set DRAG_CURSOR to the default arrow
  522. DDM.set(DRAG_CURSOR, DEFAULT);
  523. },
  524. /**
  525. * Bind DragDrop events.
  526. *
  527. * @method _bindDragDrop
  528. * @protected
  529. */
  530. _bindDragDrop: function() {
  531. var instance = this;
  532. var boundingBox = instance.get(BOUNDING_BOX);
  533. var dragInitHandle = null;
  534. instance._createDragInitHandler = function() {
  535. instance.ddDelegate = new A.DD.Delegate(
  536. {
  537. bubbleTargets: instance,
  538. container: boundingBox,
  539. invalid: DOT+CSS_TREE_NODE_CONTENT_INVALID,
  540. nodes: DOT+CSS_TREE_NODE_CONTENT,
  541. target: true
  542. }
  543. );
  544. var dd = instance.ddDelegate.dd;
  545. dd.plug(A.Plugin.DDProxy, {
  546. moveOnEnd: false,
  547. positionProxy: false,
  548. borderStyle: null
  549. })
  550. .plug(A.Plugin.DDNodeScroll, {
  551. scrollDelay: instance.get(SCROLL_DELAY),
  552. node: boundingBox
  553. });
  554. dd.removeInvalid('a');
  555. if (dragInitHandle) {
  556. dragInitHandle.detach();
  557. }
  558. };
  559. // Check for mobile devices and execute _createDragInitHandler before events
  560. if (!UA.touch) {
  561. // only create the drag on the init elements if the user mouseover the boundingBox for init performance reasons
  562. dragInitHandle = boundingBox.on(['focus', 'mousedown', 'mousemove'], instance._createDragInitHandler);
  563. }
  564. else {
  565. instance._createDragInitHandler();
  566. }
  567. // drag & drop listeners
  568. instance.on('drag:align', instance._onDragAlign);
  569. instance.on('drag:start', instance._onDragStart);
  570. instance.on('drop:exit', instance._onDropExit);
  571. instance.after('drop:hit', instance._afterDropHit);
  572. instance.on('drop:hit', instance._onDropHit);
  573. instance.on('drop:over', instance._onDropOver);
  574. },
  575. /**
  576. * Set the append CSS state on the passed <code>nodeContent</code>.
  577. *
  578. * @method _appendState
  579. * @param {Node} nodeContent
  580. * @protected
  581. */
  582. _appendState: function(nodeContent) {
  583. var instance = this;
  584. instance.dropAction = APPEND;
  585. instance.get(HELPER).addClass(CSS_TREE_DRAG_STATE_APPEND);
  586. nodeContent.addClass(CSS_TREE_DRAG_INSERT_APPEND);
  587. },
  588. /**
  589. * Set the going down CSS state on the passed <code>nodeContent</code>.
  590. *
  591. * @method _goingDownState
  592. * @param {Node} nodeContent
  593. * @protected
  594. */
  595. _goingDownState: function(nodeContent) {
  596. var instance = this;
  597. instance.dropAction = BELOW;
  598. instance.get(HELPER).addClass(CSS_TREE_DRAG_STATE_INSERT_BELOW);
  599. nodeContent.addClass(CSS_TREE_DRAG_INSERT_BELOW);
  600. },
  601. /**
  602. * Set the going up CSS state on the passed <code>nodeContent</code>.
  603. *
  604. * @method _goingUpState
  605. * @param {Node} nodeContent
  606. * @protected
  607. */
  608. _goingUpState: function(nodeContent) {
  609. var instance = this;
  610. instance.dropAction = ABOVE;
  611. instance.get(HELPER).addClass(CSS_TREE_DRAG_STATE_INSERT_ABOVE);
  612. nodeContent.addClass(CSS_TREE_DRAG_INSERT_ABOVE);
  613. },
  614. /**
  615. * Set the reset CSS state on the passed <code>nodeContent</code>.
  616. *
  617. * @method _resetState
  618. * @param {Node} nodeContent
  619. * @protected
  620. */
  621. _resetState: function(nodeContent) {
  622. var instance = this;
  623. var helper = instance.get(HELPER);
  624. helper.removeClass(CSS_TREE_DRAG_STATE_APPEND);
  625. helper.removeClass(CSS_TREE_DRAG_STATE_INSERT_ABOVE);
  626. helper.removeClass(CSS_TREE_DRAG_STATE_INSERT_BELOW);
  627. if (nodeContent) {
  628. nodeContent.removeClass(CSS_TREE_DRAG_INSERT_ABOVE);
  629. nodeContent.removeClass(CSS_TREE_DRAG_INSERT_APPEND);
  630. nodeContent.removeClass(CSS_TREE_DRAG_INSERT_BELOW);
  631. }
  632. },
  633. /**
  634. * Update the CSS node state (i.e. going down, going up, append etc).
  635. *
  636. * @method _updateNodeState
  637. * @param {EventFacade} event
  638. * @protected
  639. */
  640. _updateNodeState: function(event) {
  641. var instance = this;
  642. var drag = event.drag;
  643. var drop = event.drop;
  644. var nodeContent = drop.get(NODE);
  645. var dropNode = nodeContent.get(PARENT_NODE);
  646. var dragNode = drag.get(NODE).get(PARENT_NODE);
  647. var dropTreeNode = dropNode.getData(TREE_NODE);
  648. // reset the classNames from the last nodeContent
  649. instance._resetState(instance.nodeContent);
  650. // cannot drop the dragged element into any of its children
  651. // nor above an undraggable element
  652. // using DOM contains method for performance reason
  653. if (!!dropTreeNode.get(DRAGGABLE) && !dragNode.contains(dropNode)) {
  654. // nArea splits the height in 3 areas top/center/bottom
  655. // these areas are responsible for defining the state when the mouse is over any of them
  656. var nArea = nodeContent.get(OFFSET_HEIGHT) / 3;
  657. var yTop = nodeContent.getY();
  658. var yCenter = yTop + nArea;
  659. var yBottom = yTop + nArea*2;
  660. var mouseY = drag.mouseXY[1];
  661. // UP: mouse on the top area of the node
  662. if ((mouseY > yTop) && (mouseY < yCenter)) {
  663. instance._goingUpState(nodeContent);
  664. }
  665. // DOWN: mouse on the bottom area of the node
  666. else if (mouseY > yBottom) {
  667. instance._goingDownState(nodeContent);
  668. }
  669. // APPEND: mouse on the center area of the node
  670. else if ((mouseY > yCenter) && (mouseY < yBottom)) {
  671. // if it's a folder set the state to append
  672. if (dropTreeNode && !dropTreeNode.isLeaf()) {
  673. instance._appendState(nodeContent);
  674. }
  675. // if it's a leaf we need to set the ABOVE or BELOW state instead of append
  676. else {
  677. if (instance.direction === UP) {
  678. instance._goingUpState(nodeContent);
  679. }
  680. else {
  681. instance._goingDownState(nodeContent);
  682. }
  683. }
  684. }
  685. }
  686. instance.nodeContent = nodeContent;
  687. },
  688. /**
  689. * Fires after the drop hit event.
  690. *
  691. * @method _afterDropHit
  692. * @param {EventFacade} event drop hit event facade
  693. * @protected
  694. */
  695. _afterDropHit: function(event) {
  696. var instance = this;
  697. var dropAction = instance.dropAction;
  698. var dragNode = event.drag.get(NODE).get(PARENT_NODE);
  699. var dropNode = event.drop.get(NODE).get(PARENT_NODE);
  700. var dropTreeNode = dropNode.getData(TREE_NODE);
  701. var dragTreeNode = dragNode.getData(TREE_NODE);
  702. var output = instance.getEventOutputMap(instance);
  703. output.tree.dropNode = dropTreeNode;
  704. output.tree.dragNode = dragTreeNode;
  705. if (dropAction === ABOVE) {
  706. dropTreeNode.insertBefore(dragTreeNode);
  707. instance.bubbleEvent('dropInsert', output);
  708. }
  709. else if (dropAction === BELOW) {
  710. dropTreeNode.insertAfter(dragTreeNode);
  711. instance.bubbleEvent('dropInsert', output);
  712. }
  713. else if (dropAction === APPEND) {
  714. if (dropTreeNode && !dropTreeNode.isLeaf()) {
  715. if (!dropTreeNode.get(EXPANDED)) {
  716. // expand node when drop a child on it
  717. dropTreeNode.expand();
  718. }
  719. dropTreeNode.appendChild(dragTreeNode);
  720. instance.bubbleEvent('dropAppend', output);
  721. }
  722. }
  723. instance._resetState(instance.nodeContent);
  724. // bubbling drop event
  725. instance.bubbleEvent('drop', output);
  726. instance.dropAction = null;
  727. },
  728. /**
  729. * Fires on drag align event.
  730. *
  731. * @method _onDragAlign
  732. * @param {EventFacade} event append event facade
  733. * @protected
  734. */
  735. _onDragAlign: function(event) {
  736. var instance = this;
  737. var lastY = instance.lastY;
  738. var y = event.target.lastXY[1];
  739. // if the y change
  740. if (y !== lastY) {
  741. // set the drag direction
  742. instance.direction = (y < lastY) ? UP : DOWN;
  743. }
  744. instance.lastY = y;
  745. },
  746. /**
  747. * Fires on drag start event.
  748. *
  749. * @method _onDragStart
  750. * @param {EventFacade} event append event facade
  751. * @protected
  752. */
  753. _onDragStart: function(event) {
  754. var instance = this;
  755. var drag = event.target;
  756. var dragNode = drag.get(NODE).get(PARENT_NODE);
  757. var dragTreeNode = dragNode.getData(TREE_NODE);
  758. var lastSelected = instance.get(LAST_SELECTED);
  759. // select drag node
  760. if (lastSelected) {
  761. lastSelected.unselect();
  762. }
  763. dragTreeNode.select();
  764. // initialize drag helper
  765. var helper = instance.get(HELPER);
  766. var helperLabel = helper.one(DOT+CSS_TREE_DRAG_HELPER_LABEL);
  767. // show helper, we need display block here, yui dd hide it with display none
  768. helper.setStyle(DISPLAY, BLOCK).show();
  769. // set the CSS_TREE_DRAG_HELPER_LABEL html with the label of the dragged node
  770. helperLabel.html( dragTreeNode.get(LABEL) );
  771. // update the DRAG_NODE with the new helper
  772. drag.set(DRAG_NODE, helper);
  773. },
  774. /**
  775. * Fires on drop over event.
  776. *
  777. * @method _onDropOver
  778. * @param {EventFacade} event append event facade
  779. * @protected
  780. */
  781. _onDropOver: function(event) {
  782. var instance = this;
  783. instance._updateNodeState(event);
  784. },
  785. /**
  786. * Fires on drop hit event.
  787. *
  788. * @method _onDropHit
  789. * @param {EventFacade} event append event facade
  790. * @protected
  791. */
  792. _onDropHit: function(event) {
  793. var dropNode = event.drop.get(NODE).get(PARENT_NODE);
  794. var dropTreeNode = dropNode.getData(TREE_NODE);
  795. if (!isTreeNode(dropTreeNode)) {
  796. event.preventDefault();
  797. }
  798. },
  799. /**
  800. * Fires on drop exit event.
  801. *
  802. * @method _onDropExit
  803. * @param {EventFacade} event append event facade
  804. * @protected
  805. */
  806. _onDropExit: function() {
  807. var instance = this;
  808. instance.dropAction = null;
  809. instance._resetState(instance.nodeContent);
  810. }
  811. }
  812. }
  813. );
  814. A.TreeViewDD = TreeViewDD;
  815. }, '@VERSION@' ,{requires:['aui-tree-node','aui-tree-paginator','aui-tree-io','dd-delegate','dd-proxy'], skinnable:true});