This is an archive of past discussions about MediaWiki:Common.js. Do not edit the contents of this page. If you wish to start a new discussion or revive an old one, please do so on the current talk page.
For the main page hack that removes stuff on the main page, why not just use the page title mentioned in the HTML header of every page?
For example, this was on this page in the html sourcecode:
<script type= "text/javascript">
var skin = "monobook";
var stylepath = "/skins-1.5";
var wgArticlePath = "/wiki/$1";
var wgScriptPath = "/w";
var wgServer = "http://en.wikipedia.org";
var wgCanonicalNamespace = "MediaWiki_talk";
var wgPageName = "MediaWiki_talk:Monobook.js";
var wgTitle = "Monobook.js";
var wgArticleId = 725652;
var wgUserName = "GeorgeMoney";
var wgUserLanguage = "en";
var wgContentLanguage = "en";
</script>
Is javascript even needed for some of this anymore? Per rev:17119 there is now a css class for each page.
The following, hypothetically, could be added to MediaWiki:Monobook.css:
As this section is UNDOCUMENTED and UNMAINTAINED, perhaps it should be removed and started over, with appropriate use of the javascript variables, as well as taking advantage of per-page CSS support. IMHO --Splarka (rant) 07:39, 17 December 2006 (UTC)
I support this. Many browsers that have javascript disabled probably do not have css disabled. I have not used any browser that lets you disable CSS (if it has CSS in the first place) so the amount of users affected by this "hack" will be higher. It would also be much cleaner and easier to update by moving it to the monobook.css file. GeorgeMoney (talk) 01:54, 18 December 2006 (UTC)
History and 'My Contributions'
I'm not sure if this is the right place to report this, but the worst that can happen is someone will say 'This isn't the right place to post this'. Anyway, I'm using Internet Explorer 6, and the content boxes on the history pages, and 'My Contributions' are compressed so that I can't see the text. I'm wondering if this is a problem that everyone with Internet Explorer 6 gets, and if this is something that can be fixed here?--Jcvamp
Please change ta['ca-nstab-wp'] = new Array('c','View the project page'); to ta['ca-nstab-project'] = new Array('c','View the project page');. That is the name of the Project tab. Thank you. --Thunderhead09:21, 16 August 2006 (UTC)
fr.wikipedia.org uses a nice hack in its monobook.js to add a toolbar button which opens a little popup window to ask for table dimensions, and to insert the table as wikitext into the edit box. Try it out by editing a page and clicking the table button (first from the left). Should we copy this idea?--Eloquence*14:14, 25 August 2006 (UTC)
See [2]. Within these scripts there is also a simple script ("Reference divs") that makes the auto-generated references appear with a scrollbar so that they won't take up so much room. I'd like to add this here.Voice-of-All10:05, 26 August 2006 (UTC)
I coded up a replacement for the createNavigationBarToggleButton function at MediaWiki:Monobook.js which allows one to specify if the box should be open or closed by default. It can be found at [3] if you want to check the code. Once it's added to Monobook.js (replacing the function already there), using NavFrameDefaultHide instead of NavFrame will force the box to be hidden by default, and using NavFrameDefaultShow instead of NavFrame will force the box to be shown by default. I intend to add the code to Monobook.js in a few days if nobody complains. --cesarb16:59, 2 September 2006 (UTC)
Hold on. Two months ago I proposed a more general enhancement to the functionality of the navigation bars above; test code is here, sandbox here. My code is currently written with different class names. The idea was to allow alternate texts for the button (implemented with the "title" attribute), and to allow "inline" dynamic nav content. I would really like to see some work on getting this functionality implemented.
On defaults, I don't think it's a good idea to build the show-default into the name of the header class; in my test code I indicate a show-default through a separate class used in addition to the header class. Gimmetrow17:58, 2 September 2006 (UTC)
Where the hell are the docs for all of the NavFrame stuff? I've been searching for about 45 minutes now. —MichaelZ. 2006-10-31 04:01 Z
oh no!
The new "section 0 edit link" is really ugly and messes up alot of pages pushing text a long way. It is really obtrusive and messes with already installed scripts.
If you do want to add one please add it higher so it doesn't mess up anything else and remove that part from the monobook.css you can add it to the div's style.
Using an older version of Safari, this turned most article text smaller and gray, and also caused some sentences to look like a hyperlink (but when clicked they went nowhere). Seems better after the revert. Carl Lindberg01:34, 3 September 2006 (UTC)
Yes, this new code created links in some odd places on some pages (in Safari 2.0.4). However, Edit Top, which I have been using, doesn't have a look consistent with the other edit tabs. I agree this should be part of the site software, however it also shouldn't be beta tested live on the site. I've been asking for two months to have my own codes tested and rolled in... Gimmetrow01:46, 3 September 2006 (UTC)
I've tried the updated version of Edit Top and the edit tab seems to be consistent with the others on the page. The edit link is showing up on diff and history pages, however. Gimmetrow03:53, 3 September 2006 (UTC)
Well, for reference, here is the old Edit Top script:
If people really want to do this, it should probably be on the right side of the page above the border-bottom for the headline for the section you will be editing, like the other section-edit edit links are. Personally I would never use it, but from answering help desk questions it does seem to be a point of confusion for at least a few people, some even thinking the top section was some locked section only editable by special people. - cohesion17:46, 5 September 2006 (UTC)
Helper function for user scripts
I would like this funtion to be included so it's easier for users to include user scripts. —The preceding unsigned comment was added by AzaToth (talk • contribs).
/*Takes the wikipage "page" and includes it's raw text as javascript.*/
function import_external(page){
if( document.createElement && document.childNodes ) {
var url =
'http://en.wikipedia.org/w/index.php?title=' +
page +
'&action=raw&ctype=text/javascript';
var scriptElem = document.createElement('script');
scriptElem.setAttribute('src',url);
scriptElem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
}
I don't know, is this generally done for user scripts? The script would break on non-monobook skins, and there is no common site-wide local javascript. Would it be fine if users just added this helper script when they are using scripts that call it? —Mets501 (talk)18:14, 21 September 2006 (UTC)
/*** [[User:Lightdarkness]]'s include function ***/
function inc (file) {
var lt = String.fromCharCode(60);
var gt = String.fromCharCode(62);
document.writeln(lt+'script type="text/javascript" src="/w/index.php?title='+file+'&action=raw&ctype=text/javascript&dontcountme=s"'+gt+lt+'/script'+gt);
}
Off course every one can include it in their own script, but it's more tedious, also most people are using code like the one gimmetrow showed, and that's non optimal in at least two ways. First it will need to be reparsed when written, it is much faster to include it directly in the DOM-tree, second, when using document.writeln, the output will be written to the end of the document, generating a non-compatible page (application/xhtml-xml will bail out on such code generally). →AzaToth23:55, 21 September 2006 (UTC)
This was brought up here a month ago, without objection. For such a visually minor change, I don't see the problem with adding some small buttons to the toolbar (and it is not bleeding over or anything). The vast majority of people who edit this site do not even know how to just "add them" or that they need an account, and they don't know javascript either. Some of these buttons are badly needed (ie table, which fr. has). Though perhaps a few could be shaved off just for the sake of simplicity.Voice-of-All19:28, 24 September 2006 (UTC)
Digital_me plans to write a bit of disabling javascript, but I agree with perhaps cutting them down. It is a little mad, and the WYSIWYG will be here reasonably soon. —Xyrael / 19:30, 24 September 2006 (UTC)
Well, I don't think most people would know that there was discussion here. I think that this is a pretty major change, and the discussion should be more publicized. I, for one, oppose them, as they are more unnessecary clutter to the already mostly unused edit toolbar.--digital_me(Talk•Contribs)19:31, 24 September 2006 (UTC)
The table button isn't such a bad idea. But the table code produced by the form popping up needs to be improved. I wouln't want to have newbies entering such ugly defaults for tables. Hey and the template call button wasn't that bad. Too bad it has already been removed again. --Ligulem19:42, 24 September 2006 (UTC)
The template button on the top of the edit window is better than the "Wiki-markup" section below the edit window. --Ligulem19:56, 24 September 2006 (UTC)
Agree with that. But could be dangerous. I fear hordes of angry Wikipedians piling at VPT :). Removing things is always delicate... --Ligulem20:07, 24 September 2006 (UTC)
Many of the buttons are redundant with the wiki markup section, and do we really need a javascript button just to add a ':' ? Gimmetrow19:46, 24 September 2006 (UTC)
I'd say it's useful for new editors. On the other hand coloured text (already removed), left-aligned and centered text are not. —Ruud20:00, 24 September 2006 (UTC)
The : tab is rarely useful to a new editor in article space. By the time an editor runs across a need, they will have seen it on talk pages. Gimmetrow20:03, 24 September 2006 (UTC)
I want to remind people that while these buttons may be very useless to most of us, they are very useful for new editors (who, obviously, have absolutely no clue how to add these buttons to their perosnal monobook.js). —Ruud19:52, 24 September 2006 (UTC)
I am a fairly experienced WP editor. I still think the new buttons are a big help They are easier to use than the codes below the edit box, and easier than typing (or remembering) code. Individuals can quibble about whether some are more helpful than others, but that is mostly personal preference experssed by people who do know how to edit their perosnal monobook.js. Finell(Talk)19:16, 26 September 2006 (UTC)
hem* The new JS-code looks a bit bad (I thought VoA knows JS). Look some comments from me [[5]] (and my corresponding optimized code here, you can also look at the talkpage). I've completly replaced the function marque_tab() for the table button (after all buttons be added) p.s. I've not read any discussion to this relation before, so you can hint me. --Olliminatore12:49, 28 September 2006 (UTC)
I can't do that but you can look my code . Other matter: I think the center, left text align should not be used in normal articles, so remove them from standard of all (maybe <br /> too). --Olliminatore10:18, 3 October 2006 (UTC)
Table button
I have removed the "add table" button from the toolbar. As a piece of code it is incomplete (the popup it generates is awful), and the tables it makes are equally poor. If you are going to develop new components, please submit them to the community for review and debugging before adding them to the core javascript. I don't object to have a table generator - but we can do much better than a quick hack. Thanks, ed g2s • talk13:55, 29 September 2006 (UTC)
Note that all background colour and other styling is (as it should be) done in the stylesheet (.wikitable). Options such as "border width" and "alternate rows" should not be provided. ed g2s • talk14:08, 29 September 2006 (UTC)
Cross post: Hmm, odd. It was still showing up on my toolbar. After my edit I did a hard refresh and it went away - so unless my cache was two days old (possible) - your commenting might not have been enough. Anyway, no harm done. ed g2s • talk14:04, 29 September 2006 (UTC)
Cross post: :Yes, you did have had an outdated cache, as the button already went away thanks to my edit. I'm going to revert your edit, if you don't mind. We either disable that code on the top-most level (as I did it with my edit), or we remove that stuff completely. Keeping some brain dead code there serves not much purpose. --Ligulem14:08, 29 September 2006 (UTC)
First a simple IE detector need to be added. If a user is using IE, then the button should be disabled. As for table appearance, anyone is welcome to fix it with something that looks prettier.Voice-of-All20:01, 30 September 2006 (UTC)
My mentioned version has that feature, for IE (Opera too) the button makes only table sample syntax (from MarkS). (p.s. I don't tested IE for window open, because this function also don't works with my expanded function method) --Olliminatore20:26, 30 September 2006 (UTC)
It crashed my version of IE (IE 6) about 5 minutes ago. Someone who know how should definitely disable the button in IE until the problem is fixed. (It doesn't always crash IE, just sometimes; it's worked for me before, so testing it once in IE isn't enough to indicate the end of the problem.) 147.188.147.47
Why not just the standard control for generating a table you get in word editors, like this? That's just a demo I knocked up in half an hour, but you get the idea. ed g2s • talk11:08, 2 October 2006 (UTC)
Yes, that looks cool, can "you" make this function (with headline and item column option) to a corresponding popup window? That would be it. --Olliminatore15:45, 4 October 2006 (UTC)
Archive
Just a note to all. I have archived some of the contents of this page. If anyone has any objects over this, please feel free to state your concerns. --Siva1979Talk to me04:38, 25 September 2006 (UTC)
Page not found
I propose we add:
addOnloadHook(function(){
if(document.getElementById('noarticletext')) {
var pgs = wgPageName.replace(/_/g, " ");
document.title = pgs+" - Page Not Found - Wikipedia, the free encyclopedia";
document.getElementById('searchInput').value = pgs;
}
});
Which does:
Adds a "page not found" message to the page title (which is pretty useful, because sometimes I open many pages in tabs and want to know if any are non-existant)
And adds the page title into the search box just incase someone typed something wrong and wants to fix their mistake.
Both of these should be submitted to bugzilla as enhancements and implemented in PHP, not JavaScript hacks. ed g2s • talk21:38, 7 October 2006 (UTC)
addLoadEvent versus addOnloadHook
Is there a reason that the code here doesn't use addOnloadHook that's defined in wikibits.js? Instead, addLoadEvent is defined and used. They would seem to do the same thing, but I might be missing a difference since I'm not very knowledgeable about JS. --68.142.14.9114:59, 28 September 2006 (UTC)
The extra buttons in the toolbar, though useful, are causing serious lag in the edit page load time. I first tried adding these extra buttons (stolen from the Hebrew Wikipedia) several months back, and noticed the problem then, as did others. The problem still exists. Currently, for me at least, the toolbar takes 5+ seconds to load. — BRIAN0918 • 2006-10-11 02:25Z
Me neither. IIRC I noticed a very minor lag the first time they had to load (but far below 5 seconds). Since then, they are in the cache of my Firefox 1.5.0.7 (Windows XP) and everything loads immediately (I still have them right now even though they have been removed already by Brian0918, because I didn't force a cache update yet). --Ligulem08:42, 11 October 2006 (UTC)
These should really be added back. The toolbar can be disabled via prefrences. Many other wikipedias, like RU and FR, already have such buttons. I don't see a need to remove a few very useful sitewide buttons due to one user having them take too long to load.Voice-of-All16:21, 15 October 2006 (UTC)
Does the loading of the toolbar prevent editing? If not I don't see a problem with it loading so slowly. Even the standard toolbar can take 2 or 3 seconds to load when I'm running BitTorrent in the background. —Ruud16:35, 15 October 2006 (UTC)
No, it just loads in the background. Actually, the bar loads near instantly, its the images that take a while sometimes, but it does not hang the page or anything, they just appear one by one.Voice-of-All16:39, 15 October 2006 (UTC)
Please restore the extra buttons. They were very helpful. I experienced no delay in the edit box opening, and did not notice any delay in the button graphics being rendered (but a 5-second delay in that, if there was one, would not delay my editing). Finell(Talk)07:22, 16 October 2006 (UTC)
I agree: Bring back the buttons! They are very useful, and the only delay present is caused by loading the images. Albany NY13:22, 16 October 2006 (UTC)
I propose we add the buttons back and post a message on WP:VPT and WP:AN if anyone is experiencing the problems Brian0918 describes. Non-instantaneous loading should only happen sporadically when the images have disappeared from the browser cache, however it might also be possible that the Javascript executes too slowly one some computer/browser configurations. —Ruud17:39, 16 October 2006 (UTC)
There is a strong concensus, in this and another item on this Talk page, for restoring the additional edit toolbar buttons. Will it be done? Finell(Talk)20:57, 26 October 2006 (UTC)
Not a fan. Makes finding the few useful buttons (sig and redirect) harder. But I appear to be in the minority, so how can I remove these from my monobook? Should the "mwCustomEditButtons = false;" thing still work? --Spangineerws(háblame)22:35, 4 November 2006 (UTC)
Original code: Setting the style attribute works in Mozilla, but IE forgets it. The result was that the triangle appeared immediately to the left of the header text in IE.
Patched code: Assigning the style as an attribute forces IE to remember that the element should be floated. Mozilla ignores "styleFloat" and will still display the triangle correctly; IE ignores "cssFloat" and will still display the triangle correctly.[6]
I have tested this patch on a local, bleeding-edge copy of MediaWiki from SVN using IE6 and Ffx2: no browser recorded a javascript error.
From my experience coding this and the above source, I believe that this patch will work on all browsers.
What do people think of the pl.wiki's "auto edit summary" thing? (See [7] for example, and try clicking on one of the green boxes below the edit summary field.) Is it worth implementing here? It might encourage people to use edit summaries more, because it'll be very easy to add. It will probably also help newbies who aren't sure what to type in the edit field by giving examples. —Mets501 (talk)18:22, 7 November 2006 (UTC)
I've implemented several proposed fixes brought up at the village pump and the various Category:Wrong title templates. The code is now more complex, but I believe it does the Right Thing in almost every case. Its operation and downsides are detailed at User talk:Interiot/js/RealTitle.js. If a few more days pass without any issues brought up, I'd like to add it to the global monobook.js. --Interiot06:17, 21 November 2006 (UTC)
I added this to the common.js now. Now everyone should see that pages like mod_perl, Category:x86 microprocessors, and User:rambot show up with lowercase and underscores as needed (turn off javascript in your browser to see how they were displayed before). Pages like Softimage XSI shouldn't have their main title changed, but should have the title at the very top of the browser (or in the tab) changed. --Interiot04:18, 24 November 2006 (UTC)
Do you know how much confusion this has caused? And I'm only talking about myself here; think about all the other people that may have been racking their brains out over this. This thing shouldn't be here without more discussion first; if capital letters aren't technically possible for whatever reason, we shouldn't be making adjustments to make article titles look correct. Did nobody think that four people don't speak for everybody that has an account on Wikipedia? I don't want this; I want to see the {{lowercase}} tags in articles as they should appear. Either revert this change and start a new discussion where more people are likely to comment, or give me a way to make article titles look the way I want them to look. JDtalk20:38, 29 November 2006 (UTC)
You can disable this now by adding disableRealTitle = 1; to your monobook.js. The idea behind hiding {{lowercase}} is that the only reason they're included on articles is because the title displays incorrectly. Once the title displays correctly, the reader doesn't need to be bothered about the internal limitation on that page anymore... is that incorrect? (just to clarify: it still appears on articles that don't have a pasteable title, for instance {{pipe in title}}) As this discussion notes, multiple wikis have taken up this feature before en.wikipedia.org did, and there were a group of people who wanted English Wikipedia to have it earlier. The feature was discussed in numerous places... [8][9][10] but I'd be happy to discuss it WP:VPT or elsewhere again if you'd like.
According to the Signpost, this page is now deprecated. All of this should be copied to MediaWiki:Common.js, and all of the stuff that we still want to keep specific only to Monobook.js should be added using a skin test with the skin variable. —Mets501 (talk)21:19, 21 November 2006 (UTC)
Looks like it's already working. (eg. [11] mentions that it's pulling its data from both MediaWiki:Common.js and MediaWiki:Monobook.js). If there's no monobook.js-specific code here, can we just move this page there? --Interiot21:36, 21 November 2006 (UTC)
Copied (not moved) the JS back to MediaWiki:Monobook.js for now. If common.js suddenly does start working, the code might be included twice, perhaps with worse sideeffect than having no JS for a while. —Ruud00:05, 22 November 2006 (UTC)
I'd suggest to change the max. before collapsing to 2, or even 3, rather than just on 1 (current NavigationBarShowDefault setting). -- User:Docu
If this is what makes some templates with the show/hide thing in them automatically close, could you revert this please, or tell me how I could make templates that are showing automatically stay hidden? JDtalk06:45, 1 December 2006 (UTC)
Some templates assume the collapse count is either 0 or 1. It's unfortunate, but raising it above 1 will break some behaviour somewhere. Gimmetrow02:23, 18 December 2006 (UTC)
if (window.showModalDialog && document.compatMode && document.compatMode == "CSS1Compat")
{
var oldWidth;
var docEl = document.documentElement;
function fixIEScroll()
{
if (!oldWidth || docEl.clientWidth > oldWidth)
doFixIEScroll();
else
setTimeout(doFixIEScroll, 1);
oldWidth = docEl.clientWidth;
}
function doFixIEScroll() {
docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? "hidden" : "";
}
document.attachEvent("onreadystatechange", fixIEScroll);
attachEvent("onresize", fixIEScroll);
}
deprecating addLoadEvent
Should we remove adLoadEvent, as it only duplicates the functionality of addOnloadHook (defined in wikibits.js). This will break the user scripts of a few dozen users. —Ruud15:51, 26 November 2006 (UTC)
Maybe make it a thin wrapper around the latter at first, and add a comment about it being deprecated. Do the same here and here, and fix the call here. Then contact the users still using it and suggest they change their scripts, and wait a bit. Before finally removing it completely an admin can fix the remaining instances, but it's probably more polite to ask before poking around other people's user scripts. —Ilmari Karonen (talk) 17:42, 26 November 2006 (UTC)
I've noticed two problem with this fix, both relating to when a page using it is edited. The first occurs when editing either the whole page or the "0" section. The correcting of the capitalisation occurs, but the "Editing " is not added to the beginning, nor it the "(section)" part for editing the "0" section. The second occurs when editing any other section in which no correction occurs but the "Editing " remains, effectively doing nothing at all.
It doesn't happen if you're editing but not previewing the article. But anyway...
What's the best thing to trigger off of, for the script to know it's in editing mode? Is wgIsArticle appropriate? --Interiot11:17, 5 December 2006 (UTC)
I suggest checking if document.location contains /wiki/ or /w/ at the beginning of the path.
Monobook emits wgServer and wgScriptPath as global javascript variables; I'm not sure if other skins do the same. It might be better to just hard-wire it to http://en.wikipedia.org/w/ in that case. --DavidHOzAu03:35, 10 December 2006 (UTC)
That catches a lot more than editing (e.g., history, and even articles themselves if a URL like http://en.wikipedia.org/w/index.php?title=EBay is used). For history and diff pages, wgIsArticle is also set to false. If you want to catch only edit pages, perhaps check for "action=edit" and "action=submit" (the latter for previews) in the URL? -- Jitse Niesen (talk) 04:55, 10 December 2006 (UTC)
Ooops, I forgot about page actions. Ok then here's the full-blown code snippet:
if (document.location.indexOf(wgServer + wgScriptPath + "/") == 0) {
var action_matches = document.location.match( /action=([^&]+)/ );
var action = (action_matches == null) ? 'view' : action_matches[1];
switch(action) {
case 'history':
case 'print':
case 'purge':
case 'render':
case 'view':
isPreview = false;
break;
case 'submit':
isPreview = true;
break;
default: // nothing to do
return;
}
}
// rest of code here
Right, it would be good to keep the code as simple as possible. Yes, wgIsArticle's value does vary a bit in history/diff/move/protect/delete, but it doesn't matter what its value is under those situations, because true or false, we can't display the RealTitle in those cases anyway. wgIsArticle's value really only matters when RealTitleBanner is rendered on screen, which is: 1) when viewing an article, and 2) when editing an article, and its value is good in both cases. So wgIsArticle should work fine, I think. --Interiot01:50, 11 December 2006 (UTC)
NavFrame styles limitation
As it stands right now, NavFrame limits the use of class tags on elements to ONLY the Nav* classes. You cannot do something like class="NavFrame messagebox standard-talk". This is because of the following lines:
if (NavChild.className == 'NavPic') {
...
if (NavChild.className == 'NavContent') {
...
if (NavChild.className == 'NavPic') {
...
if (NavChild.className == 'NavContent') {
...
if (NavFrame.className == "NavFrame") {
...
if (NavFrame.childNodes[j].className == "NavHead") {
Each of these should be changed to regular expression matches, respectively:
if (NavChild.className.match(/(\s|^)NavPic(\s|$)/)) {
...
if (NavChild.className.match(/(\s|^)NavContent(\s|$)/)) {
...
if (NavChild.className.match(/(\s|^)NavPic(\s|$)/)) {
...
if (NavChild.className.match(/(\s|^)NavContent(\s|$)/)) {
...
if (NavFrame.className.match(/(\s|^)NavFrame(\s|$)/)) {
...
if (NavFrame.childNodes[j].className.match(/(\s|^)NavHead(\s|$)/)) {
Also, after looking into it further, there seem to be some inconsistencies in the file. Some parts use function hasClass, which is horribly inefficient:
function hasClass( element, className ) {
var Classes = element.className.split( " " );
for ( var i = 0; i < Classes.length; i++ ) {
if ( Classes[i] == className ) {
return ( true );
}
}
return ( false );
}
It could easily be rewritten as:
function hasClass(element, className) {
return element.className.match((new RegExp("(\\s|^)"+className+"(\\s|$)")));
}
After making that change, the previous rewrites I mentioned (such as if (NavChild.className.match(/(\s|^)NavPic(\s|$)/)) {) should be reformed (ie. if (hasClass(NavChild, 'NavPic')) {). ♠ SG→Talk20:43, 25 December 2006 (UTC)
I've modified the collapsible tables to use literal regular expressions (which are faster than dynamically created RegExp-obejcts [13]). I'm having trouble changing NavFrame, though. —Ruud23:47, 25 December 2006 (UTC)
The results were pretty consistently something like:
hasClass1() x 10000: 532 ms
hasClass2() x 10000: 818 ms
hasClass3() x 10000: 765 ms
hasClass4() x 10000: 523 ms
So, the regex version is fastest, but only if you can avoid recompiling it every time. I didn't see a consistent difference between hasClass2 and hasClass3, but hasClass1/4 were always about 30% faster than the others. Feel free to rerun this stuff yourself. The differences between the versions are:
hasClass1: Compiles regex, uses reCache to avoid recompiling
hasClass2: Compiles regex every time
hasClass3: Uses split on space and equality check
hasClass4: Compiles regex, uses reCache, avoids an extra function call for regex cache lookup
Another possible version would use indexOf, but I don't think it's worth writing it. Since the number of iterations of this thing will almost certainly be 2 orders of magnitude less than 10000, I can't see this stuff making a huge difference to load time. My feeling is that "hasClass" should remain a function, for convenience, and it should be implemented in the most readable way. Mike Dillon17:16, 26 December 2006 (UTC)
P.S. I just tested the capture v. no capture versions by adding hasClass5:
function hasClass5 (element, className) {
return element.className.match(
new RegExp("(\\s|^)\\Q" + className + "\\E(\\s|$)"));
}
It made no consistent difference. It was a tiny bit faster to avoid the capture, but once again, the scale of this thing makes it moot. That doesn't mean that we shouldn't use the fastest one, it just means it doesn't make a significant difference. Mike Dillon17:20, 26 December 2006 (UTC)
Just for kicks, I decided to reimplement part of Perl's Benchmark.pm in Javascript:
compareAll(10000, {
"re+cache": function () { hasClass1(test, "a") },
"re+nocache": function () { hasClass2(test, "a") },
"split": function () { hasClass3(test, "a") },
"re+cache+onefunc": function () { hasClass4(test, "a") },
"re+nocache+capture": function () { hasClass5(test, "a") },
"re+literal": function () { test.className.match(/(?:^|\s)a(?:$|\s)/) },
});
It is indeed the fastest, coming in at about 10-15% faster than the one-function caching version (hasClass4). However, like I said before, I think the value of having this as a function outweighs the value of having the fastest implementation, given that the order of magnitude is much lower than 10000. Mike Dillon18:47, 26 December 2006 (UTC)
Cool! (Even though the outcome doesn't really surprise me.) I initially planned to comment on the "horrible inefficiency" of my hasClass function, but then decided I did like the elegance of regular expressions in JavaScript. —Ruud20:11, 26 December 2006 (UTC)
At the risk of sounding like I'm talking to myself... I've removed the previous code samples out of this discussion. You can see them at User:Mike Dillon/NavFrame test. The summary is that the testing results consistently show the following performance order:
Constant regex (Ruud's version)
hasClass() implemented with regex cache (my version, a.k.a. hasClass4)
hasClass() implemented with split (old version, a.k.a. hasClass3)
hasClass() implemented with regex and no cache (SG's version, a.k.a. hasClass2)
There was a little variance in whether the split or uncached regex version were faster, but in most of my test runs the split version was faster than SG's version (one of the results shown above was an exception to this). I'm obviously partial to my version, because it is fast enough compared to the constant regex version and allows the function to be reused. Mike Dillon20:21, 26 December 2006 (UTC)
Since this stuff is obviously browser specific, I tested this again in Firefox 2.0 (I was using Galeon/Mozilla 1.7). In Firefox, the split version is consistently the slowest. The caching versions are always faster than the non-caching versions and the constant regex is always fastest. Mike Dillon20:28, 26 December 2006 (UTC)
Thanks! After a discussion on Ruud's talk page, I'm pretty sure I figured out the problem he was having with the regex matching code for the NavFrame structures. I believe the issue was that the code was calling ".className.match()" on all the child nodes of the NavFrame and some of them were text nodes, not elements (which means they don't have ".className"). For me, this is yet another reason to retain the hasClass() function instead of using constant regexes. Mike Dillon16:05, 27 December 2006 (UTC)
Long response
Ah, great tests! I believe I did exaggerate in saying that the function is slow, so I apologize for that. Good move with the cache idea and ?:; your function is quite superior to mine.
Failure
However, actually testing the result of your regular expression ALWAYS returns false/null. This is due to using quote: \Q...\E. As far as I know, JavaScript regexp does not support this. That's alright, though, because valid classNames never contain any metacharacters (except -, which is useless without []).
Optimized optimization
I ran some tests of my own, and optimized your function. I created four variations, but only one of them turned out faster than yours:
var hasClass9 = (function () {
var reCache = {};
return function (element, className) {
return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
};
})();
Now, on average, Internet Explorer 6/7 and Firefox 2.0 show no difference whatsoever between my function and yours, so I'll just show one of IE7's results, while skipping a few of the slow ones (note: in Firefox, I had to test each function one at a time; it seems Firefox executes scripts slower as they progress, I assume this is a memory issue as Firefox has always had):
Edit: These Internet Explorer 7 results are from before I removed \\Q...\\E. Strangely enough, after cleaning that out, Internet Explorer started running onefunc9 faster than onefunc4. Weird!
re+cache x 10000: 441 ms
split x 10000: 611 ms
re+literal x 10000: 420 ms
re+cache+onefunc4 x 10000: 351 ms
re+cache+onefunc9 x 10000: 351 ms
Internet Explorer 7
Rate
split
re+cache
re+literal
re+cache+onefunc4
re+cache+onefunc9
split
16367/s
--
-38.5%
-45.5%
-74.1%
-74.1%
re+cache
22676/s
+27.8%
--
-5%
-25.6%
-25.6%
re+literal
23810/s
+31.3%
+4.8%
--
-19.7%
-19.7%
re+cache+onefunc4
28490/s
+42.6%
+20.4%
+16.4%
--
0%
re+cache+onefunc9
28490/s
+42.6%
+20.4%
+16.4%
0%
--
Ah, but then I tested it on Safari and Opera -- and trust me, I'm as surprised as you:
re+cache x 10000: 403 ms
split x 10000: 494 ms
re+literal x 10000: 411 ms
re+cache+onefunc4 x 10000: 362 ms
re+cache+onefunc9 x 10000: 277 ms
Safari
Rate
split
re+cache
re+literal
re+cache+onefunc4
re+cache+onefunc9
split
20243/s
--
-20.2%
-22.6%
-36.5%
-78.3%
re+cache
24331/s
+16.8%
--
-2%
-13.5%
-48.4%
re+literal
24814/s
+18.4%
+1.9%
--
-11.3%
-45.5%
re+cache+onefunc4
27624/s
+26.7%
+11.9%
+10.2%
--
30.7%
re+cache+onefunc9
36101/s
+43.9%
+32.6%
+31.3%
23.5%
--
Opera is even crazier, look at how fast it does the split function:
re+cache x 10000: 260 ms
split x 10000: 190 ms
re+literal x 10000: 231 ms
re+cache+onefunc4 x 10000: 240 ms
re+cache+onefunc9 x 10000: 150 ms
Opera 9
Rate
re+cache
re+cache+onefunc4
re+literal
split
re+cache+onefunc9
re+cache
38462/s
--
-8.3%
-12.6%
-36.8%
-73.3%
re+cache+onefunc4
41667/s
+7.7%
--
-3.9%
-26.3%
-60%
re+literal
43290/s
+11.2%
+3.8%
--
-21.6%
-54%
split
52632/s
+26.9%
+20.8%
+17.7%
--
+26.7%
re+cache+onefunc9
66667/s
+42.3%
+37.5%
+35.1%
-21.1%
--
Better testing
Regardless, this is a highly unrealistic test case. More often than not, we will only be looking for a specific class a few times per page (on a busy talk page, with a few project headers, let's say 1-4). To simulate this, we'll pick a random character each time the function is called (still unrealistic, as we won't be doing 10000 of these with 27 choices). So, instead of searching for "d": String.fromCharCode(97 + Math.round(Math.random() * 25).
With this test in Opera, re+cache+onefunc9 wins every time by 30-40%. re+cache+onefunc4, split and re+cache seem to vary, randomly trading places on each try. re+nocache and re+nocache+capture are a whopping 260% slower than onefunc9.
Firefox shows me that re+cache+onefunc9 bests re+cache+onefunc4 again, but only by about 5-20%. Like Opera, the nocache functions are the slowest, by about 120%.
Internet Explorer is faster than Firefox overall, except that split is the slowest, at around -80%.
Safari showed results similar to Internet Explorer, except split was at -115%.
Thanks for the catch on \Q...\E. I obviously didn't to any functional testing, just performance testing ;) You're right that the lack of quoting shouldn't be a problem in practice, since valid CSS class names can't contain any metacharacters. I was just being paranoid. Thanks also for the extra testing. So correct me if I'm wrong, but the difference between hasClass4 and hasClass9 is that hasClass9 substitutes an extra array access for an assignment? I reran the same tests on Linux and the no-assign version is faster there too, so I guess we have a winner. Mike Dillon01:54, 28 December 2006 (UTC)
Yes, it seems pretty weird. It's just that the JavaScript implementations vary widely from browser to browser. Oh, one other thing. In response to the error that occurs when trying to .className.match() on an element which doesn't have className (such as a text node, though you shouldn't be doing that in the first place), a simple if (element.className) could be added, and that prevents the browser from trying to do a match. ♠ SG→Talk02:13, 28 December 2006 (UTC)
Exactly what I was thinking. I think the value of being able to blindly call hasClass() on everything in .childNodes makes it worth having the .className check in the function.
However, I just realized that another way to avoid this is using RegExp.test(String) instead of String.match(RegExp), just as you did in hasClass9(). I pretty sure that calling test with a null argument isn't ever a problem. That way the extra "if" test isn't done in cases where it isn't needed; the miniscule performance hit only happens if you lazily pass a non-Element node to hasClass(). I'd appreciate it if you could test RegExp.test(null) on the browsers you have access to, but I assume it shouldn't be a problem on any of them. Mike Dillon02:22, 28 December 2006 (UTC)
You are right. I tested it on IE6/7, FF2, Opera 9 and Safari; none of them report an error. So, I guess we won't be needing that if statement after all. We won't need to accommodate non-elements though, as that would be the fault of the coder, not the function. ♠ SG→Talk02:40, 28 December 2006 (UTC)
If you mean non-Nodes, I agree. But I think any DOM node, including Text nodes should be testable with this function, for the sake of convenience. Limiting to Element limits usefulness. Mike Dillon02:43, 28 December 2006 (UTC)
Yes, sorry, non-nodes. It'll work on anything that exists (it'll only throw an error if you try to access element.attribute if element does not exist). Oh, I forgot to mention that this also works on IE5.5, but IE5 fails (for other reasons; .test(null) actually works). ♠ SG→Talk02:47, 28 December 2006 (UTC)
I hate to ask, but what failed in IE5? I'm pretty sure IE5 is almost negligible these days, but I couldn't find current browser stats for English Wikipedia. Wikipedia:Browsers still had about 16% IE5 in October 2004...
Well, IE5 doesn't support ?:. It really doesn't conform to the regex specs. It also doesn't have array.push, which is used in your test function (but that is easily fixed). It's pointless to support IE5 anymore; approximately 1% of the world's browser usage is IE5.x, of which the majority is 5.5. With IE7 out and already gaining share, there is no reason to even test with IE5 anymore, due to the workarounds required. Wikipedia doesn't render properly in IE5 anyways, and there are plenty of script errors.
Just by guessing, I'd say Wikipedia's IE5.x usage is at 1-3%. Back in October 2004, the world IE5.x share was approximately 12%. Really, that 1-3% is not worth putting in time and effort to make scripts less efficient. They can still access the site, it just renders improperly and most scripts don't work.
As for my computer, well, I'm using a Pentium 4-M 2.2GHz on Windows XP (actually, TinyXP). I'm guessing I have a faster hard drive and/or RAM, seeing as how your CPU is obviously superior to mine. ♠ SG→Talk04:12, 28 December 2006 (UTC)
I'm not getting an error... I guess we could put an if (!element) { return false } inside the inner function of hasClass() just to be safe. It's weird that you're getting that error and I'm not. Mike Dillon16:42, 28 December 2006 (UTC)
Also, what browser are you testing and where does the page blank? That might give some indication of where the problem is. Mike Dillon16:44, 28 December 2006 (UTC)
FF 2.0.0.1. I've added a test for a non-existant element, but now NavFrame is broken? (The show/hide button doesn't appear.) —Ruud17:30, 28 December 2006 (UTC)
I assume this is fixed, am I correct? I don't see an additional if statement and all of the collapsible elements seem to be working in your sandbox. ♠ SG→Talk19:07, 28 December 2006 (UTC)
Since we're on the topic of optimizing Common.js, I looked through all the code and noticed that there are three places that are calling document.getElementsByTagName() on every iteration of a for loop. In these cases, that function should only be called once, before the for loop. I've made a personal copy of Common.js at User:Mike Dillon/MediaWiki:Common.js that shows the changes in the most recent diff. Mike Dillon18:57, 28 December 2006 (UTC)
Actually, it's faster to only search for getElementsByTagName at each iteration. Why? Because if you do this:
var all = elem.getElementsByTagName('li'); for (...) { ... }
...every time ANY element contained in all is changed even slightly, the entire array has to be updated again. By accessing getElementsByTagName on each iteration, we only update one variable. Here's a good reference:[15]
In most cases, this is faster than caching the NodeList. In the second example, the browser doesn't need to create the node list object. It needs only to find the element at index i at that exact moment.
However, there are some cases where optimization is due, such as:
for(var j=0; b = document.getElementsByTagName("li")[j]; j++) {
This here, in function LinkFA, is actually searching the entire document for list elements. It should actually only be looking for them in the 'p-lang' element:
Except here, I'm not sure whether or not it's faster to cache p-lang or to look it up every time. Time for more execution speed tests? ♠ SG→Talk19:32, 28 December 2006 (UTC)
I'm not sure what you're saying here. From what I can see, document.getElementsByTagName("div")[i] searches for all divs and then indexes into the resulting HTMLCollection on each pass. I don't think you can assume that it would optimize that into "look for the i-th div" on each pass. Is that what you're saying? This isn't a caching thing. It's avoiding repeatedly collecting the divs. The HTMLCollection contains a bunch of pointers to nodes, so I don't see what updating the nodes themselves has to do with that. All of the cases I changed are cases of calling getElementsByTagName() on Document, not on an individual element. Mike Dillon20:46, 28 December 2006 (UTC)
I'm getting a "missing name after . operator". I think you need to use ".className" instead of ".class" in the code if ( document.getElementById( InterwikiLinks[i].class + "-fa" ) ) {. Mike Dillon20:52, 28 December 2006 (UTC)
I just did this quick test in a document with 100 empty divs:
compareAll(1000, {
"fetch-many": function () {
var d;
for (var i = 0; d = document.getElementsByTagName("div")[i]; i++) {
}
},
"fetch-once": function () {
var d;
var divs = document.getElementsByTagName("div");
for (var i = 0; d = divs[i]; i++) {
}
},
});
The results were:
fetch-many x 1000: 4702 ms
fetch-once x 1000: 1305 ms
The result had pretty much the same time profiles in Galeon and Firefox on Linux. Maybe the results will be different in another browser, but I doubt it. Mike Dillon21:20, 28 December 2006 (UTC)
I just tested with 10 divs and "fetch-once" is still faster:
var body = document.getElementsByTagName("body")[0];
var div = document.createElement("div");
for (var i = 0; i < 10; i++) {
body.appendChild(div.cloneNode(false));
}
compareAll(1000, {
"fetch-many": function () {
var d;
for (var i = 0; d = document.getElementsByTagName("div")[i]; i++) {
}
},
"fetch-once": function () {
var d;
var divs = document.getElementsByTagName("div");
for (var i = 0; d = divs[i]; i++) {
}
},
});
The article seems to be assuming that you're manipulating the DOM tree within the loop, such that the content of the NodeList object returned by getElementsByTagName() gets updated deveral times. In that case the method recommended in the article might be faster. In any case, I suspect that an even better solution for such cases would be to copy the content of the NodeList into an ordinary array before the actual DOM-manipulation loop. —Ilmari Karonen (talk) 22:30, 28 December 2006 (UTC)
Go ahead and test it. I'm not sure you're right, since you have to iterate through the whole HTMLCollection followed by the array if you do that, but maybe there's some bookkeeping overhead of iterating through the HTMLCollection while unrelated changes are happening in the DOM. My tests weren't doing any DOM manipulation, so maybe that makes a difference. Mike Dillon22:34, 28 December 2006 (UTC)
This was easy enough to test, so I did it:
var body = document.getElementsByTagName("body")[0];
var div = document.createElement("div");
for (var i = 0; i < 10; i++) {
body.appendChild(div.cloneNode(false));
}
var span = document.createElement("div");
compareAll(1000, {
"fetch-many": function () {
var d;
for (var i = 0; d = document.getElementsByTagName("div")[i]; i++) {
var copy = span.cloneNode(false);
d.appendChild(copy);
d.removeChild(copy);
}
},
"fetch-once": function () {
var d;
var divs = document.getElementsByTagName("div");
for (var i = 0; d = divs[i]; i++) {
var copy = span.cloneNode(false);
d.appendChild(copy);
d.removeChild(copy);
}
},
"fetch-copy": function () {
var d;
var divs = document.getElementsByTagName("div");
var divsCopy = new Array();
for (var i = 0; d = divs[i]; i++) {
divsCopy.push(d);
}
for (var i = 0; d = divsCopy[i]; i++) {
var copy = span.cloneNode(false);
d.appendChild(copy);
d.removeChild(copy);
}
},
});
Well I'll be damned. I ran some tests of my own; mine modified className instead of the whole DOM tree, I figured it would be more realistic, as that's usually what we do on WP.
fetch-many x 1000: 3245 ms
fetch-copy x 1000: 2113 ms
fetch-once x 1000: 1813 ms
Turns out once is a bit faster, with many being the slowest by far. So your original plan to do
var d;
var divs = document.getElementsByTagName("div");
for (var i = 0; d = divs[i]; i++) { ... }
I don't know if my tests were totally representative, but I only saw a 5-15% difference when making the copy, so I'd say the copy may be a micro-optimization for the use cases represented in Common.js. We should keep in mind that the copy is a way to optimize code that does heavy DOM manipulation in a loop, but I don't think the extra complexity is warranted except to fix a known performance problem. Mike Dillon06:37, 29 December 2006 (UTC)
Maybe it's time to start Wikipedia:Javascript as a more long-term place to put performance hints for writing site-wide and personal Javascript. It would be a good place to highlight comparative testing strategies and caveats as well, along with pointers to things like the PeachPit article. Mike Dillon06:40, 29 December 2006 (UTC)
I have to agree; while copying the nodes is faster, we probably won't be doing it 1000 times per page, so the difference is negligible. For the sake of simplicity, I say we should just list the elements once.
As for a WP:JS project, yes, that does sound like a good idea. Instead of just archiving all of these benchmarks, we could copy the important parts (ie. the speed tables) to various subpages of a WP:JS project. Of course, as much as I like the idea (honestly, a place to store real JavaScript optimization tips -- sign me up!), I wonder how much relevance it has to a WP project.
Though, we COULD always start up an actual JavaScript optimization article (not a guide, but rather a "list" of sorts). ♠ SG→Talk08:06, 29 December 2006 (UTC)
/** Main Page Append Complete list Link *******************************************************
*
* Description: Adds a link to the complete list of languages available of the main page.
* Maintainers: [[User:AzaToth]]
*/
if ( wgPageName == 'Main_Page' && wgIsArticle ) {
// Add a "Complete list" link to the "in other languages" box on the main page,
// using some very unstable Javscript.
function mainPageAppendCompleteListLink() {
try {
var node = document.
getElementById( "p-lang" ).
getElementsByTagName('div')[0].
getElementsByTagName('ul')[0];
var strongNode = document.createElement( 'strong' );
var aNode = document.createElement( 'a' );
var liNode = document.createElement( 'li' );
strongNode.appendChild( document.createTextNode( 'Complete list' ) );
aNode.setAttribute( 'href' , 'http://meta.wikimedia.org/wiki/List_of_Wikipedias' );
aNode.appendChild( strongNode );
liNode.appendChild( aNode );
node.appendChild( liNode );
} catch(e) {
// lets just ignore what's happened
return;
}
}
addOnloadHook( mainPageAppendCompleteListLink );
}
Nice work. There is a typo in your comment in the catch block ("happend" for "happened"), and there is no need to recheck wgTitle in mainPageTransform, since it only executes if the title is "Main Page". Mike Dillon22:54, 28 December 2006 (UTC)
Not sure about when it should be executed or not, since the old version is pretty hard to decipher. I was mainly saying that if the outer if statement already checks if ( wgTitle == 'Main Page' ), then the hooks will only be added when that condition is true and it doesn't need to be rechecked inside the hook function itself.
Yea, I thought about that, but the only problem is that I'm not admin (yet for the millionth time), so I can't make edits directly. →AzaToth23:53, 28 December 2006 (UTC)
I was just referring to the fact that you stuck your name on the "maintained by" comment. Just because you can't edit it doesn't mean you don't maintain it. I'm involved with "maintaining" plenty of stuff at work, but the QA team still has to approve releases and the operations team has to actually make the changes ;) Mike Dillon01:48, 29 December 2006 (UTC)
I've changed the check done to make sure the script is only executed on the main page. I'm puzzled by what mainPageTransform does, though. Shouldn't both the if and else if check for mpSmallEnabled (instead of !mpSmallEnabled?)
Actually, Internet Explorer does NOT support textContent, but rather uses innerText. You need to test for innerText first, and then use textContent if that fails. I suggest setting a global var for this, so you don't have to keep testing every time you want to change the text of something. ♠ SG→Talk18:28, 29 December 2006 (UTC)
Oh, I thought also IE did handle DOM level 3. We dont need to test for it before, we just do it in the catch →AzaToth18:45, 29 December 2006 (UTC)
function mainPageRenameNamespaceTab() {
try {
node = document.getElementById( 'ca-nstab-main' ).firstChild;
try {
node.textContent = 'Main Page'; // Per DOM Level 3
} catch(e) {
node.innerText = 'Main Page'; // IE doesn't handle .textContent
}
} catch(e) {
// node not found
}
}
As we now have a Common.js, we could include this module here, to be used for user created modules, was rejected before in Monobook.js because it should be able to be used by everyone, and not only those who where using monobook. →AzaToth17:52, 29 December 2006 (UTC)
/** Import Module *************************************************************
*
* Description: Includes a raw wiki page as javascript,
* used for including user made modules as scripts
* Maintainers: User:AzaToth
*/
function import_module( page ){
try {
var url = wgServer + wgArticlePath.replace( '$1' , escape( page ) ) + '?action=raw&ctype=text/css';
var scriptElem = document.createElement( 'script' );
scriptElem.setAttribute( 'src' , url );
scriptElem.setAttribute( 'type' , 'text/javascript' );
document.getElementsByTagName( 'head' )[0].appendChild( scriptElem );
} catch( e ) {
return;
}
}
Maybe there should be two functions: import_script and import_stylesheet?
The URL isn't correct: this should be wgScriptPath + "/index.php?title=" + escape( page.replace( " ", "_" ) ) + "&action=raw&ctype=text/javascript&dontcountme=s".
I don't think silently ignoring any errors is the correct thing to do in this case.
No it's a string in JavaScript that is outputted as HTML. See the source of this page and see how your personal stylesheet is included. —Ruud22:25, 29 December 2006 (UTC)
(Despite the <nowiki> tags, the &s got lost in your code above.) The extra &s have disappeared in FF's DOM inspector as well, so it indeed seems that the JS src attribute is not interpreted literally as the HTML src attribute. —Ruud22:37, 29 December 2006 (UTC)
Yeah, I saw that. Weird. Anyways, the escaping is a source-level thing. By the time you're in the DOM, everything is raw characters. Escaping ampersands in JavaScript code is only necessary if the code itself is in a raw script tag in the HTML without a CDATA wrapper. Even then, browser quirks let you get away with not escaping there even. Mike Dillon22:44, 29 December 2006 (UTC)
I saw that these were added, which is really cool. Two things though:
The page.replace(" ", "_") is not necessary; escape(page) will make a valid "title" param that MediaWiki can understand
The CDATA stuff in the body of the "style" tag is not needed
Neither of these things will break anything, but they aren't doing anything useful either. As I said, a plain escaped title will work fine. The CDATA thing will just be ignored because the CSS parser sees them as comments. Mike Dillon15:30, 31 December 2006 (UTC)
The CDATA will cause the browser's XML parser not to parse the stylesheet, which is invalid XML due to the presence of ampersands. —Ruud18:21, 31 December 2006 (UTC)
This won't go through the XML parser. It's in raw JavaScript code and direct additions to the DOM are by necessity pre-parsed. It won't have any effect one way or the other. Mike Dillon18:29, 31 December 2006 (UTC)
Because {{click}} is an ugly hack, and messes up screen readers, etc. why not make a JS version?
The benefits would be:
If something like a screen reader was being used, it would just not execute the js and no harm done
There are some browsers that have trouble rendering things like this, but would have no problem using js
..please add more..
Here is a prototype:
/** Click on Image ***********************************************************
*
* Description: Make images clickable to a different location
* than the one set by MediaWiki
* Maintainers: [[User:GeorgeMoney]]
*/
addOnloadHook(function() {
var usebody = document.getElementById('bodyContent') || document;
var divs = usebody.getElementsByTagName('div');
for(var i = 0; i < divs.length; i++) {
try {
if(divs[i].getAttribute('class') != 'click') continue;
var titleurl = divs[i].getAttribute('title').split('URL=');
divs[i].getElementsByTagName('a')[0]
.setAttribute('title', titleurl[0]);
divs[i].setAttribute('title', '');
if(typeof titleurl[1] == 'undefined') continue;
var useurl;
if(titleurl[1].substr(0, 2) == '[['
&& titleurl[1].substr(titleurl[1].length-2) == ']]') {
useurl = titleurl[1].substr(0, titleurl[1].length-2).substr(2);
useurl = wgServer + wgArticlePath.replace('$1', useurl);
} else
useurl = titleurl[1];
divs[i].getElementsByTagName('a')[0]
.setAttribute('href', useurl);
} catch(e) { }
}
});
so you would type <div class="click" title="title to be set after javascript parses URL=http://example.com">[[Image:Myimage]]</div>
Which would then set the href (url) of the link which contains the image to http://example.com, and link's title to "title to be set after javascript parses".
Using wikilinks on the link works too.
I know this might sound complicated, but it is actually quite simple.
I guess to solve the copyright problem we could set the title of the link to the old link's href, like "Please see foo for copright info", or maybe even have it append fromimage=true&oldimage=foo which could add in the contentSub "For information on the image that refered you here, see: foo", etc.. GeorgeMoney (talk) 23:54, 3 January 2007 (UTC)
That wouldn't work on the Main Page, where {{click}} is used to link a picture of Wiktionary's logo to Wiktionary, etc.. --ais523 15:17, 9 January 2007 (UTC)