From cf00965f26b85f6d05286a864b20e3c099ad5ee5 Mon Sep 17 00:00:00 2001 From: Artanis Date: Wed, 31 Oct 2007 21:30:41 +0000 Subject: [PATCH] Tagger v2 - 20071031 1430 - Add/Remove/Applied tag indicator images. - Rewrote JS to be neater. - Removed overly complicated and not-quite-functional search limiter in favor of slightly delaying query. - SQL escaping moved to PHP for safety. - Added option "Enable Tagger." Defaults false. - Added option "Delay queries by [$int] milliseconds." Delays AJAX using timeouts, waits for additional characters. Default 250. - Added option "Limit queries returning more than [$int] tags to [$int]." Limits server hit and client-side memory overhead. Defaults 30 and 30. git-svn-id: file:///home/shish/svn/shimmie2/trunk@604 7f39781d-f577-437e-ae19-be835c7a54ca --- contrib/tagger/images/active.png | Bin 0 -> 183 bytes contrib/tagger/images/add-tag.png | Bin 0 -> 227 bytes contrib/tagger/images/inactive.png | Bin 0 -> 170 bytes contrib/tagger/images/rem-tag.png | Bin 0 -> 198 bytes contrib/tagger/images/tag-img.psd | Bin 0 -> 2148 bytes contrib/tagger/main.php | 30 +- contrib/tagger/script.js | 518 +++++++++++------------------ contrib/tagger/style.css | 16 +- contrib/tagger/theme.php | 25 +- 9 files changed, 244 insertions(+), 345 deletions(-) create mode 100644 contrib/tagger/images/active.png create mode 100644 contrib/tagger/images/add-tag.png create mode 100644 contrib/tagger/images/inactive.png create mode 100644 contrib/tagger/images/rem-tag.png create mode 100644 contrib/tagger/images/tag-img.psd diff --git a/contrib/tagger/images/active.png b/contrib/tagger/images/active.png new file mode 100644 index 0000000000000000000000000000000000000000..4e4942c8c5a6e8feea2cff6c10ba8eb424db9f3f GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCyDDqA0IPmT(MivH9 X4OWH=yO!z$l`(j_`njxgN@xNAvJx>W literal 0 HcmV?d00001 diff --git a/contrib/tagger/images/add-tag.png b/contrib/tagger/images/add-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..dccedf8ddddb993f70433fe86b774538df5bce75 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCyDKq1)@*N775{M_8syb=cIqSVBa z)D(sC%#sX+kc?CXcTeAd_bIA*K!xs}E{-7*m#0oR$jhL>!OZ`-hwtR1uS*RzIKR0s zU}x>x6rlZj`->7wz5N}wibr|3U8o9VXyawb-k(@f4u_bxCyDFVdQ I&MBb@0P46Y%m4rY literal 0 HcmV?d00001 diff --git a/contrib/tagger/images/rem-tag.png b/contrib/tagger/images/rem-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb9827a0f400c615120a8c0c27d6f4c9cfc7f66 GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCyD_A-%p00i_>zopr0N6t|Qvd(} literal 0 HcmV?d00001 diff --git a/contrib/tagger/images/tag-img.psd b/contrib/tagger/images/tag-img.psd new file mode 100644 index 0000000000000000000000000000000000000000..4404dfeea31c728a139b28eba5fff6b859d508a9 GIT binary patch literal 2148 zcmd^=%}T>S5XUD?sUP&vg9o1>&`VF^Npey_5WMyhZIvReP+IYs_9c8GkY{%2;B zO_SCyL=bn$>}F>6x3jym$w7R6K>=wA(d^2zP2A@a9mFSR;gj?`bc{AYbuHVPVxk69 zS{a@fYN<-3@|xD-EfP&6^Fr=Sh{Aro-_& zq(dQX*efCVy-KcTqx)e6wq~#1qwULl5be=ql^0+gwVG1BV%0T2YSjHw&Y|D(v}vtk z_BQ6PJlomARa&Hr@4o$Eb_4fzwc_kDTH4G>qG!3LRay2a&bCa#S#uUF$(p5;mR^k| zm1RBqx$Ia^utI>uSbS7e;;qnsNcc(&yeB)TEzMWWW!;B>?CT@uN3^b^dgtRaoY zU2W+~?77aZnmyN#DE8|IM&x@daVbytuzZ%PQEMqWw-#Pg9!a_V_nw?FyOK35_3S^T zOKpZM&LBfF1|7oHvj+cE8}LoR$Juwht#H@T_}-ZeIi5j=xEJUU7#1utfx)c-$9KG~ caM#hPDRVd;<#0SQoa6Bw;fRen;+}Kf0P5AOVE_OC literal 0 HcmV?d00001 diff --git a/contrib/tagger/main.php b/contrib/tagger/main.php index 34bdd62c..cb54bae9 100644 --- a/contrib/tagger/main.php +++ b/contrib/tagger/main.php @@ -15,8 +15,23 @@ class Tagger extends Extension { if(is_a($event,'DisplayingImageEvent')) { global $page, $config, $user; - if($config->get_bool("tag_edit_anon") || ($user->id != $config->get_int("anon_id"))) + if($config->get_bool("tag_edit_anon") + || ($user->id != $config->get_int("anon_id")) + && $config->get_bool("ext_tagger_enabled")) + { $this->theme->build_tagger($page,$event); + } + } + if(is_a($event,'SetupBuildingEvent')) { + $sb = new SetupBlock("Tagger"); + $sb->add_bool_option("ext_tagger_enabled","Enable Tagger"); + $sb->add_int_option("ext_tagger_search_delay","
Delay queries by "); + $sb->add_label(" milliseconds."); + $sb->add_label("
Limit queries returning more than "); + $sb->add_int_option("ext_tagger_tag_max"); + $sb->add_label(" tags to "); + $sb->add_int_option("ext_tagger_limit"); + $event->panel->add_block($sb); } } } add_event_listener( new tagger()); @@ -42,7 +57,7 @@ class TaggerXML extends Extension { } $xml = "\n". - "". + "". $tags. ""; @@ -55,11 +70,14 @@ class TaggerXML extends Extension { private function match_tag_list ($s) { global $database, $config, $event; + $max_rows = $config->get_int("ext_tagger_tag_max",30); + $limit_rows = $config->get_int("ext_tagger_limit",30); + $values = array(); // Match - $p = strlen($s) == 1? " ":"\_"; - $sq = "%".$p.$s."%"; + $p = strlen($s) == 1? " ":"_"; + $sq = "%".mysql_real_escape_string($p.$s)."%"; $match = "concat(?,tag) LIKE ?"; array_push($values,$p,$sq); // Exclude @@ -74,9 +92,9 @@ class TaggerXML extends Extension { // FROM based on return count $q_from = null; $count = $this->count($q_where,$values); - if ($count > 60) { + if ($count > $max_rows) { $q_from = "FROM (SELECT * FROM `tags` {$q_where} ". - "ORDER BY count DESC LIMIT 0,30) AS `c_tags`"; + "ORDER BY count DESC LIMIT 0, {$limit_rows}) AS `c_tags`"; $q_where = null; $count = array("max"=>$count); } else { diff --git a/contrib/tagger/script.js b/contrib/tagger/script.js index 43f91885..e01c8168 100644 --- a/contrib/tagger/script.js +++ b/contrib/tagger/script.js @@ -3,328 +3,216 @@ * Author: Artanis (Erik Youngren ) * * Do not remove this notice. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* Tagger Window Object - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -function Tagger() { -// components - this.t_parent = null; - this.t_title = null; - this.t_toolbar = null; - this.t_menu = null; - this.t_body = null; - this.t_tags = null; - this.t_form = null; - this.t_status = null; -// data - this.searchTags = null; - this.appliedTags = null; -// methods - this.initialize = initialize; - this.submit = submit; - this.getPosition = function () { return findPos(this.t_parent); }; - this.setPosition = setPosition; - this.setSavedPosition = setSavedPosition; - this.getSavedPosition = getSavedPosition; - this.tagSearch = tagSearch; - this.searchRequest = searchRequest; - this.searchReceive = searchReceive; - this.tagListReceive = tagListReceive; - this.tagPublish = tagPublish; - this.prepTags = prepTags; - this.createTag = createTag; - this.buildPages = buildPages; - this.tagsToString = tagsToString; - this.toggleTag = toggleTag; - this.setAlert = setAlert; - - -// definitions - function initialize () { + +var Tagger = { + initialize : function (image_id) { + // object navigation + this.tag.parent = this; + this.position.parent = this; // components - this.t_parent = byId("tagger_parent"); - this.t_title = byId("tagger_titlebar"); - this.t_toolbar = byId("tagger_toolbar"); - this.t_menu = byId("tagger_p-menu"); - this.t_body = byId("tagger_body"); - this.t_tags = byId("tagger_tags"); - this.t_form = this.t_tags.parentNode; - this.t_status = byId("tagger_statusbar"); - //pages - //this.buildPages(); + this.editor.container = byId('tagger_parent'); + this.editor.titlebar = byId('tagger_titlebar'); + this.editor.toolbar = byId('tagger_toolbar'); + //this.editor.menu = byId('tagger_p-menu'); + this.editor.body = byId('tagger_body'); + this.editor.tags = byId('tagger_tags'); + this.editor.form = this.editor.tags.parentNode; + this.editor.statusbar = byId('tagger_statusbar'); // initial data - ajaxXML(query+"/"+image_id,tagListReceive); - // reveal - this.t_parent.style.display = ""; - // dragging - DragHandler.attach(this.t_title); - // set position - var pos = ( Tagger.getSavedPosition() || Tagger.getPosition() ); - setPosition(pos[0],pos[1]); - // events - window.onunload = function () {Tagger.setSavedPosition(); }; + this.tag.image = image_id; + this.tag.query = config.make_link("tagger/tags"); + this.tag.list = null; + this.tag.suggest = null; + this.tag.image_tags(); - } - function submit() { - this.t_tags.value = Tagger.tagsToString(Tagger.appliedTags); - } - function setPosition(x,y) { - if(!x || !y) { - with(Tagger.t_parent.style) { - top = "25px"; - left = ""; - right = "25px"; - bottom = ""; - } - var pos = Tagger.getPosition(); - x = pos[0]; - y = pos[1]; - } - with(Tagger.t_parent.style) { - top = y+"px"; - left = x+"px"; - right=""; - bottom=""; - } - } - function setSavedPosition(x,y) { - if (!x || !y) { - var p = Tagger.getPosition(); - x = p[0]; - y = p[1]; - } - setCookie("shimmie_tagger-position",x+" "+y,14); - } - function getSavedPosition() { - var p = getCookie("shimmie_tagger-position"); - if(p) { - return p.split(" "); - } else { - return false; - } - } - function tagSearch(s,ms) { - clearTimeout(tagger_filter_timer); - tagger_filter_timer = setTimeout("Tagger.searchRequest('"+s+"')",ms); - } - function searchRequest(s) { - var s_query = !s? query+"?s" : query+"?s="+sqlescape(s); - - if(!this.searchTags) { - ajaxXML(s_query,searchReceive); - return true; - } else { - var prv_s = this.searchTags.getAttribute('query'); - - if(s==prv_s) { - return false; - }else if(!s || s.length <= 2 || s.length 2 && s.match(reescape(prv_s))) { - var len = this.searchTags.childNodes.length; - - for (var i=len-1; i>=0; i--) { - var tag = this.searchTags.childNodes[i]; - var t_name = tag.firstChild.data; - - if(!t_name.match(reescape(s))) { - this.searchTags.removeChild(tag); - // TODO: Fix so back searches are not needlessly re-queried. - //tag.setAttribute("style","display:none;"); - } else { - //tag.setAttribute("style",""); - } - } - - if (len != this.searchTags.childNodes.length) { - this.searchTags.setAttribute('query',s); - } - } - } - return false; - } - function searchReceive(xml) { - Tagger.searchTags = document.importNode(xml.getElementsByTagName("list")[0],true); - tagPublish(Tagger.searchTags,byId("tagger_p-search")); - - if(Tagger.searchTags.getAttribute("max")) { - Tagger.setAlert("maxout","Showing "+Tagger.searchTags.getAttribute("rows")+" of "+Tagger.searchTags.getAttribute("max")+" tags"); - } else { - Tagger.setAlert("maxout",false); - } - } + // reveal + this.editor.container.style.display = ""; - function tagListReceive(xml) { - Tagger.appliedTags = document.importNode(xml.getElementsByTagName("list")[0],true); - tagPublish(Tagger.appliedTags,byId("tagger_p-applied")); - } - function tagPublish(tag_list,page) { - page.innerHTML = ""; - Tagger.prepTags(tag_list); - page.appendChild(tag_list); - } - function prepTags(tag_list) { - var len = tag_list.childNodes.length; + // dragging + DragHandler.attach(this.editor.titlebar); + + // positioning + this.position.load(); + + // events + window.onunload = function () { Tagger.position.save(); }; + }, + + alert : function (type,text,timeout) { + var id = "tagger_alert-"+type + var t_alert = byId(id); + if (t_alert) { + if(text == false) { + // remove + t_alert.parentNode.removeChild(t_alert); + } else { + // update + t_alert.innerHTML = text; + } + } else if (text) { + // create + var t_alert = document.createElement("div"); + t_alert.setAttribute("id",id); + t_alert.appendChild(document.createTextNode(text)); + this.editor.statusbar.appendChild(t_alert); + if(timeout>1) { + console.log("Tagger.alert('"+type+"',false,0)"); + setTimeout("Tagger.alert('"+type+"',false,0)",timeout); + } + } + }, + + editor : {}, + + tag : { + submit : function () { + var l = this.list.childNodes.length; + var tags = Array(); + for(var i=0; i0) { - var tag = document.createElement("tag"); - tag.setAttribute("count","0"); - tag.setAttribute("id","newTag_"+tag_name); - tag.setAttribute("count",1); - tag.setAttribute("title","New"); - tag.onclick = function() { toggleTag(this); }; - tag.appendChild(document.createTextNode(tag_name)); - Tagger.appliedTags.appendChild(tag); - } - } - function buildPages () { - var pages = getElementsByTagNames("div",byId("tagger_body")); - var len = pages.length; - for(var i=0; i"+ - pages[i].getAttribute('name')+""; - } - } - function tagsToString(tags) { - var len = tags.childNodes.length; - var str = ""; - for (var i=0; i 0) { + var tag = document.createElement("tag"); + tag.setAttribute("count","0"); + tag.setAttribute("id","newTag_"+tag_name); + tag.setAttribute("title","New - 0 uses"); + tag.onclick = function() { + Tagger.tag.toggle(this); + }; + tag.appendChild(document.createTextNode(tag_name)); + Tagger.tag.list.appendChild(tag); + } + }, + + toggle : function (tag) { + if(tag.parentNode == this.list) { + this.list.removeChild(tag); + } else { + this.list.appendChild(tag); + } + }, + + ajax : function (url, callback) { + var http = (new XMLHttpRequest || new ActiveXObject("Microsoft.XMLHTTP")); + http.open("GET",url,true); + http.onreadystatechange = function () { + if(http.readyState == 4) callback(http); + }; + http.send(null); } - } -} - -/* AJAX - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -function ajaxXML(url, callback) { - //var http = getHTTPObject(); - var http = (new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")); - http.open("GET", url, true); - http.onreadystatechange = function() { - if(http.readyState == 4) callback(http.responseXML); - } - http.send(null); -} - -/* Miscellaneous Code - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Quirksmode -// http://www.quirksmode.org/dom/getElementsByTagNames.htmlgetElementbyId -function getElementsByTagNames(list,obj) { - if (!obj) var obj = document; - var tagNames = list.split(','); - var resultArray = new Array(); - for (var i=0;iadd_header(""); $page->add_block(new Block(null, - "","main",1000)); + "","main",1000)); // Tagger block $page->add_block( new Block( @@ -28,10 +23,12 @@ class taggerTheme extends Themelet { "main")); } private function html($image) { + global $config; $i_image_id = int_escape($image->id); $h_source = html_escape($image->source); - if(isset($_GET['search'])) {$h_query = "search=".url_escape($_GET['search']);} - else {$h_query = "";} + $h_query = isset($_GET['search'])? $h_query= "search=".url_escape($_GET['search']) : ""; + + $delay = $config->get_string("ext_tagger_search_delay","250"); $url_form = make_link("tag_edit/set"); @@ -41,9 +38,9 @@ class taggerTheme extends Themelet {
Tagger
- - -
+ + + @@ -55,9 +52,9 @@ class taggerTheme extends Themelet {
-->
-
-
+
+