// When enabled, quotes are not neccesary
// for inputting multi-word tags.
allowSpaces: false,
// Whether to animate tag removals or not.
animate: true,
// The below options are for using a single field instead of several
// for our form values.
//
// When enabled, will use a single hidden field for the form,
// rather than one per tag. It will delimit tags in the field
// with singleFieldDelimiter.
//
// The easiest way to use singleField is to just instantiate tag-it
// on an INPUT element, in which case singleField is automatically
// set to true, and singleFieldNode is set to that element. This
// way, you don't need to fiddle with these options.
singleField: false,
singleFieldDelimiter: ‹,›,
// Set this to an input DOM node to use an existing form field.
// Any text in it will be erased on init. But it will be
// populated with the text of tags as they are created,
// delimited by singleFieldDelimiter.
//
// If this is not set, we create an input node for it,
// with the name given in settings.fieldName,
// ignoring settings.itemName.
singleFieldNode: null,
// Optionally set a tabindex attribute on the input that gets
// created for tag-it.
tabIndex: null,
_create: function() {
// for handling static scoping inside callbacks
var that = this;
// There are 2 kinds of DOM nodes this widget can be instantiated on:
// 1. UL, OL, or some element containing either of these.
// 2. INPUT, in which case ‹singleField› is overridden to true,
// a UL is created and the INPUT is hidden.
if (this.element.is(‹input›)) {
this.tagList = $(‹<ul></ul>›).insertAfter(this.element);
this.options.singleField = true;
this.options.singleFieldNode = this.element;
this.element.css(‹display›, ‹none›);
} else {
this.tagList = this.element.find(‹ul, ol›).andSelf().last();
}
this._tagInput = $(‹<input type=«text»
/>›).addClass(‹ui-widget-content›);
if (this.options.tabIndex) {
this._tagInput.attr(‹tabindex›, this.options.tabIndex);
}
if (this.options.placeholderText) {
this._tagInput.attr(‹placeholder›, this.options.placeholderText);
}
this.options.tagSource = this.options.tagSource || function(search,
showChoices) {
var filter = search.term.toLowerCase();
var choices = $.grep(this.options.availableTags, function(element) {
// Only match autocomplete options that begin with the search term.
// (Case insensitive.)
return (element.toLowerCase().indexOf(filter) === 0);
});
showChoices(this._subtractArray(choices, this.assignedTags()));
};
// Bind tagSource callback functions to this context.
if ($.isFunction(this.options.tagSource)) {
this.options.tagSource = $.proxy(this.options.tagSource, this);
}
this.tagList
.addClass(‹tagit›)
.addClass(‹ui-widget ui-widget-content ui-corner-all›)
// Create the input field.
.append($(‹<li
class=«tagit-new»></li>›).append(this._tagInput))
.click(function(e) {
var target = $(e.target);
if (target.hasClass(‹tagit-label›)) {
that._trigger(‹onTagClicked›, e,
target.closest(‹.tagit-choice›));
} else {
// Sets the focus() to the input field, if the user
// clicks anywhere inside the UL. This is needed
// because the input field needs to be of a small size.
that._tagInput.focus();
}
});
// Add existing tags from the list, if any.
this.tagList.children(‹li›).each(function() {
if (!$(this).hasClass(‹tagit-new›)) {
that.createTag($(this).html(), $(this).attr(‹class›));
$(this).remove();
}
});
// Single field support.
if (this.options.singleField) {
if (this.options.singleFieldNode) {
// Add existing tags from the input field.
var node = $(this.options.singleFieldNode);
var tags = node.val().split(this.options.singleFieldDelimiter);
node.val('');
$.each(tags, function(index, tag) {
that.createTag(tag);
});
} else {
// Create our single field input after our list.
this.options.singleFieldNode = this.tagList.after(‹<input
type=«hidden» style=«display:none;» value="" name=«› +
this.options.fieldName + ‹» />›);
}
}
// Events.
this._tagInput
.keydown(function(event) {
// Backspace is not detected within a keypress, so it must use keydown.
if (event.which == $.ui.keyCode.BACKSPACE && that._tagInput.val()
=== '') {
var tag = that._lastTag();
if (!that.options.removeConfirmation || tag.hasClass(‹remove›)) {
// When backspace is pressed, the last tag is deleted.
that.removeTag(tag);
} else if (that.options.removeConfirmation) {
tag.addClass(‹remove ui-state-highlight›);
}
} else if (that.options.removeConfirmation) {
that._lastTag().removeClass(‹remove ui-state-highlight›);
}
// Comma/Space/Enter are all valid delimiters for new tags,
// except when there is an open quote or if setting allowSpaces = true.
// Tab will also create a tag, unless the tag input is empty, in which case it
isn't caught.
if (
event.which == $.ui.keyCode.COMMA ||
event.which == $.ui.keyCode.ENTER ||
(
event.which == $.ui.keyCode.TAB &&
that._tagInput.val() !== ''
) ||
(
event.which == $.ui.keyCode.SPACE &&
that.options.allowSpaces !== true &&
(
$.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) !=
‹"› ||
// The autocomplete doesn't close automatically when TAB is pressed.
// So let's ensure that it closes.
that._tagInput.autocomplete(‹close›);
}
}).blur(function(e){
// Create a tag when the element loses focus (unless it's empty).
that.createTag(that._cleanedInput());
});
// Autocomplete.
if (this.options.availableTags || this.options.tagSource) {
this._tagInput.autocomplete({
source: this.options.tagSource,
select: function(event, ui) {
// Delete the last tag if we autocomplete something despite the input being
empty
// This happens because the input's blur event causes the tag to be created
when
// the user clicks an autocomplete item.
// The only artifact of this is that while the user holds down the mouse
button
// on the selected autocomplete item, a tag is shown with the pre-autocompleted
text,
// and is changed to the autocompleted text upon mouseup.
if (that._tagInput.val() === '') {
that.removeTag(that._lastTag(), false);
}
that.createTag(ui.item.value);
// Preventing the tag input to be updated with the chosen value.
return false;
}
});
}
},
_cleanedInput: function() {
// Returns the contents of the tag input, cleaned and ready to be passed to
createTag
return $.trim(this._tagInput.val().replace(/^«(.*)»$/, ‹$1›));
},
assignedTags: function() {
// Returns an array of tag string values
var that = this;
var tags = [];
if (this.options.singleField) {
tags =
$(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter);
if (tags[0] === '') {
tags = [];
}
} else {
this.tagList.children(‹.tagit-choice›).each(function() {
tags.push(that.tagLabel(this));
});
}
return tags;
},
_updateSingleTagsField: function(tags) {
// Takes a list of tag string values, updates this.options.singleFieldNode.val
to the tags delimited by this.options.singleFieldDelimiter
$(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter));
},
_subtractArray: function(a1, a2) {
var result = [];
for (var i = 0; i < a1.length; i++) {
if ($.inArray(a1[i], a2) == -1) {
result.push(a1[i]);
}
}
return result;
},
createTag: function(value, additionalClass) {
var that = this;
// Automatically trims the value of leading and trailing whitespace.
value = $.trim(value);
if (!this._isNew(value) || value === '') {
return false;
}
var label = $(this.options.onTagClicked ? ‹<a
class=«tagit-label»>› : ‹<span
class=«tagit-label»></span>›).text(value);
// Create tag.
var tag = $(‹<li></li>›)
.addClass(‹tagit-choice ui-widget-content ui-state-default
ui-corner-all›)
.addClass(additionalClass)
.append(label);
// Button for removing the tag.
var removeTagIcon = $(‹<span></span>›)
.addClass(‹ui-icon ui-icon-close›);
var removeTag = $(‹<a><span
class=«text-icon»>\xd7</span>›) // \xd7 is an X
.addClass(‹tagit-close›)
.append(removeTagIcon)
.click(function(e) {
// Removes a tag when the little ‹x› is clicked.
that.removeTag(tag);
});
tag.append(removeTag);
// Unless options.singleField is set, each tag has a hidden input field
inline.
if (this.options.singleField) {
var tags = this.assignedTags();
tags.push(value);
this._updateSingleTagsField(tags);
} else {
var escapedValue = label.html();
tag.append(‹<input type=«hidden» style=«display:none;» value=«› +
escapedValue + ‹» name=«› + this.options.itemName + ‹[› +
this.options.fieldName + ‹][]» />›);
}
this._trigger(‹onTagAdded›, null, tag);
// Cleaning the input.
this._tagInput.val('');
// insert tag
this._tagInput.parent().before(tag);
},
http://www.youtube.com/watch?…
>>944155
Невидимый шревт дохуя штоле?
>>944170
Можно сделать ссылку на пикчу, которая нихуя не пикча.
(function($) {
$.widget(‹ui.tagit›, {
options: {
itemName : ‹item›,
fieldName : ‹tags›,
availableTags : [],
tagSource : null,
removeConfirmation: false,
caseSensitive : true,
placeholderText : null,
// When enabled, quotes are not neccesary
// for inputting multi-word tags.
allowSpaces: false,
// Whether to animate tag removals or not.
animate: true,
// The below options are for using a single field instead of several
// for our form values.
//
// When enabled, will use a single hidden field for the form,
// rather than one per tag. It will delimit tags in the field
// with singleFieldDelimiter.
//
// The easiest way to use singleField is to just instantiate tag-it
// on an INPUT element, in which case singleField is automatically
// set to true, and singleFieldNode is set to that element. This
// way, you don't need to fiddle with these options.
singleField: false,
singleFieldDelimiter: ‹,›,
// Set this to an input DOM node to use an existing form field.
// Any text in it will be erased on init. But it will be
// populated with the text of tags as they are created,
// delimited by singleFieldDelimiter.
//
// If this is not set, we create an input node for it,
// with the name given in settings.fieldName,
// ignoring settings.itemName.
singleFieldNode: null,
// Optionally set a tabindex attribute on the input that gets
// created for tag-it.
tabIndex: null,
// Event callbacks.
onTagAdded : null,
onTagRemoved: null,
onTagClicked: null
},
_create: function() {
// for handling static scoping inside callbacks
var that = this;
// There are 2 kinds of DOM nodes this widget can be instantiated on:
// 1. UL, OL, or some element containing either of these.
// 2. INPUT, in which case ‹singleField› is overridden to true,
// a UL is created and the INPUT is hidden.
if (this.element.is(‹input›)) {
this.tagList = $(‹<ul></ul>›).insertAfter(this.element);
this.options.singleField = true;
this.options.singleFieldNode = this.element;
this.element.css(‹display›, ‹none›);
} else {
this.tagList = this.element.find(‹ul, ol›).andSelf().last();
}
this._tagInput = $(‹<input type=«text» />›).addClass(‹ui-widget-content›);
if (this.options.tabIndex) {
this._tagInput.attr(‹tabindex›, this.options.tabIndex);
}
if (this.options.placeholderText) {
this._tagInput.attr(‹placeholder›, this.options.placeholderText);
}
this.options.tagSource = this.options.tagSource || function(search, showChoices) {
var filter = search.term.toLowerCase();
var choices = $.grep(this.options.availableTags, function(element) {
// Only match autocomplete options that begin with the search term.
// (Case insensitive.)
return (element.toLowerCase().indexOf(filter) === 0);
});
showChoices(this._subtractArray(choices, this.assignedTags()));
};
// Bind tagSource callback functions to this context.
if ($.isFunction(this.options.tagSource)) {
this.options.tagSource = $.proxy(this.options.tagSource, this);
}
Оп как бы говорит нам —
—
такая параша, что никаких слов, чтоб описать
её не хватит.
this.tagList
.addClass(‹tagit›)
.addClass(‹ui-widget ui-widget-content ui-corner-all›)
// Create the input field.
.append($(‹<li class=«tagit-new»></li>›).append(this._tagInput))
.click(function(e) {
var target = $(e.target);
if (target.hasClass(‹tagit-label›)) {
that._trigger(‹onTagClicked›, e, target.closest(‹.tagit-choice›));
} else {
// Sets the focus() to the input field, if the user
// clicks anywhere inside the UL. This is needed
// because the input field needs to be of a small size.
that._tagInput.focus();
}
});
// Add existing tags from the list, if any.
this.tagList.children(‹li›).each(function() {
if (!$(this).hasClass(‹tagit-new›)) {
that.createTag($(this).html(), $(this).attr(‹class›));
$(this).remove();
}
});
// Single field support.
if (this.options.singleField) {
if (this.options.singleFieldNode) {
// Add existing tags from the input field.
var node = $(this.options.singleFieldNode);
var tags = node.val().split(this.options.singleFieldDelimiter);
node.val('');
$.each(tags, function(index, tag) {
that.createTag(tag);
});
} else {
// Create our single field input after our list.
this.options.singleFieldNode = this.tagList.after(‹<input type=«hidden» style=«display:none;» value="" name=«› + this.options.fieldName + ‹» />›);
}
}
Съеби, баттхёрток.
// Events.
this._tagInput
.keydown(function(event) {
// Backspace is not detected within a keypress, so it must use keydown.
if (event.which == $.ui.keyCode.BACKSPACE && that._tagInput.val() === '') {
var tag = that._lastTag();
if (!that.options.removeConfirmation || tag.hasClass(‹remove›)) {
// When backspace is pressed, the last tag is deleted.
that.removeTag(tag);
} else if (that.options.removeConfirmation) {
tag.addClass(‹remove ui-state-highlight›);
}
} else if (that.options.removeConfirmation) {
that._lastTag().removeClass(‹remove ui-state-highlight›);
}
// Comma/Space/Enter are all valid delimiters for new tags,
// except when there is an open quote or if setting allowSpaces = true.
// Tab will also create a tag, unless the tag input is empty, in which case it isn't caught.
if (
event.which == $.ui.keyCode.COMMA ||
event.which == $.ui.keyCode.ENTER ||
(
event.which == $.ui.keyCode.TAB &&
that._tagInput.val() !== ''
) ||
(
event.which == $.ui.keyCode.SPACE &&
that.options.allowSpaces !== true &&
(
$.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) != ‹"› ||
(
event.which == $.ui.keyCode.SPACE &&
that.options.allowSpaces !== true &&
(
$.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) != ‹«› ||
(
$.trim(that._tagInput.val()).charAt(0) == ‹»› &&
$.trim(that._tagInput.val()).charAt($.trim(that._tagInput.val()).length — 1) == ‹"› &&
$.trim(that._tagInput.val()).length — 1 !== 0
)
)
)
) {
event.preventDefault();
that.createTag(that._cleanedInput());
// The autocomplete doesn't close automatically when TAB is pressed.
// So let's ensure that it closes.
that._tagInput.autocomplete(‹close›);
}
}).blur(function(e){
// Create a tag when the element loses focus (unless it's empty).
that.createTag(that._cleanedInput());
});
// Autocomplete.
if (this.options.availableTags || this.options.tagSource) {
this._tagInput.autocomplete({
source: this.options.tagSource,
select: function(event, ui) {
// Delete the last tag if we autocomplete something despite the input being empty
// This happens because the input's blur event causes the tag to be created when
// the user clicks an autocomplete item.
// The only artifact of this is that while the user holds down the mouse button
// on the selected autocomplete item, a tag is shown with the pre-autocompleted text,
// and is changed to the autocompleted text upon mouseup.
if (that._tagInput.val() === '') {
that.removeTag(that._lastTag(), false);
}
that.createTag(ui.item.value);
// Preventing the tag input to be updated with the chosen value.
return false;
}
});
}
},
_cleanedInput: function() {
// Returns the contents of the tag input, cleaned and ready to be passed to createTag
return $.trim(this._tagInput.val().replace(/^«(.*)»$/, ‹$1›));
},
_lastTag: function() {
return this.tagList.children(‹.tagit-choice:last›);
},
assignedTags: function() {
// Returns an array of tag string values
var that = this;
var tags = [];
if (this.options.singleField) {
tags = $(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter);
if (tags[0] === '') {
tags = [];
}
} else {
this.tagList.children(‹.tagit-choice›).each(function() {
tags.push(that.tagLabel(this));
});
}
return tags;
},
_updateSingleTagsField: function(tags) {
// Takes a list of tag string values, updates this.options.singleFieldNode.val to the tags delimited by this.options.singleFieldDelimiter
$(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter));
},
_subtractArray: function(a1, a2) {
var result = [];
for (var i = 0; i < a1.length; i++) {
if ($.inArray(a1[i], a2) == -1) {
result.push(a1[i]);
}
}
return result;
},
tagLabel: function(tag) {
// Returns the tag's string label.
if (this.options.singleField) {
return $(tag).children(‹.tagit-label›).text();
} else {
return $(tag).children(‹input›).val();
}
},
_isNew: function(value) {
var that = this;
var isNew = true;
this.tagList.children(‹.tagit-choice›).each(function(i) {
if (that._formatStr(value) == that._formatStr(that.tagLabel(this))) {
isNew = false;
return false;
}
});
return isNew;
},
_formatStr: function(str) {
if (this.options.caseSensitive) {
return str;
}
return $.trim(str.toLowerCase());
},
createTag: function(value, additionalClass) {
var that = this;
// Automatically trims the value of leading and trailing whitespace.
value = $.trim(value);
if (!this._isNew(value) || value === '') {
return false;
}
var label = $(this.options.onTagClicked ? ‹<a class=«tagit-label»>› : ‹<span class=«tagit-label»></span>›).text(value);
// Create tag.
var tag = $(‹<li></li>›)
.addClass(‹tagit-choice ui-widget-content ui-state-default ui-corner-all›)
.addClass(additionalClass)
.append(label);
// Button for removing the tag.
var removeTagIcon = $(‹<span></span>›)
.addClass(‹ui-icon ui-icon-close›);
var removeTag = $(‹<a><span class=«text-icon»>\xd7</span>›) // \xd7 is an X
.addClass(‹tagit-close›)
.append(removeTagIcon)
.click(function(e) {
// Removes a tag when the little ‹x› is clicked.
that.removeTag(tag);
});
tag.append(removeTag);
// Unless options.singleField is set, each tag has a hidden input field inline.
if (this.options.singleField) {
var tags = this.assignedTags();
tags.push(value);
this._updateSingleTagsField(tags);
} else {
var escapedValue = label.html();
tag.append(‹<input type=«hidden» style=«display:none;» value=«› + escapedValue + ‹» name=«› + this.options.itemName + ‹[› + this.options.fieldName + ‹][]» />›);
}
this._trigger(‹onTagAdded›, null, tag);
// Cleaning the input.
this._tagInput.val('');
// insert tag
this._tagInput.parent().before(tag);
},
removeTag: function(tag, animate) {
animate = animate || this.options.animate;
tag = $(tag);
this._trigger(‹onTagRemoved›, null, tag);
if (this.options.singleField) {
var tags = this.assignedTags();
var removedTagLabel = this.tagLabel(tag);
tags = $.grep(tags, function(el){
return el != removedTagLabel;
});
this._updateSingleTagsField(tags);
}
// Animate the removal.
if (animate) {
tag.fadeOut(‹fast›).hide(‹blind›, {direction: ‹horizontal›}, ‹fast›, function(){
tag.remove();
}).dequeue();
} else {
tag.remove();
}
},
removeAll: function() {
// Removes all tags.
var that = this;
this.tagList.children(‹.tagit-choice›).each(function(index, tag) {
that.removeTag(tag, false);
});
}
});
})(jQuery);
(← + Сtrl) вернуться назадк новым сообщениям (Сtrl + →)