s3_cors_fileupload 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.document +5 -0
  2. data/.gitignore +51 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +14 -0
  5. data/Gemfile.lock +39 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +104 -0
  8. data/Rakefile +58 -0
  9. data/lib/generators/s3_cors_fileupload/install/USAGE +17 -0
  10. data/lib/generators/s3_cors_fileupload/install/install_generator.rb +51 -0
  11. data/lib/generators/s3_cors_fileupload/install/templates/amazon_s3.yml +17 -0
  12. data/lib/generators/s3_cors_fileupload/install/templates/create_source_files.rb +14 -0
  13. data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads.js +94 -0
  14. data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads_controller.rb +90 -0
  15. data/lib/generators/s3_cors_fileupload/install/templates/source_file.rb +53 -0
  16. data/lib/generators/s3_cors_fileupload/install/templates/views/_template_download.html.erb +29 -0
  17. data/lib/generators/s3_cors_fileupload/install/templates/views/_template_upload.html.erb +31 -0
  18. data/lib/generators/s3_cors_fileupload/install/templates/views/_template_uploaded.html.erb +25 -0
  19. data/lib/generators/s3_cors_fileupload/install/templates/views/index.html.erb +43 -0
  20. data/lib/s3_cors_fileupload.rb +2 -0
  21. data/lib/s3_cors_fileupload/rails.rb +8 -0
  22. data/lib/s3_cors_fileupload/rails/config.rb +27 -0
  23. data/lib/s3_cors_fileupload/rails/engine.rb +6 -0
  24. data/lib/s3_cors_fileupload/rails/form_helper.rb +91 -0
  25. data/lib/s3_cors_fileupload/rails/policy_helper.rb +48 -0
  26. data/lib/s3_cors_fileupload/version.rb +5 -0
  27. data/s3_cors_fileupload.gemspec +35 -0
  28. data/spec/s3_cors_fileupload/version_spec.rb +17 -0
  29. data/spec/s3_cors_fileupload_spec.rb +9 -0
  30. data/spec/spec_helper.rb +16 -0
  31. data/vendor/assets/images/loading.gif +0 -0
  32. data/vendor/assets/images/progressbar.gif +0 -0
  33. data/vendor/assets/javascripts/s3_cors_fileupload/index.js +6 -0
  34. data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload-ui.js +732 -0
  35. data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload.js +1106 -0
  36. data/vendor/assets/javascripts/s3_cors_fileupload/jquery.iframe-transport.js +172 -0
  37. data/vendor/assets/javascripts/s3_cors_fileupload/vendor/jquery.ui.widget.js +511 -0
  38. data/vendor/assets/javascripts/s3_cors_fileupload/vendor/load-image.js +122 -0
  39. data/vendor/assets/javascripts/s3_cors_fileupload/vendor/tmpl.js +87 -0
  40. data/vendor/assets/stylesheets/jquery.fileupload-ui.css.erb +85 -0
  41. metadata +205 -0
@@ -0,0 +1,172 @@
1
+ /*
2
+ * jQuery Iframe Transport Plugin 1.5
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
+ /*jslint unparam: true, nomen: true */
13
+ /*global define, window, document */
14
+
15
+ (function (factory) {
16
+ 'use strict';
17
+ if (typeof define === 'function' && define.amd) {
18
+ // Register as an anonymous AMD module:
19
+ define(['jquery'], factory);
20
+ } else {
21
+ // Browser globals:
22
+ factory(window.jQuery);
23
+ }
24
+ }(function ($) {
25
+ 'use strict';
26
+
27
+ // Helper variable to create unique names for the transport iframes:
28
+ var counter = 0;
29
+
30
+ // The iframe transport accepts three additional options:
31
+ // options.fileInput: a jQuery collection of file input fields
32
+ // options.paramName: the parameter name for the file form data,
33
+ // overrides the name property of the file input field(s),
34
+ // can be a string or an array of strings.
35
+ // options.formData: an array of objects with name and value properties,
36
+ // equivalent to the return data of .serializeArray(), e.g.:
37
+ // [{name: 'a', value: 1}, {name: 'b', value: 2}]
38
+ $.ajaxTransport('iframe', function (options) {
39
+ if (options.async && (options.type === 'POST' || options.type === 'GET')) {
40
+ var form,
41
+ iframe;
42
+ return {
43
+ send: function (_, completeCallback) {
44
+ form = $('<form style="display:none;"></form>');
45
+ form.attr('accept-charset', options.formAcceptCharset);
46
+ // javascript:false as initial iframe src
47
+ // prevents warning popups on HTTPS in IE6.
48
+ // IE versions below IE8 cannot set the name property of
49
+ // elements that have already been added to the DOM,
50
+ // so we set the name along with the iframe HTML markup:
51
+ iframe = $(
52
+ '<iframe src="javascript:false;" name="iframe-transport-' +
53
+ (counter += 1) + '"></iframe>'
54
+ ).bind('load', function () {
55
+ var fileInputClones,
56
+ paramNames = $.isArray(options.paramName) ?
57
+ options.paramName : [options.paramName];
58
+ iframe
59
+ .unbind('load')
60
+ .bind('load', function () {
61
+ var response;
62
+ // Wrap in a try/catch block to catch exceptions thrown
63
+ // when trying to access cross-domain iframe contents:
64
+ try {
65
+ response = iframe.contents();
66
+ // Google Chrome and Firefox do not throw an
67
+ // exception when calling iframe.contents() on
68
+ // cross-domain requests, so we unify the response:
69
+ if (!response.length || !response[0].firstChild) {
70
+ throw new Error();
71
+ }
72
+ } catch (e) {
73
+ response = undefined;
74
+ }
75
+ // The complete callback returns the
76
+ // iframe content document as response object:
77
+ completeCallback(
78
+ 200,
79
+ 'success',
80
+ {'iframe': response}
81
+ );
82
+ // Fix for IE endless progress bar activity bug
83
+ // (happens on form submits to iframe targets):
84
+ $('<iframe src="javascript:false;"></iframe>')
85
+ .appendTo(form);
86
+ form.remove();
87
+ });
88
+ form
89
+ .prop('target', iframe.prop('name'))
90
+ .prop('action', options.url)
91
+ .prop('method', options.type);
92
+ if (options.formData) {
93
+ $.each(options.formData, function (index, field) {
94
+ $('<input type="hidden"/>')
95
+ .prop('name', field.name)
96
+ .val(field.value)
97
+ .appendTo(form);
98
+ });
99
+ }
100
+ if (options.fileInput && options.fileInput.length &&
101
+ options.type === 'POST') {
102
+ fileInputClones = options.fileInput.clone();
103
+ // Insert a clone for each file input field:
104
+ options.fileInput.after(function (index) {
105
+ return fileInputClones[index];
106
+ });
107
+ if (options.paramName) {
108
+ options.fileInput.each(function (index) {
109
+ $(this).prop(
110
+ 'name',
111
+ paramNames[index] || options.paramName
112
+ );
113
+ });
114
+ }
115
+ // Appending the file input fields to the hidden form
116
+ // removes them from their original location:
117
+ form
118
+ .append(options.fileInput)
119
+ .prop('enctype', 'multipart/form-data')
120
+ // enctype must be set as encoding for IE:
121
+ .prop('encoding', 'multipart/form-data');
122
+ }
123
+ form.submit();
124
+ // Insert the file input fields at their original location
125
+ // by replacing the clones with the originals:
126
+ if (fileInputClones && fileInputClones.length) {
127
+ options.fileInput.each(function (index, input) {
128
+ var clone = $(fileInputClones[index]);
129
+ $(input).prop('name', clone.prop('name'));
130
+ clone.replaceWith(input);
131
+ });
132
+ }
133
+ });
134
+ form.append(iframe).appendTo(document.body);
135
+ },
136
+ abort: function () {
137
+ if (iframe) {
138
+ // javascript:false as iframe src aborts the request
139
+ // and prevents warning popups on HTTPS in IE6.
140
+ // concat is used to avoid the "Script URL" JSLint error:
141
+ iframe
142
+ .unbind('load')
143
+ .prop('src', 'javascript'.concat(':false;'));
144
+ }
145
+ if (form) {
146
+ form.remove();
147
+ }
148
+ }
149
+ };
150
+ }
151
+ });
152
+
153
+ // The iframe transport returns the iframe content document as response.
154
+ // The following adds converters from iframe to text, json, html, and script:
155
+ $.ajaxSetup({
156
+ converters: {
157
+ 'iframe text': function (iframe) {
158
+ return $(iframe[0].body).text();
159
+ },
160
+ 'iframe json': function (iframe) {
161
+ return $.parseJSON($(iframe[0].body).text());
162
+ },
163
+ 'iframe html': function (iframe) {
164
+ return $(iframe[0].body).html();
165
+ },
166
+ 'iframe script': function (iframe) {
167
+ return $.globalEval($(iframe[0].body).text());
168
+ }
169
+ }
170
+ });
171
+
172
+ }));
@@ -0,0 +1,511 @@
1
+ /*
2
+ * jQuery UI Widget 1.9.0+amd
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2012 jQuery Foundation and other contributors
6
+ * Released under the MIT license.
7
+ * http://jquery.org/license
8
+ *
9
+ * http://api.jqueryui.com/jQuery.widget/
10
+ */
11
+
12
+ (function (factory) {
13
+ if (typeof define === "function" && define.amd) {
14
+ // Register as an anonymous AMD module:
15
+ define(["jquery"], factory);
16
+ } else {
17
+ // Browser globals:
18
+ factory(jQuery);
19
+ }
20
+ }(function( $, undefined ) {
21
+
22
+ var uuid = 0,
23
+ slice = Array.prototype.slice,
24
+ _cleanData = $.cleanData;
25
+ $.cleanData = function( elems ) {
26
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
27
+ try {
28
+ $( elem ).triggerHandler( "remove" );
29
+ // http://bugs.jquery.com/ticket/8235
30
+ } catch( e ) {}
31
+ }
32
+ _cleanData( elems );
33
+ };
34
+
35
+ $.widget = function( name, base, prototype ) {
36
+ var fullName, existingConstructor, constructor, basePrototype,
37
+ namespace = name.split( "." )[ 0 ];
38
+
39
+ name = name.split( "." )[ 1 ];
40
+ fullName = namespace + "-" + name;
41
+
42
+ if ( !prototype ) {
43
+ prototype = base;
44
+ base = $.Widget;
45
+ }
46
+
47
+ // create selector for plugin
48
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
49
+ return !!$.data( elem, fullName );
50
+ };
51
+
52
+ $[ namespace ] = $[ namespace ] || {};
53
+ existingConstructor = $[ namespace ][ name ];
54
+ constructor = $[ namespace ][ name ] = function( options, element ) {
55
+ // allow instantiation without "new" keyword
56
+ if ( !this._createWidget ) {
57
+ return new constructor( options, element );
58
+ }
59
+
60
+ // allow instantiation without initializing for simple inheritance
61
+ // must use "new" keyword (the code above always passes args)
62
+ if ( arguments.length ) {
63
+ this._createWidget( options, element );
64
+ }
65
+ };
66
+ // extend with the existing constructor to carry over any static properties
67
+ $.extend( constructor, existingConstructor, {
68
+ version: prototype.version,
69
+ // copy the object used to create the prototype in case we need to
70
+ // redefine the widget later
71
+ _proto: $.extend( {}, prototype ),
72
+ // track widgets that inherit from this widget in case this widget is
73
+ // redefined after a widget inherits from it
74
+ _childConstructors: []
75
+ });
76
+
77
+ basePrototype = new base();
78
+ // we need to make the options hash a property directly on the new instance
79
+ // otherwise we'll modify the options hash on the prototype that we're
80
+ // inheriting from
81
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
82
+ $.each( prototype, function( prop, value ) {
83
+ if ( $.isFunction( value ) ) {
84
+ prototype[ prop ] = (function() {
85
+ var _super = function() {
86
+ return base.prototype[ prop ].apply( this, arguments );
87
+ },
88
+ _superApply = function( args ) {
89
+ return base.prototype[ prop ].apply( this, args );
90
+ };
91
+ return function() {
92
+ var __super = this._super,
93
+ __superApply = this._superApply,
94
+ returnValue;
95
+
96
+ this._super = _super;
97
+ this._superApply = _superApply;
98
+
99
+ returnValue = value.apply( this, arguments );
100
+
101
+ this._super = __super;
102
+ this._superApply = __superApply;
103
+
104
+ return returnValue;
105
+ };
106
+ })();
107
+ }
108
+ });
109
+ constructor.prototype = $.widget.extend( basePrototype, {
110
+ // TODO: remove support for widgetEventPrefix
111
+ // always use the name + a colon as the prefix, e.g., draggable:start
112
+ // don't prefix for widgets that aren't DOM-based
113
+ widgetEventPrefix: name
114
+ }, prototype, {
115
+ constructor: constructor,
116
+ namespace: namespace,
117
+ widgetName: name,
118
+ // TODO remove widgetBaseClass, see #8155
119
+ widgetBaseClass: fullName,
120
+ widgetFullName: fullName
121
+ });
122
+
123
+ // If this widget is being redefined then we need to find all widgets that
124
+ // are inheriting from it and redefine all of them so that they inherit from
125
+ // the new version of this widget. We're essentially trying to replace one
126
+ // level in the prototype chain.
127
+ if ( existingConstructor ) {
128
+ $.each( existingConstructor._childConstructors, function( i, child ) {
129
+ var childPrototype = child.prototype;
130
+
131
+ // redefine the child widget using the same prototype that was
132
+ // originally used, but inherit from the new version of the base
133
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
134
+ });
135
+ // remove the list of existing child constructors from the old constructor
136
+ // so the old child constructors can be garbage collected
137
+ delete existingConstructor._childConstructors;
138
+ } else {
139
+ base._childConstructors.push( constructor );
140
+ }
141
+
142
+ $.widget.bridge( name, constructor );
143
+ };
144
+
145
+ $.widget.extend = function( target ) {
146
+ var input = slice.call( arguments, 1 ),
147
+ inputIndex = 0,
148
+ inputLength = input.length,
149
+ key,
150
+ value;
151
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
152
+ for ( key in input[ inputIndex ] ) {
153
+ value = input[ inputIndex ][ key ];
154
+ if (input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
155
+ target[ key ] = $.isPlainObject( value ) ? $.widget.extend( {}, target[ key ], value ) : value;
156
+ }
157
+ }
158
+ }
159
+ return target;
160
+ };
161
+
162
+ $.widget.bridge = function( name, object ) {
163
+ var fullName = object.prototype.widgetFullName;
164
+ $.fn[ name ] = function( options ) {
165
+ var isMethodCall = typeof options === "string",
166
+ args = slice.call( arguments, 1 ),
167
+ returnValue = this;
168
+
169
+ // allow multiple hashes to be passed on init
170
+ options = !isMethodCall && args.length ?
171
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
172
+ options;
173
+
174
+ if ( isMethodCall ) {
175
+ this.each(function() {
176
+ var methodValue,
177
+ instance = $.data( this, fullName );
178
+ if ( !instance ) {
179
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
180
+ "attempted to call method '" + options + "'" );
181
+ }
182
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
183
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
184
+ }
185
+ methodValue = instance[ options ].apply( instance, args );
186
+ if ( methodValue !== instance && methodValue !== undefined ) {
187
+ returnValue = methodValue && methodValue.jquery ?
188
+ returnValue.pushStack( methodValue.get() ) :
189
+ methodValue;
190
+ return false;
191
+ }
192
+ });
193
+ } else {
194
+ this.each(function() {
195
+ var instance = $.data( this, fullName );
196
+ if ( instance ) {
197
+ instance.option( options || {} )._init();
198
+ } else {
199
+ new object( options, this );
200
+ }
201
+ });
202
+ }
203
+
204
+ return returnValue;
205
+ };
206
+ };
207
+
208
+ $.Widget = function( options, element ) {};
209
+ $.Widget._childConstructors = [];
210
+
211
+ $.Widget.prototype = {
212
+ widgetName: "widget",
213
+ widgetEventPrefix: "",
214
+ defaultElement: "<div>",
215
+ options: {
216
+ disabled: false,
217
+
218
+ // callbacks
219
+ create: null
220
+ },
221
+ _createWidget: function( options, element ) {
222
+ element = $( element || this.defaultElement || this )[ 0 ];
223
+ this.element = $( element );
224
+ this.uuid = uuid++;
225
+ this.eventNamespace = "." + this.widgetName + this.uuid;
226
+ this.options = $.widget.extend( {},
227
+ this.options,
228
+ this._getCreateOptions(),
229
+ options );
230
+
231
+ this.bindings = $();
232
+ this.hoverable = $();
233
+ this.focusable = $();
234
+
235
+ if ( element !== this ) {
236
+ // 1.9 BC for #7810
237
+ // TODO remove dual storage
238
+ $.data( element, this.widgetName, this );
239
+ $.data( element, this.widgetFullName, this );
240
+ this._on({ remove: "destroy" });
241
+ this.document = $( element.style ?
242
+ // element within the document
243
+ element.ownerDocument :
244
+ // element is window or document
245
+ element.document || element );
246
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
247
+ }
248
+
249
+ this._create();
250
+ this._trigger( "create", null, this._getCreateEventData() );
251
+ this._init();
252
+ },
253
+ _getCreateOptions: $.noop,
254
+ _getCreateEventData: $.noop,
255
+ _create: $.noop,
256
+ _init: $.noop,
257
+
258
+ destroy: function() {
259
+ this._destroy();
260
+ // we can probably remove the unbind calls in 2.0
261
+ // all event bindings should go through this._on()
262
+ this.element
263
+ .unbind( this.eventNamespace )
264
+ // 1.9 BC for #7810
265
+ // TODO remove dual storage
266
+ .removeData( this.widgetName )
267
+ .removeData( this.widgetFullName )
268
+ // support: jquery <1.6.3
269
+ // http://bugs.jquery.com/ticket/9413
270
+ .removeData( $.camelCase( this.widgetFullName ) );
271
+ this.widget()
272
+ .unbind( this.eventNamespace )
273
+ .removeAttr( "aria-disabled" )
274
+ .removeClass(
275
+ this.widgetFullName + "-disabled " +
276
+ "ui-state-disabled" );
277
+
278
+ // clean up events and states
279
+ this.bindings.unbind( this.eventNamespace );
280
+ this.hoverable.removeClass( "ui-state-hover" );
281
+ this.focusable.removeClass( "ui-state-focus" );
282
+ },
283
+ _destroy: $.noop,
284
+
285
+ widget: function() {
286
+ return this.element;
287
+ },
288
+
289
+ option: function( key, value ) {
290
+ var options = key,
291
+ parts,
292
+ curOption,
293
+ i;
294
+
295
+ if ( arguments.length === 0 ) {
296
+ // don't return a reference to the internal hash
297
+ return $.widget.extend( {}, this.options );
298
+ }
299
+
300
+ if ( typeof key === "string" ) {
301
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
302
+ options = {};
303
+ parts = key.split( "." );
304
+ key = parts.shift();
305
+ if ( parts.length ) {
306
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
307
+ for ( i = 0; i < parts.length - 1; i++ ) {
308
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
309
+ curOption = curOption[ parts[ i ] ];
310
+ }
311
+ key = parts.pop();
312
+ if ( value === undefined ) {
313
+ return curOption[ key ] === undefined ? null : curOption[ key ];
314
+ }
315
+ curOption[ key ] = value;
316
+ } else {
317
+ if ( value === undefined ) {
318
+ return this.options[ key ] === undefined ? null : this.options[ key ];
319
+ }
320
+ options[ key ] = value;
321
+ }
322
+ }
323
+
324
+ this._setOptions( options );
325
+
326
+ return this;
327
+ },
328
+ _setOptions: function( options ) {
329
+ var key;
330
+
331
+ for ( key in options ) {
332
+ this._setOption( key, options[ key ] );
333
+ }
334
+
335
+ return this;
336
+ },
337
+ _setOption: function( key, value ) {
338
+ this.options[ key ] = value;
339
+
340
+ if ( key === "disabled" ) {
341
+ this.widget()
342
+ .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
343
+ .attr( "aria-disabled", value );
344
+ this.hoverable.removeClass( "ui-state-hover" );
345
+ this.focusable.removeClass( "ui-state-focus" );
346
+ }
347
+
348
+ return this;
349
+ },
350
+
351
+ enable: function() {
352
+ return this._setOption( "disabled", false );
353
+ },
354
+ disable: function() {
355
+ return this._setOption( "disabled", true );
356
+ },
357
+
358
+ _on: function( element, handlers ) {
359
+ // no element argument, shuffle and use this.element
360
+ if ( !handlers ) {
361
+ handlers = element;
362
+ element = this.element;
363
+ } else {
364
+ // accept selectors, DOM elements
365
+ element = $( element );
366
+ this.bindings = this.bindings.add( element );
367
+ }
368
+
369
+ var instance = this;
370
+ $.each( handlers, function( event, handler ) {
371
+ function handlerProxy() {
372
+ // allow widgets to customize the disabled handling
373
+ // - disabled as an array instead of boolean
374
+ // - disabled class as method for disabling individual parts
375
+ if ( instance.options.disabled === true ||
376
+ $( this ).hasClass( "ui-state-disabled" ) ) {
377
+ return;
378
+ }
379
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
380
+ .apply( instance, arguments );
381
+ }
382
+
383
+ // copy the guid so direct unbinding works
384
+ if ( typeof handler !== "string" ) {
385
+ handlerProxy.guid = handler.guid =
386
+ handler.guid || handlerProxy.guid || $.guid++;
387
+ }
388
+
389
+ var match = event.match( /^(\w+)\s*(.*)$/ ),
390
+ eventName = match[1] + instance.eventNamespace,
391
+ selector = match[2];
392
+ if ( selector ) {
393
+ instance.widget().delegate( selector, eventName, handlerProxy );
394
+ } else {
395
+ element.bind( eventName, handlerProxy );
396
+ }
397
+ });
398
+ },
399
+
400
+ _off: function( element, eventName ) {
401
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
402
+ element.unbind( eventName ).undelegate( eventName );
403
+ },
404
+
405
+ _delay: function( handler, delay ) {
406
+ function handlerProxy() {
407
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
408
+ .apply( instance, arguments );
409
+ }
410
+ var instance = this;
411
+ return setTimeout( handlerProxy, delay || 0 );
412
+ },
413
+
414
+ _hoverable: function( element ) {
415
+ this.hoverable = this.hoverable.add( element );
416
+ this._on( element, {
417
+ mouseenter: function( event ) {
418
+ $( event.currentTarget ).addClass( "ui-state-hover" );
419
+ },
420
+ mouseleave: function( event ) {
421
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
422
+ }
423
+ });
424
+ },
425
+
426
+ _focusable: function( element ) {
427
+ this.focusable = this.focusable.add( element );
428
+ this._on( element, {
429
+ focusin: function( event ) {
430
+ $( event.currentTarget ).addClass( "ui-state-focus" );
431
+ },
432
+ focusout: function( event ) {
433
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
434
+ }
435
+ });
436
+ },
437
+
438
+ _trigger: function( type, event, data ) {
439
+ var prop, orig,
440
+ callback = this.options[ type ];
441
+
442
+ data = data || {};
443
+ event = $.Event( event );
444
+ event.type = ( type === this.widgetEventPrefix ?
445
+ type :
446
+ this.widgetEventPrefix + type ).toLowerCase();
447
+ // the original event may come from any element
448
+ // so we need to reset the target on the new event
449
+ event.target = this.element[ 0 ];
450
+
451
+ // copy original event properties over to the new event
452
+ orig = event.originalEvent;
453
+ if ( orig ) {
454
+ for ( prop in orig ) {
455
+ if ( !( prop in event ) ) {
456
+ event[ prop ] = orig[ prop ];
457
+ }
458
+ }
459
+ }
460
+
461
+ this.element.trigger( event, data );
462
+ return !( $.isFunction( callback ) &&
463
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
464
+ event.isDefaultPrevented() );
465
+ }
466
+ };
467
+
468
+ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
469
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
470
+ if ( typeof options === "string" ) {
471
+ options = { effect: options };
472
+ }
473
+ var hasOptions,
474
+ effectName = !options ?
475
+ method :
476
+ options === true || typeof options === "number" ?
477
+ defaultEffect :
478
+ options.effect || defaultEffect;
479
+ options = options || {};
480
+ if ( typeof options === "number" ) {
481
+ options = { duration: options };
482
+ }
483
+ hasOptions = !$.isEmptyObject( options );
484
+ options.complete = callback;
485
+ if ( options.delay ) {
486
+ element.delay( options.delay );
487
+ }
488
+ if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {
489
+ element[ method ]( options );
490
+ } else if ( effectName !== method && element[ effectName ] ) {
491
+ element[ effectName ]( options.duration, options.easing, callback );
492
+ } else {
493
+ element.queue(function( next ) {
494
+ $( this )[ method ]();
495
+ if ( callback ) {
496
+ callback.call( element[ 0 ] );
497
+ }
498
+ next();
499
+ });
500
+ }
501
+ };
502
+ });
503
+
504
+ // DEPRECATED
505
+ if ( $.uiBackCompat !== false ) {
506
+ $.Widget.prototype._getCreateOptions = function() {
507
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
508
+ };
509
+ }
510
+
511
+ }));