Grid.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. SC.loadPackage({ 'Grid': {
  2. comment: 'I provide a grid for the page, with controls to set the configuration of the grid. When I am active, I arrange Elements with my method Grid>>arrangeElement.',
  3. properties: {
  4. gridContainer: { comment: 'I hold the DOM container in which the grid is shown as background image. ' },
  5. gridControl: { comment: 'I hold the DOM container for the grid controls.' },
  6. myDocument: { comment: 'I store a reference to my document.' },
  7. active: { comment: 'Wether the grid is active.',
  8. transform: function(aBoolean){
  9. if(aBoolean){
  10. this.get('gridContainer').style.opacity = 1;
  11. }else{
  12. this.get('gridContainer').style.opacity = 0;
  13. }
  14. return aBoolean;
  15. }
  16. },
  17. gridSize: { comment: 'The grid size in pixel.',
  18. transform: function(anInt){
  19. var canvas, ctx;
  20. if(anInt >= 7){
  21. canvas = document.createElement('canvas');
  22. canvas.width = anInt;
  23. canvas.height = anInt;
  24. ctx = canvas.getContext('2d');
  25. ctx.strokeStyle = 'rgba(255,41,61,0.4)';
  26. ctx.beginPath();
  27. ctx.moveTo(anInt, 0);
  28. ctx.lineTo(anInt, anInt);
  29. ctx.stroke();
  30. ctx.beginPath();
  31. ctx.moveTo(0, anInt);
  32. ctx.lineTo(anInt, anInt);
  33. ctx.stroke();
  34. this.get('gridContainer').style.backgroundImage = 'url("' + canvas.toDataURL() + '")';
  35. }
  36. return anInt < 7 ? 0 : anInt;
  37. }
  38. },
  39. visible: { comment: 'Wether I am visible or not.',
  40. transform: function(aBoolean){
  41. if(aBoolean){
  42. if(this.get('active')){
  43. this.get('gridContainer').style.opacity = 1;
  44. }else{
  45. this.get('gridContainer').style.opacity = 0;
  46. }
  47. this.get('gridControl').classList.remove('sg-editing-grid-control-hidden');
  48. }else{
  49. this.get('gridContainer').style.opacity = 0;
  50. this.get('gridControl').classList.add('sg-editing-grid-control-hidden');
  51. }
  52. return aBoolean;
  53. }
  54. }
  55. },
  56. methods: {
  57. init: {
  58. comment: 'I initalize myself.',
  59. code: function(theDocument){
  60. this.set({ myDocument: theDocument });
  61. var self = this,
  62. pageContainer = theDocument.get('pageContainer'),
  63. config = pageContainer.getAttribute('data-superglue-grid').split('/'),
  64. active = config[0] === 'on',
  65. gridSize = active ? parseInt(config[1]) : 0,
  66. gridContainer = this.set({ gridContainer: (function(){
  67. var gridContainer = document.createElement('div');
  68. gridContainer.setAttribute('id', 'sg-editing-grid-container');
  69. return gridContainer;
  70. }).call(this)
  71. }),
  72. gridControl = this.set({ gridControl: (function(){
  73. var gridControl = document.createElement('div');
  74. gridControl.setAttribute('id', 'sg-editing-grid-control');
  75. theDocument.get('editingContainer').appendChild(gridControl);
  76. return gridControl;
  77. }).call(this)
  78. });
  79. document.body.insertBefore(gridContainer, this.get('myDocument').get('pageContainer'));
  80. window.addEventListener('resize', function(){
  81. self.do('updateDimensions');
  82. }, false);
  83. this.set({
  84. active: active,
  85. gridSize: gridSize
  86. });
  87. this.do('initGridControl');
  88. }
  89. },
  90. updateDimensions: {
  91. comment: 'I update the gridContainer\'s dimensions and position.',
  92. code: function(newConfig){
  93. var gridContainer = this.get('gridContainer');
  94. var layout = newConfig ? newConfig : SuperGlue.get('document').get('layout'),
  95. minHeight = SuperGlue.get('document') ? SuperGlue.get('document').do('getMinHeight') : 0,
  96. minWidth;
  97. if(layout.centered){
  98. if(window.innerWidth >= layout.width){
  99. gridContainer.style.width = layout.width + 'px';
  100. gridContainer.style.left = '50%';
  101. gridContainer.style.marginLeft = layout.width / -2 + 'px';
  102. }else{
  103. gridContainer.style.width = layout.width + 'px';
  104. gridContainer.style.left = '0px';
  105. gridContainer.style.marginLeft = '0px';
  106. }
  107. }else{
  108. minWidth = SuperGlue.get('document') ? SuperGlue.get('document').do('getMinWidth') : 0;
  109. gridContainer.style.width = (minWidth < window.innerWidth - 20 ? window.innerWidth - 20 : minWidth) + 'px';
  110. gridContainer.style.left = '0px';
  111. gridContainer.style.marginLeft = '0px';
  112. }
  113. gridContainer.style.height = (minHeight < window.innerHeight ? window.innerHeight : minHeight) + 'px';
  114. }
  115. },
  116. initGridControl: {
  117. comment: 'I init the gridControl.',
  118. code: function(){
  119. var self = this,
  120. startX,
  121. gridSize,
  122. wasVisible,
  123. gridControl = this.get('gridControl'),
  124. allElements,
  125. allElementDimensions,
  126. pageWidth,
  127. onMouseDown = function(evt){
  128. startX = evt.pageX;
  129. gridSize = self.get('gridSize');
  130. SuperGlue.get('document').set({ interactionInProgress: true });
  131. SuperGlue.get('selection').do('clearAll');
  132. wasVisible = self.get('visible');
  133. self.set({ visible: true });
  134. allElements = SuperGlue.get('document').get('children');
  135. allElementDimensions = [];
  136. for(var i = 0, l = allElements.length; i < l; i++){
  137. allElementDimensions.push({
  138. top: allElements[i].get('top'),
  139. left: allElements[i].get('left'),
  140. width: allElements[i].get('width'),
  141. height: allElements[i].get('height')
  142. })
  143. }
  144. pageWidth = self.get('myDocument').get('layout').width;
  145. // Undo
  146. (function(gridSize, active, allElements, allElementDimensions){
  147. SuperGlue.get('history').do('actionHasStarted', function(){
  148. self.set({
  149. gridSize: gridSize,
  150. active: active
  151. });
  152. if(active){
  153. self.get('gridControl').style.left = self.get('gridSize') * 2 + 'px';
  154. }else{
  155. self.get('gridControl').style.left = '0px';
  156. }
  157. for(var i = 0, l = allElements.length; i < l; i++){
  158. allElements[i].set({
  159. top: allElementDimensions[i].top,
  160. left: allElementDimensions[i].left,
  161. width: allElementDimensions[i].width,
  162. height: allElementDimensions[i].height
  163. })
  164. }
  165. })
  166. }).call(this, gridSize, self.get('active'), allElements, allElementDimensions)
  167. document.addEventListener('mousemove', onMouseMove, true);
  168. document.addEventListener('mouseup', onMouseUp, true);
  169. evt.stopPropagation();
  170. evt.preventDefault();
  171. },
  172. onMouseMove = function(evt){
  173. var newGridSize = Math.floor(gridSize + ((evt.pageX - startX) / 2));
  174. if(newGridSize < 7){
  175. if(self.get('active')){
  176. self.set({ active: false });
  177. }
  178. gridControl.style.left = '0px';
  179. newGridSize = 0;
  180. }else if(newGridSize > 70){
  181. self.set({ gridSize: 70 });
  182. gridControl.style.left = '140px';
  183. }else{
  184. if(!self.get('active')){
  185. self.set({ active: true });
  186. }
  187. self.set({ gridSize: newGridSize });
  188. gridControl.style.left = newGridSize * 2 + 'px';
  189. }
  190. for(var i = 0, l = allElements.length; i < l; i++){
  191. allElements[i].set(allElementDimensions[i]);
  192. if(pageWidth && (allElements[i].get('left') + allElements[i].get('width')) > pageWidth){
  193. var newLeft = allElements[i].get('left'),
  194. newWidth = allElements[i].get('width');
  195. while(newLeft + newWidth > pageWidth){
  196. newLeft = allElements[i].set({
  197. left: (allElementDimensions[i].left - 0.5 * newGridSize)
  198. });
  199. newWidth = allElements[i].set({
  200. width: (allElementDimensions[i].width - newGridSize)
  201. });
  202. }
  203. }
  204. }
  205. },
  206. onMouseUp = function(evt){
  207. document.removeEventListener('mousemove', onMouseMove, true);
  208. document.removeEventListener('mouseup', onMouseUp, true);
  209. SuperGlue.get('document').set({ interactionInProgress: false });
  210. self.set({ visible: wasVisible });
  211. // Redo
  212. (function(gridSize, active, allElements){
  213. var allElementDimensions = [];
  214. for(var i = 0, l = allElements.length; i < l; i++){
  215. allElementDimensions.push({
  216. top: allElements[i].get('top'),
  217. left: allElements[i].get('left'),
  218. width: allElements[i].get('width'),
  219. height: allElements[i].get('height')
  220. })
  221. }
  222. SuperGlue.get('history').do('actionHasSucceeded', function(){
  223. self.set({
  224. gridSize: gridSize,
  225. active: active
  226. });
  227. if(active){
  228. self.get('gridControl').style.left = self.get('gridSize') * 2 + 'px';
  229. }else{
  230. self.get('gridControl').style.left = '0px';
  231. }
  232. for(var i = 0, l = allElements.length; i < l; i++){
  233. allElements[i].set({
  234. top: allElementDimensions[i].top,
  235. left: allElementDimensions[i].left,
  236. width: allElementDimensions[i].width,
  237. height: allElementDimensions[i].height
  238. })
  239. }
  240. })
  241. }).call(this, self.get('gridSize'), self.get('active'), SuperGlue.get('document').get('children') )
  242. evt.stopPropagation();
  243. evt.preventDefault();
  244. };
  245. gridControl.style.left = this.get('gridSize') * 2 + 'px';
  246. gridControl.addEventListener('mousedown', onMouseDown, false);
  247. }
  248. }
  249. }
  250. }});