recordselect 3.2.4 → 3.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,419 +0,0 @@
1
- document.observe("dom:loaded", function() {
2
- RecordSelect.document_loaded = true;
3
- document.on('ajax:before', 'div.record-select * li.record a', function(event) {
4
- var link = event.findElement();
5
- if (link) {
6
- if (RecordSelect.notify(link) == false) {
7
- event.stop();
8
- } else {
9
- link.toggleClassName("selected");
10
- }
11
- }
12
- return true;
13
- });
14
- });
15
-
16
- Form.Element.AfterActivity = function(element, callback, delay) {
17
- element = $(element);
18
- if (!delay) delay = 0.25;
19
- new Form.Element.Observer(element, delay, function(element, value) {
20
- // TODO: display loading indicator
21
- if (element.activity_timer) clearTimeout(element.activity_timer);
22
- element.activity_timer = setTimeout(function() {
23
- callback(element.value);
24
- }, delay * 1000 + 50);
25
- });
26
- }
27
-
28
- var RecordSelect = new Object();
29
- RecordSelect.document_loaded = false;
30
-
31
- RecordSelect.notify = function(item) {
32
- var e = Element.up(item, '.record-select-handler');
33
- var onselect = e.onselect || e.getAttribute('onselect');
34
- if (typeof onselect != 'function') onselect = eval(onselect);
35
- if (onselect)
36
- {
37
- try {
38
- onselect(item.parentNode.id.substr(2), (item.down('label') || item).innerHTML.unescapeHTML(), e);
39
- } catch(e) {
40
- alert(e);
41
- }
42
- return false;
43
- }
44
- else return true;
45
- };
46
-
47
- RecordSelect.render_page = function(record_select_id, page) {
48
- var page_element = $$('#' + record_select_id + ' ol')[0];
49
- if (page_element) Element.replace(page_element, page);
50
- };
51
-
52
- RecordSelect.Abstract = Class.create();
53
- Object.extend(RecordSelect.Abstract.prototype, {
54
- /**
55
- * obj - the id or element that will anchor the recordselect to the page
56
- * url - the url to run the recordselect
57
- * options - ??? (check concrete classes)
58
- */
59
- initialize: function(obj, url, options) {
60
- this.obj = $(obj);
61
- this.url = url;
62
- this.options = options;
63
- this.container;
64
- if (this.options.onchange && typeof this.options.onchange != 'function') {
65
- this.options.onchange = eval(this.options.onchange);
66
- }
67
-
68
- if (RecordSelect.document_loaded) this.onload();
69
- else Event.observe(window, 'load', this.onload.bind(this));
70
- },
71
-
72
- /**
73
- * Finish the setup - IE doesn't like doing certain things before the page loads
74
- * --override--
75
- */
76
- onload: function() {},
77
-
78
- /**
79
- * the onselect event handler - when someone clicks on a record
80
- * --override--
81
- */
82
- onselect: function(id, value) {
83
- alert(id + ': ' + value);
84
- },
85
-
86
- /**
87
- * opens the recordselect
88
- */
89
- open: function() {
90
- if (this.is_open()) return;
91
-
92
- new Ajax.Updater(this.container, this.url, {
93
- method: 'get',
94
- evalScripts: true,
95
- asynchronous: true,
96
- onComplete: function() {
97
- this.show();
98
- // needs to be mousedown so the event doesn't get canceled by other code (see issue #26)
99
- Element.observe(document.body, 'mousedown', this.onbodyclick.bindAsEventListener(this));
100
- }.bind(this)
101
- });
102
- },
103
-
104
- /**
105
- * positions and reveals the recordselect
106
- */
107
- show: function() {
108
- var offset = Position.cumulativeOffset(this.obj),
109
- top = Element.getHeight(this.obj) + offset[1],
110
- window_height = document.viewport.getHeight();
111
- this.container.style.left = offset[0] + 'px';
112
- if (top + Element.getHeight(this.container) > window_height)
113
- this.container.style.bottom = (window_height - offset[1]) + 'px';
114
- else this.container.style.top = top + 'px';
115
-
116
- if (this._use_iframe_mask()) {
117
- this.container.insertAdjacentHTML('afterEnd', '<iframe src="javascript:false;" class="record-select-mask" />');
118
- var mask = this.container.next('iframe');
119
- mask.style.left = this.container.style.left;
120
- mask.style.top = this.container.style.top;
121
- }
122
-
123
- this.container.show();
124
-
125
- if (this._use_iframe_mask()) {
126
- var dimensions = this.container.immediateDescendants().first().getDimensions();
127
- mask.style.width = dimensions.width + 'px';
128
- mask.style.height = dimensions.height + 'px';
129
- }
130
- },
131
-
132
- /**
133
- * closes the recordselect by emptying the container
134
- */
135
- close: function() {
136
- if (this._use_iframe_mask()) {
137
- this.container.next('iframe').remove();
138
- }
139
-
140
- this.container.hide();
141
- // hopefully by using remove() instead of innerHTML we won't leak memory
142
- this.container.immediateDescendants().invoke('remove');
143
- },
144
-
145
- /**
146
- * returns true/false for whether the recordselect is open
147
- */
148
- is_open: function() {
149
- return (!this.container.innerHTML.blank())
150
- },
151
-
152
- /**
153
- * when the user clicks outside the dropdown
154
- */
155
- onbodyclick: function(ev) {
156
- if (!this.is_open()) return;
157
- var elem = $(Event.element(ev));
158
- var ancestors = elem.ancestors();
159
- ancestors.push(elem);
160
- if (ancestors.include(this.container) || ancestors.include(this.obj)) return;
161
- this.close();
162
- },
163
-
164
- /**
165
- * creates and initializes (and returns) the recordselect container
166
- */
167
- create_container: function() {
168
- new Insertion.Bottom(document.body, '<div class="record-select-container record-select-handler"></div>');
169
- e = document.body.childNodes[document.body.childNodes.length - 1];
170
- e.onselect = this.onselect.bind(this);
171
- e.style.display = 'none';
172
-
173
- return $(e);
174
- },
175
-
176
- /**
177
- * all the behavior to respond to a text field as a search box
178
- */
179
- _respond_to_text_field: function(text_field) {
180
- // attach the events to start this party
181
- text_field.observe('focus', this.open.bind(this));
182
-
183
- // the autosearch event - needs to happen slightly late (keyup is later than keypress)
184
- text_field.observe('keyup', function() {
185
- if (!this.is_open()) return;
186
- this.container.down('.text-input').value = text_field.value;
187
- }.bind(this));
188
-
189
- // keyboard navigation, if available
190
- if (this.onkeydown) {
191
- text_field.observe('keydown', this.onkeydown.bind(this));
192
- }
193
- },
194
-
195
- _use_iframe_mask: function() {
196
- return this.container.insertAdjacentHTML ? true : false;
197
- }
198
- });
199
-
200
- /**
201
- * Adds keyboard navigation to RecordSelect objects
202
- */
203
- Object.extend(RecordSelect.Abstract.prototype, {
204
- current: null,
205
-
206
- /**
207
- * keyboard navigation - where to intercept the keys is up to the concrete class
208
- */
209
- onkeydown: function(ev) {
210
- var elem;
211
- switch (ev.keyCode) {
212
- case Event.KEY_UP:
213
- if (this.current && this.current.up('.record-select')) elem = this.current.previous();
214
- if (!elem) elem = this.container.getElementsBySelector('ol li.record').last();
215
- this.highlight(elem);
216
- break;
217
- case Event.KEY_DOWN:
218
- if (this.current && this.current.up('.record-select')) elem = this.current.next();
219
- if (!elem) elem = this.container.getElementsBySelector('ol li.record').first();
220
- this.highlight(elem);
221
- break;
222
- case Event.KEY_SPACE:
223
- case Event.KEY_RETURN:
224
- if (this.current) this.current.down('a').onclick();
225
- break;
226
- case Event.KEY_RIGHT:
227
- elem = this.container.down('li.pagination.next');
228
- if (elem) elem.down('a').onclick();
229
- break;
230
- case Event.KEY_LEFT:
231
- elem = this.container.down('li.pagination.previous');
232
- if (elem) elem.down('a').onclick();
233
- break;
234
- case Event.KEY_ESC:
235
- this.close();
236
- break;
237
- default:
238
- return;
239
- }
240
- Event.stop(ev); // so "enter" doesn't submit the form, among other things(?)
241
- },
242
-
243
- /**
244
- * moves the highlight to a new object
245
- */
246
- highlight: function(obj) {
247
- if (this.current) this.current.removeClassName('current');
248
- this.current = $(obj);
249
- obj.addClassName('current');
250
- }
251
- });
252
-
253
- /**
254
- * Used by link_to_record_select
255
- * The options hash should contain a onselect: key, with a javascript function as value
256
- */
257
- RecordSelect.Dialog = Class.create();
258
- RecordSelect.Dialog.prototype = Object.extend(new RecordSelect.Abstract(), {
259
- onload: function() {
260
- this.container = this.create_container();
261
- this.obj.observe('click', this.toggle.bind(this));
262
-
263
- if (this.onkeypress) this.obj.observe('keypress', this.onkeypress.bind(this));
264
- },
265
-
266
- onselect: function(id, value) {
267
- if (this.options.onselect(id, value) != false) this.close();
268
- },
269
-
270
- toggle: function() {
271
- if (this.is_open()) this.close();
272
- else this.open();
273
- }
274
- });
275
-
276
- /**
277
- * Used by record_select_field helper
278
- * The options hash may contain id: and label: keys, designating the current value
279
- * The options hash may also include an onchange: key, where the value is a javascript function (or eval-able string) for an callback routine
280
- * and field_name: key, where value will be set as name of the input field.
281
- */
282
- RecordSelect.Single = Class.create();
283
- RecordSelect.Single.prototype = Object.extend(new RecordSelect.Abstract(), {
284
- onload: function() {
285
- // initialize the container
286
- this.container = this.create_container();
287
- this.container.addClassName('record-select-autocomplete');
288
-
289
- // create the hidden input
290
- new Insertion.After(this.obj, '<input type="hidden" name="" value="" />')
291
- this.hidden_input = this.obj.next();
292
-
293
- // transfer the input name from the text input to the hidden input
294
- this.hidden_input.name = this.obj.name;
295
- this.obj.name = this.options.field_name || '';
296
-
297
- // initialize the values
298
- if (this.options.label) this.set(this.options.id, this.options.label);
299
-
300
- this._respond_to_text_field(this.obj);
301
- if (this.obj.focused) this.open(); // if it was focused before we could attach observers
302
- },
303
-
304
- close: function() {
305
- // if they close the dialog with the text field empty, then delete the id value
306
- if (this.obj.value == '') this.set('', '');
307
-
308
- RecordSelect.Abstract.prototype.close.call(this);
309
- },
310
-
311
- onselect: function(id, value) {
312
- this.set(id, value);
313
- if (this.options.onchange) this.options.onchange.call(this, id, value);
314
- this.obj.fire('recordselect:change', {"id": id, "label": value});
315
- this.close();
316
- },
317
-
318
- /**
319
- * sets the id/label
320
- */
321
- set: function(id, label) {
322
- this.obj.value = label.unescapeHTML();
323
- this.hidden_input.value = id;
324
- }
325
- });
326
-
327
- /**
328
- * Used by record_select_autocomplete helper
329
- * The options hash may contain label: key, designating the current value
330
- * The options hash may also include an onchange: key, where the value is a javascript function (or eval-able string) for an callback routine.
331
- */
332
- RecordSelect.Autocomplete = Class.create();
333
- RecordSelect.Autocomplete.prototype = Object.extend(new RecordSelect.Abstract(), {
334
- onload: function() {
335
- // initialize the container
336
- this.container = this.create_container();
337
- this.container.addClassName('record-select-autocomplete');
338
-
339
- // initialize the values
340
- if (this.options.label) this.set(this.options.label);
341
-
342
- this._respond_to_text_field(this.obj);
343
- if (this.obj.focused) this.open(); // if it was focused before we could attach observers
344
- },
345
-
346
- close: function() {
347
- // if they close the dialog with the text field empty, then delete the id value
348
- if (this.obj.value == '') this.set('', '');
349
-
350
- RecordSelect.Abstract.prototype.close.call(this);
351
- },
352
-
353
- onselect: function(id, value) {
354
- this.set(value);
355
- if (this.options.onchange) this.options.onchange.call(this, id, value);
356
- this.obj.fire('recordselect:change', {"id": id, "label": value});
357
- this.close();
358
- },
359
-
360
- /**
361
- * sets the id/label
362
- */
363
- set: function(label) {
364
- this.obj.value = label.unescapeHTML();
365
- }
366
- });
367
-
368
- /**
369
- * Used by record_multi_select_field helper.
370
- * Options:
371
- * list - the id (or object) of the <ul> to contain the <li>s of selected entries
372
- * current - an array of id:/label: keys designating the currently selected entries
373
- */
374
- RecordSelect.Multiple = Class.create();
375
- RecordSelect.Multiple.prototype = Object.extend(new RecordSelect.Abstract(), {
376
- onload: function() {
377
- // initialize the container
378
- this.container = this.create_container();
379
- this.container.addClassName('record-select-autocomplete');
380
-
381
- // decide where the <li> entries should be placed
382
- if (this.options.list) this.list_container = $(this.options.list);
383
- else this.list_container = this.obj.next('ul');
384
-
385
- // take the input name from the text input, and store it for this.add()
386
- this.input_name = this.obj.name;
387
- this.obj.name = '';
388
-
389
- // initialize the list
390
- $A(this.options.current).each(function(c) {
391
- this.add(c.id, c.label);
392
- }.bind(this));
393
-
394
- this._respond_to_text_field(this.obj);
395
- if (this.obj.focused) this.open(); // if it was focused before we could attach observers
396
- },
397
-
398
- onselect: function(id, value) {
399
- this.add(id, value);
400
- },
401
-
402
- /**
403
- * Adds a record to the selected list
404
- */
405
- add: function(id, label) {
406
- // return silently if this value has already been selected
407
- var already_selected = this.list_container.getElementsBySelector('input').any(function(i) {
408
- return i.value == id
409
- });
410
- if (already_selected) return;
411
-
412
- var entry = '<li>'
413
- + '<a href="#" onclick="$(this.parentNode).remove(); return false;" class="remove">remove</a>'
414
- + '<input type="hidden" name="' + this.input_name + '" value="' + id + '" />'
415
- + '<label>' + label + '</label>'
416
- + '</li>';
417
- new Insertion.Top(this.list_container, entry);
418
- }
419
- });
@@ -1,5 +0,0 @@
1
- <% if RecordSelect::Config.js_framework == :jquery %>
2
- <% require_asset "jquery/record_select" %>
3
- <% else %>
4
- <% require_asset "prototype/record_select" %>
5
- <% end %>
@@ -1,133 +0,0 @@
1
- .record-select {
2
- width: 300px;
3
- border: 1px solid #afd0f5;
4
- font-family: sans-serif;
5
- background-color: #fff;
6
- font-size: 11px;
7
- }
8
-
9
- .record-select img {
10
- border-width: 0px;
11
- }
12
-
13
- .record-select form {
14
- display: inline;
15
- }
16
-
17
- .record-select form .text-input {
18
- width: 294px;
19
- margin: 2px auto 1px auto;
20
- display: block;
21
- border: 1px solid #999;
22
- }
23
-
24
- .record-select form input.example {
25
- color: #999;
26
- text-align: center;
27
- }
28
-
29
- .record-select form .search_submit {
30
- display: none;
31
- }
32
-
33
- .record-select ol,
34
- .record-select li {
35
- margin: 0px;
36
- padding: 0px;
37
- list-style: none;
38
- clear: both;
39
- }
40
-
41
- .record-select a {
42
- color: #0066cc;
43
- text-decoration: none;
44
- }
45
-
46
- .record-select ol a {
47
- display: block;
48
- zoom: 1;
49
- background-color: #e6f2ff;
50
- padding: 2px 4px;
51
- }
52
-
53
- .record-select ol .even a {
54
- background-color: #ffffff;
55
- }
56
-
57
- .record-select ol .pagination a {
58
- background-color: #eee;
59
- }
60
-
61
- .record-select ol .previous a {
62
- border-bottom: 1px solid #afd0f5;
63
- }
64
-
65
- .record-select ol .next a {
66
- border-top: 1px solid #afd0f5;
67
- }
68
-
69
- .record-select ol .pagination a img {
70
- vertical-align: middle;
71
- }
72
-
73
- .record-select ol .found {
74
- text-align: center;
75
- font-style: italic;
76
- color: #999;
77
- padding: 1px 4px;
78
- border-bottom: 1px solid #afd0f5;
79
- }
80
-
81
- .record-select ol .current a,
82
- .record-select ol a:hover {
83
- background-color: #ffff88;
84
- }
85
-
86
- .record-select ol a.selected {
87
- background-color: #666;
88
- color: #fff;
89
- }
90
-
91
- .record-select-container {
92
- position: absolute;
93
- z-index: 100;
94
- }
95
-
96
- iframe.record-select-mask {
97
- /* to mask windowed elements in IE6 */
98
- position: absolute;
99
- z-index: 99;
100
- filter: progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0);
101
- }
102
-
103
- .record-select-autocomplete form .text-input {
104
- display: none;
105
- }
106
-
107
- .record-select-list {
108
- padding: 0px;
109
- margin: 0px;
110
- list-style: none;
111
- }
112
-
113
- .record-select-list li {
114
- overflow: auto;
115
- zoom: 1;
116
- margin-left: 10px;
117
- font-size: 80%;
118
- }
119
-
120
- .record-select-list label {
121
- float: left;
122
- }
123
-
124
- .record-select-list a.remove {
125
- display: block;
126
- width: 0px;
127
- height: 16px;
128
- padding-left: 16px;
129
- background: url(<%= image_path 'record_select/cross.gif' %>) no-repeat 0 0;
130
- overflow: hidden;
131
- float: left;
132
- margin-right: 5px;
133
- }