puffer 0.0.32 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/Gemfile +1 -26
- data/Gemfile.lock +66 -64
- data/README.md +34 -23
- data/Rakefile +1 -11
- data/VERSION +1 -1
- data/app/assets/javascripts/puffer/application.js +6 -1
- data/app/assets/javascripts/puffer/associations.js +18 -0
- data/app/assets/javascripts/puffer/puffer.js +7 -0
- data/app/assets/javascripts/puffer/right-calendar-src.js +19 -3
- data/app/assets/javascripts/puffer/right-dnd-src.js +591 -0
- data/app/assets/javascripts/puffer/right-in-edit-src.js +373 -0
- data/app/assets/javascripts/puffer/right-keys-src.js +87 -0
- data/app/assets/javascripts/puffer/{paginator.js → right-paginator-src.js} +0 -0
- data/app/assets/javascripts/puffer/right-slider-src.js +29 -32
- data/app/assets/javascripts/puffer/right-sortable-src.js +430 -0
- data/app/assets/javascripts/puffer/right-src.js +358 -99
- data/app/assets/stylesheets/puffer/puffer.css +29 -4
- data/app/components/base/form.html.erb +8 -14
- data/app/components/base_component.rb +1 -1
- data/app/components/boolean/form.html.erb +5 -3
- data/app/components/boolean/index.html.erb +6 -2
- data/app/components/boolean_component.rb +2 -2
- data/app/components/date_time/filter.html.erb +9 -0
- data/app/components/date_time/form.html.erb +8 -4
- data/app/components/date_time_component.rb +21 -5
- data/app/components/file/form.html.erb +8 -4
- data/app/components/hidden/form.html.erb +3 -1
- data/app/components/nested_attributes_many/form.html.erb +47 -0
- data/app/components/nested_attributes_many_component.rb +7 -0
- data/app/components/nested_attributes_one/form.html.erb +48 -0
- data/app/components/nested_attributes_one_component.rb +7 -0
- data/app/components/password/form.html.erb +8 -4
- data/app/components/password_component.rb +1 -1
- data/app/components/references_many/index.html.erb +1 -1
- data/app/components/references_one/choose.html.erb +1 -1
- data/app/components/references_one/form.html.erb +10 -9
- data/app/components/references_one_component.rb +0 -1
- data/app/components/render_component.rb +13 -0
- data/app/components/select/filter.html.erb +4 -2
- data/app/components/select/form.html.erb +8 -4
- data/app/components/text/form.html.erb +8 -4
- data/app/controllers/admin/sessions_controller.rb +1 -21
- data/app/controllers/puffer/base.rb +10 -3
- data/app/controllers/puffer/dashboard_base.rb +7 -1
- data/app/controllers/puffer/{sessions_base.rb → sessions/base.rb} +10 -7
- data/app/controllers/puffer/sessions/clearance.rb +29 -0
- data/app/controllers/puffer/{sessions_devise_base.rb → sessions/devise.rb} +1 -1
- data/app/controllers/puffer/sessions/simple.rb +28 -0
- data/app/controllers/puffer/tree_base.rb +1 -1
- data/app/models/puffer_user.rb +3 -0
- data/app/views/layouts/puffer.html.erb +3 -3
- data/app/views/puffer/base/_edit.html.erb +15 -0
- data/app/views/puffer/base/_index.html.erb +26 -0
- data/app/views/puffer/base/_show.html.erb +13 -0
- data/app/views/puffer/base/_table.html.erb +1 -1
- data/app/views/puffer/base/edit.html.erb +1 -15
- data/app/views/puffer/base/edit.js.erb +1 -0
- data/app/views/puffer/base/index.html.erb +1 -20
- data/app/views/puffer/base/index.js.erb +1 -0
- data/app/views/puffer/base/new.html.erb +1 -1
- data/app/views/puffer/base/show.html.erb +1 -22
- data/app/views/puffer/base/show.js.erb +1 -0
- data/app/views/puffer/base/update.js.erb +1 -0
- data/app/views/puffer/sessions/base/new.html.erb +11 -0
- data/app/views/puffer/tree_base/_record.html.erb +1 -1
- data/lib/puffer/component.rb +14 -47
- data/lib/puffer/controller/auth.rb +13 -9
- data/lib/puffer/controller/config.rb +18 -0
- data/lib/puffer/controller/mutate.rb +8 -8
- data/lib/puffer/engine.rb +5 -0
- data/lib/puffer/field.rb +5 -11
- data/lib/puffer/filters.rb +86 -56
- data/lib/puffer/helpers/component_helper.rb +24 -0
- data/lib/puffer/helpers/puffer_helper.rb +65 -0
- data/lib/puffer/helpers/puffer_tree_helper.rb +19 -0
- data/lib/puffer/orm_adapter/active_record.rb +40 -11
- data/lib/puffer/orm_adapter/base.rb +9 -0
- data/lib/puffer/orm_adapter/mongoid.rb +32 -9
- data/lib/puffer/resource/node.rb +2 -2
- data/lib/puffer/resource/routing.rb +30 -16
- data/lib/puffer/resource.rb +20 -20
- data/lib/puffer/version.rb +3 -0
- data/lib/puffer.rb +26 -5
- data/puffer.gemspec +34 -296
- data/spec/app/components/base_component_spec.rb +1 -1
- data/spec/app/components/boolean_component_spec.rb +2 -0
- data/spec/app/components/date_time_component_spec.rb +1 -0
- data/spec/app/components/file_component_spec.rb +1 -0
- data/spec/app/components/hidden_component_spec.rb +1 -0
- data/spec/app/components/password_component_spec.rb +2 -0
- data/spec/app/components/select_component_spec.rb +1 -0
- data/spec/app/components/string_component_spec.rb +1 -0
- data/spec/app/components/text_component_spec.rb +1 -0
- data/spec/dummy/app/controllers/admin/news_controller.rb +2 -0
- data/spec/dummy/app/controllers/admin/profiles_controller.rb +1 -1
- data/spec/dummy/app/controllers/admin/users_controller.rb +2 -0
- data/spec/dummy/app/controllers/orms/active_record_orm_primals_controller.rb +8 -0
- data/spec/dummy/app/helpers/news_helper.rb +7 -0
- data/spec/dummy/app/models/active_record_orm/has_many_reference.rb +5 -0
- data/spec/dummy/app/models/active_record_orm/has_one_reference.rb +5 -0
- data/spec/dummy/app/models/active_record_orm/primal.rb +4 -0
- data/spec/dummy/config/environments/development.rb +1 -1
- data/spec/dummy/db/migrate/20111120144025_create_active_record_orm_has_one_references.rb +10 -0
- data/spec/dummy/db/migrate/20111122203304_create_active_record_orm_has_many_references.rb +10 -0
- data/spec/dummy/db/schema.rb +15 -1
- data/spec/helpers/puffer_helper_spec.rb +1 -1
- data/spec/lib/fields_spec.rb +0 -9
- data/spec/lib/filters_spec.rb +4 -8
- data/spec/lib/orm_adapter/base_shared.rb +22 -0
- data/spec/spec_helper.rb +1 -1
- metadata +89 -60
- data/app/components/string/form.html.erb +0 -5
- data/app/helpers/puffer_helper.rb +0 -51
- data/app/helpers/puffer_tree_helper.rb +0 -15
- data/app/views/puffer/sessions_base/new.html.erb +0 -11
- data/lib/puffer/extensions/form.rb +0 -16
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drag'n'Drop module v2.2.2
|
|
3
|
+
* http://rightjs.org/plugins/drag-n-drop
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2009-2011 Nikolay Nemshilov
|
|
6
|
+
*/
|
|
7
|
+
(function(window, document, RightJS) {
|
|
8
|
+
/**
|
|
9
|
+
* The DND module initialization script
|
|
10
|
+
*
|
|
11
|
+
* Copyright (C) 2010 Nikolay Nemshilov
|
|
12
|
+
*/
|
|
13
|
+
var R = RightJS,
|
|
14
|
+
$ = RightJS.$,
|
|
15
|
+
$w = RightJS.$w,
|
|
16
|
+
Class = RightJS.Class,
|
|
17
|
+
isHash = RightJS.isHash,
|
|
18
|
+
isArray = RightJS.isArray,
|
|
19
|
+
Element = RightJS.Element,
|
|
20
|
+
Observer = RightJS.Observer;
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Draggable unit
|
|
26
|
+
*
|
|
27
|
+
* Copyright (C) 2009-2011 Nikolay Nemshilov
|
|
28
|
+
*/
|
|
29
|
+
var Draggable = new Class(Observer, {
|
|
30
|
+
extend: {
|
|
31
|
+
version: '2.2.2',
|
|
32
|
+
|
|
33
|
+
EVENTS: $w('before start drag stop drop'),
|
|
34
|
+
|
|
35
|
+
Options: {
|
|
36
|
+
handle: null, // a handle element that will start the drag
|
|
37
|
+
|
|
38
|
+
snap: 0, // a number in pixels or [x,y]
|
|
39
|
+
axis: null, // null or 'x' or 'y' or 'vertical' or 'horizontal'
|
|
40
|
+
range: null, // {x: [min, max], y:[min, max]} or reference to another element
|
|
41
|
+
|
|
42
|
+
dragClass: 'dragging', // the in-process class name
|
|
43
|
+
|
|
44
|
+
clone: false, // if should keep a clone in place
|
|
45
|
+
revert: false, // marker if the object should be moved back on finish
|
|
46
|
+
revertDuration: 'normal', // the moving back fx duration
|
|
47
|
+
|
|
48
|
+
scroll: true, // if it should automatically scroll
|
|
49
|
+
scrollSensitivity: 32, // the scrolling area size in pixels
|
|
50
|
+
|
|
51
|
+
zIndex: 10000000, // the element's z-index
|
|
52
|
+
moveOut: false, // marker if the draggable should be moved out of it's context (for overflown elements)
|
|
53
|
+
|
|
54
|
+
relName: 'draggable' // the audodiscovery feature key
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// referenece to the currently active draggable
|
|
58
|
+
current: null,
|
|
59
|
+
|
|
60
|
+
// scans the document for auto-processed draggables with the rel="draggable" attribute
|
|
61
|
+
rescan: function(scope) {
|
|
62
|
+
var key = this.Options.relName, ref = this === Draggable ? 'draggable' : 'droppable';
|
|
63
|
+
|
|
64
|
+
($(scope)||$(document)).find('*[rel^="'+key+'"]').each(function(element) {
|
|
65
|
+
if (!element[ref]) {
|
|
66
|
+
new this(element, new Function('return '+element.get('data-'+key))() || {});
|
|
67
|
+
}
|
|
68
|
+
}, this);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Basic controller
|
|
74
|
+
*
|
|
75
|
+
* @param mixed element reference
|
|
76
|
+
* @param Object options
|
|
77
|
+
*/
|
|
78
|
+
initialize: function(element, options) {
|
|
79
|
+
this.element = $(element);
|
|
80
|
+
this.$super(options);
|
|
81
|
+
|
|
82
|
+
this._dragStart = R(this.dragStart).bind(this);
|
|
83
|
+
this.handle.onMousedown(this._dragStart);
|
|
84
|
+
|
|
85
|
+
this.element.draggable = this;
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* detaches the mouse observers out of the draggable element
|
|
90
|
+
*
|
|
91
|
+
* @return this
|
|
92
|
+
*/
|
|
93
|
+
destroy: function() {
|
|
94
|
+
this.handle.stopObserving('mousedown', this._dragStart);
|
|
95
|
+
delete(this.element.draggable);
|
|
96
|
+
|
|
97
|
+
return this;
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// additional options processing
|
|
101
|
+
setOptions: function(options) {
|
|
102
|
+
this.$super(options);
|
|
103
|
+
|
|
104
|
+
// checking the handle
|
|
105
|
+
this.handle = this.options.handle ? $(this.options.handle) : this.element;
|
|
106
|
+
|
|
107
|
+
// checking the spappings
|
|
108
|
+
if (isArray(this.options.snap)) {
|
|
109
|
+
this.snapX = this.options.snap[0];
|
|
110
|
+
this.snapY = this.options.snap[1];
|
|
111
|
+
} else {
|
|
112
|
+
this.snapX = this.snapY = this.options.snap;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return this;
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Moves the element back to the original position
|
|
120
|
+
*
|
|
121
|
+
* @return this
|
|
122
|
+
*/
|
|
123
|
+
revert: function() {
|
|
124
|
+
var position = this.clone.position();
|
|
125
|
+
var end_style = {
|
|
126
|
+
top: (position.y + this.ryDiff) + 'px',
|
|
127
|
+
left: (position.x + this.rxDiff) + 'px'
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
if (this.options.revertDuration && this.element.morph) {
|
|
131
|
+
this.element.morph(end_style, {
|
|
132
|
+
duration: this.options.revertDuration,
|
|
133
|
+
onFinish: R(this.swapBack).bind(this)
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
this.element.setStyle(end_style);
|
|
137
|
+
this.swapBack();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return this;
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// protected
|
|
144
|
+
|
|
145
|
+
// handles the event start
|
|
146
|
+
dragStart: function(event) {
|
|
147
|
+
if (this._drag) { return false; } else { this._drag = true; }
|
|
148
|
+
|
|
149
|
+
this.fire('before', this, event.stop());
|
|
150
|
+
|
|
151
|
+
// calculating the positions diff
|
|
152
|
+
var position = this.element.position();
|
|
153
|
+
|
|
154
|
+
this.xDiff = event.pageX - position.x;
|
|
155
|
+
this.yDiff = event.pageY - position.y;
|
|
156
|
+
|
|
157
|
+
// grabbing the relative position diffs for nested spaces
|
|
158
|
+
this.rxDiff = this.ryDiff = 0;
|
|
159
|
+
this.element.parents().reverse().each(function(parent) {
|
|
160
|
+
if (parent.getStyle('position') !== 'static') {
|
|
161
|
+
parent = parent.position();
|
|
162
|
+
|
|
163
|
+
this.rxDiff = - parent.x;
|
|
164
|
+
this.ryDiff = - parent.y;
|
|
165
|
+
}
|
|
166
|
+
}, this);
|
|
167
|
+
|
|
168
|
+
// preserving the element sizes
|
|
169
|
+
var size = {
|
|
170
|
+
x: this.element.getStyle('width'),
|
|
171
|
+
y: this.element.getStyle('height')
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
if (size.x == 'auto') { size.x = this.element._.offsetWidth + 'px'; }
|
|
175
|
+
if (size.y == 'auto') { size.y = this.element._.offsetHeight + 'px'; }
|
|
176
|
+
|
|
177
|
+
// building a clone element if necessary
|
|
178
|
+
if (this.options.clone || this.options.revert) {
|
|
179
|
+
this.clone = new Element(this.element._.cloneNode(true)).setStyle({
|
|
180
|
+
visibility: this.options.clone ? 'visible' : 'hidden'
|
|
181
|
+
}).insertTo(this.element, 'before');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// reinserting the element to the body so it was over all the other elements
|
|
185
|
+
this.element.setStyle({
|
|
186
|
+
position: 'absolute',
|
|
187
|
+
zIndex: Draggable.Options.zIndex++,
|
|
188
|
+
top: (position.y + this.ryDiff) + 'px',
|
|
189
|
+
left: (position.x + this.rxDiff) + 'px',
|
|
190
|
+
width: size.x,
|
|
191
|
+
height: size.y
|
|
192
|
+
}).addClass(this.options.dragClass);
|
|
193
|
+
|
|
194
|
+
if (this.options.moveOut) {
|
|
195
|
+
this.element.insertTo(document.body);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// caching the window scrolls
|
|
199
|
+
this.winScrolls = $(window).scrolls();
|
|
200
|
+
this.winSizes = $(window).size();
|
|
201
|
+
|
|
202
|
+
Draggable.current = this.calcConstraints().fire('start', this, event);
|
|
203
|
+
|
|
204
|
+
this.style = this.element._.style;
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// catches the mouse move event
|
|
208
|
+
dragProcess: function(event) {
|
|
209
|
+
var page_x = event.pageX, page_y = event.pageY, x = page_x - this.xDiff, y = page_y - this.yDiff;
|
|
210
|
+
|
|
211
|
+
// checking the range
|
|
212
|
+
if (this.ranged) {
|
|
213
|
+
if (this.minX > x) { x = this.minX; }
|
|
214
|
+
if (this.maxX < x) { x = this.maxX; }
|
|
215
|
+
if (this.minY > y) { y = this.minY; }
|
|
216
|
+
if (this.maxY < y) { y = this.maxY; }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// checking the scrolls
|
|
220
|
+
if (this.options.scroll) {
|
|
221
|
+
var scrolls = {x: this.winScrolls.x, y: this.winScrolls.y},
|
|
222
|
+
sensitivity = this.options.scrollSensitivity;
|
|
223
|
+
|
|
224
|
+
if ((page_y - scrolls.y) < sensitivity) {
|
|
225
|
+
scrolls.y = page_y - sensitivity;
|
|
226
|
+
} else if ((scrolls.y + this.winSizes.y - page_y) < sensitivity){
|
|
227
|
+
scrolls.y = page_y - this.winSizes.y + sensitivity;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if ((page_x - scrolls.x) < sensitivity) {
|
|
231
|
+
scrolls.x = page_x - sensitivity;
|
|
232
|
+
} else if ((scrolls.x + this.winSizes.x - page_x) < sensitivity){
|
|
233
|
+
scrolls.x = page_x - this.winSizes.x + sensitivity;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (scrolls.y < 0) { scrolls.y = 0; }
|
|
237
|
+
if (scrolls.x < 0) { scrolls.x = 0; }
|
|
238
|
+
|
|
239
|
+
if (scrolls.y < this.winScrolls.y || scrolls.y > this.winScrolls.y ||
|
|
240
|
+
scrolls.x < this.winScrolls.x || scrolls.x > this.winScrolls.x) {
|
|
241
|
+
|
|
242
|
+
$(window).scrollTo(this.winScrolls = scrolls);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// checking the snaps
|
|
247
|
+
if (this.snapX) { x = x - x % this.snapX; }
|
|
248
|
+
if (this.snapY) { y = y - y % this.snapY; }
|
|
249
|
+
|
|
250
|
+
// checking the constraints
|
|
251
|
+
if (!this.axisY) { this.style.left = (x + this.rxDiff) + 'px'; }
|
|
252
|
+
if (!this.axisX) { this.style.top = (y + this.ryDiff) + 'px'; }
|
|
253
|
+
|
|
254
|
+
this.fire('drag', this, event);
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
// handles the event stop
|
|
258
|
+
dragStop: function(event) {
|
|
259
|
+
this.element.removeClass(this.options.dragClass);
|
|
260
|
+
|
|
261
|
+
// notifying the droppables for the drop
|
|
262
|
+
Droppable.checkDrop(event, this);
|
|
263
|
+
|
|
264
|
+
if (this.options.revert) {
|
|
265
|
+
this.revert();
|
|
266
|
+
} else {
|
|
267
|
+
this._drag = false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
Draggable.current = null;
|
|
271
|
+
|
|
272
|
+
this.fire('stop', this, event);
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
// swaps the clone element to the actual element back
|
|
276
|
+
swapBack: function() {
|
|
277
|
+
if (this.clone) {
|
|
278
|
+
this.clone.replace(
|
|
279
|
+
this.element.setStyle({
|
|
280
|
+
width: this.clone.getStyle('width'),
|
|
281
|
+
height: this.clone.getStyle('height'),
|
|
282
|
+
position: this.clone.getStyle('position'),
|
|
283
|
+
zIndex: this.clone.getStyle('zIndex') || ''
|
|
284
|
+
})
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
this._drag = false;
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
// calculates the constraints
|
|
291
|
+
calcConstraints: function() {
|
|
292
|
+
var axis = this.options.axis;
|
|
293
|
+
this.axisX = R(['x', 'horizontal']).include(axis);
|
|
294
|
+
this.axisY = R(['y', 'vertical']).include(axis);
|
|
295
|
+
|
|
296
|
+
this.ranged = false;
|
|
297
|
+
var range = this.options.range;
|
|
298
|
+
if (range) {
|
|
299
|
+
this.ranged = true;
|
|
300
|
+
|
|
301
|
+
// if the range is defined by another element
|
|
302
|
+
var element = $(range);
|
|
303
|
+
if (element instanceof Element) {
|
|
304
|
+
var dims = element.dimensions();
|
|
305
|
+
|
|
306
|
+
range = {
|
|
307
|
+
x: [dims.left, dims.left + dims.width],
|
|
308
|
+
y: [dims.top, dims.top + dims.height]
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (isHash(range)) {
|
|
313
|
+
var size = this.element.size();
|
|
314
|
+
|
|
315
|
+
if (range.x) {
|
|
316
|
+
this.minX = range.x[0];
|
|
317
|
+
this.maxX = range.x[1] - size.x;
|
|
318
|
+
}
|
|
319
|
+
if (range.y) {
|
|
320
|
+
this.minY = range.y[0];
|
|
321
|
+
this.maxY = range.y[1] - size.y;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Droppable unit
|
|
332
|
+
*
|
|
333
|
+
* Copyright (C) 2009-2010 Nikolay Nemshilov
|
|
334
|
+
*/
|
|
335
|
+
var Droppable = new Class(Observer, {
|
|
336
|
+
extend: {
|
|
337
|
+
EVENTS: $w('drop hover leave'),
|
|
338
|
+
|
|
339
|
+
Options: {
|
|
340
|
+
accept: '*',
|
|
341
|
+
containment: null, // the list of elements (or ids) that should to be accepted
|
|
342
|
+
|
|
343
|
+
overlap: null, // 'x', 'y', 'horizontal', 'vertical', 'both' makes it respond only if the draggable overlaps the droppable
|
|
344
|
+
overlapSize: 0.5, // the overlapping level 0 for nothing 1 for the whole thing
|
|
345
|
+
|
|
346
|
+
allowClass: 'droppable-allow',
|
|
347
|
+
denyClass: 'droppable-deny',
|
|
348
|
+
|
|
349
|
+
relName: 'droppable' // automatically discovered feature key
|
|
350
|
+
},
|
|
351
|
+
|
|
352
|
+
// See the Draggable rescan method, case we're kinda hijacking it in here
|
|
353
|
+
rescan: Draggable.rescan,
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Checks for hoverting draggable
|
|
357
|
+
*
|
|
358
|
+
* @param Event mouse event
|
|
359
|
+
* @param Draggable draggable
|
|
360
|
+
*/
|
|
361
|
+
checkHover: function(event, draggable) {
|
|
362
|
+
for (var i=0, length = this.active.length; i < length; i++) {
|
|
363
|
+
this.active[i].checkHover(event, draggable);
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Checks for a drop
|
|
369
|
+
*
|
|
370
|
+
* @param Event mouse event
|
|
371
|
+
* @param Draggable draggable
|
|
372
|
+
*/
|
|
373
|
+
checkDrop: function(event, draggable) {
|
|
374
|
+
for (var i=0, length = this.active.length; i < length; i++) {
|
|
375
|
+
this.active[i].checkDrop(event, draggable);
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
|
|
379
|
+
active: []
|
|
380
|
+
},
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Basic cosntructor
|
|
384
|
+
*
|
|
385
|
+
* @param mixed the draggable element reference
|
|
386
|
+
* @param Object options
|
|
387
|
+
*/
|
|
388
|
+
initialize: function(element, options) {
|
|
389
|
+
this.element = $(element);
|
|
390
|
+
this.$super(options);
|
|
391
|
+
|
|
392
|
+
Droppable.active.push(this.element._droppable = this);
|
|
393
|
+
},
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Detaches the attached events
|
|
397
|
+
*
|
|
398
|
+
* @return self
|
|
399
|
+
*/
|
|
400
|
+
destroy: function() {
|
|
401
|
+
Droppable.active = Droppable.active.without(this);
|
|
402
|
+
delete(this.element.droppable);
|
|
403
|
+
return this;
|
|
404
|
+
},
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* checks the event for hovering
|
|
408
|
+
*
|
|
409
|
+
* @param Event mouse event
|
|
410
|
+
* @param Draggable the draggable object
|
|
411
|
+
*/
|
|
412
|
+
checkHover: function(event, draggable) {
|
|
413
|
+
if (this.hoveredBy(event, draggable)) {
|
|
414
|
+
if (!this._hovered) {
|
|
415
|
+
this._hovered = true;
|
|
416
|
+
this.element.addClass(this.options[this.allows(draggable) ? 'allowClass' : 'denyClass']);
|
|
417
|
+
this.fire('hover', draggable, this, event);
|
|
418
|
+
}
|
|
419
|
+
} else if (this._hovered) {
|
|
420
|
+
this._hovered = false;
|
|
421
|
+
this.reset().fire('leave', draggable, this, event);
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Checks if it should process the drop from draggable
|
|
427
|
+
*
|
|
428
|
+
* @param Event mouse event
|
|
429
|
+
* @param Draggable draggable
|
|
430
|
+
*/
|
|
431
|
+
checkDrop: function(event, draggable) {
|
|
432
|
+
this.reset();
|
|
433
|
+
if (this.hoveredBy(event, draggable) && this.allows(draggable)) {
|
|
434
|
+
draggable.fire('drop', this, draggable, event);
|
|
435
|
+
this.fire('drop', draggable, this, event);
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* resets the element state
|
|
441
|
+
*
|
|
442
|
+
* @return self
|
|
443
|
+
*/
|
|
444
|
+
reset: function() {
|
|
445
|
+
this.element.removeClass(this.options.allowClass).removeClass(this.options.denyClass);
|
|
446
|
+
return this;
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
// protected
|
|
450
|
+
|
|
451
|
+
// checks if the element is hovered by the event
|
|
452
|
+
hoveredBy: function(event, draggable) {
|
|
453
|
+
var dims = this.element.dimensions(),
|
|
454
|
+
t_top = dims.top,
|
|
455
|
+
t_left = dims.left,
|
|
456
|
+
t_right = dims.left + dims.width,
|
|
457
|
+
t_bottom = dims.top + dims.height,
|
|
458
|
+
event_x = event.pageX,
|
|
459
|
+
event_y = event.pageY;
|
|
460
|
+
|
|
461
|
+
// checking the overlapping
|
|
462
|
+
if (this.options.overlap) {
|
|
463
|
+
var drag_dims = draggable.element.dimensions(),
|
|
464
|
+
level = this.options.overlapSize,
|
|
465
|
+
top = drag_dims.top,
|
|
466
|
+
left = drag_dims.left,
|
|
467
|
+
right = drag_dims.left + drag_dims.width,
|
|
468
|
+
bottom = drag_dims.top + drag_dims.height;
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
switch (this.options.overlap) {
|
|
472
|
+
// horizontal overlapping only check
|
|
473
|
+
case 'x':
|
|
474
|
+
case 'horizontal':
|
|
475
|
+
return (
|
|
476
|
+
(top > t_top && top < t_bottom) ||
|
|
477
|
+
(bottom > t_top && bottom < t_bottom)
|
|
478
|
+
) && (
|
|
479
|
+
(left > t_left && left < (t_right - dims.width * level)) ||
|
|
480
|
+
(right < t_right && right > (t_left + dims.width * level))
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
// vertical overlapping only check
|
|
484
|
+
case 'y':
|
|
485
|
+
case 'vertical':
|
|
486
|
+
return (
|
|
487
|
+
(left > t_left && left < t_right) ||
|
|
488
|
+
(right > t_left && right < t_right)
|
|
489
|
+
) && (
|
|
490
|
+
(top > t_top && top < (t_bottom - dims.height * level)) ||
|
|
491
|
+
(bottom < t_bottom && bottom > (t_top + dims.height * level))
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
// both overlaps check
|
|
495
|
+
default:
|
|
496
|
+
return (
|
|
497
|
+
(left > t_left && left < (t_right - dims.width * level)) ||
|
|
498
|
+
(right < t_right && right > (t_left + dims.width * level))
|
|
499
|
+
) && (
|
|
500
|
+
(top > t_top && top < (t_bottom - dims.height * level)) ||
|
|
501
|
+
(bottom < t_bottom && bottom > (t_top + dims.height * level))
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
} else {
|
|
506
|
+
// simple check agains the event position
|
|
507
|
+
return event_x > t_left && event_x < t_right && event_y > t_top && event_y < t_bottom;
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
|
|
511
|
+
// checks if the object accepts the draggable
|
|
512
|
+
allows: function(draggable) {
|
|
513
|
+
if (this.options.containment && !this._scanned) {
|
|
514
|
+
this.options.containment = R(this.options.containment).map($);
|
|
515
|
+
this._scanned = true;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// checking the invitations list
|
|
519
|
+
var welcomed = this.options.containment ? this.options.containment.includes(draggable.element) : true;
|
|
520
|
+
|
|
521
|
+
return welcomed && (this.options.accept == '*' ? true : draggable.element.match(this.options.accept));
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* The document events hooker
|
|
528
|
+
*
|
|
529
|
+
* Copyright (C) 2009-2011 Nikolay Nemshilov
|
|
530
|
+
*/
|
|
531
|
+
$(document).on({
|
|
532
|
+
// parocesses the automatically discovered elements
|
|
533
|
+
ready: function() {
|
|
534
|
+
Draggable.rescan();
|
|
535
|
+
Droppable.rescan();
|
|
536
|
+
},
|
|
537
|
+
|
|
538
|
+
// watch the draggables moving arond
|
|
539
|
+
mousemove: function(event) {
|
|
540
|
+
if (Draggable.current !== null) {
|
|
541
|
+
Draggable.current.dragProcess(event);
|
|
542
|
+
Droppable.checkHover(event, Draggable.current);
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
|
|
546
|
+
// releases the current draggable on mouse up
|
|
547
|
+
mouseup: function(event) {
|
|
548
|
+
if (Draggable.current !== null) {
|
|
549
|
+
Draggable.current.dragStop(event);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Element level hooks for drag'n'drops
|
|
556
|
+
*
|
|
557
|
+
* Copyright (C) 2009-2010 Nikolay Nemshilov
|
|
558
|
+
*/
|
|
559
|
+
Element.include({
|
|
560
|
+
|
|
561
|
+
makeDraggable: function(options) {
|
|
562
|
+
new Draggable(this, options);
|
|
563
|
+
return this;
|
|
564
|
+
},
|
|
565
|
+
|
|
566
|
+
undoDraggable: function() {
|
|
567
|
+
if ('draggable' in this) {
|
|
568
|
+
this.draggable.destroy();
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return this;
|
|
572
|
+
},
|
|
573
|
+
|
|
574
|
+
makeDroppable: function(options) {
|
|
575
|
+
new Droppable(this, options);
|
|
576
|
+
return this;
|
|
577
|
+
},
|
|
578
|
+
|
|
579
|
+
undoDroppable: function() {
|
|
580
|
+
if ('droppable' in this) {
|
|
581
|
+
this.droppable.destroy();
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return this;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
window.Draggable = RightJS.Draggable = Draggable;
|
|
590
|
+
window.Droppable = RightJS.Droppable = Droppable;
|
|
591
|
+
})(window, document, RightJS);
|