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