rich_cms 2.1.7 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. data/{CHANGELOG → CHANGELOG.rdoc} +24 -0
  2. data/README.textile +49 -33
  3. data/Rakefile +92 -10
  4. data/VERSION +1 -1
  5. data/app/controllers/rich/cms_controller.rb +10 -39
  6. data/app/controllers/rich/cms_sessions_controller.rb +31 -0
  7. data/app/views/rich/cms/dock/_menu.html.erb +10 -8
  8. data/app/views/rich/cms/dock/_panel.html.erb +1 -1
  9. data/app/views/rich/cms/dock/panel/edit/_rails2.html.erb +5 -3
  10. data/app/views/rich/cms/dock/panel/edit/_rails3.html.erb +4 -2
  11. data/app/views/rich/cms/dock/panel/login/_rails2.html.erb +18 -12
  12. data/app/views/rich/cms/dock/panel/login/_rails3.html.erb +18 -12
  13. data/app/views/rich_cms.html.erb +1 -1
  14. data/assets/jzip/jquery/cleditor.js +1132 -1132
  15. data/assets/jzip/jquery/extensions/browser_detect.js +1 -2
  16. data/assets/jzip/native/extensions.js +41 -0
  17. data/assets/jzip/rich/cms/editor.js +41 -7
  18. data/assets/jzip/rich_cms.jz +2 -1
  19. data/assets/sass/rich_cms/_panel.sass +11 -1
  20. data/config/routes.rb +12 -11
  21. data/lib/generators/rich/cms_admin/cms_admin_generator.rb +82 -0
  22. data/lib/generators/rich/{authlogic_user/templates → cms_admin/templates/authlogic}/migration.rb +0 -0
  23. data/lib/generators/rich/{authlogic_user/templates → cms_admin/templates/authlogic}/model.rb +0 -0
  24. data/lib/generators/rich/{authlogic_user/templates → cms_admin/templates/authlogic}/session.rb +0 -0
  25. data/lib/rich/cms/actionpack/action_controller/base.rb +3 -44
  26. data/lib/rich/cms/actionpack/action_view/base.rb +32 -10
  27. data/lib/rich/cms/actionpack.rb +1 -2
  28. data/lib/rich/cms/auth.rb +110 -0
  29. data/lib/rich/cms/content/group.rb +1 -2
  30. data/lib/rich/cms/content/item.rb +2 -3
  31. data/lib/rich/cms/core/string/html_safe.rb +1 -2
  32. data/lib/rich/cms/core/string.rb +1 -2
  33. data/lib/rich/cms/engine.rb +23 -51
  34. data/lib/rich/cms/rails/engine.rb +1 -2
  35. data/lib/rich/cms/version.rb +11 -0
  36. data/lib/rich_cms.rb +2 -2
  37. data/rails_generators/rich_cms_admin/lib/devise/route_devise.rb +32 -0
  38. data/rails_generators/rich_cms_admin/rich_cms_admin_generator.rb +113 -0
  39. data/rails_generators/{rich_authlogic_user/templates → rich_cms_admin/templates/authlogic}/migration.rb +0 -0
  40. data/rails_generators/{rich_authlogic_user/templates → rich_cms_admin/templates/authlogic}/model.rb +0 -0
  41. data/rails_generators/{rich_authlogic_user/templates → rich_cms_admin/templates/authlogic}/session.rb +0 -0
  42. data/rails_generators/{rich_authlogic_user → rich_cms_admin}/templates/config.rb +0 -0
  43. data/rails_generators/rich_cms_admin/templates/devise/README +23 -0
  44. data/rails_generators/rich_cms_admin/templates/devise/devise.rb +105 -0
  45. data/rails_generators/rich_cms_admin/templates/devise/en.yml +35 -0
  46. data/rails_generators/rich_cms_admin/templates/devise/migration.rb +23 -0
  47. data/rails_generators/rich_cms_admin/templates/devise/model.rb +9 -0
  48. data/rails_generators/rich_cms_content/rich_cms_content_generator.rb +18 -12
  49. data/rich_cms.gemspec +295 -105
  50. data/test/integrator.rb +89 -0
  51. data/test/rails-2/dummy/.bundle/config +2 -0
  52. data/test/rails-2/dummy/Gemfile +15 -0
  53. data/test/rails-2/dummy/Gemfile.lock +97 -0
  54. data/test/rails-2/dummy/Rakefile +10 -0
  55. data/test/rails-2/dummy/app/controllers/application_controller.rb +10 -0
  56. data/test/rails-2/dummy/app/helpers/application_helper.rb +3 -0
  57. data/test/rails-2/dummy/config/boot.rb +124 -0
  58. data/test/rails-2/dummy/config/database.yml +23 -0
  59. data/test/rails-2/dummy/config/environment.rb +41 -0
  60. data/test/rails-2/dummy/config/environments/development.rb +17 -0
  61. data/test/rails-2/dummy/config/environments/production.rb +28 -0
  62. data/test/rails-2/dummy/config/environments/test.rb +28 -0
  63. data/test/rails-2/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/test/rails-2/dummy/config/initializers/cookie_verification_secret.rb +7 -0
  65. data/test/rails-2/dummy/config/initializers/devise.rb +105 -0
  66. data/test/rails-2/dummy/config/initializers/enrichments.rb +5 -0
  67. data/test/rails-2/dummy/config/initializers/inflections.rb +10 -0
  68. data/test/rails-2/dummy/config/initializers/mime_types.rb +5 -0
  69. data/test/rails-2/dummy/config/initializers/new_rails_defaults.rb +21 -0
  70. data/test/rails-2/dummy/config/initializers/session_store.rb +15 -0
  71. data/test/rails-2/dummy/config/locales/en.yml +5 -0
  72. data/test/rails-2/dummy/config/preinitializer.rb +20 -0
  73. data/test/rails-2/dummy/config/routes.rb +44 -0
  74. data/test/rails-2/dummy/db/schema.rb +49 -0
  75. data/test/rails-2/dummy/db/seeds.rb +10 -0
  76. data/test/rails-2/dummy/public/404.html +30 -0
  77. data/test/rails-2/dummy/public/422.html +30 -0
  78. data/test/rails-2/dummy/public/500.html +30 -0
  79. data/test/rails-2/dummy/public/favicon.ico +0 -0
  80. data/test/rails-2/dummy/public/images/rails.png +0 -0
  81. data/test/rails-2/dummy/public/images/rich/cms/cleditor/buttons.gif +0 -0
  82. data/test/rails-2/dummy/public/images/rich/cms/cleditor/toolbar.gif +0 -0
  83. data/test/rails-2/dummy/public/javascripts/jquery/core.js +158 -0
  84. data/test/rails-2/dummy/public/javascripts/jquery/ui/rich_cms/core.js +1207 -0
  85. data/test/rails-2/dummy/public/javascripts/jquery/ui/rich_cms/draggable.js +798 -0
  86. data/test/rails-2/dummy/public/javascripts/jquery/ui/rich_cms/mouse.js +950 -0
  87. data/test/rails-2/dummy/public/javascripts/jquery/ui/rich_cms/widget.js +1188 -0
  88. data/test/rails-2/dummy/public/javascripts/rich_cms.js +1746 -0
  89. data/test/rails-2/dummy/public/robots.txt +5 -0
  90. data/test/rails-2/dummy/script/about +4 -0
  91. data/test/rails-2/dummy/script/console +3 -0
  92. data/test/rails-2/dummy/script/dbconsole +3 -0
  93. data/test/rails-2/dummy/script/destroy +3 -0
  94. data/test/rails-2/dummy/script/generate +3 -0
  95. data/test/rails-2/dummy/script/performance/benchmarker +3 -0
  96. data/test/rails-2/dummy/script/performance/profiler +3 -0
  97. data/test/rails-2/dummy/script/plugin +3 -0
  98. data/test/rails-2/dummy/script/runner +3 -0
  99. data/test/rails-2/dummy/script/server +3 -0
  100. data/test/rails-2/dummy/test/fixtures/authlogic_users.yml +6 -0
  101. data/test/rails-2/dummy/test/fixtures/devise_users.yml +5 -0
  102. data/test/rails-2/pending.rb +88 -0
  103. data/test/rails-2/test_helper.rb +13 -0
  104. data/test/rails-3/dummy/.bundle/config +2 -0
  105. data/test/rails-3/dummy/Gemfile +15 -0
  106. data/test/rails-3/dummy/Gemfile.lock +139 -0
  107. data/test/rails-3/dummy/Rakefile +7 -0
  108. data/test/rails-3/dummy/app/controllers/application_controller.rb +3 -0
  109. data/test/rails-3/dummy/app/helpers/application_helper.rb +2 -0
  110. data/test/rails-3/dummy/config/application.rb +42 -0
  111. data/test/rails-3/dummy/config/boot.rb +13 -0
  112. data/test/rails-3/dummy/config/database.yml +23 -0
  113. data/test/rails-3/dummy/config/environment.rb +5 -0
  114. data/test/rails-3/dummy/config/environments/development.rb +26 -0
  115. data/test/rails-3/dummy/config/environments/production.rb +49 -0
  116. data/test/rails-3/dummy/config/environments/test.rb +35 -0
  117. data/test/rails-3/dummy/config/initializers/backtrace_silencers.rb +7 -0
  118. data/test/rails-3/dummy/config/initializers/devise.rb +142 -0
  119. data/test/rails-3/dummy/config/initializers/enrichments.rb +5 -0
  120. data/test/rails-3/dummy/config/initializers/inflections.rb +10 -0
  121. data/test/rails-3/dummy/config/initializers/mime_types.rb +5 -0
  122. data/test/rails-3/dummy/config/initializers/secret_token.rb +7 -0
  123. data/test/rails-3/dummy/config/initializers/session_store.rb +8 -0
  124. data/test/rails-3/dummy/config/locales/en.yml +5 -0
  125. data/test/rails-3/dummy/config/routes.rb +59 -0
  126. data/test/rails-3/dummy/config.ru +4 -0
  127. data/test/rails-3/dummy/db/schema.rb +49 -0
  128. data/test/rails-3/dummy/db/seeds.rb +10 -0
  129. data/test/rails-3/dummy/public/404.html +26 -0
  130. data/test/rails-3/dummy/public/422.html +26 -0
  131. data/test/rails-3/dummy/public/500.html +26 -0
  132. data/test/rails-3/dummy/public/favicon.ico +0 -0
  133. data/test/rails-3/dummy/public/images/rich/cms/cleditor/buttons.gif +0 -0
  134. data/test/rails-3/dummy/public/images/rich/cms/cleditor/toolbar.gif +0 -0
  135. data/test/rails-3/dummy/public/javascripts/jquery/core.js +158 -0
  136. data/test/rails-3/dummy/public/javascripts/jquery/ui/rich_cms/core.js +1207 -0
  137. data/test/rails-3/dummy/public/javascripts/jquery/ui/rich_cms/draggable.js +798 -0
  138. data/test/rails-3/dummy/public/javascripts/jquery/ui/rich_cms/mouse.js +950 -0
  139. data/test/rails-3/dummy/public/javascripts/jquery/ui/rich_cms/widget.js +1188 -0
  140. data/test/rails-3/dummy/public/javascripts/rich_cms.js +1746 -0
  141. data/test/rails-3/dummy/script/rails +6 -0
  142. data/test/rails-3/dummy/test/fixtures/authlogic_users.yml +6 -0
  143. data/test/rails-3/dummy/test/fixtures/devise_users.yml +5 -0
  144. data/test/rails-3/test_helper.rb +17 -0
  145. data/test/shared/dummy/db/schema.rb +49 -0
  146. data/test/shared/dummy/db/seeds.rb +10 -0
  147. data/test/shared/dummy/fixtures/authlogic_users.yml +6 -0
  148. data/test/shared/dummy/models/authlogic_user.rb +8 -0
  149. data/test/shared/dummy/models/authlogic_user_session.rb +10 -0
  150. data/test/shared/dummy/models/cms_content.rb +2 -0
  151. data/test/shared/dummy/models/devise_user.rb +3 -0
  152. data/test/shared/dummy/stylesheets/app.css +100 -0
  153. data/test/shared/dummy/stylesheets/rich_cms.css +159 -0
  154. data/test/shared/dummy/views/application/index.html.erb +13 -0
  155. data/test/shared/dummy/views/layouts/application.html.erb +12 -0
  156. data/test/shared/support/action_controller/integration.rb +55 -0
  157. data/test/shared/support/action_controller/test_case.rb +28 -0
  158. data/test/shared/support/capybara/setup.rb +14 -0
  159. data/test/shared/support/test_helper.rb +1 -0
  160. data/test/shared/tests/actionpack/action_controller/base_test.rb +14 -0
  161. data/test/shared/tests/actionpack/action_view/base_test.rb +19 -0
  162. data/test/shared/tests/activesupport/active_support/dependencies_test.rb +15 -0
  163. data/test/shared/tests/app/integration/authenticated/authlogic.rb +88 -0
  164. data/test/shared/tests/app/integration/authenticated/devise_test.rb +89 -0
  165. data/test/shared/tests/app/integration/non_authenticated.rb +63 -0
  166. data/test/shared/tests/app/routing_test.rb +31 -0
  167. data/test/shared/tests/auth_test.rb +11 -0
  168. data/test/shared/tests/content/group.rb +10 -0
  169. data/test/shared/tests/content/item.rb +10 -0
  170. data/test/shared/tests/core/string/html_safe.rb +15 -0
  171. data/test/shared/tests/dummy_app.rb +228 -0
  172. data/test/shared/tests/engine_test.rb +19 -0
  173. data/test/shared/tests/rails/engine_test.rb +13 -0
  174. data/test/shared/tests/readme_test.rb +13 -0
  175. metadata +231 -63
  176. data/.gitignore +0 -2
  177. data/lib/generators/rich/authlogic_user/authlogic_user_generator.rb +0 -64
  178. data/rails_generators/rich_authlogic_user/rich_authlogic_user_generator.rb +0 -64
  179. data/test/test_helper.rb +0 -6
@@ -0,0 +1,798 @@
1
+
2
+ /*
3
+ * jQuery UI Draggable 1.8.4
4
+ *
5
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6
+ * Dual licensed under the MIT or GPL Version 2 licenses.
7
+ * http://jquery.org/license
8
+ *
9
+ * http://docs.jquery.com/UI/Draggables
10
+ *
11
+ * Depends:
12
+ * jquery.ui.core.js
13
+ * jquery.ui.mouse.js
14
+ * jquery.ui.widget.js
15
+ */
16
+ (function( $, undefined ) {
17
+
18
+ $.widget("ui.draggable", $.ui.mouse, {
19
+ widgetEventPrefix: "drag",
20
+ options: {
21
+ addClasses: true,
22
+ appendTo: "parent",
23
+ axis: false,
24
+ connectToSortable: false,
25
+ containment: false,
26
+ cursor: "auto",
27
+ cursorAt: false,
28
+ grid: false,
29
+ handle: false,
30
+ helper: "original",
31
+ iframeFix: false,
32
+ opacity: false,
33
+ refreshPositions: false,
34
+ revert: false,
35
+ revertDuration: 500,
36
+ scope: "default",
37
+ scroll: true,
38
+ scrollSensitivity: 20,
39
+ scrollSpeed: 20,
40
+ snap: false,
41
+ snapMode: "both",
42
+ snapTolerance: 20,
43
+ stack: false,
44
+ zIndex: false
45
+ },
46
+ _create: function() {
47
+
48
+ if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
49
+ this.element[0].style.position = 'relative';
50
+
51
+ (this.options.addClasses && this.element.addClass("ui-draggable"));
52
+ (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
53
+
54
+ this._mouseInit();
55
+
56
+ },
57
+
58
+ destroy: function() {
59
+ if(!this.element.data('draggable')) return;
60
+ this.element
61
+ .removeData("draggable")
62
+ .unbind(".draggable")
63
+ .removeClass("ui-draggable"
64
+ + " ui-draggable-dragging"
65
+ + " ui-draggable-disabled");
66
+ this._mouseDestroy();
67
+
68
+ return this;
69
+ },
70
+
71
+ _mouseCapture: function(event) {
72
+
73
+ var o = this.options;
74
+
75
+ // among others, prevent a drag on a resizable-handle
76
+ if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
77
+ return false;
78
+
79
+ //Quit if we're not on a valid handle
80
+ this.handle = this._getHandle(event);
81
+ if (!this.handle)
82
+ return false;
83
+
84
+ return true;
85
+
86
+ },
87
+
88
+ _mouseStart: function(event) {
89
+
90
+ var o = this.options;
91
+
92
+ //Create and append the visible helper
93
+ this.helper = this._createHelper(event);
94
+
95
+ //Cache the helper size
96
+ this._cacheHelperProportions();
97
+
98
+ //If ddmanager is used for droppables, set the global draggable
99
+ if($.ui.ddmanager)
100
+ $.ui.ddmanager.current = this;
101
+
102
+ /*
103
+ * - Position generation -
104
+ * This block generates everything position related - it's the core of draggables.
105
+ */
106
+
107
+ //Cache the margins of the original element
108
+ this._cacheMargins();
109
+
110
+ //Store the helper's css position
111
+ this.cssPosition = this.helper.css("position");
112
+ this.scrollParent = this.helper.scrollParent();
113
+
114
+ //The element's absolute position on the page minus margins
115
+ this.offset = this.positionAbs = this.element.offset();
116
+ this.offset = {
117
+ top: this.offset.top - this.margins.top,
118
+ left: this.offset.left - this.margins.left
119
+ };
120
+
121
+ $.extend(this.offset, {
122
+ click: { //Where the click happened, relative to the element
123
+ left: event.pageX - this.offset.left,
124
+ top: event.pageY - this.offset.top
125
+ },
126
+ parent: this._getParentOffset(),
127
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
128
+ });
129
+
130
+ //Generate the original position
131
+ this.originalPosition = this.position = this._generatePosition(event);
132
+ this.originalPageX = event.pageX;
133
+ this.originalPageY = event.pageY;
134
+
135
+ //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
136
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
137
+
138
+ //Set a containment if given in the options
139
+ if(o.containment)
140
+ this._setContainment();
141
+
142
+ //Trigger event + callbacks
143
+ if(this._trigger("start", event) === false) {
144
+ this._clear();
145
+ return false;
146
+ }
147
+
148
+ //Recache the helper size
149
+ this._cacheHelperProportions();
150
+
151
+ //Prepare the droppable offsets
152
+ if ($.ui.ddmanager && !o.dropBehaviour)
153
+ $.ui.ddmanager.prepareOffsets(this, event);
154
+
155
+ this.helper.addClass("ui-draggable-dragging");
156
+ this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
157
+ return true;
158
+ },
159
+
160
+ _mouseDrag: function(event, noPropagation) {
161
+
162
+ //Compute the helpers position
163
+ this.position = this._generatePosition(event);
164
+ this.positionAbs = this._convertPositionTo("absolute");
165
+
166
+ //Call plugins and callbacks and use the resulting position if something is returned
167
+ if (!noPropagation) {
168
+ var ui = this._uiHash();
169
+ if(this._trigger('drag', event, ui) === false) {
170
+ this._mouseUp({});
171
+ return false;
172
+ }
173
+ this.position = ui.position;
174
+ }
175
+
176
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
177
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
178
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
179
+
180
+ return false;
181
+ },
182
+
183
+ _mouseStop: function(event) {
184
+
185
+ //If we are using droppables, inform the manager about the drop
186
+ var dropped = false;
187
+ if ($.ui.ddmanager && !this.options.dropBehaviour)
188
+ dropped = $.ui.ddmanager.drop(this, event);
189
+
190
+ //if a drop comes from outside (a sortable)
191
+ if(this.dropped) {
192
+ dropped = this.dropped;
193
+ this.dropped = false;
194
+ }
195
+
196
+ //if the original element is removed, don't bother to continue
197
+ if(!this.element[0] || !this.element[0].parentNode)
198
+ return false;
199
+
200
+ if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
201
+ var self = this;
202
+ $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
203
+ if(self._trigger("stop", event) !== false) {
204
+ self._clear();
205
+ }
206
+ });
207
+ } else {
208
+ if(this._trigger("stop", event) !== false) {
209
+ this._clear();
210
+ }
211
+ }
212
+
213
+ return false;
214
+ },
215
+
216
+ cancel: function() {
217
+
218
+ if(this.helper.is(".ui-draggable-dragging")) {
219
+ this._mouseUp({});
220
+ } else {
221
+ this._clear();
222
+ }
223
+
224
+ return this;
225
+
226
+ },
227
+
228
+ _getHandle: function(event) {
229
+
230
+ var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
231
+ $(this.options.handle, this.element)
232
+ .find("*")
233
+ .andSelf()
234
+ .each(function() {
235
+ if(this == event.target) handle = true;
236
+ });
237
+
238
+ return handle;
239
+
240
+ },
241
+
242
+ _createHelper: function(event) {
243
+
244
+ var o = this.options;
245
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
246
+
247
+ if(!helper.parents('body').length)
248
+ helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
249
+
250
+ if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
251
+ helper.css("position", "absolute");
252
+
253
+ return helper;
254
+
255
+ },
256
+
257
+ _adjustOffsetFromHelper: function(obj) {
258
+ if (typeof obj == 'string') {
259
+ obj = obj.split(' ');
260
+ }
261
+ if ($.isArray(obj)) {
262
+ obj = {left: +obj[0], top: +obj[1] || 0};
263
+ }
264
+ if ('left' in obj) {
265
+ this.offset.click.left = obj.left + this.margins.left;
266
+ }
267
+ if ('right' in obj) {
268
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
269
+ }
270
+ if ('top' in obj) {
271
+ this.offset.click.top = obj.top + this.margins.top;
272
+ }
273
+ if ('bottom' in obj) {
274
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
275
+ }
276
+ },
277
+
278
+ _getParentOffset: function() {
279
+
280
+ //Get the offsetParent and cache its position
281
+ this.offsetParent = this.helper.offsetParent();
282
+ var po = this.offsetParent.offset();
283
+
284
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
285
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
286
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
287
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
288
+ if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
289
+ po.left += this.scrollParent.scrollLeft();
290
+ po.top += this.scrollParent.scrollTop();
291
+ }
292
+
293
+ if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
294
+ || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
295
+ po = { top: 0, left: 0 };
296
+
297
+ return {
298
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
299
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
300
+ };
301
+
302
+ },
303
+
304
+ _getRelativeOffset: function() {
305
+
306
+ if(this.cssPosition == "relative") {
307
+ var p = this.element.position();
308
+ return {
309
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
310
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
311
+ };
312
+ } else {
313
+ return { top: 0, left: 0 };
314
+ }
315
+
316
+ },
317
+
318
+ _cacheMargins: function() {
319
+ this.margins = {
320
+ left: (parseInt(this.element.css("marginLeft"),10) || 0),
321
+ top: (parseInt(this.element.css("marginTop"),10) || 0)
322
+ };
323
+ },
324
+
325
+ _cacheHelperProportions: function() {
326
+ this.helperProportions = {
327
+ width: this.helper.outerWidth(),
328
+ height: this.helper.outerHeight()
329
+ };
330
+ },
331
+
332
+ _setContainment: function() {
333
+
334
+ var o = this.options;
335
+ if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
336
+ if(o.containment == 'document' || o.containment == 'window') this.containment = [
337
+ 0 - this.offset.relative.left - this.offset.parent.left,
338
+ 0 - this.offset.relative.top - this.offset.parent.top,
339
+ $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
340
+ ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
341
+ ];
342
+
343
+ if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
344
+ var ce = $(o.containment)[0]; if(!ce) return;
345
+ var co = $(o.containment).offset();
346
+ var over = ($(ce).css("overflow") != 'hidden');
347
+
348
+ this.containment = [
349
+ co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
350
+ co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
351
+ co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
352
+ co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
353
+ ];
354
+ } else if(o.containment.constructor == Array) {
355
+ this.containment = o.containment;
356
+ }
357
+
358
+ },
359
+
360
+ _convertPositionTo: function(d, pos) {
361
+
362
+ if(!pos) pos = this.position;
363
+ var mod = d == "absolute" ? 1 : -1;
364
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
365
+
366
+ return {
367
+ top: (
368
+ pos.top // The absolute mouse position
369
+ + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
370
+ + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
371
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
372
+ ),
373
+ left: (
374
+ pos.left // The absolute mouse position
375
+ + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
376
+ + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
377
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
378
+ )
379
+ };
380
+
381
+ },
382
+
383
+ _generatePosition: function(event) {
384
+
385
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
386
+ var pageX = event.pageX;
387
+ var pageY = event.pageY;
388
+
389
+ /*
390
+ * - Position constraining -
391
+ * Constrain the position to a mix of grid, containment.
392
+ */
393
+
394
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
395
+
396
+ if(this.containment) {
397
+ if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
398
+ if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
399
+ if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
400
+ if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
401
+ }
402
+
403
+ if(o.grid) {
404
+ var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
405
+ pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
406
+
407
+ var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
408
+ pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
409
+ }
410
+
411
+ }
412
+
413
+ return {
414
+ top: (
415
+ pageY // The absolute mouse position
416
+ - this.offset.click.top // Click offset (relative to the element)
417
+ - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
418
+ - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
419
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
420
+ ),
421
+ left: (
422
+ pageX // The absolute mouse position
423
+ - this.offset.click.left // Click offset (relative to the element)
424
+ - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
425
+ - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
426
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
427
+ )
428
+ };
429
+
430
+ },
431
+
432
+ _clear: function() {
433
+ this.helper.removeClass("ui-draggable-dragging");
434
+ if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
435
+ //if($.ui.ddmanager) $.ui.ddmanager.current = null;
436
+ this.helper = null;
437
+ this.cancelHelperRemoval = false;
438
+ },
439
+
440
+ // From now on bulk stuff - mainly helpers
441
+
442
+ _trigger: function(type, event, ui) {
443
+ ui = ui || this._uiHash();
444
+ $.ui.plugin.call(this, type, [event, ui]);
445
+ if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
446
+ return $.Widget.prototype._trigger.call(this, type, event, ui);
447
+ },
448
+
449
+ plugins: {},
450
+
451
+ _uiHash: function(event) {
452
+ return {
453
+ helper: this.helper,
454
+ position: this.position,
455
+ originalPosition: this.originalPosition,
456
+ offset: this.positionAbs
457
+ };
458
+ }
459
+
460
+ });
461
+
462
+ $.extend($.ui.draggable, {
463
+ version: "1.8.4"
464
+ });
465
+
466
+ $.ui.plugin.add("draggable", "connectToSortable", {
467
+ start: function(event, ui) {
468
+
469
+ var inst = $(this).data("draggable"), o = inst.options,
470
+ uiSortable = $.extend({}, ui, { item: inst.element });
471
+ inst.sortables = [];
472
+ $(o.connectToSortable).each(function() {
473
+ var sortable = $.data(this, 'sortable');
474
+ if (sortable && !sortable.options.disabled) {
475
+ inst.sortables.push({
476
+ instance: sortable,
477
+ shouldRevert: sortable.options.revert
478
+ });
479
+ sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
480
+ sortable._trigger("activate", event, uiSortable);
481
+ }
482
+ });
483
+
484
+ },
485
+ stop: function(event, ui) {
486
+
487
+ //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
488
+ var inst = $(this).data("draggable"),
489
+ uiSortable = $.extend({}, ui, { item: inst.element });
490
+
491
+ $.each(inst.sortables, function() {
492
+ if(this.instance.isOver) {
493
+
494
+ this.instance.isOver = 0;
495
+
496
+ inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
497
+ this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
498
+
499
+ //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
500
+ if(this.shouldRevert) this.instance.options.revert = true;
501
+
502
+ //Trigger the stop of the sortable
503
+ this.instance._mouseStop(event);
504
+
505
+ this.instance.options.helper = this.instance.options._helper;
506
+
507
+ //If the helper has been the original item, restore properties in the sortable
508
+ if(inst.options.helper == 'original')
509
+ this.instance.currentItem.css({ top: 'auto', left: 'auto' });
510
+
511
+ } else {
512
+ this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
513
+ this.instance._trigger("deactivate", event, uiSortable);
514
+ }
515
+
516
+ });
517
+
518
+ },
519
+ drag: function(event, ui) {
520
+
521
+ var inst = $(this).data("draggable"), self = this;
522
+
523
+ var checkPos = function(o) {
524
+ var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
525
+ var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
526
+ var itemHeight = o.height, itemWidth = o.width;
527
+ var itemTop = o.top, itemLeft = o.left;
528
+
529
+ return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
530
+ };
531
+
532
+ $.each(inst.sortables, function(i) {
533
+
534
+ //Copy over some variables to allow calling the sortable's native _intersectsWith
535
+ this.instance.positionAbs = inst.positionAbs;
536
+ this.instance.helperProportions = inst.helperProportions;
537
+ this.instance.offset.click = inst.offset.click;
538
+
539
+ if(this.instance._intersectsWith(this.instance.containerCache)) {
540
+
541
+ //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
542
+ if(!this.instance.isOver) {
543
+
544
+ this.instance.isOver = 1;
545
+ //Now we fake the start of dragging for the sortable instance,
546
+ //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
547
+ //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
548
+ this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
549
+ this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
550
+ this.instance.options.helper = function() { return ui.helper[0]; };
551
+
552
+ event.target = this.instance.currentItem[0];
553
+ this.instance._mouseCapture(event, true);
554
+ this.instance._mouseStart(event, true, true);
555
+
556
+ //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
557
+ this.instance.offset.click.top = inst.offset.click.top;
558
+ this.instance.offset.click.left = inst.offset.click.left;
559
+ this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
560
+ this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
561
+
562
+ inst._trigger("toSortable", event);
563
+ inst.dropped = this.instance.element; //draggable revert needs that
564
+ //hack so receive/update callbacks work (mostly)
565
+ inst.currentItem = inst.element;
566
+ this.instance.fromOutside = inst;
567
+
568
+ }
569
+
570
+ //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
571
+ if(this.instance.currentItem) this.instance._mouseDrag(event);
572
+
573
+ } else {
574
+
575
+ //If it doesn't intersect with the sortable, and it intersected before,
576
+ //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
577
+ if(this.instance.isOver) {
578
+
579
+ this.instance.isOver = 0;
580
+ this.instance.cancelHelperRemoval = true;
581
+
582
+ //Prevent reverting on this forced stop
583
+ this.instance.options.revert = false;
584
+
585
+ // The out event needs to be triggered independently
586
+ this.instance._trigger('out', event, this.instance._uiHash(this.instance));
587
+
588
+ this.instance._mouseStop(event, true);
589
+ this.instance.options.helper = this.instance.options._helper;
590
+
591
+ //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
592
+ this.instance.currentItem.remove();
593
+ if(this.instance.placeholder) this.instance.placeholder.remove();
594
+
595
+ inst._trigger("fromSortable", event);
596
+ inst.dropped = false; //draggable revert needs that
597
+ }
598
+
599
+ };
600
+
601
+ });
602
+
603
+ }
604
+ });
605
+
606
+ $.ui.plugin.add("draggable", "cursor", {
607
+ start: function(event, ui) {
608
+ var t = $('body'), o = $(this).data('draggable').options;
609
+ if (t.css("cursor")) o._cursor = t.css("cursor");
610
+ t.css("cursor", o.cursor);
611
+ },
612
+ stop: function(event, ui) {
613
+ var o = $(this).data('draggable').options;
614
+ if (o._cursor) $('body').css("cursor", o._cursor);
615
+ }
616
+ });
617
+
618
+ $.ui.plugin.add("draggable", "iframeFix", {
619
+ start: function(event, ui) {
620
+ var o = $(this).data('draggable').options;
621
+ $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
622
+ $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
623
+ .css({
624
+ width: this.offsetWidth+"px", height: this.offsetHeight+"px",
625
+ position: "absolute", opacity: "0.001", zIndex: 1000
626
+ })
627
+ .css($(this).offset())
628
+ .appendTo("body");
629
+ });
630
+ },
631
+ stop: function(event, ui) {
632
+ $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
633
+ }
634
+ });
635
+
636
+ $.ui.plugin.add("draggable", "opacity", {
637
+ start: function(event, ui) {
638
+ var t = $(ui.helper), o = $(this).data('draggable').options;
639
+ if(t.css("opacity")) o._opacity = t.css("opacity");
640
+ t.css('opacity', o.opacity);
641
+ },
642
+ stop: function(event, ui) {
643
+ var o = $(this).data('draggable').options;
644
+ if(o._opacity) $(ui.helper).css('opacity', o._opacity);
645
+ }
646
+ });
647
+
648
+ $.ui.plugin.add("draggable", "scroll", {
649
+ start: function(event, ui) {
650
+ var i = $(this).data("draggable");
651
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
652
+ },
653
+ drag: function(event, ui) {
654
+
655
+ var i = $(this).data("draggable"), o = i.options, scrolled = false;
656
+
657
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
658
+
659
+ if(!o.axis || o.axis != 'x') {
660
+ if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
661
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
662
+ else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
663
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
664
+ }
665
+
666
+ if(!o.axis || o.axis != 'y') {
667
+ if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
668
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
669
+ else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
670
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
671
+ }
672
+
673
+ } else {
674
+
675
+ if(!o.axis || o.axis != 'x') {
676
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
677
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
678
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
679
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
680
+ }
681
+
682
+ if(!o.axis || o.axis != 'y') {
683
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
684
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
685
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
686
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
687
+ }
688
+
689
+ }
690
+
691
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
692
+ $.ui.ddmanager.prepareOffsets(i, event);
693
+
694
+ }
695
+ });
696
+
697
+ $.ui.plugin.add("draggable", "snap", {
698
+ start: function(event, ui) {
699
+
700
+ var i = $(this).data("draggable"), o = i.options;
701
+ i.snapElements = [];
702
+
703
+ $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
704
+ var $t = $(this); var $o = $t.offset();
705
+ if(this != i.element[0]) i.snapElements.push({
706
+ item: this,
707
+ width: $t.outerWidth(), height: $t.outerHeight(),
708
+ top: $o.top, left: $o.left
709
+ });
710
+ });
711
+
712
+ },
713
+ drag: function(event, ui) {
714
+
715
+ var inst = $(this).data("draggable"), o = inst.options;
716
+ var d = o.snapTolerance;
717
+
718
+ var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
719
+ y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
720
+
721
+ for (var i = inst.snapElements.length - 1; i >= 0; i--){
722
+
723
+ var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
724
+ t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
725
+
726
+ //Yes, I know, this is insane ;)
727
+ if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
728
+ if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
729
+ inst.snapElements[i].snapping = false;
730
+ continue;
731
+ }
732
+
733
+ if(o.snapMode != 'inner') {
734
+ var ts = Math.abs(t - y2) <= d;
735
+ var bs = Math.abs(b - y1) <= d;
736
+ var ls = Math.abs(l - x2) <= d;
737
+ var rs = Math.abs(r - x1) <= d;
738
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
739
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
740
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
741
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
742
+ }
743
+
744
+ var first = (ts || bs || ls || rs);
745
+
746
+ if(o.snapMode != 'outer') {
747
+ var ts = Math.abs(t - y1) <= d;
748
+ var bs = Math.abs(b - y2) <= d;
749
+ var ls = Math.abs(l - x1) <= d;
750
+ var rs = Math.abs(r - x2) <= d;
751
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
752
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
753
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
754
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
755
+ }
756
+
757
+ if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
758
+ (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
759
+ inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
760
+
761
+ };
762
+
763
+ }
764
+ });
765
+
766
+ $.ui.plugin.add("draggable", "stack", {
767
+ start: function(event, ui) {
768
+
769
+ var o = $(this).data("draggable").options;
770
+
771
+ var group = $.makeArray($(o.stack)).sort(function(a,b) {
772
+ return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
773
+ });
774
+ if (!group.length) { return; }
775
+
776
+ var min = parseInt(group[0].style.zIndex) || 0;
777
+ $(group).each(function(i) {
778
+ this.style.zIndex = min + i;
779
+ });
780
+
781
+ this[0].style.zIndex = min + group.length;
782
+
783
+ }
784
+ });
785
+
786
+ $.ui.plugin.add("draggable", "zIndex", {
787
+ start: function(event, ui) {
788
+ var t = $(ui.helper), o = $(this).data("draggable").options;
789
+ if(t.css("zIndex")) o._zIndex = t.css("zIndex");
790
+ t.css('zIndex', o.zIndex);
791
+ },
792
+ stop: function(event, ui) {
793
+ var o = $(this).data("draggable").options;
794
+ if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
795
+ }
796
+ });
797
+
798
+ })(jQuery);