textext-rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,175 @@
1
+ /**
2
+ * jQuery TextExt Plugin
3
+ * http://alexgorbatchev.com/textext
4
+ *
5
+ * @version 1.2.0
6
+ * @copyright Copyright (C) 2011 Alex Gorbatchev. All rights reserved.
7
+ * @license MIT License
8
+ */
9
+ (function($)
10
+ {
11
+ /**
12
+ * Suggestions plugin allows to easily specify the list of suggestion items that the
13
+ * Autocomplete plugin would present to the user.
14
+ *
15
+ * @author agorbatchev
16
+ * @date 2011/08/18
17
+ * @id TextExtSuggestions
18
+ */
19
+ function TextExtSuggestions() {};
20
+
21
+ $.fn.textext.TextExtSuggestions = TextExtSuggestions;
22
+ $.fn.textext.addPlugin('suggestions', TextExtSuggestions);
23
+
24
+ var p = TextExtSuggestions.prototype,
25
+ /**
26
+ * Suggestions plugin only has one option and that is to set suggestion items. It could be
27
+ * changed when passed to the `$().textext()` function. For example:
28
+ *
29
+ * $('textarea').textext({
30
+ * plugins: 'suggestions',
31
+ * suggestions: [ "item1", "item2" ]
32
+ * })
33
+ *
34
+ * @author agorbatchev
35
+ * @date 2011/08/18
36
+ * @id TextExtSuggestions.options
37
+ */
38
+
39
+ /**
40
+ * List of items that Autocomplete plugin would display in the dropdown.
41
+ *
42
+ * @name suggestions
43
+ * @default null
44
+ * @author agorbatchev
45
+ * @date 2011/08/18
46
+ * @id TextExtSuggestions.options.suggestions
47
+ */
48
+ OPT_SUGGESTIONS = 'suggestions',
49
+
50
+ /**
51
+ * Suggestions plugin dispatches or reacts to the following events.
52
+ *
53
+ * @author agorbatchev
54
+ * @date 2011/08/17
55
+ * @id TextExtSuggestions.events
56
+ */
57
+
58
+ /**
59
+ * Suggestions plugin reacts to the `getSuggestions` event and returns `suggestions` items
60
+ * from the options.
61
+ *
62
+ * @name getSuggestions
63
+ * @author agorbatchev
64
+ * @date 2011/08/19
65
+ * @id TextExtSuggestions.events.getSuggestions
66
+ */
67
+
68
+ /**
69
+ * Suggestions plugin triggers the `setSuggestions` event to pass its own list of `Suggestions`
70
+ * to the Autocomplete plugin.
71
+ *
72
+ * @name setSuggestions
73
+ * @author agorbatchev
74
+ * @date 2011/08/19
75
+ * @id TextExtSuggestions.events.setSuggestions
76
+ */
77
+
78
+ /**
79
+ * Suggestions plugin reacts to the `postInit` event to pass its list of `suggestions` to the
80
+ * Autocomplete right away.
81
+ *
82
+ * @name postInit
83
+ * @author agorbatchev
84
+ * @date 2011/08/19
85
+ * @id TextExtSuggestions.events.postInit
86
+ */
87
+
88
+ DEFAULT_OPTS = {
89
+ suggestions : null
90
+ }
91
+ ;
92
+
93
+ /**
94
+ * Initialization method called by the core during plugin instantiation.
95
+ *
96
+ * @signature TextExtSuggestions.init(core)
97
+ *
98
+ * @param core {TextExt} Instance of the TextExt core class.
99
+ *
100
+ * @author agorbatchev
101
+ * @date 2011/08/18
102
+ * @id TextExtSuggestions.init
103
+ */
104
+ p.init = function(core)
105
+ {
106
+ var self = this;
107
+
108
+ self.baseInit(core, DEFAULT_OPTS);
109
+
110
+ self.on({
111
+ getSuggestions : self.onGetSuggestions,
112
+ postInit : self.onPostInit
113
+ });
114
+ };
115
+
116
+ /**
117
+ * Triggers `setSuggestions` and passes supplied suggestions to the Autocomplete plugin.
118
+ *
119
+ * @signature TextExtSuggestions.setSuggestions(suggestions, showHideDropdown)
120
+ *
121
+ * @param suggestions {Array} List of suggestions. With the default `ItemManager` it should
122
+ * be a list of strings.
123
+ * @param showHideDropdown {Boolean} If it's undesirable to show the dropdown right after
124
+ * suggestions are set, `false` should be passed for this argument.
125
+ *
126
+ * @author agorbatchev
127
+ * @date 2011/08/19
128
+ * @id TextExtSuggestions.setSuggestions
129
+ */
130
+ p.setSuggestions = function(suggestions, showHideDropdown)
131
+ {
132
+ this.trigger('setSuggestions', { result : suggestions, showHideDropdown : showHideDropdown != false });
133
+ };
134
+
135
+ /**
136
+ * Reacts to the `postInit` event and triggers `setSuggestions` event to set suggestions list
137
+ * right after initialization.
138
+ *
139
+ * @signature TextExtSuggestions.onPostInit(e)
140
+ *
141
+ * @param e {Object} jQuery event.
142
+ *
143
+ * @author agorbatchev
144
+ * @date 2011/08/19
145
+ * @id TextExtSuggestions.onPostInit
146
+ */
147
+ p.onPostInit = function(e)
148
+ {
149
+ var self = this;
150
+ self.setSuggestions(self.opts(OPT_SUGGESTIONS), false);
151
+ };
152
+
153
+ /**
154
+ * Reacts to the `getSuggestions` event and triggers `setSuggestions` event with the list
155
+ * of `suggestions` specified in the options.
156
+ *
157
+ * @signature TextExtSuggestions.onGetSuggestions(e, data)
158
+ *
159
+ * @param e {Object} jQuery event.
160
+ * @param data {Object} Payload from the `getSuggestions` event with the user query, eg `{ query: {String} }`.
161
+ *
162
+ * @author agorbatchev
163
+ * @date 2011/08/19
164
+ * @id TextExtSuggestions.onGetSuggestions
165
+ */
166
+ p.onGetSuggestions = function(e, data)
167
+ {
168
+ var self = this,
169
+ suggestions = self.opts(OPT_SUGGESTIONS)
170
+ ;
171
+
172
+ suggestions.sort();
173
+ self.setSuggestions(self.itemManager().filter(suggestions, data.query));
174
+ };
175
+ })(jQuery);
@@ -0,0 +1,638 @@
1
+ /**
2
+ * jQuery TextExt Plugin
3
+ * http://alexgorbatchev.com/textext
4
+ *
5
+ * @version 1.2.0
6
+ * @copyright Copyright (C) 2011 Alex Gorbatchev. All rights reserved.
7
+ * @license MIT License
8
+ */
9
+ (function($)
10
+ {
11
+ /**
12
+ * Tags plugin brings in the traditional tag functionality where user can assemble and
13
+ * edit list of tags. Tags plugin works especially well together with Autocomplete, Filter,
14
+ * Suggestions and Ajax plugins to provide full spectrum of features. It can also work on
15
+ * its own and just do one thing -- tags.
16
+ *
17
+ * @author agorbatchev
18
+ * @date 2011/08/19
19
+ * @id TextExtTags
20
+ */
21
+ function TextExtTags() {};
22
+
23
+ $.fn.textext.TextExtTags = TextExtTags;
24
+ $.fn.textext.addPlugin('tags', TextExtTags);
25
+
26
+ var p = TextExtTags.prototype,
27
+
28
+ CSS_DOT = '.',
29
+ CSS_TAGS_ON_TOP = 'text-tags-on-top',
30
+ CSS_DOT_TAGS_ON_TOP = CSS_DOT + CSS_TAGS_ON_TOP,
31
+ CSS_TAG = 'text-tag',
32
+ CSS_DOT_TAG = CSS_DOT + CSS_TAG,
33
+ CSS_TAGS = 'text-tags',
34
+ CSS_DOT_TAGS = CSS_DOT + CSS_TAGS,
35
+
36
+ /**
37
+ * Tags plugin options are grouped under `tags` when passed to the
38
+ * `$().textext()` function. For example:
39
+ *
40
+ * $('textarea').textext({
41
+ * plugins: 'tags',
42
+ * tags: {
43
+ * items: [ "tag1", "tag2" ]
44
+ * }
45
+ * })
46
+ *
47
+ * @author agorbatchev
48
+ * @date 2011/08/19
49
+ * @id TextExtTags.options
50
+ */
51
+
52
+ /**
53
+ * This is a toggle switch to enable or disable the Tags plugin. The value is checked
54
+ * each time at the top level which allows you to toggle this setting on the fly.
55
+ *
56
+ * @name tags.enabled
57
+ * @default true
58
+ * @author agorbatchev
59
+ * @date 2011/08/19
60
+ * @id TextExtTags.options.tags.enabled
61
+ */
62
+ OPT_ENABLED = 'tags.enabled',
63
+
64
+ /**
65
+ * Allows to specify tags which will be added to the input by default upon initialization.
66
+ * Each item in the array must be of the type that current `ItemManager` can understand.
67
+ * Default type is `String`.
68
+ *
69
+ * @name tags.items
70
+ * @default null
71
+ * @author agorbatchev
72
+ * @date 2011/08/19
73
+ * @id TextExtTags.options.tags.items
74
+ */
75
+ OPT_ITEMS = 'tags.items',
76
+
77
+ /**
78
+ * HTML source that is used to generate a single tag.
79
+ *
80
+ * @name html.tag
81
+ * @default '<div class="text-tags"/>'
82
+ * @author agorbatchev
83
+ * @date 2011/08/19
84
+ * @id TextExtTags.options.html.tag
85
+ */
86
+ OPT_HTML_TAG = 'html.tag',
87
+
88
+ /**
89
+ * HTML source that is used to generate container for the tags.
90
+ *
91
+ * @name html.tags
92
+ * @default '<div class="text-tag"><div class="text-button"><span class="text-label"/><a class="text-remove"/></div></div>'
93
+ * @author agorbatchev
94
+ * @date 2011/08/19
95
+ * @id TextExtTags.options.html.tags
96
+ */
97
+ OPT_HTML_TAGS = 'html.tags',
98
+
99
+ /**
100
+ * Tags plugin dispatches or reacts to the following events.
101
+ *
102
+ * @author agorbatchev
103
+ * @date 2011/08/17
104
+ * @id TextExtTags.events
105
+ */
106
+
107
+ /**
108
+ * Tags plugin triggers the `isTagAllowed` event before adding each tag to the tag list. Other plugins have
109
+ * an opportunity to interrupt this by setting `result` of the second argument to `false`. For example:
110
+ *
111
+ * $('textarea').textext({...}).bind('isTagAllowed', function(e, data)
112
+ * {
113
+ * if(data.tag === 'foo')
114
+ * data.result = false;
115
+ * })
116
+ *
117
+ * The second argument `data` has the following format: `{ tag : {Object}, result : {Boolean} }`. `tag`
118
+ * property is in the format that the current `ItemManager` can understand.
119
+ *
120
+ * @name isTagAllowed
121
+ * @author agorbatchev
122
+ * @date 2011/08/19
123
+ * @id TextExtTags.events.isTagAllowed
124
+ */
125
+ EVENT_IS_TAG_ALLOWED = 'isTagAllowed',
126
+
127
+ DEFAULT_OPTS = {
128
+ tags : {
129
+ enabled : true,
130
+ items : null
131
+ },
132
+
133
+ html : {
134
+ tags : '<div class="text-tags"/>',
135
+ tag : '<div class="text-tag"><div class="text-button"><span class="text-label"/><a class="text-remove"/></div></div>'
136
+ }
137
+ }
138
+ ;
139
+
140
+ /**
141
+ * Initialization method called by the core during plugin instantiation.
142
+ *
143
+ * @signature TextExtTags.init(core)
144
+ *
145
+ * @param core {TextExt} Instance of the TextExt core class.
146
+ *
147
+ * @author agorbatchev
148
+ * @date 2011/08/19
149
+ * @id TextExtTags.init
150
+ */
151
+ p.init = function(core)
152
+ {
153
+ this.baseInit(core, DEFAULT_OPTS);
154
+
155
+ var self = this,
156
+ input = self.input(),
157
+ container
158
+ ;
159
+
160
+ if(self.opts(OPT_ENABLED))
161
+ {
162
+ container = $(self.opts(OPT_HTML_TAGS));
163
+ input.after(container);
164
+
165
+ $(self).data('container', container);
166
+
167
+ self.on({
168
+ enterKeyPress : self.onEnterKeyPress,
169
+ backspaceKeyDown : self.onBackspaceKeyDown,
170
+ preInvalidate : self.onPreInvalidate,
171
+ postInit : self.onPostInit,
172
+ getFormData : self.onGetFormData
173
+ });
174
+
175
+ self.on(container, {
176
+ click : self.onClick,
177
+ mousemove : self.onContainerMouseMove
178
+ });
179
+
180
+ self.on(input, {
181
+ mousemove : self.onInputMouseMove
182
+ });
183
+ }
184
+
185
+ self._originalPadding = {
186
+ left : parseInt(input.css('paddingLeft') || 0),
187
+ top : parseInt(input.css('paddingTop') || 0)
188
+ };
189
+
190
+ self._paddingBox = {
191
+ left : 0,
192
+ top : 0
193
+ };
194
+
195
+ self.updateFormCache();
196
+ };
197
+
198
+ /**
199
+ * Returns HTML element in which all tag HTML elements are residing.
200
+ *
201
+ * @signature TextExtTags.containerElement()
202
+ *
203
+ * @author agorbatchev
204
+ * @date 2011/08/15
205
+ * @id TextExtTags.containerElement
206
+ */
207
+ p.containerElement = function()
208
+ {
209
+ return $(this).data('container');
210
+ };
211
+
212
+ //--------------------------------------------------------------------------------
213
+ // Event handlers
214
+
215
+ /**
216
+ * Reacts to the `postInit` event triggered by the core and sets default tags
217
+ * if any were specified.
218
+ *
219
+ * @signature TextExtTags.onPostInit(e)
220
+ *
221
+ * @param e {Object} jQuery event.
222
+ *
223
+ * @author agorbatchev
224
+ * @date 2011/08/09
225
+ * @id TextExtTags.onPostInit
226
+ */
227
+ p.onPostInit = function(e)
228
+ {
229
+ var self = this;
230
+ self.addTags(self.opts(OPT_ITEMS));
231
+ };
232
+
233
+ /**
234
+ * Reacts to the [`getFormData`][1] event triggered by the core. Returns data with the
235
+ * weight of 200 to be *greater than the Autocomplete plugin* data weight. The weights
236
+ * system is covered in greater detail in the [`getFormData`][1] event documentation.
237
+ *
238
+ * [1]: /manual/textext.html#getformdata
239
+ *
240
+ * @signature TextExtTags.onGetFormData(e, data, keyCode)
241
+ *
242
+ * @param e {Object} jQuery event.
243
+ * @param data {Object} Data object to be populated.
244
+ * @param keyCode {Number} Key code that triggered the original update request.
245
+ *
246
+ * @author agorbatchev
247
+ * @date 2011/08/22
248
+ * @id TextExtTags.onGetFormData
249
+ */
250
+ p.onGetFormData = function(e, data, keyCode)
251
+ {
252
+ var self = this,
253
+ inputValue = keyCode === 13 ? '' : self.val(),
254
+ formValue = self._formData
255
+ ;
256
+
257
+ data[200] = self.formDataObject(inputValue, formValue);
258
+ };
259
+
260
+ /**
261
+ * Returns initialization priority of the Tags plugin which is expected to be
262
+ * *less than the Autocomplete plugin* because of the dependencies. The value is
263
+ * 100.
264
+ *
265
+ * @signature TextExtTags.initPriority()
266
+ *
267
+ * @author agorbatchev
268
+ * @date 2011/08/22
269
+ * @id TextExtTags.initPriority
270
+ */
271
+ p.initPriority = function()
272
+ {
273
+ return 100;
274
+ };
275
+
276
+ /**
277
+ * Reacts to user moving mouse over the text area when cursor is over the text
278
+ * and not over the tags. Whenever mouse cursor is over the area covered by
279
+ * tags, the tags container is flipped to be on top of the text area which
280
+ * makes all tags functional with the mouse.
281
+ *
282
+ * @signature TextExtTags.onInputMouseMove(e)
283
+ *
284
+ * @param e {Object} jQuery event.
285
+ *
286
+ * @author agorbatchev
287
+ * @date 2011/08/08
288
+ * @id TextExtTags.onInputMouseMove
289
+ */
290
+ p.onInputMouseMove = function(e)
291
+ {
292
+ this.toggleZIndex(e);
293
+ };
294
+
295
+ /**
296
+ * Reacts to user moving mouse over the tags. Whenever the cursor moves out
297
+ * of the tags and back into where the text input is happening visually,
298
+ * the tags container is sent back under the text area which allows user
299
+ * to interact with the text using mouse cursor as expected.
300
+ *
301
+ * @signature TextExtTags.onContainerMouseMove(e)
302
+ *
303
+ * @param e {Object} jQuery event.
304
+ *
305
+ * @author agorbatchev
306
+ * @date 2011/08/08
307
+ * @id TextExtTags.onContainerMouseMove
308
+ */
309
+ p.onContainerMouseMove = function(e)
310
+ {
311
+ this.toggleZIndex(e);
312
+ };
313
+
314
+ /**
315
+ * Reacts to the `backspaceKeyDown` event. When backspace key is pressed in an empty text field,
316
+ * deletes last tag from the list.
317
+ *
318
+ * @signature TextExtTags.onBackspaceKeyDown(e)
319
+ *
320
+ * @param e {Object} jQuery event.
321
+ *
322
+ * @author agorbatchev
323
+ * @date 2011/08/02
324
+ * @id TextExtTags.onBackspaceKeyDown
325
+ */
326
+ p.onBackspaceKeyDown = function(e)
327
+ {
328
+ var self = this,
329
+ lastTag = self.tagElements().last()
330
+ ;
331
+
332
+ if(self.val().length == 0)
333
+ self.removeTag(lastTag);
334
+ };
335
+
336
+ /**
337
+ * Reacts to the `preInvalidate` event and updates the input box to look like the tags are
338
+ * positioned inside it.
339
+ *
340
+ * @signature TextExtTags.onPreInvalidate(e)
341
+ *
342
+ * @param e {Object} jQuery event.
343
+ *
344
+ * @author agorbatchev
345
+ * @date 2011/08/19
346
+ * @id TextExtTags.onPreInvalidate
347
+ */
348
+ p.onPreInvalidate = function(e)
349
+ {
350
+ var self = this,
351
+ lastTag = self.tagElements().last(),
352
+ pos = lastTag.position()
353
+ ;
354
+
355
+ if(lastTag.length > 0)
356
+ pos.left += lastTag.innerWidth();
357
+ else
358
+ pos = self._originalPadding;
359
+
360
+ self._paddingBox = pos;
361
+
362
+ self.input().css({
363
+ paddingLeft : pos.left,
364
+ paddingTop : pos.top
365
+ });
366
+ };
367
+
368
+ /**
369
+ * Reacts to the mouse `click` event.
370
+ *
371
+ * @signature TextExtTags.onClick(e)
372
+ *
373
+ * @param e {Object} jQuery event.
374
+ *
375
+ * @author agorbatchev
376
+ * @date 2011/08/19
377
+ * @id TextExtTags.onClick
378
+ */
379
+ p.onClick = function(e)
380
+ {
381
+ var self = this,
382
+ source = $(e.target),
383
+ focus = 0
384
+ ;
385
+
386
+ if(source.is(CSS_DOT_TAGS))
387
+ {
388
+ focus = 1;
389
+ }
390
+ else if(source.is('.text-remove'))
391
+ {
392
+ self.removeTag(source.parents(CSS_DOT_TAG + ':first'));
393
+ focus = 1;
394
+ }
395
+
396
+ if(focus)
397
+ self.core().focusInput();
398
+ };
399
+
400
+ /**
401
+ * Reacts to the `enterKeyPress` event and adds whatever is currently in the text input
402
+ * as a new tag. Triggers `isTagAllowed` to check if the tag could be added first.
403
+ *
404
+ * @signature TextExtTags.onEnterKeyPress(e)
405
+ *
406
+ * @param e {Object} jQuery event.
407
+ *
408
+ * @author agorbatchev
409
+ * @date 2011/08/19
410
+ * @id TextExtTags.onEnterKeyPress
411
+ */
412
+ p.onEnterKeyPress = function(e)
413
+ {
414
+ var self = this,
415
+ val = self.val(),
416
+ tag = self.itemManager().stringToItem(val)
417
+ ;
418
+
419
+ if(self.isTagAllowed(tag))
420
+ {
421
+ self.addTags([ tag ]);
422
+ // refocus the textarea just in case it lost the focus
423
+ self.core().focusInput();
424
+ }
425
+ };
426
+
427
+ //--------------------------------------------------------------------------------
428
+ // Core functionality
429
+
430
+ /**
431
+ * Creates a cache object with all the tags currently added which will be returned
432
+ * in the `onGetFormData` handler.
433
+ *
434
+ * @signature TextExtTags.updateFormCache()
435
+ *
436
+ * @author agorbatchev
437
+ * @date 2011/08/09
438
+ * @id TextExtTags.updateFormCache
439
+ */
440
+ p.updateFormCache = function()
441
+ {
442
+ var self = this,
443
+ result = []
444
+ ;
445
+
446
+ self.tagElements().each(function()
447
+ {
448
+ result.push($(this).data(CSS_TAG));
449
+ });
450
+
451
+ // cache the results to be used in the onGetFormData
452
+ self._formData = result;
453
+ };
454
+
455
+ /**
456
+ * Toggles tag container to be on top of the text area or under based on where
457
+ * the mouse cursor is located. When cursor is above the text input and out of
458
+ * any of the tags, the tags container is sent under the text area. If cursor
459
+ * is over any of the tags, the tag container is brought to be over the text
460
+ * area.
461
+ *
462
+ * @signature TextExtTags.toggleZIndex(e)
463
+ *
464
+ * @param e {Object} jQuery event.
465
+ *
466
+ * @author agorbatchev
467
+ * @date 2011/08/08
468
+ * @id TextExtTags.toggleZIndex
469
+ */
470
+ p.toggleZIndex = function(e)
471
+ {
472
+ var self = this,
473
+ offset = self.input().offset(),
474
+ mouseX = e.clientX - offset.left,
475
+ mouseY = e.clientY - offset.top,
476
+ box = self._paddingBox,
477
+ container = self.containerElement(),
478
+ isOnTop = container.is(CSS_DOT_TAGS_ON_TOP),
479
+ isMouseOverText = mouseX > box.left && mouseY > box.top
480
+ ;
481
+
482
+ if(!isOnTop && !isMouseOverText || isOnTop && isMouseOverText)
483
+ container[(!isOnTop ? 'add' : 'remove') + 'Class'](CSS_TAGS_ON_TOP);
484
+ };
485
+
486
+ /**
487
+ * Returns all tag HTML elements.
488
+ *
489
+ * @signature TextExtTags.tagElements()
490
+ *
491
+ * @author agorbatchev
492
+ * @date 2011/08/19
493
+ * @id TextExtTags.tagElements
494
+ */
495
+ p.tagElements = function()
496
+ {
497
+ return this.containerElement().find(CSS_DOT_TAG);
498
+ };
499
+
500
+ /**
501
+ * Wrapper around the `isTagAllowed` event which triggers it and returns `true`
502
+ * if `result` property of the second argument remains `true`.
503
+ *
504
+ * @signature TextExtTags.isTagAllowed(tag)
505
+ *
506
+ * @param tag {Object} Tag object that the current `ItemManager` can understand.
507
+ * Default is `String`.
508
+ *
509
+ * @author agorbatchev
510
+ * @date 2011/08/19
511
+ * @id TextExtTags.isTagAllowed
512
+ */
513
+ p.isTagAllowed = function(tag)
514
+ {
515
+ var opts = { tag : tag, result : true };
516
+ this.trigger(EVENT_IS_TAG_ALLOWED, opts);
517
+ return opts.result === true;
518
+ };
519
+
520
+ /**
521
+ * Adds specified tags to the tag list. Triggers `isTagAllowed` event for each tag
522
+ * to insure that it could be added. Calls `TextExt.getFormData()` to refresh the data.
523
+ *
524
+ * @signature TextExtTags.addTags(tags)
525
+ *
526
+ * @param tags {Array} List of tags that current `ItemManager` can understand. Default
527
+ * is `String`.
528
+ *
529
+ * @author agorbatchev
530
+ * @date 2011/08/19
531
+ * @id TextExtTags.addTags
532
+ */
533
+ p.addTags = function(tags)
534
+ {
535
+ if(!tags || tags.length == 0)
536
+ return;
537
+
538
+ var self = this,
539
+ core = self.core(),
540
+ container = self.containerElement(),
541
+ i, tag
542
+ ;
543
+
544
+ for(i = 0; i < tags.length; i++)
545
+ {
546
+ tag = tags[i];
547
+
548
+ if(tag && self.isTagAllowed(tag))
549
+ container.append(self.renderTag(tag));
550
+ }
551
+
552
+ self.updateFormCache();
553
+ core.getFormData();
554
+ core.invalidateBounds();
555
+ };
556
+
557
+ /**
558
+ * Returns HTML element for the specified tag.
559
+ *
560
+ * @signature TextExtTags.getTagElement(tag)
561
+ *
562
+ * @param tag {Object} Tag object in the format that current `ItemManager` can understand.
563
+ * Default is `String`.
564
+
565
+ * @author agorbatchev
566
+ * @date 2011/08/19
567
+ * @id TextExtTags.getTagElement
568
+ */
569
+ p.getTagElement = function(tag)
570
+ {
571
+ var self = this,
572
+ list = self.tagElements(),
573
+ i, item
574
+ ;
575
+
576
+ for(i = 0; i < list.length, item = $(list[i]); i++)
577
+ if(self.itemManager().compareItems(item.data(CSS_TAG), tag))
578
+ return item;
579
+ };
580
+
581
+ /**
582
+ * Removes specified tag from the list. Calls `TextExt.getFormData()` to refresh the data.
583
+ *
584
+ * @signature TextExtTags.removeTag(tag)
585
+ *
586
+ * @param tag {Object} Tag object in the format that current `ItemManager` can understand.
587
+ * Default is `String`.
588
+ *
589
+ * @author agorbatchev
590
+ * @date 2011/08/19
591
+ * @id TextExtTags.removeTag
592
+ */
593
+ p.removeTag = function(tag)
594
+ {
595
+ var self = this,
596
+ core = self.core(),
597
+ element
598
+ ;
599
+
600
+ if(tag instanceof $)
601
+ {
602
+ element = tag;
603
+ tag = tag.data(CSS_TAG);
604
+ }
605
+ else
606
+ {
607
+ element = self.getTagElement(tag);
608
+ }
609
+
610
+ element.remove();
611
+ self.updateFormCache();
612
+ core.getFormData();
613
+ core.invalidateBounds();
614
+ };
615
+
616
+ /**
617
+ * Creates and returns new HTML element from the source code specified in the `html.tag` option.
618
+ *
619
+ * @signature TextExtTags.renderTag(tag)
620
+ *
621
+ * @param tag {Object} Tag object in the format that current `ItemManager` can understand.
622
+ * Default is `String`.
623
+ *
624
+ * @author agorbatchev
625
+ * @date 2011/08/19
626
+ * @id TextExtTags.renderTag
627
+ */
628
+ p.renderTag = function(tag)
629
+ {
630
+ var self = this,
631
+ node = $(self.opts(OPT_HTML_TAG))
632
+ ;
633
+
634
+ node.find('.text-label').text(self.itemManager().itemToString(tag));
635
+ node.data(CSS_TAG, tag);
636
+ return node;
637
+ };
638
+ })(jQuery);