tagedit-rails 1.0.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.
- data/.gitignore +17 -0
- data/.project +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/lib/tagedit/rails.rb +8 -0
- data/lib/tagedit/rails/version.rb +5 -0
- data/tagedit-rails.gemspec +27 -0
- data/vendor/assets/images/cross.png +0 -0
- data/vendor/assets/images/delete.png +0 -0
- data/vendor/assets/images/disc.png +0 -0
- data/vendor/assets/images/edit.png +0 -0
- data/vendor/assets/images/go.png +0 -0
- data/vendor/assets/images/tick.png +0 -0
- data/vendor/assets/images/undo.png +0 -0
- data/vendor/assets/javascripts/jquery.tagedit.extensions.js +3 -0
- data/vendor/assets/javascripts/tagedit.js +3 -0
- data/vendor/assets/javascripts/tagedit/jquery.autoGrowInput.js +63 -0
- data/vendor/assets/javascripts/tagedit/jquery.tagedit.js +458 -0
- data/vendor/assets/stylesheets/jquery.tagedit.css +47 -0
- data/vendor/assets/stylesheets/jquery.tagedit.extensions.css +3 -0
- data/vendor/assets/stylesheets/tagedit.css +5 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/jquery-ui-1.8.6.custom.css +347 -0
- metadata +164 -0
data/.gitignore
ADDED
data/.project
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<projectDescription>
|
3
|
+
<name>tagedit-rails</name>
|
4
|
+
<comment></comment>
|
5
|
+
<projects>
|
6
|
+
</projects>
|
7
|
+
<buildSpec>
|
8
|
+
</buildSpec>
|
9
|
+
<natures>
|
10
|
+
<nature>org.radrails.rails.core.railsnature</nature>
|
11
|
+
<nature>com.aptana.ruby.core.rubynature</nature>
|
12
|
+
</natures>
|
13
|
+
</projectDescription>
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Matthew
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Tagedit Rails
|
2
|
+
|
3
|
+
Use [Tagedit](https://github.com/webworka/Tagedit) with Rails 3.2.6+ Asset Pipeline.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
This gem vendors Tagedit for Rails 3.2.6 and greater. The files will be
|
8
|
+
added to the asset pipeline and available for you to use.
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'tagedit-rails'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install tagedit-rails
|
21
|
+
|
22
|
+
Now you need to edit your `app/assets/javascripts/application.js` file and add the following line:
|
23
|
+
|
24
|
+
``` javascript
|
25
|
+
//= require tagedit
|
26
|
+
```
|
27
|
+
|
28
|
+
And then edit your `app/assets/stylesheets/application.css` file and add the following line:
|
29
|
+
|
30
|
+
|
31
|
+
``` css
|
32
|
+
/*
|
33
|
+
*= require tagedit
|
34
|
+
*/
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
With the gem installed and included in your asset manifests, you can now
|
40
|
+
use tagedit as you normally would.
|
41
|
+
|
42
|
+
## Requirements
|
43
|
+
|
44
|
+
Be aware the original Tagedit use his own jquery and jquery-ui files, in this version I changed it to gems usage.
|
45
|
+
|
46
|
+
You should have `require jquery` and `require jquery.ui.all` in your `app/assets/javascripts/application.js` before this gem.
|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tagedit/rails/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tagedit-rails"
|
8
|
+
spec.version = Tagedit::Rails::VERSION
|
9
|
+
spec.authors = ["Matthew Oklander"]
|
10
|
+
spec.email = ["mottiokla@gmail.com"]
|
11
|
+
spec.description = 'This gem provides Tagedit extension for your Rails 3.2.6+ application.'
|
12
|
+
spec.summary = 'Use Tagedit with Rails 3.2.6+'
|
13
|
+
spec.homepage = "http://www.o-sandbox.com"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "jquery-rails", ">= 3.0.4"
|
22
|
+
spec.add_dependency "jquery-ui-rails", ">= 4.0.4"
|
23
|
+
spec.add_dependency "rails", ">= 3.2.6"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,63 @@
|
|
1
|
+
(function($){
|
2
|
+
|
3
|
+
// jQuery autoGrowInput plugin by James Padolsey
|
4
|
+
// See related thread: http://stackoverflow.com/questions/931207/is-there-a-jquery-autogrow-plugin-for-text-fields
|
5
|
+
|
6
|
+
$.fn.autoGrowInput = function(o) {
|
7
|
+
|
8
|
+
o = $.extend({
|
9
|
+
maxWidth: 1000,
|
10
|
+
minWidth: 0,
|
11
|
+
comfortZone: 70
|
12
|
+
}, o);
|
13
|
+
|
14
|
+
this.filter('input:text').each(function(){
|
15
|
+
|
16
|
+
var minWidth = o.minWidth || $(this).width(),
|
17
|
+
val = '',
|
18
|
+
input = $(this),
|
19
|
+
testSubject = $('<tester/>').css({
|
20
|
+
position: 'absolute',
|
21
|
+
top: -9999,
|
22
|
+
left: -9999,
|
23
|
+
width: 'auto',
|
24
|
+
fontSize: input.css('fontSize'),
|
25
|
+
fontFamily: input.css('fontFamily'),
|
26
|
+
fontWeight: input.css('fontWeight'),
|
27
|
+
letterSpacing: input.css('letterSpacing'),
|
28
|
+
whiteSpace: 'nowrap'
|
29
|
+
}),
|
30
|
+
check = function() {
|
31
|
+
|
32
|
+
if (val === (val = input.val())) {return;}
|
33
|
+
|
34
|
+
// Enter new content into testSubject
|
35
|
+
var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
|
36
|
+
testSubject.html(escaped);
|
37
|
+
|
38
|
+
// Calculate new width + whether to change
|
39
|
+
var testerWidth = testSubject.width(),
|
40
|
+
newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
|
41
|
+
currentWidth = input.width(),
|
42
|
+
isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
|
43
|
+
|| (newWidth > minWidth && newWidth < o.maxWidth);
|
44
|
+
|
45
|
+
// Animate width
|
46
|
+
if (isValidWidthChange) {
|
47
|
+
input.width(newWidth);
|
48
|
+
}
|
49
|
+
|
50
|
+
};
|
51
|
+
|
52
|
+
testSubject.insertAfter(input);
|
53
|
+
|
54
|
+
$(this).bind('keyup keydown blur update', check);
|
55
|
+
|
56
|
+
check();
|
57
|
+
});
|
58
|
+
|
59
|
+
return this;
|
60
|
+
|
61
|
+
};
|
62
|
+
|
63
|
+
})(jQuery);
|
@@ -0,0 +1,458 @@
|
|
1
|
+
/*
|
2
|
+
* Tagedit - jQuery Plugin
|
3
|
+
* The Plugin can be used to edit tags from a database the easy way
|
4
|
+
*
|
5
|
+
* Examples and documentation at: tagedit.webwork-albrecht.de
|
6
|
+
*
|
7
|
+
* Copyright (c) 2010 Oliver Albrecht <info@webwork-albrecht.de>
|
8
|
+
*
|
9
|
+
* License:
|
10
|
+
* This work is licensed under a MIT License
|
11
|
+
* http://www.opensource.org/licenses/mit-license.php
|
12
|
+
*
|
13
|
+
* @author Oliver Albrecht Mial: info@webwork-albrecht.de Twitter: @webworka
|
14
|
+
* @version 1.2.1 (11/2011)
|
15
|
+
* Requires: jQuery v1.4+, jQueryUI v1.8+, jQuerry.autoGrowInput
|
16
|
+
*
|
17
|
+
* Example of usage:
|
18
|
+
*
|
19
|
+
* $( "input.tag" ).tagedit();
|
20
|
+
*
|
21
|
+
* Possible options:
|
22
|
+
*
|
23
|
+
* autocompleteURL: '', // url for a autocompletion
|
24
|
+
* deleteEmptyItems: true, // Deletes items with empty value
|
25
|
+
* deletedPostfix: '-d', // will be put to the Items that are marked as delete
|
26
|
+
* addedPostfix: '-a', // will be put to the Items that are choosem from the database
|
27
|
+
* additionalListClass: '', // put a classname here if the wrapper ul shoud receive a special class
|
28
|
+
* allowEdit: true, // Switch on/off edit entries
|
29
|
+
* allowDelete: true, // Switch on/off deletion of entries. Will be ignored if allowEdit = false
|
30
|
+
* allowAdd: true, // switch on/off the creation of new entries
|
31
|
+
* direction: 'ltr' // Sets the writing direction for Outputs and Inputs
|
32
|
+
* animSpeed: 500 // Sets the animation speed for effects
|
33
|
+
* autocompleteOptions: {}, // Setting Options for the jquery UI Autocomplete (http://jqueryui.com/demos/autocomplete/)
|
34
|
+
* breakKeyCodes: [ 13, 44 ], // Sets the characters to break on to parse the tags (defaults: return, comma)
|
35
|
+
* checkNewEntriesCaseSensitive: false, // If there is a new Entry, it is checked against the autocompletion list. This Flag controlls if the check is (in-)casesensitive
|
36
|
+
* texts: { // some texts
|
37
|
+
* removeLinkTitle: 'Remove from list.',
|
38
|
+
* saveEditLinkTitle: 'Save changes.',
|
39
|
+
* deleteLinkTitle: 'Delete this tag from database.',
|
40
|
+
* deleteConfirmation: 'Are you sure to delete this entry?',
|
41
|
+
* deletedElementTitle: 'This Element will be deleted.',
|
42
|
+
* breakEditLinkTitle: 'Cancel'
|
43
|
+
* }
|
44
|
+
*/
|
45
|
+
|
46
|
+
(function($) {
|
47
|
+
|
48
|
+
$.fn.tagedit = function(options) {
|
49
|
+
/**
|
50
|
+
* Merge Options with defaults
|
51
|
+
*/
|
52
|
+
options = $.extend(true, {
|
53
|
+
// default options here
|
54
|
+
autocompleteURL: null,
|
55
|
+
deletedPostfix: '-d',
|
56
|
+
addedPostfix: '-a',
|
57
|
+
additionalListClass: '',
|
58
|
+
allowEdit: true,
|
59
|
+
allowDelete: true,
|
60
|
+
allowAdd: true,
|
61
|
+
direction: 'ltr',
|
62
|
+
animSpeed: 500,
|
63
|
+
autocompleteOptions: {
|
64
|
+
select: function( event, ui ) {
|
65
|
+
$(this).val(ui.item.value).trigger('transformToTag', [ui.item.id]);
|
66
|
+
return false;
|
67
|
+
}
|
68
|
+
},
|
69
|
+
breakKeyCodes: [ 13, 44 ],
|
70
|
+
checkNewEntriesCaseSensitive: false,
|
71
|
+
texts: {
|
72
|
+
removeLinkTitle: 'Remove from list.',
|
73
|
+
saveEditLinkTitle: 'Save changes.',
|
74
|
+
deleteLinkTitle: 'Delete this tag from database.',
|
75
|
+
deleteConfirmation: 'Are you sure to delete this entry?',
|
76
|
+
deletedElementTitle: 'This Element will be deleted.',
|
77
|
+
breakEditLinkTitle: 'Cancel'
|
78
|
+
}
|
79
|
+
}, options || {});
|
80
|
+
|
81
|
+
// no action if there are no elements
|
82
|
+
if(this.length == 0) {
|
83
|
+
return;
|
84
|
+
}
|
85
|
+
|
86
|
+
// set the autocompleteOptions source
|
87
|
+
if(options.autocompleteURL) {
|
88
|
+
options.autocompleteOptions.source = options.autocompleteURL;
|
89
|
+
}
|
90
|
+
|
91
|
+
// Set the direction of the inputs
|
92
|
+
var direction= this.attr('dir');
|
93
|
+
if(direction && direction.length > 0) {
|
94
|
+
options.direction = this.attr('dir');
|
95
|
+
}
|
96
|
+
|
97
|
+
var elements = this;
|
98
|
+
|
99
|
+
var baseNameRegexp = new RegExp("^(.*)\\[([0-9]*?("+options.deletedPostfix+"|"+options.addedPostfix+")?)?\]$", "i");
|
100
|
+
|
101
|
+
var baseName = elements.eq(0).attr('name').match(baseNameRegexp);
|
102
|
+
if(baseName && baseName.length == 4) {
|
103
|
+
baseName = baseName[1];
|
104
|
+
}
|
105
|
+
else {
|
106
|
+
// Elementname does not match the expected format, exit
|
107
|
+
alert('elementname dows not match the expected format (regexp: '+baseNameRegexp+')')
|
108
|
+
return;
|
109
|
+
}
|
110
|
+
|
111
|
+
// init elements
|
112
|
+
inputsToList();
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Creates the tageditinput from a list of textinputs
|
116
|
+
*
|
117
|
+
*/
|
118
|
+
function inputsToList() {
|
119
|
+
var html = '<ul class="tagedit-list '+options.additionalListClass+'">';
|
120
|
+
|
121
|
+
elements.each(function() {
|
122
|
+
var element_name = $(this).attr('name').match(baseNameRegexp);
|
123
|
+
if(element_name && element_name.length == 4 && (options.deleteEmptyItems == false || $(this).val().length > 0)) {
|
124
|
+
if(element_name[1].length > 0) {
|
125
|
+
var elementId = typeof element_name[2] != 'undefined'? element_name[2]: '';
|
126
|
+
|
127
|
+
html += '<li class="tagedit-listelement tagedit-listelement-old">';
|
128
|
+
html += '<span dir="'+options.direction+'">' + $(this).val() + '</span>';
|
129
|
+
html += '<input type="hidden" name="'+baseName+'['+elementId+']" value="'+$(this).val()+'" />';
|
130
|
+
html += '<a class="tagedit-close" title="'+options.texts.removeLinkTitle+'">x</a>';
|
131
|
+
html += '</li>';
|
132
|
+
}
|
133
|
+
}
|
134
|
+
});
|
135
|
+
|
136
|
+
// replace Elements with the list and save the list in the local variable elements
|
137
|
+
elements.last().after(html)
|
138
|
+
var newList = elements.last().next();
|
139
|
+
elements.remove();
|
140
|
+
elements = newList;
|
141
|
+
|
142
|
+
// Check if some of the elementshav to be marked as deleted
|
143
|
+
if(options.deletedPostfix.length > 0) {
|
144
|
+
elements.find('input[name$="'+options.deletedPostfix+'\]"]').each(function() {
|
145
|
+
markAsDeleted($(this).parent());
|
146
|
+
});
|
147
|
+
}
|
148
|
+
|
149
|
+
// put an input field at the End
|
150
|
+
// Put an empty element at the end
|
151
|
+
html = '<li class="tagedit-listelement tagedit-listelement-new">';
|
152
|
+
html += '<input type="text" name="'+baseName+'[]" value="" id="tagedit-input" disabled="disabled" class="tagedit-input-disabled" dir="'+options.direction+'"/>';
|
153
|
+
html += '</li>';
|
154
|
+
html += '</ul>';
|
155
|
+
|
156
|
+
elements
|
157
|
+
.append(html)
|
158
|
+
// Set function on the input
|
159
|
+
.find('#tagedit-input')
|
160
|
+
.each(function() {
|
161
|
+
$(this).autoGrowInput({comfortZone: 15, minWidth: 15, maxWidth: 20000});
|
162
|
+
|
163
|
+
// Event ist triggert in case of choosing an item from the autocomplete, or finish the input
|
164
|
+
$(this).bind('transformToTag', function(event, id) {
|
165
|
+
var oldValue = (typeof id != 'undefined' && id.length > 0);
|
166
|
+
|
167
|
+
var checkAutocomplete = oldValue == true? false : true;
|
168
|
+
// check if the Value ist new
|
169
|
+
var isNewResult = isNew($(this).val(), checkAutocomplete);
|
170
|
+
if(isNewResult[0] === true || (isNewResult[0] === false && typeof isNewResult[1] == 'string')) {
|
171
|
+
|
172
|
+
if(oldValue == false && typeof isNewResult[1] == 'string') {
|
173
|
+
oldValue = true;
|
174
|
+
id = isNewResult[1];
|
175
|
+
}
|
176
|
+
|
177
|
+
if(options.allowAdd == true || oldValue) {
|
178
|
+
// Make a new tag in front the input
|
179
|
+
html = '<li class="tagedit-listelement tagedit-listelement-old">';
|
180
|
+
html += '<span dir="'+options.direction+'">' + $(this).val() + '</span>';
|
181
|
+
var name = oldValue? baseName + '['+id+options.addedPostfix+']' : baseName + '[]';
|
182
|
+
html += '<input type="hidden" name="'+name+'" value="'+$(this).val()+'" />';
|
183
|
+
html += '<a class="tagedit-close" title="'+options.texts.removeLinkTitle+'">x</a>';
|
184
|
+
html += '</li>';
|
185
|
+
|
186
|
+
$(this).parent().before(html);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
$(this).val('');
|
190
|
+
|
191
|
+
// close autocomplete
|
192
|
+
if(options.autocompleteOptions.source) {
|
193
|
+
$(this).autocomplete( "close" );
|
194
|
+
}
|
195
|
+
|
196
|
+
})
|
197
|
+
.keydown(function(event) {
|
198
|
+
var code = event.keyCode > 0? event.keyCode : event.which;
|
199
|
+
|
200
|
+
switch(code) {
|
201
|
+
case 8: // BACKSPACE
|
202
|
+
if($(this).val().length == 0) {
|
203
|
+
// delete Last Tag
|
204
|
+
var elementToRemove = elements.find('li.tagedit-listelement-old').last();
|
205
|
+
elementToRemove.fadeOut(options.animSpeed, function() {elementToRemove.remove();})
|
206
|
+
event.preventDefault();
|
207
|
+
return false;
|
208
|
+
}
|
209
|
+
break;
|
210
|
+
case 9: // TAB
|
211
|
+
if($(this).val().length > 0 && $('ul.ui-autocomplete #ui-active-menuitem').length == 0) {
|
212
|
+
$(this).trigger('transformToTag');
|
213
|
+
event.preventDefault();
|
214
|
+
return false;
|
215
|
+
}
|
216
|
+
break;
|
217
|
+
}
|
218
|
+
return true;
|
219
|
+
})
|
220
|
+
.keypress(function(event) {
|
221
|
+
var code = event.keyCode > 0? event.keyCode : event.which;
|
222
|
+
if($.inArray(code, options.breakKeyCodes) > -1) {
|
223
|
+
if($(this).val().length > 0 && $('ul.ui-autocomplete #ui-active-menuitem').length == 0) {
|
224
|
+
$(this).trigger('transformToTag');
|
225
|
+
}
|
226
|
+
event.preventDefault();
|
227
|
+
return false;
|
228
|
+
}
|
229
|
+
return true;
|
230
|
+
})
|
231
|
+
.bind('paste', function(e){
|
232
|
+
var that = $(this);
|
233
|
+
if (e.type == 'paste'){
|
234
|
+
setTimeout(function(){
|
235
|
+
that.trigger('transformToTag');
|
236
|
+
}, 1);
|
237
|
+
}
|
238
|
+
})
|
239
|
+
.blur(function() {
|
240
|
+
if($(this).val().length == 0) {
|
241
|
+
// disable the field to prevent sending with the form
|
242
|
+
$(this).attr('disabled', 'disabled').addClass('tagedit-input-disabled');
|
243
|
+
}
|
244
|
+
else {
|
245
|
+
// Delete entry after a timeout
|
246
|
+
var input = $(this);
|
247
|
+
$(this).data('blurtimer', window.setTimeout(function() {input.val('');}, 500));
|
248
|
+
}
|
249
|
+
})
|
250
|
+
.focus(function() {
|
251
|
+
window.clearTimeout($(this).data('blurtimer'));
|
252
|
+
});
|
253
|
+
|
254
|
+
if(options.autocompleteOptions.source != false) {
|
255
|
+
$(this).autocomplete(options.autocompleteOptions);
|
256
|
+
}
|
257
|
+
})
|
258
|
+
.end()
|
259
|
+
.click(function(event) {
|
260
|
+
switch(event.target.tagName) {
|
261
|
+
case 'A':
|
262
|
+
$(event.target).parent().fadeOut(options.animSpeed, function() {
|
263
|
+
$(event.target).parent().remove();
|
264
|
+
});
|
265
|
+
break;
|
266
|
+
case 'INPUT':
|
267
|
+
case 'SPAN':
|
268
|
+
case 'LI':
|
269
|
+
if($(event.target).hasClass('tagedit-listelement-deleted') == false &&
|
270
|
+
$(event.target).parent('li').hasClass('tagedit-listelement-deleted') == false) {
|
271
|
+
// Don't edit an deleted Items
|
272
|
+
return doEdit(event);
|
273
|
+
}
|
274
|
+
default:
|
275
|
+
$(this).find('#tagedit-input')
|
276
|
+
.removeAttr('disabled')
|
277
|
+
.removeClass('tagedit-input-disabled')
|
278
|
+
.focus();
|
279
|
+
}
|
280
|
+
return false;
|
281
|
+
})
|
282
|
+
}
|
283
|
+
|
284
|
+
/**
|
285
|
+
* Sets all Actions and events for editing an Existing Tag.
|
286
|
+
*
|
287
|
+
* @param event {object} The original Event that was given
|
288
|
+
* return {boolean}
|
289
|
+
*/
|
290
|
+
function doEdit(event) {
|
291
|
+
if(options.allowEdit == false) {
|
292
|
+
// Do nothing
|
293
|
+
return;
|
294
|
+
}
|
295
|
+
|
296
|
+
var element = event.target.tagName == 'SPAN'? $(event.target).parent() : $(event.target);
|
297
|
+
|
298
|
+
var closeTimer = null;
|
299
|
+
|
300
|
+
// Event that is fired if the User finishes the edit of a tag
|
301
|
+
element.bind('finishEdit', function(event, doReset) {
|
302
|
+
window.clearTimeout(closeTimer);
|
303
|
+
|
304
|
+
var textfield = $(this).find(':text');
|
305
|
+
var isNewResult = isNew(textfield.val(), true);
|
306
|
+
if(textfield.val().length > 0 && (typeof doReset == 'undefined' || doReset === false) && (isNewResult[0] == true)) {
|
307
|
+
// This is a new Value and we do not want to do a reset. Set the new value
|
308
|
+
$(this).find(':hidden').val(textfield.val());
|
309
|
+
$(this).find('span').html(textfield.val());
|
310
|
+
}
|
311
|
+
|
312
|
+
textfield.remove();
|
313
|
+
$(this).find('a.tagedit-save, a.tagedit-break, a.tagedit-delete, tester').remove(); // Workaround. This normaly has to be done by autogrow Plugin
|
314
|
+
$(this).removeClass('tagedit-listelement-edit').unbind('finishEdit');
|
315
|
+
return false;
|
316
|
+
});
|
317
|
+
|
318
|
+
var hidden = element.find(':hidden');
|
319
|
+
html = '<input type="text" name="tmpinput" autocomplete="off" value="'+hidden.val()+'" class="tagedit-edit-input" dir="'+options.direction+'"/>';
|
320
|
+
html += '<a class="tagedit-save" title="'+options.texts.saveEditLinkTitle+'">o</a>';
|
321
|
+
html += '<a class="tagedit-break" title="'+options.texts.breakEditLinkTitle+'">x</a>';
|
322
|
+
|
323
|
+
// If the Element is one from the Database, it can be deleted
|
324
|
+
if(options.allowDelete == true && element.find(':hidden').length > 0 &&
|
325
|
+
typeof element.find(':hidden').attr('name').match(baseNameRegexp)[3] != 'undefined') {
|
326
|
+
html += '<a class="tagedit-delete" title="'+options.texts.deleteLinkTitle+'">d</a>';
|
327
|
+
}
|
328
|
+
|
329
|
+
hidden.after(html);
|
330
|
+
element
|
331
|
+
.addClass('tagedit-listelement-edit')
|
332
|
+
.find('a.tagedit-save')
|
333
|
+
.click(function() {
|
334
|
+
$(this).parent().trigger('finishEdit');
|
335
|
+
return false;
|
336
|
+
})
|
337
|
+
.end()
|
338
|
+
.find('a.tagedit-break')
|
339
|
+
.click(function() {
|
340
|
+
$(this).parent().trigger('finishEdit', [true]);
|
341
|
+
return false;
|
342
|
+
})
|
343
|
+
.end()
|
344
|
+
.find('a.tagedit-delete')
|
345
|
+
.click(function() {
|
346
|
+
window.clearTimeout(closeTimer);
|
347
|
+
if(confirm(options.texts.deleteConfirmation)) {
|
348
|
+
markAsDeleted($(this).parent());
|
349
|
+
}
|
350
|
+
else {
|
351
|
+
$(this).parent().find(':text').trigger('finishEdit', [true]);
|
352
|
+
}
|
353
|
+
return false;
|
354
|
+
})
|
355
|
+
.end()
|
356
|
+
.find(':text')
|
357
|
+
.focus()
|
358
|
+
.autoGrowInput({comfortZone: 10, minWidth: 15, maxWidth: 20000})
|
359
|
+
.keypress(function(event) {
|
360
|
+
switch(event.keyCode) {
|
361
|
+
case 13: // RETURN
|
362
|
+
event.preventDefault();
|
363
|
+
$(this).parent().trigger('finishEdit');
|
364
|
+
return false;
|
365
|
+
case 27: // ESC
|
366
|
+
event.preventDefault();
|
367
|
+
$(this).parent().trigger('finishEdit', [true]);
|
368
|
+
return false;
|
369
|
+
}
|
370
|
+
return true;
|
371
|
+
})
|
372
|
+
.blur(function() {
|
373
|
+
var that = $(this);
|
374
|
+
closeTimer = window.setTimeout(function() {that.parent().trigger('finishEdit', [true])}, 500);
|
375
|
+
});
|
376
|
+
}
|
377
|
+
|
378
|
+
/**
|
379
|
+
* Marks a single Tag as deleted.
|
380
|
+
*
|
381
|
+
* @param element {object}
|
382
|
+
*/
|
383
|
+
function markAsDeleted(element) {
|
384
|
+
element
|
385
|
+
.trigger('finishEdit', [true])
|
386
|
+
.addClass('tagedit-listelement-deleted')
|
387
|
+
.attr('title', options.deletedElementTitle);
|
388
|
+
element.find(':hidden').each(function() {
|
389
|
+
var nameEndRegexp = new RegExp('('+options.addedPostfix+'|'+options.deletedPostfix+')?\]');
|
390
|
+
var name = $(this).attr('name').replace(nameEndRegexp, options.deletedPostfix+']');
|
391
|
+
$(this).attr('name', name);
|
392
|
+
});
|
393
|
+
|
394
|
+
}
|
395
|
+
|
396
|
+
/**
|
397
|
+
* Checks if a tag is already choosen.
|
398
|
+
*
|
399
|
+
* @param value {string}
|
400
|
+
* @param checkAutocomplete {boolean} optional Check also the autocomplet values
|
401
|
+
* @returns {Array} First item is a boolean, telling if the item should be put to the list, second is optional the ID from autocomplete list
|
402
|
+
*/
|
403
|
+
function isNew(value, checkAutocomplete) {
|
404
|
+
checkAutocomplete = typeof checkAutocomplete == 'undefined'? false : checkAutocomplete;
|
405
|
+
var autoCompleteId = null;
|
406
|
+
|
407
|
+
var compareValue = options.checkNewEntriesCaseSensitive == true? value : value.toLowerCase();
|
408
|
+
|
409
|
+
var isNew = true;
|
410
|
+
elements.find('li.tagedit-listelement-old input:hidden').each(function() {
|
411
|
+
var elementValue = options.checkNewEntriesCaseSensitive == true? $(this).val() : $(this).val().toLowerCase();
|
412
|
+
if(elementValue == compareValue) {
|
413
|
+
isNew = false;
|
414
|
+
}
|
415
|
+
});
|
416
|
+
|
417
|
+
if (isNew == true && checkAutocomplete == true && options.autocompleteOptions.source != false) {
|
418
|
+
var result = [];
|
419
|
+
if ($.isArray(options.autocompleteOptions.source)) {
|
420
|
+
result = options.autocompleteOptions.source;
|
421
|
+
}
|
422
|
+
else if ($.isFunction(options.autocompleteOptions.source)) {
|
423
|
+
options.autocompleteOptions.source({term: value}, function (data) {result = data});
|
424
|
+
}
|
425
|
+
else if (typeof options.autocompleteOptions.source === "string") {
|
426
|
+
// Check also autocomplete values
|
427
|
+
var autocompleteURL = options.autocompleteOptions.source;
|
428
|
+
if (autocompleteURL.match(/\?/)) {
|
429
|
+
autocompleteURL += '&';
|
430
|
+
} else {
|
431
|
+
autocompleteURL += '?';
|
432
|
+
}
|
433
|
+
autocompleteURL += 'term=' + value;
|
434
|
+
$.ajax({
|
435
|
+
async: false,
|
436
|
+
url: autocompleteURL,
|
437
|
+
dataType: 'json',
|
438
|
+
complete: function (XMLHttpRequest, textStatus) {
|
439
|
+
result = $.parseJSON(XMLHttpRequest.responseText);
|
440
|
+
}
|
441
|
+
});
|
442
|
+
}
|
443
|
+
|
444
|
+
// If there is an entry for that already in the autocomplete, don't use it (Check could be case sensitive or not)
|
445
|
+
for (var i = 0; i < result.length; i++) {
|
446
|
+
var label = options.checkNewEntriesCaseSensitive == true? result[i].label : result[i].label.toLowerCase();
|
447
|
+
if (label == compareValue) {
|
448
|
+
isNew = false;
|
449
|
+
autoCompleteId = result[i].id;
|
450
|
+
break;
|
451
|
+
}
|
452
|
+
}
|
453
|
+
}
|
454
|
+
|
455
|
+
return new Array(isNew, autoCompleteId);
|
456
|
+
}
|
457
|
+
}
|
458
|
+
})(jQuery);
|