All my scripts should be listed here
/***\n!Metadata:\n|''Name:''|ArchivedTimeline|\n|''Description:''|Timeline archived monthly.|\n|''Version:''|0.6.1|\n|''Date:''|Jul 25, 2006|\n|''Source:''|http://sourceforge.net/project/showfiles.php?group_id=150646|\n|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License]]|\n|''~CoreVersion:''|2.0.11|\n|''Browser:''|Firefox 1.5+; InternetExplorer 6.0|\n\n!Syntax/Examples:\n|{{{<<timeline [modified | created] [maxentries]>>}}}|\n!Revision History:\n|''Version''|''Date''|''Note''|\n|0.6.1|Aug 12, 2006|A great effect on config.macros.timeline.slider for Firefox, thanks Bob McElrath|\n|0.6.0|Jul 25, 2006|Runs compatibly with TW 2.1.0 (rev #403+)|\n|0.5.2|Jun 21, 2006|Fixed bugs for dateFormat of TW 2.1|\n|~|~|Change default dateFormat to "0DD mmm, YYYY"|\n|0.5.1|Jun 04, 2006|Added config.macros.archivedTimeline.orderBy for localization|\n|0.5.0|Apr 19, 2006|Fixed bug for twice records of the same date ()|\n|~|~|Added Date.prototype.convertToLocalYYYYMMDDHHMM<<br>>in order to backward compatible with 2.0.6-|\n|0.4.0|Apr 03, 2006|Added new parameter, {{{<<timeline [sortfield] [maxentries]>>}}}|\n|~|~|Added config.options.txtTimelineMaxentries|\n|0.3.1|Feb 04, 2006|JSLint checked|\n|0.3.0|Feb 04, 2006|Fixed several missing variable declarations|\n|0.2.0|Dec 26, 2005|changed for the new feature of Macro timeline of TW 2.0.0 beta 6|\n|0.1.0|Nov 3, 2005|Initial release|\n\n!Code section:\n***/\n//{{{\nversion.extensions.archivedTimeline = {major: 0, minor: 6, revision: 1,\n date: new Date("Aug 12, 2006"),\n name: "ArchivedTimeline",\n type: "Macro",\n author: "BramChen",\n source: "http://sourceforge.net/project/showfiles.php?group_id=150646"\n};\nconfig.options.txtTimelineMaxentries=0;\nconfig.macros.archivedTimeline = {\n tooltips: "Archives sorted by date ",\n orderBy:{modified: "modified", created: "created"},\n dateFormat: "0DD MMM YYYY"\n};\nconfig.macros.timeline = config.macros.archivedTimeline;\n\nconfig.macros.timeline.handler = function(place,macroName,params) {\n var field = params[0] ? params[0] : "modified";\n\n place.appendChild(document.createTextNode(this.tooltips + this.orderBy[field]));\n var tiddlers = store.reverseLookup("tags","excludeLists",false,field);\n var lastMonth = ""; var lastDay = ""; var theText = "----\sn"; var i = 0;\n var last = (params[1])?params[1]:config.options.txtTimelineMaxentries;\n last = (isNaN(last)||last<1) ? 0:tiddlers.length-Math.min(tiddlers.length,parseInt(last));\n var cookie; var archives;\n for (var t=tiddlers.length-1; t>=last; t--) {\n var tiddler = tiddlers[t];\n var theMonth = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,6);\n var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);\n if(theMonth != lastMonth) {\n if (lastMonth === "") {\n lastMonth = theMonth;\n }\n else {\n place.appendChild(document.createElement("hr"));\n cookie = 'chktimeline'+(i++);\n archives = this.formatString(this.dateFormat, lastMonth);\n this.slider(place,cookie,theText,archives,this.tooltips + archives);\n lastMonth = theMonth; theText = "----\sn";\n }\n }\n if(theDay != lastDay){\n theText += tiddler[field].formatString(this.dateFormat) + '\sn';\n lastDay = theDay; \n }\n theText += '* [[' + tiddler.title + ']]\sn';\n }\n place.appendChild(document.createElement("hr"));\n cookie = 'chktimeline'+(i++);\n archives = this.formatString(this.dateFormat, lastMonth);\n this.slider(place,cookie,theText,archives,this.tooltips + archives);\n place.appendChild(document.createElement("hr"));\n};\n\nconfig.macros.timeline.onClickSlider = config.macros.slider.onClickSlider;\n\nconfig.macros.timeline.slider = function(place,cookie,text,id,tooltips)\n{\n var btn = createTiddlyButton(place,id,tooltips,this.onClickSlider);\n var panel = document.createElement("div");\n panel.className = "timelineSliderPanel";\n panel.setAttribute("cookie",cookie);\n panel.style.display = config.options[cookie] ? "block" : "none";\n place.appendChild(panel);\n if(text){\n wikify(text,panel);\n }\n};\n\nconfig.macros.timeline.formatString = function(template, yyyymm)\n{\n var dateString = new Date(yyyymm.substr(0,4)+'/'+yyyymm.substr(4,2)+'/01');\n template = template.replace(/DDD|0DD|DD/g,'');\n return dateString.formatString(template);\n};\nif (!Date.prototype.convertToLocalYYYYMMDDHHMM){\n Date.prototype.convertToLocalYYYYMMDDHHMM = function(){\n return(String.zeroPad(this.getFullYear(),4) + String.zeroPad(this.getMonth()+1,2) + String.zeroPad(this.getDate(),2) + String.zeroPad(this.getHours(),2) + String.zeroPad(this.getMinutes(),2));\n }\n}\n//}}}
AutoHotkey is a free, open-source utility for Windows. but you already knew that.
PMagness
I don't know if there will ever be downloads from this site. Try the following:\n[[AHK]] - All my scripts\nInProgress - Scripts I am still working on\nNotWorking - Scripts that are broken or buggy\n[[Working]] - Finished scripts?
Used this to figure out how to properly work with hex information. Converts string to hex and back to string again. with hex information I only wanted the 2 char hex representation like A1 or FF etc. not 0xA1.\n{{{\nShouldBe = HexIt\nTestString = 4865784974\n\nOutput := HexToString(TestString)\n\nMsgBox, Output:`t`t%Output%`nShould be:`t%ShouldBe%\nHexToString(String)\n {\n local Length, CharStr, RetString\n \n ;Return '0' if the string was blank\n If !String\n Return 0\n\n Length := StrLen(String)//2\n\n ;Parse the String\n Loop, %Length%\n {\n ;Retrieve Hex\n StringMid, CharStr, String, A_Index*2 - 1, 2\n \n CharStr = 0x%CharStr%\n\n ;Build the return string\n RetString .= Chr(CharStr)\n \n }\n \n ;Return the string to the caller\n Return RetString\n }\n}}}
Idle is a program I wrote to figure out how to store a programs idle time. I had to add the keyboard hook and mouse hook because of my wireless Microsoft mouse.\n{{{\n#InstallKeybdHook\n#InstallMouseHook\nSetTimer, IdleCheck\nGui, Add, Edit, x76 y17 w130 h20,\nGui, Add, Text, x6 y17 w70 h20,Dummy\nGui, Add, Text, x6 y47 w70 h20,Current\nGui, Add, Text, x6 y77 w70 h20,Total\nGui, Add, Text, x76 y47 w130 h20 vCurrent, 0\nGui, Add, Text, x76 y77 w130 h20 vTotal, 0\nGui, Add, Button, x56 y107 w100 h30, Ok\nGui, Show, x398 y110 h148 w219, Idle Test\nReturn\n\nIdleCheck:\nGuiControlGet, Current\nif (Current > A_TimeIdlePhysical)\n{\n GuiControlGet, Total\n Updated := Total + Current\n GuiControl,,Total, %Updated%\n}\nGuiControl,,Current,%A_TimeIdlePhysical%\nReturn\n\nButtonOk:\nGuiClose:\nExitApp\n}}}
Scripts I am still working on
/***\n|Name|InlineJavascriptPlugin|\n|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|\n|Version|1.6.0|\n|Author|Eric Shulman - ELS Design Studios|\n|License|http://www.TiddlyTools.com/#LegalStatements <<br>>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|~CoreVersion|2.1|\n|Type|plugin|\n|Requires||\n|Overrides||\n|Description|Insert Javascript executable code directly into your tiddler content.|\n\n''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.\n!!!!!Usage\n<<<\nWhen installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered.\n\n''Deferred execution from an 'onClick' link''\nBy including a {{{label="..."}}} parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered. You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text\n\n''External script source files:''\nYou can also load javascript from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.\n\n''Display script source in tiddler output''\nBy including the keyword parameter "show", in the initial {{{<script>}}} marker, the plugin will include the script source code in the output that it displays in the tiddler.\n\n''Defining javascript functions and libraries:''\nAlthough the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed. Thus, you cannot load a library and //immediately// use it's functions within the same tiddler. However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).\n\nTo ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened. For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.\n\nSince the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines. Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.\n\n''Creating dynamic tiddler content''\nAn important difference between this implementation of embedded scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document:\n* In a typical web document, you use the document.write() function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.\n* However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and completely replaces the entire ~TiddlyWiki document in your browser window.\n* To allow these scripts to work unmodified, the plugin automatically converts all occurences of document.write() so that the output is inserted into the tiddler content instead of replacing the entire ~TiddlyWiki document.\n\nIf your script does not use document.write() to create dynamically embedded content within a tiddler, your javascript can, as an alternative, explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display. For example, using {{{return "thistext"}}} will produce the same output as {{{document.write("thistext")}}}.\n\n//Note: your script code is automatically 'wrapped' inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.//\n\n''Accessing the ~TiddlyWiki DOM''\nThe plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.\n\nAccess to this DOM element allows you to create scripts that can:\n* vary their actions based upon the specific location in which they are embedded\n* access 'tiddler-relative' information (use findContainingTiddler(place))\n* perform direct DOM manipulations (when returning wikified text is not enough)\n<<<\n!!!!!Examples\n<<<\nan "alert" message box:\n><script show>\n alert('InlineJavascriptPlugin: this is a demonstration message');\n</script>\ndynamic output:\n><script show>\n return (new Date()).toString();\n</script>\nwikified dynamic output:\n><script show>\n return "link to current user: [["+config.options.txtUserName+"]]";\n</script>\ndynamic output using 'place' to get size information for current tiddler:\n><script show>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\ncreating an 'onclick' button/link that runs a script:\n><script label="click here" title="clicking this link will show an 'alert' box" show>\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\nloading a script from a source url:\n>http://www.TiddlyTools.com/demo.js contains:\n>>{{{function demo() { alert('this output is from demo(), defined in demo.js') } }}}\n>>{{{alert('InlineJavascriptPlugin: demo.js has been loaded'); }}}\n><script src="demo.js" show>\n return "loading demo.js..."\n</script>\n><script label="click to execute demo() function" show>\n demo()\n</script>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2007.02.19 [1.6.0]'' added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script\n''2006.10.16 [1.5.2]'' add newline before closing '}' in 'function out_' wrapper. Fixes error caused when last line of script is a comment.\n''2006.06.01 [1.5.1]'' when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly\n''2006.04.19 [1.5.0]'' added 'show' parameter to force display of javascript source code in tiddler output\n''2006.01.05 [1.4.0]'' added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.\n''2005.12.13 [1.3.1]'' when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski\n''2005.11.09 [1.3.0]'' for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by BradleyMeck\n''2005.11.08 [1.2.0]'' handle loading of javascript from an external URL via src="..." syntax\n''2005.11.08 [1.1.0]'' pass 'place' param into scripts to provide direct DOM access \n''2005.11.08 [1.0.0]'' initial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.inlineJavascript= {major: 1, minor: 6, revision: 0, date: new Date(2007,2,19)};\n\nconfig.formatters.push( {\n name: "inlineJavascript",\n match: "\s\s<script",\n lookahead: "\s\s<script(?: src=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?(?: label=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?(?: title=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?( show)?\s\s>((?:.|\s\sn)*?)\s\s</script\s\s>",\n\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n if (lookaheadMatch[1]) { // load a script library\n // make script tag, set src, add to body to execute, then remove for cleanup\n var script = document.createElement("script"); script.src = lookaheadMatch[1];\n document.body.appendChild(script); document.body.removeChild(script);\n }\n if (lookaheadMatch[5]) { // there is script code\n if (lookaheadMatch[4]) // show inline script code in tiddler output\n wikify("{{{\sn"+lookaheadMatch[0]+"\sn}}}\sn",w.output);\n if (lookaheadMatch[2]) { // create a link to an 'onclick' script\n // add a link, define click handler, save code in link (pass 'place'), set link attributes\n var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);\n link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}\n link.code="function _out(place){"+lookaheadMatch[5]+"\sn};_out(this);"\n link.setAttribute("title",lookaheadMatch[3]?lookaheadMatch[3]:"");\n link.setAttribute("href","javascript:;");\n link.style.cursor="pointer";\n }\n else { // run inline script code\n var code="function _out(place){"+lookaheadMatch[5]+"\sn};_out(w.output);"\n code=code.replace(/document.write\s(/gi,'place.innerHTML+=(');\n try { var out = eval(code); } catch(e) { out = e.description?e.description:e.toString(); }\n if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);\n }\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n} )\n//}}}
My interest include my wife, family, our pets, the outdoors, computers, programing, watching movies/TV, and sleeping. Although not necessarily in that order or any order for that matter. I enjoy searching the internet for interesting (to me) [[freeware/opensource]] programs for both new ideas and usefulness. I don't beleive in re-inventing the wheel if not necessary. I appreciate AutoHotkey for everything it stands for since I discovered it over two years ago. I discovered [[Autoit|http://www.autoitscript.com]] first then [[Kixtart|http://www.kixtart.org]] then finally AutoHotkey. It was a no brainer to switch to. I like the ability to compile scripts. This is what I disliked about most early forms of the basic programming language which I first learned. Actually [[My Computer History]] is quite varied but that is another story.
Things that interest me. If you are here then they might interest you too. At least I can help you waste more time than you already have, Enjoy.\nFYI: These are in no particular order...\n[[TiddlyWiki|http://www.tiddlywiki.com/]] - This site software.\n[[TiddlySpot|http://www.tiddlyspot.com/]] - Free TiddlyWiki hosting site.\n[[Wikipedia|http://en.wikipedia.org/]]\n----\nPeter Answers http://www.peteranswers.com/ enter the answer by starting with a period then type the answer then end the answer with a period , finish the petition to the proper length then a semicolon. then type the question and click accept.\n----\nSubservient Chicken http://www.subservientchicken.com/ you type in what you want him to do and he does it.\n----\nhttp://www.makezine.com/blog/archive/2006/11/the_open_source_1.html\nhttp://www.zoho.com/\nhttp://www.google.com/notebook\nhttp://docs.google.com/\nhttp://www.google.com/calendar\nhere is a wiki based upon tiddlywiki\nhttp://www.socialtext.com/\nhttp://us.ajax13.com/en/\nhttp://www.thinkfree.com/common/main.tfo\nhttp://dandelife.com/\nhttp://www.rememberthemilk.com/\nhttp://jott.com\nhttp://www.imified.com/\nhttp://twitter.com/
[[Downloads]]\n[[Interests]]\n[[Links]]\n----\n~~[[TiddlyWiki|http://www.tiddlywiki.com/]] <<version>>~~
<!-- Start of StatCounter Code -->\n<script type="text/javascript" language="javascript">\nvar sc_project=2391562; \nvar sc_invisible=1; \nvar sc_partition=22; \nvar sc_security="f394cc6c"; \nvar sc_text=1; \n</script>\n\n<script type="text/javascript" language="javascript" src="http://www.statcounter.com/counter/counter.js"></script><noscript><a href="http://www.statcounter.com/" target="_blank"><img src="http://c23.statcounter.com/counter.php?sc_project=2391562&java=0&security=f394cc6c&invisible=0" alt="web hit counter" border="0"></a> </noscript>
Monitor is a program I am writing to monitor what I do during the day then I can tell exactly what I did for the day when my boss or someone asks. For the most part this program is working, but I still cannot use it as some important features are missing.\nversion 2 ? [[Monitor2]]\n{{{\n;Things left to do\n;1) Fix A_IdleTime usage?\n; a) Store all idle times somehow not just last count\n; b) Possibly store active usage and then the idle time on another line...Hum...\n;2) Convert times from miliseconds to a readable time format HH:MM:SS\n;3) Extract url if in browser or total the time up for browser type\n;4) Save data when application is terminated\n\n#Persistent\nSetBatchLines, 75ms\nProcess, Priority, , L\n\nSetTimer, WindowCheck\nwinx := WinActive("A")\nwinxtime := A_TickCount\nGui, Add, ListView, x6 y7 w620 h350 vWinData, Time|Idle|Title\nGui, Add, Button, x526 y357 w100 h30 , Ok\nGui, Show, x131 y91 h395 w636, Active Window Monitor\nReturn\n\nWindowCheck:\nFoundIt := "False"\nGuiControlGet, WinData\nCritical ; prevent interruption\nIf (winx != WinActive("A")) {\n WinGetTitle, wintitle, ahk_id %winx%\n Records := LV_GetCount() \n Loop %Records% ;before adding check if wintitle is unique\n {\n LV_GetText(RetrievedText, A_Index,3)\n if (RetrievedText == wintitle)\n {\n LV_GetText(SomeTime, A_Index,1)\n LV_GetText(MyIdleTime, A_Index,2) ;NOTE: idle time does not seem correct - too low for miliseconds\n LV_Modify(A_Index,Col1,SomeTime+(A_TickCount - winxtime),MyIdleTime+A_TimeIdle)\n FoundIt := "True" ;found a matching title\n break \n }\n\n }\n if (FoundIt = "False") and wintitle != "" ; didn't find a matching title\n LV_Add("",(A_TickCount - winxtime)-A_TimeIdle, A_TimeIdle, wintitle )\n winxtime := A_TickCount\n}\nwinx := WinActive("A")\nReturn\n\nButtonOk:\nGuiClose:\nExitApp\n}}}
An update or just another version? [[Monitor]]\n{{{\n;Things left to do\n;1) Fix A_IdleTime usage? (it doesn't look accurate)\n; a) Store all idle times somehow not just last count\n; b) Possibly store active usage and then the idle time on another line...Hum...\n;2) Convert times from miliseconds to a readable time format HH:MM:SS\n;3) Extract url if in browser or total the time up for browser type\n;4) Save data when application is terminated\n\n#Persistent\nSetBatchLines, 75ms\nProcess, Priority, , L\n;Global IdleTime\n;Global TotalIdleTime\n\nSetTimer, WindowCheck\nwinx := WinActive("A")\nwinxtime := A_TickCount\nGui, Add, ListView, x6 y7 w620 h350 vWinData, Start|End|Length|Idle|Title\nGui, Add, Button, x526 y357 w100 h30 , Ok\nGui, Show, x131 y91 h395 w636, Active Window Monitor\nReturn\n\nWindowCheck:\nif (IdleTime > A_TimeIdlePhysical)\n{\n TotalIdleTime := TotalIdleTime + IdleTime\n}\nIdleTime := A_TimeIdlePhysical\n\nFoundIt := "False"\nGuiControlGet, WinData\nCritical ; prevent interruption\nIf (winx != WinActive("A")) {\n WinGetTitle, wintitle, ahk_id %winx%\n Records := LV_GetCount() \n Loop %Records% ;before adding check if wintitle is unique\n {\n LV_GetText(RetrievedText, A_Index,5)\n if (RetrievedText == wintitle)\n {\n LV_GetText(StartTime, A_Index,1)\n LV_GetText(ActiveTime, A_Index,3)\n LV_GetText(MyIdleTime, A_Index,4) ;NOTE: idle time does not seem correct - too low for miliseconds\n LV_Modify(A_Index,Col1,StartTime,A_Now,ActiveTime+(A_TickCount - winxtime),MyIdleTime+TotalIdleTime)\n FoundIt := "True" ;found a matching title\n IdleTime :=0\n break \n }\n }\n if (FoundIt = "False") and wintitle != "" ; didn't find a matching title\n {\n LV_Add("",A_Now,A_Now,A_TickCount - winxtime, TotalIdleTime, wintitle )\n IdleTime :=0\n }\n winxtime := A_TickCount\n}\nwinx := WinActive("A")\nReturn\n\nFormatSeconds(NumberOfSeconds) ; Convert the specified number of seconds to hh:mm:ss format.\n{\n time = 19990101 ; *Midnight* of an arbitrary date.\n time += %NumberOfSeconds%, seconds\n FormatTime, mmss, %time%, mm:ss\n return NumberOfSeconds//3600 ":" mmss ; This method is used to support more than 24 hours worth of sections.\n}\n\nButtonOk:\nGuiClose:\nExitApp\n}}}
MultiGui was written to help me with multiple gui windows. It was not clear from the documentation exactly how to access variable from a secondary gui and this small program showed me the way.\n{{{\nMenu, FileMenu, Add, &Open Gui2..., Gui2\nMenu, FileMenu, Add, E&xit, GuiClose\nMenu, HelpMenu, Add, &About..., MenuAbout\nMenu, MyMenuBar, Add, &File, :FileMenu\nMenu, MyMenuBar, Add, &Help, :HelpMenu\nGui, Menu, MyMenuBar\nGui, Add, Button, x66 y60 w100 h30 , ClickMe\nGui, Show, h200 w300, 'GUIDemo - [1] ;start gui1\nReturn\n\nGui2:\nGui, 2:+owner1 ;gui1 owns gui2\nMenu, Gui2Menu, Add, &Close, CloseGui2\nMenu, Gui2MenuBar, Add, &File, :Gui2Menu\nGui, 2:Menu, Gui2MenuBar \nGui, 2:Add, Button, x66 y60 w100 h30 , ClickMe \nGui, 2:Show, h150 w250, GUIDemo - [2] ;start gui2\nReturn\n\nButtonClickMe:\n2ButtonClickMe: ;prefix label with gui#\nMsgBox, You clicked the button from GUIDemo - [%A_Gui%] ;indicate which gui initiated call\nReturn\n\nMenuAbout:\nMsgBox ,32, About, GuiDemo 03-06-2007, 10 ;display simple about box\nReturn\n\nCloseGui2:\nGui, 2:Destroy ;close gui2 and remove from memory\nReturn\n\nGuiClose:\nExitApp ;close gui1 and gui2 if it exists\n}}}
I been programming for quite a few years first learning basic on a [[TI99/4A|http://www.mainbyte.com/ti99/computers/ti994a.html]] then a [[Commadore64|http://www.obsoletecomputermuseum.org/c64/]] and years on an [[AppleIIe|http://applemuseum.bott.org/sections/computers/IIe.html]] before moving on to the [[AppleIIgs|http://applemuseum.bott.org/sections/computers/IIgs.html]] (man I fell for this computer and wanted it bad.) I wanted it but did not have the money to purchase it until I went into the service. I bought it right out of military basic training with the money I had saved up. my next computer was a [[Macintosh Plus]] (with a 300 baud modem) first online experience was with [[AOL]]. This is also when I took my first computer programming class "[[Pascal]]" I was the only person in the class programming on an Apple everyone else had a PC. My instructor allowed it because he used a Macintosh too. after turning in several assignments with a virus (unknowingly) I had to be told what a computer virus was and how to get rid of it. I jumped onto the PC bandwagon with my second programming class "[[C]]" buying a used 386 IBM ???? something with micro-channel architecture and [[DOS]] 5.0 (boy this was a learning curve) I quickly went to a store and bought a 486 Packard Bell ???? PC with [[Windows 3.1]]. I used the Packard Bell for quite a while, it served me well. I used it while learning "[[Visual Basic]] 3.0" and upgrading to [[Windows 95]] when it came out. I bought the version with 13 floppy diskettes for some unknown reason( which I still have somewhere in my garage for another unknown reason). After taking a computer hardware class I felt comfortable enough to build my own PC jumping into the Pentium class PC (who would have thought we could ever use up 32MB of ram).I started teaching myself [[UNIX]] (work related) then the Internet took off and I got a job building web pages learning first [[Coldfusion]] then [[ASP]] then attempting to learn [[PHP]] which I still don't know very well. I also dabbled in [[Flash]] but just briefly. This is also about the time I got [[DSL]] at home. Then 911 happened and the bottom dropped out of the DotCom boom. Then I jumped back in time and learned [[Clipper]] programming (for a job) a DOS programming application based on [[DBASE]] type stuff, which I still sort of do, Currently I am learning [[Java]] at work and [[AutoHotkey]] at home in my spare time. I no longer try to build my own computers as its cheaper to buy already built and I don't know of a build it your self laptop since moving on to laptop computers at home several years ago. If you are still reading this then you must be just as geeky as me or really bored. Hey thats all.
Scripts that are broken or buggy
Welcome, I am in the process of learning AutoHotkey. This is my personal site I am using to store/share all my scripts in the hopes that they might be useful to someone, but primarially for me to learn with out cluttering up the AutoHotkey fourms with my learning scripts. I write simple scripts usually to figure out a single task focusing in on a single command or problem. This is my own personal way of learning and retaining information. I am doing this site for myself but if it helps the AutoHotkey community then thats great too. Enjoy your stay. Hopefully you will find something of interest here.
Progress is a small program I wrote to figure out how to update a progress bars variables (primarily RANGE which for me was harder than I expected).\n{{{\nGui, Add, Progress, x6 y50 w290 h30 Range0-100 vProgressBar, 25 \nGui, Add, Button, x106 y100 w90 h30 , Update \nGui, Add, Text, x16 y10 w60 h20 , Position \nGui, Add, Edit, x76 y10 w70 h20 vPPosition , 25 \nGui, Add, Text, x156 y10 w60 h20 , Range \nGui, Add, Edit, x216 y10 w70 h20 vPRange, 100 \nGui, Show, x131 y91 h161 w309, ProgressBar Demo \nReturn \n\nButtonUpdate: \nGuiControlGet, PPosition \nGuiControlGet, PRange \nMsgBox, Position:`t%PPosition%`nRange:`t0-%PRange% \nguicontrol, +Range0-%PRange%,ProgressBar ; this works \nguicontrol,,ProgressBar, %PPosition% ; this works \nReturn \n\nGuiClose: \nExitApp\n}}}
Welcome to my personal AutoHotkey site
PMagness
My attempt to work with the stringcasecompare functionality of AutoHotkey, unfortunately it still does not quite work. I do however know there are some variables to determine the values of said functionality. "~A_StringCaseSense"\n{{{\nGui, Add, Edit, x16 y10 w190 h20 vEditOne, Sample Text\nGui, Add, Edit, x16 y40 w190 h20 vEditTwo, sample text\nGui, Add, CheckBox, x16 y70 w190 h20 +Checked vMatch, Match Case Exactly\nGui, Add, Button, x56 y100 w110 h30 , Compare\nGui, Show, x131 y91 h146 w224, StringCaseSense\nReturn\n\nButtonCompare:\nGuiControlGet, EditOne\nGuiControlGet, EditTwo\nGuiControlGet, Match\nIf Match = 1\n{\n StringCaseSense, On\n}\nElse \n{\n StringCaseSense, Off\n}\n\n;It is my understanding that a (single "=") equals statement when \n;used to compare strings, relys on the value of StringCaseSense.\n;Question: Is it possible to determine the value of StringCaseSense?\n\nIf (EditOne = EditTwo) \n{\n MsgBox, Match=%Match%`n`nFirst String`t%EditOne%`n`tMatches`nSecond String`t%EditTwo%\n}\nElse\n{\n MsgBox, Match=%Match%`n`nFirst String`t%EditOne%`n`tDoes not exactly match`nSecond String`t%EditTwo%\n}\nReturn\n\nGuiClose:\nExitApp\n}}}
a free MicroContent WikiWikiWeb created by JeremyRuston and a busy Community of independent developers. It's written in HTML, CSS and JavaScript to run on any modern browser without needing any ServerSide logic. It allows anyone to create personal SelfContained hypertext documents that can be posted to a WebServer, sent by email or kept on a USB thumb drive to make a WikiOnAStick. Because it doesn't need to be installed and configured it makes a great GuerillaWiki. This is revision 2.1.3 of TiddlyWiki, and is published under an OpenSourceLicense.
A lot of the small scripts I have written to figure things out with this program. I was looking for a line typing program and could not find one to use with my daughter. I sometimes make her write lines for punishment, she hates it and asked if she could use the computer instead. I know that the computer can cut-n-paste etc. so I said no. Well this got me thinking maybe I could find a program on the net or write my own. It turns out there is a program on the net, however this is geared towards S&M or somthing (who knew writing lines could be a kink? This has turned out to be more of a challenge (programming wise) than anything. I will probably never use this script for its intended purpose since I now feel it it easier to type than write (print). Plus the little darling could use AutoHotkey to defeat me too ;) .\n{{{\n;StringCaseSense, On\nGui +LastFound\nWinGet, GuiID, ID\nMenu, FileMenu, Add, &New..., MenuNew\nMenu, FileMenu, Add, &Open..., MenuOpen\nMenu, FileMenu, Add, &Save..., MenuHandler\nMenu, FileMenu, Add, E&xit, MenuQuit\nMenu, HelpMenu, Add, S&tats..., MenuHandler\nMenu, HelpMenu, Add, &About..., MenuHandler\nMenu, MyMenuBar, Add, &File, :FileMenu ; Attach the two sub-menus that were created above.\nMenu, MyMenuBar, Add, &Help, :HelpMenu\n\nGui, Add, Edit, x6 y40 w460 h20 -WantReturn vEditBox, \nGui, Add, Text, x6 y20 w460 h20 vLineText\nGui, Add, Progress, x6 y343 w460 h10 vProgressBar, 0\nGui, Add, ListBox, x6 y70 w460 h250 vListBox, \nGui, Add, Button, x366 y310 w100 h30 vButton +Disabled, Finished\nGui, Add, Button, x470 y40 w40 h20 Default,Ok\nGui, Add, StatusBar\nGui, Show, x131 y91 h400 w550, Type 'Em Lines\nGui, Menu, MyMenuBar\nReturn\n\n\n\nMenuHandler:\nreturn\n\nButtonOk:\nGuiControlGet, EditBox\nif EditBox = %aLine%\nGoSub, AddIt\nReturn\n\nAddIt:\nGuiControl,, ListBox , %EditBox%\nCounter += 1\nStatusText = %Counter% out of %aCount% Completed\nSB_SetText(StatusText)\nGuiControl,, ProgressBar, %Counter%\nGuiControl,, EditBox, \nReturn\n\nMenuOpen:\nFileSelectFile, FileName, 24, , Open Line Structure File, Line Structure File (*.lsf)\nIniRead, aLine, %FileName%, Structure, Line\nIniRead, aCount, %FileName%, Structure, Count\nIniRead, aMatch, %FileName%, Structure, Match\nIf aMatch = 1\n{ \n msgbox, On`tExactly %aMatch%\n StringCaseSense, On\n}\nElse \n{\n msgbox, Off`tJust Match %aMatch%\n StringCaseSense, Off\n}\n;IfEqual, Match, 0, StringCaseSense, Off\nStatusText = 0 out of %aCount% Completed\nGuiControl,, LineText, %aLine%\nguicontrol, +Range0-%aCount%,ProgressBar\nSB_SetText(StatusText)\nReturn\n\nMenuNew:\nGui, 2:+owner1\nGui, 2:Add, Text, x6 y10 w40 h20 , Line\nGui, 2:Add, Edit, x46 y10 w420 h20 vLine \nGui, 2:Add, Text, x6 y40 w40 h20 , Count\nGui, 2:Add, ComboBox, x46 y40 w80 h120 vCount, 50||75|100|150|200|300|400|500\nGui, 2:Add, CheckBox, x146 y40 w150 h20 Checked1 vMatch, Line is Case Sensitive\nGui, 2:Add, Button, x366 y40 w100 h30 , Save\nGui, 2:Show, x131 y91 h87 w479, New Line\nReturn\n\n2ButtonSave:\nFileSelectFile, FileName, S24, , Save Line Structure File, Line Structure File (*.lsf)\nGuiControlGet, Line\nGuiControlGet, Count\nGuiControlGet, Match\nIniWrite, %Line%, %FileName%, Structure, Line\nIniWrite, %Count%, %FileName%, Structure, Count\nIniWrite, %Match%, %FileName%, Structure, Match\nGui, 2:Destroy \nReturn\n\nButtonSave: \nGui, 2:Destroy\nReturn\n\nMenuQuit:\nExitApp\nreturn\n\n;disable control+v (paste) from working while typing lines\n$^v:: \nreturn\n\n;disable shift+insert (paste) from working while typing lines\n$+Insert:: \nreturn\n\n;disable all right clicking (paste) for context menus, they can allow pasting\n*RButton::\nreturn\n\nGuiClose:\nExitApp\n}}}
I don't remember exactly what I did this for but it does seem to work. I think this was attempting to figure out how to use global variables. I now know variable declaration only works inside functions.\n{{{\nVar1 = 100\nMsgBox, Var1 = %Var1%`nVar2 = %Var2%\nX := VariableTest(Var1)\nMsgBox , Var1 = %Var1%`nVar2 = %Var2%`nVariableTest = %X%\nExitApp\n\nVariableTest(Var1)\n{\nGlobal Var2 = 10\nMsgBox, Var1 = %Var1%`nVar2 = %Var2%\nReturn Var1 + Var2\n}\n}}}
Finished scripts?
/***\n|''Name:''|YourSearchPlugin|\n|''Version:''|2.0.2 (2006-02-13)|\n|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|2.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n<<tiddler [[YourSearch Introduction]]>>\nFor more information see [[Help|YourSearch Help]].\n\n!Compatibility\nThis plugin requires TiddlyWiki 2.0. \nUse http://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1 for older TiddlyWiki versions.\n\n!Revision history\n* v2.0.2 (2006-02-13)\n** Bugfix for Firefox 1.5.0.1 related to the "Show prefix" checkbox. Thanks to Ted Pavlic for reporting and to BramChen for fixing. \n** Internal\n*** Make "JSLint" conform\n* v2.0.1 (2006-02-05)\n** Support "Exact Word Match" (use '=' to prefix word)\n** Support default filter settings (when no filter flags are given in search term)\n** Rework on the "less than 3 chars search text" feature (thanks to EricShulman)\n** Better support SinglePageMode when doing "Open all tiddlers" (thanks to EricShulman)\n** Support Firefox 1.5.0.1\n** Bug: Fixed a hilite bug in "classic search mode" (thanks to EricShulman)\n* v2.0.0 (2006-01-16)\n** Add User Interface\n* v1.0.1 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.0 (2005-12-28)\n** initial version\n/%\n***/\n//{{{\n//============================================================================\n//============================================================================\n// YourSearchPlugin\n//============================================================================\n//============================================================================\n\n// Ensure that the Plugin is only installed once.\n//\nif (!version.extensions.YourSearchPlugin) {\n\nversion.extensions.YourSearchPlugin = {\n major: 2, minor: 0, revision: 2,\n date: new Date(2006, 2, 13), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#YourSearchPlugin"\n};\n\nvar alertAndThrow = function(msg) {alert(msg);throw msg;};\n\nif (!window.abego) window.abego = {};\nif (abego.YourSearch) alertAndThrow("abego.YourSearch already defined");\nabego.YourSearch = {};\n\nif (version.major < 2) alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.0 or newer.\sn\snGet YourSearch 1.0.1 to use YourSearch with older versions of TiddlyWiki.\sn\snhttp://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1");\n\n//----------------------------------------------------------------------------\n// The STQ (SimpleTiddlerQuery) Class\n//----------------------------------------------------------------------------\n\n// Internal.\n// \nvar STQ = function(queryText, caseSensitive, matchTitleOnly, useRegExp) {\n this.queryText = queryText;\n this.caseSensitive = caseSensitive;\n\n if (useRegExp) {\n this.regExp = new RegExp(queryText, caseSensitive ? "mg" : "img");\n return;\n }\n \n this.terms = [];\n\n // The regular expression that matches a single search term of the form\n // (whitespace handling and grouping omitted for clarity):\n //\n // -?[#!%]*(<doubleQuoteStringLiteral>|<wordWithoutSpace>) (AND|OR)?\n //\n // group 1: '-' (negate, optional)\n // group 2: [!%#]* (may be empty)\n // group 3: String literal "..."\n // group 4: word\n // group 5: AND / OR (optional) \n //\n // (group 3 xor group 4 is defined)\n //\n var re = /\ss*(\s-)?([#%!=]*)(?:(?:("(?:(?:\s\s")|[^"])*")|(\sS+)))(?:\ss+((?:[aA][nN][dD])|(?:[oO][rR]))(?!\sS))?/mg;\n\n var matches = re.exec(queryText);\n\n while (matches != null && matches.length == 6) {\n var negate = '-' == matches[1];\n var flags = matches[2];\n var inTitle = flags.indexOf('!') >= 0;\n var inText = flags.indexOf('%') >= 0;\n var inTag = flags.indexOf('#') >= 0;\n var wordMatch = flags.indexOf('=') >= 0;\n if (!inTitle && !inText && !inTag) {\n inTitle = config.options.chkSearchInTitle;\n inText = config.options.chkSearchInText;\n inTag = config.options.chkSearchInTags;\n \n // If all settings are off (i.e. all results would be empty, \n // i.e user error or checkboxes are gone) set all settings\n if (!inTitle && !inText && !inTag) {\n inTitle = inText = inTag = true;\n }\n }\n if (matchTitleOnly) {\n inText = false;\n inTag = false;\n }\n \n var text;\n if (matches[3]) {\n //Quoted String\n try {\n text = eval(matches[3]);\n } catch (ex) {\n // ignore error. Will be handled right after this.\n }\n } else {\n text = matches[4];\n }\n if (!text) {\n throw "Invalid search expression: %0".format([queryText]);\n }\n var orFollows = matches[5] && matches[5].charAt(0).toLowerCase() == 'o';\n this.terms.push(new STQ.Term(text, inTitle, inText, inTag, negate, orFollows, caseSensitive, wordMatch));\n \n matches = re.exec(queryText);\n }\n};\n\nvar me = STQ.prototype;\n\n// Internal.\n// \n// Returns an array with those tiddlers from the tiddlersMap that \n// match the query.\n//\nme.getMatchingTiddlers = function(tiddlersMap) {\n var result = [];\n for (var i in tiddlersMap) {\n var t = tiddlersMap[i];\n if ((t instanceof Tiddler) && this.matchesTiddler(t)) {\n result.push(t);\n }\n }\n return result;\n};\n\n\n// Internal.\n// \n// Returns true if the query has a match in the given tiddler.\n//\n// @param tiddler [may be null]\n//\nme.matchesTiddler = function(tiddler) {\n if (this.regExp) {\n return this.regExp.test(tiddler.title) || this.regExp.test(tiddler.text);\n }\n \n var n = this.terms.length;\n if (n == 0) {\n return false;\n }\n \n var hasMatch = this.terms[0].matchesTiddler(tiddler);\n for (var i = 1; i < this.terms.length; i++) {\n if (this.terms[i-1].orFollows) {\n // the OR case.\n \n // shortcut: when the first operand of an OR is true \n // we don't need to evaluate the second operand since \n // the result of the OR will always be true.\n \n // In the other case we actually to the "OR"\n if (!hasMatch) {\n hasMatch |= this.terms[i].matchesTiddler(tiddler);\n }\n } else {\n // the AND case.\n \n // shortcut: when the first operand of an AND is false \n // we don't need to evaluate the second operand since\n // the result of the AND will always be false.\n \n // Otherwise we actually to the "AND"\n if (hasMatch) {\n hasMatch &= this.terms[i].matchesTiddler(tiddler);\n }\n }\n }\n return hasMatch;\n};\n\n// Internal.\n// \nme.getOnlyMatchTitleQuery = function() {\n if (!this.onlyMatchTitleQuery) {\n this.onlyMatchTitleQuery = new STQ(this.queryText, this.caseSensitive, true, this.useRegExp);\n }\n return this.onlyMatchTitleQuery;\n};\n\n\n// Returns a regular expression that can be used to marking/hiliting\n// matches in the text.\n//\n// @return [may be null] null when the query does not provide marking information.\n//\nme.getMarkRegExp = function() {\n if (this.regExp) {\n // Only use the regExp for marking when it does not match the empty string.\n return "".search(this.regExp) >= 0 ? null : this.regExp;\n }\n \n var stringSet = {};\n var n = this.terms.length;\n for (var i = 0; i < this.terms.length; i++) {\n var term = this.terms[i];\n if (!term.negate) stringSet[term.text] = true;\n }\n\n var pattern = [];\n for (var t in stringSet) pattern.push("(" + t.escapeRegExp() + ")");\n \n if (pattern.length == 0) return null;\n\n var joinedPattern = pattern.join("|");\n return new RegExp(joinedPattern, this.caseSensitive ? "mg" : "img");\n};\n\n// Internal.\n// \nme.toString = function() {\n if (this.regExp) {\n return this.regExp.toString();\n }\n \n var result = "";\n for (var i = 0; i < this.terms.length; i++) {\n result += this.terms[i].toString();\n }\n return result;\n};\n\n//----------------------------------------------------------------------------\n// The STQ.Term Class\n//----------------------------------------------------------------------------\n\n// Internal.\n//\nSTQ.Term = function(text, inTitle, inText, inTag, negate, orFollows, caseSensitive, wordMatch) {\n this.text = text;\n this.inTitle = inTitle;\n this.inText = inText;\n this.inTag = inTag;\n this.negate = negate;\n this.orFollows = orFollows;\n this.caseSensitive = caseSensitive;\n this.wordMatch = wordMatch;\n \n var reText = text.escapeRegExp();\n if (this.wordMatch) reText = "\s\sb"+reText+"\s\sb";\n this.regExp = new RegExp(reText, "m"+(caseSensitive ? "" : "i"));\n};\n\n// Internal.\n//\nSTQ.Term.prototype.toString = function() {\n return (this.negate ? "-" : "")+(this.inTitle ? "!" : "")+(this.inText? "%" : "")+(this.inTag? "#" : "")+(this.wordMatch ? "=" : "")+'"'+this.text+'"'+ (this.orFollows ? " OR " : " AND ");\n};\n\n// Internal.\n//\n// Returns true if the term has a match in the given tiddler.\n//\n// @param tiddler [may be null]\n//\nSTQ.Term.prototype.matchesTiddler = function(tiddler) {\n if (!tiddler) {\n return false;\n }\n \n if (this.inTitle && this.regExp.test(tiddler.title)) {\n return !this.negate;\n }\n if (this.inText && this.regExp.test(tiddler.text)) {\n return !this.negate;\n }\n if (this.inTag) {\n var tags = tiddler.tags;\n if (tags) {\n for (var i = 0; i < tags.length; i++) {\n if (this.regExp.test(tags[i])) {\n return !this.negate;\n }\n }\n }\n }\n \n return this.negate;\n};\n\n//----------------------------------------------------------------------------\n// Utils\n//----------------------------------------------------------------------------\n\nvar stringToInt = function(s, defaultValue) {\n if (!s) return defaultValue;\n var n = parseInt(s);\n return (n == NaN) ? defaultValue : n;\n};\n\nvar getIntAttribute = function(elem, name, defaultValue) {\n return stringToInt(elem.getAttribute(name));\n};\n\n// Returns true if e is either self or a descendant (child, grandchild,...) of self.\n//\n// @param self DOM:Element\n// @param e DOM:Element or null\n//\nvar isDescendantOrSelf = function(self, e) {\n while (e != null) {\n if (self == e) return true;\n e = e.parentNode;\n }\n return false;\n};\n\nvar getMatchCount = function(s, re) {\n var m = s.match(re);\n return m ? m.length : 0;\n};\n\nvar createEllipsis = function(place) {\n var e = createTiddlyElement(place,"span");\n e.innerHTML = "&hellip;";\n};\n\nvar isWordChar = function(c) {\n return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c == "_";\n};\n\n// Returns the bounds of the word in s around offset as a {start: , end:} object.\n//\n// Returns null when the char at offset is not a word char.\n//\nvar getWordBounds = function(s, offset) {\n // Handle the "offset is not in word" case\n if (!isWordChar(s[offset])) return null;\n\n for (var i = offset-1; i >= 0 && isWordChar(s[i]); i--) \n {/*empty*/}\n \n var startIndex = i+1;\n var n = s.length;\n for (i = offset+1; i < n && isWordChar(s[i]); i++) \n {/*empty*/}\n \n return {start: startIndex, end: i};\n};\n\n\nvar removeTextDecoration = function(s) {\n var removeThis = ["''", "{{{", "}}}", "//", "<<<", "/***", "***/"];\n var reText = "";\n for (var i = 0; i < removeThis.length; i++) {\n if (i != 0) reText += "|";\n reText += "("+removeThis[i].escapeRegExp()+")";\n }\n return s.replace(new RegExp(reText, "mg"), "").trim();\n};\n\nvar logText = "";\nvar lastLogTime = null;\nvar logMessage = function(kind, s) {\n var now = new Date();\n var delta = lastLogTime ? (now-lastLogTime).toString() : "";\n logText += "<tr><td>"+now.convertToYYYYMMDDHHMMSSMMM()+"</td><td align='right'>"+delta+"</td><td>"+kind+"</td><td>"+s.htmlEncode()+"</td></tr>\sn";\n lastLogTime = now;\n};\n\nfunction writeLog() {\n var t = " <<JsDoIt 'WriteLog' 'WriteLog' 'javascript:writeLog();story.closeTiddler(\s"Log\s");story.displayTiddler(null,\s"Log\s");'>>"+\n "<html><table><tbody><tr><th>Time</th><th>Delta (ms)</th><th>Kind</th><th>Message</th></tr>\sn" + logText + "</tbody></table></html>";\n store.saveTiddler("Log", "Log",t,config.options.txtUserName,new Date(),["System", "Log"]);\n logText = "";\n lastLogTime = null;\n}\n\n//----------------------------------------------------------------------------\n// The Search Core\n//----------------------------------------------------------------------------\n\n// Constants\n\n// DOM IDs\nvar yourSearchResultID = "yourSearchResult";\nvar yourSearchResultItemsID = "yourSearchResultItems";\n\n// Visual appearance of the result page\nvar maxCharsInTitle = 80;\nvar maxCharsInTags = 50;\nvar maxCharsInText = 250;\nvar maxPagesInNaviBar = 10; // Maximum number of pages listed in the navigation bar (before or after the current page)\n\nvar itemsPerPageDefault = 25; // Default maximum number of items on one search result page\nvar itemsPerPageWithPreviewDefault = 10; // Default maximum number of items on one search result page when PreviewText is on\n\n// Context Calculation\nvar minMatchWithContextSize = 40; \nvar maxMovementForWordCorrection = 4; // When a "match" context starts or end on a word the context borders may be changed to at most this amound to include or exclude the word.\n\n// Ranking Weights\nvar matchInTitleWeight = 4;\nvar precisionInTitleWeight = 10;\nvar matchInTagsWeight = 2;\n\n// Variables\nvar resultElement; // The (popup) DOM element containing the search result [may be null]\nvar lastResults; // Array of tiddlers that matched the last search\nvar lastQuery; // The last Search query (STQ)\nvar lastSearchText; // The last search text, as used to create the lastQuery\nvar searchInputField; // The "search" input field\nvar searchButton; // The "search" button\nvar firstIndexOnPage = 0; // The index of the first item of the lastResults list displayed on the search result page\n\nvar currentTiddler; // While creating the search result page the tiddler that is currently rendered.\nvar indexInPage; // The index (in the current page) of the tiddler currently rendered.\nvar indexInResult; // The index (in the result array) of the tiddler currently rendered.\n\n\nvar getItemsPerPage = function() {\n var n = (config.options.chkPreviewText) \n ? stringToInt(config.options.txtItemsPerPageWithPreview, itemsPerPageWithPreviewDefault) \n : stringToInt(config.options.txtItemsPerPage, itemsPerPageDefault);\n return (n > 0) ? n : 1;\n};\n\nvar standardRankFunction = function(tiddler, query) { \n // Count the matches in the title and the tags\n var markRE = query.getMarkRegExp();\n if (!markRE) return 1;\n \n var matchesInTitle = tiddler.title.match(markRE);\n var nMatchesInTitle = matchesInTitle ? matchesInTitle.length : 0;\n var nMatchesInTags = getMatchCount(tiddler.getTags(), markRE);\n\n // Calculate the "precision" of the matches in the title as the ratio of\n // the length of the matches to the total length of the title.\n var lengthOfMatchesInTitle = matchesInTitle ? matchesInTitle.join("").length : 0;\n var precisionInTitle = tiddler.title.length > 0 ? lengthOfMatchesInTitle/tiddler.title.length : 0;\n \n // calculate a weighted score\n var rank= nMatchesInTitle * matchInTitleWeight \n + nMatchesInTags * matchInTagsWeight \n + precisionInTitle * precisionInTitleWeight \n + 1;\n\n return rank;\n};\n\n// @return Tiddler[]\n//\nvar findMatches = function(store, searchText,caseSensitive,useRegExp,sortField,excludeTag) {\n lastSearchText = searchText;\n\n var candidates = store.reverseLookup("tags",excludeTag,false);\n var query = new STQ(searchText,caseSensitive, false, useRegExp); \n lastQuery = query;\n\n var results = query.getMatchingTiddlers(candidates);\n\n // Rank the results\n var rankFunction = abego.YourSearch.getRankFunction();\n for (var i = 0; i < results.length; i++) {\n var tiddler = results[i];\n var rank = rankFunction(tiddler, query);\n // Add the rank information to the tiddler.\n // This is used during the sorting, but it may also\n // be used in the result, e.g. to display some "relevance" \n // information in the result \n tiddler.searchRank = rank; \n }\n \n // sort the result, taking care of the rank and the sortField \n if(!sortField) {\n sortField = "title";\n }\n \n var sortFunction = function (a,b) {\n var searchRankDiff = a.searchRank - b.searchRank;\n if (searchRankDiff == 0) {\n if (a[sortField] == b[sortField]) {\n return(0); \n } else {\n return (a[sortField] < b[sortField]) ? -1 : +1; \n }\n } else {\n return (searchRankDiff > 0) ? -1 : +1; \n }\n };\n results.sort(sortFunction);\n \n lastResults = results;\n \n return results;\n};\n\n\n//----------------------------------------------------------------------------\n// Handling "limited marked text" in the preview\n//\n// The found/matched texts should be displayed to the user in the preview. To make \n// it more useful the matched texts should be shown in their contexts, i.e. with\n// some text around them. Since we only have limited space for the preview \n// (around two lines for the text preview, less for the tags and title) and \n// also don't want to both the user with "too much context" we use some \n// heuristics to find the "best context (size)". \n//\n// On the other hand we want to use as much as possible of the preview area, \n// so if there is room left we also display as much text from the beginning\n// of the text as possible. This gives the user some kind of "overall context"\n// especiallay if the start of the text is introductorily.\n//\n// Text Ranges\n//\n// To represent the ranges that should be displayed "Range" object are used.\n// This are objects with a "start" and "end" property. In a corresponding\n// "Ranges array" these objects are sorted by their start and no range object \n// intersects/touches any other of the array.\n//\n//----------------------------------------------------------------------------\n\nvar moveToWordBorder = function(s, offset, isStartOffset) {\n var wordBounds;\n if (isStartOffset) {\n wordBounds = getWordBounds(s, offset);\n } else {\n if (offset <= 0) return offset;\n wordBounds = getWordBounds(s, offset-1);\n }\n if (!wordBounds) return offset;\n \n if (isStartOffset) {\n if (wordBounds.start >= offset-maxMovementForWordCorrection) return wordBounds.start;\n if (wordBounds.end <= offset+maxMovementForWordCorrection) return wordBounds.end;\n } else {\n if (wordBounds.end <= offset+maxMovementForWordCorrection) return wordBounds.end;\n if (wordBounds.start >= offset-maxMovementForWordCorrection) return wordBounds.start;\n }\n return offset;\n};\n\nvar getContextRangeAround = function(s, startIndex, endIndex, matchCount, maxLen) {\n // Partition the available space into equal sized areas for each match and one \n // for the text start.\n // But the size should not go below a certain limit\n var size = Math.max(Math.floor(maxLen/(matchCount+1)), minMatchWithContextSize);\n \n // Substract the size of the range to get the size of the context.\n var contextSize = Math.max(size-(endIndex-startIndex), 0);\n // Two thirds of the context should be before the match, one third after.\n var contextEnd = Math.min(Math.floor(endIndex+contextSize/3), s.length);\n var contextStart = Math.max(contextEnd - size, 0);\n\n // If the contextStart/End is inside a word and the end of the word is\n // close move the pointers accordingly to make the text more readable.\n contextStart = moveToWordBorder(s, contextStart, true);\n contextEnd = moveToWordBorder(s, contextEnd, false);\n \n return {start: contextStart, end: contextEnd};\n};\n\n// Splits s into a sequence of "matched" and "unmatched" substrings, using the \n// matchRegExp to do the matching.\n// \n// Returns an array of objects with a "text" property containing the substring text. \n// Substrings that are "matches" also contain a boolean "isMatch" property set to true.\n// \n// @param matchRegExp [may be null] when null no matching is performed and the returned \n// array just contains one item with s as its text\n// \nvar getTextAndMatchArray = function(s, matchRegExp) {\n var result = [];\n if (matchRegExp) {\n var startIndex = 0;\n var n = s.length;\n var currentLen = 0;\n do {\n matchRegExp.lastIndex = startIndex;\n var match = matchRegExp.exec(s);\n if (match) {\n if (startIndex < match.index) {\n var t = s.substring(startIndex, match.index);\n result.push({text:t});\n }\n result.push({text:match[0], isMatch:true});\n startIndex = match.index + match[0].length;\n } else {\n result.push({text: s.substr(startIndex)});\n break;\n }\n } while (true);\n } else {\n result.push({text: s});\n }\n return result;\n};\n\n\nvar simpleCreateLimitedTextWithMarks = function(place, s, maxLen) {\n if (!lastQuery) return;\n \n var textAndMatches = getTextAndMatchArray(s, lastQuery.getMarkRegExp());\n var currentLen = 0;\n for (var i=0; i < textAndMatches.length && currentLen < maxLen; i++) {\n var t = textAndMatches[i];\n var text = t.text;\n if (t.isMatch) {\n createTiddlyElement(place,"span",null,"marked",text); \n } else {\n var remainingLen = maxLen-currentLen;\n if (remainingLen < text.length) {\n text = text.substring(0, remainingLen)+"...";\n }\n createTiddlyText(place, text);\n }\n currentLen += text.length;\n }\n};\n\n\n\nvar addRange = function(ranges, startIndex, endIndex) {\n var n = ranges.length;\n \n // When there are no ranges in ranges, just add it.\n if (n == 0) {\n ranges.push({start: startIndex, end: endIndex});\n return;\n }\n \n var i = 0;\n for (; i < n; i++) {\n var range = ranges[i];\n \n // find the first range that intersects or "touches" [startIndex, endIndex[\n if (range.start <= endIndex && startIndex <= range.end) {\n // Found.\n \n var r;\n // find the first range behind the new range that does not interfere\n var rIndex = i+1;\n for (; rIndex < n; rIndex++) {\n r = ranges[rIndex];\n if (r.start > endIndex || startIndex > range.end) {\n break;\n }\n }\n \n // Replace the ranges i to rIndex-1 with the union of the new range with these ranges.\n var unionStart = startIndex;\n var unionEnd = endIndex;\n for (var j = i; j < rIndex; j++) {\n r = ranges[j];\n unionStart = Math.min(unionStart, r.start);\n unionEnd = Math.max(unionEnd, r.end);\n }\n ranges.splice(i, rIndex-i, {start: unionStart, end: unionEnd});\n return; \n }\n \n // if we found a range R that is right of the new range there is no\n // intersection and we can insert the new range before R.\n if (range.start > endIndex) {\n break;\n }\n }\n\n // When we are here the new range does not interfere with any range in ranges and\n // i is the index of the first range right to it (or ranges.length, when the new range\n // becomes the right most range). \n\n ranges.splice(i, 0, {start: startIndex, end: endIndex});\n};\n\nvar getTotalRangesSize = function(ranges) {\n var totalRangeSize = 0;\n for (var i=0; i < ranges.length; i++) {\n var range = ranges[i];\n totalRangeSize += range.end-range.start;\n }\n return totalRangeSize;\n};\n\n// Processes the text between startIndex and endIndex of the textAndMatches\n// "writes" them (as DOM elements) at the given place, possibly as "marked" text.\n//\n// When endIndex is not the end of the full text an ellisis is appended. \n//\nvar writeTextAndMatchRange = function(place, s, textAndMatches, startIndex, endIndex) {\n var t;\n var text;\n \n // find the first text item to write\n var pos = 0;\n var i = 0;\n var offset = 0;\n for (;i < textAndMatches.length; i++) {\n t = textAndMatches[i];\n text = t.text;\n if (startIndex < pos+text.length) {\n offset = startIndex - pos;\n break;\n }\n pos += text.length;\n }\n \n var remainingLen = endIndex - startIndex;\n for (; i < textAndMatches.length && remainingLen > 0; i++) {\n t = textAndMatches[i];\n text = t.text.substr(offset);\n offset = 0;\n if (text.length > remainingLen) text = text.substr(0,remainingLen);\n \n if (t.isMatch) {\n createTiddlyElement(place,"span",null,"marked",text);\n } else {\n createTiddlyText(place, text);\n }\n remainingLen -= text.length;\n }\n \n if (endIndex < s.length) {\n createEllipsis(place);\n }\n};\n\nvar getMatchedTextCount = function(textAndMatches) {\n var result = 0;\n for (var i=0; i < textAndMatches.length; i++) {\n if (textAndMatches[i].isMatch) {\n result++;\n }\n }\n return result; \n};\n\n// Get all ranges around matched substrings with their contexts\n//\nvar getMatchedTextWithContextRanges = function(textAndMatches, s, maxLen) {\n var ranges = [];\n var matchCount = getMatchedTextCount(textAndMatches);\n var pos = 0;\n for (var i=0; i < textAndMatches.length; i++) {\n var t = textAndMatches[i];\n var text = t.text;\n if (t.isMatch) {\n var range = getContextRangeAround(s, pos, pos+text.length, matchCount, maxLen);\n addRange(ranges, range.start, range.end);\n }\n pos += text.length;\n }\n return ranges;\n};\n\nvar fillUpRanges = function(s, ranges, maxLen) {\n var remainingLen = maxLen - getTotalRangesSize(ranges);\n while (remainingLen > 0) {\n if (ranges.length == 0) {\n // No matches added yet. Make one large range.\n addRange(ranges, 0, moveToWordBorder(s, maxLen, false));\n return;\n } else {\n var range = ranges[0];\n var startIndex;\n var maxEndIndex;\n if (range.start == 0) {\n // The first range already starts at the beginning of the string.\n\n // When there is a second range fill to the next range start or to the maxLen.\n startIndex = range.end;\n if (ranges.length > 1) {\n maxEndIndex = ranges[1].start;\n } else {\n // Only one range. Add a range after that with the complete remaining len \n // (corrected to "beautify" the output)\n addRange(ranges, startIndex, moveToWordBorder(s, startIndex+remainingLen, false));\n return;\n }\n } else {\n // There is unused space between the start of the text and the first range.\n startIndex = 0;\n maxEndIndex = range.start;\n }\n var endIndex = Math.min(maxEndIndex, startIndex+remainingLen);\n addRange(ranges, startIndex, endIndex);\n remainingLen -= (endIndex-startIndex);\n }\n }\n};\n\n// Write the given ranges of s, using textAndMatches for marking portions of the text.\n//\nvar writeRanges = function(place, s, textAndMatches, ranges, maxLen) {\n if (ranges.length == 0) return;\n \n // When the first range is not at the start of the text write an ellipsis("...")\n // (Ellipses between ranges are written in the writeTextAndMatchRange method)\n if (ranges[0].start > 0) createEllipsis(place);\n\n var remainingLen = maxLen;\n for (var i = 0; i < ranges.length && remainingLen > 0; i++) {\n var range = ranges[i];\n var len = Math.min(range.end - range.start, remainingLen);\n writeTextAndMatchRange(place, s, textAndMatches, range.start, range.start+len);\n remainingLen -= len;\n }\n};\n\nvar createLimitedTextWithMarksAndContext = function(place, s, maxLen) {\n if (!lastQuery) return;\n \n if (s.length < maxLen) maxLen = s.length;\n \n var textAndMatches = getTextAndMatchArray(s, lastQuery.getMarkRegExp());\n \n var ranges = getMatchedTextWithContextRanges(textAndMatches, s, maxLen);\n \n // When the maxLen is not yet reached add more ranges \n // starting from the beginning until either maxLen or \n // the end of the string is reached.\n fillUpRanges(s, ranges, maxLen);\n\n writeRanges(place, s, textAndMatches, ranges, maxLen);\n};\n\nvar createLimitedTextWithMarks = function(place, s, maxLen) {\n// return simpleCreateLimitedTextWithMarks(place, s, maxLen);\n return createLimitedTextWithMarksAndContext(place, s, maxLen);\n};\n\n\n//----------------------------------------------------------------------------\n// The Search Result\n//----------------------------------------------------------------------------\n\nvar myStorySearch = function(text,useCaseSensitive,useRegExp)\n{\n highlightHack = new RegExp(useRegExp ? text:text.escapeRegExp(),useCaseSensitive ? "mg" : "img");\n var matches = findMatches(store, text,useCaseSensitive,useRegExp,"title","excludeSearch");\n\n firstIndexOnPage = 0;\n showResult();\n \n highlightHack = null;\n};\n\n\nvar myMacroSearchHandler = function(place,macroName,params)\n{\n var lastSearchText = "";\n var searchTimeout = null;\n var doSearch = function(txt)\n {\n if (config.options.chkUseYourSearch)\n myStorySearch(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);\n else\n story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);\n lastSearchText = txt.value;\n };\n var clickHandler = function(e)\n {\n doSearch(searchInputField);\n return false;\n };\n var keyHandler = function(e)\n {\n if (!e) var e = window.event;\n switch(e.keyCode)\n {\n case 13:\n doSearch(this);\n break;\n case 27:\n // When the result is open, close it, \n // otherwise clear the content of the input field\n if (isResultOpen()) {\n closeResult();\n } else {\n this.value = "";\n clearMessage();\n }\n break;\n }\n if (String.fromCharCode(e.keyCode) == this.accessKey || e.altKey) \n {\n reopenResultIfApplicable();\n }\n\n if(this.value.length<3 && searchTimeout) clearTimeout(searchTimeout);\n if((this.value.length > 2) && (this.value != lastSearchText))\n if (!config.options.chkUseYourSearch || config.options.chkSearchAsYouType)\n {\n if(searchTimeout)\n clearTimeout(searchTimeout);\n var txt = this;\n searchTimeout = setTimeout(function() {doSearch(txt);},500);\n }\n if (this.value.length == 0) \n {\n closeResult();\n }\n };\n\n\n var focusHandler = function(e)\n {\n this.select();\n reopenResultIfApplicable();\n };\n\n var btn = createTiddlyButton(place,this.label,this.prompt,clickHandler);\n var txt = createTiddlyElement(place,"input",null,null,null);\n if(params[0])\n txt.value = params[0];\n txt.onkeyup = keyHandler;\n txt.onfocus = focusHandler;\n txt.setAttribute("size",this.sizeTextbox);\n txt.setAttribute("accessKey",this.accessKey);\n txt.setAttribute("autocomplete","off");\n if(config.browser.isSafari)\n {\n txt.setAttribute("type","search");\n txt.setAttribute("results","5");\n }\n else\n txt.setAttribute("type","text");\n\n searchInputField = txt;\n searchButton = btn;\n};\n\nvar isResultOpen = function() {\n return resultElement != null && resultElement.parentNode == document.body;\n};\n\nvar closeResult = function() {\n if (isResultOpen()) {\n document.body.removeChild(resultElement);\n }\n};\n\n\nvar openAllFoundTiddlers = function() {\n closeResult();\n if (lastResults) {\n var titles=[];\n for(var i = 0; i<lastResults.length; i++)\n titles.push(lastResults[i].title);\n story.displayTiddlers(null,titles);\n }\n};\n\n// Refreshes the content of the result with the current search result\n// of the selected page.\n//\n// Assumes that the result is already open. \n//\nvar refreshResult = function() {\n if (!resultElement || !searchInputField) return;\n\n // Load the template for the YourSearchResult\n var html = store.getTiddlerText("YourSearchResultTemplate");\n if (!html) html = "<b>Tiddler YourSearchResultTemplate not found</b>";\n resultElement.innerHTML = html;\n\n // Ensure that the firstIndexOnPage is really a page start. \n // This may have become violated when the ItemsPerPage are changed,\n // e.g. when switching between previewText and simple mode.\n firstIndexOnPage = Math.floor(firstIndexOnPage / getItemsPerPage()) * getItemsPerPage();\n \n // Expand the template macros etc.\n applyHtmlMacros(resultElement,null);\n refreshElements(resultElement,null);\n \n // When there are items found add them to the result page (pagewise)\n if (lastResults && lastResults.length > 0) {\n // Load the template how to display the items that represent a found tiddler\n var itemHtml = store.getTiddlerText("YourSearchItemTemplate");\n if (!itemHtml) alertAndThrow("YourSearchItemTemplate not found");\n \n // Locate the node that shall contain the list of found tiddlers\n var items = document.getElementById(yourSearchResultItemsID);\n if(!items)\n items = createTiddlyElement(resultElement,"div",yourSearchResultItemsID);\n\n // Add the items of the current page\n var endIndex = Math.min(firstIndexOnPage+getItemsPerPage(), lastResults.length);\n indexInPage = -1;\n for (var i=firstIndexOnPage; i < endIndex; i++) {\n currentTiddler = lastResults[i];\n indexInPage++;\n indexInResult = i;\n\n var item = createTiddlyElement(items,"div",null, "yourSearchItem");\n item.innerHTML = itemHtml;\n applyHtmlMacros(item,null);\n refreshElements(item,null);\n }\n }\n \n // The currentTiddler must only be defined while rendering the found tiddlers\n currentTiddler = null;\n\n ensureResultIsDisplayedNicely();\n};\n\n// Makes sure the result page has a good size and position and visible\n// (may scroll the window)\n//\nvar ensureResultIsDisplayedNicely = function() {\n adjustResultPositionAndSize();\n scrollVisible();\n};\n\nvar scrollVisible = function() {\n // Scroll the window to make the result page (and the search Input field) visible.\n if (resultElement) window.scrollTo(0,ensureVisible(resultElement));\n if (searchInputField) window.scrollTo(0,ensureVisible(searchInputField));\n};\n\n// Adjusts the resultElement's size and position, relative to the search input field.\n//\nvar adjustResultPositionAndSize = function() {\n if (!searchInputField) return;\n \n var root = searchInputField;\n \n // Position the result below the root and resize it if necessary.\n var rootLeft = findPosX(root);\n var rootTop = findPosY(root);\n var rootHeight = root.offsetHeight;\n var popupLeft = rootLeft;\n var popupTop = rootTop + rootHeight;\n\n // Make sure the result is not wider than the window\n var winWidth = findWindowWidth();\n if (winWidth < resultElement.offsetWidth) {\n resultElement.style.width = (winWidth - 100)+"px";\n winWidth = findWindowWidth();\n }\n\n // Ensure that the left and right of the result are not\n // clipped by the window. Move it to the left or right, if necessary. \n var popupWidth = resultElement.offsetWidth;\n if(popupLeft + popupWidth > winWidth)\n popupLeft = winWidth - popupWidth-30;\n if (popupLeft < 0) popupLeft = 0;\n \n // Do the actual moving\n resultElement.style.left = popupLeft + "px";\n resultElement.style.top = popupTop + "px";\n resultElement.style.display = "block";\n};\n\nvar showResult = function() {\n if (!resultElement) {\n resultElement = createTiddlyElement(document.body,"div",yourSearchResultID,"yourSearchResult");\n } else if (resultElement.parentNode != document.body) {\n document.body.appendChild(resultElement);\n }\n\n refreshResult();\n};\n\nvar reopenResultIfApplicable = function() {\n if (searchInputField == null || !config.options.chkUseYourSearch) return;\n \n if ((searchInputField.value == lastSearchText) && lastSearchText && !isResultOpen()) {\n // For speedup we check re-use the previously created resultElement, if possible.\n if (resultElement && (resultElement.parentNode != document.body)) {\n document.body.appendChild(resultElement);\n ensureResultIsDisplayedNicely();\n } else {\n showResult();\n }\n }\n};\n\nvar setFirstIndexOnPage = function(index) {\n if (!lastResults || lastResults.length == 0) return;\n\n firstIndexOnPage = Math.min(Math.max(0, index), lastResults.length-1);\n refreshResult(); \n};\n\n\nvar onDocumentClick = function(e) {\n // Close the search result page when the user clicks on the document\n // (and not into the searchInputField, on the search button or in the result)\n if (e.target == searchInputField) return; \n if (e.target == searchButton) return; \n if (resultElement && isDescendantOrSelf(resultElement, e.target)) return; \n \n closeResult();\n};\n\nvar onDocumentKeyup = function(e) {\n // Close the search result page when the user presses "ESC"\n if (e.keyCode == 27) closeResult();\n};\naddEvent(document,"click",onDocumentClick);\naddEvent(document,"keyup",onDocumentKeyup);\n\n\n//----------------------------------------------------------------------------\n// Macros\n//----------------------------------------------------------------------------\n\n// ====Macro yourSearch ================================================\n\nconfig.macros.yourSearch = {\n // Standard Properties\n label: "yourSearch",\n prompt: "Gives access to the current/last YourSearch result",\n\n funcs: {},\n \n tests: {\n "true" : function() {return true;},\n "false" : function() {return false;},\n "found" : function() {return lastResults && lastResults.length > 0;},\n "previewText" : function() {return config.options.chkPreviewText;}\n }\n};\n\nconfig.macros.yourSearch.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length == 0) return;\n\n var name = params[0];\n var func = config.macros.yourSearch.funcs[name];\n if (func) func(place,macroName,params,wikifier,paramString,tiddler);\n};\n\nconfig.macros.yourSearch.funcs.itemRange = function(place) {\n if (lastResults) {\n var endIndex = Math.min(firstIndexOnPage+getItemsPerPage(), lastResults.length);\n var s = "%0 - %1".format([firstIndexOnPage+1,endIndex]);\n createTiddlyText(place, s);\n }\n};\n\nconfig.macros.yourSearch.funcs.count = function(place) {\n if (lastSearchText) {\n createTiddlyText(place, lastResults.length.toString());\n }\n};\n\nconfig.macros.yourSearch.funcs.query = function(place) {\n if (lastResults) {\n createTiddlyText(place, lastSearchText);\n }\n};\n\nconfig.macros.yourSearch.funcs.version = function(place) {\n var t = "YourSearch %0.%1.%2".format(\n [version.extensions.YourSearchPlugin.major, \n version.extensions.YourSearchPlugin.minor, \n version.extensions.YourSearchPlugin.revision]);\n var e = createTiddlyElement(place, "a");\n e.setAttribute("href", "http://tiddlywiki.abego-software.de/#YourSearchPlugin");\n e.innerHTML = '<font color="black" face="Arial, Helvetica, sans-serif">'+t+'<font>';\n};\n\nconfig.macros.yourSearch.funcs.copyright = function(place) {\n var e = createTiddlyElement(place, "a");\n //e.setAttribute("href", "http://tiddlywiki.abego-software.de");\n //e.innerHTML = '<font color="black" face="Arial, Helvetica, sans-serif">&copy; 2005-2006 <b><font color="red">abego</font></b> Software<font>';\n};\n\n\nconfig.macros.yourSearch.funcs.linkButton = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params < 2) return;\n \n var tiddlyLink = params[1];\n var text = params < 3 ? tiddlyLink : params[2];\n var tooltip = params < 4 ? text : params[3];\n var accessKey = params < 5 ? null : params[4];\n \n var btn = createTiddlyButton(place,text,tooltip,closeResultAndDisplayTiddler,null,null, accessKey);\n btn.setAttribute("tiddlyLink",tiddlyLink);\n};\n\nconfig.macros.yourSearch.funcs.closeButton = function(place,macroName,params,wikifier,paramString,tiddler) {\n var button = createTiddlyButton(place, "close", "Close the Search Results (Shortcut: ESC)", closeResult);\n};\n\nconfig.macros.yourSearch.funcs.openAllButton = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!lastResults) return;\n var n = lastResults.length;\n if (n == 0) return;\n\n var title = n == 1 ? "open tiddler" : "open all %0 tiddlers".format([n]);\n var button = createTiddlyButton(place, title, "Open all found tiddlers (Shortcut: Alt-O)", openAllFoundTiddlers);\n button.setAttribute("accessKey","O");\n};\n\nvar onNaviButtonClick = function(e) {\n if (!e) var e = window.event;\n var pageIndex = getIntAttribute(this, "page");\n setFirstIndexOnPage(pageIndex * getItemsPerPage(), 0);\n};\n\nconfig.macros.yourSearch.funcs.naviBar = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!lastResults || lastResults.length == 0) return;\n\n var button;\n var currentPageIndex = Math.floor(firstIndexOnPage / getItemsPerPage());\n var lastPageIndex = Math.floor((lastResults.length-1) / getItemsPerPage());\n if (currentPageIndex > 0) {\n button = createTiddlyButton(place, "Previous", "Go to previous page (Shortcut: Alt-'<')", onNaviButtonClick, "prev");\n button.setAttribute("page",(currentPageIndex-1).toString());\n button.setAttribute("accessKey","<");\n }\n\n for (var i = -maxPagesInNaviBar; i < maxPagesInNaviBar; i++) {\n var pageIndex = currentPageIndex+i;\n if (pageIndex < 0) continue;\n if (pageIndex > lastPageIndex) break;\n\n var pageNo = (i+currentPageIndex+1).toString();\n var buttonClass = pageIndex == currentPageIndex ? "currentPage" : "otherPage";\n button = createTiddlyButton(place, pageNo, "Go to page %0".format([pageNo]), onNaviButtonClick, buttonClass);\n button.setAttribute("page",(pageIndex).toString());\n }\n \n if (currentPageIndex < lastPageIndex) {\n button = createTiddlyButton(place, "Next", "Go to next page (Shortcut: Alt-'>')", onNaviButtonClick, "next");\n button.setAttribute("page",(currentPageIndex+1).toString());\n button.setAttribute("accessKey",">");\n }\n};\n\n\nconfig.macros.yourSearch.funcs["if"] = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length < 2) return;\n \n var testName = params[1];\n var negate = (testName == "not");\n if (negate) {\n if (params.length < 3) return;\n testName = params[2];\n }\n \n var test = config.macros.yourSearch.tests[testName];\n var showIt = false;\n try {\n if (test) {\n showIt = test(place,macroName,params,wikifier,paramString,tiddler) != negate;\n } else {\n // When no predefined test is specified try to evaluate it as a JavaScript expression.\n showIt = (!eval(testName)) == negate;\n }\n } catch (ex) {\n }\n \n if (!showIt) {\n place.style.display="none";\n }\n};\n\nvar createOptionWithRefresh = function(place, optionParams, wikifier,tiddler) {\n invokeMacro(place,"option",optionParams,wikifier,tiddler);\n // The option macro appended the component at the end of the place.\n var elem = place.lastChild;\n var oldOnClick = elem.onclick;\n elem.onclick = function(e) {\n var result = oldOnClick.apply(this, arguments);\n refreshResult();\n return result;\n };\n return elem;\n};\n\nconfig.macros.yourSearch.funcs.chkPreviewText = function(place,macroName,params,wikifier,paramString,tiddler) {\n var optionParams = params.slice(1).join(" ");\n \n var elem = createOptionWithRefresh(place, "chkPreviewText", wikifier,tiddler);\n elem.setAttribute("accessKey", "P");\n elem.title = "Show text preview of found tiddlers (Shortcut: Alt-P)"; \n return elem;\n};\n\n// ====Macro foundTiddler ================================================\n\nconfig.macros.foundTiddler = {\n // Standard Properties\n label: "foundTiddler",\n prompt: "Provides information on the tiddler currently processed on the YourSearch result page",\n \n funcs: {}\n};\n\n\nconfig.macros.foundTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n var name = params[0];\n var func = config.macros.foundTiddler.funcs[name];\n if (func) func(place,macroName,params,wikifier,paramString,tiddler);\n};\n\n// Closes the Search Result window and displays the tiddler \n// defined by the "tiddlyLink" attribute of this element\n//\nvar closeResultAndDisplayTiddler = function(e)\n{\n closeResult();\n \n var title = this.getAttribute("tiddlyLink");\n if(title) {\n var withHilite = this.getAttribute("withHilite");\n var oldHighlightHack = highlightHack;\n if (withHilite && withHilite=="true" && lastQuery) {\n highlightHack = lastQuery.getMarkRegExp();\n }\n story.displayTiddler(this,title);\n highlightHack = oldHighlightHack;\n }\n return(false);\n};\n\n// Returns the "shortcut number" of the currentTiddler. \n// I.e. When the user presses Alt-n the given tiddler is opened/display.\n//\n// @return 0-9 or -1 when no number is defined\n//\nvar getShortCutNumber = function() {\n if (!currentTiddler) return -1;\n \n if (indexInPage >= 0 && indexInPage <= 9) {\n return indexInPage < 9 ? (indexInPage+1) : 0;\n } else {\n return -1;\n }\n};\n\nconfig.macros.foundTiddler.funcs.title = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n \n var shortcutNumber = getShortCutNumber();\n var tooltip = shortcutNumber >= 0 \n ? "Open tiddler (Shortcut: Alt-%0)".format([shortcutNumber.toString()])\n : "Open tiddler";\n\n var btn = createTiddlyButton(place,null,tooltip,closeResultAndDisplayTiddler,null);\n btn.setAttribute("tiddlyLink",currentTiddler.title);\n btn.setAttribute("withHilite","true");\n \n createLimitedTextWithMarks(btn, currentTiddler.title, maxCharsInTitle);\n\n if (shortcutNumber >= 0) {\n btn.setAttribute("accessKey",shortcutNumber.toString());\n }\n};\n\nconfig.macros.foundTiddler.funcs.tags = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n\n createLimitedTextWithMarks(place, currentTiddler.getTags(), maxCharsInTags);\n};\n\nconfig.macros.foundTiddler.funcs.text = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n\n createLimitedTextWithMarks(place, removeTextDecoration(currentTiddler.text), maxCharsInText);\n};\n\n\n// Renders the "shortcut number" of the current tiddler, to indicate to the user\n// what number to "Alt-press" to open the tiddler.\n//\nconfig.macros.foundTiddler.funcs.number = function(place,macroName,params,wikifier,paramString,tiddler) {\n var numberToDisplay = getShortCutNumber();\n if (numberToDisplay >= 0) {\n var text = "%0)".format([numberToDisplay.toString()]);\n createTiddlyElement(place,"span",null,"shortcutNumber",text);\n }\n};\n\nfunction scrollToAnchor(name) {\n return false;\n}\n//----------------------------------------------------------------------------\n// Configuration Stuff\n//----------------------------------------------------------------------------\n\nif (config.options.chkUseYourSearch == undefined) config.options.chkUseYourSearch = true;\nif (config.options.chkPreviewText == undefined) config.options.chkPreviewText = true;\nif (config.options.chkSearchAsYouType == undefined) config.options.chkSearchAsYouType=true;\nif (config.options.chkSearchInTitle == undefined) config.options.chkSearchInTitle=true;\nif (config.options.chkSearchInText == undefined) config.options.chkSearchInText=true;\nif (config.options.chkSearchInTags == undefined) config.options.chkSearchInTags=true;\nif (config.options.txtItemsPerPage == undefined) config.options.txtItemsPerPage =itemsPerPageDefault;\nif (config.options.txtItemsPerPageWithPreview == undefined) config.options.txtItemsPerPageWithPreview=itemsPerPageWithPreviewDefault;\n\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]])//";\n\n//----------------------------------------------------------------------------\n// Shadow Tiddlers\n//----------------------------------------------------------------------------\n\nconfig.shadowTiddlers["YourSearch Introduction"] = \n "!About YourSearch\sn"+\n "\sn"+\n "YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!\sn"+\n "\sn"+\n "''May the '~Alt-F' be with you.''\sn"+\n "\sn"+\n "\sn"+\n "!Features\sn"+\n "* YourSearch searches for tiddlers that match your query ''as you type'' into the 'search' field. It presents a list of the ''\s"Top Ten\s"'' tiddlers in a ''popup-like window'': the ''[[YourSearch Result]]''. The tiddlers currently displayed in your TiddlyWiki are not affected.\sn"+\n "* Using ''~TiddlerRank technology'' the [[YourSearch Result]] lists the ''most interesting tiddlers first''.\sn"+\n "* Through ''Filtered Search'' and ''Boolean Search'' you can easily refining your search, like excluding words or searching for multiple words. This way less tiddlers are displayed in the [[YourSearch Result]] and you can faster scan the result for the tiddler you are looking for.\sn"+\n "* The [[YourSearch Result]] lists the found tiddlers ''page-wise'', e.g. 10 per page. Use the ''Result Page Navigation Bar'' to navigate between pages if the result does not fit on one page.\sn"+\n "* The [[YourSearch Result]] states the ''total number of found tiddlers''. This way you can quickly decide if you want to browse the result list or if you want to refine your search first to shorten the result list.\sn"+\n "* Beside the ''title of the found tiddlers'' the [[YourSearch Result]] also ''displays tags'' and ''tiddler text previews''. The ''tiddler text preview'' is an extract of the tiddler's content, showing the most interesting parts related to your query (e.g. the texts around the words you are looking for).\sn"+\n "* The words you are looking for are hilited in the titles, tags and text previews of the [[YourSearch Result]].\sn"+\n "* If you are not interested in the tiddler text previews but prefer to get longer lists of tiddlers on one result page you may ''switch of the text preview''.\sn"+\n "* If the [[YourSearch Result]] contains the tiddler you are looking for you can just ''click its title to display'' it in your TiddlyWiki. Alternatively you may also ''open all found tiddlers'' at once. \sn"+\n "* Use [[YourSearch Options]] to customize YourSearch to your needs. E.g. depending on the size of your screen you may change the number of tiddlers displayed in the [[YourSearch Result]]. In the [[YourSearch Options]] and the AdvancedOptions you may also switch off YourSearch in case you temporarily want to use the standard search.\sn"+\n "* For the most frequently actions ''access keys'' are defined so you can perform your search without using the mouse.\sn"+\n "\sn"\n ;\n\nconfig.shadowTiddlers["YourSearch Help"] = \n// "<html><a name='Top'/>"+\n// "<a href='javascript:scrollToAnchor(\s"Filtered\s");'>[Filtered Search] </a>"+\n// "<a href='#Boolean'>[Boolean Search] </a>"+\n// "<a href='#Exact'>['Exact Word' Search] </a>"+\n// "<a href='#Combined'>[Combined Search] </a>"+\n// "<a href='#Case'>[CaseSensitiveSearch and RegExpSearch] </a>"+\n// "<a href='#Access'>[Access Keys] </a>"+\n// "</html>"+\n "<<tiddler [[YourSearch Introduction]]>>"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Filtered Search<html><a name='Filtered'/></html>\sn"+\n "Using the Filtered Search you can restrict your search to certain parts of a tiddler, e.g only search the tags or only the titles.\sn"+\n "|!What you want|!What you type|!Example|\sn"+\n "|Search ''titles only''|start word with ''!''|{{{!jonny}}}|\sn"+\n "|Search ''contents only''|start word with ''%''|{{{%football}}}|\sn"+\n "|Search ''tags only''|start word with ''#''|{{{#Plugin}}}|\sn"+\n "\sn"+\n "You may use more than one filter for a word. E.g. {{{!#Plugin}}} finds tiddlers containing \s"Plugin\s" either in the title or in the tags (but does not look for \s"Plugin\s" in the content).\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Boolean Search<html><a name='Boolean'/></html>\sn"+\n "The Boolean Search is useful when searching for multiple words.\sn"+\n "|!What you want|!What you type|!Example|\sn"+\n "|''All words'' must exist|List of words|{{{jonny jeremy}}}|\sn"+\n "|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\sn"+\n "|A word ''must not exist''|Start word with ''-''|{{{-jonny}}}|\sn"+\n "\sn"+\n "''Note:'' When you specify two words, separated with a space, YourSearch finds all tiddlers that contain both words, but not necessarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need to put the words into quotes. I.e. you type: {{{\s"john brown\s"}}}.\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!'Exact Word' Search<html><a name='Exact'/></html>\sn"+\n "By default a search result all matches that 'contain' the searched text. \sn"+\n " E.g. if you search for 'Task' you will get all tiddlers containing 'Task', but also 'CompletedTask', 'TaskForce' etc.\sn"+\n "\sn"+\n "If you only want to get the tiddlers that contain 'exactly the word' you need to prefix it with a '='. E.g. typing '=Task' will the tiddlers that contain the word 'Task', ignoring words that just contain 'Task' as a substring.\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Combined Search<html><a name='Combined'/></html>\sn"+\n "You are free to combine the various search options. \sn"+\n "\sn"+\n "''Examples''\sn"+\n "|!What you type|!Result|\sn"+\n "|{{{!jonny !jeremy -%football}}}| all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its titles, but no {{{football}}} in content.|\sn"+\n "|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact word). Tags named 'CompletedTask', 'TaskForce' etc. are not considered.|\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!~CaseSensitiveSearch and ~RegExpSearch<html><a name='Case'/></html>\sn"+\n "The standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearch. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Access Keys<html><a name='Access'/></html>\sn"+\n "You are encouraged to use the access keys (also called \s"shortcut\s" keys) for the most frequently used operations. For quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\sn"+\n "\sn"+\n "|!Key|!Operation|\sn"+\n "|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search input field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the previous search result. This way you can quickly display multiple tiddlers using \s"Press {{{Alt-F}}}. Select tiddler.\s" sequences.|\sn"+\n "|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Result]] is already closed and the cursor is in the search input field the field's content is cleared so you start a new query.|\sn"+\n "|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second etc. tiddler from the result list.|\sn"+\n "|{{{Alt-O}}}|Opens all found tiddlers.|\sn"+\n "|{{{Alt-P}}}|Toggles the 'Preview Text' mode.|\sn"+\n "|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[YourSearch Result]].|\sn"+\n "|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the {{{Return}}} key actually starts the search (as does pressing the 'search' button).|\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"\n ;\n\nconfig.shadowTiddlers["YourSearch Options"] = \n "|>|!YourSearch Options|\sn"+\n "|>|<<option chkUseYourSearch>> Use 'Your Search'|\sn"+\n "|!|<<option chkPreviewText>> Show Text Preview|\sn"+\n "|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required to start search)|\sn"+\n "|!|Default Search Filter:<<option chkSearchInTitle>>Titles ('!') <<option chkSearchInText>>Texts ('%') <<option chkSearchInTags>>Tags ('#') <html><br><font size=\s"-2\s">The parts of a tiddlers that are searched when you don't explicitly specify a filter in the search text (using a '!', '%' or '#' prefix).</font></html>|\sn"+\n "|!|Number of items on search result page: <<option txtItemsPerPage>>|\sn"+\n "|!|Number of items on search result page with preview text: <<option txtItemsPerPageWithPreview>>|\sn"\n ;\n \nconfig.shadowTiddlers["YourSearchStyleSheet"] = \n "/***\sn"+\n "!~YourSearchResult Stylesheet\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchResult {\sn"+\n "\stposition: absolute;\sn"+\n "\stwidth: 800px;\sn"+\n "\sn"+\n "\stpadding: 0.2em;\sn"+\n "\stlist-style: none;\sn"+\n "\stmargin: 0;\sn"+\n "\sn"+\n "\stbackground: White;\sn"+\n "\stborder: 1px solid DarkGray;\sn"+\n "}\sn"+\n "\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Summary Section\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchResult .summary {\sn"+\n "\stborder-bottom-width: thin;\sn"+\n "\stborder-bottom-style: solid;\sn"+\n "\stborder-bottom-color: #999999;\sn"+\n "\stpadding-bottom: 4px;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchRange, .yourSearchCount, .yourSearchQuery {\sn"+\n "\stfont-weight: bold;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchResult .summary .button {\sn"+\n "\stfont-size: 10px;\sn"+\n "\sn"+\n "\stpadding-left: 0.3em;\sn"+\n "\stpadding-right: 0.3em;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchResult .summary .chkBoxLabel {\sn"+\n "\stfont-size: 10px;\sn"+\n "\sn"+\n "\stpadding-right: 0.3em;\sn"+\n "}\sn"+\n "\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Items Area\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchResult .marked {\sn"+\n "\stbackground: none;\sn"+\n "\stfont-weight: bold;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchItem {\sn"+\n "\stmargin-top: 2px;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNumber {\sn"+\n "\stcolor: #808080;\sn"+\n "}\sn"+\n "\sn"+\n "\sn"+\n ".yourSearchTags {\sn"+\n "\stcolor: #008000;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchText {\sn"+\n "\stcolor: #808080;\sn"+\n "\stmargin-bottom: 6px;\sn"+\n "}\sn"+\n "\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Footer\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchFooter {\sn"+\n "\stmargin-top: 8px;\sn"+\n "\stborder-top-width: thin;\sn"+\n "\stborder-top-style: solid;\sn"+\n "\stborder-top-color: #999999;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchFooter a:hover{\sn"+\n "\stbackground: none;\sn"+\n "\stcolor: none;\sn"+\n "}\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Navigation Bar\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchNaviBar a {\sn"+\n "\stfont-size: 16px;\sn"+\n "\stmargin-left: 4px;\sn"+\n "\stmargin-right: 4px;\sn"+\n "\stcolor: black;\sn"+\n "\sttext-decoration: underline;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar a:hover {\sn"+\n "\stbackground-color: none;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar .prev {\sn"+\n "\stfont-weight: bold;\sn"+\n "\stcolor: blue;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar .currentPage {\sn"+\n "\stcolor: #FF0000;\sn"+\n "\stfont-weight: bold;\sn"+\n "\sttext-decoration: none;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar .next {\sn"+\n "\stfont-weight: bold;\sn"+\n "\stcolor: blue;\sn"+\n "}\sn"+\n "/*}}}*/\sn"\n ;\n\nconfig.shadowTiddlers["YourSearchResultTemplate"] = \n "<!--\sn"+\n "{{{\sn"+\n "-->\sn"+\n "<span macro=\s"yourSearch if found\s">\sn"+\n "<!-- The Summary Header ============================================ -->\sn"+\n "<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+\n " <tr>\sn"+\n "\st<td align=\s"left\s">\sn"+\n "\st\stYourSearch Result <span class=\s"yourSearchRange\s" macro=\s"yourSearch itemRange\s"></span>\sn"+\n "\st\st&nbsp;of&nbsp;<span class=\s"yourSearchCount\s" macro=\s"yourSearch count\s"></span>\sn"+\n "\st\stfor&nbsp;<span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>\sn"+\n "\st</td>\sn"+\n "\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+\n "\st\st<span macro=\s"yourSearch chkPreviewText\s"></span><span class=\s"chkBoxLabel\s">preview text</span>\sn"+\n "\st\st<span macro=\s"yourSearch openAllButton\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+\n "\st</td>\sn"+\n " </tr>\sn"+\n "</tbody></table>\sn"+\n "\sn"+\n "<!-- The List of Found Tiddlers ============================================ -->\sn"+\n "<div id=\s"yourSearchResultItems\s" itemsPerPage=\s"25\s" itemsPerPageWithPreview=\s"10\s"></div>\sn"+\n "\sn"+\n "<!-- The Footer (with the Navigation) ============================================ -->\sn"+\n "<table class=\s"yourSearchFooter\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+\n " <tr>\sn"+\n "\st<td align=\s"left\s">\sn"+\n "\st\stResult page: <span class=\s"yourSearchNaviBar\s" macro=\s"yourSearch naviBar\s"></span>\sn"+\n "\st</td>\sn"+\n "\st<td align=\s"right\s"><span macro=\s"yourSearch version\s"></span>, <span macro=\s"yourSearch copyright\s"></span>\sn"+\n "\st</td>\sn"+\n " </tr>\sn"+\n "</tbody></table>\sn"+\n "<!-- end of the 'tiddlers found' case =========================================== -->\sn"+\n "</span>\sn"+\n "\sn"+\n "\sn"+\n "<!-- The \s"No tiddlers found\s" case =========================================== -->\sn"+\n "<span macro=\s"yourSearch if not found\s">\sn"+\n "<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+\n " <tr>\sn"+\n "\st<td align=\s"left\s">\sn"+\n "\st\stYourSearch Result: No tiddlers found for <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>.\sn"+\n "\st</td>\sn"+\n "\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+\n "\st</td>\sn"+\n " </tr>\sn"+\n "</tbody></table>\sn"+\n "</span>\sn"+\n "\sn"+\n "\sn"+\n "<!--\sn"+\n "}}}\sn"+\n "-->\sn"\n ;\n\nconfig.shadowTiddlers["YourSearchItemTemplate"] = \n "<!--\sn"+\n "{{{\sn"+\n "-->\sn"+\n "<span class='yourSearchNumber' macro='foundTiddler number'></span>\sn"+\n "<span class='yourSearchTitle' macro='foundTiddler title'/></span>&nbsp;-&nbsp;\sn"+\n "<span class='yourSearchTags' macro='foundTiddler tags'/></span>\sn"+\n "<span macro=\s"yourSearch if previewText\s"><div class='yourSearchText' macro='foundTiddler text'/></div></span>\sn"+\n "<!--\sn"+\n "}}}\sn"+\n "-->"\n ;\nconfig.shadowTiddlers["YourSearch"] = "<<tiddler [[YourSearch Help]]>>";\n\nconfig.shadowTiddlers["YourSearch Result"] = "The popup-like window displaying the result of a YourSearch query.";\n\n\nsetStylesheet(\n store.getTiddlerText("YourSearchStyleSheet"),\n "yourSearch");\n\n//----------------------------------------------------------------------------\n// Install YourSearch\n//----------------------------------------------------------------------------\n\n// Overwrite the TiddlyWiki search handler and verify after a while \n// that nobody else has overwritten it.\n\nvar origMacros_search_handler = config.macros.search.handler;\nconfig.macros.search.handler = myMacroSearchHandler;\n\n\nvar ownsOverwrittenFunctions = function() {\n var result = (config.macros.search.handler == myMacroSearchHandler);\n return result;\n};\n\nvar checkForOtherHijacker = function() {\n if (!ownsOverwrittenFunctions()) {\n alert("Message from YourSearchPlugin:\sn\sn\sn"+\n "Another plugin has disabled the 'Your Search' features.\sn\sn\sn"+\n "You may disable the other plugin or change the load order of \sn"+\n "the plugins (by changing the names of the tiddlers)\sn"+ \n "to enable the 'Your Search' features.");\n }\n};\n\nsetTimeout(checkForOtherHijacker, 5000);\n\n\n// === Public API =================================\n\nabego.YourSearch.getStandardRankFunction = function() {\n return standardRankFunction;\n};\n\nabego.YourSearch.getRankFunction = function() {\n return abego.YourSearch.getStandardRankFunction();\n};\n\nabego.YourSearch.getCurrentTiddler = function() {\n return currentTiddler;\n};\n\n} // of "install only once"\n//}}}\n// Used Globals (for JSLint) ==============\n\n// ... JavaScript Core\n/*global alert,clearTimeout,confirm */\n// ... TiddlyWiki Core\n/*global Tiddler, applyHtmlMacros, clearMessage, createTiddlyElement, createTiddlyButton, createTiddlyText, ensureVisible ,findPosX, highlightHack, findPosY,findWindowWidth, invokeMacro, saveChanges, refreshElements, story */\n\n/***\n%/\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005-2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n