User talk:The Transhumanist/ViewAnnotationToggler.js: Difference between revisions

Content deleted Content added
Complication: revise msg, refresh ping
m Replaced deprecated <source> tags with <syntaxhighlight>
 
(39 intermediate revisions by 3 users not shown)
Line 1:
{{User:The Transhumanist/Workshop boilerplate/Lead hatnote}}
= Explanatory notes (source code walk-through) =
 
: '''''This script is operational: its main features work; it is under further development'''''
You can only use so many comments in the source code before you start to choke or bury the programming itself. So, I've put short summaries in the source code, and have provided in-depth explanations here. My intention is twofold:
# to thoroughly document the script so that even relatively new JavaScript beginners can understand what it does.
# to refresh my memory of exactly how the script works, in case I don't look at the source code (or any JavaScript) for weeks or months.
 
AnnotationToggler = Annotation Toggler. It adds a tab menu item to toggle list item (LI) annotations.
The explanatory notes include examples, and links to relevant documentation pages, tutorials, etc.
 
= Script's workshop =
In addition to some standard [[JavaScript]] code, this script also relies heavily on the [[jQuery]] library.
: ''This is the work area for developing the script and its documentation. The talk page portion of this page starts at [[#Discussions]], below.''
 
== Description / instruction manual ==
If you have any questions, feel free to ask me ''[[#Discussions|at the bottom of this page under '''Discussions''']]''. Trying to answer them will help me learn JavaScript better.
 
: '''''This script is operational: its main features work; it is under further development'''''
== General approach ==
 
ViewAnnotationToggler.js: adds a tab menu item and hot key to turn list item annotations off and on, across all pages..
 
The hot key is {{keypress|Shift|Alt|a}}.
 
This script works on the list items in bulleted lists, lists in which each item is
preceded by a bullet. Bulleted lists abound upon Wikipedia. They are used in stand-alone
lists which are entire articles that are lists, and they are used in embedded lists
situated within articles.
 
Many list items have an annotation, that is, the list item is followed by a description.
These descriptions are useful, but they may obscure the items in the list that they
describe. Sometimes, it is useful to look at the bare list, without the annotations.
 
This script turns those descriptions on and off. It provides a tab menu command and
a hotkey for doing so.
 
When you don't need to see the descriptions, turn them off. When you need more detail,
hit the toggle again, and the descriptions return. The script stores its status so it
doesn't start over between pages &mdash; when annotations are turned off, they are off for
all pages until you turn them back on again.
 
{{User:The Transhumanist/Workshop boilerplate/Install}}
 
{{User:The Transhumanist/Workshop boilerplate/Explanatory notes}} <!--includes h2 heading-->
 
=== General approach ===
 
We prep the page by wrapping list item annotations in spans with the class "anno". Then we refer to that class later in hide and show functions which create a menu item that the user can click on. How we do all of this is explained in fine detail below.
 
=== aliases ===
 
An alias is one string defined to mean another. Another term for "alias" is "shortcut". In the script, the following aliases are used:
Line 31 ⟶ 57:
That is a "bodyguard function", and is explained in the section below...
 
=== Bodyguard function ===
 
The bodyguard function assigns an alias for a name within the function, and reserves that alias for that purpose only. For example, if you want "t" to be interpreted only as "transhumanist".
Line 55 ⟶ 81:
</syntaxhighlight>
 
''For the best explanation of the bodyguard function I've found so far, see: [http://codeimpossible.com/2010/01/13/solving-document-ready-is-not-a-function-and-other-problems/ Solving "$(document).ready is not a function" and other problems]''
 
=== The ready() event listener/handler ===
 
The ready() event listener/handler makes the rest of the script wait until the page (and its [[Document Object Model|DOM]]) is loaded and ready to be worked on. If the script tries to do its thing before the page is loaded, there won't be anywhere for it to place the menu item (mw.util.addPortletLink), and the script will fail.
 
ItIn jQuery, it looks like this: [http://learn.jquery.com/using-j\query-core/document-ready/ <code>$( document ).ready() {});</code>]
 
The part of the script that is being made to wait goes inside the curly brackets. (startingBut you would generally start that on the next line, withand put the ending curly bracket, closing parenthesis, and semicolon following that on a line of their own)., like this:
 
See also: http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
 
The jQuery shorthand version of the same thing looks like this:
 
<syntaxhighlight lang="javascript">
1 $(function() {<br>
2 // Body of function (or even the rest of the script) goes here, such as a click handler.<br>
2 // Handler for .ready() called.<br>
3 });
</syntaxhighlight>
 
''This is all explained further onat [https://api.jquery.com/ready/ the jQuery page for <code>.ready()</code>]''
 
For the plain vanilla version see: http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
 
=== Prep work ===
 
==== var ====
 
This is a [[reserved word]] [https://www.w3schools.com/js/js_reserved.asp reserved] (aka "keyword]"). The keyword [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var var] is used to declare variables in variable statements. A variable is a container you can put a value in. To declare the variable portletlink, write this:
 
<syntaxhighlight lang="javascript">
Line 93 ⟶ 117:
</syntaxhighlight>
 
==== document.get.ElementById() ====
 
Part of the [https://developer.mozilla.org/en-US/docs/Web/API/Document WWW's Document API], this method returns the element with the specified ID. That is, it fetches the entire contents of a unique element. (If the element ID is not unique, it'll fetch the first one only).
Line 100 ⟶ 124:
* [https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById document.getElementById()]
 
A key use of this method is to assign the contents of an element to a variable. (''[[#cont.outerHTML|See below]]'').
 
==== "mw-content-text" ====
 
<code>mw-content-text</code> is an element ID. Unlike classes, IDs are unique (or are supposed to be).
 
Unfortunately, this ID is not covered in [[WP:IDS]].
 
But it is included in the list [[mw:Manual:Interface/IDs and classes]]:
Line 112 ⟶ 136:
It's the part of the HTML page (of a Wikipedia page) that "holds everything between the page title and contentSub on the one hand, and ArticleFeedback and categories on the other hand. [It is] present on each page view (includes history view, non-existing pages, print view, ...)."
 
==== cont.outerHTML ====
 
"cont" is a variable.
Line 129 ⟶ 153:
* [https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML Element.outerHTML]
 
==== outerHTML.replace ====
 
innerHTML.replace tells [[regex]] to search and replace only within the contents of elements, NOT including their tags.
Line 146 ⟶ 170:
* [http://coursesweb.net/javascript/innerhtml-outerhtml-get-replace-html-content_t innerHTML and outerHTML to Get and Replace HTML content]
 
==== Wrapping the annotations in span tags ====
 
With this tactic, we isolate the annotations so that we can switch their display on and off later in the script. To isolate them, we wrap the desired content in span tags, with the span including a class. Once they all have the same class, we can manipulate them all at once (like hiding or showing them all).
Line 160 ⟶ 184:
This approach is easier (and more elegant) than using regex to remove the annotations directly, because if you do it that way, you would need to save a copy of the whole page before you removed them, in order to get them back when you "toggle" them back on.
 
=== Central control structure ===
 
This part controls the main flow of the script (decides what to do under what circumstances):
Line 181 ⟶ 205:
First, it checks if the Vector skin is being used and runs the rest of the script only if it is.
 
Then it checks the status of the script, that is, whether it was set to "show" or "hide" the last time it was used.
 
Then it calls the function that corresponds with the current status (calling either annoHide or annoShow, defaulting to annoShow if there is no status).
Line 188 ⟶ 212:
* [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling Control flow and error handling]
 
==== if and if/else statements ====
 
* [https://www.w3schools.com/js/js_if_else.asp JavaScript If...Else Statements]
Line 194 ⟶ 218:
* <nowiki>https://www.tutorialspoint.com/javascript/javascript_ifelse.htm</nowiki>
 
==== mw.config.get ( 'skin' ) ====
 
This looks up the value for skin (the internal name of the currently used skin) saved in MediaWiki's configuration file.
Line 201 ⟶ 225:
* [https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config mw.config]
 
==== logical operators ====
 
<code>===</code> means "equal value and equal type"
Line 207 ⟶ 231:
* [https://www.w3schools.com/js/js_comparisons.asp JavaScript Comparison and Logical Operators]
 
==== localStorage.getItem ====
 
* [https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage LocalStorage]
* [https://developer.mozilla.org/en-US/docs/Web/API/Storage/getItem Storage.getItem()]
 
==== Calling a function ====
 
In JavaScript, a function is a subroutine. You call a function by its name. The function "example" is called like this:
Line 224 ⟶ 248:
The script has 2 custom functions written in it: annoHide, and annoShow. Each one includes a function call to the other, but the main controlling structure of the program checks local storage to see what the program's hide/show status is (in local storage), and calls the corresponding function.
 
=== Subroutines (functions) ===
 
==== Defining a function ====
 
"Function" is another name for "[[subroutine]]". Here's how you define a function in JavaScript:
Line 243 ⟶ 267:
A function is not activated until it is called. ''(See next section).''
 
==== localStorage.setItem ====
 
The [https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage <code>localStorage</code> property] allows you to store some data in the browser's memory area for later use, so you don't lose it when changing pages or closing the browser.
 
What we use it for in the script is to store the script's show/hide status, so we can check it (each time the script starts) to see whether the script is supposed to execute the annoHide or the annoShow function. To create a data item in localStorage named "annostatus" for storing the value "show", we do this:
Line 261 ⟶ 285:
''For further detail, see: [https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API Using the Web Storage API]''.
 
==== How the script hides and shows the annotations ====
 
The main power of the script is provided by using two jQuery methods: [http://api.jquery.com/hide/ .hide] and [http://api.jquery.com/show/ .show]
Line 276 ⟶ 300:
</syntaxhighlight>
 
==== Checking and clearing the menu item ====
 
After the script executes a show or hide, the menu item needs to be updated. The first step is to check that it ("annoSwitch") exists, and if it does, remove it. Like this:
Line 293 ⟶ 317:
* [https://api.jquery.com/detach/ .detach()]
 
==== Creating a menu item with mw.util.addPortletLink ====
 
[[mw:ResourceLoader/Core modules#addPortletLink|mw.util.addPortletLink]] is a function in the core module "[[mw:ResourceLoader/Core modules#MediaWiki|mediaWiki]]". It adds a menu item to one of Wikipedia's menus. Use "p-tb" to signify the toolbox menu on the sidebar menu.
Line 303 ⟶ 327:
</syntaxhighlight>
 
It has up to 7 parameters, with the first 3 being required. Only those 3 are used above.
 
'''Important:''' It won't do anything until you bind it to a click handler (see below).
 
General usage:
<syntaxhighlight lang="javascript">
mw.util.addPortletLink( 'portletId', 'href', 'text', 'id', 'tooltip', 'accesskey', 'nextnode');
</syntaxhighlight>
 
It's components:
<code>mw.util.addPortletLink( portletId, href, text [, id [, tooltip [, accesskey [, nextnode ]]]] );</code>
* <code>mw.util.addPortletLink</code>: the ResourceLoader module to add links to the portlets.
* <code>portletId</code>: portlet id— the section where the new menu item is to be placed. Valid values:
** <code>p-navigation</code>: Navigation section in left sidebar
** <code>p-interaction</code>: Interaction section in left sidebar
** <code>p-tb</code>: Toolbox section in left sidebar
** <code>coll-print_export</code>: Print/export section in left sidebar
** <code>p-personal</code> Personal toolbar at the top of the page
** <code>p-views</code> Upper right tabs in Vector only (read, edit, history, watch, etc.)
** <code>p-cactions</code> Drop-down menu containing move, etc. (in Vector); subject/talk links and action links in other skins
* <code>href</code>: Link to the Wikipedia or external page
* <code>text</code>: Text that displays
* <code>id</code>: HTML id (optional)
* <code>tooltip</code>: Tooltip to display on mouseover (optional)
* <code>accesskey</code>: Shortcut key press (optional)
* <code>nextnode</code>: Existing portlet link to place the new portlet link before (optional)
 
The optional fields must be included in the above order. To skip a field without changing it, use the value <var>null</var>.
* portletID = ID of the menu you want to add the menu item to
* href =
* text = the name of the menu item as it is to appear in the menu
* ID = element ID
* tooltip = the tip that shows up when you hover the mouse cursor over the menu item
* accesskey = the name of the hot key (without the Shift-alt)
* nextnode =
 
''For the documentation on this function, see https://www.mediawiki.org/wiki/ResourceLoader/Modules#addPortletLink'' and [[Help:Customizing toolbars]].
 
'''Important:''' It won't do anything until you bind it to a click handler (see below).
 
==== click handler ====
 
To make the above menu item so it does something when you click on it, you have to "bind" it to a handler. Like this:
Line 333 ⟶ 369:
4 }
</syntaxhighlight>
 
 
The "handler" is the part between the curly brackets.
Line 341 ⟶ 376:
<code>e.preventDefault()</code> is short for <code>[http://api.jquery.com/event.preventDefault/ event.preventDefault()]</code>, one of jQuery's event objects.
 
== Change log ==
 
* 2017-07-07
** Version 0.4 &ndash; [https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=789519032 ready to embark on fixing the viewport]
* 2017-07-06
** Moved the functions to the end of the script to make it easier to follow; marked the sections clearly
* 2017-07-05
** Added document ready function, so the script waits until the DOM is loaded before running
** Changed menu items to "Annotations (show)" and "Annotations (hide)"
* 2017-01-19
** Version 0.3 &ndash; [https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=760834841 Simplified the script to wrap annotations and then hide or show them].
* 2016-12-11
** Version 0.2 &ndash; [https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=754184988 on/off status persists across pages].
* 2016-12-08
** Anchor regexes on <nowiki><li></nowiki> (starting only) element delimiters
Line 360 ⟶ 384:
*** Uses regex to remove annotations
*** Uses a toggle to switch back and forth between the two states
* 2016-12-11
** Version 0.2 &ndash; [https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=754184988 on/off status persists across pages].
* 2017-01-19
** Version 0.3 &ndash; [https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=760834841 Simplified the script to wrap annotations and then hide or show them].
* 2017-07-05
** Added document ready function, so the script waits until the DOM is loaded before running
** Changed menu items to "Annotations (show)" and "Annotations (hide)"
* 2017-07-06
** Moved the functions to the end of the script to make it easier to follow; marked the sections clearly
* 2017-07-07
** Version 0.4 &ndash; [https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=789519032 ready to embark on fixing the viewport]
* 2018-02-23
** Changed name to ViewAnnotationToggler.js
** removed activation filter so it works on all pages
* 2018-03-13
** Script editor wouldn't work while ViewAnnotationToggler was running, so added a deactivation filter so that this script doesn't run on edit pages.
 
== Task list ==
 
=== Bug reports ===
 
=== Desired/completed features ===
 
: ''Completed features are marked with {{done}}''
 
= Desired features =
Improvements needed:
 
* Don't run on move pages
* Since it hides content, an indicator is needed to show when it is on/off.
* Fix the conflict with sidebar toggle (it also uses hot-key Shift-Alt-a)
Line 374 ⟶ 422:
* Feature to apply and save fixes (conversions) to wikicode (i.e., replace non-standard annotation punctuation in the page source)
 
=== Have the viewport stay anchored on its top entry when the toggle is used ===
 
==== Temporary fix for viewport problem: invisibility ====
 
http://stackoverflow.com/questions/9614622/equivalent-of-jquery-hide-to-set-visibility-hidden
 
It states:
There isn't one [(a jQuery function)] built in but you could write your own quite easily:
 
Line 408 ⟶ 456:
Here's a [http://jsfiddle.net/nGhjQ/ working example].
 
=== Find/replace annotations of other formats ===
 
== Find/replace annotations of other formats ==
 
* regular hyphens
Line 419 ⟶ 466:
* colons
 
=== Find/replace annotations of lead list entries (without bullets) ===
 
* Only on pages with the title "Outline of"
Line 429 ⟶ 476:
** The bullet?
 
=== Program on/off switch ===
= Completed features =
 
 
== Program on/off switch ==
 
The current objective is to store global variables, and pass them on to the next page, including the current page upon refresh.
Line 448 ⟶ 492:
Feature completed. [[User talk:The Transhumanist|<i>The&nbsp;Transhumanist</i>]] 09:06, 11 December 2016 (UTC)
 
=== Went from cloning/regex-to-null to show/hide wrapper ===
 
Initially, the program toggled hide/show in a rather convoluted way: first it saved the mw-content element by cloning it. Then it deleted the annotations using regex. To get them back, it made a clone of the clone, and then replaced mw-content with the second clone. Here's that version:
Line 457 ⟶ 501:
 
https://en.wikipedia.org/w/index.php?title=User:The_Transhumanist/anno.js&oldid=760834841
 
 
It shrank by several lines of code. [[User talk:The Transhumanist|<i>The&nbsp;Transhumanist</i>]] 13:27, 19 January 2017 (UTC)
 
== Development notes ==
 
=== Trycatch needed, and more ===
:The Transhumanist, where you use local storage.getItem() or setItem() you should always wrap that in try catch, as it can fail at any moment (even if you checked previously). This can be due to the browser running out of storage space for the ___domain, or because the browser is running in privacy mode or with an ad blocker extensions or something. Also, your new RegExp() calls should be lifted outside of the for loops, so that they aren't continuously recreated. For wpTextbox1.value, realise that sometimes the content might be managed by an editor (The syntaxhighlighting beta does this for instance). We use the [https://phabricator.wikimedia.org/source/mediawiki/browse/master/resources/src/jquery/jquery.textSelection.js jquery.textSelection plugin] to abstract way from these differences. Don't check document.title, check mw.config.get( 'wgTitle' ) or mw.config.get( 'wgPageName' ). And when you use mw.util.addPortlink, you have to ensure that the mediawiki.util plugin is loaded already, which you can do by using [https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader mw.loader.using]. —[[User:TheDJ|Th<span style="color: green">e</span>DJ]] ([[User talk:TheDJ|talk]] • [[Special:Contributions/TheDJ|contribs]]) 14:47, 27 October 2017 (UTC)
 
=== Links to related discussions ===
 
* [[Wikipedia talk:WikiProject JavaScript#I'm stumped: How do you save a ___location in the viewport to reposition the viewport later?]] (May/June 2017)
* [[User talk:Anomie/Archives/2017#I'm stumped]](Jan 2017)
** wrap with span and toggle display property
** [https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint Document.elementFromPoint()]
* [[Wikipedia:Reference desk/Archives/Computing/2016 December 9#Scroll position in JavaScript]] (Dec 2016)
Line 484 ⟶ 530:
* [[Wikipedia:Village pump (proposals)/Archive 132#Interactive chess boards]] (May 2016)
 
=== Injecting/inserting/embedding style ===
 
One way to hide/show a class is to define that class on the page, and then toggle its display property. Where are the instructions on how to do this?
 
Here are some related links:
Line 498 ⟶ 544:
* [https://davidwalsh.name/add-rules-stylesheets Add Rules to Stylesheets with JavaScript]
 
=== Save and reset the viewport position relative to its topmost element ===
I'm thinking of the following approach, but do not know how to implement it:
 
Line 511 ⟶ 557:
This is a rather cludgy way to do it. See the next section instead. 23:40, 3 June 2017 (UTC)
 
==== Identify the elements in the viewport ====
 
I would like to find the topmost element that starts within the viewport.
 
===== Check a particular element to determine if it is in the viewport =====
 
* [https://gist.github.com/jjmu15/8646226 check if element is in viewport]
Line 527 ⟶ 573:
* http://stackoverflow.com/questions/37882208/get-element-___location-relative-to-viewport-with-selenium-python
 
===== How to get (and process) all elements on the page =====
 
This approach can be used to create a function to check every element's position against the viewport's position, to determine which element is the topmost in the viewport. One problem is that some elements might be inside other elements, such as navigation sidebars, but most of those will be over on the right of the page, so you can check the x-coordinate to filter those out.)
Line 534 ⟶ 580:
* [http://stackoverflow.com/questions/12823264/get-all-elements-in-the-body-tag-using-pure-javascript Get all elements in the body tag using pure javascript]
 
===== How to get position of an element =====
 
* [https://www.stackoverflow.com/questions/5598743/finding-elements-position-relative-to-the-document finding element's position relative to the document]
* [https://www.w3schools.com/jquery/css_position.asp jQuery position() Method] &ndash; returns the position (relative to its parent element) of the first matched element.
 
==== Find and adjust viewport position ====
 
* [http://kirbysayshi.com/2013/08/19/maintaining-scroll-position-knockoutjs-list.html Maintaining Scroll Position When Adding Content to the Top of a Container] &ndash; includes plain JS and jQuery solutions (working from the offset of an element).
 
==== Find viewport position ====
 
The goal here is to maintain the position of the scroll, with respect to the topmost list entry on the screen, and have the formatting change while maintaining that position.
Line 554 ⟶ 600:
* [http://www.w3schools.com/css/css_rwd_viewport.asp About the viewport]
 
===== Get offsets of viewport =====
 
* [https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY Window.scrollY] & [https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollX Window.scrollX]
Line 560 ⟶ 606:
* ''[http://stackoverflow.com/questions/9271747/can-i-detect-the-user-viewable-area-on-the-browser Can I detect the user viewable area on the browser?]''
 
===== difference between heights =====
 
* http://stackoverflow.com/questions/762394/firefox-get-actual-screen-___location-of-viewport &ndash; window.outerheight - window.innerheight
* [https://www.w3schools.com/js/js_window.asp JavaScript Window - The Browser Object Model] &ndash; explains how to get window size via window.innerHeight & window.innerWidth
 
===== scrollTop =====
 
* [https://api.jquery.com/scrollTop/ scrollTop()]
Line 577 ⟶ 623:
* [http://stackoverflow.com/questions/19618545/body-scrolltop-vs-documentelement-scrolltop-vs-window-pagyoffset-vs-window-scrol body.scrollTop vs documentElement.scrollTop vs window.pagYOffset vs window.scrollY]
 
===== Find center of viewport =====
 
* [http://stackoverflow.com/questions/23453613/to-find-center-of-the-viewport-and-store-it-in-variables to find center of the viewport and store it in variables]
* [http://stackoverflow.com/questions/210717/using-jquery-to-center-a-div-on-the-screen Using jQuery to center a DIV on the screen]
 
==== Set viewport position ====
 
* [https://www.w3schools.com/jsref/met_win_scrollto.asp Window scrollTo() Method]
* [https://www.w3schools.com/jsref/met_win_scrollby.asp Window scrollBy() Method]
 
==== A possible solution ====
 
The functionality I'm trying to add to this script is to reposition the viewport to restore it to where it was in the text after some text has been hidden or unhidden.
Line 593 ⟶ 639:
I've been searching for any and all pages that can explain any part of the problem, and have listed the ones I've found so far [[#Save and reset the viewport position relative to its topmost element|above]].
 
===== Talk-through 1 =====
{{Further|Pseudocode}}
Maybe this approach would work:
 
Line 605 ⟶ 652:
# Use that offset to reposition the viewport using [https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop scrollTop]
 
===== Talk-through 2 =====
{{Further|Pseudocode}}
 
Put another way:
 
Line 621 ⟶ 670:
# Set the viewport position relative to the targetElement, by offsetDifference
 
=== Adjust viewport position by difference between height of anno elements above viewport before and after the hide or show ===
 
From [[Wikipedia talk:WikiProject JavaScript#I'm stumped: How do you save a ___location in the viewport to reposition the viewport later?]]:
Line 660 ⟶ 709:
: This looks way more efficient than [[User_talk:The_Transhumanist/anno.js#A_possible_solution|the approach I've been working on above]]. Thank you. I'll see what I can do with it. [[User talk:The Transhumanist|<i>The&nbsp;Transhumanist</i>]] 23:38, 3 June 2017 (UTC)
 
==== Complication ====
 
{{ping|Evad37}} I inserted the code that you provided (above) into [[User:The Transhumanist/anno.js|the script]], and the script repositioned the viewport in a surprising way.
Line 686 ⟶ 735:
 
I look forward to your reply, [[User talk:The Transhumanist|<i>The&nbsp;Transhumanist</i>]] 16:01, 8 July 2017 (UTC)
:I'm not sure if this is the problem, but you probably shouldn't be creating and removing portlet links each time the subroutines run – just define it once, at the start. Something like
<syntaxhighlight lang="javascript">
// get the value of our status variable from memory
// (this tells us what mode to start in)
var annostatus = localStorage.getItem('annostatus');
 
// run the function corresponding to the current status
== Find/verify non-li list-lead entries ==
if ( annostatus === "hide" ) {
//Create portlet link in (show) state
mw.util.addPortletLink( 'p-tb', '#', 'Annotations \(show\)', 'ca-anno', 'Show the annotations', 'a' );
//then do the hiding
annoHide();
} else {
//Create portlet link in (hide) state
mw.util.addPortletLink( 'p-tb', '#', 'Annotations \(hide\)', 'ca-anno', 'Hide the annotations', 'a' );
//then do the showing
annoShow();
}
 
$('#ca-anno').click( function ( e ) {
e.preventDefault();
var $portletLink = $('#ca-anno').find('a');
var portletTitle = $portletLink.attr('title');
var portletText = $portletLink.text();
if ( portletText.includes('hide') ) {
//toggle portlet title/text
$portletLink.attr('title', portletTitle.replace('Hide', 'Show')).text(portletText.replace('hide', 'show');
//then do the hiding
annoHide();
} else {
//toggle portlet title/text
$portletLink.attr('title', portletTitle.replace('Show', 'Hide')).text(portletText.replace('show', 'hide');
//then do the showing
annoShow();
} );
} );
</syntaxhighlight>
And remove the portlet creation/removal code from within annoHide and annoShow. - <u>'''[[User:Evad37|Evad]]''37'''''</u>&nbsp;<span style="font-size:95%;">&#91;[[d:w:User talk:Evad37|talk]]]</span> 02:32, 9 July 2017 (UTC)
 
=== Find/verify non-li list-lead entries ===
 
=== Fix annotation delimiters (to ndashes) ===
 
See [[User:GregU/dashes.js]].
 
= Discussions =
 
Post new discussion threads below.
 
== The Bug Report ==
 
Hi, {{ping|The Transhumanist}}. I've discovered an unintended side-effect caused by a line of code in your script, or should I say ''the'' line of code.
 
<syntaxhighlight lang="JavaScript>
cont.outerHTML = cont.outerHTML.replace(/(<li>.*?)( –.*)/g,'$1<span class="anno">$2</span>');
</syntaxhighlight>
 
This code strips action handlers from DOM elements which are descendants of <code>mw-content-text</code>. This notably affects 'buttons', such as the 'show/hide' button in the following templates:
 
{{collapse top}}
Peekaboo.
{{collapse bottom}}
 
{{Fragaria|state=expanded}}
 
You ''might'' be able to prevent this by iterating through <code>&lt;li&gt;</code> elements, like so:
 
<syntaxhighlight lang="JavaScript">
$("#mw-content-text li").each(function()
{
$(this).html($(this).html().replace(/(.*?)( –.*)/g,'$1<span class="anno">$2</span>'));
});
</syntaxhighlight>
 
Let me know if this helps! Regards, <span style="font-family:Times New Roman">[[User:Guywan|''GUYWAN'']] ( [[User talk:Guywan|''t'']] &middot; [[Special:Contributions/Guywan|''c'']] )</span> 12:20, 6 June 2019 (UTC)