Merge "SpecialMovepage: Convert form to use OOUI controls"
[lhc/web/wiklou.git] / resources / src / jquery / jquery.expandableField.js
1 /**
2 * This plugin provides functionality to expand a text box on focus to double it's current width
3 *
4 * Usage:
5 *
6 * Set options:
7 * $('#textbox').expandableField( { option1: value1, option2: value2 } );
8 * $('#textbox').expandableField( option, value );
9 * Get option:
10 * value = $('#textbox').expandableField( option );
11 * Initialize:
12 * $('#textbox').expandableField();
13 *
14 * Options:
15 *
16 */
17 ( function ( $ ) {
18
19 $.expandableField = {
20 /**
21 * Expand the field, make the callback
22 */
23 expandField: function ( e, context ) {
24 context.config.beforeExpand.call( context.data.$field, context );
25 context.data.$field
26 .animate( { width: context.data.expandedWidth }, 'fast', function () {
27 context.config.afterExpand.call( this, context );
28 } );
29 },
30 /**
31 * Condense the field, make the callback
32 */
33 condenseField: function ( e, context ) {
34 context.config.beforeCondense.call( context.data.$field, context );
35 context.data.$field
36 .animate( { width: context.data.condensedWidth }, 'fast', function () {
37 context.config.afterCondense.call( this, context );
38 } );
39 },
40 /**
41 * Sets the value of a property, and updates the widget accordingly
42 *
43 * @param {String} property Name of property
44 * @param {Mixed} value Value to set property with
45 */
46 configure: function ( context, property, value ) {
47 // TODO: Validate creation using fallback values
48 context.config[ property ] = value;
49 }
50
51 };
52
53 $.fn.expandableField = function () {
54
55 // Multi-context fields
56 var returnValue,
57 args = arguments;
58
59 $( this ).each( function () {
60 var key, context, timeout;
61
62 /* Construction / Loading */
63
64 context = $( this ).data( 'expandableField-context' );
65
66 // TODO: Do we need to check both null and undefined?
67 if ( context === undefined || context === null ) {
68 context = {
69 config: {
70 // callback function for before collapse
71 beforeCondense: function () {},
72
73 // callback function for before expand
74 beforeExpand: function () {},
75
76 // callback function for after collapse
77 afterCondense: function () {},
78
79 // callback function for after expand
80 afterExpand: function () {},
81
82 // Whether the field should expand to the left or the right -- defaults to left
83 expandToLeft: true
84 }
85 };
86 }
87
88 /* API */
89 // Handle various calling styles
90 if ( args.length > 0 ) {
91 if ( typeof args[ 0 ] === 'object' ) {
92 // Apply set of properties
93 for ( key in args[ 0 ] ) {
94 $.expandableField.configure( context, key, args[ 0 ][ key ] );
95 }
96 } else if ( typeof args[ 0 ] === 'string' ) {
97 if ( args.length > 1 ) {
98 // Set property values
99 $.expandableField.configure( context, args[ 0 ], args[ 1 ] );
100
101 // TODO: Do we need to check both null and undefined?
102 } else if ( returnValue === null || returnValue === undefined ) {
103 // Get property values, but don't give access to internal data - returns only the first
104 returnValue = ( args[ 0 ] in context.config ? undefined : context.config[ args[ 0 ] ] );
105 }
106 }
107 }
108
109 /* Initialization */
110
111 if ( context.data === undefined ) {
112 context.data = {
113 // The width of the field in it's condensed state
114 condensedWidth: $( this ).width(),
115
116 // The width of the field in it's expanded state
117 expandedWidth: $( this ).width() * 2,
118
119 // Reference to the field
120 $field: $( this )
121 };
122
123 $( this )
124 .addClass( 'expandableField' )
125 .focus( function ( e ) {
126 clearTimeout( timeout );
127 $.expandableField.expandField( e, context );
128 } )
129 .blur( function ( e ) {
130 timeout = setTimeout( function () {
131 $.expandableField.condenseField( e, context );
132 }, 250 );
133 } );
134 }
135 // Store the context for next time
136 $( this ).data( 'expandableField-context', context );
137 } );
138 return returnValue !== undefined ? returnValue : $( this );
139 };
140
141 }( jQuery ) );