better-jquery-fileupload-rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +94 -0
  3. data/Rakefile +15 -0
  4. data/app/assets/images/loading.gif +0 -0
  5. data/app/assets/images/progressbar.gif +0 -0
  6. data/app/assets/javascripts/jquery-fileupload/angularjs.js +12 -0
  7. data/app/assets/javascripts/jquery-fileupload/basic-plus.js +11 -0
  8. data/app/assets/javascripts/jquery-fileupload/basic.js +3 -0
  9. data/app/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js +120 -0
  10. data/app/assets/javascripts/jquery-fileupload/cors/jquery.xdr-transport.js +89 -0
  11. data/app/assets/javascripts/jquery-fileupload/index.js +13 -0
  12. data/app/assets/javascripts/jquery-fileupload/jquery-ui.js +13 -0
  13. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js +429 -0
  14. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js +112 -0
  15. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js +321 -0
  16. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-jquery-ui.js +155 -0
  17. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js +175 -0
  18. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js +710 -0
  19. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js +122 -0
  20. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js +112 -0
  21. data/app/assets/javascripts/jquery-fileupload/jquery.fileupload.js +1466 -0
  22. data/app/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js +217 -0
  23. data/app/assets/javascripts/jquery-fileupload/locale.js +29 -0
  24. data/app/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.js +95 -0
  25. data/app/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js +563 -0
  26. data/app/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js +1 -0
  27. data/app/assets/javascripts/jquery-fileupload/vendor/tmpl.js +87 -0
  28. data/app/assets/stylesheets/jquery.fileupload-noscript.css +22 -0
  29. data/app/assets/stylesheets/jquery.fileupload-ui-noscript.css +17 -0
  30. data/app/assets/stylesheets/jquery.fileupload-ui.css +57 -0
  31. data/app/assets/stylesheets/jquery.fileupload.css +36 -0
  32. data/lib/jquery-fileupload-rails.rb +8 -0
  33. data/lib/jquery/fileupload/rails/engine.rb +8 -0
  34. data/lib/jquery/fileupload/rails/middleware.rb +59 -0
  35. data/lib/jquery/fileupload/rails/upload.rb +3 -0
  36. data/lib/jquery/fileupload/rails/version.rb +7 -0
  37. metadata +121 -0
@@ -0,0 +1,217 @@
1
+ /*
2
+ * jQuery Iframe Transport Plugin 1.8.3
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2011, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ */
11
+
12
+ /* global define, require, window, document */
13
+
14
+ (function (factory) {
15
+ 'use strict';
16
+ if (typeof define === 'function' && define.amd) {
17
+ // Register as an anonymous AMD module:
18
+ define(['jquery'], factory);
19
+ } else if (typeof exports === 'object') {
20
+ // Node/CommonJS:
21
+ factory(require('jquery'));
22
+ } else {
23
+ // Browser globals:
24
+ factory(window.jQuery);
25
+ }
26
+ }(function ($) {
27
+ 'use strict';
28
+
29
+ // Helper variable to create unique names for the transport iframes:
30
+ var counter = 0;
31
+
32
+ // The iframe transport accepts four additional options:
33
+ // options.fileInput: a jQuery collection of file input fields
34
+ // options.paramName: the parameter name for the file form data,
35
+ // overrides the name property of the file input field(s),
36
+ // can be a string or an array of strings.
37
+ // options.formData: an array of objects with name and value properties,
38
+ // equivalent to the return data of .serializeArray(), e.g.:
39
+ // [{name: 'a', value: 1}, {name: 'b', value: 2}]
40
+ // options.initialIframeSrc: the URL of the initial iframe src,
41
+ // by default set to "javascript:false;"
42
+ $.ajaxTransport('iframe', function (options) {
43
+ if (options.async) {
44
+ // javascript:false as initial iframe src
45
+ // prevents warning popups on HTTPS in IE6:
46
+ /*jshint scripturl: true */
47
+ var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
48
+ /*jshint scripturl: false */
49
+ form,
50
+ iframe,
51
+ addParamChar;
52
+ return {
53
+ send: function (_, completeCallback) {
54
+ form = $('<form style="display:none;"></form>');
55
+ form.attr('accept-charset', options.formAcceptCharset);
56
+ addParamChar = /\?/.test(options.url) ? '&' : '?';
57
+ // XDomainRequest only supports GET and POST:
58
+ if (options.type === 'DELETE') {
59
+ options.url = options.url + addParamChar + '_method=DELETE';
60
+ options.type = 'POST';
61
+ } else if (options.type === 'PUT') {
62
+ options.url = options.url + addParamChar + '_method=PUT';
63
+ options.type = 'POST';
64
+ } else if (options.type === 'PATCH') {
65
+ options.url = options.url + addParamChar + '_method=PATCH';
66
+ options.type = 'POST';
67
+ }
68
+ // IE versions below IE8 cannot set the name property of
69
+ // elements that have already been added to the DOM,
70
+ // so we set the name along with the iframe HTML markup:
71
+ counter += 1;
72
+ iframe = $(
73
+ '<iframe src="' + initialIframeSrc +
74
+ '" name="iframe-transport-' + counter + '"></iframe>'
75
+ ).bind('load', function () {
76
+ var fileInputClones,
77
+ paramNames = $.isArray(options.paramName) ?
78
+ options.paramName : [options.paramName];
79
+ iframe
80
+ .unbind('load')
81
+ .bind('load', function () {
82
+ var response;
83
+ // Wrap in a try/catch block to catch exceptions thrown
84
+ // when trying to access cross-domain iframe contents:
85
+ try {
86
+ response = iframe.contents();
87
+ // Google Chrome and Firefox do not throw an
88
+ // exception when calling iframe.contents() on
89
+ // cross-domain requests, so we unify the response:
90
+ if (!response.length || !response[0].firstChild) {
91
+ throw new Error();
92
+ }
93
+ } catch (e) {
94
+ response = undefined;
95
+ }
96
+ // The complete callback returns the
97
+ // iframe content document as response object:
98
+ completeCallback(
99
+ 200,
100
+ 'success',
101
+ {'iframe': response}
102
+ );
103
+ // Fix for IE endless progress bar activity bug
104
+ // (happens on form submits to iframe targets):
105
+ $('<iframe src="' + initialIframeSrc + '"></iframe>')
106
+ .appendTo(form);
107
+ window.setTimeout(function () {
108
+ // Removing the form in a setTimeout call
109
+ // allows Chrome's developer tools to display
110
+ // the response result
111
+ form.remove();
112
+ }, 0);
113
+ });
114
+ form
115
+ .prop('target', iframe.prop('name'))
116
+ .prop('action', options.url)
117
+ .prop('method', options.type);
118
+ if (options.formData) {
119
+ $.each(options.formData, function (index, field) {
120
+ $('<input type="hidden"/>')
121
+ .prop('name', field.name)
122
+ .val(field.value)
123
+ .appendTo(form);
124
+ });
125
+ }
126
+ if (options.fileInput && options.fileInput.length &&
127
+ options.type === 'POST') {
128
+ fileInputClones = options.fileInput.clone();
129
+ // Insert a clone for each file input field:
130
+ options.fileInput.after(function (index) {
131
+ return fileInputClones[index];
132
+ });
133
+ if (options.paramName) {
134
+ options.fileInput.each(function (index) {
135
+ $(this).prop(
136
+ 'name',
137
+ paramNames[index] || options.paramName
138
+ );
139
+ });
140
+ }
141
+ // Appending the file input fields to the hidden form
142
+ // removes them from their original location:
143
+ form
144
+ .append(options.fileInput)
145
+ .prop('enctype', 'multipart/form-data')
146
+ // enctype must be set as encoding for IE:
147
+ .prop('encoding', 'multipart/form-data');
148
+ // Remove the HTML5 form attribute from the input(s):
149
+ options.fileInput.removeAttr('form');
150
+ }
151
+ form.submit();
152
+ // Insert the file input fields at their original location
153
+ // by replacing the clones with the originals:
154
+ if (fileInputClones && fileInputClones.length) {
155
+ options.fileInput.each(function (index, input) {
156
+ var clone = $(fileInputClones[index]);
157
+ // Restore the original name and form properties:
158
+ $(input)
159
+ .prop('name', clone.prop('name'))
160
+ .attr('form', clone.attr('form'));
161
+ clone.replaceWith(input);
162
+ });
163
+ }
164
+ });
165
+ form.append(iframe).appendTo(document.body);
166
+ },
167
+ abort: function () {
168
+ if (iframe) {
169
+ // javascript:false as iframe src aborts the request
170
+ // and prevents warning popups on HTTPS in IE6.
171
+ // concat is used to avoid the "Script URL" JSLint error:
172
+ iframe
173
+ .unbind('load')
174
+ .prop('src', initialIframeSrc);
175
+ }
176
+ if (form) {
177
+ form.remove();
178
+ }
179
+ }
180
+ };
181
+ }
182
+ });
183
+
184
+ // The iframe transport returns the iframe content document as response.
185
+ // The following adds converters from iframe to text, json, html, xml
186
+ // and script.
187
+ // Please note that the Content-Type for JSON responses has to be text/plain
188
+ // or text/html, if the browser doesn't include application/json in the
189
+ // Accept header, else IE will show a download dialog.
190
+ // The Content-Type for XML responses on the other hand has to be always
191
+ // application/xml or text/xml, so IE properly parses the XML response.
192
+ // See also
193
+ // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
194
+ $.ajaxSetup({
195
+ converters: {
196
+ 'iframe text': function (iframe) {
197
+ return iframe && $(iframe[0].body).text();
198
+ },
199
+ 'iframe json': function (iframe) {
200
+ return iframe && $.parseJSON($(iframe[0].body).text());
201
+ },
202
+ 'iframe html': function (iframe) {
203
+ return iframe && $(iframe[0].body).html();
204
+ },
205
+ 'iframe xml': function (iframe) {
206
+ var xmlDoc = iframe && iframe[0];
207
+ return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
208
+ $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
209
+ $(xmlDoc.body).html());
210
+ },
211
+ 'iframe script': function (iframe) {
212
+ return iframe && $.globalEval($(iframe[0].body).text());
213
+ }
214
+ }
215
+ });
216
+
217
+ }));
@@ -0,0 +1,29 @@
1
+ /*
2
+ * jQuery File Upload Plugin Localization Example 6.5.1
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2012, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ */
11
+
12
+ /*global window */
13
+
14
+ window.locale = {
15
+ "fileupload": {
16
+ "errors": {
17
+ "maxFileSize": "File is too big",
18
+ "minFileSize": "File is too small",
19
+ "acceptFileTypes": "Filetype not allowed",
20
+ "maxNumberOfFiles": "Max number of files exceeded",
21
+ "uploadedBytes": "Uploaded bytes exceed file size",
22
+ "emptyResult": "Empty file upload result"
23
+ },
24
+ "error": "Error",
25
+ "start": "Start",
26
+ "cancel": "Cancel",
27
+ "destroy": "Delete"
28
+ }
29
+ };
@@ -0,0 +1,95 @@
1
+ /*
2
+ * JavaScript Canvas to Blob 2.0.5
3
+ * https://github.com/blueimp/JavaScript-Canvas-to-Blob
4
+ *
5
+ * Copyright 2012, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ *
11
+ * Based on stackoverflow user Stoive's code snippet:
12
+ * http://stackoverflow.com/q/4998908
13
+ */
14
+
15
+ /*jslint nomen: true, regexp: true */
16
+ /*global window, atob, Blob, ArrayBuffer, Uint8Array, define */
17
+
18
+ (function (window) {
19
+ 'use strict';
20
+ var CanvasPrototype = window.HTMLCanvasElement &&
21
+ window.HTMLCanvasElement.prototype,
22
+ hasBlobConstructor = window.Blob && (function () {
23
+ try {
24
+ return Boolean(new Blob());
25
+ } catch (e) {
26
+ return false;
27
+ }
28
+ }()),
29
+ hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&
30
+ (function () {
31
+ try {
32
+ return new Blob([new Uint8Array(100)]).size === 100;
33
+ } catch (e) {
34
+ return false;
35
+ }
36
+ }()),
37
+ BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||
38
+ window.MozBlobBuilder || window.MSBlobBuilder,
39
+ dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&
40
+ window.ArrayBuffer && window.Uint8Array && function (dataURI) {
41
+ var byteString,
42
+ arrayBuffer,
43
+ intArray,
44
+ i,
45
+ mimeString,
46
+ bb;
47
+ if (dataURI.split(',')[0].indexOf('base64') >= 0) {
48
+ // Convert base64 to raw binary data held in a string:
49
+ byteString = atob(dataURI.split(',')[1]);
50
+ } else {
51
+ // Convert base64/URLEncoded data component to raw binary data:
52
+ byteString = decodeURIComponent(dataURI.split(',')[1]);
53
+ }
54
+ // Write the bytes of the string to an ArrayBuffer:
55
+ arrayBuffer = new ArrayBuffer(byteString.length);
56
+ intArray = new Uint8Array(arrayBuffer);
57
+ for (i = 0; i < byteString.length; i += 1) {
58
+ intArray[i] = byteString.charCodeAt(i);
59
+ }
60
+ // Separate out the mime component:
61
+ mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
62
+ // Write the ArrayBuffer (or ArrayBufferView) to a blob:
63
+ if (hasBlobConstructor) {
64
+ return new Blob(
65
+ [hasArrayBufferViewSupport ? intArray : arrayBuffer],
66
+ {type: mimeString}
67
+ );
68
+ }
69
+ bb = new BlobBuilder();
70
+ bb.append(arrayBuffer);
71
+ return bb.getBlob(mimeString);
72
+ };
73
+ if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
74
+ if (CanvasPrototype.mozGetAsFile) {
75
+ CanvasPrototype.toBlob = function (callback, type, quality) {
76
+ if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
77
+ callback(dataURLtoBlob(this.toDataURL(type, quality)));
78
+ } else {
79
+ callback(this.mozGetAsFile('blob', type));
80
+ }
81
+ };
82
+ } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
83
+ CanvasPrototype.toBlob = function (callback, type, quality) {
84
+ callback(dataURLtoBlob(this.toDataURL(type, quality)));
85
+ };
86
+ }
87
+ }
88
+ if (typeof define === 'function' && define.amd) {
89
+ define(function () {
90
+ return dataURLtoBlob;
91
+ });
92
+ } else {
93
+ window.dataURLtoBlob = dataURLtoBlob;
94
+ }
95
+ }(this));
@@ -0,0 +1,563 @@
1
+ /*! jQuery UI - v1.11.1+CommonJS - 2014-09-17
2
+ * http://jqueryui.com
3
+ * Includes: widget.js
4
+ * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
5
+
6
+ (function( factory ) {
7
+ if ( typeof define === "function" && define.amd ) {
8
+
9
+ // AMD. Register as an anonymous module.
10
+ define([ "jquery" ], factory );
11
+
12
+ } else if (typeof exports === "object") {
13
+ // Node/CommonJS:
14
+ factory(require("jquery"));
15
+
16
+ } else {
17
+
18
+ // Browser globals
19
+ factory( jQuery );
20
+ }
21
+ }(function( $ ) {
22
+ /*!
23
+ * jQuery UI Widget 1.11.1
24
+ * http://jqueryui.com
25
+ *
26
+ * Copyright 2014 jQuery Foundation and other contributors
27
+ * Released under the MIT license.
28
+ * http://jquery.org/license
29
+ *
30
+ * http://api.jqueryui.com/jQuery.widget/
31
+ */
32
+
33
+
34
+ var widget_uuid = 0,
35
+ widget_slice = Array.prototype.slice;
36
+
37
+ $.cleanData = (function( orig ) {
38
+ return function( elems ) {
39
+ var events, elem, i;
40
+ for ( i = 0; (elem = elems[i]) != null; i++ ) {
41
+ try {
42
+
43
+ // Only trigger remove when necessary to save time
44
+ events = $._data( elem, "events" );
45
+ if ( events && events.remove ) {
46
+ $( elem ).triggerHandler( "remove" );
47
+ }
48
+
49
+ // http://bugs.jquery.com/ticket/8235
50
+ } catch( e ) {}
51
+ }
52
+ orig( elems );
53
+ };
54
+ })( $.cleanData );
55
+
56
+ $.widget = function( name, base, prototype ) {
57
+ var fullName, existingConstructor, constructor, basePrototype,
58
+ // proxiedPrototype allows the provided prototype to remain unmodified
59
+ // so that it can be used as a mixin for multiple widgets (#8876)
60
+ proxiedPrototype = {},
61
+ namespace = name.split( "." )[ 0 ];
62
+
63
+ name = name.split( "." )[ 1 ];
64
+ fullName = namespace + "-" + name;
65
+
66
+ if ( !prototype ) {
67
+ prototype = base;
68
+ base = $.Widget;
69
+ }
70
+
71
+ // create selector for plugin
72
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
73
+ return !!$.data( elem, fullName );
74
+ };
75
+
76
+ $[ namespace ] = $[ namespace ] || {};
77
+ existingConstructor = $[ namespace ][ name ];
78
+ constructor = $[ namespace ][ name ] = function( options, element ) {
79
+ // allow instantiation without "new" keyword
80
+ if ( !this._createWidget ) {
81
+ return new constructor( options, element );
82
+ }
83
+
84
+ // allow instantiation without initializing for simple inheritance
85
+ // must use "new" keyword (the code above always passes args)
86
+ if ( arguments.length ) {
87
+ this._createWidget( options, element );
88
+ }
89
+ };
90
+ // extend with the existing constructor to carry over any static properties
91
+ $.extend( constructor, existingConstructor, {
92
+ version: prototype.version,
93
+ // copy the object used to create the prototype in case we need to
94
+ // redefine the widget later
95
+ _proto: $.extend( {}, prototype ),
96
+ // track widgets that inherit from this widget in case this widget is
97
+ // redefined after a widget inherits from it
98
+ _childConstructors: []
99
+ });
100
+
101
+ basePrototype = new base();
102
+ // we need to make the options hash a property directly on the new instance
103
+ // otherwise we'll modify the options hash on the prototype that we're
104
+ // inheriting from
105
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
106
+ $.each( prototype, function( prop, value ) {
107
+ if ( !$.isFunction( value ) ) {
108
+ proxiedPrototype[ prop ] = value;
109
+ return;
110
+ }
111
+ proxiedPrototype[ prop ] = (function() {
112
+ var _super = function() {
113
+ return base.prototype[ prop ].apply( this, arguments );
114
+ },
115
+ _superApply = function( args ) {
116
+ return base.prototype[ prop ].apply( this, args );
117
+ };
118
+ return function() {
119
+ var __super = this._super,
120
+ __superApply = this._superApply,
121
+ returnValue;
122
+
123
+ this._super = _super;
124
+ this._superApply = _superApply;
125
+
126
+ returnValue = value.apply( this, arguments );
127
+
128
+ this._super = __super;
129
+ this._superApply = __superApply;
130
+
131
+ return returnValue;
132
+ };
133
+ })();
134
+ });
135
+ constructor.prototype = $.widget.extend( basePrototype, {
136
+ // TODO: remove support for widgetEventPrefix
137
+ // always use the name + a colon as the prefix, e.g., draggable:start
138
+ // don't prefix for widgets that aren't DOM-based
139
+ widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
140
+ }, proxiedPrototype, {
141
+ constructor: constructor,
142
+ namespace: namespace,
143
+ widgetName: name,
144
+ widgetFullName: fullName
145
+ });
146
+
147
+ // If this widget is being redefined then we need to find all widgets that
148
+ // are inheriting from it and redefine all of them so that they inherit from
149
+ // the new version of this widget. We're essentially trying to replace one
150
+ // level in the prototype chain.
151
+ if ( existingConstructor ) {
152
+ $.each( existingConstructor._childConstructors, function( i, child ) {
153
+ var childPrototype = child.prototype;
154
+
155
+ // redefine the child widget using the same prototype that was
156
+ // originally used, but inherit from the new version of the base
157
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
158
+ });
159
+ // remove the list of existing child constructors from the old constructor
160
+ // so the old child constructors can be garbage collected
161
+ delete existingConstructor._childConstructors;
162
+ } else {
163
+ base._childConstructors.push( constructor );
164
+ }
165
+
166
+ $.widget.bridge( name, constructor );
167
+
168
+ return constructor;
169
+ };
170
+
171
+ $.widget.extend = function( target ) {
172
+ var input = widget_slice.call( arguments, 1 ),
173
+ inputIndex = 0,
174
+ inputLength = input.length,
175
+ key,
176
+ value;
177
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
178
+ for ( key in input[ inputIndex ] ) {
179
+ value = input[ inputIndex ][ key ];
180
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
181
+ // Clone objects
182
+ if ( $.isPlainObject( value ) ) {
183
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
184
+ $.widget.extend( {}, target[ key ], value ) :
185
+ // Don't extend strings, arrays, etc. with objects
186
+ $.widget.extend( {}, value );
187
+ // Copy everything else by reference
188
+ } else {
189
+ target[ key ] = value;
190
+ }
191
+ }
192
+ }
193
+ }
194
+ return target;
195
+ };
196
+
197
+ $.widget.bridge = function( name, object ) {
198
+ var fullName = object.prototype.widgetFullName || name;
199
+ $.fn[ name ] = function( options ) {
200
+ var isMethodCall = typeof options === "string",
201
+ args = widget_slice.call( arguments, 1 ),
202
+ returnValue = this;
203
+
204
+ // allow multiple hashes to be passed on init
205
+ options = !isMethodCall && args.length ?
206
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
207
+ options;
208
+
209
+ if ( isMethodCall ) {
210
+ this.each(function() {
211
+ var methodValue,
212
+ instance = $.data( this, fullName );
213
+ if ( options === "instance" ) {
214
+ returnValue = instance;
215
+ return false;
216
+ }
217
+ if ( !instance ) {
218
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
219
+ "attempted to call method '" + options + "'" );
220
+ }
221
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
222
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
223
+ }
224
+ methodValue = instance[ options ].apply( instance, args );
225
+ if ( methodValue !== instance && methodValue !== undefined ) {
226
+ returnValue = methodValue && methodValue.jquery ?
227
+ returnValue.pushStack( methodValue.get() ) :
228
+ methodValue;
229
+ return false;
230
+ }
231
+ });
232
+ } else {
233
+ this.each(function() {
234
+ var instance = $.data( this, fullName );
235
+ if ( instance ) {
236
+ instance.option( options || {} );
237
+ if ( instance._init ) {
238
+ instance._init();
239
+ }
240
+ } else {
241
+ $.data( this, fullName, new object( options, this ) );
242
+ }
243
+ });
244
+ }
245
+
246
+ return returnValue;
247
+ };
248
+ };
249
+
250
+ $.Widget = function( /* options, element */ ) {};
251
+ $.Widget._childConstructors = [];
252
+
253
+ $.Widget.prototype = {
254
+ widgetName: "widget",
255
+ widgetEventPrefix: "",
256
+ defaultElement: "<div>",
257
+ options: {
258
+ disabled: false,
259
+
260
+ // callbacks
261
+ create: null
262
+ },
263
+ _createWidget: function( options, element ) {
264
+ element = $( element || this.defaultElement || this )[ 0 ];
265
+ this.element = $( element );
266
+ this.uuid = widget_uuid++;
267
+ this.eventNamespace = "." + this.widgetName + this.uuid;
268
+ this.options = $.widget.extend( {},
269
+ this.options,
270
+ this._getCreateOptions(),
271
+ options );
272
+
273
+ this.bindings = $();
274
+ this.hoverable = $();
275
+ this.focusable = $();
276
+
277
+ if ( element !== this ) {
278
+ $.data( element, this.widgetFullName, this );
279
+ this._on( true, this.element, {
280
+ remove: function( event ) {
281
+ if ( event.target === element ) {
282
+ this.destroy();
283
+ }
284
+ }
285
+ });
286
+ this.document = $( element.style ?
287
+ // element within the document
288
+ element.ownerDocument :
289
+ // element is window or document
290
+ element.document || element );
291
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
292
+ }
293
+
294
+ this._create();
295
+ this._trigger( "create", null, this._getCreateEventData() );
296
+ this._init();
297
+ },
298
+ _getCreateOptions: $.noop,
299
+ _getCreateEventData: $.noop,
300
+ _create: $.noop,
301
+ _init: $.noop,
302
+
303
+ destroy: function() {
304
+ this._destroy();
305
+ // we can probably remove the unbind calls in 2.0
306
+ // all event bindings should go through this._on()
307
+ this.element
308
+ .unbind( this.eventNamespace )
309
+ .removeData( this.widgetFullName )
310
+ // support: jquery <1.6.3
311
+ // http://bugs.jquery.com/ticket/9413
312
+ .removeData( $.camelCase( this.widgetFullName ) );
313
+ this.widget()
314
+ .unbind( this.eventNamespace )
315
+ .removeAttr( "aria-disabled" )
316
+ .removeClass(
317
+ this.widgetFullName + "-disabled " +
318
+ "ui-state-disabled" );
319
+
320
+ // clean up events and states
321
+ this.bindings.unbind( this.eventNamespace );
322
+ this.hoverable.removeClass( "ui-state-hover" );
323
+ this.focusable.removeClass( "ui-state-focus" );
324
+ },
325
+ _destroy: $.noop,
326
+
327
+ widget: function() {
328
+ return this.element;
329
+ },
330
+
331
+ option: function( key, value ) {
332
+ var options = key,
333
+ parts,
334
+ curOption,
335
+ i;
336
+
337
+ if ( arguments.length === 0 ) {
338
+ // don't return a reference to the internal hash
339
+ return $.widget.extend( {}, this.options );
340
+ }
341
+
342
+ if ( typeof key === "string" ) {
343
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
344
+ options = {};
345
+ parts = key.split( "." );
346
+ key = parts.shift();
347
+ if ( parts.length ) {
348
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
349
+ for ( i = 0; i < parts.length - 1; i++ ) {
350
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
351
+ curOption = curOption[ parts[ i ] ];
352
+ }
353
+ key = parts.pop();
354
+ if ( arguments.length === 1 ) {
355
+ return curOption[ key ] === undefined ? null : curOption[ key ];
356
+ }
357
+ curOption[ key ] = value;
358
+ } else {
359
+ if ( arguments.length === 1 ) {
360
+ return this.options[ key ] === undefined ? null : this.options[ key ];
361
+ }
362
+ options[ key ] = value;
363
+ }
364
+ }
365
+
366
+ this._setOptions( options );
367
+
368
+ return this;
369
+ },
370
+ _setOptions: function( options ) {
371
+ var key;
372
+
373
+ for ( key in options ) {
374
+ this._setOption( key, options[ key ] );
375
+ }
376
+
377
+ return this;
378
+ },
379
+ _setOption: function( key, value ) {
380
+ this.options[ key ] = value;
381
+
382
+ if ( key === "disabled" ) {
383
+ this.widget()
384
+ .toggleClass( this.widgetFullName + "-disabled", !!value );
385
+
386
+ // If the widget is becoming disabled, then nothing is interactive
387
+ if ( value ) {
388
+ this.hoverable.removeClass( "ui-state-hover" );
389
+ this.focusable.removeClass( "ui-state-focus" );
390
+ }
391
+ }
392
+
393
+ return this;
394
+ },
395
+
396
+ enable: function() {
397
+ return this._setOptions({ disabled: false });
398
+ },
399
+ disable: function() {
400
+ return this._setOptions({ disabled: true });
401
+ },
402
+
403
+ _on: function( suppressDisabledCheck, element, handlers ) {
404
+ var delegateElement,
405
+ instance = this;
406
+
407
+ // no suppressDisabledCheck flag, shuffle arguments
408
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
409
+ handlers = element;
410
+ element = suppressDisabledCheck;
411
+ suppressDisabledCheck = false;
412
+ }
413
+
414
+ // no element argument, shuffle and use this.element
415
+ if ( !handlers ) {
416
+ handlers = element;
417
+ element = this.element;
418
+ delegateElement = this.widget();
419
+ } else {
420
+ element = delegateElement = $( element );
421
+ this.bindings = this.bindings.add( element );
422
+ }
423
+
424
+ $.each( handlers, function( event, handler ) {
425
+ function handlerProxy() {
426
+ // allow widgets to customize the disabled handling
427
+ // - disabled as an array instead of boolean
428
+ // - disabled class as method for disabling individual parts
429
+ if ( !suppressDisabledCheck &&
430
+ ( instance.options.disabled === true ||
431
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
432
+ return;
433
+ }
434
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
435
+ .apply( instance, arguments );
436
+ }
437
+
438
+ // copy the guid so direct unbinding works
439
+ if ( typeof handler !== "string" ) {
440
+ handlerProxy.guid = handler.guid =
441
+ handler.guid || handlerProxy.guid || $.guid++;
442
+ }
443
+
444
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
445
+ eventName = match[1] + instance.eventNamespace,
446
+ selector = match[2];
447
+ if ( selector ) {
448
+ delegateElement.delegate( selector, eventName, handlerProxy );
449
+ } else {
450
+ element.bind( eventName, handlerProxy );
451
+ }
452
+ });
453
+ },
454
+
455
+ _off: function( element, eventName ) {
456
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
457
+ element.unbind( eventName ).undelegate( eventName );
458
+ },
459
+
460
+ _delay: function( handler, delay ) {
461
+ function handlerProxy() {
462
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
463
+ .apply( instance, arguments );
464
+ }
465
+ var instance = this;
466
+ return setTimeout( handlerProxy, delay || 0 );
467
+ },
468
+
469
+ _hoverable: function( element ) {
470
+ this.hoverable = this.hoverable.add( element );
471
+ this._on( element, {
472
+ mouseenter: function( event ) {
473
+ $( event.currentTarget ).addClass( "ui-state-hover" );
474
+ },
475
+ mouseleave: function( event ) {
476
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
477
+ }
478
+ });
479
+ },
480
+
481
+ _focusable: function( element ) {
482
+ this.focusable = this.focusable.add( element );
483
+ this._on( element, {
484
+ focusin: function( event ) {
485
+ $( event.currentTarget ).addClass( "ui-state-focus" );
486
+ },
487
+ focusout: function( event ) {
488
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
489
+ }
490
+ });
491
+ },
492
+
493
+ _trigger: function( type, event, data ) {
494
+ var prop, orig,
495
+ callback = this.options[ type ];
496
+
497
+ data = data || {};
498
+ event = $.Event( event );
499
+ event.type = ( type === this.widgetEventPrefix ?
500
+ type :
501
+ this.widgetEventPrefix + type ).toLowerCase();
502
+ // the original event may come from any element
503
+ // so we need to reset the target on the new event
504
+ event.target = this.element[ 0 ];
505
+
506
+ // copy original event properties over to the new event
507
+ orig = event.originalEvent;
508
+ if ( orig ) {
509
+ for ( prop in orig ) {
510
+ if ( !( prop in event ) ) {
511
+ event[ prop ] = orig[ prop ];
512
+ }
513
+ }
514
+ }
515
+
516
+ this.element.trigger( event, data );
517
+ return !( $.isFunction( callback ) &&
518
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
519
+ event.isDefaultPrevented() );
520
+ }
521
+ };
522
+
523
+ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
524
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
525
+ if ( typeof options === "string" ) {
526
+ options = { effect: options };
527
+ }
528
+ var hasOptions,
529
+ effectName = !options ?
530
+ method :
531
+ options === true || typeof options === "number" ?
532
+ defaultEffect :
533
+ options.effect || defaultEffect;
534
+ options = options || {};
535
+ if ( typeof options === "number" ) {
536
+ options = { duration: options };
537
+ }
538
+ hasOptions = !$.isEmptyObject( options );
539
+ options.complete = callback;
540
+ if ( options.delay ) {
541
+ element.delay( options.delay );
542
+ }
543
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
544
+ element[ method ]( options );
545
+ } else if ( effectName !== method && element[ effectName ] ) {
546
+ element[ effectName ]( options.duration, options.easing, callback );
547
+ } else {
548
+ element.queue(function( next ) {
549
+ $( this )[ method ]();
550
+ if ( callback ) {
551
+ callback.call( element[ 0 ] );
552
+ }
553
+ next();
554
+ });
555
+ }
556
+ };
557
+ });
558
+
559
+ var widget = $.widget;
560
+
561
+
562
+
563
+ }));