assetable 0.1.2

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.
Files changed (83) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +181 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/images/assetable/icon-upload.png +0 -0
  6. data/app/assets/images/assetable/icons/icon-ai.png +0 -0
  7. data/app/assets/images/assetable/icons/icon-css.png +0 -0
  8. data/app/assets/images/assetable/icons/icon-desmos.png +0 -0
  9. data/app/assets/images/assetable/icons/icon-doc.png +0 -0
  10. data/app/assets/images/assetable/icons/icon-document.png +0 -0
  11. data/app/assets/images/assetable/icons/icon-docx.png +0 -0
  12. data/app/assets/images/assetable/icons/icon-eps.png +0 -0
  13. data/app/assets/images/assetable/icons/icon-flash.png +0 -0
  14. data/app/assets/images/assetable/icons/icon-html.png +0 -0
  15. data/app/assets/images/assetable/icons/icon-jpg.png +0 -0
  16. data/app/assets/images/assetable/icons/icon-js.png +0 -0
  17. data/app/assets/images/assetable/icons/icon-mov.png +0 -0
  18. data/app/assets/images/assetable/icons/icon-mp3.png +0 -0
  19. data/app/assets/images/assetable/icons/icon-mp4.png +0 -0
  20. data/app/assets/images/assetable/icons/icon-pdf.png +0 -0
  21. data/app/assets/images/assetable/icons/icon-php.png +0 -0
  22. data/app/assets/images/assetable/icons/icon-png.png +0 -0
  23. data/app/assets/images/assetable/icons/icon-ppt.png +0 -0
  24. data/app/assets/images/assetable/icons/icon-pptx.png +0 -0
  25. data/app/assets/images/assetable/icons/icon-txt.png +0 -0
  26. data/app/assets/images/assetable/icons/icon-xls.png +0 -0
  27. data/app/assets/images/assetable/icons/icon-xlsx.png +0 -0
  28. data/app/assets/images/assetable/icons/icon-xml.png +0 -0
  29. data/app/assets/javascripts/assetable/asset_gallery.js.coffee +74 -0
  30. data/app/assets/javascripts/assetable/assetable_uploader.js.coffee +204 -0
  31. data/app/assets/javascripts/assetable/gallery.js.coffee +33 -0
  32. data/app/assets/javascripts/assetable/uploader.js.coffee +10 -0
  33. data/app/assets/javascripts/vendor/bootstrap-modal.js +246 -0
  34. data/app/assets/javascripts/vendor/jquery-ui-1.10.3.custom.js +2252 -0
  35. data/app/assets/stylesheets/assetable/_assetable.css.sass +9 -0
  36. data/app/assets/stylesheets/assetable/_bootstrap.css.sass +5 -0
  37. data/app/assets/stylesheets/assetable/components/_buttons.css.sass +99 -0
  38. data/app/assets/stylesheets/assetable/components/_close.css.sass +28 -0
  39. data/app/assets/stylesheets/assetable/components/_forms.css.sass +219 -0
  40. data/app/assets/stylesheets/assetable/components/_gallery.css.sass +118 -0
  41. data/app/assets/stylesheets/assetable/components/_modals.css.sass +116 -0
  42. data/app/assets/stylesheets/assetable/components/_progress.css.sass +91 -0
  43. data/app/assets/stylesheets/assetable/components/_uploader.css.sass +175 -0
  44. data/app/assets/stylesheets/assetable/core/_mixins.css.sass +754 -0
  45. data/app/assets/stylesheets/assetable/core/_utilities.css.sass +5 -0
  46. data/app/assets/stylesheets/assetable/core/_variables.css.sass +165 -0
  47. data/app/controllers/assetable/assets_controller.rb +38 -0
  48. data/app/controllers/assetable/external_services_controller.rb +36 -0
  49. data/app/models/asset.rb +53 -0
  50. data/app/models/asset_attachment.rb +4 -0
  51. data/app/models/document.rb +5 -0
  52. data/app/models/external_service.rb +14 -0
  53. data/app/models/gallery.rb +7 -0
  54. data/app/models/image.rb +5 -0
  55. data/app/models/video.rb +5 -0
  56. data/app/uploaders/document_uploader.rb +50 -0
  57. data/app/uploaders/image_uploader.rb +67 -0
  58. data/app/uploaders/video_uploader.rb +40 -0
  59. data/app/views/assetable/assets/_asset.html.haml +20 -0
  60. data/app/views/assetable/assets/_gallery.html.haml +12 -0
  61. data/app/views/assetable/external_services/new.html.haml +31 -0
  62. data/config/initializers/carrierwave.rb +6 -0
  63. data/config/initializers/gallery_input.rb +37 -0
  64. data/config/initializers/uploader_input.rb +80 -0
  65. data/config/routes.rb +8 -0
  66. data/db/migrate/20131122232735_create_assets.rb +19 -0
  67. data/db/migrate/20131123172825_create_asset_attachments.rb +15 -0
  68. data/db/migrate/20131125200943_create_galleries.rb +14 -0
  69. data/lib/assetable.rb +18 -0
  70. data/lib/assetable/config.rb +23 -0
  71. data/lib/assetable/core.rb +41 -0
  72. data/lib/assetable/engine.rb +15 -0
  73. data/lib/assetable/version.rb +3 -0
  74. data/lib/tasks/assetable_tasks.rake +4 -0
  75. data/test/fixtures/asset_attachments.yml +11 -0
  76. data/test/fixtures/assets.yml +11 -0
  77. data/test/fixtures/images.yml +11 -0
  78. data/test/fixtures/videos.yml +11 -0
  79. data/test/models/asset_attachment_test.rb +7 -0
  80. data/test/models/asset_test.rb +7 -0
  81. data/test/models/image_test.rb +7 -0
  82. data/test/models/video_test.rb +7 -0
  83. metadata +371 -0
@@ -0,0 +1,33 @@
1
+ $(document).ready ->
2
+
3
+ # Bind the koh uploader and galleries to a page
4
+ $(".gallery-uploader").each ->
5
+
6
+ # Check that it's not already bound
7
+ unless $(this).hasClass("uploadable")
8
+ $(this).addClass "uploadable"
9
+ $this = $(this)
10
+ $this.removeClass "uploader"
11
+
12
+ field = $this.attr("data-uploader-input-name")
13
+
14
+ $this.assetable_uploader
15
+ multi_selection: true
16
+ gallery: true
17
+ url: "/assetable/assets"
18
+ fieldname: field
19
+ authenticity_token: $("meta[name=\"csrf-token\"]").attr("content")
20
+ onUploaded: (resp) ->
21
+ $this.find('.uploadar-data-wrapper').append(resp.html)
22
+ fileRemoved: (button, item) ->
23
+ $(button).closest('.uploader-preview').remove()
24
+
25
+
26
+
27
+ # Make the gallery sortable
28
+ $(this).sortable
29
+ items: "div.uploader-preview"
30
+ distance: 50
31
+ tolerance: 'pointer'
32
+ placeholder: 'uploader-sortable-placeholder'
33
+
@@ -0,0 +1,10 @@
1
+ #= require moxie
2
+ #= require plupload.dev
3
+ #= require plupload.settings
4
+ #= require jquery.plupload.queue
5
+ #= require vendor/jquery-ui-1.10.3.custom
6
+ #= require vendor/bootstrap-modal
7
+
8
+ #= require assetable/assetable_uploader
9
+ #= require assetable/gallery
10
+ #= require assetable/asset_gallery
@@ -0,0 +1,246 @@
1
+ /* ========================================================================
2
+ * Bootstrap: modal.js v3.0.3
3
+ * http://getbootstrap.com/javascript/#modals
4
+ * ========================================================================
5
+ * Copyright 2013 Twitter, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ======================================================================== */
19
+
20
+
21
+ +function ($) { "use strict";
22
+
23
+ // MODAL CLASS DEFINITION
24
+ // ======================
25
+
26
+ var Modal = function (element, options) {
27
+ this.options = options
28
+ this.$element = $(element)
29
+ this.$backdrop =
30
+ this.isShown = null
31
+
32
+ if (this.options.remote) this.$element.load(this.options.remote)
33
+ }
34
+
35
+ Modal.DEFAULTS = {
36
+ backdrop: true
37
+ , keyboard: true
38
+ , show: true
39
+ }
40
+
41
+ Modal.prototype.toggle = function (_relatedTarget) {
42
+ return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
43
+ }
44
+
45
+ Modal.prototype.show = function (_relatedTarget) {
46
+ var that = this
47
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
48
+
49
+ this.$element.trigger(e)
50
+
51
+ if (this.isShown || e.isDefaultPrevented()) return
52
+
53
+ this.isShown = true
54
+
55
+ this.escape()
56
+
57
+ this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
58
+
59
+ this.backdrop(function () {
60
+ var transition = $.support.transition && that.$element.hasClass('fade')
61
+
62
+ if (!that.$element.parent().length) {
63
+ that.$element.appendTo(document.body) // don't move modals dom position
64
+ }
65
+
66
+ that.$element.show()
67
+
68
+ if (transition) {
69
+ that.$element[0].offsetWidth // force reflow
70
+ }
71
+
72
+ that.$element
73
+ .addClass('in')
74
+ .attr('aria-hidden', false)
75
+
76
+ that.enforceFocus()
77
+
78
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
79
+
80
+ transition ?
81
+ that.$element.find('.modal-dialog') // wait for modal to slide in
82
+ .one($.support.transition.end, function () {
83
+ that.$element.focus().trigger(e)
84
+ })
85
+ .emulateTransitionEnd(300) :
86
+ that.$element.focus().trigger(e)
87
+ })
88
+ }
89
+
90
+ Modal.prototype.hide = function (e) {
91
+ if (e) e.preventDefault()
92
+
93
+ e = $.Event('hide.bs.modal')
94
+
95
+ this.$element.trigger(e)
96
+
97
+ if (!this.isShown || e.isDefaultPrevented()) return
98
+
99
+ this.isShown = false
100
+
101
+ this.escape()
102
+
103
+ $(document).off('focusin.bs.modal')
104
+
105
+ this.$element
106
+ .removeClass('in')
107
+ .attr('aria-hidden', true)
108
+ .off('click.dismiss.modal')
109
+
110
+ $.support.transition && this.$element.hasClass('fade') ?
111
+ this.$element
112
+ .one($.support.transition.end, $.proxy(this.hideModal, this))
113
+ .emulateTransitionEnd(300) :
114
+ this.hideModal()
115
+ }
116
+
117
+ Modal.prototype.enforceFocus = function () {
118
+ $(document)
119
+ .off('focusin.bs.modal') // guard against infinite focus loop
120
+ .on('focusin.bs.modal', $.proxy(function (e) {
121
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
122
+ this.$element.focus()
123
+ }
124
+ }, this))
125
+ }
126
+
127
+ Modal.prototype.escape = function () {
128
+ if (this.isShown && this.options.keyboard) {
129
+ this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
130
+ e.which == 27 && this.hide()
131
+ }, this))
132
+ } else if (!this.isShown) {
133
+ this.$element.off('keyup.dismiss.bs.modal')
134
+ }
135
+ }
136
+
137
+ Modal.prototype.hideModal = function () {
138
+ var that = this
139
+ this.$element.hide()
140
+ this.backdrop(function () {
141
+ that.removeBackdrop()
142
+ that.$element.trigger('hidden.bs.modal')
143
+ })
144
+ }
145
+
146
+ Modal.prototype.removeBackdrop = function () {
147
+ this.$backdrop && this.$backdrop.remove()
148
+ this.$backdrop = null
149
+ }
150
+
151
+ Modal.prototype.backdrop = function (callback) {
152
+ var that = this
153
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
154
+
155
+ if (this.isShown && this.options.backdrop) {
156
+ var doAnimate = $.support.transition && animate
157
+
158
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
159
+ .appendTo(document.body)
160
+
161
+ this.$element.on('click.dismiss.modal', $.proxy(function (e) {
162
+ if (e.target !== e.currentTarget) return
163
+ this.options.backdrop == 'static'
164
+ ? this.$element[0].focus.call(this.$element[0])
165
+ : this.hide.call(this)
166
+ }, this))
167
+
168
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
169
+
170
+ this.$backdrop.addClass('in')
171
+
172
+ if (!callback) return
173
+
174
+ doAnimate ?
175
+ this.$backdrop
176
+ .one($.support.transition.end, callback)
177
+ .emulateTransitionEnd(150) :
178
+ callback()
179
+
180
+ } else if (!this.isShown && this.$backdrop) {
181
+ this.$backdrop.removeClass('in')
182
+
183
+ $.support.transition && this.$element.hasClass('fade')?
184
+ this.$backdrop
185
+ .one($.support.transition.end, callback)
186
+ .emulateTransitionEnd(150) :
187
+ callback()
188
+
189
+ } else if (callback) {
190
+ callback()
191
+ }
192
+ }
193
+
194
+
195
+ // MODAL PLUGIN DEFINITION
196
+ // =======================
197
+
198
+ var old = $.fn.modal
199
+
200
+ $.fn.modal = function (option, _relatedTarget) {
201
+ return this.each(function () {
202
+ var $this = $(this)
203
+ var data = $this.data('bs.modal')
204
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
205
+
206
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
207
+ if (typeof option == 'string') data[option](_relatedTarget)
208
+ else if (options.show) data.show(_relatedTarget)
209
+ })
210
+ }
211
+
212
+ $.fn.modal.Constructor = Modal
213
+
214
+
215
+ // MODAL NO CONFLICT
216
+ // =================
217
+
218
+ $.fn.modal.noConflict = function () {
219
+ $.fn.modal = old
220
+ return this
221
+ }
222
+
223
+
224
+ // MODAL DATA-API
225
+ // ==============
226
+
227
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
228
+ var $this = $(this)
229
+ var href = $this.attr('href')
230
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
231
+ var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
232
+
233
+ e.preventDefault()
234
+
235
+ $target
236
+ .modal(option, this)
237
+ .one('hide', function () {
238
+ $this.is(':visible') && $this.focus()
239
+ })
240
+ })
241
+
242
+ $(document)
243
+ .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
244
+ .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
245
+
246
+ }(jQuery);
@@ -0,0 +1,2252 @@
1
+ /*! jQuery UI - v1.10.3 - 2013-12-03
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js
4
+ * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5
+
6
+ (function( $, undefined ) {
7
+
8
+ var uuid = 0,
9
+ runiqueId = /^ui-id-\d+$/;
10
+
11
+ // $.ui might exist from components with no dependencies, e.g., $.ui.position
12
+ $.ui = $.ui || {};
13
+
14
+ $.extend( $.ui, {
15
+ version: "1.10.3",
16
+
17
+ keyCode: {
18
+ BACKSPACE: 8,
19
+ COMMA: 188,
20
+ DELETE: 46,
21
+ DOWN: 40,
22
+ END: 35,
23
+ ENTER: 13,
24
+ ESCAPE: 27,
25
+ HOME: 36,
26
+ LEFT: 37,
27
+ NUMPAD_ADD: 107,
28
+ NUMPAD_DECIMAL: 110,
29
+ NUMPAD_DIVIDE: 111,
30
+ NUMPAD_ENTER: 108,
31
+ NUMPAD_MULTIPLY: 106,
32
+ NUMPAD_SUBTRACT: 109,
33
+ PAGE_DOWN: 34,
34
+ PAGE_UP: 33,
35
+ PERIOD: 190,
36
+ RIGHT: 39,
37
+ SPACE: 32,
38
+ TAB: 9,
39
+ UP: 38
40
+ }
41
+ });
42
+
43
+ // plugins
44
+ $.fn.extend({
45
+ focus: (function( orig ) {
46
+ return function( delay, fn ) {
47
+ return typeof delay === "number" ?
48
+ this.each(function() {
49
+ var elem = this;
50
+ setTimeout(function() {
51
+ $( elem ).focus();
52
+ if ( fn ) {
53
+ fn.call( elem );
54
+ }
55
+ }, delay );
56
+ }) :
57
+ orig.apply( this, arguments );
58
+ };
59
+ })( $.fn.focus ),
60
+
61
+ scrollParent: function() {
62
+ var scrollParent;
63
+ if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
64
+ scrollParent = this.parents().filter(function() {
65
+ return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
66
+ }).eq(0);
67
+ } else {
68
+ scrollParent = this.parents().filter(function() {
69
+ return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
70
+ }).eq(0);
71
+ }
72
+
73
+ return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
74
+ },
75
+
76
+ zIndex: function( zIndex ) {
77
+ if ( zIndex !== undefined ) {
78
+ return this.css( "zIndex", zIndex );
79
+ }
80
+
81
+ if ( this.length ) {
82
+ var elem = $( this[ 0 ] ), position, value;
83
+ while ( elem.length && elem[ 0 ] !== document ) {
84
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
85
+ // This makes behavior of this function consistent across browsers
86
+ // WebKit always returns auto if the element is positioned
87
+ position = elem.css( "position" );
88
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
89
+ // IE returns 0 when zIndex is not specified
90
+ // other browsers return a string
91
+ // we ignore the case of nested elements with an explicit value of 0
92
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
93
+ value = parseInt( elem.css( "zIndex" ), 10 );
94
+ if ( !isNaN( value ) && value !== 0 ) {
95
+ return value;
96
+ }
97
+ }
98
+ elem = elem.parent();
99
+ }
100
+ }
101
+
102
+ return 0;
103
+ },
104
+
105
+ uniqueId: function() {
106
+ return this.each(function() {
107
+ if ( !this.id ) {
108
+ this.id = "ui-id-" + (++uuid);
109
+ }
110
+ });
111
+ },
112
+
113
+ removeUniqueId: function() {
114
+ return this.each(function() {
115
+ if ( runiqueId.test( this.id ) ) {
116
+ $( this ).removeAttr( "id" );
117
+ }
118
+ });
119
+ }
120
+ });
121
+
122
+ // selectors
123
+ function focusable( element, isTabIndexNotNaN ) {
124
+ var map, mapName, img,
125
+ nodeName = element.nodeName.toLowerCase();
126
+ if ( "area" === nodeName ) {
127
+ map = element.parentNode;
128
+ mapName = map.name;
129
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
130
+ return false;
131
+ }
132
+ img = $( "img[usemap=#" + mapName + "]" )[0];
133
+ return !!img && visible( img );
134
+ }
135
+ return ( /input|select|textarea|button|object/.test( nodeName ) ?
136
+ !element.disabled :
137
+ "a" === nodeName ?
138
+ element.href || isTabIndexNotNaN :
139
+ isTabIndexNotNaN) &&
140
+ // the element and all of its ancestors must be visible
141
+ visible( element );
142
+ }
143
+
144
+ function visible( element ) {
145
+ return $.expr.filters.visible( element ) &&
146
+ !$( element ).parents().addBack().filter(function() {
147
+ return $.css( this, "visibility" ) === "hidden";
148
+ }).length;
149
+ }
150
+
151
+ $.extend( $.expr[ ":" ], {
152
+ data: $.expr.createPseudo ?
153
+ $.expr.createPseudo(function( dataName ) {
154
+ return function( elem ) {
155
+ return !!$.data( elem, dataName );
156
+ };
157
+ }) :
158
+ // support: jQuery <1.8
159
+ function( elem, i, match ) {
160
+ return !!$.data( elem, match[ 3 ] );
161
+ },
162
+
163
+ focusable: function( element ) {
164
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
165
+ },
166
+
167
+ tabbable: function( element ) {
168
+ var tabIndex = $.attr( element, "tabindex" ),
169
+ isTabIndexNaN = isNaN( tabIndex );
170
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
171
+ }
172
+ });
173
+
174
+ // support: jQuery <1.8
175
+ if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
176
+ $.each( [ "Width", "Height" ], function( i, name ) {
177
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
178
+ type = name.toLowerCase(),
179
+ orig = {
180
+ innerWidth: $.fn.innerWidth,
181
+ innerHeight: $.fn.innerHeight,
182
+ outerWidth: $.fn.outerWidth,
183
+ outerHeight: $.fn.outerHeight
184
+ };
185
+
186
+ function reduce( elem, size, border, margin ) {
187
+ $.each( side, function() {
188
+ size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
189
+ if ( border ) {
190
+ size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
191
+ }
192
+ if ( margin ) {
193
+ size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
194
+ }
195
+ });
196
+ return size;
197
+ }
198
+
199
+ $.fn[ "inner" + name ] = function( size ) {
200
+ if ( size === undefined ) {
201
+ return orig[ "inner" + name ].call( this );
202
+ }
203
+
204
+ return this.each(function() {
205
+ $( this ).css( type, reduce( this, size ) + "px" );
206
+ });
207
+ };
208
+
209
+ $.fn[ "outer" + name] = function( size, margin ) {
210
+ if ( typeof size !== "number" ) {
211
+ return orig[ "outer" + name ].call( this, size );
212
+ }
213
+
214
+ return this.each(function() {
215
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
216
+ });
217
+ };
218
+ });
219
+ }
220
+
221
+ // support: jQuery <1.8
222
+ if ( !$.fn.addBack ) {
223
+ $.fn.addBack = function( selector ) {
224
+ return this.add( selector == null ?
225
+ this.prevObject : this.prevObject.filter( selector )
226
+ );
227
+ };
228
+ }
229
+
230
+ // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
231
+ if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
232
+ $.fn.removeData = (function( removeData ) {
233
+ return function( key ) {
234
+ if ( arguments.length ) {
235
+ return removeData.call( this, $.camelCase( key ) );
236
+ } else {
237
+ return removeData.call( this );
238
+ }
239
+ };
240
+ })( $.fn.removeData );
241
+ }
242
+
243
+
244
+
245
+
246
+
247
+ // deprecated
248
+ $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
249
+
250
+ $.support.selectstart = "onselectstart" in document.createElement( "div" );
251
+ $.fn.extend({
252
+ disableSelection: function() {
253
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
254
+ ".ui-disableSelection", function( event ) {
255
+ event.preventDefault();
256
+ });
257
+ },
258
+
259
+ enableSelection: function() {
260
+ return this.unbind( ".ui-disableSelection" );
261
+ }
262
+ });
263
+
264
+ $.extend( $.ui, {
265
+ // $.ui.plugin is deprecated. Use $.widget() extensions instead.
266
+ plugin: {
267
+ add: function( module, option, set ) {
268
+ var i,
269
+ proto = $.ui[ module ].prototype;
270
+ for ( i in set ) {
271
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
272
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
273
+ }
274
+ },
275
+ call: function( instance, name, args ) {
276
+ var i,
277
+ set = instance.plugins[ name ];
278
+ if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
279
+ return;
280
+ }
281
+
282
+ for ( i = 0; i < set.length; i++ ) {
283
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
284
+ set[ i ][ 1 ].apply( instance.element, args );
285
+ }
286
+ }
287
+ }
288
+ },
289
+
290
+ // only used by resizable
291
+ hasScroll: function( el, a ) {
292
+
293
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
294
+ if ( $( el ).css( "overflow" ) === "hidden") {
295
+ return false;
296
+ }
297
+
298
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
299
+ has = false;
300
+
301
+ if ( el[ scroll ] > 0 ) {
302
+ return true;
303
+ }
304
+
305
+ // TODO: determine which cases actually cause this to happen
306
+ // if the element doesn't have the scroll set, see if it's possible to
307
+ // set the scroll
308
+ el[ scroll ] = 1;
309
+ has = ( el[ scroll ] > 0 );
310
+ el[ scroll ] = 0;
311
+ return has;
312
+ }
313
+ });
314
+
315
+ })( jQuery );
316
+ (function( $, undefined ) {
317
+
318
+ var uuid = 0,
319
+ slice = Array.prototype.slice,
320
+ _cleanData = $.cleanData;
321
+ $.cleanData = function( elems ) {
322
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
323
+ try {
324
+ $( elem ).triggerHandler( "remove" );
325
+ // http://bugs.jquery.com/ticket/8235
326
+ } catch( e ) {}
327
+ }
328
+ _cleanData( elems );
329
+ };
330
+
331
+ $.widget = function( name, base, prototype ) {
332
+ var fullName, existingConstructor, constructor, basePrototype,
333
+ // proxiedPrototype allows the provided prototype to remain unmodified
334
+ // so that it can be used as a mixin for multiple widgets (#8876)
335
+ proxiedPrototype = {},
336
+ namespace = name.split( "." )[ 0 ];
337
+
338
+ name = name.split( "." )[ 1 ];
339
+ fullName = namespace + "-" + name;
340
+
341
+ if ( !prototype ) {
342
+ prototype = base;
343
+ base = $.Widget;
344
+ }
345
+
346
+ // create selector for plugin
347
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
348
+ return !!$.data( elem, fullName );
349
+ };
350
+
351
+ $[ namespace ] = $[ namespace ] || {};
352
+ existingConstructor = $[ namespace ][ name ];
353
+ constructor = $[ namespace ][ name ] = function( options, element ) {
354
+ // allow instantiation without "new" keyword
355
+ if ( !this._createWidget ) {
356
+ return new constructor( options, element );
357
+ }
358
+
359
+ // allow instantiation without initializing for simple inheritance
360
+ // must use "new" keyword (the code above always passes args)
361
+ if ( arguments.length ) {
362
+ this._createWidget( options, element );
363
+ }
364
+ };
365
+ // extend with the existing constructor to carry over any static properties
366
+ $.extend( constructor, existingConstructor, {
367
+ version: prototype.version,
368
+ // copy the object used to create the prototype in case we need to
369
+ // redefine the widget later
370
+ _proto: $.extend( {}, prototype ),
371
+ // track widgets that inherit from this widget in case this widget is
372
+ // redefined after a widget inherits from it
373
+ _childConstructors: []
374
+ });
375
+
376
+ basePrototype = new base();
377
+ // we need to make the options hash a property directly on the new instance
378
+ // otherwise we'll modify the options hash on the prototype that we're
379
+ // inheriting from
380
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
381
+ $.each( prototype, function( prop, value ) {
382
+ if ( !$.isFunction( value ) ) {
383
+ proxiedPrototype[ prop ] = value;
384
+ return;
385
+ }
386
+ proxiedPrototype[ prop ] = (function() {
387
+ var _super = function() {
388
+ return base.prototype[ prop ].apply( this, arguments );
389
+ },
390
+ _superApply = function( args ) {
391
+ return base.prototype[ prop ].apply( this, args );
392
+ };
393
+ return function() {
394
+ var __super = this._super,
395
+ __superApply = this._superApply,
396
+ returnValue;
397
+
398
+ this._super = _super;
399
+ this._superApply = _superApply;
400
+
401
+ returnValue = value.apply( this, arguments );
402
+
403
+ this._super = __super;
404
+ this._superApply = __superApply;
405
+
406
+ return returnValue;
407
+ };
408
+ })();
409
+ });
410
+ constructor.prototype = $.widget.extend( basePrototype, {
411
+ // TODO: remove support for widgetEventPrefix
412
+ // always use the name + a colon as the prefix, e.g., draggable:start
413
+ // don't prefix for widgets that aren't DOM-based
414
+ widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
415
+ }, proxiedPrototype, {
416
+ constructor: constructor,
417
+ namespace: namespace,
418
+ widgetName: name,
419
+ widgetFullName: fullName
420
+ });
421
+
422
+ // If this widget is being redefined then we need to find all widgets that
423
+ // are inheriting from it and redefine all of them so that they inherit from
424
+ // the new version of this widget. We're essentially trying to replace one
425
+ // level in the prototype chain.
426
+ if ( existingConstructor ) {
427
+ $.each( existingConstructor._childConstructors, function( i, child ) {
428
+ var childPrototype = child.prototype;
429
+
430
+ // redefine the child widget using the same prototype that was
431
+ // originally used, but inherit from the new version of the base
432
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
433
+ });
434
+ // remove the list of existing child constructors from the old constructor
435
+ // so the old child constructors can be garbage collected
436
+ delete existingConstructor._childConstructors;
437
+ } else {
438
+ base._childConstructors.push( constructor );
439
+ }
440
+
441
+ $.widget.bridge( name, constructor );
442
+ };
443
+
444
+ $.widget.extend = function( target ) {
445
+ var input = slice.call( arguments, 1 ),
446
+ inputIndex = 0,
447
+ inputLength = input.length,
448
+ key,
449
+ value;
450
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
451
+ for ( key in input[ inputIndex ] ) {
452
+ value = input[ inputIndex ][ key ];
453
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
454
+ // Clone objects
455
+ if ( $.isPlainObject( value ) ) {
456
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
457
+ $.widget.extend( {}, target[ key ], value ) :
458
+ // Don't extend strings, arrays, etc. with objects
459
+ $.widget.extend( {}, value );
460
+ // Copy everything else by reference
461
+ } else {
462
+ target[ key ] = value;
463
+ }
464
+ }
465
+ }
466
+ }
467
+ return target;
468
+ };
469
+
470
+ $.widget.bridge = function( name, object ) {
471
+ var fullName = object.prototype.widgetFullName || name;
472
+ $.fn[ name ] = function( options ) {
473
+ var isMethodCall = typeof options === "string",
474
+ args = slice.call( arguments, 1 ),
475
+ returnValue = this;
476
+
477
+ // allow multiple hashes to be passed on init
478
+ options = !isMethodCall && args.length ?
479
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
480
+ options;
481
+
482
+ if ( isMethodCall ) {
483
+ this.each(function() {
484
+ var methodValue,
485
+ instance = $.data( this, fullName );
486
+ if ( !instance ) {
487
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
488
+ "attempted to call method '" + options + "'" );
489
+ }
490
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
491
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
492
+ }
493
+ methodValue = instance[ options ].apply( instance, args );
494
+ if ( methodValue !== instance && methodValue !== undefined ) {
495
+ returnValue = methodValue && methodValue.jquery ?
496
+ returnValue.pushStack( methodValue.get() ) :
497
+ methodValue;
498
+ return false;
499
+ }
500
+ });
501
+ } else {
502
+ this.each(function() {
503
+ var instance = $.data( this, fullName );
504
+ if ( instance ) {
505
+ instance.option( options || {} )._init();
506
+ } else {
507
+ $.data( this, fullName, new object( options, this ) );
508
+ }
509
+ });
510
+ }
511
+
512
+ return returnValue;
513
+ };
514
+ };
515
+
516
+ $.Widget = function( /* options, element */ ) {};
517
+ $.Widget._childConstructors = [];
518
+
519
+ $.Widget.prototype = {
520
+ widgetName: "widget",
521
+ widgetEventPrefix: "",
522
+ defaultElement: "<div>",
523
+ options: {
524
+ disabled: false,
525
+
526
+ // callbacks
527
+ create: null
528
+ },
529
+ _createWidget: function( options, element ) {
530
+ element = $( element || this.defaultElement || this )[ 0 ];
531
+ this.element = $( element );
532
+ this.uuid = uuid++;
533
+ this.eventNamespace = "." + this.widgetName + this.uuid;
534
+ this.options = $.widget.extend( {},
535
+ this.options,
536
+ this._getCreateOptions(),
537
+ options );
538
+
539
+ this.bindings = $();
540
+ this.hoverable = $();
541
+ this.focusable = $();
542
+
543
+ if ( element !== this ) {
544
+ $.data( element, this.widgetFullName, this );
545
+ this._on( true, this.element, {
546
+ remove: function( event ) {
547
+ if ( event.target === element ) {
548
+ this.destroy();
549
+ }
550
+ }
551
+ });
552
+ this.document = $( element.style ?
553
+ // element within the document
554
+ element.ownerDocument :
555
+ // element is window or document
556
+ element.document || element );
557
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
558
+ }
559
+
560
+ this._create();
561
+ this._trigger( "create", null, this._getCreateEventData() );
562
+ this._init();
563
+ },
564
+ _getCreateOptions: $.noop,
565
+ _getCreateEventData: $.noop,
566
+ _create: $.noop,
567
+ _init: $.noop,
568
+
569
+ destroy: function() {
570
+ this._destroy();
571
+ // we can probably remove the unbind calls in 2.0
572
+ // all event bindings should go through this._on()
573
+ this.element
574
+ .unbind( this.eventNamespace )
575
+ // 1.9 BC for #7810
576
+ // TODO remove dual storage
577
+ .removeData( this.widgetName )
578
+ .removeData( this.widgetFullName )
579
+ // support: jquery <1.6.3
580
+ // http://bugs.jquery.com/ticket/9413
581
+ .removeData( $.camelCase( this.widgetFullName ) );
582
+ this.widget()
583
+ .unbind( this.eventNamespace )
584
+ .removeAttr( "aria-disabled" )
585
+ .removeClass(
586
+ this.widgetFullName + "-disabled " +
587
+ "ui-state-disabled" );
588
+
589
+ // clean up events and states
590
+ this.bindings.unbind( this.eventNamespace );
591
+ this.hoverable.removeClass( "ui-state-hover" );
592
+ this.focusable.removeClass( "ui-state-focus" );
593
+ },
594
+ _destroy: $.noop,
595
+
596
+ widget: function() {
597
+ return this.element;
598
+ },
599
+
600
+ option: function( key, value ) {
601
+ var options = key,
602
+ parts,
603
+ curOption,
604
+ i;
605
+
606
+ if ( arguments.length === 0 ) {
607
+ // don't return a reference to the internal hash
608
+ return $.widget.extend( {}, this.options );
609
+ }
610
+
611
+ if ( typeof key === "string" ) {
612
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
613
+ options = {};
614
+ parts = key.split( "." );
615
+ key = parts.shift();
616
+ if ( parts.length ) {
617
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
618
+ for ( i = 0; i < parts.length - 1; i++ ) {
619
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
620
+ curOption = curOption[ parts[ i ] ];
621
+ }
622
+ key = parts.pop();
623
+ if ( value === undefined ) {
624
+ return curOption[ key ] === undefined ? null : curOption[ key ];
625
+ }
626
+ curOption[ key ] = value;
627
+ } else {
628
+ if ( value === undefined ) {
629
+ return this.options[ key ] === undefined ? null : this.options[ key ];
630
+ }
631
+ options[ key ] = value;
632
+ }
633
+ }
634
+
635
+ this._setOptions( options );
636
+
637
+ return this;
638
+ },
639
+ _setOptions: function( options ) {
640
+ var key;
641
+
642
+ for ( key in options ) {
643
+ this._setOption( key, options[ key ] );
644
+ }
645
+
646
+ return this;
647
+ },
648
+ _setOption: function( key, value ) {
649
+ this.options[ key ] = value;
650
+
651
+ if ( key === "disabled" ) {
652
+ this.widget()
653
+ .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
654
+ .attr( "aria-disabled", value );
655
+ this.hoverable.removeClass( "ui-state-hover" );
656
+ this.focusable.removeClass( "ui-state-focus" );
657
+ }
658
+
659
+ return this;
660
+ },
661
+
662
+ enable: function() {
663
+ return this._setOption( "disabled", false );
664
+ },
665
+ disable: function() {
666
+ return this._setOption( "disabled", true );
667
+ },
668
+
669
+ _on: function( suppressDisabledCheck, element, handlers ) {
670
+ var delegateElement,
671
+ instance = this;
672
+
673
+ // no suppressDisabledCheck flag, shuffle arguments
674
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
675
+ handlers = element;
676
+ element = suppressDisabledCheck;
677
+ suppressDisabledCheck = false;
678
+ }
679
+
680
+ // no element argument, shuffle and use this.element
681
+ if ( !handlers ) {
682
+ handlers = element;
683
+ element = this.element;
684
+ delegateElement = this.widget();
685
+ } else {
686
+ // accept selectors, DOM elements
687
+ element = delegateElement = $( element );
688
+ this.bindings = this.bindings.add( element );
689
+ }
690
+
691
+ $.each( handlers, function( event, handler ) {
692
+ function handlerProxy() {
693
+ // allow widgets to customize the disabled handling
694
+ // - disabled as an array instead of boolean
695
+ // - disabled class as method for disabling individual parts
696
+ if ( !suppressDisabledCheck &&
697
+ ( instance.options.disabled === true ||
698
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
699
+ return;
700
+ }
701
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
702
+ .apply( instance, arguments );
703
+ }
704
+
705
+ // copy the guid so direct unbinding works
706
+ if ( typeof handler !== "string" ) {
707
+ handlerProxy.guid = handler.guid =
708
+ handler.guid || handlerProxy.guid || $.guid++;
709
+ }
710
+
711
+ var match = event.match( /^(\w+)\s*(.*)$/ ),
712
+ eventName = match[1] + instance.eventNamespace,
713
+ selector = match[2];
714
+ if ( selector ) {
715
+ delegateElement.delegate( selector, eventName, handlerProxy );
716
+ } else {
717
+ element.bind( eventName, handlerProxy );
718
+ }
719
+ });
720
+ },
721
+
722
+ _off: function( element, eventName ) {
723
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
724
+ element.unbind( eventName ).undelegate( eventName );
725
+ },
726
+
727
+ _delay: function( handler, delay ) {
728
+ function handlerProxy() {
729
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
730
+ .apply( instance, arguments );
731
+ }
732
+ var instance = this;
733
+ return setTimeout( handlerProxy, delay || 0 );
734
+ },
735
+
736
+ _hoverable: function( element ) {
737
+ this.hoverable = this.hoverable.add( element );
738
+ this._on( element, {
739
+ mouseenter: function( event ) {
740
+ $( event.currentTarget ).addClass( "ui-state-hover" );
741
+ },
742
+ mouseleave: function( event ) {
743
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
744
+ }
745
+ });
746
+ },
747
+
748
+ _focusable: function( element ) {
749
+ this.focusable = this.focusable.add( element );
750
+ this._on( element, {
751
+ focusin: function( event ) {
752
+ $( event.currentTarget ).addClass( "ui-state-focus" );
753
+ },
754
+ focusout: function( event ) {
755
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
756
+ }
757
+ });
758
+ },
759
+
760
+ _trigger: function( type, event, data ) {
761
+ var prop, orig,
762
+ callback = this.options[ type ];
763
+
764
+ data = data || {};
765
+ event = $.Event( event );
766
+ event.type = ( type === this.widgetEventPrefix ?
767
+ type :
768
+ this.widgetEventPrefix + type ).toLowerCase();
769
+ // the original event may come from any element
770
+ // so we need to reset the target on the new event
771
+ event.target = this.element[ 0 ];
772
+
773
+ // copy original event properties over to the new event
774
+ orig = event.originalEvent;
775
+ if ( orig ) {
776
+ for ( prop in orig ) {
777
+ if ( !( prop in event ) ) {
778
+ event[ prop ] = orig[ prop ];
779
+ }
780
+ }
781
+ }
782
+
783
+ this.element.trigger( event, data );
784
+ return !( $.isFunction( callback ) &&
785
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
786
+ event.isDefaultPrevented() );
787
+ }
788
+ };
789
+
790
+ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
791
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
792
+ if ( typeof options === "string" ) {
793
+ options = { effect: options };
794
+ }
795
+ var hasOptions,
796
+ effectName = !options ?
797
+ method :
798
+ options === true || typeof options === "number" ?
799
+ defaultEffect :
800
+ options.effect || defaultEffect;
801
+ options = options || {};
802
+ if ( typeof options === "number" ) {
803
+ options = { duration: options };
804
+ }
805
+ hasOptions = !$.isEmptyObject( options );
806
+ options.complete = callback;
807
+ if ( options.delay ) {
808
+ element.delay( options.delay );
809
+ }
810
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
811
+ element[ method ]( options );
812
+ } else if ( effectName !== method && element[ effectName ] ) {
813
+ element[ effectName ]( options.duration, options.easing, callback );
814
+ } else {
815
+ element.queue(function( next ) {
816
+ $( this )[ method ]();
817
+ if ( callback ) {
818
+ callback.call( element[ 0 ] );
819
+ }
820
+ next();
821
+ });
822
+ }
823
+ };
824
+ });
825
+
826
+ })( jQuery );
827
+ (function( $, undefined ) {
828
+
829
+ var mouseHandled = false;
830
+ $( document ).mouseup( function() {
831
+ mouseHandled = false;
832
+ });
833
+
834
+ $.widget("ui.mouse", {
835
+ version: "1.10.3",
836
+ options: {
837
+ cancel: "input,textarea,button,select,option",
838
+ distance: 1,
839
+ delay: 0
840
+ },
841
+ _mouseInit: function() {
842
+ var that = this;
843
+
844
+ this.element
845
+ .bind("mousedown."+this.widgetName, function(event) {
846
+ return that._mouseDown(event);
847
+ })
848
+ .bind("click."+this.widgetName, function(event) {
849
+ if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
850
+ $.removeData(event.target, that.widgetName + ".preventClickEvent");
851
+ event.stopImmediatePropagation();
852
+ return false;
853
+ }
854
+ });
855
+
856
+ this.started = false;
857
+ },
858
+
859
+ // TODO: make sure destroying one instance of mouse doesn't mess with
860
+ // other instances of mouse
861
+ _mouseDestroy: function() {
862
+ this.element.unbind("."+this.widgetName);
863
+ if ( this._mouseMoveDelegate ) {
864
+ $(document)
865
+ .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
866
+ .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
867
+ }
868
+ },
869
+
870
+ _mouseDown: function(event) {
871
+ // don't let more than one widget handle mouseStart
872
+ if( mouseHandled ) { return; }
873
+
874
+ // we may have missed mouseup (out of window)
875
+ (this._mouseStarted && this._mouseUp(event));
876
+
877
+ this._mouseDownEvent = event;
878
+
879
+ var that = this,
880
+ btnIsLeft = (event.which === 1),
881
+ // event.target.nodeName works around a bug in IE 8 with
882
+ // disabled inputs (#7620)
883
+ elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
884
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
885
+ return true;
886
+ }
887
+
888
+ this.mouseDelayMet = !this.options.delay;
889
+ if (!this.mouseDelayMet) {
890
+ this._mouseDelayTimer = setTimeout(function() {
891
+ that.mouseDelayMet = true;
892
+ }, this.options.delay);
893
+ }
894
+
895
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
896
+ this._mouseStarted = (this._mouseStart(event) !== false);
897
+ if (!this._mouseStarted) {
898
+ event.preventDefault();
899
+ return true;
900
+ }
901
+ }
902
+
903
+ // Click event may never have fired (Gecko & Opera)
904
+ if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
905
+ $.removeData(event.target, this.widgetName + ".preventClickEvent");
906
+ }
907
+
908
+ // these delegates are required to keep context
909
+ this._mouseMoveDelegate = function(event) {
910
+ return that._mouseMove(event);
911
+ };
912
+ this._mouseUpDelegate = function(event) {
913
+ return that._mouseUp(event);
914
+ };
915
+ $(document)
916
+ .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
917
+ .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
918
+
919
+ event.preventDefault();
920
+
921
+ mouseHandled = true;
922
+ return true;
923
+ },
924
+
925
+ _mouseMove: function(event) {
926
+ // IE mouseup check - mouseup happened when mouse was out of window
927
+ if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
928
+ return this._mouseUp(event);
929
+ }
930
+
931
+ if (this._mouseStarted) {
932
+ this._mouseDrag(event);
933
+ return event.preventDefault();
934
+ }
935
+
936
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
937
+ this._mouseStarted =
938
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
939
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
940
+ }
941
+
942
+ return !this._mouseStarted;
943
+ },
944
+
945
+ _mouseUp: function(event) {
946
+ $(document)
947
+ .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
948
+ .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
949
+
950
+ if (this._mouseStarted) {
951
+ this._mouseStarted = false;
952
+
953
+ if (event.target === this._mouseDownEvent.target) {
954
+ $.data(event.target, this.widgetName + ".preventClickEvent", true);
955
+ }
956
+
957
+ this._mouseStop(event);
958
+ }
959
+
960
+ return false;
961
+ },
962
+
963
+ _mouseDistanceMet: function(event) {
964
+ return (Math.max(
965
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
966
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
967
+ ) >= this.options.distance
968
+ );
969
+ },
970
+
971
+ _mouseDelayMet: function(/* event */) {
972
+ return this.mouseDelayMet;
973
+ },
974
+
975
+ // These are placeholder methods, to be overriden by extending plugin
976
+ _mouseStart: function(/* event */) {},
977
+ _mouseDrag: function(/* event */) {},
978
+ _mouseStop: function(/* event */) {},
979
+ _mouseCapture: function(/* event */) { return true; }
980
+ });
981
+
982
+ })(jQuery);
983
+ (function( $, undefined ) {
984
+
985
+ /*jshint loopfunc: true */
986
+
987
+ function isOverAxis( x, reference, size ) {
988
+ return ( x > reference ) && ( x < ( reference + size ) );
989
+ }
990
+
991
+ function isFloating(item) {
992
+ return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
993
+ }
994
+
995
+ $.widget("ui.sortable", $.ui.mouse, {
996
+ version: "1.10.3",
997
+ widgetEventPrefix: "sort",
998
+ ready: false,
999
+ options: {
1000
+ appendTo: "parent",
1001
+ axis: false,
1002
+ connectWith: false,
1003
+ containment: false,
1004
+ cursor: "auto",
1005
+ cursorAt: false,
1006
+ dropOnEmpty: true,
1007
+ forcePlaceholderSize: false,
1008
+ forceHelperSize: false,
1009
+ grid: false,
1010
+ handle: false,
1011
+ helper: "original",
1012
+ items: "> *",
1013
+ opacity: false,
1014
+ placeholder: false,
1015
+ revert: false,
1016
+ scroll: true,
1017
+ scrollSensitivity: 20,
1018
+ scrollSpeed: 20,
1019
+ scope: "default",
1020
+ tolerance: "intersect",
1021
+ zIndex: 1000,
1022
+
1023
+ // callbacks
1024
+ activate: null,
1025
+ beforeStop: null,
1026
+ change: null,
1027
+ deactivate: null,
1028
+ out: null,
1029
+ over: null,
1030
+ receive: null,
1031
+ remove: null,
1032
+ sort: null,
1033
+ start: null,
1034
+ stop: null,
1035
+ update: null
1036
+ },
1037
+ _create: function() {
1038
+
1039
+ var o = this.options;
1040
+ this.containerCache = {};
1041
+ this.element.addClass("ui-sortable");
1042
+
1043
+ //Get the items
1044
+ this.refresh();
1045
+
1046
+ //Let's determine if the items are being displayed horizontally
1047
+ this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
1048
+
1049
+ //Let's determine the parent's offset
1050
+ this.offset = this.element.offset();
1051
+
1052
+ //Initialize mouse events for interaction
1053
+ this._mouseInit();
1054
+
1055
+ //We're ready to go
1056
+ this.ready = true;
1057
+
1058
+ },
1059
+
1060
+ _destroy: function() {
1061
+ this.element
1062
+ .removeClass("ui-sortable ui-sortable-disabled");
1063
+ this._mouseDestroy();
1064
+
1065
+ for ( var i = this.items.length - 1; i >= 0; i-- ) {
1066
+ this.items[i].item.removeData(this.widgetName + "-item");
1067
+ }
1068
+
1069
+ return this;
1070
+ },
1071
+
1072
+ _setOption: function(key, value){
1073
+ if ( key === "disabled" ) {
1074
+ this.options[ key ] = value;
1075
+
1076
+ this.widget().toggleClass( "ui-sortable-disabled", !!value );
1077
+ } else {
1078
+ // Don't call widget base _setOption for disable as it adds ui-state-disabled class
1079
+ $.Widget.prototype._setOption.apply(this, arguments);
1080
+ }
1081
+ },
1082
+
1083
+ _mouseCapture: function(event, overrideHandle) {
1084
+ var currentItem = null,
1085
+ validHandle = false,
1086
+ that = this;
1087
+
1088
+ if (this.reverting) {
1089
+ return false;
1090
+ }
1091
+
1092
+ if(this.options.disabled || this.options.type === "static") {
1093
+ return false;
1094
+ }
1095
+
1096
+ //We have to refresh the items data once first
1097
+ this._refreshItems(event);
1098
+
1099
+ //Find out if the clicked node (or one of its parents) is a actual item in this.items
1100
+ $(event.target).parents().each(function() {
1101
+ if($.data(this, that.widgetName + "-item") === that) {
1102
+ currentItem = $(this);
1103
+ return false;
1104
+ }
1105
+ });
1106
+ if($.data(event.target, that.widgetName + "-item") === that) {
1107
+ currentItem = $(event.target);
1108
+ }
1109
+
1110
+ if(!currentItem) {
1111
+ return false;
1112
+ }
1113
+ if(this.options.handle && !overrideHandle) {
1114
+ $(this.options.handle, currentItem).find("*").addBack().each(function() {
1115
+ if(this === event.target) {
1116
+ validHandle = true;
1117
+ }
1118
+ });
1119
+ if(!validHandle) {
1120
+ return false;
1121
+ }
1122
+ }
1123
+
1124
+ this.currentItem = currentItem;
1125
+ this._removeCurrentsFromItems();
1126
+ return true;
1127
+
1128
+ },
1129
+
1130
+ _mouseStart: function(event, overrideHandle, noActivation) {
1131
+
1132
+ var i, body,
1133
+ o = this.options;
1134
+
1135
+ this.currentContainer = this;
1136
+
1137
+ //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
1138
+ this.refreshPositions();
1139
+
1140
+ //Create and append the visible helper
1141
+ this.helper = this._createHelper(event);
1142
+
1143
+ //Cache the helper size
1144
+ this._cacheHelperProportions();
1145
+
1146
+ /*
1147
+ * - Position generation -
1148
+ * This block generates everything position related - it's the core of draggables.
1149
+ */
1150
+
1151
+ //Cache the margins of the original element
1152
+ this._cacheMargins();
1153
+
1154
+ //Get the next scrolling parent
1155
+ this.scrollParent = this.helper.scrollParent();
1156
+
1157
+ //The element's absolute position on the page minus margins
1158
+ this.offset = this.currentItem.offset();
1159
+ this.offset = {
1160
+ top: this.offset.top - this.margins.top,
1161
+ left: this.offset.left - this.margins.left
1162
+ };
1163
+
1164
+ $.extend(this.offset, {
1165
+ click: { //Where the click happened, relative to the element
1166
+ left: event.pageX - this.offset.left,
1167
+ top: event.pageY - this.offset.top
1168
+ },
1169
+ parent: this._getParentOffset(),
1170
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1171
+ });
1172
+
1173
+ // Only after we got the offset, we can change the helper's position to absolute
1174
+ // TODO: Still need to figure out a way to make relative sorting possible
1175
+ this.helper.css("position", "absolute");
1176
+ this.cssPosition = this.helper.css("position");
1177
+
1178
+ //Generate the original position
1179
+ this.originalPosition = this._generatePosition(event);
1180
+ this.originalPageX = event.pageX;
1181
+ this.originalPageY = event.pageY;
1182
+
1183
+ //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1184
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1185
+
1186
+ //Cache the former DOM position
1187
+ this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
1188
+
1189
+ //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
1190
+ if(this.helper[0] !== this.currentItem[0]) {
1191
+ this.currentItem.hide();
1192
+ }
1193
+
1194
+ //Create the placeholder
1195
+ this._createPlaceholder();
1196
+
1197
+ //Set a containment if given in the options
1198
+ if(o.containment) {
1199
+ this._setContainment();
1200
+ }
1201
+
1202
+ if( o.cursor && o.cursor !== "auto" ) { // cursor option
1203
+ body = this.document.find( "body" );
1204
+
1205
+ // support: IE
1206
+ this.storedCursor = body.css( "cursor" );
1207
+ body.css( "cursor", o.cursor );
1208
+
1209
+ this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
1210
+ }
1211
+
1212
+ if(o.opacity) { // opacity option
1213
+ if (this.helper.css("opacity")) {
1214
+ this._storedOpacity = this.helper.css("opacity");
1215
+ }
1216
+ this.helper.css("opacity", o.opacity);
1217
+ }
1218
+
1219
+ if(o.zIndex) { // zIndex option
1220
+ if (this.helper.css("zIndex")) {
1221
+ this._storedZIndex = this.helper.css("zIndex");
1222
+ }
1223
+ this.helper.css("zIndex", o.zIndex);
1224
+ }
1225
+
1226
+ //Prepare scrolling
1227
+ if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
1228
+ this.overflowOffset = this.scrollParent.offset();
1229
+ }
1230
+
1231
+ //Call callbacks
1232
+ this._trigger("start", event, this._uiHash());
1233
+
1234
+ //Recache the helper size
1235
+ if(!this._preserveHelperProportions) {
1236
+ this._cacheHelperProportions();
1237
+ }
1238
+
1239
+
1240
+ //Post "activate" events to possible containers
1241
+ if( !noActivation ) {
1242
+ for ( i = this.containers.length - 1; i >= 0; i-- ) {
1243
+ this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
1244
+ }
1245
+ }
1246
+
1247
+ //Prepare possible droppables
1248
+ if($.ui.ddmanager) {
1249
+ $.ui.ddmanager.current = this;
1250
+ }
1251
+
1252
+ if ($.ui.ddmanager && !o.dropBehaviour) {
1253
+ $.ui.ddmanager.prepareOffsets(this, event);
1254
+ }
1255
+
1256
+ this.dragging = true;
1257
+
1258
+ this.helper.addClass("ui-sortable-helper");
1259
+ this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1260
+ return true;
1261
+
1262
+ },
1263
+
1264
+ _mouseDrag: function(event) {
1265
+ var i, item, itemElement, intersection,
1266
+ o = this.options,
1267
+ scrolled = false;
1268
+
1269
+ //Compute the helpers position
1270
+ this.position = this._generatePosition(event);
1271
+ this.positionAbs = this._convertPositionTo("absolute");
1272
+
1273
+ if (!this.lastPositionAbs) {
1274
+ this.lastPositionAbs = this.positionAbs;
1275
+ }
1276
+
1277
+ //Do scrolling
1278
+ if(this.options.scroll) {
1279
+ if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
1280
+
1281
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
1282
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
1283
+ } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
1284
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
1285
+ }
1286
+
1287
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
1288
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
1289
+ } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
1290
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
1291
+ }
1292
+
1293
+ } else {
1294
+
1295
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
1296
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1297
+ } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
1298
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1299
+ }
1300
+
1301
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
1302
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1303
+ } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
1304
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1305
+ }
1306
+
1307
+ }
1308
+
1309
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
1310
+ $.ui.ddmanager.prepareOffsets(this, event);
1311
+ }
1312
+ }
1313
+
1314
+ //Regenerate the absolute position used for position checks
1315
+ this.positionAbs = this._convertPositionTo("absolute");
1316
+
1317
+ //Set the helper position
1318
+ if(!this.options.axis || this.options.axis !== "y") {
1319
+ this.helper[0].style.left = this.position.left+"px";
1320
+ }
1321
+ if(!this.options.axis || this.options.axis !== "x") {
1322
+ this.helper[0].style.top = this.position.top+"px";
1323
+ }
1324
+
1325
+ //Rearrange
1326
+ for (i = this.items.length - 1; i >= 0; i--) {
1327
+
1328
+ //Cache variables and intersection, continue if no intersection
1329
+ item = this.items[i];
1330
+ itemElement = item.item[0];
1331
+ intersection = this._intersectsWithPointer(item);
1332
+ if (!intersection) {
1333
+ continue;
1334
+ }
1335
+
1336
+ // Only put the placeholder inside the current Container, skip all
1337
+ // items form other containers. This works because when moving
1338
+ // an item from one container to another the
1339
+ // currentContainer is switched before the placeholder is moved.
1340
+ //
1341
+ // Without this moving items in "sub-sortables" can cause the placeholder to jitter
1342
+ // beetween the outer and inner container.
1343
+ if (item.instance !== this.currentContainer) {
1344
+ continue;
1345
+ }
1346
+
1347
+ // cannot intersect with itself
1348
+ // no useless actions that have been done before
1349
+ // no action if the item moved is the parent of the item checked
1350
+ if (itemElement !== this.currentItem[0] &&
1351
+ this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
1352
+ !$.contains(this.placeholder[0], itemElement) &&
1353
+ (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
1354
+ ) {
1355
+
1356
+ this.direction = intersection === 1 ? "down" : "up";
1357
+
1358
+ if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
1359
+ this._rearrange(event, item);
1360
+ } else {
1361
+ break;
1362
+ }
1363
+
1364
+ this._trigger("change", event, this._uiHash());
1365
+ break;
1366
+ }
1367
+ }
1368
+
1369
+ //Post events to containers
1370
+ this._contactContainers(event);
1371
+
1372
+ //Interconnect with droppables
1373
+ if($.ui.ddmanager) {
1374
+ $.ui.ddmanager.drag(this, event);
1375
+ }
1376
+
1377
+ //Call callbacks
1378
+ this._trigger("sort", event, this._uiHash());
1379
+
1380
+ this.lastPositionAbs = this.positionAbs;
1381
+ return false;
1382
+
1383
+ },
1384
+
1385
+ _mouseStop: function(event, noPropagation) {
1386
+
1387
+ if(!event) {
1388
+ return;
1389
+ }
1390
+
1391
+ //If we are using droppables, inform the manager about the drop
1392
+ if ($.ui.ddmanager && !this.options.dropBehaviour) {
1393
+ $.ui.ddmanager.drop(this, event);
1394
+ }
1395
+
1396
+ if(this.options.revert) {
1397
+ var that = this,
1398
+ cur = this.placeholder.offset(),
1399
+ axis = this.options.axis,
1400
+ animation = {};
1401
+
1402
+ if ( !axis || axis === "x" ) {
1403
+ animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
1404
+ }
1405
+ if ( !axis || axis === "y" ) {
1406
+ animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
1407
+ }
1408
+ this.reverting = true;
1409
+ $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
1410
+ that._clear(event);
1411
+ });
1412
+ } else {
1413
+ this._clear(event, noPropagation);
1414
+ }
1415
+
1416
+ return false;
1417
+
1418
+ },
1419
+
1420
+ cancel: function() {
1421
+
1422
+ if(this.dragging) {
1423
+
1424
+ this._mouseUp({ target: null });
1425
+
1426
+ if(this.options.helper === "original") {
1427
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
1428
+ } else {
1429
+ this.currentItem.show();
1430
+ }
1431
+
1432
+ //Post deactivating events to containers
1433
+ for (var i = this.containers.length - 1; i >= 0; i--){
1434
+ this.containers[i]._trigger("deactivate", null, this._uiHash(this));
1435
+ if(this.containers[i].containerCache.over) {
1436
+ this.containers[i]._trigger("out", null, this._uiHash(this));
1437
+ this.containers[i].containerCache.over = 0;
1438
+ }
1439
+ }
1440
+
1441
+ }
1442
+
1443
+ if (this.placeholder) {
1444
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
1445
+ if(this.placeholder[0].parentNode) {
1446
+ this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
1447
+ }
1448
+ if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
1449
+ this.helper.remove();
1450
+ }
1451
+
1452
+ $.extend(this, {
1453
+ helper: null,
1454
+ dragging: false,
1455
+ reverting: false,
1456
+ _noFinalSort: null
1457
+ });
1458
+
1459
+ if(this.domPosition.prev) {
1460
+ $(this.domPosition.prev).after(this.currentItem);
1461
+ } else {
1462
+ $(this.domPosition.parent).prepend(this.currentItem);
1463
+ }
1464
+ }
1465
+
1466
+ return this;
1467
+
1468
+ },
1469
+
1470
+ serialize: function(o) {
1471
+
1472
+ var items = this._getItemsAsjQuery(o && o.connected),
1473
+ str = [];
1474
+ o = o || {};
1475
+
1476
+ $(items).each(function() {
1477
+ var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
1478
+ if (res) {
1479
+ str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
1480
+ }
1481
+ });
1482
+
1483
+ if(!str.length && o.key) {
1484
+ str.push(o.key + "=");
1485
+ }
1486
+
1487
+ return str.join("&");
1488
+
1489
+ },
1490
+
1491
+ toArray: function(o) {
1492
+
1493
+ var items = this._getItemsAsjQuery(o && o.connected),
1494
+ ret = [];
1495
+
1496
+ o = o || {};
1497
+
1498
+ items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
1499
+ return ret;
1500
+
1501
+ },
1502
+
1503
+ /* Be careful with the following core functions */
1504
+ _intersectsWith: function(item) {
1505
+
1506
+ var x1 = this.positionAbs.left,
1507
+ x2 = x1 + this.helperProportions.width,
1508
+ y1 = this.positionAbs.top,
1509
+ y2 = y1 + this.helperProportions.height,
1510
+ l = item.left,
1511
+ r = l + item.width,
1512
+ t = item.top,
1513
+ b = t + item.height,
1514
+ dyClick = this.offset.click.top,
1515
+ dxClick = this.offset.click.left,
1516
+ isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
1517
+ isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
1518
+ isOverElement = isOverElementHeight && isOverElementWidth;
1519
+
1520
+ if ( this.options.tolerance === "pointer" ||
1521
+ this.options.forcePointerForContainers ||
1522
+ (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
1523
+ ) {
1524
+ return isOverElement;
1525
+ } else {
1526
+
1527
+ return (l < x1 + (this.helperProportions.width / 2) && // Right Half
1528
+ x2 - (this.helperProportions.width / 2) < r && // Left Half
1529
+ t < y1 + (this.helperProportions.height / 2) && // Bottom Half
1530
+ y2 - (this.helperProportions.height / 2) < b ); // Top Half
1531
+
1532
+ }
1533
+ },
1534
+
1535
+ _intersectsWithPointer: function(item) {
1536
+
1537
+ var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
1538
+ isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
1539
+ isOverElement = isOverElementHeight && isOverElementWidth,
1540
+ verticalDirection = this._getDragVerticalDirection(),
1541
+ horizontalDirection = this._getDragHorizontalDirection();
1542
+
1543
+ if (!isOverElement) {
1544
+ return false;
1545
+ }
1546
+
1547
+ return this.floating ?
1548
+ ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
1549
+ : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
1550
+
1551
+ },
1552
+
1553
+ _intersectsWithSides: function(item) {
1554
+
1555
+ var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
1556
+ isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
1557
+ verticalDirection = this._getDragVerticalDirection(),
1558
+ horizontalDirection = this._getDragHorizontalDirection();
1559
+
1560
+ if (this.floating && horizontalDirection) {
1561
+ return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
1562
+ } else {
1563
+ return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
1564
+ }
1565
+
1566
+ },
1567
+
1568
+ _getDragVerticalDirection: function() {
1569
+ var delta = this.positionAbs.top - this.lastPositionAbs.top;
1570
+ return delta !== 0 && (delta > 0 ? "down" : "up");
1571
+ },
1572
+
1573
+ _getDragHorizontalDirection: function() {
1574
+ var delta = this.positionAbs.left - this.lastPositionAbs.left;
1575
+ return delta !== 0 && (delta > 0 ? "right" : "left");
1576
+ },
1577
+
1578
+ refresh: function(event) {
1579
+ this._refreshItems(event);
1580
+ this.refreshPositions();
1581
+ return this;
1582
+ },
1583
+
1584
+ _connectWith: function() {
1585
+ var options = this.options;
1586
+ return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
1587
+ },
1588
+
1589
+ _getItemsAsjQuery: function(connected) {
1590
+
1591
+ var i, j, cur, inst,
1592
+ items = [],
1593
+ queries = [],
1594
+ connectWith = this._connectWith();
1595
+
1596
+ if(connectWith && connected) {
1597
+ for (i = connectWith.length - 1; i >= 0; i--){
1598
+ cur = $(connectWith[i]);
1599
+ for ( j = cur.length - 1; j >= 0; j--){
1600
+ inst = $.data(cur[j], this.widgetFullName);
1601
+ if(inst && inst !== this && !inst.options.disabled) {
1602
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
1603
+ }
1604
+ }
1605
+ }
1606
+ }
1607
+
1608
+ queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
1609
+
1610
+ for (i = queries.length - 1; i >= 0; i--){
1611
+ queries[i][0].each(function() {
1612
+ items.push(this);
1613
+ });
1614
+ }
1615
+
1616
+ return $(items);
1617
+
1618
+ },
1619
+
1620
+ _removeCurrentsFromItems: function() {
1621
+
1622
+ var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
1623
+
1624
+ this.items = $.grep(this.items, function (item) {
1625
+ for (var j=0; j < list.length; j++) {
1626
+ if(list[j] === item.item[0]) {
1627
+ return false;
1628
+ }
1629
+ }
1630
+ return true;
1631
+ });
1632
+
1633
+ },
1634
+
1635
+ _refreshItems: function(event) {
1636
+
1637
+ this.items = [];
1638
+ this.containers = [this];
1639
+
1640
+ var i, j, cur, inst, targetData, _queries, item, queriesLength,
1641
+ items = this.items,
1642
+ queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
1643
+ connectWith = this._connectWith();
1644
+
1645
+ if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
1646
+ for (i = connectWith.length - 1; i >= 0; i--){
1647
+ cur = $(connectWith[i]);
1648
+ for (j = cur.length - 1; j >= 0; j--){
1649
+ inst = $.data(cur[j], this.widgetFullName);
1650
+ if(inst && inst !== this && !inst.options.disabled) {
1651
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
1652
+ this.containers.push(inst);
1653
+ }
1654
+ }
1655
+ }
1656
+ }
1657
+
1658
+ for (i = queries.length - 1; i >= 0; i--) {
1659
+ targetData = queries[i][1];
1660
+ _queries = queries[i][0];
1661
+
1662
+ for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
1663
+ item = $(_queries[j]);
1664
+
1665
+ item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
1666
+
1667
+ items.push({
1668
+ item: item,
1669
+ instance: targetData,
1670
+ width: 0, height: 0,
1671
+ left: 0, top: 0
1672
+ });
1673
+ }
1674
+ }
1675
+
1676
+ },
1677
+
1678
+ refreshPositions: function(fast) {
1679
+
1680
+ //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
1681
+ if(this.offsetParent && this.helper) {
1682
+ this.offset.parent = this._getParentOffset();
1683
+ }
1684
+
1685
+ var i, item, t, p;
1686
+
1687
+ for (i = this.items.length - 1; i >= 0; i--){
1688
+ item = this.items[i];
1689
+
1690
+ //We ignore calculating positions of all connected containers when we're not over them
1691
+ if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
1692
+ continue;
1693
+ }
1694
+
1695
+ t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
1696
+
1697
+ if (!fast) {
1698
+ item.width = t.outerWidth();
1699
+ item.height = t.outerHeight();
1700
+ }
1701
+
1702
+ p = t.offset();
1703
+ item.left = p.left;
1704
+ item.top = p.top;
1705
+ }
1706
+
1707
+ if(this.options.custom && this.options.custom.refreshContainers) {
1708
+ this.options.custom.refreshContainers.call(this);
1709
+ } else {
1710
+ for (i = this.containers.length - 1; i >= 0; i--){
1711
+ p = this.containers[i].element.offset();
1712
+ this.containers[i].containerCache.left = p.left;
1713
+ this.containers[i].containerCache.top = p.top;
1714
+ this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
1715
+ this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
1716
+ }
1717
+ }
1718
+
1719
+ return this;
1720
+ },
1721
+
1722
+ _createPlaceholder: function(that) {
1723
+ that = that || this;
1724
+ var className,
1725
+ o = that.options;
1726
+
1727
+ if(!o.placeholder || o.placeholder.constructor === String) {
1728
+ className = o.placeholder;
1729
+ o.placeholder = {
1730
+ element: function() {
1731
+
1732
+ var nodeName = that.currentItem[0].nodeName.toLowerCase(),
1733
+ element = $( "<" + nodeName + ">", that.document[0] )
1734
+ .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
1735
+ .removeClass("ui-sortable-helper");
1736
+
1737
+ if ( nodeName === "tr" ) {
1738
+ that.currentItem.children().each(function() {
1739
+ $( "<td>&#160;</td>", that.document[0] )
1740
+ .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
1741
+ .appendTo( element );
1742
+ });
1743
+ } else if ( nodeName === "img" ) {
1744
+ element.attr( "src", that.currentItem.attr( "src" ) );
1745
+ }
1746
+
1747
+ if ( !className ) {
1748
+ element.css( "visibility", "hidden" );
1749
+ }
1750
+
1751
+ return element;
1752
+ },
1753
+ update: function(container, p) {
1754
+
1755
+ // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
1756
+ // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
1757
+ if(className && !o.forcePlaceholderSize) {
1758
+ return;
1759
+ }
1760
+
1761
+ //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
1762
+ if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
1763
+ if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
1764
+ }
1765
+ };
1766
+ }
1767
+
1768
+ //Create the placeholder
1769
+ that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
1770
+
1771
+ //Append it after the actual current item
1772
+ that.currentItem.after(that.placeholder);
1773
+
1774
+ //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
1775
+ o.placeholder.update(that, that.placeholder);
1776
+
1777
+ },
1778
+
1779
+ _contactContainers: function(event) {
1780
+ var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
1781
+ innermostContainer = null,
1782
+ innermostIndex = null;
1783
+
1784
+ // get innermost container that intersects with item
1785
+ for (i = this.containers.length - 1; i >= 0; i--) {
1786
+
1787
+ // never consider a container that's located within the item itself
1788
+ if($.contains(this.currentItem[0], this.containers[i].element[0])) {
1789
+ continue;
1790
+ }
1791
+
1792
+ if(this._intersectsWith(this.containers[i].containerCache)) {
1793
+
1794
+ // if we've already found a container and it's more "inner" than this, then continue
1795
+ if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
1796
+ continue;
1797
+ }
1798
+
1799
+ innermostContainer = this.containers[i];
1800
+ innermostIndex = i;
1801
+
1802
+ } else {
1803
+ // container doesn't intersect. trigger "out" event if necessary
1804
+ if(this.containers[i].containerCache.over) {
1805
+ this.containers[i]._trigger("out", event, this._uiHash(this));
1806
+ this.containers[i].containerCache.over = 0;
1807
+ }
1808
+ }
1809
+
1810
+ }
1811
+
1812
+ // if no intersecting containers found, return
1813
+ if(!innermostContainer) {
1814
+ return;
1815
+ }
1816
+
1817
+ // move the item into the container if it's not there already
1818
+ if(this.containers.length === 1) {
1819
+ if (!this.containers[innermostIndex].containerCache.over) {
1820
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
1821
+ this.containers[innermostIndex].containerCache.over = 1;
1822
+ }
1823
+ } else {
1824
+
1825
+ //When entering a new container, we will find the item with the least distance and append our item near it
1826
+ dist = 10000;
1827
+ itemWithLeastDistance = null;
1828
+ floating = innermostContainer.floating || isFloating(this.currentItem);
1829
+ posProperty = floating ? "left" : "top";
1830
+ sizeProperty = floating ? "width" : "height";
1831
+ base = this.positionAbs[posProperty] + this.offset.click[posProperty];
1832
+ for (j = this.items.length - 1; j >= 0; j--) {
1833
+ if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
1834
+ continue;
1835
+ }
1836
+ if(this.items[j].item[0] === this.currentItem[0]) {
1837
+ continue;
1838
+ }
1839
+ if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
1840
+ continue;
1841
+ }
1842
+ cur = this.items[j].item.offset()[posProperty];
1843
+ nearBottom = false;
1844
+ if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
1845
+ nearBottom = true;
1846
+ cur += this.items[j][sizeProperty];
1847
+ }
1848
+
1849
+ if(Math.abs(cur - base) < dist) {
1850
+ dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
1851
+ this.direction = nearBottom ? "up": "down";
1852
+ }
1853
+ }
1854
+
1855
+ //Check if dropOnEmpty is enabled
1856
+ if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
1857
+ return;
1858
+ }
1859
+
1860
+ if(this.currentContainer === this.containers[innermostIndex]) {
1861
+ return;
1862
+ }
1863
+
1864
+ itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
1865
+ this._trigger("change", event, this._uiHash());
1866
+ this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
1867
+ this.currentContainer = this.containers[innermostIndex];
1868
+
1869
+ //Update the placeholder
1870
+ this.options.placeholder.update(this.currentContainer, this.placeholder);
1871
+
1872
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
1873
+ this.containers[innermostIndex].containerCache.over = 1;
1874
+ }
1875
+
1876
+
1877
+ },
1878
+
1879
+ _createHelper: function(event) {
1880
+
1881
+ var o = this.options,
1882
+ helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
1883
+
1884
+ //Add the helper to the DOM if that didn't happen already
1885
+ if(!helper.parents("body").length) {
1886
+ $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
1887
+ }
1888
+
1889
+ if(helper[0] === this.currentItem[0]) {
1890
+ this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
1891
+ }
1892
+
1893
+ if(!helper[0].style.width || o.forceHelperSize) {
1894
+ helper.width(this.currentItem.width());
1895
+ }
1896
+ if(!helper[0].style.height || o.forceHelperSize) {
1897
+ helper.height(this.currentItem.height());
1898
+ }
1899
+
1900
+ return helper;
1901
+
1902
+ },
1903
+
1904
+ _adjustOffsetFromHelper: function(obj) {
1905
+ if (typeof obj === "string") {
1906
+ obj = obj.split(" ");
1907
+ }
1908
+ if ($.isArray(obj)) {
1909
+ obj = {left: +obj[0], top: +obj[1] || 0};
1910
+ }
1911
+ if ("left" in obj) {
1912
+ this.offset.click.left = obj.left + this.margins.left;
1913
+ }
1914
+ if ("right" in obj) {
1915
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1916
+ }
1917
+ if ("top" in obj) {
1918
+ this.offset.click.top = obj.top + this.margins.top;
1919
+ }
1920
+ if ("bottom" in obj) {
1921
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1922
+ }
1923
+ },
1924
+
1925
+ _getParentOffset: function() {
1926
+
1927
+
1928
+ //Get the offsetParent and cache its position
1929
+ this.offsetParent = this.helper.offsetParent();
1930
+ var po = this.offsetParent.offset();
1931
+
1932
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
1933
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1934
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1935
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1936
+ if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1937
+ po.left += this.scrollParent.scrollLeft();
1938
+ po.top += this.scrollParent.scrollTop();
1939
+ }
1940
+
1941
+ // This needs to be actually done for all browsers, since pageX/pageY includes this information
1942
+ // with an ugly IE fix
1943
+ if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1944
+ po = { top: 0, left: 0 };
1945
+ }
1946
+
1947
+ return {
1948
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1949
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1950
+ };
1951
+
1952
+ },
1953
+
1954
+ _getRelativeOffset: function() {
1955
+
1956
+ if(this.cssPosition === "relative") {
1957
+ var p = this.currentItem.position();
1958
+ return {
1959
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1960
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1961
+ };
1962
+ } else {
1963
+ return { top: 0, left: 0 };
1964
+ }
1965
+
1966
+ },
1967
+
1968
+ _cacheMargins: function() {
1969
+ this.margins = {
1970
+ left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
1971
+ top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
1972
+ };
1973
+ },
1974
+
1975
+ _cacheHelperProportions: function() {
1976
+ this.helperProportions = {
1977
+ width: this.helper.outerWidth(),
1978
+ height: this.helper.outerHeight()
1979
+ };
1980
+ },
1981
+
1982
+ _setContainment: function() {
1983
+
1984
+ var ce, co, over,
1985
+ o = this.options;
1986
+ if(o.containment === "parent") {
1987
+ o.containment = this.helper[0].parentNode;
1988
+ }
1989
+ if(o.containment === "document" || o.containment === "window") {
1990
+ this.containment = [
1991
+ 0 - this.offset.relative.left - this.offset.parent.left,
1992
+ 0 - this.offset.relative.top - this.offset.parent.top,
1993
+ $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
1994
+ ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1995
+ ];
1996
+ }
1997
+
1998
+ if(!(/^(document|window|parent)$/).test(o.containment)) {
1999
+ ce = $(o.containment)[0];
2000
+ co = $(o.containment).offset();
2001
+ over = ($(ce).css("overflow") !== "hidden");
2002
+
2003
+ this.containment = [
2004
+ co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
2005
+ co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
2006
+ 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,
2007
+ 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
2008
+ ];
2009
+ }
2010
+
2011
+ },
2012
+
2013
+ _convertPositionTo: function(d, pos) {
2014
+
2015
+ if(!pos) {
2016
+ pos = this.position;
2017
+ }
2018
+ var mod = d === "absolute" ? 1 : -1,
2019
+ scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
2020
+ scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
2021
+
2022
+ return {
2023
+ top: (
2024
+ pos.top + // The absolute mouse position
2025
+ this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
2026
+ this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
2027
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
2028
+ ),
2029
+ left: (
2030
+ pos.left + // The absolute mouse position
2031
+ this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
2032
+ this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
2033
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
2034
+ )
2035
+ };
2036
+
2037
+ },
2038
+
2039
+ _generatePosition: function(event) {
2040
+
2041
+ var top, left,
2042
+ o = this.options,
2043
+ pageX = event.pageX,
2044
+ pageY = event.pageY,
2045
+ scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
2046
+
2047
+ // This is another very weird special case that only happens for relative elements:
2048
+ // 1. If the css position is relative
2049
+ // 2. and the scroll parent is the document or similar to the offset parent
2050
+ // we have to refresh the relative offset during the scroll so there are no jumps
2051
+ if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
2052
+ this.offset.relative = this._getRelativeOffset();
2053
+ }
2054
+
2055
+ /*
2056
+ * - Position constraining -
2057
+ * Constrain the position to a mix of grid, containment.
2058
+ */
2059
+
2060
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
2061
+
2062
+ if(this.containment) {
2063
+ if(event.pageX - this.offset.click.left < this.containment[0]) {
2064
+ pageX = this.containment[0] + this.offset.click.left;
2065
+ }
2066
+ if(event.pageY - this.offset.click.top < this.containment[1]) {
2067
+ pageY = this.containment[1] + this.offset.click.top;
2068
+ }
2069
+ if(event.pageX - this.offset.click.left > this.containment[2]) {
2070
+ pageX = this.containment[2] + this.offset.click.left;
2071
+ }
2072
+ if(event.pageY - this.offset.click.top > this.containment[3]) {
2073
+ pageY = this.containment[3] + this.offset.click.top;
2074
+ }
2075
+ }
2076
+
2077
+ if(o.grid) {
2078
+ top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
2079
+ 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;
2080
+
2081
+ left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
2082
+ 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;
2083
+ }
2084
+
2085
+ }
2086
+
2087
+ return {
2088
+ top: (
2089
+ pageY - // The absolute mouse position
2090
+ this.offset.click.top - // Click offset (relative to the element)
2091
+ this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
2092
+ this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
2093
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
2094
+ ),
2095
+ left: (
2096
+ pageX - // The absolute mouse position
2097
+ this.offset.click.left - // Click offset (relative to the element)
2098
+ this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
2099
+ this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
2100
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
2101
+ )
2102
+ };
2103
+
2104
+ },
2105
+
2106
+ _rearrange: function(event, i, a, hardRefresh) {
2107
+
2108
+ a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
2109
+
2110
+ //Various things done here to improve the performance:
2111
+ // 1. we create a setTimeout, that calls refreshPositions
2112
+ // 2. on the instance, we have a counter variable, that get's higher after every append
2113
+ // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
2114
+ // 4. this lets only the last addition to the timeout stack through
2115
+ this.counter = this.counter ? ++this.counter : 1;
2116
+ var counter = this.counter;
2117
+
2118
+ this._delay(function() {
2119
+ if(counter === this.counter) {
2120
+ this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
2121
+ }
2122
+ });
2123
+
2124
+ },
2125
+
2126
+ _clear: function(event, noPropagation) {
2127
+
2128
+ this.reverting = false;
2129
+ // We delay all events that have to be triggered to after the point where the placeholder has been removed and
2130
+ // everything else normalized again
2131
+ var i,
2132
+ delayedTriggers = [];
2133
+
2134
+ // We first have to update the dom position of the actual currentItem
2135
+ // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
2136
+ if(!this._noFinalSort && this.currentItem.parent().length) {
2137
+ this.placeholder.before(this.currentItem);
2138
+ }
2139
+ this._noFinalSort = null;
2140
+
2141
+ if(this.helper[0] === this.currentItem[0]) {
2142
+ for(i in this._storedCSS) {
2143
+ if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
2144
+ this._storedCSS[i] = "";
2145
+ }
2146
+ }
2147
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
2148
+ } else {
2149
+ this.currentItem.show();
2150
+ }
2151
+
2152
+ if(this.fromOutside && !noPropagation) {
2153
+ delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
2154
+ }
2155
+ if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
2156
+ delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
2157
+ }
2158
+
2159
+ // Check if the items Container has Changed and trigger appropriate
2160
+ // events.
2161
+ if (this !== this.currentContainer) {
2162
+ if(!noPropagation) {
2163
+ delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
2164
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
2165
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
2166
+ }
2167
+ }
2168
+
2169
+
2170
+ //Post events to containers
2171
+ for (i = this.containers.length - 1; i >= 0; i--){
2172
+ if(!noPropagation) {
2173
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2174
+ }
2175
+ if(this.containers[i].containerCache.over) {
2176
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2177
+ this.containers[i].containerCache.over = 0;
2178
+ }
2179
+ }
2180
+
2181
+ //Do what was originally in plugins
2182
+ if ( this.storedCursor ) {
2183
+ this.document.find( "body" ).css( "cursor", this.storedCursor );
2184
+ this.storedStylesheet.remove();
2185
+ }
2186
+ if(this._storedOpacity) {
2187
+ this.helper.css("opacity", this._storedOpacity);
2188
+ }
2189
+ if(this._storedZIndex) {
2190
+ this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
2191
+ }
2192
+
2193
+ this.dragging = false;
2194
+ if(this.cancelHelperRemoval) {
2195
+ if(!noPropagation) {
2196
+ this._trigger("beforeStop", event, this._uiHash());
2197
+ for (i=0; i < delayedTriggers.length; i++) {
2198
+ delayedTriggers[i].call(this, event);
2199
+ } //Trigger all delayed events
2200
+ this._trigger("stop", event, this._uiHash());
2201
+ }
2202
+
2203
+ this.fromOutside = false;
2204
+ return false;
2205
+ }
2206
+
2207
+ if(!noPropagation) {
2208
+ this._trigger("beforeStop", event, this._uiHash());
2209
+ }
2210
+
2211
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
2212
+ this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
2213
+
2214
+ if(this.helper[0] !== this.currentItem[0]) {
2215
+ this.helper.remove();
2216
+ }
2217
+ this.helper = null;
2218
+
2219
+ if(!noPropagation) {
2220
+ for (i=0; i < delayedTriggers.length; i++) {
2221
+ delayedTriggers[i].call(this, event);
2222
+ } //Trigger all delayed events
2223
+ this._trigger("stop", event, this._uiHash());
2224
+ }
2225
+
2226
+ this.fromOutside = false;
2227
+ return true;
2228
+
2229
+ },
2230
+
2231
+ _trigger: function() {
2232
+ if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
2233
+ this.cancel();
2234
+ }
2235
+ },
2236
+
2237
+ _uiHash: function(_inst) {
2238
+ var inst = _inst || this;
2239
+ return {
2240
+ helper: inst.helper,
2241
+ placeholder: inst.placeholder || $([]),
2242
+ position: inst.position,
2243
+ originalPosition: inst.originalPosition,
2244
+ offset: inst.positionAbs,
2245
+ item: inst.currentItem,
2246
+ sender: _inst ? _inst.element : null
2247
+ };
2248
+ }
2249
+
2250
+ });
2251
+
2252
+ })(jQuery);