Wikipedia talk:User scripts
To-do list is empty: remove {{To do}} tag or click on edit to add an item. |
My first proper script
Hey everyone, could I get some opinions on my new tagger script at User:TheFearow/tagger.js? It's my second attempt at a user script (it's a slightly modified version of my User:TheFearow/stubber.js which I no longer use). It allows you to add tags to the top or bottom of a page, it will automatically open the edit form and add the required things, then submit.
Also, what are the requirements for putting things on the scripts page? Do you have to have it hosted as a subpage of the scripts page?
Thanks! Matt/TheFearow (Talk) (Contribs) (Bot) 00:04, 22 June 2007 (UTC)
- As long as it works on articles with spaces in their names (there seems to be no special-casing for this, and it's sometimes needed, so it's worth checking if you haven't already), it looks fine. There aren't any requirements in particular for putting scripts up on the page (apart from obvious common sense), although you should put
// [[Category:Wikipedia scripts]]
at the bottom of the script to help keep track of scripts that have been written; I keep all the scripts I've written in userspace subpages and link to those, which is more useful in a way than putting them as subpages of the project because it makes more transclusion methods (such as importScript) possible for the script. Hope that helps! --ais523 10:47, 22 June 2007 (UTC)
I think there is still some room for improvement:
- use
(wgAction == 'edit')
instead of checking foraction=edit
- edit summary could say which tag was added
- find
document.getElementById('ca-edit')
and then use the edit url from there (
….firstChild.href
) — this will also prevent the script from trying to tag protected pages - I think it would be more convenient to ask for a tag before moving to edit page
- I meant to say about the edit summary, but forgot. Using wgAction is a good idea that I didn't think of, although this isn't going to come up very often. As for ca-edit, I personally don't like that technique that much, because it tends to cause incompatibilities with other scripts. Asking for a tag first is really just a matter of taste. --ais523 13:36, 22 June 2007 (UTC)
Regarding the use of wgPageName
, it's probably best to do encodeURIComponent(wgPageName)
for building the title parameter instead of special-casing individual characters. This will ensure that things work right for pages with non-ASCII characters in their titles. Mike Dillon 16:04, 22 June 2007 (UTC)
- Thanks everyone, i'll implement that now. I wanted to ask for the tag first, however I don't know how to get a parameter from the URL (as in, if I had tag=wikify, hwo would I gt the value of tag?). I'll use the wgAction method, ill change the edit summary. Also, how would I implement the getElementByID method? I'll change the encodeURIComponent now. Thanks everyone! Matt/TheFearow (Talk) (Contribs) (Bot) 22:17, 22 June 2007 (UTC)
- Some answers:
- For getting parameters from the URL, there are a few scripts floating around. See MediaWiki talk:Common.js/Archive May 2007#Query strings for some code. I have a version of my own at User:Mike Dillon/Scripts/params.js, but it is a little heavy for me to recommend it. I was kind of surprised that we don't have one at Wikipedia:WikiProject User scripts/Scripts.
- Not sure what you mean about implementing the
getElementById
method, since it is already part of the DOM interface for the Document
object.
- Mike Dillon 22:54, 22 June 2007 (UTC)
- The idea behind the getElementByID method is that you use document.getElementById('ca-edit').firstChild.href to find the URL of the 'edit' link. I don't like that method, though, partly because I've had problems in the past when some browsers disagree about what constitutes the firstChild (IE's firstChild is often Firefox's 'second child' because of a blank text node in the Firefox DOM). As for getting parameters from the query string, normally I just use either tricks with split() or combinations of substr and indexOf. --ais523 11:42, 25 June 2007 (UTC)
- Thanks, I have implemented most of that. Matt/TheFearow (Talk) (Contribs) (Bot) 22:14, 25 June 2007 (UTC)
- Whenever I need to check a query string, I include a very simple querystring function that I acquired somewhere in the dim past:
function queryString(p) {
var re = RegExp('[&?]' + p + '=([^&]*)');
var matches;
if (matches = re.exec(document.location)) {
try {
return decodeURI(matches[1]);
} catch (e) {
}
}
return null;
}
- Also, you can use document.getElementById('ca-edit').getElementsByTagName('a')[0]. --Splarka (rant) 07:15, 26 June 2007 (UTC)
My second script
Hey, I was wondering what you guys think of my new script, found at User:TheFearow/welcomehelper.js. It finds Talk links for users anywhere it can, and adds a Welcome link next to it. It works in RC, NP, history pages, etc. It uses my tagger script (above) to do the actual welcoming.
Is this sort of thing worth putting on the scripts list?
Thanks! Matt/TheFearow (Talk) (Contribs) (Bot) 22:14, 25 June 2007 (UTC)
insertTags() patch
I'm going to file a new bug on bugzilla: about current implementation of insertTags()
. Since I try not to bug developers more than really necessary, I thought I would first put a notice here and see if anybody has any suggestions / improvements. Please see insertTags() ∴ Alex Smotrov 22:41, 26 June 2007 (UTC)
- You have a hard tab on the "
// Mozilla
" line that makes the code hard to read. Mike Dillon 23:55, 26 June 2007 (UTC)
- My fault, I guess I didn't actually hope that anybody would look at the code ;) Fixed formatting, slightly changed code to be more readable, transcluded the code to get syntax highlighting ∴ Alex Smotrov 15:45, 27 June 2007 (UTC)
sprintf
Made a small implementation of sprintf in JS, here if anyone wants it. It should work, but I won't give any guaranties! →AzaToth 23:22, 2 July 2007 (UTC)
function sprintf() {
if( arguments.length == 0 ) {
throw "Not enough arguments for sprintf";
}
var result = "";
var format = arguments[0];
var index = 1;
var current_index = 1;
var flags = {};
var in_operator = false;
var relative = false;
var precision = false;
var fixed = false;
var vector_delimiter = '.';
for( var i = 0; i < format.length; ++i ) {
var current_char = format.charAt(i);
if( in_operator ) {
switch( current_char ) {
case 'i':
current_char = 'd';
break;
case 'F':
current_char = 'f';
break;
case '%':
case 'c':
case 's':
case 'd':
case 'u':
case 'o':
case 'x':
case 'e':
case 'f':
case 'g':
case 'X':
case 'E':
case 'G':
case 'b':
var value = arguments[current_index];
if( vector ) {
r = value.toString().split( '' );
result += value.toString().split('').map( function( value ) {
return sprintf.format( current_char, value.charCodeAt(), flags );
}).join( vector_delimiter );
} else {
result += sprintf.format( current_char, value, flags );
}
if( !fixed ) {
++index;
}
current_index = index;
flags = {};
relative = false;
in_operator = false;
precision = false;
fixed = false;
vector = false;
vector_delimiter = '.';
break;
case 'v':
vector = true;
break;
case ' ':
case '0':
case '-':
case '+':
case '#':
flags[current_char] = true;
break;
case '*':
relative = true;
break;
case '.':
precision = true;
break;
}
if( /\d/.test( current_char ) ) {
var num = parseInt( format.substr( i ) );
var len = num.toString().length;
i += len - 1;
var next = format.charAt( i + 1 );
if( next == '$' ) {
if( num <= 0 || num >= arguments.length ) {
throw "out of bound";
}
if( relative ) {
if( precision ) {
flags['precision'] = arguments[num];
precision = false;
} else if( format.charAt( i + 2 ) == 'v' ) {
vector_delimiter = arguments[num];
}else {
flags['width'] = arguments[num];
}
relative = false;
} else {
fixed = true;
current_index = num;
}
++i;
} else if( precision ) {
flags['precision'] = num;
precision = false;
} else {
flags['width'] = num;
}
} else if ( relative && !/\d/.test( format.charAt( i + 1 ) ) ) {
if( precision ) {
flags['precision'] = arguments[current_index];
precision = false;
} else if( format.charAt( i + 1 ) == 'v' ) {
vector_delimiter = arguments[current_index];
} else {
flags['width'] = arguments[current_index];
}
++index;
if( !fixed ) {
current_index++;
}
relative = false;
}
} else {
if( current_char == '%' ) {
in_operator = true;
continue;
} else {
result += current_char;
continue;
}
}
}
return result;
}
sprintf.format = function( type, value, flags ) {
var result;
var prefix = '';
var fill = '';
var fillchar = ' ';
switch( type ) {
case '%':
result = '%';
break;
case 'c':
result = String.fromCharCode( value );
break;
case 's':
result = value.toString();
break;
case 'd':
result = parseInt( value ).toString();
break;
case 'u':
result = Math.abs( parseInt( value ) ).toString(); // it's not correct, but JS lacks unsigned ints
break;
case 'o':
result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(8);
break;
case 'x':
result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(16);
break;
case 'b':
result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(2);
break;
case 'e':
var digits = flags['precision'] ? flags['precision'] : 6;
result = (new Number( value ) ).toExponential( digits ).toString();
break;
case 'f':
var digits = flags['precision'] ? flags['precision'] : 6;
result = (new Number( value ) ).toFixed( digits ).toString();
case 'g':
var digits = flags['precision'] ? flags['precision'] : 6;
result = (new Number( value ) ).toPrecision( digits ).toString();
break;
case 'X':
result = (new Number( Math.abs( parseInt( value ) ) ) ).toString(16).toUpperCase();
break;
case 'E':
var digits = flags['precision'] ? flags['precision'] : 6;
result = (new Number( value ) ).toExponential( digits ).toString().toUpperCase();
break;
case 'G':
var digits = flags['precision'] ? flags['precision'] : 6;
result = (new Number( value ) ).toPrecision( digits ).toString().toUpperCase();
break;
}
if(flags['+'] && parseFloat( value ) > 0 && ['d','e','f','g','E','G'].indexOf(type) != -1 ) {
prefix = '+';
}
if(flags[' '] && parseFloat( value ) > 0 && ['d','e','f','g','E','G'].indexOf(type) != -1 ) {
prefix = ' ';
}
if( flags['#'] && parseInt( value ) != 0 ) {
switch(type) {
case 'o':
prefix = '0';
break;
case 'x':
case 'X':
prefix = '0x';
break;
case 'b':
prefix = '0b';
break;
}
}
if( flags['0'] && !flags['-'] ) {
fillchar = '0';
}
if( flags['width'] && flags['width'] > ( result.length + prefix.length ) ) {
var tofill = flags['width'] - result.length - prefix.length;
for( var i = 0; i < tofill; ++i ) {
fill += fillchar;
}
}
if( flags['-'] && !flags['0'] ) {
result += fill;
} else {
result = fill + result;
}
return prefix + result;
}
List of Safari compatible scripts
I have create a list of scripts that I have tested/fixed on Safari 3. If you want to add to the list please do and I anyone wants me to test something I'll gladly do that as well if I have the time. --TheDJ (talk • contribs) 23:43, 12 July 2007 (UTC)
- Ideally, all scripts should work on all browsers, so if some of my scripts don't please tell. I have the beta of Safari for Windows, so I can test, but all the same please don't expect quick responses. Time, time, time... Shinobu 10:21, 26 July 2007 (UTC)
- Actually, I felt like testing some of my scripts in Safari for Windows, here are the results:
- Gerbrant
- fw OK
- alternativeOnloadHook not used, don't care (NUDC)
- hidePane OK
- NihongoReviveFirstHelpLink OK
- realTitle OK
- edit
- autoReplace Browser bug, won't fix.
In Firefox too... did I make a programming error, or am I using an unsupported feature?
- default n/a
- linksInDiff OK
- multiReplace Browser bug, won't fix.
- regexReplace OK
BROKEN
Doesn't react to the "Replace" button.
- top OK
- gui
- mng
- decache OK
- listModules OK
- I will have a look at the broken scripts as soon as I have time. Shinobu 10:49, 26 July 2007 (UTC)
- Made some time :-) regexReplace is not working because Firefox and Safari send the onclick handler a MouseEvent object and I wasn't expecting that. Shinobu 11:30, 26 July 2007 (UTC)
- Fixed the bug in regexReplace, and filed a bug report with Apple and Mozilla, so hopefully they will fix their implementation of replace. Shinobu 20:06, 26 July 2007 (UTC)
Adding a checkbox
Can someone show me a way to use javascript to add a check-box to the page, then have another javascript function check the status of that check-box before continuing? Ideally, the checkbox would be in a portlet (doesn't really matter which one), and the second function would only continue if the checkbox is checked. This way, the second script (a userscript, possibly) can be turned on/off whenever needed. Thanks– Obsidian Mask 02:09, 1 August 2007 (UTC)