layout-grid.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. // LICENSE: BSD-3-Clause
  2. // http://git.io/vZkLP
  3. var LTGrid = (function ($) {
  4. 'use strict'
  5. /* exported Grid */
  6. /**
  7. * A collection of rect objects
  8. */
  9. var Grid = (function () {
  10. /**
  11. * @param {Array} rects array of Rect objects
  12. */
  13. function Grid(rects) {
  14. this.rects = rects || []
  15. }
  16. /**
  17. * Return all the rects that intersect with a given rect
  18. *
  19. * @param {Rect} rect
  20. * @return {Array}
  21. */
  22. Grid.prototype.getIntersectingRects = function (rect) {
  23. return this.rects.filter(function (item) {
  24. return rect !== item && rect.intersect(item)
  25. })
  26. }
  27. /**
  28. * Reduce all the vertical whitespace between rects
  29. *
  30. * @return {Grid} self
  31. */
  32. Grid.prototype.compact = function () {
  33. var rectsCopy = this.rects.slice(0)
  34. var self = this
  35. rectsCopy
  36. .sort(function (a, b) {
  37. return a.y - b.y
  38. })
  39. .forEach(function (item) {
  40. do {
  41. item.y -= 1
  42. } while (item.y >= 0 && self.getIntersectingRects(item).length === 0)
  43. item.y += 1
  44. })
  45. return this
  46. }
  47. /**
  48. * The maximum height of the rects in the grid
  49. *
  50. * @return {Number}
  51. */
  52. Grid.prototype.height = function () {
  53. var hights = this.rects.map(function (item) {
  54. return item.bottom()
  55. })
  56. return hights.length ? Math.max.apply(null, hights) : 0
  57. }
  58. /**
  59. * Move a rect inside the grid, or update its size
  60. * If there is overlap move rects downards
  61. *
  62. * @param {Rect} rect
  63. * @param {Object} params An object with optional keys x, y, w, h to modify the rect
  64. * @return {Grid} self
  65. */
  66. Grid.prototype.updateNoOverlap = function (rect, params) {
  67. var self = this
  68. this.update(rect, params)
  69. this.getIntersectingRects(rect)
  70. .forEach(function (item) {
  71. self.updateNoOverlap(item, { x: item.x, y: rect.bottom() })
  72. })
  73. return this
  74. }
  75. /**
  76. * Move a rect inside the grid, or update its size
  77. *
  78. * @param {Rect} rect
  79. * @param {Object} params An object with optional keys x, y, w, h to modify the rect
  80. * @return {Grid} self
  81. */
  82. Grid.prototype.update = function (rect, params) {
  83. rect.x = ('x' in params) ? params.x : rect.x
  84. rect.y = ('y' in params) ? params.y : rect.y
  85. rect.w = ('w' in params) ? params.w : rect.w
  86. rect.h = ('h' in params) ? params.h : rect.h
  87. return this
  88. }
  89. return Grid
  90. })()
  91. /* exported LTData */
  92. var LTData = (function ($) {
  93. var NAME = 'ltData'
  94. var LTData = {
  95. NAME: NAME
  96. }
  97. LTData.getRects = function (rects) {
  98. return $.map(rects, function (rect) {
  99. return new Rect(rect.x, rect.y, rect.w, rect.h)
  100. })
  101. }
  102. /**
  103. * Getter / setter for rects data
  104. *
  105. * @param {string} size xs, sm, md or lg
  106. * @param {Array} rects Array of Rect objects
  107. */
  108. $.fn[NAME] = function (size, rects) {
  109. var ltGrid = this[LTGrid.NAME]().data(LTGrid.DATA_KEY)
  110. if (undefined !== rects) {
  111. ltGrid
  112. .grid(size, new Grid(LTData.getRects(rects)))
  113. .update()
  114. return this
  115. }
  116. return ltGrid.grid(size).rects
  117. }
  118. return LTData
  119. })(jQuery)
  120. /* exported LTGrid */
  121. var LTGrid = (function ($) {
  122. /**
  123. * ------------------------------------------------------------------------
  124. * Constants
  125. * ------------------------------------------------------------------------
  126. */
  127. var NAME = 'ltGrid'
  128. var DATA_KEY = 'lt.grid'
  129. var EVENT_KEY = '.' + DATA_KEY
  130. var Event = {
  131. UPDATE : 'update',
  132. START : 'dragstart' + EVENT_KEY + ' touchstart' + EVENT_KEY,
  133. OVER : 'dragover' + EVENT_KEY + ' touchmove' + EVENT_KEY,
  134. END : 'dragend' + EVENT_KEY + ' touchcancel' + EVENT_KEY,
  135. DROP : 'drop' + EVENT_KEY + ' touchend' + EVENT_KEY,
  136. LEAVE : 'dragleave.' + EVENT_KEY
  137. }
  138. var Selector = {
  139. GRID : '[data-arrange="lt-grid"]',
  140. WIDGET : '[data-arrange="lt-grid"] .lt'
  141. }
  142. var Default = {
  143. resize: true,
  144. overlap: false,
  145. compact: true,
  146. params: {
  147. lg: {
  148. gap: 1,
  149. maxWidth: Number.MAX_VALUE,
  150. cols: 4,
  151. aspect: 2 / 3
  152. },
  153. md: {
  154. gap: 2,
  155. maxWidth: 1200,
  156. cols: 3,
  157. aspect: 2 / 3
  158. },
  159. sm: {
  160. gap: 3,
  161. maxWidth: 992,
  162. cols: 2,
  163. aspect: 2 / 3
  164. },
  165. xs: {
  166. gap: 4,
  167. maxWidth: 768,
  168. cols: 1,
  169. aspect: 2 / 3
  170. }
  171. }
  172. }
  173. /**
  174. * ------------------------------------------------------------------------
  175. * Class Definition
  176. * ------------------------------------------------------------------------
  177. */
  178. /**
  179. * @param {jQuery} element
  180. * @param {Object} options
  181. */
  182. function LTGrid(element, options) {
  183. this.$element = $(element)
  184. this._options = this._getOptions(options || {})
  185. this.$mask = undefined
  186. this.$ghost = undefined
  187. }
  188. // getters
  189. LTGrid.Default = Default
  190. LTGrid.NAME = NAME
  191. LTGrid.DATA_KEY = DATA_KEY
  192. LTGrid.EVENT_KEY = EVENT_KEY
  193. LTGrid.prototype.options = function () {
  194. return this._options
  195. }
  196. // public
  197. /**
  198. * Update an option directly
  199. *
  200. * @param {String} name
  201. * @param {mixed} value
  202. */
  203. LTGrid.prototype.option = function (name, value) {
  204. this._options[name] = value
  205. }
  206. /**
  207. * Get the current screen size
  208. * @return {String} xs, sm, md or lg
  209. */
  210. LTGrid.prototype.size = function () {
  211. var currentSize
  212. var windowWidth = this._windowWidth()
  213. for (var size in this._options.params) {
  214. if (windowWidth < this._options.params[size].maxWidth) {
  215. currentSize = size
  216. }
  217. }
  218. return currentSize
  219. }
  220. /**
  221. * Compact the grid for current size
  222. */
  223. LTGrid.prototype.compact = function () {
  224. var size = this.size()
  225. var grid = this.grid(size)
  226. this.grid(size, grid.compact())
  227. }
  228. /**
  229. * Resize container to match items
  230. */
  231. LTGrid.prototype.resize = function () {
  232. var size = this.size()
  233. var rect = new Rect(0, 0, 0, this.grid(size).height())
  234. var modifiedClass = rect.setCss(this.$element.attr('class'), size)
  235. this.$element.attr('class', modifiedClass)
  236. }
  237. /**
  238. * Clear artefacts like mask and ghost and update
  239. */
  240. LTGrid.prototype.end = function () {
  241. this._removeMask()
  242. this._removeGhost()
  243. this.update()
  244. }
  245. /**
  246. * Call resize and compact if allowed
  247. */
  248. LTGrid.prototype.update = function () {
  249. if (this._options.compact) {
  250. this.compact()
  251. }
  252. if (this._options.resize) {
  253. this.resize()
  254. }
  255. this.$element.trigger(Event.UPDATE)
  256. }
  257. /**
  258. * Setter / getter of a Grid object for this Layout Grid
  259. *
  260. * @param {String} size xs, sm, md or lg
  261. * @param {Grid} grid
  262. * @return {Grid}
  263. */
  264. LTGrid.prototype.grid = function (size, grid) {
  265. var $items = this.$element.children('[draggable]')
  266. if (undefined !== grid) {
  267. grid.rects.forEach(function (rect, index) {
  268. $items.eq(index)[LTRect.NAME](size, rect)
  269. })
  270. return this
  271. }
  272. return new Grid($.map($items.toArray(), function (item) {
  273. return $(item)[LTRect.NAME](size)
  274. }))
  275. }
  276. /**
  277. * Move a widget within the grid, repositioning other elements
  278. * so there is no overlapping
  279. *
  280. * @param {jQuery} $widget
  281. * @param {Object} params An object with optional keys x, y, w, h to modify the rect
  282. */
  283. LTGrid.prototype.reposition = function ($widget, params) {
  284. var size = this.size()
  285. var rect = $widget[LTRect.NAME](size)
  286. var grid = this.grid(size)
  287. if (this._options.overlap) {
  288. grid.update(rect, params)
  289. } else {
  290. grid.updateNoOverlap(rect, params)
  291. }
  292. this.grid(size, grid)
  293. this.update()
  294. }
  295. // private
  296. // ------------------------------------------------------------------------
  297. /**
  298. * Move the ghost element of a widget inside the grid.
  299. * Pass a mouse x and y coords, relative to the grid
  300. *
  301. * @param {jQuery} $widget
  302. * @param {Number} mouseX
  303. * @param {Number} mouseY
  304. */
  305. LTGrid.prototype._moveGhost = function ($widget, mouseX, mouseY) {
  306. var size = this.size()
  307. var $ghost = this._getGhost($widget)
  308. var rect = $ghost[LTRect.NAME](size)
  309. var gap = this._options.params[size].gap
  310. var cols = this._options.params[size].cols
  311. rect.x = Math.floor(mouseX / (this._itemWidth(size) + gap))
  312. rect.y = Math.floor(mouseY / (this._itemHeight(size) + gap))
  313. rect.x = Math.min(Math.max(0, rect.x), cols - rect.w)
  314. $ghost[LTRect.NAME](size, rect)
  315. }
  316. /**
  317. * Return a ghost item for a widget, cache ghost
  318. *
  319. * @param {jQuery} $widget
  320. * @return {jQuery}
  321. */
  322. LTGrid.prototype._getGhost = function ($widget) {
  323. if (undefined === this.$ghost) {
  324. this.$ghost = $('<div class="' + $widget.attr('class') + ' lt-ghost"></div>')
  325. this.$element.append(this.$ghost)
  326. }
  327. return this.$ghost
  328. }
  329. /**
  330. * Remove the ghost element for this grid
  331. *
  332. * @param {jQuery} $widget
  333. */
  334. LTGrid.prototype._removeGhost = function () {
  335. if (this.$ghost) {
  336. this.$ghost.remove()
  337. this.$ghost = undefined
  338. }
  339. }
  340. /**
  341. * Move the widget to its corresponding ghost position
  342. *
  343. * @param {jQuery} $widget
  344. */
  345. LTGrid.prototype._moveToGhost = function ($widget) {
  346. var size = this.size()
  347. var $parent = $widget.parent()
  348. var $ghost = this._getGhost($widget)
  349. var pos = $ghost[LTRect.NAME](size)
  350. this.$element.append($widget)
  351. this.reposition($widget, { x: pos.x, y: pos.y })
  352. $parent.add(this.$element)[NAME]('update')
  353. }
  354. /**
  355. * Get the mask of the grid. Create one if there is none.
  356. *
  357. * @return {jQuery}
  358. */
  359. LTGrid.prototype._getMask = function () {
  360. if (undefined === this.$mask) {
  361. this.$mask = $('<div class="lt-mask" data-lt-grid="mask"></div>')
  362. this.$element.append(this.$mask)
  363. }
  364. return this.$mask
  365. }
  366. /**
  367. * Remove the mask
  368. */
  369. LTGrid.prototype._removeMask = function () {
  370. if (undefined !== this.$mask) {
  371. this.$mask.remove()
  372. this.$mask = undefined
  373. }
  374. }
  375. /**
  376. * The width of a single grid count, in pixels
  377. *
  378. * @param {String} size xs, sm, md or lg
  379. * @return {Number}
  380. */
  381. LTGrid.prototype._itemWidth = function (size) {
  382. var cols = this._options.params[size].cols
  383. var gap = this._options.params[size].gap
  384. return (this.$element.width() - (cols - 1) * gap) / cols
  385. }
  386. /**
  387. * The height of a single grid count, in pixels
  388. *
  389. * @param {String} size xs, sm, md or lg
  390. * @return {Number}
  391. */
  392. LTGrid.prototype._itemHeight = function (size) {
  393. var aspect = this._options.params[size].aspect
  394. return this._itemWidth(size) * aspect
  395. }
  396. /**
  397. * Return the current window width
  398. *
  399. * @return {Number}
  400. */
  401. LTGrid.prototype._windowWidth = function () {
  402. return $(window).width()
  403. }
  404. LTGrid.prototype._getOptions = function (options) {
  405. return $.extend(true, {}, Default, options)
  406. }
  407. // static
  408. LTGrid._jQueryInterface = function (config, a1, a2, a3) {
  409. return this.each(function () {
  410. var $this = $(this)
  411. var data = $this.data(DATA_KEY)
  412. var _config = $.extend(
  413. true,
  414. {},
  415. Default,
  416. $this.data(),
  417. typeof config === 'object' && config
  418. )
  419. if (!data) {
  420. data = new LTGrid(this, _config)
  421. $this.data(DATA_KEY, data)
  422. }
  423. if (typeof config === 'string') {
  424. data[config](a1, a2, a3)
  425. }
  426. })
  427. }
  428. /**
  429. * ------------------------------------------------------------------------
  430. * Data Api implementation
  431. * ------------------------------------------------------------------------
  432. */
  433. $(document)
  434. .on(Event.START, Selector.WIDGET, function (event) {
  435. Store.set(event.originalEvent, this)
  436. })
  437. .on(Event.OVER, Selector.GRID, function (event) {
  438. var original = event.originalEvent
  439. var $widget = $(Store.get(original))
  440. if ($widget.length) {
  441. var pos = original.touches ? original.touches[0] : original
  442. var $this = $(this)
  443. var mouseX = pos.pageX - $this.offset().left
  444. var mouseY = pos.pageY - $this.offset().top
  445. var grid = $this[NAME]().data(DATA_KEY)
  446. event.preventDefault()
  447. grid._getMask()
  448. grid._moveGhost($widget, mouseX, mouseY)
  449. }
  450. })
  451. .on(Event.END, Selector.GRID, function () {
  452. $(this)[NAME]('end')
  453. })
  454. .on(Event.LEAVE, Selector.GRID, function (event) {
  455. event.preventDefault()
  456. if ($(event.target).data('lt-grid') === 'mask') {
  457. $(this)[NAME]('end')
  458. }
  459. })
  460. .on(Event.DROP, Selector.GRID, function (event) {
  461. var $widget = $(Store.get(event.originalEvent))
  462. if ($widget.length) {
  463. var $this = $(this)
  464. var grid = $this[NAME]().data(DATA_KEY)
  465. event.preventDefault()
  466. grid._moveToGhost($widget)
  467. grid.end()
  468. }
  469. })
  470. /**
  471. * ------------------------------------------------------------------------
  472. * jQuery
  473. * ------------------------------------------------------------------------
  474. */
  475. $.fn[NAME] = LTGrid._jQueryInterface
  476. $.fn[NAME].LTGrid = LTGrid
  477. return LTGrid
  478. })(jQuery)
  479. /* exported LTGridOnly */
  480. var LTGridOnly = (function ($) {
  481. /**
  482. * ------------------------------------------------------------------------
  483. * Constants
  484. * ------------------------------------------------------------------------
  485. */
  486. var NAME = 'ltGridOnly'
  487. var DATA_KEY = 'lt.grid-only'
  488. var EVENT_KEY = '.' + DATA_KEY
  489. var Event = {
  490. CLICK : 'click' + EVENT_KEY
  491. }
  492. var Css = {
  493. xs : 'lt-only-xs',
  494. sm : 'lt-only-sm',
  495. md : 'lt-only-md',
  496. lg : 'lt-only-lg'
  497. }
  498. var Selector = {
  499. TOGGLE : '[data-toggle="lt-grid-only"]'
  500. }
  501. /**
  502. * ------------------------------------------------------------------------
  503. * Class Definition
  504. * ------------------------------------------------------------------------
  505. */
  506. /**
  507. * @param {jQuery} element
  508. * @param {Object} options
  509. */
  510. function LTGridOnly(element, options) {
  511. this.$element = $(element)
  512. this.$target = $(options.target)[LTGrid.NAME]()
  513. this.ltGrid = this.$target.data(LTGrid.DATA_KEY)
  514. }
  515. // getters
  516. LTGridOnly.NAME = NAME
  517. LTGridOnly.DATA_KEY = DATA_KEY
  518. LTGridOnly.EVENT_KEY = EVENT_KEY
  519. // public
  520. /**
  521. * Save original params for later use
  522. */
  523. LTGridOnly.prototype.originalParams = function () {
  524. if (undefined === this.ltGrid.options().originalParams) {
  525. this.ltGrid.options().originalParams = this.ltGrid.options().params
  526. }
  527. return this.ltGrid.options().originalParams
  528. }
  529. /**
  530. * Compact the grid for current size
  531. * @param {String} size
  532. */
  533. LTGridOnly.prototype.set = function (size) {
  534. var original = this.originalParams()
  535. var onlyClasses = $.map(
  536. Css,
  537. function (name) {
  538. return name
  539. }
  540. )
  541. this.$target.removeClass(onlyClasses.join(' '))
  542. if (size) {
  543. var params = {}
  544. params[size] = original[size]
  545. params[size].maxWidth = Number.MAX_VALUE
  546. this.$target.addClass(Css[size])
  547. this.ltGrid.option('params', params)
  548. } else {
  549. this.ltGrid.option('params', original)
  550. }
  551. }
  552. // static
  553. LTGridOnly._jQueryInterface = function (config, a1) {
  554. return this.each(function () {
  555. var $this = $(this)
  556. var data = $this.data(DATA_KEY)
  557. var _config = $.extend(
  558. true,
  559. {},
  560. $this.data(),
  561. typeof config === 'object' && config
  562. )
  563. if (!data) {
  564. data = new LTGridOnly(this, _config)
  565. $this.data(DATA_KEY, data)
  566. }
  567. if (typeof config === 'string') {
  568. data[config](a1)
  569. }
  570. })
  571. }
  572. /**
  573. * ------------------------------------------------------------------------
  574. * Data Api implementation
  575. * ------------------------------------------------------------------------
  576. */
  577. $(document)
  578. .on(Event.CLICK, Selector.TOGGLE, function (event) {
  579. var $item = $(event.target)
  580. $item[LTGridOnly.NAME]('set', $item.data('only'))
  581. })
  582. /**
  583. * ------------------------------------------------------------------------
  584. * jQuery
  585. * ------------------------------------------------------------------------
  586. */
  587. $.fn[NAME] = LTGridOnly._jQueryInterface
  588. $.fn[NAME].LTGridOnly = LTGridOnly
  589. return LTGridOnly
  590. })(jQuery)
  591. /* exported LTRect */
  592. var LTRect = (function ($) {
  593. var NAME = 'ltRect'
  594. var DATA_KEY = 'lt.rect'
  595. var LTRect = {
  596. NAME: NAME,
  597. DATA_KEY: DATA_KEY
  598. }
  599. /**
  600. * Getter / setter for div element's rect.
  601. * Uses its css classes to laod the initial rect for a given size,
  602. * then caches in data.
  603. * Each screen size has its own rect
  604. *
  605. * @param {string} size xs, sm, md or lg
  606. * @param {Rect} newRect a Rect object to set
  607. * @return {jQuery}
  608. */
  609. $.fn[NAME] = function (size, newRect) {
  610. if (undefined === newRect) {
  611. if (undefined === this.data(DATA_KEY + size)) {
  612. this.data(DATA_KEY + size, (new Rect()).loadCss(this.attr('class'), size))
  613. }
  614. return this.data(DATA_KEY + size)
  615. }
  616. this.data(DATA_KEY + size, newRect)
  617. this.attr('class', newRect.setCss(this.attr('class'), size))
  618. return this
  619. }
  620. return LTRect
  621. })(jQuery)
  622. /* exported LTSize */
  623. var LTSize = (function ($) {
  624. var NAME = 'ltSize'
  625. var LTSize = {
  626. NAME: NAME
  627. }
  628. /**
  629. * Get the current size of the grid
  630. */
  631. $.fn[NAME] = function () {
  632. return this[LTGrid.NAME]().data(LTGrid.DATA_KEY).size()
  633. }
  634. return LTSize
  635. })(jQuery)
  636. /* exported Rect */
  637. /**
  638. * Object that represents a rectangle with many supporting methods
  639. */
  640. var Rect = (function () {
  641. var paramNames = ['x', 'y', 'w', 'h']
  642. /**
  643. * @param {Number} x default 0
  644. * @param {Number} y default 0
  645. * @param {Number} w width, default 1
  646. * @param {Number} h height, default 1
  647. */
  648. function Rect(x, y, w, h) {
  649. this.x = x || 0
  650. this.y = y || 0
  651. this.w = w || 1
  652. this.h = h || 1
  653. }
  654. /**
  655. * @return {Number}
  656. */
  657. Rect.prototype.bottom = function () {
  658. return this.y + this.h
  659. }
  660. /**
  661. * @return {Number}
  662. */
  663. Rect.prototype.right = function () {
  664. return this.x + this.w
  665. }
  666. /**
  667. * Check if this rect is intersecting with another rect
  668. *
  669. * @param {Rect} rect
  670. * @return {Boolean}
  671. */
  672. Rect.prototype.intersect = function (rect) {
  673. return this.x < rect.right() && this.right() > rect.x && this.y < rect.bottom() && this.bottom() > rect.y
  674. }
  675. /**
  676. * Modify a "css classes" string
  677. * with the pos and size of this rect,
  678. * for a specific screen size
  679. *
  680. * @param {String} classes html classes
  681. * @param {String} size xs, sm, md or lg
  682. * @return {String}
  683. */
  684. Rect.prototype.setCss = function (classes, size) {
  685. var self = this
  686. paramNames.forEach(function (name) {
  687. classes = classes.replace(new RegExp('lt-' + size + '-' + name + '-(\\d+)'), 'lt-' + size + '-' + name + '-' + self[name])
  688. })
  689. return classes
  690. }
  691. /**
  692. * Load data from "css classes", for a specific screen size
  693. *
  694. * @param {String} classes html classes
  695. * @param {String} size xs, sm, md or lg
  696. */
  697. Rect.prototype.loadCss = function (classes, size) {
  698. var self = this
  699. paramNames.forEach(function (name) {
  700. var match = classes.match(new RegExp('lt-' + size + '-' + name + '-(\\d+)'))
  701. if (match) {
  702. self[name] = parseInt(match[1], 10)
  703. }
  704. })
  705. return this
  706. }
  707. return Rect
  708. })()
  709. /* exported Store */
  710. /**
  711. * A class to store / retrieve element inside of dataTransfer object of an event
  712. * Fall back to a static variable if dataTransfer is not available
  713. */
  714. var Store = (function () {
  715. var Store = {}
  716. /**
  717. * Genrate a time based random number
  718. *
  719. * @return {Number}
  720. */
  721. Store.getRandomNumber = function () {
  722. return Math.round(new Date().getTime() + (Math.random() * 100))
  723. }
  724. /**
  725. * Make sure the item has an id to quickly find it
  726. * Do not override existing ids
  727. *
  728. * @param {Element} item
  729. * @return {String}
  730. */
  731. Store.getId = function (item) {
  732. if (!item.id) {
  733. item.id = 'lt-' + this.getRandomNumber()
  734. }
  735. return item.id
  736. }
  737. /**
  738. * Clear internal storage variable
  739. */
  740. Store.clear = function () {
  741. this.item = null
  742. }
  743. /**
  744. * Save the element
  745. *
  746. * @param {Event} event
  747. * @param {Element} item
  748. */
  749. Store.set = function (event, item) {
  750. this.item = JSON.stringify({
  751. LTWidget: this.getId(item)
  752. })
  753. if (event.dataTransfer) {
  754. event.dataTransfer.setData('text', this.item)
  755. }
  756. }
  757. /**
  758. * Retrieve stored element
  759. *
  760. * @param {Event} event
  761. * @return {Element}
  762. */
  763. Store.get = function (event) {
  764. var dataString = (event.dataTransfer && event.dataTransfer.getData('text')) || this.item
  765. if (dataString) {
  766. var data = JSON.parse(dataString)
  767. return document.getElementById(data.LTWidget)
  768. }
  769. }
  770. return Store
  771. })()
  772. LTGrid.Rect = Rect
  773. LTGrid.Grid = Grid
  774. return LTGrid
  775. })(jQuery)
  776. //# sourceMappingURL=layout-grid.js.map