aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorplegall <plg@piwigo.org>2010-03-06 22:10:23 +0000
committerplegall <plg@piwigo.org>2010-03-06 22:10:23 +0000
commit1c545c601beeeaafacd367d7af2077742c0fcce6 (patch)
tree95ac1513741ea80c6bed3afd6869a1fdd3ec0bed
parent97a8ddcfe7c8d3f50b3e577c0915c551e7af12fa (diff)
feature 724: improved "add tags" form. Instead of a big list of checkboxes,
displays a dynamic list of tags with jQuery, with suggestions based on existing tags and the ability to create new tags on the fly. The change was applied only on admin/picture_modify.php for test purpose. Note : FCBKcomplete 2.7 had a bug on "remote tag" click, and the bug was fixed on 2.7.1. But the suggestions were not working with 2.7.1. So I took the 2.7 and applied the tiny change to make the "remove tag" click work. git-svn-id: http://piwigo.org/svn/trunk@5067 68402e56-0260-453c-a942-63ccdbb3a9ee
-rw-r--r--admin.php25
-rw-r--r--admin/picture_modify.php78
-rw-r--r--admin/template/goto/default-layout.css44
-rw-r--r--admin/template/goto/icon/fcbkcomplete_close.gifbin0 -> 90 bytes
-rw-r--r--admin/template/goto/picture_modify.tpl27
-rw-r--r--template-common/lib/plugins/jquery.fcbkcomplete.js588
6 files changed, 731 insertions, 31 deletions
diff --git a/admin.php b/admin.php
index bc69f7321..d2ed70747 100644
--- a/admin.php
+++ b/admin.php
@@ -34,6 +34,31 @@ include_once(PHPWG_ROOT_PATH.'admin/include/functions_plugins.inc.php');
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
+// tags
+if (isset($_GET['fckb_tags']))
+{
+ $query = '
+SELECT
+ id,
+ name
+ FROM '.TAGS_TABLE.'
+;';
+ $result = pwg_query($query);
+ $taglist = array();
+ while ($row = pwg_db_fetch_assoc($result))
+ {
+ array_push(
+ $taglist,
+ array(
+ 'caption' => $row['name'],
+ 'value' => '~~'.$row['id'].'~~',
+ )
+ );
+ }
+ echo json_encode($taglist);
+ exit();
+}
+
// +-----------------------------------------------------------------------+
// | synchronize user informations |
// +-----------------------------------------------------------------------+
diff --git a/admin/picture_modify.php b/admin/picture_modify.php
index c7914f3a0..42306fc23 100644
--- a/admin/picture_modify.php
+++ b/admin/picture_modify.php
@@ -106,8 +106,32 @@ if (isset($_POST['submit']) and count($page['errors']) == 0 and !is_adviser())
array($data)
);
+ // In $_POST[tags] we receive something like array('~~6~~', '~~59~~', 'New
+ // tag', 'Another new tag') The ~~34~~ means that it is an existing
+ // tag. I've added the surrounding ~~ to permit creation of tags like "10"
+ // or "1234" (numeric characters only)
+ $tag_ids = array();
+ if (isset($_POST['tags']))
+ {
+ foreach ($_POST['tags'] as $raw_tag)
+ {
+ if (preg_match('/^~~(\d+)~~$/', $raw_tag, $matches))
+ {
+ array_push($tag_ids, $matches[1]);
+ }
+ else
+ {
+ // we have to create a new tag
+ array_push(
+ $tag_ids,
+ tag_id_from_tag_name($raw_tag)
+ );
+ }
+ }
+ }
+
set_tags(
- isset($_POST['tags']) ? $_POST['tags'] : array(),
+ $tag_ids,
$_GET['image_id']
);
@@ -169,6 +193,29 @@ if (isset($_POST['dismiss'])
set_random_representant($_POST['cat_elected']);
}
+// tags
+$tags = array();
+
+$query = '
+SELECT
+ tag_id,
+ name
+ FROM '.IMAGE_TAG_TABLE.' AS it
+ JOIN '.TAGS_TABLE.' AS t ON t.id = it.tag_id
+ WHERE image_id = '.$_GET['image_id'].'
+;';
+$result = pwg_query($query);
+while ($row = pwg_db_fetch_assoc($result))
+{
+ array_push(
+ $tags,
+ array(
+ 'value' => '~~'.$row['tag_id'].'~~',
+ 'caption' => $row['name'],
+ )
+ );
+}
+
// retrieving direct information about picture
$query = '
SELECT *
@@ -185,14 +232,6 @@ if (!empty($row['storage_category_id']))
$image_file = $row['file'];
-// tags
-$query = '
-SELECT tag_id
- FROM '.IMAGE_TAG_TABLE.'
- WHERE image_id = '.$_GET['image_id'].'
-;';
-$selected_tags = array_from_query($query, 'tag_id');
-
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
@@ -203,26 +242,9 @@ $template->set_filenames(
)
);
-$all_tags = get_all_tags();
-
-if (count($all_tags) > 0)
-{
- $tag_selection = get_html_tag_selection(
- $all_tags,
- 'tags',
- $selected_tags
- );
-}
-else
-{
- $tag_selection =
- '<p>'.
- l10n('No tag defined. Use Administration>Pictures>Tags').
- '</p>';
-}
-
$template->assign(
array(
+ 'tags' => $tags,
'U_SYNC' =>
get_root_url().'admin.php?page=picture_modify'.
'&amp;image_id='.$_GET['image_id'].
@@ -245,8 +267,6 @@ $template->assign(
'AUTHOR' => isset($_POST['author']) ? $_POST['author'] : @$row['author'],
- 'TAG_SELECTION' => $tag_selection,
-
'DESCRIPTION' =>
htmlspecialchars( isset($_POST['description']) ?
stripslashes($_POST['description']) : @$row['comment'] ),
diff --git a/admin/template/goto/default-layout.css b/admin/template/goto/default-layout.css
index 14116e1c2..9f4437d06 100644
--- a/admin/template/goto/default-layout.css
+++ b/admin/template/goto/default-layout.css
@@ -455,3 +455,47 @@ UL.tagSelection LI {
img.ui-datepicker-trigger {
cursor : pointer;
}
+
+/* jQuery FCBKcomplete */
+/* TextboxList sample CSS */
+ul.holder { margin: 0; border: 1px solid #999; overflow: hidden; height: auto !important; height: 1%; padding: 4px 5px 0; }
+*:first-child+html ul.holder { padding-bottom: 2px; } * html ul.holder { padding-bottom: 2px; } /* ie7 and below */
+ul.holder li { float: left; list-style-type: none; margin: 0 5px 4px 0; white-space:nowrap;}
+ul.holder li.bit-box, ul.holder li.bit-input input { font: 11px "Lucida Grande", "Verdana"; }
+ul.holder li.bit-box { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; border: 1px solid #CAD8F3; background: #DEE7F8; padding: 1px 5px 2px; }
+ul.holder li.bit-box-focus { border-color: #598BEC; background: #598BEC; color: #fff; }
+ul.holder li.bit-input input { width: auto; overflow:visible; margin: 0; border: 0px; outline: 0; padding: 3px 0px 2px; } /* no left/right padding here please */
+ul.holder li.bit-input input.smallinput { width: 20px; }
+
+/* Facebook demo CSS */
+#add { border: 1px solid #999; width: 550px; margin: 50px; padding: 20px 30px 10px; }
+form ol li { list-style-type: none; }
+form ol { font: 11px "Lucida Grande", "Verdana"; margin: 0; padding: 0; }
+form ol li.input-text { margin-bottom: 10px; list-style-type: none; padding-bottom: 10px; }
+form ol li.input-text label { font-weight: bold; cursor: pointer; display: block; font-size: 13px; margin-bottom: 10px; }
+form ol li.input-text input { width: 500px; padding: 5px 5px 6px; font: 11px "Lucida Grande", "Verdana"; border: 1px solid #999; }
+form ul.holder { width: 500px; }
+form ul { margin: 0 !important }
+ul.holder li.bit-box, #apple-list ul.holder li.bit-box { padding-right: 15px; position: relative; z-index:1000;}
+#apple-list ul.holder li.bit-input { margin: 0; }
+#apple-list ul.holder li.bit-input input.smallinput { width: 5px; }
+ul.holder li.bit-hover { background: #BBCEF1; border: 1px solid #6D95E0; }
+ul.holder li.bit-box-focus { border-color: #598BEC; background: #598BEC; color: #fff; }
+ul.holder li.bit-box a.closebutton { position: absolute; right: 4px; top: 5px; display: block; width: 7px; height: 7px; font-size: 1px; background: url(icon/fcbkcomplete_close.gif); }
+ul.holder li.bit-box a.closebutton:hover { background-position: 7px; }
+ul.holder li.bit-box-focus a.closebutton, ul.holder li.bit-box-focus a.closebutton:hover { background-position: bottom; }
+
+/* Autocompleter */
+
+.facebook-auto { display: none; position: absolute; width: 512px; background: #eee; }
+.facebook-auto .default { padding: 5px 7px; border: 1px solid #ccc; border-width: 0 1px 1px;font-family:"Lucida Grande","Verdana"; font-size:11px; }
+.facebook-auto ul { display: none; margin: 0; padding: 0; overflow: auto; position:absolute; z-index:9999}
+.facebook-auto ul li { padding: 5px 12px; z-index: 1000; cursor: pointer; margin: 0; list-style-type: none; border: 1px solid #ccc; border-width: 0 1px 1px; font: 11px "Lucida Grande", "Verdana"; background-color: #eee }
+.facebook-auto ul li em { font-weight: bold; font-style: normal; background: #ccc; }
+.facebook-auto ul li.auto-focus { background: #4173CC; color: #fff; }
+.facebook-auto ul li.auto-focus em { background: none; }
+.deleted { background-color:#4173CC !important; color:#ffffff !important;}
+.hidden { display:none;}
+
+#demo ul.holder li.bit-input input { padding: 2px 0 1px; border: 1px solid #999; }
+.ie6fix {height:1px;width:1px; position:absolute;top:0px;left:0px;z-index:1;} \ No newline at end of file
diff --git a/admin/template/goto/icon/fcbkcomplete_close.gif b/admin/template/goto/icon/fcbkcomplete_close.gif
new file mode 100644
index 000000000..cc2199248
--- /dev/null
+++ b/admin/template/goto/icon/fcbkcomplete_close.gif
Binary files differ
diff --git a/admin/template/goto/picture_modify.tpl b/admin/template/goto/picture_modify.tpl
index 4c8315d9b..77f1671a6 100644
--- a/admin/template/goto/picture_modify.tpl
+++ b/admin/template/goto/picture_modify.tpl
@@ -1,8 +1,25 @@
-
{include file='include/autosize.inc.tpl'}
{include file='include/dbselect.inc.tpl'}
{include file='include/datepicker.inc.tpl'}
+{known_script id="jquery.fcbkcomplete" src=$ROOT_URL|@cat:"template-common/lib/plugins/jquery.fcbkcomplete.js"}
+{literal}
+<script type="text/javascript">
+ $(document).ready(function() {
+ $("#tags").fcbkcomplete({
+ json_url: "admin.php?fckb_tags=1",
+ cache: false,
+ filter_case: true,
+ filter_hide: true,
+ firstselected: true,
+ filter_selected: true,
+ maxitems: 10,
+ newel: true
+ });
+ });
+</script>
+{/literal}
+
{literal}
<script type="text/javascript">
pwg_initialization_datepicker("#date_creation_day", "#date_creation_month", "#date_creation_year", "#date_creation_linked_date", "#date_creation_action_set");
@@ -119,7 +136,13 @@
<tr>
<td><strong>{'Tags'|@translate}</strong></td>
- <td>{$TAG_SELECTION}</td>
+ <td>
+<select id="tags" name="tags">
+{foreach from=$tags item=tag}
+ <option value="{$tag.value}" class="selected">{$tag.caption}</option>
+{/foreach}
+</select>
+ </td>
</tr>
diff --git a/template-common/lib/plugins/jquery.fcbkcomplete.js b/template-common/lib/plugins/jquery.fcbkcomplete.js
new file mode 100644
index 000000000..86b3b6ab2
--- /dev/null
+++ b/template-common/lib/plugins/jquery.fcbkcomplete.js
@@ -0,0 +1,588 @@
+/*
+ FCBKcomplete 2.7
+ - Jquery version required: 1.2.x, 1.3.x, 1.4.x
+
+ Changelog:
+ - 2.00 new version of fcbkcomplete
+
+ - 2.01 fixed bugs & added features
+ fixed filter bug for preadded items
+ focus on the input after selecting tag
+ the element removed pressing backspace when the element is selected
+ input tag in the control has a border in IE7
+ added iterate over each match and apply the plugin separately
+ set focus on the input after selecting tag
+
+ - 2.02 fixed fist element selected bug
+ fixed defaultfilter error bug
+
+ - 2.5 removed selected="selected" attribute due ie bug
+ element search algorithm changed
+ better performance fix added
+ fixed many small bugs
+ onselect event added
+ onremove event added
+
+ - 2.6 ie6/7 support fix added
+ added new public method addItem due request
+ added new options "firstselected" that you can set true/false to select first element on dropdown list
+ autoexpand input element added
+ removeItem bug fixed
+ and many more bug fixed
+ fixed public method to use it $("elem").trigger("addItem",[{"title": "test", "value": "test"}]);
+
+- 2.7 jquery 1.4 compability
+ item lock possability added by adding locked class to preadded option <option value="value" class="selected locked">text</option>
+ maximum item that can be added to the list
+ */
+/* Coded by: emposha <admin@emposha.com> */
+/* Copyright: Emposha.com <http://www.emposha.com/> - Distributed under MIT - Keep this message! */
+/*
+ * json_url - url to fetch json object
+ * cache - use cache
+ * height - maximum number of element shown before scroll will apear
+ * newel - show typed text like a element
+ * firstselected - automaticly select first element from dropdown
+ * filter_case - case sensitive filter
+ * filter_selected - filter selected items from list
+ * complete_text - text for complete page
+ * maxshownitems - maximum numbers that will be shown at dropdown list (less better performance)
+ * onselect - fire event on item select
+ * onremove - fire event on item remove
+ * maxitimes - maximum items that can be added
+ */
+jQuery(function($){
+ $.fn.fcbkcomplete = function(opt){
+ return this.each(function(){
+ function init(){
+ createFCBK();
+ preSet();
+ addInput(0);
+ }
+
+ function createFCBK(){
+ element.hide();
+ element.attr("multiple", "multiple");
+ if (element.attr("name").indexOf("[]") == -1) {
+ element.attr("name", element.attr("name") + "[]");
+ }
+
+ holder = $(document.createElement("ul"));
+ holder.attr("class", "holder");
+ element.after(holder);
+
+ complete = $(document.createElement("div"));
+ complete.addClass("facebook-auto");
+ complete.append('<div class="default">' + options.complete_text + "</div>");
+
+ if (browser_msie) {
+ complete.append('<iframe class="ie6fix" scrolling="no" frameborder="0"></iframe>');
+ browser_msie_frame = complete.children('.ie6fix');
+ }
+
+ feed = $(document.createElement("ul"));
+ feed.attr("id", elemid + "_feed");
+
+ complete.prepend(feed);
+ holder.after(complete);
+ feed.css("width", complete.width());
+ }
+
+ function preSet(){
+ element.children("option").each(function(i, option){
+ option = $(option);
+ if (option.hasClass("selected")) {
+ addItem(option.text(), option.val(), true, option.hasClass("locked"));
+ option.attr("selected", "selected");
+ }
+ else {
+ option.removeAttr("selected");
+ }
+
+ cache.push({
+ caption: option.text(),
+ value: option.val()
+ });
+ search_string += "" + (cache.length - 1) + ":" + option.text() + ";";
+ });
+ }
+
+ //public method to add new item
+ $(this).bind("addItem", function(event, data){
+ addItem(data.title, data.value);
+ });
+
+ function addItem(title, value, preadded, locked){
+ if (!maxItems()) {
+ return false;
+ }
+ var li = document.createElement("li");
+ var txt = document.createTextNode(title);
+ var aclose = document.createElement("a");
+ var liclass = "bit-box" + (locked ? " locked" : "");
+ $(li).attr({
+ "class": liclass,
+ "rel": value
+ });
+ $(li).prepend(txt);
+ $(aclose).attr({
+ "class": "closebutton",
+ "href": "#"
+ });
+
+ li.appendChild(aclose);
+ holder.append(li);
+
+ $(aclose).click(function(){
+ removeItem($(this).parent("li"));
+ return false;
+ });
+
+ if (!preadded) {
+ $("#" + elemid + "_annoninput").remove();
+ var _item;
+ addInput(1);
+ if (element.children("option[value=" + value + "]").length) {
+ _item = element.children("option[value=" + value + "]");
+ _item.get(0).setAttribute("selected", "selected");
+ if (!_item.hasClass("selected")) {
+ _item.addClass("selected");
+ }
+ }
+ else {
+ var _item = $(document.createElement("option"));
+ _item.attr("value", value).get(0).setAttribute("selected", "selected");
+ _item.attr("value", value).addClass("selected");
+ _item.text(title);
+ element.append(_item);
+ }
+ if (options.onselect.length) {
+ funCall(options.onselect, _item)
+ }
+ }
+ holder.children("li.bit-box.deleted").removeClass("deleted");
+ feed.hide();
+ browser_msie ? browser_msie_frame.hide() : '';
+ }
+
+ function removeItem(item){
+ var parent = item.parent("li");
+ if (!parent.hasClass('locked')) {
+ parent.fadeOut("fast");
+ if (options.onremove.length) {
+ var _item = element.children("option[value=" + item.attr("rel") + "]");
+ funCall(options.onremove, _item)
+ }
+ element.children("option[value=" + item.attr("rel") + "]").removeAttr("selected");
+ element.children("option[value=" + item.attr("rel") + "]").removeClass("selected");
+ item.remove();
+ deleting = 0;
+ }
+ }
+
+ function addInput(focusme){
+ var li = $(document.createElement("li"));
+ var input = $(document.createElement("input"));
+
+ li.attr({
+ "class": "bit-input",
+ "id": elemid + "_annoninput"
+ });
+ input.attr({
+ "type": "text",
+ "class": "maininput",
+ "size": "1"
+ });
+ holder.append(li.append(input));
+
+ input.focus(function(){
+ complete.fadeIn("fast");
+ });
+
+ input.blur(function(){
+ complete.fadeOut("fast");
+ });
+
+ holder.click(function(){
+ input.focus();
+ if (feed.length && input.val().length) {
+ feed.show();
+ }
+ else {
+ feed.hide();
+ browser_msie ? browser_msie_frame.hide() : '';
+ complete.children(".default").show();
+ }
+ });
+
+ input.keypress(function(event){
+ if (event.keyCode == 13) {
+ return false;
+ }
+ //auto expand input
+ input.attr("size", input.val().length + 1);
+ });
+
+ input.keydown(function(event){
+ //prevent to enter some bad chars when input is empty
+ if (event.keyCode == 191) {
+ event.preventDefault();
+ return false;
+ }
+ });
+
+ input.keyup(function(event){
+ var etext = xssPrevent(input.val());
+
+ if (event.keyCode == 8 && etext.length == 0) {
+ feed.hide();
+ browser_msie ? browser_msie_frame.hide() : '';
+ if (!holder.children("li.bit-box:last").hasClass('locked')) {
+ if (holder.children("li.bit-box.deleted").length == 0) {
+ holder.children("li.bit-box:last").addClass("deleted");
+ return false;
+ }
+ else {
+ if (deleting) {
+ return;
+ }
+ deleting = 1;
+ holder.children("li.bit-box.deleted").fadeOut("fast", function(){
+ removeItem($(this));
+ return false;
+ });
+ }
+ }
+ }
+
+ if (event.keyCode != 40 && event.keyCode != 38 && etext.length != 0) {
+ counter = 0;
+
+ if (options.json_url) {
+ if (options.cache && json_cache) {
+ addMembers(etext);
+ bindEvents();
+ }
+ else {
+ $.getJSON(options.json_url + "?tag=" + etext, null, function(data){
+ addMembers(etext, data);
+ json_cache = true;
+ bindEvents();
+ });
+ }
+ }
+ else {
+ addMembers(etext);
+ bindEvents();
+ }
+ complete.children(".default").hide();
+ feed.show();
+ }
+ });
+ if (focusme) {
+ setTimeout(function(){
+ input.focus();
+ complete.children(".default").show();
+ }, 1);
+ }
+ }
+
+ function addMembers(etext, data){
+ feed.html('');
+
+ if (!options.cache) {
+ cache = new Array();
+ search_string = "";
+ }
+
+ addTextItem(etext);
+
+ if (data != null && data.length) {
+ $.each(data, function(i, val){
+ cache.push({
+ caption: val.caption,
+ value: val.value
+ });
+ search_string += "" + (cache.length - 1) + ":" + val.caption + ";";
+ });
+ }
+
+ var maximum = options.maxshownitems < cache.length ? options.maxshownitems : cache.length;
+ var filter = "i";
+ if (options.filter_case) {
+ filter = "";
+ }
+
+ var myregexp, match;
+ try {
+ myregexp = eval('/(?:^|;)\\s*(\\d+)\\s*:[^;]*?' + etext + '[^;]*/g' + filter);
+ match = myregexp.exec(search_string);
+ }
+ catch (ex) {
+ };
+
+ var content = '';
+ while (match != null && maximum > 0) {
+ var id = match[1];
+ var object = cache[id];
+ if (options.filter_selected && element.children("option[value=" + object.value + "]").hasClass("selected")) {
+ //nothing here...
+ }
+ else {
+ content += '<li rel="' + object.value + '">' + itemIllumination(object.caption, etext) + '</li>';
+ counter++;
+ maximum--;
+ }
+ match = myregexp.exec(search_string);
+ }
+ feed.append(content);
+
+ if (options.firstselected) {
+ focuson = feed.children("li:visible:first");
+ focuson.addClass("auto-focus");
+ }
+
+ if (counter > options.height) {
+ feed.css({
+ "height": (options.height * 24) + "px",
+ "overflow": "auto"
+ });
+ if (browser_msie) {
+ browser_msie_frame.css({
+ "height": (options.height * 24) + "px",
+ "width": feed.width() + "px"
+ }).show();
+ }
+ }
+ else {
+ feed.css("height", "auto");
+ if (browser_msie) {
+ browser_msie_frame.css({
+ "height": feed.height() + "px",
+ "width": feed.width() + "px"
+ }).show();
+ }
+ }
+ }
+
+ function itemIllumination(text, etext){
+ if (options.filter_case) {
+ try {
+ eval("var text = text.replace(/(.*)(" + etext + ")(.*)/gi,'$1<em>$2</em>$3');");
+ }
+ catch (ex) {
+ };
+ }
+ else {
+ try {
+ eval("var text = text.replace(/(.*)(" + etext.toLowerCase() + ")(.*)/gi,'$1<em>$2</em>$3');");
+ }
+ catch (ex) {
+ };
+ }
+ return text;
+ }
+
+ function bindFeedEvent(){
+ feed.children("li").mouseover(function(){
+ feed.children("li").removeClass("auto-focus");
+ $(this).addClass("auto-focus");
+ focuson = $(this);
+ });
+
+ feed.children("li").mouseout(function(){
+ $(this).removeClass("auto-focus");
+ focuson = null;
+ });
+ }
+
+ function removeFeedEvent(){
+ feed.children("li").unbind("mouseover");
+ feed.children("li").unbind("mouseout");
+ feed.mousemove(function(){
+ bindFeedEvent();
+ feed.unbind("mousemove");
+ });
+ }
+
+ function bindEvents(){
+ var maininput = $("#" + elemid + "_annoninput").children(".maininput");
+ bindFeedEvent();
+ feed.children("li").unbind("mousedown");
+ feed.children("li").mousedown(function(){
+ var option = $(this);
+ addItem(option.text(), option.attr("rel"));
+ feed.hide();
+ browser_msie ? browser_msie_frame.hide() : '';
+ complete.hide();
+ });
+
+ maininput.unbind("keydown");
+ maininput.keydown(function(event){
+ if (event.keyCode == 191) {
+ event.preventDefault();
+ return false;
+ }
+
+ if (event.keyCode != 8) {
+ holder.children("li.bit-box.deleted").removeClass("deleted");
+ }
+
+ if (event.keyCode == 13 && checkFocusOn()) {
+ var option = focuson;
+ addItem(option.text(), option.attr("rel"));
+ complete.hide();
+ event.preventDefault();
+ focuson = null;
+ return false;
+ }
+
+ if (event.keyCode == 13 && !checkFocusOn()) {
+ if (options.newel) {
+ var value = xssPrevent($(this).val());
+ addItem(value, value);
+ complete.hide();
+ event.preventDefault();
+ focuson = null;
+ }
+ return false;
+ }
+
+ if (event.keyCode == 40) {
+ removeFeedEvent();
+ if (focuson == null || focuson.length == 0) {
+ focuson = feed.children("li:visible:first");
+ feed.get(0).scrollTop = 0;
+ }
+ else {
+ focuson.removeClass("auto-focus");
+ focuson = focuson.nextAll("li:visible:first");
+ var prev = parseInt(focuson.prevAll("li:visible").length, 10);
+ var next = parseInt(focuson.nextAll("li:visible").length, 10);
+ if ((prev > Math.round(options.height / 2) || next <= Math.round(options.height / 2)) && typeof(focuson.get(0)) != "undefined") {
+ feed.get(0).scrollTop = parseInt(focuson.get(0).scrollHeight, 10) * (prev - Math.round(options.height / 2));
+ }
+ }
+ feed.children("li").removeClass("auto-focus");
+ focuson.addClass("auto-focus");
+ }
+ if (event.keyCode == 38) {
+ removeFeedEvent();
+ if (focuson == null || focuson.length == 0) {
+ focuson = feed.children("li:visible:last");
+ feed.get(0).scrollTop = parseInt(focuson.get(0).scrollHeight, 10) * (parseInt(feed.children("li:visible").length, 10) - Math.round(options.height / 2));
+ }
+ else {
+ focuson.removeClass("auto-focus");
+ focuson = focuson.prevAll("li:visible:first");
+ var prev = parseInt(focuson.prevAll("li:visible").length, 10);
+ var next = parseInt(focuson.nextAll("li:visible").length, 10);
+ if ((next > Math.round(options.height / 2) || prev <= Math.round(options.height / 2)) && typeof(focuson.get(0)) != "undefined") {
+ feed.get(0).scrollTop = parseInt(focuson.get(0).scrollHeight, 10) * (prev - Math.round(options.height / 2));
+ }
+ }
+ feed.children("li").removeClass("auto-focus");
+ focuson.addClass("auto-focus");
+ }
+ });
+ }
+
+ function maxItems(){
+ if (options.maxitems != 0) {
+ if (holder.children("li.bit-box").length < options.maxitems) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ function addTextItem(value){
+ if (options.newel && maxItems()) {
+ feed.children("li[fckb=1]").remove();
+ if (value.length == 0) {
+ return;
+ }
+ var li = $(document.createElement("li"));
+ li.attr({
+ "rel": value,
+ "fckb": "1"
+ }).html(value);
+ feed.prepend(li);
+ counter++;
+ }
+ else {
+ return;
+ }
+ }
+
+ function funCall(func, item){
+ var _object = "";
+ for (i = 0; i < item.get(0).attributes.length; i++) {
+ if (item.get(0).attributes[i].nodeValue != null) {
+ _object += "\"_" + item.get(0).attributes[i].nodeName + "\": \"" + item.get(0).attributes[i].nodeValue + "\",";
+ }
+ }
+ _object = "{" + _object + " notinuse: 0}";
+ try {
+ eval(func + "(" + _object + ")");
+ }
+ catch (ex) {
+ };
+ }
+
+ function checkFocusOn(){
+ if (focuson == null) {
+ return false;
+ }
+ if (focuson.length == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ function xssPrevent(string){
+ string = string.replace(/[\"\'][\s]*javascript:(.*)[\"\']/g, "\"\"");
+ string = string.replace(/script(.*)/g, "");
+ string = string.replace(/eval\((.*)\)/g, "");
+ string = string.replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '');
+ return string;
+ }
+
+ var options = $.extend({
+ json_url: null,
+ cache: false,
+ height: "10",
+ newel: false,
+ firstselected: false,
+ filter_case: false,
+ filter_hide: false,
+ complete_text: "Start to type...",
+ maxshownitems: 30,
+ maxitems: 0,
+ onselect: "",
+ onremove: ""
+ }, opt);
+
+ //system variables
+ var holder = null;
+ var feed = null;
+ var complete = null;
+ var counter = 0;
+ var cache = new Array();
+ var json_cache = false;
+ var search_string = "";
+ var focuson = null;
+ var deleting = 0;
+ var browser_msie = "\v" == "v";
+ var browser_msie_frame;
+
+ var element = $(this);
+ var elemid = element.attr("id");
+ init();
+
+ return this;
+ });
+ };
+});