Changeset 6267
- Timestamp:
- 02/10/10 15:20:30 (2 years ago)
- Location:
- trunk/TagMePlugin
- Files:
-
- 3 edited
-
data/System/TagMeAjaxHelper.txt (modified) (3 diffs)
-
pub/System/TagMeAjaxHelper/jqui.css (modified) (1 diff)
-
pub/System/TagMeAjaxHelper/jqui.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/TagMePlugin/data/System/TagMeAjaxHelper.txt
r6196 r6267 8 8 }% 9 9 %ENDSECTION{"tagquery"}% 10 %STARTSECTION{"jqui"}%%JQREQUIRE{"textboxlist"}%%JQREQUIRE{"autocomplete"}%%JQREQUIRE{"simplemodal"}%%JQREQUIRE{"hoverintent"}%% ADDTOHEAD{10 %STARTSECTION{"jqui"}%%JQREQUIRE{"textboxlist"}%%JQREQUIRE{"autocomplete"}%%JQREQUIRE{"simplemodal"}%%JQREQUIRE{"hoverintent"}%%JQREQUIRE{"queryobject"}%%ADDTOHEAD{ 11 11 "TAGMEPLUGIN::JQUI" 12 12 text="<meta name='foswiki.TagMePlugin.jquitags' … … 16 16 <link rel='stylesheet' href='%PUBURLPATH%/%SYSTEMWEB%/TagMeAjaxHelper/jqui.css' 17 17 type='text/css' media='all'/>" 18 requires="JQUERYPLUGIN::TEXTBOXLIST, JQUERYPLUGIN::AUTOCOMPLETE, JQUERYPLUGIN::SIMPLEMODAL, JQUERYPLUGIN::HOVERINTENT" 19 }%<div id='tagmejqcontainer'><span id="tagmejqtagstatus"> </span><div id="tagmejqcloud" style="display:none"></div><a id="tagmejqtag" href="%SCRIPTURLPATH{"view"}%/%SYSTEMWEB%/TagMeViewAllTags">%MAKETEXT{"Tags"}% </a><form name="tagmeshow" method="post" action="%SCRIPTURLPATH{"viewauth"}%/%WEB%/%TOPIC%"> 18 requires="JQUERYPLUGIN::TEXTBOXLIST, JQUERYPLUGIN::AUTOCOMPLETE, JQUERYPLUGIN::SIMPLEMODAL, JQUERYPLUGIN::HOVERINTENT, JQUERYPLUGIN::QUERYOBJECT" 19 }%<div id='tagmejqcontainer'><span id="tagmejqtagstatus"> </span> 20 <div id="tagmejqcloud" style="display:none"></div> 21 <span id="tagmejqtag" title="%MAKETEXT{"Click for tag cloud pop-up"}%"> 22 %MAKETEXT{"Tags"}% </span> 23 <form name="tagmeshow" method="post" action="%SCRIPTURLPATH{"viewauth"}%/%WEB%/%TOPIC%"> 20 24 <input type="text" name="add" id="tagmejqinputfield" title="%MAKETEXT{"Enter a tag name to apply to this topic"}%" size="15" value="%TAGME{ tpaction="showalltags" web="%BASEWEB%" topic="%BASETOPIC%"}%"/> 21 25 </form></div>%ENDSECTION{"jqui"}% 22 26 23 %STARTSECTION{"cloud"}%<form id="tagmeWebSelect" method="post" action="%SCRIPTURLPATH{"view"}%/%WEB%/%TOPIC%"> 24 Tags: 25 <input type="checkbox" id="tagmeCheckboxJustThisWeb" name="web" value="%BASEWEB%" checked="checked"/> 26 <label for="web">from just this web</label> 27 <input type="checkbox" id="tagmeCheckboxJustMe" name="user" value="me"/> 28 <label for="web">set by me</label> 29 </form><div id="tagmeTagCloud" style="line-height:2em;"> 30 %TAGME{tpaction="showalltags" web="%URLPARAM{"tpweb"}%" by="%URLPARAM{"tpuser"}%" format="<a href=\"%SCRIPTURLPATH{"view"}%/%SYSTEMWEB%/TagMeSearch?tag=$tag;by=%URLPARAM{ "by" }%\" style=\"font-size:$size%\">$tag</a>" separator=" " minsize="94" maxsize="220" by="%URLPARAM{ "tpuser" }%" }% 27 %STARTSECTION{"cloud"}% 28 ---+++ %MAKETEXT{"Tag Cloud for"}% %IF{"'%URLPARAM{"tpweb"}%'=''" 29 then="%MAKETEXT{"all webs"}%" 30 else="%MAKETEXT{"[[[_1].WebHome][[_1]]] web" args="%URLPARAM{"tpweb"}%"}%" 31 }% 32 <br/> 33 <form id="tagmeWebSelect" method="post" action="%SCRIPTURLPATH{"view"}%/%WEB%/%TOPIC%"> 34 <input type="checkbox" id="tagmeCheckboxJustThisWeb" name="tpweb"\ 35 value="%URLPARAM{"tpweb"}%" %IF{"'%URLPARAM{"tpweb"}%'=''" then="checked='checked'"}%\ 36 title="%MAKETEXT{"Show tags from all webs"}%"\ 37 /> 38 <label for="tpweb">%MAKETEXT{"all webs"}%</label> | 39 <input type="checkbox" id="tagmeCheckboxJustMe" name="tpuser" value="me" \ 40 %IF{"'%URLPARAM{"tpuser"}%'='me'" then="checked='checked'"}%\ 41 title="%MAKETEXT{"Show tags used by me"}%"\ 42 /> 43 <label for="tpuser">%MAKETEXT{"set by me"}%</label> | 44 <a href="%SCRIPTURLPATH{"view"}%/%SYSTEMWEB%/TagMeRenameTag"\ 45 title="%MAKETEXT{"Rename tags"}%">%MAKETEXT{"rename..."}%</a> | 46 <a href="%SCRIPTURLPATH{"view"}%/%SYSTEMWEB%/TagMeDeleteTag"\ 47 title="%MAKETEXT{"Delete tags"}%">%MAKETEXT{"delete..."}%</a> 48 </form> 49 <div id="tagmeTagCloud" style="line-height:2em;"> 50 %TAGME{tpaction="showalltags" 51 web="%URLPARAM{"tpweb"}%" 52 by="%URLPARAM{"tpuser"}%" 53 format="<a href='%SCRIPTURLPATH{"view"}%/%SYSTEMWEB%/TagMeSearch?tag=$tag;by=%URLPARAM{ "tpuser" }%;qcallingweb=%URLPARAM{"qcallingweb"}%' style='font-size:$size%' title='%MAKETEXT{"Other topics with this tag"}%'>$tag</a>" 54 separator=" " 55 minsize="94" 56 maxsize="220" 57 }% 31 58 </div>%ENDSECTION{"cloud"}% 32 59 … … 34 61 * Set NOWYSIWYG = 1 35 62 --> 63 -
trunk/TagMePlugin/pub/System/TagMeAjaxHelper/jqui.css
r6196 r6267 1 1 #tagmejqcontainer { 2 2 } 3 3 4 #tagmejqtagstatus, #tagmejqtag { 4 5 float: left; 6 } 7 #tagmejqtag { 8 text-decoration: underline; 9 } 10 #tagmejqtag:hover { 11 color: #C0FFC0; 12 background-color: #778899; 13 cursor: pointer; 5 14 } 6 15 #tagmejqtagstatus { -
trunk/TagMePlugin/pub/System/TagMeAjaxHelper/jqui.js
r6196 r6267 1 /*Interactive user interface for TagMePlugin, implemented wth JQuery. 2 3 This file is Copyright (C) 2010 Paul.W.Harvey@csiro.au - www.taxonomy.org.au 4 Centre for Plant Biodiversity Research, CSIRO Plant Industry - www.csiro.au/pi 5 6 This program is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free Software 8 Foundation; either version 2 of the License, or (at your option) any later 9 version. 10 11 This program is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 PARTICULAR PURPOSE. See the GNU General Public License for more details, 14 published at http://www.gnu.org/copyleft/gpl.html */ 15 1 /* 2 * Interactive user interface for Foswiki TagMePlugin, implemented wth JQuery. 3 * 4 * This file is Copyright (C) 2010 Paul.W.Harvey@csiro.au - www.taxonomy.org.au 5 * Centre for Plant Biodiversity Research CSIRO Plant Industry- www.csiro.au/pi 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details, published at http://www.gnu.org/copyleft/gpl.html 16 * 17 * @author: Paul Harvey <Paul.W.Harvey@csiro.au> 18 * @date: 2010-02-10 19 * @see: http://foswiki.org/Extensions/TagMePlugin#jqui 20 */ 21 22 23 'use strict'; 16 24 jQuery(document).ready(function () { 17 var didCloudHover = false; 18 19 /* Check that tagName exists inList, and if not, POST the action and execute 20 ** the finishHandler(tagName) */ 21 var actOnMissingTag = function (tagName, inList, action, finishHandler) { 22 var didModify = false; 23 24 if (jQuery.inArray(tagName, inList) === -1) { 25 jQuery('#tagmejqtagstatus').addClass('spinning'); 26 jQuery.post(foswiki.scriptUrlPath + '/viewauth/' + foswiki.web + 27 '/' + foswiki.topic, { 28 tpaction : action, 29 tptag : tagName, 30 contenttype : 'text/plain', 31 skin : 'tagmejquiajax' 32 }, 33 function (data) { 34 linkifyTagText(); 35 jQuery('#tagmejqtagstatus').removeClass('spinning'); 36 finishHandler(tagName); 37 } 38 ); 39 didModify = true; 40 } 41 42 return didModify; 43 } 44 45 /* There must be an easier way to remove the textNode from a span; but 46 ** I don't know it... yet. .text('') destroys child elements we want to 47 ** keep. */ 48 var removeTextNodes = function (element) { 49 jQuery(element).contents().filter( 50 function() { 51 if (this.nodeType === Node.TEXT_NODE) { 52 this.textContent = ''; 53 } 54 } 55 ); 56 57 return; 58 }; 59 /* By default, textboxlist doesn't handle hyperlinks in the list items. 60 ** This would be much better implemented using some sort of callback, but 61 ** textboxlist didn't seem to implement a suitable hook. */ 62 var linkifyTagText = function () { 63 jQuery( 64 '#tagmejqcontainer > form > div.jqTextboxListContainer > span:not(.linkified)' 65 ).each( 66 function (index, tagSpan) { 67 theTag = jQuery(tagSpan).text(); 68 removeTextNodes(tagSpan); 69 jQuery(tagSpan).append('<a href="' + foswiki.scriptUrlPath + '/view/' + 70 foswiki.systemWebName + '/TagMeSearch?tag=' + theTag + 71 '" title="Other topics with this tag">' + theTag + '</a>'); 72 jQuery(tagSpan).addClass('linkified'); 73 } 74 ); 75 76 return; 77 }; 78 79 /* Convert the comma separated list of tags into an array. */ 80 foswiki.TagMePlugin.jquitags = foswiki.TagMePlugin.jquitags.split(','); 81 82 /* Use Michael Daum's very nifty textboxlist jq plugin to allow the user to 83 ** work on tags */ 84 jQuery("#tagmejqinputfield").textboxlist( 85 { 86 onSelect: function(input) { 87 /* The logic here is a bit odd, started out anticipating a batch rather than 88 ** one-by-one POST to updated a modified selection of tags... */ 89 var selectedTags = input.currentValues; 90 var didAdd = false; 91 /* If there's a selected tag that isn't in the list of stored tags, 92 ** it needs to be added. */ 93 jQuery.each(selectedTags, 94 function (index, tagName) { 95 didAdd = actOnMissingTag(tagName, foswiki.TagMePlugin.jquitags, 'add', 96 function (tagName) { 97 foswiki.TagMePlugin.jquitags.push(tagName); 98 } 99 ) 100 } 101 ); 102 103 if (!didAdd) { 104 /* If there's a stored tag that isn't in the list of selected tags, 105 ** it needs to be removed. */ 106 jQuery.each(foswiki.TagMePlugin.jquitags, 107 function (index, tagName) { 108 if ( 109 !actOnMissingTag(tagName, selectedTags, 'remove', 110 function (tagName) { 111 foswiki.TagMePlugin.jquitags.pop(tagName); 112 } 113 ) 114 ) { 115 linkifyTagText(); 116 } 117 } 118 ); 119 } 120 }, 121 122 autocomplete: foswiki.scriptUrlPath + '/view/' + foswiki.systemWebName + '/TagMeAjaxHelper', 123 124 autocompleteOpts: { 125 extraParams: { 126 section : 'tagquery', 127 contenttype : 'text/plain', 128 skin : 'text' 129 }, 130 autoFill: true, 131 matchCase: false, 132 multiple: false, 133 max: 0, 134 mustMatch: false 135 } 136 } 137 ); 138 linkifyTagText(); 139 140 var loadCloud = function (urlExtra) { 141 if (typeof(urlExtra) !== 'string') { 142 urlExtra = ''; 143 } 144 jQuery('#tagmejqtag').addClass('spinning'); 145 jQuery('#tagmejqcloud').load(foswiki.scriptUrlPath + '/view/' + 146 foswiki.systemWebName + '/TagMeAjaxHelper?skin=text;contenttype=text/plain;section=cloud' + 147 urlExtra, 148 function () { 149 jQuery('#tagmejqtag').removeClass('spinning'); 150 jQuery('#tagmejqcloud').modal( 151 { 152 opacity: 7, 153 position: ['50px', null], 154 maxWidth: (document.width - 50) 155 } 156 ); 157 } 158 ); 159 }; 160 161 /* Fire up the tag cloud in a modal dialogue on mouse hover */ 162 jQuery('#tagmejqtag').hoverIntent( 163 { 164 over : function () {loadCloud()}, 165 166 out: function () {} 167 } 168 ); 169 170 /* Auto-close the tags dialogue after the mouse has wandered over it and 171 ** away again. */ 172 jQuery('#tagmejqcloud').hoverIntent( 173 { 174 interval : 60, 175 176 over : function () { 177 /* Arm the UI to close the dialogue on mouseout */ 178 didCloudHover = true; 179 jQuery('#tagmeCheckboxJustThisWeb').click(function () 180 { 181 loadCloud(';tpweb=' + jQuery(this).val()); 182 } 183 ); 184 jQuery('#tagmeCheckboxJustMe').click(function () 185 { 186 loadCloud(';tpuser=me'); 187 } 188 ); 189 }, 190 191 out : function () { 192 if (didCloudHover) { 193 jQuery.modal.close(); 194 } 195 } 196 } 197 ); 198 } 199 ); 25 (function ($) { 26 $.fn.tagmeui = function (options) { 27 $(this).each(function () { 28 var tagmeui = new TagMeUI($(this), options); 29 30 tagmeui.initTagField(); 31 }); 32 33 return this; 34 }; 35 36 function TagMeUI(caller, options) { 37 var that = this; 38 39 this.caller = caller; 40 this.urlQuery = $.parsequery(window.location.search); 41 this.cloudQuery = this.urlQuery.copy(); 42 this.cloudQuery.SET('skin', 'text'); 43 this.cloudQuery.SET('contenttype', 'text/plain'); 44 this.cloudQuery.SET('section', 'cloud'); 45 /* Convert comma separated list of tags (from html meta) to array */ 46 this.tags = foswiki.TagMePlugin.jquitags.split(','); 47 if (!this.cloudQuery.get('qcallingweb')) { 48 this.cloudQuery.SET('qcallingweb', foswiki.web); 49 } 50 this.settings = { 51 cloudSpinner: '#tagmejqtag', 52 cloudContainer: '#tagmejqcloud', 53 cloudWeb: (function () { 54 var web = that.cloudQuery.get('qcallingweb'); 55 56 if (!web) { 57 web = foswiki.web; 58 } 59 60 if (!that.cloudQuery.get('tpweb')) { 61 that.cloudQuery.SET('tpweb', web); 62 } 63 64 return web; 65 }()), 66 cloudGetUrl: foswiki.scriptUrlPath + '/view/' + 67 foswiki.systemWebName + '/TagMeAjaxHelper', 68 cloudUiJustThisWeb: '#tagmeCheckboxJustThisWeb', 69 cloudUiJustMe: '#tagmeCheckboxJustMe', 70 cloudModalOpts: { 71 opacity: 7, 72 position: ['50px', null], 73 maxWidth: (document.width - 50), 74 persist: true, 75 onShow: function () { 76 $('#simplemodal-overlay').click( 77 78 function () { 79 $.modal.close(); 80 }); 81 } 82 }, 83 taglistSpinner: '#tagmejqtagstatus', 84 taglistContainer: '#tagmejqcontainer', 85 taglistInputField: '#tagmejqinputfield', 86 tagLinkUrl: foswiki.scriptUrlPath + '/view/' + 87 foswiki.systemWebName + '/TagMeSearch', 88 tagPostUrl: foswiki.scriptUrlPath + '/viewauth/' + foswiki.web + 89 '/' + foswiki.topic, 90 autocompleteUrl: foswiki.scriptUrlPath + '/view/' + 91 foswiki.systemWebName + '/TagMeAjaxHelper', 92 autocompleteOpts: { 93 extraParams: { 94 section: 'tagquery', 95 contenttype: 'text/plain', 96 skin: 'text' 97 }, 98 autoFill: true, 99 matchCase: false, 100 multiple: false, 101 max: 0, 102 mustMatch: false 103 } 104 }; 105 $.extend(this.settings, options); 106 } 107 108 /* Check that tagName exists inList, and if not, POST the action and execute 109 ** the finishHandler(tagName) */ 110 TagMeUI.prototype.actOnMissingTag = function (tagName, inList, action, finishHandler) { 111 var didModify = false, 112 that = this; 113 114 if ($.inArray(tagName, inList) === -1) { 115 $(this.settings.taglistSpinner).addClass('spinning'); 116 $.post(this.settings.postUrl, { 117 tpaction: action, 118 tptag: tagName, 119 contenttype: 'text/plain', 120 skin: 'tagmejquiajax' 121 }, 122 123 function (data) { 124 that.linkifyTagText(that.settings.taglistContainer); 125 $(that.settings.taglistSpinner).removeClass('spinning'); 126 finishHandler(tagName); 127 }); 128 didModify = true; 129 } 130 131 return didModify; 132 }; 133 134 /* By default, textboxlist doesn't handle hyperlinks in the list items. 135 ** This would be much better implemented using some sort of callback, but 136 ** textboxlist didn't seem to implement a suitable hook. */ 137 TagMeUI.prototype.linkifyTagText = function (selector) { 138 var that = this; 139 $(selector + ' > form > div.jqTextboxListContainer > span:not(.linkified)').each( 140 function (index, tagSpan) { 141 var tagQuery = $.parsequery().copy(); 142 143 /* There must be an easier way to remove the textNode from a span; but 144 ** I don't know it... yet. .text('') destroys child elements we want to 145 ** keep. */ 146 function removeTextNodes(element) { 147 $(element).contents().filter( 148 function () { 149 if (this.nodeType === Node.TEXT_NODE) { 150 this.textContent = ''; 151 } 152 } 153 ); 154 155 return; 156 } 157 158 theTag = $(tagSpan).text(); 159 tagQuery.SET('tag', theTag); 160 tagQuery.SET('qcallingweb', foswiki.web); 161 removeTextNodes(tagSpan); 162 $(tagSpan).append('<a href="' + that.settings.tagLinkUrl + 163 tagQuery.toString() + '" title="Other topics with this tag">' + 164 theTag + '</a>'); 165 $(tagSpan).addClass('linkified'); 166 } 167 ); 168 169 return; 170 }; 171 172 TagMeUI.prototype.loadCloud = function () { 173 var that = this; 174 175 function initDialogue() { 176 function setQueryWithCheckbox(qkey, qvalue, checkbox, sense) { 177 if ($(checkbox).is(':checked') === sense) { 178 that.cloudQuery.SET(qkey, qvalue); 179 } else { 180 that.cloudQuery = that.cloudQuery.remove(qkey); 181 } 182 } 183 184 if ($('#simplemodal-container').width() > $(document).width() - 50) { 185 $('#simplemodal-container').width($(document).width() - 50); 186 } 187 $(that.settings.cloudUiJustThisWeb).click(function () { 188 setQueryWithCheckbox('tpweb', that.settings.cloudWeb, 189 that.settings.cloudUiJustThisWeb, false); 190 that.loadCloud(); 191 }); 192 $(that.settings.cloudUiJustMe).click(function () { 193 setQueryWithCheckbox('tpuser', 'me', 194 that.settings.cloudUiJustMe, true); 195 that.loadCloud(); 196 }); 197 } 198 199 $(this.settings.cloudSpinner).addClass('spinning'); 200 $(this.settings.cloudContainer).load(this.settings.cloudGetUrl + 201 this.cloudQuery.toString(), function () { 202 $(that.settings.cloudSpinner).removeClass('spinning'); 203 $(that.settings.cloudContainer).modal(that.settings.cloudModalOpts); 204 initDialogue(); 205 }); 206 }; 207 208 TagMeUI.prototype.initTagField = function () { 209 /* MD's textboxlist jq plugin allows the user to easily work on tags */ 210 var that = this; 211 212 $(this.settings.taglistInputField).textboxlist({ 213 onSelect: function (input) { 214 /* The logic here is a bit odd, started out anticipating a batch rather than 215 ** one-by-one POST to updated a modified selection of tags... */ 216 var selectedTags = input.currentValues, 217 didAdd = false; 218 219 /* If there's a selected tag that isn't in the list of stored tags, 220 ** it needs to be added. */ 221 $.each(selectedTags, function (index, tagName) { 222 if (that.actOnMissingTag(tagName, that.tags, 'add', 223 function (tagName) { 224 that.tags.push(tagName); 225 }) 226 ) { 227 didAdd = true; 228 } 229 }); 230 231 if (!didAdd) { 232 /* If there's a stored tag that isn't in the list of selected tags, 233 ** it needs to be removed. */ 234 $.each(that.tags, function (index, tagName) { 235 if (!that.actOnMissingTag(tagName, selectedTags, 'remove', 236 function (tagName) { 237 that.tags.pop(tagName); 238 }) 239 ) { 240 that.linkifyTagText(that.settings.taglistContainer); 241 } 242 }); 243 } 244 }, 245 246 autocomplete: this.settings.autocompleteUrl, 247 248 autocompleteOpts: this.settings.autocompleteOpts 249 }); 250 251 this.linkifyTagText(this.settings.taglistContainer); 252 253 $(this.settings.cloudSpinner).click(function () { 254 that.loadCloud(); 255 }); 256 }; 257 258 $.fn.tagmeui(); 259 }(jQuery)); 260 });
Note: See TracChangeset
for help on using the changeset viewer.
