CreationMenu.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. SC.loadPackage({ 'CreationMenu': {
  2. comment: 'I am the CreationMenu which is shown when the user drags over the document background.',
  3. sharedProperties: {
  4. menuContainer: { initValue: '<div id="sg-editing-creation-menu"><div id="sg-editing-creation-menu-items"></div></div>' },
  5. },
  6. properties: {
  7. myNode: { comment: 'I hold my DOM node.' },
  8. myItemsNode: { comment: 'I hold the DOM node for the items container.' },
  9. startX: { transform: function(anInt){
  10. return anInt;
  11. }
  12. },
  13. startY: { transform: function(anInt){
  14. return anInt;
  15. }
  16. },
  17. stopX: { transform: function(anInt){
  18. var startX = this.get('startX'),
  19. myNode = this.get('myNode'),
  20. grid = SuperGlue.get('document').get('grid'),
  21. gridSize = grid.get('gridSize'),
  22. left, width;
  23. if(anInt > startX){
  24. if(grid.get('active')){
  25. left = Math.floor(startX / gridSize) * gridSize;
  26. width = Math.ceil((anInt - startX) / gridSize) * gridSize;
  27. }else{
  28. left = startX;
  29. width = anInt - startX;
  30. }
  31. }else{
  32. if(grid.get('active')){
  33. left = Math.floor(anInt / gridSize) * gridSize;
  34. width = Math.ceil(startX / gridSize) * gridSize - Math.floor(anInt / gridSize) * gridSize;
  35. }else{
  36. left = anInt;
  37. width = startX - anInt;
  38. }
  39. }
  40. myNode.style.width = width + 'px';
  41. myNode.style.left = left + 'px';
  42. return anInt;
  43. }
  44. },
  45. stopY: { transform: function(anInt){
  46. var startY = this.get('startY'),
  47. myNode = this.get('myNode'),
  48. grid = SuperGlue.get('document').get('grid'),
  49. gridSize = grid.get('gridSize'),
  50. top, height;
  51. if(anInt > startY){
  52. if(grid.get('active')){
  53. top = Math.floor(startY / gridSize) * gridSize;
  54. height = Math.ceil((anInt - startY) / gridSize) * gridSize;
  55. }else{
  56. top = startY;
  57. height = anInt - startY;
  58. }
  59. }else{
  60. if(grid.get('active')){
  61. top = Math.floor(anInt / gridSize) * gridSize;
  62. height = Math.ceil(startY / gridSize) * gridSize - Math.floor(anInt / gridSize) * gridSize;
  63. }else{
  64. top = anInt;
  65. height = startY - anInt;
  66. }
  67. }
  68. myNode.style.height = height + 'px';
  69. myNode.style.top = top + 'px';
  70. return anInt;
  71. }
  72. },
  73. active: { comment: 'I store my state as a boolean.' }
  74. },
  75. methods: {
  76. init: {
  77. comment: 'I init myself.',
  78. code: function(){
  79. var self = this,
  80. myNode = (new DOMParser()).parseFromString(this.class.get('menuContainer'), 'text/html').body.firstChild,
  81. myItemsNode = myNode.firstChild,
  82. menuItemsClasses = (function(){
  83. return SC.getClasses().filter(function(classname){
  84. return SC.behavesLike(classname, 'Element');
  85. });
  86. }).call(this),
  87. menuItem = null;
  88. for(var i = menuItemsClasses.length - 1; i >= 0; i--){
  89. menuItem = (new DOMParser()).parseFromString(
  90. SC.getSharedProperty(menuItemsClasses[i], 'creationMenuItem'),
  91. 'text/html').body.firstChild;
  92. var onMouseUp = (function(classname){
  93. return function(evt){
  94. self.do('performCreation', classname);
  95. }
  96. }).call(this, menuItemsClasses[i])
  97. menuItem.addEventListener('mouseup', onMouseUp, false);
  98. myItemsNode.appendChild(menuItem);
  99. }
  100. this.set({
  101. myNode: myNode,
  102. myItemsNode: myItemsNode
  103. });
  104. }
  105. },
  106. trigger: {
  107. comment: 'Show me at { startX: anInt, startY: anInt }',
  108. code: function(myCoordinates){
  109. var self = this,
  110. myNode = this.get('myNode'),
  111. myItemsNode = this.get('myItemsNode'),
  112. editingContainer = SuperGlue.get('document').get('editingContainer');
  113. myItemsNode.style.display = 'none';
  114. this.set({
  115. startX: myCoordinates.startX,
  116. startY: myCoordinates.startY
  117. })
  118. if(myNode.parentNode !== editingContainer){
  119. editingContainer.appendChild(myNode);
  120. }
  121. this.set({ active: true })
  122. }
  123. },
  124. showItems: {
  125. comment: 'After dragging has finished, I am called to show the menu items to create an instance of a Element class.',
  126. code: function(){
  127. var myItemsNode = this.get('myItemsNode')
  128. westSide = this.get('stopX') < this.get('startX'),
  129. northSide = this.get('stopY') < this.get('startY');
  130. myItemsNode.className = '';
  131. if(westSide){
  132. if(northSide){
  133. myItemsNode.classList.add('sg-editing-creation-menu-nw');
  134. }else{
  135. myItemsNode.classList.add('sg-editing-creation-menu-sw');
  136. }
  137. }else{
  138. if(northSide){
  139. myItemsNode.classList.add('sg-editing-creation-menu-ne');
  140. }else{
  141. myItemsNode.classList.add('sg-editing-creation-menu-se');
  142. }
  143. }
  144. myItemsNode.style.display = 'block';
  145. }
  146. },
  147. close: {
  148. comment: 'Hide me!',
  149. code: function(){
  150. var myNode = this.get('myNode'),
  151. editingContainer = SuperGlue.get('document').get('editingContainer');
  152. if(myNode.parentNode === editingContainer){
  153. editingContainer.removeChild(myNode);
  154. }
  155. this.set({ active: false });
  156. }
  157. },
  158. performCreation: {
  159. comment: 'Tell the document to create a new Element.',
  160. code: function(classname){
  161. var myNodeStyle = this.get('myNode').style;
  162. SuperGlue.get('document').do('createNewElement', {
  163. classname: classname,
  164. top: parseInt(myNodeStyle.top),
  165. left: parseInt(myNodeStyle.left),
  166. width: parseInt(myNodeStyle.width),
  167. height: parseInt(myNodeStyle.height)
  168. });
  169. }
  170. }
  171. }
  172. }});