forked from ScoDoc/ScoDoc
462 lines
28 KiB
HTML
462 lines
28 KiB
HTML
|
<!DOCTYPE html><html lang="en">
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<title>jQuery tagEditor Plugin</title>
|
||
|
<meta name="description" content="A lightweight and sophisticated tag editor for jQuery. Sortable, editable tags with cursor navigation, autocomplete, and callbacks.">
|
||
|
<link rel="shortcut icon" href="https://pixabay.com/favicon.ico">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300">
|
||
|
<link rel="stylesheet" href="https://cdn.rawgit.com/yahoo/pure-release/v0.6.0/pure-min.css">
|
||
|
<style>
|
||
|
body { margin: 0; padding: 0; border: 0; min-width: 320px; color: #777; }
|
||
|
html, button, input, select, textarea, .pure-g [class *= "pure-u"] { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1.02em; }
|
||
|
p, td { line-height: 1.5; }
|
||
|
ul { padding: 0 0 0 20px; }
|
||
|
|
||
|
th { background: #eee; white-space: nowrap; }
|
||
|
th, td { padding: 10px; text-align: left; vertical-align: top; font-size: .9em; font-weight: normal; border-right: 1px solid #fff; }
|
||
|
td:first-child { white-space: nowrap; color: #008000; width: 1%; font-style: italic; }
|
||
|
|
||
|
h1, h2, h3 { color: #4b4b4b; font-family: "Source Sans Pro", sans-serif; font-weight: 300; margin: 0 0 1.2em; }
|
||
|
h1 { font-size: 4.5em; color: #1f8dd6; margin: 0 0 .4em; }
|
||
|
h2 { font-size: 2em; color: #636363; }
|
||
|
h3 { font-size: 1.8em; color: #4b4b4b; margin: 1.8em 0 .8em }
|
||
|
h4 { font: bold 1em sans-serif; color: #636363; margin: 4em 0 1em; }
|
||
|
a { color: #4e99c7; text-decoration: none; }
|
||
|
a:hover { text-decoration: underline; }
|
||
|
p, pre { margin: 0 0 1.2em; }
|
||
|
::selection { color: #fff; background: #328efd; }
|
||
|
::-moz-selection { color: #fff; background: #328efd; }
|
||
|
|
||
|
@media (max-width:480px) {
|
||
|
h1 { font-size: 3em; }
|
||
|
h2 { font-size: 1.8em; }
|
||
|
h3 { font-size: 1.5em; }
|
||
|
td:first-child { white-space: normal; }
|
||
|
}
|
||
|
|
||
|
.inline-code { padding: 1px 5px; background: #eee; border-radius: 2px; }
|
||
|
pre { padding: 15px 10px; font-size: .9em; color: #555; background: #edf3f8; }
|
||
|
pre i { color: #aaa; } /* comments */
|
||
|
pre b { font-weight: normal; color: #cf4b25; } /* strings */
|
||
|
pre em { color: #0c59e9; } /* numeric */
|
||
|
|
||
|
/* Pure CSS */
|
||
|
.pure-button { margin: 5px 0; text-decoration: none !important; }
|
||
|
.button-lg { margin: 5px 0; padding: .65em 1.6em; font-size: 105%; }
|
||
|
.button-sm { font-size: 85%; }
|
||
|
|
||
|
textarea {
|
||
|
width: 100%; height: 29px; padding: .3em .5em; border: 1px solid #ddd; font-size: .9em;
|
||
|
box-sizing: border-box; margin: 0 0 20px;
|
||
|
}
|
||
|
textarea[readonly] { color: #aaa; background: #f7f7f7; }
|
||
|
|
||
|
#response {
|
||
|
margin: 0 0 1.2em; padding: 10px; background: #f3f3f3; color: #777;
|
||
|
font-size: .9em; max-height: 150px; overflow: hidden; overflow-y: auto;
|
||
|
}
|
||
|
#response i { font-style: normal; color: #cf4b25; }
|
||
|
#response hr { margin: 2px 0; border: 0; border-top: 1px solid #eee; border-bottom: 1px solid #fdfdfd; }
|
||
|
|
||
|
/* overwrite default CSS for tiny, dark tags in demo5 */
|
||
|
#demo5+.tag-editor { background: #fafafa; font-size: 12px; }
|
||
|
#demo5+.tag-editor .tag-editor-tag { color: #fff; background: #555; border-radius: 2px; }
|
||
|
#demo5+.tag-editor .tag-editor-spacer { width: 7px; }
|
||
|
#demo5+.tag-editor .tag-editor-delete { display: none; }
|
||
|
|
||
|
/* color tags */
|
||
|
.tag-editor .red-tag .tag-editor-tag { color: #c65353; background: #ffd7d7; }
|
||
|
.tag-editor .red-tag .tag-editor-delete { background-color: #ffd7d7; }
|
||
|
.tag-editor .green-tag .tag-editor-tag { color: #45872c; background: #e1f3da; }
|
||
|
.tag-editor .green-tag .tag-editor-delete { background-color: #e1f3da; }
|
||
|
</style>
|
||
|
<link rel="stylesheet" href="jquery.tag-editor.css">
|
||
|
</head>
|
||
|
<body>
|
||
|
<div style="max-width:900px;padding:0 10px;margin:40px auto;text-align:center">
|
||
|
<h1>tagEditor</h1>
|
||
|
<h2>A powerful and lightweight tag editor plugin for jQuery.</h2>
|
||
|
<a href="https://github.com/Pixabay/jQuery-tagEditor/archive/master.zip" class="pure-button pure-button-primary button-lg">Download</a>
|
||
|
|
||
|
<a href="https://github.com/Pixabay/jQuery-tagEditor" class="pure-button button-lg">View on GitHub</a>
|
||
|
</div>
|
||
|
<div style="border-top: 1px solid #eee;border-bottom:1px solid #eee;background:#fafafa;margin:30px 0;padding:20px 5px">
|
||
|
<div style="padding :0 7px 0 5px;max-width:900px;margin:auto">
|
||
|
<textarea id="hero-demo">example tags, sortable, autocomplete, edit in place, tab/cursor navigation, duplicate check, callbacks, copy-paste, placeholder, public methods, custom delimiter, graceful degradation</textarea>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div style="max-width:900px;margin:auto;padding:0 10px 50px">
|
||
|
<h3>Overview and Features</h3>
|
||
|
<p>
|
||
|
Released under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.
|
||
|
Source on <a href="https://github.com/Pixabay/jQuery-tagEditor">Github</a> (<a href="https://github.com/Pixabay/jQuery-tagEditor#changelog">changelog</a>).
|
||
|
Compatible with jQuery 1.7.0+ in Firefox, Safari, Chrome, Opera, Internet Explorer 8+. IE7 technically works, but no care has gone into CSS/layout bugs.
|
||
|
tagEditor depends on accursoft's <a href="https://github.com/accursoft/caret">caret plugin</a> (1.1 kB minified).
|
||
|
</p>
|
||
|
<ul>
|
||
|
<li>Lightweight: 8.5 kB of JavaScript - less than 3.2 kB gzipped</li>
|
||
|
<li>Edit in place tags</li>
|
||
|
<li>Intuitive navigation between tags with cursor keys, Tab, Shift+Tab, Enter, Pos1, End, Backspace, Del, and ESC</li>
|
||
|
<li>Optional jQuery UI sortable</li>
|
||
|
<li>Optional jQuery UI autocomplete</li>
|
||
|
<li>Copy-paste or delete multiple selected tags</li>
|
||
|
<li>Duplicate tags check</li>
|
||
|
<li>Custom delimiter/s</li>
|
||
|
<li>Placeholder</li>
|
||
|
<li>Custom style for faulty tags</li>
|
||
|
<li>Public methods for reading, adding and removing tags + destroy function</li>
|
||
|
<li>Callbacks</li>
|
||
|
<li>Allows tabindex for form navigation</li>
|
||
|
<li>Graceful degradation if JavaScript is disabled</li>
|
||
|
</ul>
|
||
|
<p>
|
||
|
This plugin was developed by and for <a href="https://pixabay.com/">Pixabay.com</a> - an international repository for free Public Domain images.
|
||
|
We have implemented this piece of software in production and we share it - in the spirit of Pixabay - freely with others.
|
||
|
</p>
|
||
|
|
||
|
<h3>Usage</h3>
|
||
|
<p>
|
||
|
Include the stylesheet <span class="inline-code">jquery.tag-editor.css</span> in the <span class="inline-code"><head></span> section of your HTML document - and the JavaScript file <span class="inline-code">jquery.tag-editor.min.js</span> after loading jQuery and optional jQuery UI sortable/autocomplete.
|
||
|
Make sure to also load accursoft's <a href="http://code.accursoft.com/caret">caret plugin</a> (1.1 kB minified).
|
||
|
tagEditor accepts settings from an object of key/value pairs, and can be assigned to any text input field or textarea.
|
||
|
</p>
|
||
|
<pre>
|
||
|
$(selector).tagEditor({key1: value1, key2: value2});
|
||
|
|
||
|
<i>// examples</i>
|
||
|
|
||
|
<i>// assign tag editor to textarea - existing text will be used as initial tags</i>
|
||
|
$(<b>'textarea'</b>).tagEditor();
|
||
|
|
||
|
<i>// assign tag editor to text input with initial tags</i>
|
||
|
$(<b>'input[type="text"]'</b>).tagEditor({ initialTags: [<b>'tag1'</b>, <b>'tag2'</b>, <b>'tag3'</b>] });
|
||
|
|
||
|
<i>// use jQuery UI autocomplete</i>
|
||
|
$(<b>'#my_textarea'</b>).tagEditor({ autocomplete: { <b>'source'</b>: <b>'/url/'</b>, minLength: <em>3</em> } });</pre>
|
||
|
|
||
|
<h3>Settings</h3>
|
||
|
<table>
|
||
|
<tr><th>Property</th><th>Default</th><th>Description</th></tr>
|
||
|
<tr><td>initialTags</td><td>[]</td><td>Initial tags as an array of strings.</td></tr>
|
||
|
<tr><td>maxTags</td><td><i>null</i></td><td>Maximum number of allowed tags.</td></tr>
|
||
|
<tr><td>maxLength</td><td>50</td><td><span class="inline-code">maxlength</span> attribute of the tag input field.</td></tr>
|
||
|
<tr>
|
||
|
<td>delimiter</td><td style="white-space:nowrap">',;'</td>
|
||
|
<td>
|
||
|
<p>
|
||
|
Required string of delimiters - characters for separating tags.
|
||
|
The first character is used as default delimiter in the (hidden) original field.
|
||
|
</p>
|
||
|
</td>
|
||
|
</tr>
|
||
|
<tr><td>placeholder</td><td>''</td><td>Placeholder text for empty tag editor.</td></tr>
|
||
|
<tr><td>forceLowercase</td><td><i>true</i></td><td>Lowercase all tags.</td></tr>
|
||
|
<tr><td>removeDuplicates</td><td><i>true</i></td><td>Automatically remove duplicate tags.</td></tr>
|
||
|
<tr><td>clickDelete</td><td><i>false</i></td><td>Delete tags on right click and on Ctrl+click.</td></tr>
|
||
|
<tr><td>animateDelete</td><td><i>175</i></td><td>Animate duration for deletion of tags in milliseconds. Set to 0 for non-animated removal.</td></tr>
|
||
|
<tr><td>sortable</td><td><i>true</i></td><td>If <a href="https://jqueryui.com/sortable/">jQuery UI sortable</a> is available and this option is set to <span class="inline-code">true</span>, tags are sortable by drag and drop.</td></tr>
|
||
|
<tr><td>autocomplete</td><td><i>null</i></td><td><a href="https://jqueryui.com/autocomplete/">jQuery UI autocomplete</a> options as key/value pairs object. If provided, jQuery UI autocomplete must be loaded additionally.</td></tr>
|
||
|
|
||
|
<tr><td colspan="3"> </td></tr>
|
||
|
<tr><th>Callbacks</th><th colspan="2"></th></tr>
|
||
|
<tr><td>onChange(field, editor, tags)</td><td colspan="2">Callback that fires after tags are changed. <span class="inline-code">field</span> is the (hidden) original field, <span class="inline-code">editor</span> is the editor's DOM element (an <ul> list of tag elements), and <span class="inline-code">tags</span> contains the list of current tags.</td></tr>
|
||
|
<tr><td>beforeTagSave(field, editor, tags, tag, val)</td><td colspan="2">Callback that fires before a tag is saved. <span class="inline-code">field</span> is the (hidden) original field, <span class="inline-code">editor</span> is the editor's DOM element. <span class="inline-code">tags</span> contains the list of current tags, <span class="inline-code">tag</span> is the value that is about to get overwritten (empty string, unless an existing tag gets changed), and <span class="inline-code">val</span> is the new value to be saved. <span class="inline-code">beforeTagSave()</span> may return a string for overwriting the saved tag. Return <span class="inline-code">false</span> for reverting to the tag's previous value (or to skip this tag value in the case of copy-paste insertion).</td></tr>
|
||
|
<tr><td>beforeTagDelete(field, editor, tags, val)</td><td colspan="2">Callback that fires before a tag is deleted. <span class="inline-code">field</span> is the (hidden) original field, <span class="inline-code">editor</span> is the editor's DOM element. <span class="inline-code">tags</span> contains the list of current tags, <span class="inline-code">val</span> is the tag that is about to get deleted. Return <span class="inline-code">false</span> to prevent this action.</td></tr>
|
||
|
|
||
|
<tr><td colspan="3"> </td></tr>
|
||
|
<tr><th>Public Methods</th><th colspan="2"></th></tr>
|
||
|
<tr><td>getTags</td><td colspan="2">
|
||
|
Returns a list of objects in the following format:
|
||
|
<br>[{ field: <i>selected input/textarea</i>, editor: <i>editor instance for field</i>, tags: <i>current tags</i> }]
|
||
|
</td></tr>
|
||
|
<tr><td>addTag(val, blur)</td><td colspan="2">Adds <span class="inline-code">val</span> as a new tag. Set <span class="inline-code">blur</span> to <span class="inline-code">true</span> if focus should not be set automatically into an empty, new tag after this action.</td></tr>
|
||
|
<tr><td>removeTag(val, blur)</td><td colspan="2">Removes <span class="inline-code">val</span> as tag. Set <span class="inline-code">blur</span> to <span class="inline-code">true</span> if focus should not be set automatically into an empty, new tag after this action.</td></tr>
|
||
|
<tr><td>destroy</td><td colspan="2">Removes the tag editor instance an restores visibility of the original text field or textarea.</td></tr>
|
||
|
</table>
|
||
|
|
||
|
<h3 style="margin-top:.8em;border-top:1px solid #eee;padding-top:1.8em">Demos</h3>
|
||
|
|
||
|
<h4 style="margin-top:.5em">Basic settings</h4>
|
||
|
<pre>
|
||
|
$(<b>'#demo1'</b>).tagEditor({
|
||
|
initialTags: [<b>'Hello'</b>, <b>'World'</b>, <b>'Example'</b>, <b>'Tags'</b>],
|
||
|
delimiter: <b>', '</b>, <i>/* space and comma */</i>
|
||
|
placeholder: <b>'Enter tags ...'</b>
|
||
|
});</pre>
|
||
|
<div style="margin:0 0 1.2em">
|
||
|
<p>The original field - textarea or text input - is normally hidden automatically. We show it here to make value changes visible:</p>
|
||
|
<textarea id="demo1"></textarea>
|
||
|
</div>
|
||
|
<p>
|
||
|
The placeholder is visible when all tags are deleted and the editor looses focus.
|
||
|
jQuery UI is already loaded on this page - and by default, tags are then sortable via drag and drop.
|
||
|
</p>
|
||
|
|
||
|
<h4>Autocomplete</h4>
|
||
|
<p>
|
||
|
For enabling tag autocompletion, make sure to have <a href="https://jqueryui.com/autocomplete/">jQuery UI autocomplete</a> readily loaded.
|
||
|
You can then pass <i>any</i> options that work with UI autocomplete to your tagEditor settings.
|
||
|
</p>
|
||
|
<pre>
|
||
|
$(<b>'#demo2'</b>).tagEditor({
|
||
|
autocomplete: {
|
||
|
delay: 0, <i>// show suggestions immediately</i>
|
||
|
position: { collision: 'flip' }, <i>// automatic menu position up/down</i>
|
||
|
source: [<b>'ActionScript'</b>, <b>'AppleScript'</b>, <b>'Asp'</b>, ... <b>'Python'</b>, <b>'Ruby'</b>]
|
||
|
},
|
||
|
forceLowercase: <em>false</em>,
|
||
|
placeholder: <b>'Programming languages ...'</b>
|
||
|
});</pre>
|
||
|
<div style="margin:0 0 1.2em"><textarea id="demo2"></textarea></div>
|
||
|
|
||
|
<h4>Public methods</h4>
|
||
|
<pre>
|
||
|
$(<b>'#demo3'</b>).tagEditor({
|
||
|
initialTags: [<b>'Hello'</b>, <b>'World'</b>],
|
||
|
placeholder: <b>'Enter tags ...'</b>
|
||
|
});</pre>
|
||
|
<div style="margin:0 0 1.2em"><textarea id="demo3"></textarea></div>
|
||
|
<p>
|
||
|
<span onclick="alert($('#demo3').tagEditor('getTags')[0].tags);" class="ed_on pure-button button-sm">getTags</span>
|
||
|
<span onclick="$('#demo3').tagEditor('addTag', 'example');" class="ed_on pure-button button-sm">addTag 'example'</span>
|
||
|
<span onclick="$('#demo3').tagEditor('removeTag', 'example', true);" class="ed_on pure-button button-sm">removeTag 'example'</span>
|
||
|
<span id="remove_all_tags" class="ed_on pure-button button-sm">Remove all tags</span>
|
||
|
<span onclick="$('#demo3').tagEditor('destroy');$('.ed_on').hide();$('.ed_off').show();" class="ed_on pure-button button-sm">destroy</span>
|
||
|
<span onclick="$('#demo3').tagEditor({ placeholder: 'Enter tags ...' });$('.ed_off').hide();$('.ed_on').show();" class="ed_off pure-button button-sm" style="display:none">Init editor</span>
|
||
|
</p>
|
||
|
<pre>
|
||
|
<i>// actions on button clicks</i>
|
||
|
|
||
|
<i>// getTags</i>
|
||
|
alert( $(<b>'#demo3'</b>).tagEditor(<b>'getTags'</b>)[0].tags );
|
||
|
|
||
|
<i>// addTag</i>
|
||
|
$(<b>'#demo3'</b>).tagEditor(<b>'addTag'</b>, <b>'example'</b>);
|
||
|
|
||
|
<i>// removeTag</i>
|
||
|
$(<b>'#demo3'</b>).tagEditor(<b>'removeTag'</b>, <b>'example'</b>);
|
||
|
|
||
|
<i>// Remove all tags</i>
|
||
|
function() {
|
||
|
var tags = $(<b>'#demo3'</b>).tagEditor(<b>'getTags'</b>)[0].tags;
|
||
|
for (i = 0; i < tags.length; i++) { $(<b>'#demo3'</b>).tagEditor(<b>'removeTag'</b>, tags[i]); }
|
||
|
}
|
||
|
<i>// working shortcut for removing all tags
|
||
|
// $('#demo3').next('.tag-editor').find('.tag-editor-delete').click();</i>
|
||
|
|
||
|
<i>// destroy</i>
|
||
|
$(<b>'#demo3'</b>).tagEditor(<b>'destroy'</b>);
|
||
|
|
||
|
<i>// re-init editor</i>
|
||
|
$(<b>'#demo3'</b>).tagEditor({ placeholder: <b>'Enter tags ...'</b> });</pre>
|
||
|
|
||
|
<h4>Callbacks</h4>
|
||
|
<pre>
|
||
|
$(<b>'#demo4'</b>).tagEditor({
|
||
|
initialTags: [<b>'Hello'</b>, <b>'World'</b>],
|
||
|
placeholder: <b>'Enter tags ...'</b>,
|
||
|
onChange: function(field, editor, tags) {
|
||
|
$(<b>'#response'</b>).prepend(
|
||
|
<b>'Tags changed to: '</b> + (tags.length ? tags.join(<b>', '</b>) : <b>'----'</b>) + <b>'<hr>'</b>
|
||
|
);
|
||
|
},
|
||
|
beforeTagSave: function(field, editor, tags, tag, val) {
|
||
|
$(<b>'#response'</b>).prepend(<b>'Tag '</b> + val + <b>' saved'</b> + (tag ? <b>' over '</b> + tag : <b>''</b>) + <b>'.'</b>);
|
||
|
},
|
||
|
beforeTagDelete: function(field, editor, tags, val) {
|
||
|
var q = confirm(<b>'Remove tag "'</b> + val + <b>'"?'</b>);
|
||
|
if (q) $(<b>'#response'</b>).prepend(<b>'Tag '</b> + val + <b>' deleted.'</b>);
|
||
|
else $(<b>'#response'</b>).prepend(<b>'Removal of '</b> + val + <b>' discarded.'</b>);
|
||
|
return q;
|
||
|
}
|
||
|
});</pre>
|
||
|
<div style="margin:0 0 1.2em"><textarea id="demo4"></textarea></div>
|
||
|
<p style="font-size:.9em;margin:0 0 .2em">Callback response:</p>
|
||
|
<div id="response">Starting tags: <i>hello, world</i></div>
|
||
|
|
||
|
<h4>Custom style and clickDelete</h4>
|
||
|
<p>
|
||
|
Use right mouse click or Ctrl+left click to delete tags.
|
||
|
</p>
|
||
|
<pre>
|
||
|
$(<b>'#demo5'</b>).tagEditor({
|
||
|
clickDelete: true,
|
||
|
initialTags: [ ... ],
|
||
|
placeholder: <b>'Enter tags ...'</b>
|
||
|
});</pre>
|
||
|
<div style="margin:0 0 1.2em"><textarea id="demo5"></textarea></div>
|
||
|
<pre>
|
||
|
<i>/* overwrite default CSS for tiny, dark tags */</i>
|
||
|
|
||
|
<b>#demo5+.tag-editor</b> { background: <em>#fafafa</em>; font-size: <em>12px</em>; }
|
||
|
<b>#demo5+.tag-editor .tag-editor-tag</b> {
|
||
|
color: <em>#fff</em>; background: <em>#555</em>;
|
||
|
border-radius: <em>2px</em>;
|
||
|
}
|
||
|
<b>#demo5+.tag-editor .tag-editor-spacer</b> { width: <em>7px</em>; }
|
||
|
<b>#demo5+.tag-editor .tag-editor-delete</b> { display: <em>none</em>; }</pre>
|
||
|
<p>
|
||
|
This jQuery plugin was designed with custom styling in mind. In this example we've enabled the <span class="inline-code">clickDelete</span> feature while hiding all delete icons. Both options may be used at the same time, as well.
|
||
|
By fiddling around with the default stylesheet, you can achieve almost any desired look for your tag Editor.
|
||
|
Comments inside the CSS file will help you understand what rule controls which object inside the editor.
|
||
|
</p>
|
||
|
|
||
|
<h4>Custom CSS classes for tags</h4>
|
||
|
<p>
|
||
|
Using the onChange callback for adding custom CSS classes to specific tags.
|
||
|
</p>
|
||
|
<pre>
|
||
|
$(<b>'#demo6'</b>).tagEditor({
|
||
|
initialTags: [<b>'custom'</b>, <b>'class'</b>, <b>'red'</b>, <b>'green'</b>, <b>'demo'</b>],
|
||
|
onChange: tag_classes
|
||
|
});
|
||
|
|
||
|
function tag_classes(field, editor, tags) {
|
||
|
$(<b>'li'</b>, editor).each(function(){
|
||
|
var li = $(this);
|
||
|
if (li.find(<b>'.tag-editor-tag'</b>).html() == <b>'red'</b>) li.addClass(<b>'red-tag'</b>);
|
||
|
else if (li.find(<b>'.tag-editor-tag'</b>).html() == <b>'green'</b>) li.addClass(<b>'green-tag'</b>)
|
||
|
else li.removeClass(<b>'red-tag green-tag'</b>);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
<i>// first assign tag classes after initializing tagEditor; onChange is not called on init</i>
|
||
|
tag_classes(null, $('#demo6').tagEditor('getTags')[0].editor);</pre>
|
||
|
<div style="margin:0 0 1.2em"><textarea id="demo6"></textarea></div>
|
||
|
<p>
|
||
|
In the onChange callback we iterate over all tags and assign custom CSS classes where appropriate.
|
||
|
The DOM structure of the editor looks like this:
|
||
|
</p>
|
||
|
<pre><ul>
|
||
|
<li>
|
||
|
<div class=<b>"tag-editor-spacer"</b>></div>
|
||
|
<div class=<b>"tag-editor-tag"</b>>Tag content</div>
|
||
|
<div class=<b>"tag-editor-delete"</b>><i></i></div>
|
||
|
</li>
|
||
|
[...]
|
||
|
</ul></pre>
|
||
|
|
||
|
<p>
|
||
|
In the example, we simply add CSS classes to the <span class="inline-code"><li></span> elements.
|
||
|
This is just an exampe of what the onChange callback may be used for. Inside of it, <span class="inline-code">addTag</span> and <span class="inline-code">removeTag</span> may be called to dynamically change the current list of tags.
|
||
|
</p>
|
||
|
|
||
|
<div style="margin:40px 0;overflow:hidden">
|
||
|
<span id="github_social"></span>
|
||
|
<div style="float:left;margin-right:35px">
|
||
|
<a href="#" data-width="70" class="twitter-share-button" data-text="jQuery tagEditor Plugin"></a>
|
||
|
</div>
|
||
|
<div style="float:left">
|
||
|
<div class="g-plusone" data-size="medium"></div>
|
||
|
</div>
|
||
|
<div style="float:left;width:140px" class="fb-like" data-send="false" data-layout="button_count" data-width="140" data-show-faces="false"></div>
|
||
|
</div>
|
||
|
|
||
|
<p style="border-top:1px solid #eee;padding-top:30px">Please report any bugs and issues at the <a href="https://github.com/Pixabay/jQuery-tagEditor">GitHub repositiory</a>.</p>
|
||
|
<p>This software is released as Open Source under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> by <a href="https://pixabay.com/users/Simon/">Simon Steinberger / Pixabay.com</a>.</p>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<div style="background:#fafafa;border-top:1px solid #eee;padding:15px;font-size:.9em">
|
||
|
<div style="max-width:900px;margin:auto;padding:0 10px">
|
||
|
<a style="float:right;margin-left:20px" href="https://pixabay.com/en/service/about/">About Us</a>
|
||
|
<a style="float:right;margin-left:20px" href="https://pixabay.com/en/blog/">Blog</a>
|
||
|
<a style="float:right;margin-left:20px" href="https://goodies.pixabay.com/">More Goodies</a>
|
||
|
© <a href="https://pixabay.com/">Pixabay.com</a> / Simon Steinberger / Hans Braxmeier
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div id="fb-root"></div>
|
||
|
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
|
||
|
<script src="https://code.jquery.com/ui/1.10.2/jquery-ui.min.js"></script>
|
||
|
<script src="jquery.caret.min.js"></script>
|
||
|
<script src="jquery.tag-editor.js"></script>
|
||
|
<script>
|
||
|
// jQuery UI autocomplete extension - suggest labels may contain HTML tags
|
||
|
// github.com/scottgonzalez/jquery-ui-extensions/blob/master/src/autocomplete/jquery.ui.autocomplete.html.js
|
||
|
(function($){var proto=$.ui.autocomplete.prototype,initSource=proto._initSource;function filter(array,term){var matcher=new RegExp($.ui.autocomplete.escapeRegex(term),"i");return $.grep(array,function(value){return matcher.test($("<div>").html(value.label||value.value||value).text());});}$.extend(proto,{_initSource:function(){if(this.options.html&&$.isArray(this.options.source)){this.source=function(request,response){response(filter(this.options.source,request.term));};}else{initSource.call(this);}},_renderItem:function(ul,item){return $("<li></li>").data("item.autocomplete",item).append($("<a></a>")[this.options.html?"html":"text"](item.label)).appendTo(ul);}});})(jQuery);
|
||
|
|
||
|
var cache = {};
|
||
|
function googleSuggest(request, response) {
|
||
|
var term = request.term;
|
||
|
if (term in cache) { response(cache[term]); return; }
|
||
|
$.ajax({
|
||
|
url: 'https://query.yahooapis.com/v1/public/yql',
|
||
|
dataType: 'JSONP',
|
||
|
data: { format: 'json', q: 'select * from xml where url="http://google.com/complete/search?output=toolbar&q='+term+'"' },
|
||
|
success: function(data) {
|
||
|
var suggestions = [];
|
||
|
try { var results = data.query.results.toplevel.CompleteSuggestion; } catch(e) { var results = []; }
|
||
|
$.each(results, function() {
|
||
|
try {
|
||
|
var s = this.suggestion.data.toLowerCase();
|
||
|
suggestions.push({label: s.replace(term, '<b>'+term+'</b>'), value: s});
|
||
|
} catch(e){}
|
||
|
});
|
||
|
cache[term] = suggestions;
|
||
|
response(suggestions);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
$(function() {
|
||
|
$('#hero-demo').tagEditor({
|
||
|
placeholder: 'Enter tags ...',
|
||
|
autocomplete: { source: googleSuggest, minLength: 3, delay: 250, html: true, position: { collision: 'flip' } }
|
||
|
});
|
||
|
|
||
|
$('#demo1').tagEditor({ initialTags: ['Hello', 'World', 'Example', 'Tags'], delimiter: ', ', placeholder: 'Enter tags ...' }).css('display', 'block').attr('readonly', true);
|
||
|
|
||
|
$('#demo2').tagEditor({
|
||
|
autocomplete: { delay: 0, position: { collision: 'flip' }, source: ['ActionScript', 'AppleScript', 'Asp', 'BASIC', 'C', 'C++', 'CSS', 'Clojure', 'COBOL', 'ColdFusion', 'Erlang', 'Fortran', 'Groovy', 'Haskell', 'HTML', 'Java', 'JavaScript', 'Lisp', 'Perl', 'PHP', 'Python', 'Ruby', 'Scala', 'Scheme'] },
|
||
|
forceLowercase: false,
|
||
|
placeholder: 'Programming languages ...'
|
||
|
});
|
||
|
|
||
|
$('#demo3').tagEditor({ initialTags: ['Hello', 'World'], placeholder: 'Enter tags ...' });
|
||
|
$('#remove_all_tags').click(function() {
|
||
|
var tags = $('#demo3').tagEditor('getTags')[0].tags;
|
||
|
for (i=0;i<tags.length;i++){ $('#demo3').tagEditor('removeTag', tags[i]); }
|
||
|
});
|
||
|
|
||
|
$('#demo4').tagEditor({
|
||
|
initialTags: ['Hello', 'World'],
|
||
|
placeholder: 'Enter tags ...',
|
||
|
onChange: function(field, editor, tags) { $('#response').prepend('Tags changed to: <i>'+(tags.length ? tags.join(', ') : '----')+'</i><hr>'); },
|
||
|
beforeTagSave: function(field, editor, tags, tag, val) { $('#response').prepend('Tag <i>'+val+'</i> saved'+(tag ? ' over <i>'+tag+'</i>' : '')+'.<hr>'); },
|
||
|
beforeTagDelete: function(field, editor, tags, val) {
|
||
|
var q = confirm('Remove tag "'+val+'"?');
|
||
|
if (q) $('#response').prepend('Tag <i>'+val+'</i> deleted.<hr>');
|
||
|
else $('#response').prepend('Removal of <i>'+val+'</i> discarded.<hr>');
|
||
|
return q;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$('#demo5').tagEditor({ clickDelete: true, initialTags: ['custom style', 'dark tags', 'delete on click', 'no delete icon', 'hello', 'world'], placeholder: 'Enter tags ...' });
|
||
|
|
||
|
function tag_classes(field, editor, tags) {
|
||
|
$('li', editor).each(function(){
|
||
|
var li = $(this);
|
||
|
if (li.find('.tag-editor-tag').html() == 'red') li.addClass('red-tag');
|
||
|
else if (li.find('.tag-editor-tag').html() == 'green') li.addClass('green-tag')
|
||
|
else li.removeClass('red-tag green-tag');
|
||
|
});
|
||
|
}
|
||
|
$('#demo6').tagEditor({ initialTags: ['custom', 'class', 'red', 'green', 'demo'], onChange: tag_classes });
|
||
|
tag_classes(null, $('#demo6').tagEditor('getTags')[0].editor); // or editor == $('#demo6').next()
|
||
|
});
|
||
|
|
||
|
if (~window.location.href.indexOf('http')) {
|
||
|
(function() {var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;po.src = 'https://apis.google.com/js/plusone.js';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);})();
|
||
|
(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.4&appId=114593902037957";fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));
|
||
|
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
|
||
|
$('#github_social').html('\
|
||
|
<iframe style="float:left;margin-right:15px" src="//ghbtns.com/github-btn.html?user=Pixabay&repo=jQuery-tagEditor&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>\
|
||
|
<iframe style="float:left;margin-right:15px" src="//ghbtns.com/github-btn.html?user=Pixabay&repo=jQuery-tagEditor&type=fork&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>\
|
||
|
');
|
||
|
}
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|