Hello Albert,

I've stubled upon an issue -- when AutoSuggestPlugin is included (eval'ed 
without importing) via SharedTiddlersPlugin [1], the styles are not applied 
-- and made a quick fix for it: added the
refreshStyles("StyleSheetAutoSuggest");
line before the
store.addNotification("StyleSheetAutoSuggest", refreshStyles);
line, which seems to be worth including in the main plugin.

Also, in my tweaked version, I've substituted the "chars" with the 
[^\\|\\n\\]] thing, but didn't get what ([^\\x00-\\xff]*) stands for, so 
could you point what's the purpose of this piece (so that I can turn it 
into some more readable RegExp?

For the reference, I attach my tweaked snapshot of the plugin.

Best regards,
Yakov.

[1] http://yakovl.bplaced.net/TW/STP/STP.html

среда, 16 апреля 2014 г., 0:47:59 UTC+4 пользователь Albert Riedinger 
написал:
>
> Today I worked out a temporary solution for pretty links, so it is 
> possible now to type "[[SOME_LABEL|" which gives you tiddler title 
> suggestions.
> It was a tough nut to crack for a regex newbie like me, but it works :)
>
> Try it out and have fun[1]!
> Albert
>
> [1] http://autosuggest.tiddlyspace.com/#AutoSuggestPlugin
>

-- 
You received this message because you are subscribed to the Google Groups 
"TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/tiddlywiki.
For more options, visit https://groups.google.com/d/optout.
/***
|''Name''|AutoSuggestPlugin|
|''Source''|http://autosuggest.tiddlyspace.com/#AutoSuggestPlugin|
|''Version''|0.2.6 Alpha (2014-04-16), tweak 2.0 by YL|
|''Author''|Albert Riedinger|
|''License''|[[Creative Commons BY-SA 
3.0|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion''|2.x|
|''Type''|plugin|
|''Requires''|[[jQuery.Caret.min.js]], [[jQuery.AtWho.min.js]]|
|''Optional''|[[jQuery.asuggest.min.js]] with [[jQuery.a-tools.min.js]]|
|''Stylesheet''|[[StyleSheetAutoSuggest]] (shadow)|
|''Documentation''|[[AutoSuggestPluginInfo]]|
|''Description''|provides automatic suggestions for all kind of TW data in edit 
mode|

!Usage
* insert {{{autoSuggest}}} in [[ToolbarCommands]] (EditToolbar Slice)
* activate auto suggestion in edit mode
* type in tiddler text field ...
** {{{[[}}} > for tiddler name suggestions
*** {{{[[}}}LABEL{{{|}}} for pretty links
** {{{[[##}}} > for section name suggestions of current tiddler (inserts tiddly 
link to chosen section)
** {{{[[::}}} > for slice name suggestions of current tiddler
** {{{[[??}}} > for field name suggestions of current tiddler (inserts wikified 
content of chosen field with {{{view}}} macro)
** {{{##}}} > for tag suggestions
** {{{<<}}} > for macro name suggestions
* type in tag input field
** {{{[[}}} > for tiddler name suggestions
** {{{##}}} > for tag suggestions
* if word completion is activated in options, you get inline "office-like" word 
completion in tiddler text field (experimental) ...
** press {{{TAB}}} to cycle through suggestions
** press {{{RETURN}}} to accept suggestion

!History
* 0.2.0 > initial working release
* 0.2.1 > option for inserting whitespace after suggestion
* 0.2.2 > {{{##}}} > tag suggestion in tag input field (inserts tiddly link: 
{{{[[TAG]]}}})
* 0.2.3
** {{{EXPERIMENTAL}}} implemented word completion with 
[[jQuery.asuggest.min.js]] > if activated in options, it provides inline 
"office-like" word completion for tiddler names
*** press {{{TAB}}} to cycle through suggestions
*** press {{{RETURN}}} to accept suggestion
*** in a future release it will suggest more: user defined dictionary (tiddler 
with word list), (cached) word list from current tiddler etc.
* 0.2.4
** updated [[jQuery.AtWho.min.js]] and [[jQuery.Caret.min.js]]
** {{{[[##}}} > section name suggestions for current tiddler (inserts tiddly 
link: {{{[[SECTION_NAME|CURRENT_TIDDLER##SECTION_NAME]]}}})
** {{{[[::}}} > slice name suggestions for current tiddler (inserts slice 
link?: {{{[[CURRENT_TIDDLER::SLICE_NAME]]}}})
** {{{[[??}}} > field name suggestions for current tiddler (inserts wikified 
field value: {{{<<view FIELD_NAME wikified>>}}})
** preliminary support for diacritic characters (like äöüßáàéè etc.)
* 0.2.5
** {{{[[}}}LABEL{{{|}}} > added support for pretty links
* 0.2.6
** fixed minor regex bug in pretty links matcher

!Options
| Value | Description |h
|>| GENERAL |h
|auto suggest scope (global/local): <<option chkAutoSuggestGlobal>> |if 
''checked'' (true) > auto suggestion state will be saved for all tiddlers in a 
cookie (see option below)<br>if ''not checked'' (false) > auto suggestion state 
will be saved on a per-tiddler-basis in the custom field {{{autosuggest}}} 
(''NOT IMPLEMENTED YET'')|
|auto suggest global: <<option chkAutoSuggestGlobalState>> |if ''checked'' auto 
suggestion will be activated for all tiddlers (if auto sugesst scope is set to 
local, this option will be deactivated)|
|button label<br>(autosuggest activated): <<option txtAutoSuggestBtnAlt>> ||
|button label<br>(autosuggest deactivated): <<option txtAutoSuggestBtn>> ||
|suggestion limit: <<option txtAutoSuggestListLimit>> |limits number of 
suggestions in popup list|
|insert whitespace after suggestion: <<option chkAutoSuggestInsertWhitespace>> 
|if ''checked'' > whitespace will be inserted after suggestion|
|>| TIDDLERS |h
| ... | ... |
|>| SECTIONS |h
| ... | ... |
|>| SLICES |h
| ... | ... |
|>| FIELDS |h
| ... | ... |
|>| TAGS |h
| ... | ... |
|>| MACROS |h
| ... | ... |
|>| ''{{{EXPERIMENTAL}}}'' |h
|>| WORD COMPLETION |h
|activate word completion: <<option chkAutoSuggestWordComplete>>||


!Code
***/
//{{{
version.extensions.AutoSuggestPlugin = { major: 0, minor: 2, revision: 6, date: 
new Date(2014, 04, 16) };
(function($){
// ---------- Options ----------
if (config.options.chkAutoSuggestGlobal === undefined) 
config.options.chkAutoSuggestGlobal = true;
if (config.options.chkAutoSuggestGlobalState === undefined) 
config.options.chkAutoSuggestGlobalState = false;
if (config.options.txtAutoSuggestBtn === undefined) 
config.options.txtAutoSuggestBtn = "autosuggest off";
if (config.options.txtAutoSuggestBtnAlt === undefined) 
config.options.txtAutoSuggestBtnAlt = "autosuggest on";
// !!!BUG funktioniert noch nicht
if (config.options.txtAutoSuggestListLimit === undefined) 
config.options.txtAutoSuggestListLimit = 8;
if (config.options.chkAutoSuggestInsertWhitespace === undefined) 
config.options.chkAutoSuggestInsertWhitespace = false;
if (config.options.chkAutoSuggestWordComplete === undefined) 
config.options.chkAutoSuggestWordComplete = false;

config.commands.autoSuggest = {
        text: config.options.txtAutoSuggestBtn,
        text_alt: config.options.txtAutoSuggestBtnAlt,
        tooltip: "activate automatic word suggestion for edit fields",
        tooltip_alt: "deactivate automatic word suggestion for edit fields",
        suggLimit: config.options.txtAutoSuggestListLimit,
        hideReadOnly: true,

        handler: function(event, src, title) {
                var here = story.findContainingTiddler(src); if (!here) return;
                var hereTid = here.id.substr(7);
                var txt = {
                        areas: here.getElementsByTagName("textarea"),
                        inputs: here.querySelectorAll("input[type=text]") // 
does not work with IE > 8
                };
                var asGlobal = config.options.chkAutoSuggestGlobal;
                var asGlobalState = config.options.chkAutoSuggestGlobalState;

                if (!txt.areas && !txt.inputs) return;

                if (!asGlobalState) {
                        this.on(txt, src, hereTid);
                } else {
                        this.off(txt, src);
                }

                return false;
        },

        on: function(txt, btn, hereTid) {
                // get all textareas with edit attribute (txt.areas)
                for (i=0; i<txt.areas.length; i++) {
                        if (txt.areas[i].getAttribute("edit") === undefined) 
continue;
                        // type of field (txt.areas.field)
                        txt.areas[i].field = txt.areas[i].getAttribute("edit");
                        //console.log("txt.areas[i]: " + txt.areas + " / field: 
"+txt.areas[i].field);
                }
                // get all input fields with edit attribute (txt.inputs)
                for (i=0; i<txt.inputs.length; i++) {
                        if (txt.inputs[i].getAttribute("edit") === undefined) 
continue;
                        // type of field (txt.inputs.field)
                        txt.inputs[i].field = 
txt.inputs[i].getAttribute("edit");
                        //console.log("txt.inputs[i]: " + txt.inputs + " / 
field: "+txt.inputs[i].field);
                }

                var t = store.getTiddlers();

                // get all tiddler names (tidList)
                var tids = [];
                for (var i=0; i<t.length; i++) { tids.push(t[i].title); }
                var tidList = jQuery.map(tids, function(val) {
                        return { "name":val };
                });

                // get sections (sectionList)
                //      * for current tiddler only (sections for specific 
tiddlers is coming in a future release)
                var sections = [];
                var tidText = store.getTiddlerText(hereTid, "");
                var regExpSec = /(?:^|\n)!{1,6}([^\n]*)\n/gm;
                do { var s = regExpSec.exec(tidText); if (s) { 
sections.push(s[1]); } } while(s);
                var sectionList = jQuery.map(sections, function(val) {
                        return { "tid":hereTid, "name":val };
                });

                // get slices (sliceList)
                //      * for current tiddler only (slices for specific 
tiddlers is coming in a future release)
                var slices = store.calcAllSlices(hereTid);
                var sliceList = jQuery.map(slices, function(val, key) {
                        return { "tid":hereTid, "name":key, "slice":val };
                });

                // get fields (fieldList)
                //      * for current tiddler only (fields for specific 
tiddlers is coming in a future release)
                var fields = {}
                var hereTidObj = store.fetchTiddler(hereTid);
                store.forEachField(
                        hereTidObj,
                        function(hereTidObj, f, v){ fields[f] = v; },
                        true
                );
                var fieldList = jQuery.map(fields, function(val, key) {
                        return { "name":key, "value":val };
                });

                // get all tags (tagList)
                var tags = store.getTags();
                var tagList = jQuery.map(tags, function(val) {
                        return { "name":val[0], "count":val[1] };
                });

                // get all TiddlyWiki macros (macroList)
                var macroList = Object.keys(config.macros);

                var tplTidLink = "<li data-value='${name}]]'>${name}</li>";
                var tplSectionLink = "<li 
data-value='[[${name}|${tid}##${name}]]'>${name}</li>";
                var tplSlice = "<li 
data-value='[[${tid}::${name}]]'>${name}<br><small>${slice}</small></li>";
                var tplField = "<li data-value='<<view ${name} 
wikified>>'>${name}<br><small>${value}</small></li>";
                var tplTagLink = "<li data-value='[[${name}]]'>${name} <small 
style='float:right;padding-left:2rem'>${count}</small></li>";

                // callbacks for AtWho listeners
                // default callbacks
                var cbAll = {
                        before_insert: function(value, $li) {
                                if 
(config.options.chkAutoSuggestInsertWhitespace) value = value + " ";
                                return value;
                        }
                };
                // custom callbacks
                // default matcher
                var cbMatch = {
                        matcher: function(flag, subtext, 
should_start_with_space) {
                                var match, regexp;
// YL question: why the flag is not defined (flag = "[[")
                                flag = 
flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
                                if (should_start_with_space)
                                        flag = "(?:^|\\s)" + flag;

/* YL tweak */                  regexp = new 
RegExp(flag+"([^\\|\\n\\]]*)$|"+flag+"([^\\x00-\\xff]*)$", "gi");
// YL question: what's the purpose of the second part and that \\x00-\\xff 
thing?
                                match = regexp.exec(subtext);
                                if (match)
                                        return match[2] || match[1];
                                else
                                        return null;
                        }
                };
                // !EXPERIMENTAL! matcher for tiddly links AND pretty links
                var cbMatchTidLink = {
                        matcher: function(flag, subtext, 
should_start_with_space) {
                                var match, regexp;
                                // fixed flag
                                flag = "[[";
                                flag = 
flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
                                if(should_start_with_space)
                                        flag = "(?:^|\\s)" + flag;

/* YL tweak */                  regexp = new RegExp(flag+ "([^\\|\\n\\]]*)$|"+ 
flag+"[^\\|\\n\\]]+\\|([^\\|\\n\\]]*)$", "gi");
                                match = regexp.exec(subtext);
                                if (match)
                                        return match[2] || match[1];
                                else
                                        return null;
                        }
                };
                // merge all callbacks
                var cb = $.extend({}, cbMatch, cbAll);
                var cbTidLink = $.extend({}, cbMatchTidLink, cbAll);

                // !!! TODO:
                //      * specify fields (text, tags etc.)
                $(txt.areas)
                        .atwho({ at: "", callbacks: cbTidLink, tpl: tplTidLink, 
data: tidList, limit: this.suggLimit })
                        .atwho({ at: "[[##", callbacks: cb, tpl: 
tplSectionLink, data: sectionList, limit: this.suggLimit })
                        .atwho({ at: "[[::", callbacks: cb, tpl: tplSlice, 
data: sliceList, limit: this.suggLimit })
                        .atwho({ at: "[[??", callbacks: cb, tpl: tplField, 
data: fieldList, limit: this.suggLimit })
                        .atwho({ at: "##", callbacks: cb, tpl: tplTagLink, 
data: tagList, limit: this.suggLimit })
                        .atwho({ at: "<<", callbacks: cb, data: macroList, 
limit: this.suggLimit });
                $(txt.inputs)
                        .atwho({ at: "[[", callbacks: cb, tpl: tplTidLink, 
data: tidList, limit: this.suggLimit })
                        .atwho({ at: "##", callbacks: cb, tpl: tplTagLink, 
data: tagList, limit: this.suggLimit });

                // activating word completion
                // TODO:
                // * check if autosuggest is installed
                if (config.options.chkAutoSuggestWordComplete) {
                        $(txt.areas).asuggest(tids, {
                                "minChunkSize":         1,
                                "stopSuggestionKeys":   [$.asuggestKeys.RETURN]
                        });
                }

                // log AtWho matches for debugging
                //$(txt.areas).on("matched.atwho", function(event, flag, query) 
{
                //      console.log(event, "matched: " + flag + " / result: " + 
query);
                //});

                $(btn).html(this.text_alt);
                $(btn).attr("title", this.tooltip_alt);
                config.options.chkAutoSuggestGlobalState = true;
        },

        off: function(txt, btn) {
                $(txt.areas).atwho("destroy");
                $(txt.inputs).atwho("destroy");
                $(btn).html(this.text);
                $(btn).attr("title", this.tooltip_alt);
                config.options.chkAutoSuggestGlobalState = false;
        }
};
//}}}

/***
!!Hijacking config.commands.editTiddler.handler
***/
//{{{
config.commands.editTiddler.handler_AUTOSUGGEST = 
config.commands.editTiddler.handler;
config.commands.editTiddler.handler = function(event, src, title) {
        var asHere = story.findContainingTiddler(src);
        var asHereTid = asHere.id.substr(7);

        // invoke original editTiddler command
        config.commands.editTiddler.handler_AUTOSUGGEST.apply(this, arguments);

        var asGlobalState = config.options.chkAutoSuggestGlobalState;
        var txt = {
                areas: asHere.getElementsByTagName("textarea"),
                inputs: asHere.querySelectorAll("input[type=text]") // does not 
work with IE > 8
        };
        if (!txt.areas && !txt.inputs) return;
        // find autoSuggest command button
        var btn = $(story.getTiddler(title)).find(".command_autoSuggest");
        if (asGlobalState === true) config.commands.autoSuggest.on(txt, btn, 
asHereTid);
};
//}}}

/***
!!Shadow Tiddler for Styles
***/
//{{{
config.shadowTiddlers.StyleSheetAutoSuggest =
        "/*{{{*/\n" +
        ".atwho-view 
{\n\tposition:absolute;\n\ttop:0;\n\tleft:0;\n\tdisplay:none;\n\tmargin-top:18px;\n\tbackground:white;\n\tborder:1px
 solid #DDD;\n\tborder-radius:3px;\n\tbox-shadow:0 0 5px 
rgba(0,0,0,0.1);\n\tmin-width:120px;\n\tz-index:10;\n}\n" +
        ".atwho-view .cur {\n\tbackground:#3366FF;\n\tcolor:white;\n}\n" +
        ".atwho-view .cur small {\n\tcolor:white;\n}\n" +
        ".atwho-view strong {\n\tcolor:#3366FF;\n}\n" +
        ".atwho-view .cur strong {\n\tcolor:white;\n\tfont:bold;\n}\n" +
        ".atwho-view ul {\n\t/* width:100px; 
*/\n\tlist-style:none;\n\tpadding:0;\n\tmargin:auto;\n}\n" +
        ".atwho-view ul li {\n\tdisplay:block;\n\tpadding:5px 
10px;\n\tborder-bottom:1px solid #DDD;\n\tcursor:pointer;\n\t/* border-top:1px 
solid #C8C8C8; */\n}\n" +
        ".atwho-view small 
{\n\tfont-size:smaller;\n\tcolor:#777;\n\tfont-weight:normal;\n}\n" +
        "/*}}}*/";
/* YL tweak */ // refresh at once: otherwise the styles are not applied when 
shared via SharedTiddlersPlugin
refreshStyles("StyleSheetAutoSuggest");
store.addNotification("StyleSheetAutoSuggest", refreshStyles);
})(jQuery);
//}}}

Reply via email to