├── .gitignore
├── Cakefile
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── Rakefile
├── bower.json
├── gridly.jquery.json
├── images
├── fork.png
├── tar.png
└── zip.png
├── index.haml
├── index.html
├── javascripts
├── jquery.gridly.coffee
├── jquery.gridly.js
├── jquery.js
├── rainbow.js
├── sample.coffee
└── sample.js
├── package.json
├── packages
├── jquery.gridly.tar
└── jquery.gridly.zip
└── stylesheets
├── jquery.gridly.css
├── jquery.gridly.sass
├── sample.css
└── sample.sass
/.gitignore:
--------------------------------------------------------------------------------
1 | .sass*
--------------------------------------------------------------------------------
/Cakefile:
--------------------------------------------------------------------------------
1 | PROJECT = "jquery.gridly"
2 |
3 | {spawn, exec} = require "child_process"
4 |
5 | command = (name, args...) ->
6 | proc = spawn name, args
7 |
8 | proc.stderr.on "data", (buffer) ->
9 | console.log buffer.toString()
10 |
11 | proc.stdout.on "data", (buffer) ->
12 | console.log buffer.toString()
13 |
14 | proc.on "exit", (status) -> process.exit(1) if status != 0
15 |
16 | task "watch", "SASS and CoffeeScript", (options) ->
17 | command "sass", "--sourcemap=none", "--watch", "stylesheets:stylesheets"
18 | command "sass", "--sourcemap=none", "--watch", "spec:spec"
19 | command "coffee", "-wc", "javascripts"
20 | command "coffee", "-wc", "spec"
21 |
22 | task "compile", "HAML", (opions) ->
23 | command "haml", "index.haml", "index.html"
24 |
25 | task "package", "Package CSS and JS", (options) ->
26 | command "zip", "packages/#{PROJECT}.zip",
27 | "javascripts/#{PROJECT}.js",
28 | "stylesheets/#{PROJECT}.css",
29 | command "tar", "-cf",
30 | "packages/#{PROJECT}.tar",
31 | "javascripts/#{PROJECT}.js",
32 | "stylesheets/#{PROJECT}.css",
33 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'rake'
4 | gem 'haml'
5 | gem 'sass'
6 | gem 'jasmine'
7 | gem 'listen'
8 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | bourbon (7.0.0)
5 | thor (~> 1.0)
6 | ffi (1.13.1)
7 | haml (5.1.2)
8 | temple (>= 0.8.0)
9 | tilt
10 | jasmine (3.5.1)
11 | jasmine-core (~> 3.5.0)
12 | phantomjs
13 | rack (>= 1.2.1)
14 | rake
15 | jasmine-core (3.5.0)
16 | listen (3.2.1)
17 | rb-fsevent (~> 0.10, >= 0.10.3)
18 | rb-inotify (~> 0.9, >= 0.9.10)
19 | neat (1.7.4)
20 | bourbon (>= 4.0)
21 | sass (>= 3.3)
22 | phantomjs (2.1.1.0)
23 | rack (2.2.3)
24 | rake (13.0.1)
25 | rb-fsevent (0.10.4)
26 | rb-inotify (0.10.1)
27 | ffi (~> 1.0)
28 | sass (3.7.4)
29 | sass-listen (~> 4.0.0)
30 | sass-listen (4.0.0)
31 | rb-fsevent (~> 0.9, >= 0.9.4)
32 | rb-inotify (~> 0.9, >= 0.9.7)
33 | temple (0.8.2)
34 | thor (1.0.1)
35 | tilt (2.0.10)
36 |
37 | PLATFORMS
38 | ruby
39 |
40 | DEPENDENCIES
41 | bourbon
42 | haml
43 | jasmine
44 | listen
45 | neat
46 | rake
47 | sass
48 |
49 | BUNDLED WITH
50 | 2.1.4
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 - 2013 Kevin Sylvestre
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jQuery Gridly
2 |
3 | Gridly is a jQuery plugin to enable dragging and dropping as well as resizing on a grid.
4 |
5 | ## Installation
6 |
7 | To install copy the *javascripts* and *stylesheets* directories into your project and add the following snippet to the header:
8 |
9 |
10 |
11 |
12 |
13 | This plugin is also registered under http://bower.io/ to simplify integration. Try:
14 |
15 | npm install -g bower
16 | bower install gridly
17 |
18 | Lastly this plugin is registered as a https://rails-assets.org/ to simplify integration with Ruby on Rails applications:
19 |
20 | **Gemfile**
21 |
22 | + source 'https://rails-assets.org'
23 | ...
24 | + gem 'rails-assets-gridly'
25 |
26 | **application.css**
27 |
28 | /*
29 | ...
30 | *= require gridly
31 | ...
32 | */
33 |
34 | **application.js**
35 |
36 | //= require jquery
37 | ...
38 | //= require gridly
39 |
40 | ## Examples
41 |
42 | Setting up a gridly is easy. The following snippet is a good start:
43 |
44 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
68 |
69 | ## Configuration
70 |
71 | Gridly uses a fairly standard pattern for handling grids and offers three configuration options for sizing: *base*, *gutter* and *columns*:
72 |
73 | $('.gridly').gridly({
74 | base: 60, // px
75 | gutter: 20, // px
76 | columns: 12
77 | });
78 |
79 | When using the drag and drop sorting callbacks can be passed in when initializing:
80 |
81 | var reordering = function($elements) {
82 | // Called before the drag and drop starts with the elements in their starting position.
83 | };
84 |
85 | var reordered = function($elements) {
86 | // Called after the drag and drop ends with the elements in their ending position.
87 | };
88 |
89 | $('.gridly').gridly({
90 | callbacks: { reordering: reordering , reordered: reordered }
91 | });
92 |
93 |
94 | $('.gridly').gridly('draggable', 'off'); // disables dragging
95 | $('.gridly').gridly('draggable', 'on); // enables dragging
96 |
97 | ## Contributing
98 |
99 | Gridly is maintained in `CoffeeScript`. All contributions need to be submitted in `CoffeeScript`. The project includes a `Cakefile` that can be used to compile all assets (see: `cake watch`). For more information about `CoffeeScript` see:
100 |
101 | - http://coffeescript.org/
102 | - http://arcturo.github.io/library/coffeescript/
103 |
104 | ## Status
105 |
106 | [](https://travis-ci.org/ksylvest/jquery-gridly)
107 |
108 | ## Copyright
109 |
110 | Copyright (c) 2013 - 2015 Kevin Sylvestre. See LICENSE for details.
111 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 |
2 | begin
3 | require 'jasmine'
4 | load 'jasmine/tasks/jasmine.rake'
5 | rescue LoadError
6 | task :jasmine do
7 | abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gridly",
3 | "version": "1.3.0",
4 | "main": [ "./javascripts/jquery.gridly.js","./stylesheets/jquery.gridly.css" ],
5 | "ignore":
6 | [
7 | "README*",
8 | "LICENSE*",
9 | "**/*.sass",
10 | "**/*.coffee",
11 | "**/sample.*",
12 | "**/rainbow.js",
13 | "**/rainbow.css",
14 | "**/jquery.js",
15 | "**/jquery.css",
16 | "samples",
17 | "spec",
18 | "bourbon",
19 | "neat",
20 | "packages",
21 | "images",
22 | "Cakefile*",
23 | "Rakefile*",
24 | "Gemfile*",
25 | ".git*",
26 | ".travis*",
27 | "*bower.json",
28 | "*jquery.json",
29 | "index*"
30 | ],
31 | "dependencies": { "jquery": "latest" }
32 | }
33 |
--------------------------------------------------------------------------------
/gridly.jquery.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gridly",
3 | "title": "jQuery Gridly",
4 | "description": "Gridly is a jQuery plugin that allows for dragging and dropping as well as resizing.",
5 | "keywords": ["grid","animation"],
6 | "version": "1.3.0",
7 | "author": {
8 | "name": "Kevin Sylvestre",
9 | "email": "kevin@ksylvest.com",
10 | "url": "http://ksylvest.com/"
11 | },
12 | "licenses":
13 | [
14 | {
15 | "type": "MIT",
16 | "url": "https://github.com/ksylvest/jquery-gridly/LICENSE"
17 | }
18 | ],
19 | "bugs": "https://github.com/ksylvest/jquery-gridly/issues",
20 | "docs": "https://ksylvest.github.com/jquery-gridly",
21 | "homepage": "https://ksylvest.github.com/jquery-gridly",
22 | "download": "https://ksylvest.github.com/jquery-gridly",
23 | "dependencies":
24 | {
25 | "jquery": ">1.5"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/images/fork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ksylvest/jquery-gridly/65d1e4bfdc3f16cd837710d8b631b91c4db01ddc/images/fork.png
--------------------------------------------------------------------------------
/images/tar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ksylvest/jquery-gridly/65d1e4bfdc3f16cd837710d8b631b91c4db01ddc/images/tar.png
--------------------------------------------------------------------------------
/images/zip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ksylvest/jquery-gridly/65d1e4bfdc3f16cd837710d8b631b91c4db01ddc/images/zip.png
--------------------------------------------------------------------------------
/index.haml:
--------------------------------------------------------------------------------
1 | !!! 5
2 | %html
3 | %head
4 | %meta{ charset: "UTF-8" }
5 | %title jQuery Gridly
6 | %link{ href:"https://fonts.googleapis.com/css?family=Lato", rel: "stylesheet", type: "text/css" }
7 | %link{ href:"stylesheets/jquery.gridly.css", rel: "stylesheet", type: "text/css" }
8 | %link{ href:"stylesheets/sample.css", rel: "stylesheet", type: "text/css" }
9 | %script{ src:"javascripts/jquery.js", type: "text/javascript" }
10 | %script{ src:"javascripts/jquery.gridly.js", type: "text/javascript" }
11 | %script{ src:"javascripts/sample.js", type: "text/javascript" }
12 | %script{ src: "javascripts/rainbow.js", type: "text/javascript" }
13 | :javascript
14 |
15 | var _gaq = _gaq || [];
16 | _gaq.push(['_setAccount', 'UA-31911059-1']);
17 | _gaq.push(['_trackPageview']);
18 |
19 | (function() {
20 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
21 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
22 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
23 | })();
24 |
25 | %body
26 | %a{ href: "https://github.com/ksylvest/jquery-gridly"}
27 | %img.fork{ src: "images/fork.png", alt: "Fork" }
28 | .content
29 | %h1 jQuery Gridly
30 | %p Gridly is a jQuery plugin to enable dragging and dropping as well as resizing on a grids. In the example below try tapping or dragging any of the bricks.
31 | %h2 Example
32 | %section.example
33 | .gridly
34 | - 20.times do
35 | .brick.small
36 | %a.delete{ href: '#' } ×
37 | %p.actions
38 | %a.add.button{ href: '#' } Add
39 | %h2 Installation
40 | %p To install download one of these packages and include the jquery.gridly.js and jquery.gridly.css files in your head with the following:
41 | %section.formats
42 | .format
43 | %a.zip{ href: "packages/jquery.gridly.zip" }
44 | .format
45 | %a.tar{ href: "packages/jquery.gridly.tar" }
46 | %pre
47 | %code{ data: { language: "html" } }
48 | = preserve do
49 | :escaped
50 |
51 |
52 |
53 | %h2 Example
54 | %p Setting up a gridly is easy. The following snippet is a good start:
55 | %pre
56 | %code{ data: { language: "html" } }
57 | = preserve do
58 | :escaped
59 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
88 | %p.copy
89 | Copyright (c) 2013 - 2015
90 | %a{ href: "http://ksylvest.com/" } Kevin Sylvestre
91 | %p.links
92 | %a{ href: "https://github.com/ksylvest" } GitHub
93 | %a{ href: "https://plus.google.com/+KevinSylvestre?rel=author" } Google
94 | %a{ href: "https://twitter.com/ksylvest" } Twitter
95 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | jQuery Gridly
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
jQuery Gridly
32 |
Gridly is a jQuery plugin to enable dragging and dropping as well as resizing on a grids. In the example below try tapping or dragging any of the bricks.
33 |
Example
34 |
35 |
36 |
39 |
42 |
45 |
48 |
51 |
54 |
57 |
60 |
63 |
66 |
69 |
72 |
75 |
78 |
81 |
84 |
87 |
90 |
93 |
96 |
97 |
98 | Add
99 |
100 |
101 |
Installation
102 |
To install download one of these packages and include the jquery.gridly.js and jquery.gridly.css files in your head with the following:
103 |
111 |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js" type="text/javascript"></script>
<script src="javascript/jquery.gridly.js" type="text/javascript"></script>
<link href="stylesheets/jquery.gridly.css" rel="stylesheet" type="text/css" />
112 |
Example
113 |
Setting up a gridly is easy. The following snippet is a good start:
114 |
<style type="text/css">
.gridly {
position: relative;
width: 960px;
}
.brick.small {
width: 140px;
height: 140px;
}
.brick.large {
width: 300px;
height: 300px;
}
</style>
<div class="gridly">
<div class="brick small"></div>
<div class="brick small"></div>
<div class="brick large"></div>
<div class="brick small"></div>
<div class="brick small"></div>
<div class="brick large"></div>
</div>
<script>
$('.gridly').gridly({
base: 60, // px
gutter: 20, // px
columns: 12
});
</script>
115 |
116 | Copyright (c) 2013 - 2015
117 | Kevin Sylvestre
118 |
119 |
120 | GitHub
121 | Google
122 | Twitter
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/javascripts/jquery.gridly.coffee:
--------------------------------------------------------------------------------
1 | ###
2 | jQuery Gridly
3 | Copyright 2020 Kevin Sylvestre
4 | 1.3.0
5 | ###
6 |
7 | "use strict"
8 |
9 | $ = jQuery
10 |
11 | class Animation
12 | @transitions:
13 | "webkitTransition": "webkitTransitionEnd"
14 | "mozTransition": "mozTransitionEnd"
15 | "oTransition": "oTransitionEnd"
16 | "transition": "transitionend"
17 |
18 | @transition: ($el) ->
19 | el = $el[0]
20 | return result for type, result of @transitions when el.style[type]?
21 |
22 | @execute: ($el, callback) ->
23 | transition = @transition($el)
24 | if transition? then $el.one(transition, callback) else callback()
25 |
26 | class Draggable
27 |
28 | constructor: ($container, selector, callbacks) ->
29 | @$container = $container
30 | @selector = selector
31 | @callbacks = callbacks
32 | @toggle()
33 |
34 | bind: (method = 'on') =>
35 | $(document)[method] 'mousemove touchmove', @moved
36 | $(document)[method] 'mouseup touchcancel', @ended
37 |
38 | toggle: (method = 'on') =>
39 | @$container[method] 'mousedown touchstart', @selector, @began
40 | @$container[method] 'touchend', @selector, @touchend
41 | @$container[method] 'click', @selector, @click
42 |
43 | on: =>
44 | @toggle('on')
45 |
46 | off: =>
47 | @toggle('off')
48 |
49 | coordinate: (event) =>
50 | switch event.type
51 | when 'touchstart','touchmove','touchend','touchcancel' then event.originalEvent.touches[0]
52 | else event
53 |
54 | began: (event) =>
55 | return if @$target
56 | event.preventDefault()
57 | event.stopPropagation()
58 | @bind('on')
59 |
60 | @$target = $(event.target).closest(@$container.find(@selector))
61 | @$target.addClass('dragging')
62 |
63 | @origin =
64 | x: @coordinate(event).pageX - @$target.position().left
65 | y: @coordinate(event).pageY - @$target.position().top
66 |
67 | @callbacks?.began?(event)
68 |
69 | ended: (event) =>
70 | return unless @$target?
71 | if event.type != 'touchend'
72 | event.preventDefault()
73 | event.stopPropagation()
74 | @bind('off')
75 |
76 | @$target.removeClass('dragging')
77 |
78 | delete @$target
79 | delete @origin
80 |
81 | @callbacks?.ended?(event)
82 |
83 | moved: (event) =>
84 | return unless @$target?
85 | event.preventDefault()
86 | event.stopPropagation()
87 |
88 | @$target.css
89 | left: @coordinate(event).pageX - @origin.x
90 | top: @coordinate(event).pageY - @origin.y
91 |
92 | @dragged = @$target
93 | @callbacks?.moved?(event)
94 |
95 | click: (event) =>
96 | return unless @dragged
97 | event.preventDefault()
98 | event.stopPropagation()
99 | delete @dragged
100 |
101 | touchend: (event) =>
102 | @ended(event)
103 | @click(event)
104 |
105 | class Gridly
106 |
107 | @settings:
108 | base: 60
109 | gutter: 20
110 | columns: 12
111 | draggable:
112 | zIndex: 800
113 | selector : '> *'
114 |
115 | @gridly: ($el, options = {}) ->
116 | data = $el.data('_gridly')
117 | if data
118 | $.extend data.settings, options
119 | else
120 | data = new Gridly($el, options)
121 | $el.data('_gridly', data)
122 | return data
123 |
124 | constructor: ($el, settings = {}) ->
125 | @$el = $el
126 | @settings = $.extend {}, Gridly.settings, settings
127 | @ordinalize(@$('> *'))
128 | @draggable() unless @settings.draggable is false
129 | return @
130 |
131 | ordinalize: ($elements) =>
132 | for i in [0 .. $elements.length]
133 | $element = $($elements[i])
134 | $element.data('position', i)
135 |
136 | reordinalize: ($element, position) =>
137 | $element.data('position', position)
138 |
139 | $: (selector) =>
140 | @$el.find(selector)
141 |
142 | compare: (d, s) =>
143 | return +1 if d.y > s.y + s.h
144 | return -1 if s.y > d.y + d.h
145 | return +1 if (d.x + (d.w / 2)) > (s.x + (s.w / 2))
146 | return -1 if (s.x + (s.w / 2)) > (d.x + (d.w / 2))
147 | return 0
148 |
149 | draggable: (method) =>
150 | @_draggable ?= new Draggable @$el, @settings.draggable.selector,
151 | began: @draggingBegan
152 | ended: @draggingEnded
153 | moved: @draggingMoved
154 | @_draggable[method]() if method?
155 |
156 | $sorted: ($elements) =>
157 | ($elements || @$('> *')).sort (a,b) ->
158 | $a = $(a)
159 | $b = $(b)
160 | aPosition = $a.data('position')
161 | bPosition = $b.data('position')
162 | aPositionInt = parseInt(aPosition)
163 | bPositionInt = parseInt(bPosition)
164 | return -1 if aPosition? and not bPosition?
165 | return +1 if bPosition? and not aPosition?
166 | return -1 if not aPosition and not bPosition and $a.index() < $b.index()
167 | return +1 if not bPosition and not aPosition and $b.index() < $a.index()
168 | return -1 if aPositionInt < bPositionInt
169 | return +1 if bPositionInt < aPositionInt
170 | return 0
171 |
172 | draggingBegan: (event) =>
173 | $elements = @$sorted()
174 | @ordinalize($elements)
175 | setTimeout @layout, 0
176 | @settings?.callbacks?.reordering?($elements)
177 |
178 | draggingEnded: (event) =>
179 | $elements = @$sorted()
180 | @ordinalize($elements)
181 | setTimeout @layout, 0
182 | @settings?.callbacks?.reordered?($elements, @_draggable.dragged)
183 |
184 | draggingMoved: (event) =>
185 | $dragging = $(event.target).closest(@$(@settings.draggable.selector))
186 | $elements = @$sorted(@$(@settings.draggable.selector))
187 | positions = @structure($elements).positions
188 | original = index = $dragging.data('position')
189 |
190 | for element in positions.filter((position) -> position.$element.is($dragging))
191 | element.x = $dragging.position().left
192 | element.y = $dragging.position().top
193 | element.w = $dragging.data('width') || $dragging.outerWidth()
194 | element.h = $dragging.data('height') || $dragging.outerHeight()
195 |
196 | positions.sort @compare
197 |
198 | $elements = positions.map (position) -> position.$element
199 | $elements = (@settings.callbacks?.optimize || @optimize)($elements)
200 |
201 | for i in [0...$elements.length]
202 | @reordinalize($($elements[i]), i)
203 |
204 | @layout()
205 |
206 | size: ($element) =>
207 | (($element.data('width') || $element.outerWidth()) + @settings.gutter) / (@settings.base + @settings.gutter)
208 |
209 | position: ($element, columns) =>
210 | size = @size($element)
211 |
212 | height = Infinity
213 | column = 0
214 |
215 | for i in [0 ... (columns.length - size)]
216 | max = Math.max columns[i ... (i + size)]...
217 | if max < height
218 | height = max
219 | column = i
220 |
221 | for i in [column ... column + size]
222 | columns[i] = height + ($element.data('height') || $element.outerHeight()) + @settings.gutter
223 |
224 | x: (column * (@settings.base + @settings.gutter))
225 | y: height
226 |
227 | structure: ($elements = @$sorted()) =>
228 | positions = []
229 | columns = (0 for i in [0 .. @settings.columns])
230 |
231 | for index in [0 ... $elements.length]
232 | $element = $($elements[index])
233 |
234 | position = @position($element, columns)
235 | positions.push
236 | x: position.x
237 | y: position.y
238 | w: $element.data('width') || $element.outerWidth()
239 | h: $element.data('height') || $element.outerHeight()
240 | $element: $element
241 |
242 | height: Math.max columns...
243 | positions: positions
244 |
245 | layout: =>
246 | $elements = (@settings.callbacks?.optimize || @optimize)(@$sorted())
247 |
248 | structure = @structure($elements)
249 |
250 | for index in [0 ... $elements.length]
251 | $element = $($elements[index])
252 | position = structure.positions[index]
253 |
254 | continue if $element.is('.dragging')
255 |
256 | $element.css
257 | position: 'absolute'
258 | left: position.x
259 | top: position.y
260 |
261 | @$el.css
262 | height: structure.height
263 |
264 | optimize: (originals) =>
265 | results = []
266 |
267 | columns = 0
268 | while originals.length > 0
269 | columns = 0 if columns is @settings.columns
270 |
271 | index = 0
272 | for index in [0...originals.length]
273 | break unless columns + @size($(originals[index])) > @settings.columns
274 |
275 | if index is originals.length
276 | index = 0
277 | columns = 0
278 |
279 | columns += @size($(originals[index]))
280 |
281 | # Move from originals into results
282 | results.push(originals.splice(index,1)[0])
283 |
284 | return results
285 |
286 | $.fn.extend
287 | gridly: (option = {}, parameters...) ->
288 | @each ->
289 | $this = $(@)
290 |
291 | options = $.extend {}, $.fn.gridly.defaults, typeof option is "object" and option
292 | action = if typeof option is "string" then option else option.action
293 | action ?= "layout"
294 |
295 | Gridly.gridly($this, options)[action](parameters)
296 |
--------------------------------------------------------------------------------
/javascripts/jquery.gridly.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 2.5.1
2 | (function() {
3 | /*
4 | jQuery Gridly
5 | Copyright 2020 Kevin Sylvestre
6 | 1.3.0
7 | */
8 | "use strict";
9 | var $, Animation, Draggable, Gridly;
10 |
11 | $ = jQuery;
12 |
13 | Animation = (function() {
14 | class Animation {
15 | static transition($el) {
16 | var el, ref, result, type;
17 | el = $el[0];
18 | ref = this.transitions;
19 | for (type in ref) {
20 | result = ref[type];
21 | if (el.style[type] != null) {
22 | return result;
23 | }
24 | }
25 | }
26 |
27 | static execute($el, callback) {
28 | var transition;
29 | transition = this.transition($el);
30 | if (transition != null) {
31 | return $el.one(transition, callback);
32 | } else {
33 | return callback();
34 | }
35 | }
36 |
37 | };
38 |
39 | Animation.transitions = {
40 | "webkitTransition": "webkitTransitionEnd",
41 | "mozTransition": "mozTransitionEnd",
42 | "oTransition": "oTransitionEnd",
43 | "transition": "transitionend"
44 | };
45 |
46 | return Animation;
47 |
48 | }).call(this);
49 |
50 | Draggable = class Draggable {
51 | constructor($container, selector, callbacks) {
52 | this.bind = this.bind.bind(this);
53 | this.toggle = this.toggle.bind(this);
54 | this.on = this.on.bind(this);
55 | this.off = this.off.bind(this);
56 | this.coordinate = this.coordinate.bind(this);
57 | this.began = this.began.bind(this);
58 | this.ended = this.ended.bind(this);
59 | this.moved = this.moved.bind(this);
60 | this.click = this.click.bind(this);
61 | this.touchend = this.touchend.bind(this);
62 | this.$container = $container;
63 | this.selector = selector;
64 | this.callbacks = callbacks;
65 | this.toggle();
66 | }
67 |
68 | bind(method = 'on') {
69 | $(document)[method]('mousemove touchmove', this.moved);
70 | return $(document)[method]('mouseup touchcancel', this.ended);
71 | }
72 |
73 | toggle(method = 'on') {
74 | this.$container[method]('mousedown touchstart', this.selector, this.began);
75 | this.$container[method]('touchend', this.selector, this.touchend);
76 | return this.$container[method]('click', this.selector, this.click);
77 | }
78 |
79 | on() {
80 | return this.toggle('on');
81 | }
82 |
83 | off() {
84 | return this.toggle('off');
85 | }
86 |
87 | coordinate(event) {
88 | switch (event.type) {
89 | case 'touchstart':
90 | case 'touchmove':
91 | case 'touchend':
92 | case 'touchcancel':
93 | return event.originalEvent.touches[0];
94 | default:
95 | return event;
96 | }
97 | }
98 |
99 | began(event) {
100 | var ref;
101 | if (this.$target) {
102 | return;
103 | }
104 | event.preventDefault();
105 | event.stopPropagation();
106 | this.bind('on');
107 | this.$target = $(event.target).closest(this.$container.find(this.selector));
108 | this.$target.addClass('dragging');
109 | this.origin = {
110 | x: this.coordinate(event).pageX - this.$target.position().left,
111 | y: this.coordinate(event).pageY - this.$target.position().top
112 | };
113 | return (ref = this.callbacks) != null ? typeof ref.began === "function" ? ref.began(event) : void 0 : void 0;
114 | }
115 |
116 | ended(event) {
117 | var ref;
118 | if (this.$target == null) {
119 | return;
120 | }
121 | if (event.type !== 'touchend') {
122 | event.preventDefault();
123 | event.stopPropagation();
124 | }
125 | this.bind('off');
126 | this.$target.removeClass('dragging');
127 | delete this.$target;
128 | delete this.origin;
129 | return (ref = this.callbacks) != null ? typeof ref.ended === "function" ? ref.ended(event) : void 0 : void 0;
130 | }
131 |
132 | moved(event) {
133 | var ref;
134 | if (this.$target == null) {
135 | return;
136 | }
137 | event.preventDefault();
138 | event.stopPropagation();
139 | this.$target.css({
140 | left: this.coordinate(event).pageX - this.origin.x,
141 | top: this.coordinate(event).pageY - this.origin.y
142 | });
143 | this.dragged = this.$target;
144 | return (ref = this.callbacks) != null ? typeof ref.moved === "function" ? ref.moved(event) : void 0 : void 0;
145 | }
146 |
147 | click(event) {
148 | if (!this.dragged) {
149 | return;
150 | }
151 | event.preventDefault();
152 | event.stopPropagation();
153 | return delete this.dragged;
154 | }
155 |
156 | touchend(event) {
157 | this.ended(event);
158 | return this.click(event);
159 | }
160 |
161 | };
162 |
163 | Gridly = (function() {
164 | class Gridly {
165 | static gridly($el, options = {}) {
166 | var data;
167 | data = $el.data('_gridly');
168 | if (data) {
169 | $.extend(data.settings, options);
170 | } else {
171 | data = new Gridly($el, options);
172 | $el.data('_gridly', data);
173 | }
174 | return data;
175 | }
176 |
177 | constructor($el, settings = {}) {
178 | this.ordinalize = this.ordinalize.bind(this);
179 | this.reordinalize = this.reordinalize.bind(this);
180 | this.$ = this.$.bind(this);
181 | this.compare = this.compare.bind(this);
182 | this.draggable = this.draggable.bind(this);
183 | this.$sorted = this.$sorted.bind(this);
184 | this.draggingBegan = this.draggingBegan.bind(this);
185 | this.draggingEnded = this.draggingEnded.bind(this);
186 | this.draggingMoved = this.draggingMoved.bind(this);
187 | this.size = this.size.bind(this);
188 | this.position = this.position.bind(this);
189 | this.structure = this.structure.bind(this);
190 | this.layout = this.layout.bind(this);
191 | this.optimize = this.optimize.bind(this);
192 | this.$el = $el;
193 | this.settings = $.extend({}, Gridly.settings, settings);
194 | this.ordinalize(this.$('> *'));
195 | if (this.settings.draggable !== false) {
196 | this.draggable();
197 | }
198 | return this;
199 | }
200 |
201 | ordinalize($elements) {
202 | var $element, i, j, ref, results1;
203 | results1 = [];
204 | for (i = j = 0, ref = $elements.length; (0 <= ref ? j <= ref : j >= ref); i = 0 <= ref ? ++j : --j) {
205 | $element = $($elements[i]);
206 | results1.push($element.data('position', i));
207 | }
208 | return results1;
209 | }
210 |
211 | reordinalize($element, position) {
212 | return $element.data('position', position);
213 | }
214 |
215 | $(selector) {
216 | return this.$el.find(selector);
217 | }
218 |
219 | compare(d, s) {
220 | if (d.y > s.y + s.h) {
221 | return +1;
222 | }
223 | if (s.y > d.y + d.h) {
224 | return -1;
225 | }
226 | if ((d.x + (d.w / 2)) > (s.x + (s.w / 2))) {
227 | return +1;
228 | }
229 | if ((s.x + (s.w / 2)) > (d.x + (d.w / 2))) {
230 | return -1;
231 | }
232 | return 0;
233 | }
234 |
235 | draggable(method) {
236 | if (this._draggable == null) {
237 | this._draggable = new Draggable(this.$el, this.settings.draggable.selector, {
238 | began: this.draggingBegan,
239 | ended: this.draggingEnded,
240 | moved: this.draggingMoved
241 | });
242 | }
243 | if (method != null) {
244 | return this._draggable[method]();
245 | }
246 | }
247 |
248 | $sorted($elements) {
249 | return ($elements || this.$('> *')).sort(function(a, b) {
250 | var $a, $b, aPosition, aPositionInt, bPosition, bPositionInt;
251 | $a = $(a);
252 | $b = $(b);
253 | aPosition = $a.data('position');
254 | bPosition = $b.data('position');
255 | aPositionInt = parseInt(aPosition);
256 | bPositionInt = parseInt(bPosition);
257 | if ((aPosition != null) && (bPosition == null)) {
258 | return -1;
259 | }
260 | if ((bPosition != null) && (aPosition == null)) {
261 | return +1;
262 | }
263 | if (!aPosition && !bPosition && $a.index() < $b.index()) {
264 | return -1;
265 | }
266 | if (!bPosition && !aPosition && $b.index() < $a.index()) {
267 | return +1;
268 | }
269 | if (aPositionInt < bPositionInt) {
270 | return -1;
271 | }
272 | if (bPositionInt < aPositionInt) {
273 | return +1;
274 | }
275 | return 0;
276 | });
277 | }
278 |
279 | draggingBegan(event) {
280 | var $elements, ref, ref1;
281 | $elements = this.$sorted();
282 | this.ordinalize($elements);
283 | setTimeout(this.layout, 0);
284 | return (ref = this.settings) != null ? (ref1 = ref.callbacks) != null ? typeof ref1.reordering === "function" ? ref1.reordering($elements) : void 0 : void 0 : void 0;
285 | }
286 |
287 | draggingEnded(event) {
288 | var $elements, ref, ref1;
289 | $elements = this.$sorted();
290 | this.ordinalize($elements);
291 | setTimeout(this.layout, 0);
292 | return (ref = this.settings) != null ? (ref1 = ref.callbacks) != null ? typeof ref1.reordered === "function" ? ref1.reordered($elements, this._draggable.dragged) : void 0 : void 0 : void 0;
293 | }
294 |
295 | draggingMoved(event) {
296 | var $dragging, $elements, element, i, index, j, k, len, original, positions, ref, ref1, ref2;
297 | $dragging = $(event.target).closest(this.$(this.settings.draggable.selector));
298 | $elements = this.$sorted(this.$(this.settings.draggable.selector));
299 | positions = this.structure($elements).positions;
300 | original = index = $dragging.data('position');
301 | ref = positions.filter(function(position) {
302 | return position.$element.is($dragging);
303 | });
304 | for (j = 0, len = ref.length; j < len; j++) {
305 | element = ref[j];
306 | element.x = $dragging.position().left;
307 | element.y = $dragging.position().top;
308 | element.w = $dragging.data('width') || $dragging.outerWidth();
309 | element.h = $dragging.data('height') || $dragging.outerHeight();
310 | }
311 | positions.sort(this.compare);
312 | $elements = positions.map(function(position) {
313 | return position.$element;
314 | });
315 | $elements = (((ref1 = this.settings.callbacks) != null ? ref1.optimize : void 0) || this.optimize)($elements);
316 | for (i = k = 0, ref2 = $elements.length; (0 <= ref2 ? k < ref2 : k > ref2); i = 0 <= ref2 ? ++k : --k) {
317 | this.reordinalize($($elements[i]), i);
318 | }
319 | return this.layout();
320 | }
321 |
322 | size($element) {
323 | return (($element.data('width') || $element.outerWidth()) + this.settings.gutter) / (this.settings.base + this.settings.gutter);
324 | }
325 |
326 | position($element, columns) {
327 | var column, height, i, j, k, max, ref, ref1, ref2, size;
328 | size = this.size($element);
329 | height = 2e308;
330 | column = 0;
331 | for (i = j = 0, ref = columns.length - size; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
332 | max = Math.max(...columns.slice(i, (i + size)));
333 | if (max < height) {
334 | height = max;
335 | column = i;
336 | }
337 | }
338 | for (i = k = ref1 = column, ref2 = column + size; (ref1 <= ref2 ? k < ref2 : k > ref2); i = ref1 <= ref2 ? ++k : --k) {
339 | columns[i] = height + ($element.data('height') || $element.outerHeight()) + this.settings.gutter;
340 | }
341 | return {
342 | x: column * (this.settings.base + this.settings.gutter),
343 | y: height
344 | };
345 | }
346 |
347 | structure($elements = this.$sorted()) {
348 | var $element, columns, i, index, j, position, positions, ref;
349 | positions = [];
350 | columns = (function() {
351 | var j, ref, results1;
352 | results1 = [];
353 | for (i = j = 0, ref = this.settings.columns; (0 <= ref ? j <= ref : j >= ref); i = 0 <= ref ? ++j : --j) {
354 | results1.push(0);
355 | }
356 | return results1;
357 | }).call(this);
358 | for (index = j = 0, ref = $elements.length; (0 <= ref ? j < ref : j > ref); index = 0 <= ref ? ++j : --j) {
359 | $element = $($elements[index]);
360 | position = this.position($element, columns);
361 | positions.push({
362 | x: position.x,
363 | y: position.y,
364 | w: $element.data('width') || $element.outerWidth(),
365 | h: $element.data('height') || $element.outerHeight(),
366 | $element: $element
367 | });
368 | }
369 | return {
370 | height: Math.max(...columns),
371 | positions: positions
372 | };
373 | }
374 |
375 | layout() {
376 | var $element, $elements, index, j, position, ref, ref1, structure;
377 | $elements = (((ref = this.settings.callbacks) != null ? ref.optimize : void 0) || this.optimize)(this.$sorted());
378 | structure = this.structure($elements);
379 | for (index = j = 0, ref1 = $elements.length; (0 <= ref1 ? j < ref1 : j > ref1); index = 0 <= ref1 ? ++j : --j) {
380 | $element = $($elements[index]);
381 | position = structure.positions[index];
382 | if ($element.is('.dragging')) {
383 | continue;
384 | }
385 | $element.css({
386 | position: 'absolute',
387 | left: position.x,
388 | top: position.y
389 | });
390 | }
391 | return this.$el.css({
392 | height: structure.height
393 | });
394 | }
395 |
396 | optimize(originals) {
397 | var columns, index, j, ref, results;
398 | results = [];
399 | columns = 0;
400 | while (originals.length > 0) {
401 | if (columns === this.settings.columns) {
402 | columns = 0;
403 | }
404 | index = 0;
405 | for (index = j = 0, ref = originals.length; (0 <= ref ? j < ref : j > ref); index = 0 <= ref ? ++j : --j) {
406 | if (!(columns + this.size($(originals[index])) > this.settings.columns)) {
407 | break;
408 | }
409 | }
410 | if (index === originals.length) {
411 | index = 0;
412 | columns = 0;
413 | }
414 | columns += this.size($(originals[index]));
415 | // Move from originals into results
416 | results.push(originals.splice(index, 1)[0]);
417 | }
418 | return results;
419 | }
420 |
421 | };
422 |
423 | Gridly.settings = {
424 | base: 60,
425 | gutter: 20,
426 | columns: 12,
427 | draggable: {
428 | zIndex: 800,
429 | selector: '> *'
430 | }
431 | };
432 |
433 | return Gridly;
434 |
435 | }).call(this);
436 |
437 | $.fn.extend({
438 | gridly: function(option = {}, ...parameters) {
439 | return this.each(function() {
440 | var $this, action, options;
441 | $this = $(this);
442 | options = $.extend({}, $.fn.gridly.defaults, typeof option === "object" && option);
443 | action = typeof option === "string" ? option : option.action;
444 | if (action == null) {
445 | action = "layout";
446 | }
447 | return Gridly.gridly($this, options)[action](parameters);
448 | });
449 | }
450 | });
451 |
452 | }).call(this);
453 |
--------------------------------------------------------------------------------
/javascripts/rainbow.js:
--------------------------------------------------------------------------------
1 | /* Rainbow v1.1.8 rainbowco.de | included languages: c, shell, java, coffeescript, generic, scheme, javascript, r, haskell, python, html, smalltalk, csharp, go, php, ruby, lua, css */
2 | var m=!0;
3 | window.Rainbow=function(){function r(a){var b,c=a.getAttribute&&a.getAttribute("data-language")||0;if(!c){a=a.attributes;for(b=0;b=e[d][c])delete e[d][c],delete j[d][c];if(a>=c&&ac&&b'+b+""}function t(a,b,c,h){var f=a.exec(c);if(f){++u;!b.name&&"string"==typeof b.matches[0]&&(b.name=b.matches[0],delete b.matches[0]);var k=f[0],i=f.index,v=f[0].length+i,g=function(){function f(){t(a,b,c,h)}u%100>0?f():setTimeout(f,0)};if(D(i,v))g();else{var n=w(b.matches),l=function(a,c,h){if(a>=c.length)h(k);else{var d=f[c[a]];if(d){var e=b.matches[c[a]],i=e.language,g=e.name&&e.matches?
5 | e.matches:e,j=function(b,d,e){var i;i=0;var g;for(g=1;g/g,">").replace(/&(?![\w\#]+;)/g,
7 | "&"),b,c)}function p(a,b,c){if(b|<=|>=|zero\?|positive\?|negative\?|odd\?|even\?|max|min|\+|\-|\*|\/|abs|quotient|remainder|modulo|gcd|lcm|numerator|denominator|floor|ceiling|truncate|round|rationalize|exp|log|sin|cos|tan|asin|acos|atan|sqrt|expt|make\-rectangular|make\-polar|real\-part|imag\-part|magnitude|angle|exact\->inexact|inexact\->exact|number\->string|string\->number|not|boolean\?|pair\?|cons|car|cdr|set\-car!|set\-cdr!|caar|cadr|cdar|cddr|caaar|caadr|cadar|caddr|cdaar|cdadr|cddar|cdddr|caaaar|caaadr|caadar|caaddr|cadaar|cadadr|caddar|cadddr|cdaaar|cdaadr|cdadar|cdaddr|cddaar|cddadr|cdddar|cddddr|null\?|list\?|list|length|append|reverse|list\-tail|list\-ref|memq|memv|member|assq|assv|assoc|symbol\?|symbol\->string|string\->symbol|char\?|char=\?|char<\?|char>\?|char<=\?|char>=\?|char\-ci=\?|char\-ci<\?|char\-ci>\?|char\-ci<=\?|char\-ci>=\?|char\-alphabetic\?|char\-numeric\?|char\-whitespace\?|char\-upper\-case\?|char\-lower\-case\?|char\->integer|integer\->char|char\-upcase|char\-downcase|string\?|make\-string|string|string\-length|string\-ref|string\-set!|string=\?|string\-ci=\?|string<\?|string>\?|string<=\?|string>=\?|string\-ci<\?|string\-ci>\?|string\-ci<=\?|string\-ci>=\?|substring|string\-append|string\->list|list\->string|string\-copy|string\-fill!|vector\?|make\-vector|vector|vector\-length|vector\-ref|vector\-set!|vector\->list|list\->vector|vector\-fill!|procedure\?|apply|map|for\-each|force|call\-with\-current\-continuation|call\/cc|values|call\-with\-values|dynamic\-wind|eval|scheme\-report\-environment|null\-environment|interaction\-environment|call\-with\-input\-file|call\-with\-output\-file|input\-port\?|output\-port\?|current\-input\-port|current\-output\-port|with\-input\-from\-file|with\-output\-to\-file|open\-input\-file|open\-output\-file|close\-input\-port|close\-output\-port|read|read\-char|peek\-char|eof\-object\?|char\-ready\?|write|display|newline|write\-char|load|transcript\-on|transcript\-off)(?=[\]()\s#])/g}],
18 | m);Rainbow.extend("javascript",[{name:"selector",pattern:/(\s|^)\$(?=\.|\()/g},{name:"support",pattern:/\b(window|document)\b/g},{matches:{1:"support.property"},pattern:/\.(length|node(Name|Value))\b/g},{matches:{1:"support.function"},pattern:/(setTimeout|setInterval)(?=\()/g},{matches:{1:"support.method"},pattern:/\.(getAttribute|push|getElementById|getElementsByClassName|log|setTimeout|setInterval)(?=\()/g},{matches:{1:"support.tag.script",2:[{name:"string",pattern:/('|")(.*?)(\1)/g},{name:"entity.tag.script",
19 | pattern:/(\w+)/g}],3:"support.tag.script"},pattern:/(<\/?)(script.*?)(>)/g},{name:"string.regexp",matches:{1:"string.regexp.open",2:{name:"constant.regexp.escape",pattern:/\\(.){1}/g},3:"string.regexp.close",4:"string.regexp.modifier"},pattern:/(\/)(?!\*)(.+)(\/)([igm]{0,3})/g},{matches:{1:"storage",3:"entity.function"},pattern:/(var)?(\s|^)(.*)(?=\s?=\s?function\()/g},{matches:{1:"keyword",2:"entity.function"},pattern:/(new)\s+(.*)(?=\()/g},{name:"entity.function",pattern:/(\w+)(?=:\s{0,}function)/g}]);Rainbow.extend("r",[{matches:{1:{name:"keyword.operator",pattern:/\=|<\-|<-/g},2:{name:"string",matches:{name:"constant.character.escape",pattern:/\\('|"){1}/g}}},pattern:/(\(|\s|\[|\=|:)(('|")([^\\\1]|\\.)*?(\3))/gm},{matches:{1:"constant.language"},pattern:/\b(NULL|NA|TRUE|FALSE|T|F|NaN|Inf|NA_integer_|NA_real_|NA_complex_|NA_character_)\b/g},{matches:{1:"constant.symbol"},pattern:/[^0-9a-zA-Z\._](LETTERS|letters|month\.(abb|name)|pi)/g},{name:"keyword.operator",pattern:/<-|<-|-|==|<=|<=|>>|>=|<|>|&&|&&|&|&|!=|\|\|?|\*|\+|\^|\/|%%|%\/%|\=|%in%|%\*%|%o%|%x%|\$|:|~|\[{1,2}|\]{1,2}/g},
20 | {matches:{1:"storage",3:"entity.function"},pattern:/(\s|^)(.*)(?=\s?=\s?function\s\()/g},{matches:{1:"storage.function"},pattern:/[^a-zA-Z0-9._](function)(?=\s*\()/g},{matches:{1:"namespace",2:"keyword.operator",3:"function.call"},pattern:/([a-zA-Z][a-zA-Z0-9._]+)([:]{2,3})([.a-zA-Z][a-zA-Z0-9._]*(?=\s*\())\b/g},{name:"support.function",pattern:/(^|[^0-9a-zA-Z\._])(array|character|complex|data\.frame|double|integer|list|logical|matrix|numeric|vector)(?=\s*\()/g}]);Rainbow.extend("haskell",[{name:"comment",pattern:/\{\-\-[\s\S(\w+)]+[\-\-][\}$]/gm},{name:"comment",pattern:/\-\-(.*)/g},{matches:{1:"keyword",2:"support.namespace"},pattern:/\b(module)\s(\w+)\s[\(]?(\w+)?[\)?]\swhere/g},{name:"keyword.operator",pattern:/\+|\!|\-|&(gt|lt|amp);|\/\=|\||\@|\:|\.|\+{2}|\:|\*|\=|#|\.{2}|(\\)[a-zA-Z_]/g},{name:"keyword",pattern:/\b(case|class|foreign|hiding|qualified|data|family|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|in|otherwise|module|newtype|of|then|type|where)\b/g},
21 | {name:"keyword",pattern:/[\`][a-zA-Z_']*?[\`]/g},{matches:{1:"keyword",2:"keyword.operator"},pattern:/\b(infix|infixr|infixl)+\s\d+\s(\w+)*/g},{name:"entity.class",pattern:/\b([A-Z][A-Za-z0-9_']*)/g},{name:"meta.preprocessor",matches:{1:[{matches:{1:"keyword.define",2:"entity.name"},pattern:/(\w+)\s(\w+)\b/g},{name:"keyword.define",pattern:/endif/g},{name:"constant.numeric",pattern:/\d+/g},{matches:{1:"keyword.include",2:"string"},pattern:/(include)\s(.*?)$/g}]},pattern:/^\#([\S\s]*?)$/gm}]);Rainbow.extend("python",[{name:"variable.self",pattern:/self/g},{name:"constant.language",pattern:/None|True|False/g},{name:"support.object",pattern:/object/g},{name:"support.function.python",pattern:/\b(bs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|bin|file|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern)(?=\()/g},
22 | {matches:{1:"keyword"},pattern:/\b(pass|lambda|with|is|not|in|from|elif)(?=\(|\b)/g},{matches:{1:"storage.class",2:"entity.name.class",3:"entity.other.inherited-class"},pattern:/(class)\s+(\w+)\((\w+?)\)/g},{matches:{1:"storage.function",2:"support.magic"},pattern:/(def)\s+(__\w+)(?=\()/g},{name:"support.magic",pattern:/__(name)__/g},{matches:{1:"keyword.control",2:"support.exception.type"},pattern:/(except) (\w+):/g},{matches:{1:"storage.function",2:"entity.name.function"},pattern:/(def)\s+(\w+)(?=\()/g},
23 | {name:"entity.name.function.decorator",pattern:/@(\w+)/g},{name:"comment.docstring",pattern:/('{3}|"{3})[\s\S]*?\1/gm}]);Rainbow.extend("html",[{name:"source.php.embedded",matches:{2:{language:"php"}},pattern:/<\?=?(?!xml)(php)?([\s\S]*?)(\?>)/gm},{name:"source.css.embedded",matches:{"0":{language:"css"}},pattern:/<style(.*?)>([\s\S]*?)<\/style>/gm},{name:"source.js.embedded",matches:{"0":{language:"javascript"}},pattern:/<script(?! src)(.*?)>([\s\S]*?)<\/script>/gm},{name:"comment.html",pattern:/<\!--[\S\s]*?-->/g},{matches:{1:"support.tag.open",2:"support.tag.close"},pattern:/(<)|(\/?\??>)/g},
24 | {name:"support.tag",matches:{1:"support.tag",2:"support.tag.special",3:"support.tag-name"},pattern:/(<\??)(\/|\!?)(\w+)/g},{matches:{1:"support.attribute"},pattern:/([a-z-]+)(?=\=)/gi},{matches:{1:"support.operator",2:"string.quote",3:"string.value",4:"string.quote"},pattern:/(=)('|")(.*?)(\2)/g},{matches:{1:"support.operator",2:"support.value"},pattern:/(=)([a-zA-Z\-0-9]*)\b/g},{matches:{1:"support.attribute"},pattern:/\s(\w+)(?=\s|>)(?![\s\S]*<)/g}],m);Rainbow.extend("smalltalk",[{name:"keyword.pseudovariable",pattern:/self|thisContext/g},{name:"keyword.constant",pattern:/false|nil|true/g},{name:"string",pattern:/'([^']|'')*'/g},{name:"string.symbol",pattern:/#\w+|#'([^']|'')*'/g},{name:"string.character",pattern:/\$\w+/g},{name:"comment",pattern:/"([^"]|"")*"/g},{name:"constant.numeric",pattern:/-?\d+(\.\d+)?((r-?|s)[A-Za-z0-9]+|e-?[0-9]+)?/g},{name:"entity.name.class",pattern:/\b[A-Z]\w*/g},{name:"entity.name.function",pattern:/\b[a-z]\w*:?/g},
25 | {name:"entity.name.binary",pattern:/(<|>|&|[=~\|\\\/!@*\-_+])+/g},{name:"operator.delimiter",pattern:/;[\(\)\[\]\{\}]|#\[|#\(^\./g}],m);Rainbow.extend("csharp",[{name:"constant",pattern:/\b(false|null|true)\b/g},{name:"keyword",pattern:/\b(abstract|add|alias|ascending|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|double|do|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|foreach|for|from|get|global|goto|group|if|implicit|int|interface|internal|into|in|is|join|let|lock|long|namespace|new|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|try|typeof|uint|unchecked|ulong|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/g},
26 | {matches:{1:"keyword",2:{name:"support.class",pattern:/\w+/g}},pattern:/(typeof)\s([^\$].*?)(\)|;)/g},{matches:{1:"keyword.namespace",2:{name:"support.namespace",pattern:/\w+/g}},pattern:/\b(namespace)\s(.*?);/g},{matches:{1:"storage.modifier",2:"storage.class",3:"entity.name.class",4:"storage.modifier.extends",5:"entity.other.inherited-class"},pattern:/\b(abstract|sealed)?\s?(class)\s(\w+)(\sextends\s)?([\w\\]*)?\s?\{?(\n|\})/g},{name:"keyword.static",pattern:/\b(static)\b/g},{matches:{1:"keyword.new",
27 | 2:{name:"support.class",pattern:/\w+/g}},pattern:/\b(new)\s([^\$].*?)(?=\)|\(|;|&)/g},{name:"string",pattern:/(")(.*?)\1/g},{name:"integer",pattern:/\b(0x[\da-f]+|\d+)\b/g},{name:"comment",pattern:/\/\*[\s\S]*?\*\/|(\/\/)[\s\S]*?$/gm},{name:"operator",pattern:/(\+\+|\+=|\+|--|-=|-|<<=|<<|<=|=>|>>=|>>|>=|!=|!|~|\^|\|\||&&|&=|&|\?\?|::|:|\*=|\*|\/=|%=|\|=|==|=)/g},{name:"preprocessor",pattern:/(\#if|\#else|\#elif|\#endif|\#define|\#undef|\#warning|\#error|\#line|\#region|\#endregion|\#pragma)[\s\S]*?$/gm}],
28 | m);Rainbow.extend("go",[{matches:{1:{name:"keyword.operator",pattern:/\=/g},2:{name:"string",matches:{name:"constant.character.escape",pattern:/\\(`|"){1}/g}}},pattern:/(\(|\s|\[|\=|:)((`|")([^\\\1]|\\.)*?(\3))/gm},{name:"comment",pattern:/\/\*[\s\S]*?\*\/|(\/\/)[\s\S]*?$/gm},{name:"constant.numeric",pattern:/\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi},{matches:{1:"keyword"},pattern:/\b(break|c(ase|onst|ontinue)|d(efault|efer)|else|fallthrough|for|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)(?=\(|\b)/gi},
29 | {name:"constant.language",pattern:/true|false|null|string|byte|rune|u?int(8|16|32|64)?|float(32|64)|complex(64|128)/g},{name:"keyword.operator",pattern:/\+|\!|\-|&(gt|lt|amp);|\||\*|\:?=/g},{matches:{1:"function.call"},pattern:/(\w+?)(?=\()/g},{matches:{1:"storage.function",2:"entity.name.function"},pattern:/(func)\s(.*?)(?=\()/g}]);Rainbow.extend("php",[{name:"support",pattern:/\becho\b/g},{matches:{1:"variable.dollar-sign",2:"variable"},pattern:/(\$)(\w+)\b/g},{name:"constant.language",pattern:/true|false|null/ig},{name:"constant",pattern:/\b[A-Z0-9_]{2,}\b/g},{name:"keyword.dot",pattern:/\./g},{name:"keyword",pattern:/\b(continue|break|die|end(for(each)?|switch|if)|case|require(_once)?|include(_once)?)(?=\(|\b)/g},{matches:{1:"keyword",2:{name:"support.class",pattern:/\w+/g}},pattern:/(instanceof)\s([^\$].*?)(\)|;)/g},{matches:{1:"support.function"},
30 | pattern:/\b(array(_key_exists|_merge|_keys|_shift)?|isset|count|empty|unset|printf|is_(array|string|numeric|object)|sprintf|each|date|time|substr|pos|str(len|pos|tolower|_replace|totime)?|ord|trim|in_array|implode|end|preg_match|explode|fmod|define|link|list|get_class|serialize|file|sort|mail|dir|idate|log|intval|header|chr|function_exists|dirname|preg_replace|file_exists)(?=\()/g},{name:"variable.language.php-tag",pattern:/(<\?(php)?|\?>)/g},{matches:{1:"keyword.namespace",2:{name:"support.namespace",
31 | pattern:/\w+/g}},pattern:/\b(namespace|use)\s(.*?);/g},{matches:{1:"storage.modifier",2:"storage.class",3:"entity.name.class",4:"storage.modifier.extends",5:"entity.other.inherited-class",6:"storage.modifier.extends",7:"entity.other.inherited-class"},pattern:/\b(abstract|final)?\s?(class|interface|trait)\s(\w+)(\sextends\s)?([\w\\]*)?(\simplements\s)?([\w\\]*)?\s?\{?(\n|\})/g},{name:"keyword.static",pattern:/self::|static::/g},{matches:{1:"storage.function",2:"support.magic"},pattern:/(function)\s(__.*?)(?=\()/g},
32 | {matches:{1:"keyword.new",2:{name:"support.class",pattern:/\w+/g}},pattern:/\b(new)\s([^\$].*?)(?=\)|\(|;)/g},{matches:{1:{name:"support.class",pattern:/\w+/g},2:"keyword.static"},pattern:/([\w\\]*?)(::)(?=\b|\$)/g},{matches:{2:{name:"support.class",pattern:/\w+/g}},pattern:/(\(|,\s?)([\w\\]*?)(?=\s\$)/g}]);Rainbow.extend("ruby",[{name:"string",matches:{1:"string.open",2:{name:"string.keyword",pattern:/(\#\{.*?\})/g},3:"string.close"},pattern:/("|`)(.*?[^\\\1])?(\1)/g},{name:"string",pattern:/('|"|`)([^\\\1\n]|\\.)*\1/g},{name:"string",pattern:/%[qQ](?=(\(|\[|\{|<|.)(.*?)(?:'|\)|\]|\}|>|\1))(?:\(\2\)|\[\2\]|\{\2\}|\<\2>|\1\2\1)/g},{matches:{1:"string",2:"string",3:"string"},pattern:/(<<)(\w+).*?$([\s\S]*?^\2)/gm},{matches:{1:"string",2:"string",3:"string"},pattern:/(<<\-)(\w+).*?$([\s\S]*?\2)/gm},
33 | {name:"string.regexp",matches:{1:"string.regexp",2:{name:"string.regexp",pattern:/\\(.){1}/g},3:"string.regexp",4:"string.regexp"},pattern:/(\/)(.*?)(\/)([a-z]*)/g},{name:"string.regexp",matches:{1:"string.regexp",2:{name:"string.regexp",pattern:/\\(.){1}/g},3:"string.regexp",4:"string.regexp"},pattern:/%r(?=(\(|\[|\{|<|.)(.*?)('|\)|\]|\}|>|\1))(?:\(\2\)|\[\2\]|\{\2\}|\<\2>|\1\2\1)([a-z]*)/g},{name:"comment",pattern:/#.*$/gm},{name:"comment",pattern:/^\=begin[\s\S]*?\=end$/gm},{matches:{1:"constant"},
34 | pattern:/(\w+:)[^:]/g},{matches:{1:"constant.symbol"},pattern:/[^:](:(?:\w+|(?=['"](.*?)['"])(?:"\2"|'\2')))/g},{name:"constant.numeric",pattern:/\b(0x[\da-f]+|\d+)\b/g},{name:"support.class",pattern:/\b[A-Z]\w*(?=((\.|::)[A-Za-z]|\[))/g},{name:"constant",pattern:/\b[A-Z]\w*\b/g},{matches:{1:"storage.class",2:"entity.name.class",3:"entity.other.inherited-class"},pattern:/\s*(class)\s+((?:(?:::)?[A-Z]\w*)+)(?:\s+<\s+((?:(?:::)?[A-Z]\w*)+))?/g},{matches:{1:"storage.module",2:"entity.name.class"},
35 | pattern:/\s*(module)\s+((?:(?:::)?[A-Z]\w*)+)/g},{name:"variable.global",pattern:/\$([a-zA-Z_]\w*)\b/g},{name:"variable.class",pattern:/@@([a-zA-Z_]\w*)\b/g},{name:"variable.instance",pattern:/@([a-zA-Z_]\w*)\b/g},{matches:{1:"keyword.control"},pattern:/[^\.]\b(BEGIN|begin|case|class|do|else|elsif|END|end|ensure|for|if|in|module|rescue|then|unless|until|when|while)\b(?![?!])/g},{matches:{1:"keyword.control.pseudo-method"},pattern:/[^\.]\b(alias|alias_method|break|next|redo|retry|return|super|undef|yield)\b(?![?!])|\bdefined\?|\bblock_given\?/g},
36 | {matches:{1:"constant.language"},pattern:/\b(nil|true|false)\b(?![?!])/g},{matches:{1:"variable.language"},pattern:/\b(__(FILE|LINE)__|self)\b(?![?!])/g},{matches:{1:"keyword.special-method"},pattern:/\b(require|gem|initialize|new|loop|include|extend|raise|attr_reader|attr_writer|attr_accessor|attr|catch|throw|private|module_function|public|protected)\b(?![?!])/g},{name:"keyword.operator",pattern:/\s\?\s|=|<<|<<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<|<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|%|&|\*\*|\*|\+|\-|\/|\||~|>>/g},
37 | {matches:{1:"keyword.operator.logical"},pattern:/[^\.]\b(and|not|or)\b/g},{matches:{1:"storage.function",2:"entity.name.function"},pattern:/(def)\s(.*?)(?=(\s|\())/g}],m);Rainbow.extend("lua",[{matches:{1:{name:"keyword.operator",pattern:/\=/g},2:{name:"string",matches:{name:"constant.character.escape",pattern:/\\('|"){1}/g}}},pattern:/(\(|\s|\[|\=)(('|")([^\\\1]|\\.)*?(\3))/gm},{name:"comment",pattern:/\-{2}\[{2}\-{2}[\s\S]*?\-{2}\]{2}\-{2}|(\-{2})[\s\S]*?$/gm},{name:"constant.numeric",pattern:/\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi},{matches:{1:"keyword"},pattern:/\b((a|e)nd|in|repeat|break|local|return|do|for|then|else(if)?|function|not|if|or|until|while)(?=\(|\b)/gi},
38 | {name:"constant.language",pattern:/true|false|nil/g},{name:"keyword.operator",pattern:/\+|\!|\-|&(gt|lt|amp);|\||\*|\=|#|\.{2}/g},{matches:{1:"storage.function",2:"entity.name.function"},pattern:/(function)\s+(\w+[\:|\.]?\w+?)(?=\()/g},{matches:{1:"support.function"},pattern:/\b(print|require|module|\w+\.\w+)(?=\()/g}]);Rainbow.extend("css",[{name:"comment",pattern:/\/\*[\s\S]*?\*\//gm},{name:"constant.hex-color",pattern:/#([a-f0-9]{3}|[a-f0-9]{6})(?=;|\s)/gi},{matches:{1:"constant.numeric",2:"keyword.unit"},pattern:/(\d+)(px|em|cm|s|%)?/g},{name:"string",pattern:/('|")(.*?)\1/g},{name:"support.css-property",matches:{1:"support.vendor-prefix"},pattern:/(-o-|-moz-|-webkit-|-ms-)?[\w-]+(?=\s?:)(?!.*\{)/g},{matches:{1:[{name:"entity.name.sass",pattern:/&/g},{name:"direct-descendant",pattern:/>/g},{name:"entity.name.class",
39 | pattern:/\.[\w\-_]+/g},{name:"entity.name.id",pattern:/\#[\w\-_]+/g},{name:"entity.name.pseudo",pattern:/:[\w\-_]+/g},{name:"entity.name.tag",pattern:/\w+/g}]},pattern:/([\w\ ,:\.\#\&\;\-_]+)(?=.*\{)/g},{matches:{2:"support.vendor-prefix",3:"support.css-value"},pattern:/(:|,)\s?(-o-|-moz-|-webkit-|-ms-)?([a-zA-Z-]*)(?=\b)(?!.*\{)/g},{matches:{1:"support.tag.style",2:[{name:"string",pattern:/('|")(.*?)(\1)/g},{name:"entity.tag.style",pattern:/(\w+)/g}],3:"support.tag.style"},pattern:/(<\/?)(style.*?)(>)/g}],
40 | m);
41 |
--------------------------------------------------------------------------------
/javascripts/sample.coffee:
--------------------------------------------------------------------------------
1 | $ ->
2 |
3 | brick = ""
4 |
5 | $(document).on "click touchend", ".gridly .brick", (event) ->
6 | event.preventDefault()
7 | event.stopPropagation()
8 | $this = $(this)
9 |
10 | $this.toggleClass('small')
11 | $this.toggleClass('large')
12 | size = 140 if $this.hasClass('small') # HACK
13 | size = 300 if $this.hasClass('large') # HACK
14 | $this.data('width', size)
15 | $this.data('height', size)
16 | $('.gridly').gridly 'layout'
17 |
18 | $(document).on "click", ".gridly .delete", (event) ->
19 | event.preventDefault()
20 | event.stopPropagation()
21 | $this = $(this)
22 |
23 | $this.closest('.brick').remove()
24 | $('.gridly').gridly 'layout'
25 |
26 | $(document).on "click", ".add", (event) ->
27 | event.preventDefault()
28 | event.stopPropagation()
29 | $('.gridly').append(brick)
30 | $('.gridly').gridly()
31 |
32 | $('.gridly').gridly()
33 |
--------------------------------------------------------------------------------
/javascripts/sample.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 2.5.1
2 | (function() {
3 | $(function() {
4 | var brick;
5 | brick = "";
6 | $(document).on("click touchend", ".gridly .brick", function(event) {
7 | var $this, size;
8 | event.preventDefault();
9 | event.stopPropagation();
10 | $this = $(this);
11 | $this.toggleClass('small');
12 | $this.toggleClass('large');
13 | if ($this.hasClass('small')) { // HACK
14 | size = 140;
15 | }
16 | if ($this.hasClass('large')) { // HACK
17 | size = 300;
18 | }
19 | $this.data('width', size);
20 | $this.data('height', size);
21 | return $('.gridly').gridly('layout');
22 | });
23 | $(document).on("click", ".gridly .delete", function(event) {
24 | var $this;
25 | event.preventDefault();
26 | event.stopPropagation();
27 | $this = $(this);
28 | $this.closest('.brick').remove();
29 | return $('.gridly').gridly('layout');
30 | });
31 | $(document).on("click", ".add", function(event) {
32 | event.preventDefault();
33 | event.stopPropagation();
34 | $('.gridly').append(brick);
35 | return $('.gridly').gridly();
36 | });
37 | return $('.gridly').gridly();
38 | });
39 |
40 | }).call(this);
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery.gridly",
3 | "version": "1.3.0",
4 | "description": "Gridly is a jQuery plugin to enable dragging and dropping as well as resizing on a grid.",
5 | "main": "./javascripts/jquery.gridly.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/ksylvest/jquery-gridly.git"
9 | },
10 | "author": "Kevin Sylvestre",
11 | "license": "MIT",
12 | "bugs": {
13 | "url": "https://github.com/ksylvest/jquery-gridly/issues"
14 | },
15 | "homepage": "https://github.com/ksylvest/jquery-gridly#readme"
16 | }
17 |
--------------------------------------------------------------------------------
/packages/jquery.gridly.tar:
--------------------------------------------------------------------------------
1 | javascripts/jquery.gridly.js 000644 000765 000024 00000033514 13677007261 017053 0 ustar 00kevin staff 000000 000000 // Generated by CoffeeScript 2.5.1
2 | (function() {
3 | /*
4 | jQuery Gridly
5 | Copyright 2020 Kevin Sylvestre
6 | 1.3.0
7 | */
8 | "use strict";
9 | var $, Animation, Draggable, Gridly;
10 |
11 | $ = jQuery;
12 |
13 | Animation = (function() {
14 | class Animation {
15 | static transition($el) {
16 | var el, ref, result, type;
17 | el = $el[0];
18 | ref = this.transitions;
19 | for (type in ref) {
20 | result = ref[type];
21 | if (el.style[type] != null) {
22 | return result;
23 | }
24 | }
25 | }
26 |
27 | static execute($el, callback) {
28 | var transition;
29 | transition = this.transition($el);
30 | if (transition != null) {
31 | return $el.one(transition, callback);
32 | } else {
33 | return callback();
34 | }
35 | }
36 |
37 | };
38 |
39 | Animation.transitions = {
40 | "webkitTransition": "webkitTransitionEnd",
41 | "mozTransition": "mozTransitionEnd",
42 | "oTransition": "oTransitionEnd",
43 | "transition": "transitionend"
44 | };
45 |
46 | return Animation;
47 |
48 | }).call(this);
49 |
50 | Draggable = class Draggable {
51 | constructor($container, selector, callbacks) {
52 | this.bind = this.bind.bind(this);
53 | this.toggle = this.toggle.bind(this);
54 | this.on = this.on.bind(this);
55 | this.off = this.off.bind(this);
56 | this.coordinate = this.coordinate.bind(this);
57 | this.began = this.began.bind(this);
58 | this.ended = this.ended.bind(this);
59 | this.moved = this.moved.bind(this);
60 | this.click = this.click.bind(this);
61 | this.touchend = this.touchend.bind(this);
62 | this.$container = $container;
63 | this.selector = selector;
64 | this.callbacks = callbacks;
65 | this.toggle();
66 | }
67 |
68 | bind(method = 'on') {
69 | $(document)[method]('mousemove touchmove', this.moved);
70 | return $(document)[method]('mouseup touchcancel', this.ended);
71 | }
72 |
73 | toggle(method = 'on') {
74 | this.$container[method]('mousedown touchstart', this.selector, this.began);
75 | this.$container[method]('touchend', this.selector, this.touchend);
76 | return this.$container[method]('click', this.selector, this.click);
77 | }
78 |
79 | on() {
80 | return this.toggle('on');
81 | }
82 |
83 | off() {
84 | return this.toggle('off');
85 | }
86 |
87 | coordinate(event) {
88 | switch (event.type) {
89 | case 'touchstart':
90 | case 'touchmove':
91 | case 'touchend':
92 | case 'touchcancel':
93 | return event.originalEvent.touches[0];
94 | default:
95 | return event;
96 | }
97 | }
98 |
99 | began(event) {
100 | var ref;
101 | if (this.$target) {
102 | return;
103 | }
104 | event.preventDefault();
105 | event.stopPropagation();
106 | this.bind('on');
107 | this.$target = $(event.target).closest(this.$container.find(this.selector));
108 | this.$target.addClass('dragging');
109 | this.origin = {
110 | x: this.coordinate(event).pageX - this.$target.position().left,
111 | y: this.coordinate(event).pageY - this.$target.position().top
112 | };
113 | return (ref = this.callbacks) != null ? typeof ref.began === "function" ? ref.began(event) : void 0 : void 0;
114 | }
115 |
116 | ended(event) {
117 | var ref;
118 | if (this.$target == null) {
119 | return;
120 | }
121 | if (event.type !== 'touchend') {
122 | event.preventDefault();
123 | event.stopPropagation();
124 | }
125 | this.bind('off');
126 | this.$target.removeClass('dragging');
127 | delete this.$target;
128 | delete this.origin;
129 | return (ref = this.callbacks) != null ? typeof ref.ended === "function" ? ref.ended(event) : void 0 : void 0;
130 | }
131 |
132 | moved(event) {
133 | var ref;
134 | if (this.$target == null) {
135 | return;
136 | }
137 | event.preventDefault();
138 | event.stopPropagation();
139 | this.$target.css({
140 | left: this.coordinate(event).pageX - this.origin.x,
141 | top: this.coordinate(event).pageY - this.origin.y
142 | });
143 | this.dragged = this.$target;
144 | return (ref = this.callbacks) != null ? typeof ref.moved === "function" ? ref.moved(event) : void 0 : void 0;
145 | }
146 |
147 | click(event) {
148 | if (!this.dragged) {
149 | return;
150 | }
151 | event.preventDefault();
152 | event.stopPropagation();
153 | return delete this.dragged;
154 | }
155 |
156 | touchend(event) {
157 | this.ended(event);
158 | return this.click(event);
159 | }
160 |
161 | };
162 |
163 | Gridly = (function() {
164 | class Gridly {
165 | static gridly($el, options = {}) {
166 | var data;
167 | data = $el.data('_gridly');
168 | if (data) {
169 | $.extend(data.settings, options);
170 | } else {
171 | data = new Gridly($el, options);
172 | $el.data('_gridly', data);
173 | }
174 | return data;
175 | }
176 |
177 | constructor($el, settings = {}) {
178 | this.ordinalize = this.ordinalize.bind(this);
179 | this.reordinalize = this.reordinalize.bind(this);
180 | this.$ = this.$.bind(this);
181 | this.compare = this.compare.bind(this);
182 | this.draggable = this.draggable.bind(this);
183 | this.$sorted = this.$sorted.bind(this);
184 | this.draggingBegan = this.draggingBegan.bind(this);
185 | this.draggingEnded = this.draggingEnded.bind(this);
186 | this.draggingMoved = this.draggingMoved.bind(this);
187 | this.size = this.size.bind(this);
188 | this.position = this.position.bind(this);
189 | this.structure = this.structure.bind(this);
190 | this.layout = this.layout.bind(this);
191 | this.optimize = this.optimize.bind(this);
192 | this.$el = $el;
193 | this.settings = $.extend({}, Gridly.settings, settings);
194 | this.ordinalize(this.$('> *'));
195 | if (this.settings.draggable !== false) {
196 | this.draggable();
197 | }
198 | return this;
199 | }
200 |
201 | ordinalize($elements) {
202 | var $element, i, j, ref, results1;
203 | results1 = [];
204 | for (i = j = 0, ref = $elements.length; (0 <= ref ? j <= ref : j >= ref); i = 0 <= ref ? ++j : --j) {
205 | $element = $($elements[i]);
206 | results1.push($element.data('position', i));
207 | }
208 | return results1;
209 | }
210 |
211 | reordinalize($element, position) {
212 | return $element.data('position', position);
213 | }
214 |
215 | $(selector) {
216 | return this.$el.find(selector);
217 | }
218 |
219 | compare(d, s) {
220 | if (d.y > s.y + s.h) {
221 | return +1;
222 | }
223 | if (s.y > d.y + d.h) {
224 | return -1;
225 | }
226 | if ((d.x + (d.w / 2)) > (s.x + (s.w / 2))) {
227 | return +1;
228 | }
229 | if ((s.x + (s.w / 2)) > (d.x + (d.w / 2))) {
230 | return -1;
231 | }
232 | return 0;
233 | }
234 |
235 | draggable(method) {
236 | if (this._draggable == null) {
237 | this._draggable = new Draggable(this.$el, this.settings.draggable.selector, {
238 | began: this.draggingBegan,
239 | ended: this.draggingEnded,
240 | moved: this.draggingMoved
241 | });
242 | }
243 | if (method != null) {
244 | return this._draggable[method]();
245 | }
246 | }
247 |
248 | $sorted($elements) {
249 | return ($elements || this.$('> *')).sort(function(a, b) {
250 | var $a, $b, aPosition, aPositionInt, bPosition, bPositionInt;
251 | $a = $(a);
252 | $b = $(b);
253 | aPosition = $a.data('position');
254 | bPosition = $b.data('position');
255 | aPositionInt = parseInt(aPosition);
256 | bPositionInt = parseInt(bPosition);
257 | if ((aPosition != null) && (bPosition == null)) {
258 | return -1;
259 | }
260 | if ((bPosition != null) && (aPosition == null)) {
261 | return +1;
262 | }
263 | if (!aPosition && !bPosition && $a.index() < $b.index()) {
264 | return -1;
265 | }
266 | if (!bPosition && !aPosition && $b.index() < $a.index()) {
267 | return +1;
268 | }
269 | if (aPositionInt < bPositionInt) {
270 | return -1;
271 | }
272 | if (bPositionInt < aPositionInt) {
273 | return +1;
274 | }
275 | return 0;
276 | });
277 | }
278 |
279 | draggingBegan(event) {
280 | var $elements, ref, ref1;
281 | $elements = this.$sorted();
282 | this.ordinalize($elements);
283 | setTimeout(this.layout, 0);
284 | return (ref = this.settings) != null ? (ref1 = ref.callbacks) != null ? typeof ref1.reordering === "function" ? ref1.reordering($elements) : void 0 : void 0 : void 0;
285 | }
286 |
287 | draggingEnded(event) {
288 | var $elements, ref, ref1;
289 | $elements = this.$sorted();
290 | this.ordinalize($elements);
291 | setTimeout(this.layout, 0);
292 | return (ref = this.settings) != null ? (ref1 = ref.callbacks) != null ? typeof ref1.reordered === "function" ? ref1.reordered($elements, this._draggable.dragged) : void 0 : void 0 : void 0;
293 | }
294 |
295 | draggingMoved(event) {
296 | var $dragging, $elements, element, i, index, j, k, len, original, positions, ref, ref1, ref2;
297 | $dragging = $(event.target).closest(this.$(this.settings.draggable.selector));
298 | $elements = this.$sorted(this.$(this.settings.draggable.selector));
299 | positions = this.structure($elements).positions;
300 | original = index = $dragging.data('position');
301 | ref = positions.filter(function(position) {
302 | return position.$element.is($dragging);
303 | });
304 | for (j = 0, len = ref.length; j < len; j++) {
305 | element = ref[j];
306 | element.x = $dragging.position().left;
307 | element.y = $dragging.position().top;
308 | element.w = $dragging.data('width') || $dragging.outerWidth();
309 | element.h = $dragging.data('height') || $dragging.outerHeight();
310 | }
311 | positions.sort(this.compare);
312 | $elements = positions.map(function(position) {
313 | return position.$element;
314 | });
315 | $elements = (((ref1 = this.settings.callbacks) != null ? ref1.optimize : void 0) || this.optimize)($elements);
316 | for (i = k = 0, ref2 = $elements.length; (0 <= ref2 ? k < ref2 : k > ref2); i = 0 <= ref2 ? ++k : --k) {
317 | this.reordinalize($($elements[i]), i);
318 | }
319 | return this.layout();
320 | }
321 |
322 | size($element) {
323 | return (($element.data('width') || $element.outerWidth()) + this.settings.gutter) / (this.settings.base + this.settings.gutter);
324 | }
325 |
326 | position($element, columns) {
327 | var column, height, i, j, k, max, ref, ref1, ref2, size;
328 | size = this.size($element);
329 | height = 2e308;
330 | column = 0;
331 | for (i = j = 0, ref = columns.length - size; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
332 | max = Math.max(...columns.slice(i, (i + size)));
333 | if (max < height) {
334 | height = max;
335 | column = i;
336 | }
337 | }
338 | for (i = k = ref1 = column, ref2 = column + size; (ref1 <= ref2 ? k < ref2 : k > ref2); i = ref1 <= ref2 ? ++k : --k) {
339 | columns[i] = height + ($element.data('height') || $element.outerHeight()) + this.settings.gutter;
340 | }
341 | return {
342 | x: column * (this.settings.base + this.settings.gutter),
343 | y: height
344 | };
345 | }
346 |
347 | structure($elements = this.$sorted()) {
348 | var $element, columns, i, index, j, position, positions, ref;
349 | positions = [];
350 | columns = (function() {
351 | var j, ref, results1;
352 | results1 = [];
353 | for (i = j = 0, ref = this.settings.columns; (0 <= ref ? j <= ref : j >= ref); i = 0 <= ref ? ++j : --j) {
354 | results1.push(0);
355 | }
356 | return results1;
357 | }).call(this);
358 | for (index = j = 0, ref = $elements.length; (0 <= ref ? j < ref : j > ref); index = 0 <= ref ? ++j : --j) {
359 | $element = $($elements[index]);
360 | position = this.position($element, columns);
361 | positions.push({
362 | x: position.x,
363 | y: position.y,
364 | w: $element.data('width') || $element.outerWidth(),
365 | h: $element.data('height') || $element.outerHeight(),
366 | $element: $element
367 | });
368 | }
369 | return {
370 | height: Math.max(...columns),
371 | positions: positions
372 | };
373 | }
374 |
375 | layout() {
376 | var $element, $elements, index, j, position, ref, ref1, structure;
377 | $elements = (((ref = this.settings.callbacks) != null ? ref.optimize : void 0) || this.optimize)(this.$sorted());
378 | structure = this.structure($elements);
379 | for (index = j = 0, ref1 = $elements.length; (0 <= ref1 ? j < ref1 : j > ref1); index = 0 <= ref1 ? ++j : --j) {
380 | $element = $($elements[index]);
381 | position = structure.positions[index];
382 | if ($element.is('.dragging')) {
383 | continue;
384 | }
385 | $element.css({
386 | position: 'absolute',
387 | left: position.x,
388 | top: position.y
389 | });
390 | }
391 | return this.$el.css({
392 | height: structure.height
393 | });
394 | }
395 |
396 | optimize(originals) {
397 | var columns, index, j, ref, results;
398 | results = [];
399 | columns = 0;
400 | while (originals.length > 0) {
401 | if (columns === this.settings.columns) {
402 | columns = 0;
403 | }
404 | index = 0;
405 | for (index = j = 0, ref = originals.length; (0 <= ref ? j < ref : j > ref); index = 0 <= ref ? ++j : --j) {
406 | if (!(columns + this.size($(originals[index])) > this.settings.columns)) {
407 | break;
408 | }
409 | }
410 | if (index === originals.length) {
411 | index = 0;
412 | columns = 0;
413 | }
414 | columns += this.size($(originals[index]));
415 | // Move from originals into results
416 | results.push(originals.splice(index, 1)[0]);
417 | }
418 | return results;
419 | }
420 |
421 | };
422 |
423 | Gridly.settings = {
424 | base: 60,
425 | gutter: 20,
426 | columns: 12,
427 | draggable: {
428 | zIndex: 800,
429 | selector: '> *'
430 | }
431 | };
432 |
433 | return Gridly;
434 |
435 | }).call(this);
436 |
437 | $.fn.extend({
438 | gridly: function(option = {}, ...parameters) {
439 | return this.each(function() {
440 | var $this, action, options;
441 | $this = $(this);
442 | options = $.extend({}, $.fn.gridly.defaults, typeof option === "object" && option);
443 | action = typeof option === "string" ? option : option.action;
444 | if (action == null) {
445 | action = "layout";
446 | }
447 | return Gridly.gridly($this, options)[action](parameters);
448 | });
449 | }
450 | });
451 |
452 | }).call(this);
453 | stylesheets/jquery.gridly.css 000644 000765 000024 00000000261 13677007120 017235 0 ustar 00kevin staff 000000 000000 /* jQuery Gridly
454 | * Copyright 2020 Kevin Sylvestre
455 | * 1.3.0
456 | */
457 | .gridly, .gridly > :not(.dragging) {
458 | transition: all 0.4s ease-in-out; }
459 | .gridly .dragging {
460 | z-index: 800; }
461 |
--------------------------------------------------------------------------------
/packages/jquery.gridly.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ksylvest/jquery-gridly/65d1e4bfdc3f16cd837710d8b631b91c4db01ddc/packages/jquery.gridly.zip
--------------------------------------------------------------------------------
/stylesheets/jquery.gridly.css:
--------------------------------------------------------------------------------
1 | /* jQuery Gridly
2 | * Copyright 2020 Kevin Sylvestre
3 | * 1.3.0
4 | */
5 | .gridly, .gridly > :not(.dragging) {
6 | transition: all 0.4s ease-in-out; }
7 | .gridly .dragging {
8 | z-index: 800; }
9 |
--------------------------------------------------------------------------------
/stylesheets/jquery.gridly.sass:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Gridly
3 | * Copyright 2020 Kevin Sylvestre
4 | * 1.3.0
5 | */
6 |
7 | $black: #000
8 | $white: #FFF
9 |
10 | $namespace: "gridly"
11 |
12 | .#{$namespace}
13 | &, > :not(.dragging)
14 | transition: all 0.4s ease-in-out
15 | .dragging
16 | z-index: 800
17 |
--------------------------------------------------------------------------------
/stylesheets/sample.css:
--------------------------------------------------------------------------------
1 | body, html, p, h1, h2, h3, h4, h5, h6 {
2 | font-family: "Lato", "Helvetica", serif;
3 | font-weight: normal; }
4 |
5 | code {
6 | font-family: "Consolas", "Monaco", monospace;
7 | font-weight: normal; }
8 |
9 | body, html, p, code {
10 | color: #888; }
11 |
12 | h1, h2, h3, h4, h5, h6 {
13 | color: #444; }
14 |
15 | pre {
16 | overflow: scroll;
17 | background: #EEE;
18 | padding: 10px; }
19 |
20 | .content {
21 | width: 980px;
22 | margin: 80px auto; }
23 |
24 | .formats .format {
25 | display: inline-block; }
26 |
27 | .zip {
28 | background: url("../images/zip.png");
29 | display: block;
30 | width: 128px;
31 | height: 128px; }
32 |
33 | .tar {
34 | background: url("../images/tar.png");
35 | display: block;
36 | width: 128px;
37 | height: 128px; }
38 |
39 | .fork {
40 | position: absolute;
41 | top: 0;
42 | left: 0;
43 | border: 0; }
44 |
45 | .button {
46 | display: block;
47 | padding: 20px;
48 | width: 200px;
49 | color: #FFF;
50 | background: #888;
51 | margin: 20px 0;
52 | text-align: center;
53 | text-decoration: none;
54 | border-radius: 4px; }
55 |
56 | pre .support.tag {
57 | color: #008; }
58 | pre .support.attribute {
59 | color: #800; }
60 | pre .string.value {
61 | color: #080; }
62 |
63 | .example {
64 | position: relative; }
65 | .example .brick {
66 | opacity: 1;
67 | cursor: pointer;
68 | position: relative; }
69 | .example .brick .delete {
70 | display: block;
71 | color: #FFF;
72 | background: rgba(255, 255, 255, 0.2);
73 | width: 40px;
74 | height: 40px;
75 | top: 0;
76 | right: 0;
77 | position: absolute;
78 | text-align: center;
79 | line-height: 40px; }
80 | .example .brick.small {
81 | width: 140px;
82 | height: 140px; }
83 | .example .brick.large {
84 | width: 300px;
85 | height: 300px; }
86 | .example .brick.dragging {
87 | opacity: 0.8; }
88 | .example .brick:nth-child(20n + 1) {
89 | background: #1ABC9C; }
90 | .example .brick:nth-child(20n + 2) {
91 | background: #16A085; }
92 | .example .brick:nth-child(20n + 3) {
93 | background: #2ECC71; }
94 | .example .brick:nth-child(20n + 4) {
95 | background: #27AE60; }
96 | .example .brick:nth-child(20n + 5) {
97 | background: #3498DB; }
98 | .example .brick:nth-child(20n + 6) {
99 | background: #2980B9; }
100 | .example .brick:nth-child(20n + 7) {
101 | background: #9B59B6; }
102 | .example .brick:nth-child(20n + 8) {
103 | background: #8E44AD; }
104 | .example .brick:nth-child(20n + 9) {
105 | background: #34495E; }
106 | .example .brick:nth-child(20n + 10) {
107 | background: #2C3E50; }
108 | .example .brick:nth-child(20n + 11) {
109 | background: #F1C40F; }
110 | .example .brick:nth-child(20n + 12) {
111 | background: #F39C12; }
112 | .example .brick:nth-child(20n + 13) {
113 | background: #E67E22; }
114 | .example .brick:nth-child(20n + 14) {
115 | background: #D35400; }
116 | .example .brick:nth-child(20n + 15) {
117 | background: #E74C3C; }
118 | .example .brick:nth-child(20n + 16) {
119 | background: #C0392B; }
120 | .example .brick:nth-child(20n + 17) {
121 | background: #ECF0F1; }
122 | .example .brick:nth-child(20n + 18) {
123 | background: #BDC3C7; }
124 | .example .brick:nth-child(20n + 19) {
125 | background: #95A5A6; }
126 | .example .brick:nth-child(20n + 20) {
127 | background: #7F8C8D; }
128 |
--------------------------------------------------------------------------------
/stylesheets/sample.sass:
--------------------------------------------------------------------------------
1 | $colors: #1ABC9C, #16A085, #2ECC71, #27AE60, #3498DB, #2980B9, #9B59B6, #8E44AD, #34495E, #2C3E50, #F1C40F, #F39C12, #E67E22, #D35400, #E74C3C, #C0392B, #ECF0F1, #BDC3C7, #95A5A6, #7F8C8D
2 |
3 | body, html, p, h1, h2, h3, h4, h5, h6
4 | font-family: "Lato", "Helvetica", serif
5 | font-weight: normal
6 |
7 | code
8 | font-family: "Consolas", "Monaco", monospace
9 | font-weight: normal
10 |
11 | body, html, p, code
12 | color: #888
13 |
14 | h1, h2, h3, h4, h5, h6
15 | color: #444
16 |
17 | pre
18 | overflow: scroll
19 | background: #EEE
20 | padding: 10px
21 |
22 | .content
23 | width: 980px
24 | margin: 80px auto
25 |
26 | .formats
27 | .format
28 | display: inline-block
29 |
30 | .zip
31 | background: url('../images/zip.png')
32 | display: block
33 | width: 128px
34 | height: 128px
35 |
36 | .tar
37 | background: url('../images/tar.png')
38 | display: block
39 | width: 128px
40 | height: 128px
41 |
42 | .fork
43 | position: absolute
44 | top: 0
45 | left: 0
46 | border: 0
47 |
48 | .button
49 | display: block
50 | padding: 20px
51 | width: 200px
52 | color: #FFF
53 | background: #888
54 | margin: 20px 0
55 | text:
56 | align: center
57 | decoration: none
58 | border:
59 | radius: 4px
60 |
61 | pre
62 | .support
63 | &.tag
64 | color: #008
65 | &.attribute
66 | color: #800
67 | .string
68 | &.value
69 | color: #080
70 |
71 | .example
72 | position: relative
73 | .brick
74 | opacity: 1.0
75 | cursor: pointer
76 | position: relative
77 | .delete
78 | display: block
79 | color: #FFF
80 | background: rgba(#FFF, 0.2)
81 | width: 40px
82 | height: 40px
83 | top: 0
84 | right: 0
85 | position: absolute
86 | text-align: center
87 | line-height: 40px
88 | &.small
89 | width: 140px
90 | height: 140px
91 | &.large
92 | width: 300px
93 | height: 300px
94 | &.dragging
95 | opacity: 0.8
96 | $index: 0
97 | $length: length($colors)
98 | @each $color in $colors
99 | $index: $index + 1
100 | &:nth-child(#{$length}n + #{$index})
101 | background: $color
102 |
--------------------------------------------------------------------------------