-
Notifications
You must be signed in to change notification settings - Fork 143
/
friendlytag.js
2056 lines (1871 loc) · 73 KB
/
friendlytag.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// <nowiki>
(function($) {
/*
****************************************
*** friendlytag.js: Tag module
****************************************
* Mode of invocation: Tab ("Tag")
* Active on: Existing articles and drafts; file pages with a corresponding file
* which is local (not on Commons); all redirects
* Config directives in: FriendlyConfig
*/
Twinkle.tag = function friendlytag() {
// redirect tagging
if (Morebits.wiki.isPageRedirect()) {
Twinkle.tag.mode = 'redirect';
Twinkle.addPortletLink(Twinkle.tag.callback, 'Tag', 'friendly-tag', 'Tag redirect');
// file tagging
} else if (mw.config.get('wgNamespaceNumber') === 6 && !document.getElementById('mw-sharedupload') && document.getElementById('mw-imagepage-section-filehistory')) {
Twinkle.tag.mode = 'file';
Twinkle.addPortletLink(Twinkle.tag.callback, 'Tag', 'friendly-tag', 'Add maintenance tags to file');
// article/draft article tagging
} else if ([0, 118].indexOf(mw.config.get('wgNamespaceNumber')) !== -1 && mw.config.get('wgCurRevisionId')) {
Twinkle.tag.mode = 'article';
// Can't remove tags when not viewing current version
Twinkle.tag.canRemove = (mw.config.get('wgCurRevisionId') === mw.config.get('wgRevisionId')) &&
// Disabled on latest diff because the diff slider could be used to slide
// away from the latest diff without causing the script to reload
!mw.config.get('wgDiffNewId');
Twinkle.addPortletLink(Twinkle.tag.callback, 'Tag', 'friendly-tag', 'Add or remove article maintenance tags');
}
};
Twinkle.tag.checkedTags = [];
Twinkle.tag.callback = function friendlytagCallback() {
var Window = new Morebits.simpleWindow(630, Twinkle.tag.mode === 'article' ? 500 : 400);
Window.setScriptName('Twinkle');
// anyone got a good policy/guideline/info page/instructional page link??
Window.addFooterLink('Twinkle help', 'WP:TW/DOC#tag');
var form = new Morebits.quickForm(Twinkle.tag.callback.evaluate);
if (document.getElementsByClassName('patrollink').length) {
form.append({
type: 'checkbox',
list: [
{
label: 'Mark the page as patrolled',
value: 'patrolPage',
name: 'patrolPage',
checked: Twinkle.getFriendlyPref('markTaggedPagesAsPatrolled')
}
]
});
}
switch (Twinkle.tag.mode) {
case 'article':
Window.setTitle('Article maintenance tagging');
form.append({
type: 'select',
name: 'sortorder',
label: 'View this list:',
tooltip: 'You can change the default view order in your Twinkle preferences (WP:TWPREFS).',
event: Twinkle.tag.updateSortOrder,
list: [
{ type: 'option', value: 'cat', label: 'By categories', selected: Twinkle.getFriendlyPref('tagArticleSortOrder') === 'cat' },
{ type: 'option', value: 'alpha', label: 'In alphabetical order', selected: Twinkle.getFriendlyPref('tagArticleSortOrder') === 'alpha' }
]
});
form.append({
type: 'input',
label: 'Quick filter: ',
name: 'quickfilter',
size: '30px',
event: function twinkletagquickfilter() {
var $form = $('#tagWorkArea');
// flush the DOM of all existing underline spans
$form.find('.search-hit').each(function(i, e) {
var label_element = e.parentElement;
// This would convert <label>Hello <span class=search-hit>wo</span>rld</label>
// to <label>Hello world</label>
label_element.innerHTML = label_element.textContent;
});
// allCheckboxDivs and allHeaders are defined globally, rather than in
// this function, to avoid having to recompute them on every keydown.
if (this.value) {
allCheckboxDivs.hide();
allHeaders.hide();
var searchString = this.value;
var searchRegex = new RegExp(mw.util.escapeRegExp(searchString), 'i');
$form.find('label').each(function() {
var label_text = this.textContent;
var searchHit = searchRegex.exec(label_text);
if (searchHit) {
var range = document.createRange();
var textnode = this.childNodes[0];
range.selectNodeContents(textnode);
range.setStart(textnode, searchHit.index);
range.setEnd(textnode, searchHit.index + searchString.length);
var underline_span = $('<span>').addClass('search-hit').css('text-decoration', 'underline')[0];
range.surroundContents(underline_span);
this.parentElement.style.display = 'block'; // un-hide
}
});
} else {
allCheckboxDivs.show();
allHeaders.show();
}
}
});
if (!Twinkle.tag.canRemove) {
var divElement = document.createElement('div');
divElement.innerHTML = 'For removal of existing tags, please open Tag menu from the current version of article';
form.append({
type: 'div',
name: 'untagnotice',
label: divElement
});
}
form.append({
type: 'div',
id: 'tagWorkArea',
className: 'morebits-scrollbox',
style: 'max-height: 28em'
});
form.append({
type: 'checkbox',
list: [
{
label: 'Group inside {{multiple issues}} if possible',
value: 'group',
name: 'group',
tooltip: 'If applying two or more templates supported by {{multiple issues}} and this box is checked, all supported templates will be grouped inside a {{multiple issues}} template.',
checked: Twinkle.getFriendlyPref('groupByDefault')
}
]
}
);
break;
case 'file':
Window.setTitle('File maintenance tagging');
form.append({ type: 'header', label: 'License and sourcing problem tags' });
form.append({ type: 'checkbox', name: 'fileTags', list: Twinkle.tag.file.licenseList });
form.append({ type: 'header', label: 'Wikimedia Commons-related tags' });
form.append({ type: 'checkbox', name: 'fileTags', list: Twinkle.tag.file.commonsList });
form.append({ type: 'header', label: 'Cleanup tags' });
form.append({ type: 'checkbox', name: 'fileTags', list: Twinkle.tag.file.cleanupList });
form.append({ type: 'header', label: 'Image quality tags' });
form.append({ type: 'checkbox', name: 'fileTags', list: Twinkle.tag.file.qualityList });
form.append({ type: 'header', label: 'Replacement tags' });
form.append({ type: 'checkbox', name: 'fileTags', list: Twinkle.tag.file.replacementList });
if (Twinkle.getFriendlyPref('customFileTagList').length) {
form.append({ type: 'header', label: 'Custom tags' });
form.append({ type: 'checkbox', name: 'fileTags', list: Twinkle.getFriendlyPref('customFileTagList') });
}
break;
case 'redirect':
Window.setTitle('Redirect tagging');
form.append({ type: 'header', label: 'Spelling, misspelling, tense and capitalization templates' });
form.append({ type: 'checkbox', name: 'redirectTags', list: Twinkle.tag.spellingList });
form.append({ type: 'header', label: 'Alternative name templates' });
form.append({ type: 'checkbox', name: 'redirectTags', list: Twinkle.tag.alternativeList });
form.append({ type: 'header', label: 'Miscellaneous and administrative redirect templates' });
form.append({ type: 'checkbox', name: 'redirectTags', list: Twinkle.tag.administrativeList });
if (Twinkle.getFriendlyPref('customRedirectTagList').length) {
form.append({ type: 'header', label: 'Custom tags' });
form.append({ type: 'checkbox', name: 'redirectTags', list: Twinkle.getFriendlyPref('customRedirectTagList') });
}
break;
default:
alert('Twinkle.tag: unknown mode ' + Twinkle.tag.mode);
break;
}
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
if (Twinkle.tag.mode === 'article') {
result.quickfilter.focus(); // place cursor in the Quick filter field as soon as window is opened
Twinkle.tag.alreadyPresentTags = [];
if (Twinkle.tag.canRemove) {
// Look for existing maintenance tags in the lead section and put them in array
// All tags are HTML table elements that are direct children of .mw-parser-output,
// except when they are within {{multiple issues}}
$('.mw-parser-output').children().each(function parsehtml(i, e) {
// break out on encountering the first heading, which means we are no
// longer in the lead section
if (e.tagName === 'H2') {
return false;
}
// The ability to remove tags depends on the template's {{ambox}} |name=
// parameter bearing the template's correct name (preferably) or a name that at
// least redirects to the actual name
// All tags have their first class name as "box-" + template name
if (e.className.indexOf('box-') === 0) {
if (e.classList[0] === 'box-Multiple_issues') {
$(e).find('.ambox').each(function(idx, e) {
var tag = e.classList[0].slice(4).replace(/_/g, ' ');
Twinkle.tag.alreadyPresentTags.push(tag);
});
return true; // continue
}
var tag = e.classList[0].slice(4).replace(/_/g, ' ');
Twinkle.tag.alreadyPresentTags.push(tag);
}
});
// {{Uncategorized}} and {{Improve categories}} are usually placed at the end
if ($('.box-Uncategorized').length) {
Twinkle.tag.alreadyPresentTags.push('Uncategorized');
}
if ($('.box-Improve_categories').length) {
Twinkle.tag.alreadyPresentTags.push('Improve categories');
}
}
// Add status text node after Submit button
var statusNode = document.createElement('small');
statusNode.id = 'tw-tag-status';
Twinkle.tag.status = {
// initial state; defined like this because these need to be available for reference
// in the click event handler
numAdded: 0,
numRemoved: 0
};
$(Window.buttons[0]).after(statusNode);
// fake a change event on the sort dropdown, to initialize the tag list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sortorder.dispatchEvent(evt);
} else {
// Redirects and files: Add a link to each template's description page
Morebits.quickForm.getElements(result, Twinkle.tag.mode + 'Tags').forEach(generateLinks);
}
};
// Used in Quick Filter event function
var allCheckboxDivs, allHeaders;
Twinkle.tag.updateSortOrder = function(e) {
var sortorder = e.target.value;
Twinkle.tag.checkedTags = e.target.form.getChecked('articleTags') || [];
var container = new Morebits.quickForm.element({ type: 'fragment' });
// function to generate a checkbox, with appropriate subgroup if needed
var makeCheckbox = function(tag, description) {
var checkbox = { value: tag, label: '{{' + tag + '}}: ' + description };
if (Twinkle.tag.checkedTags.indexOf(tag) !== -1) {
checkbox.checked = true;
}
switch (tag) {
case 'Cleanup':
checkbox.subgroup = {
name: 'cleanup',
type: 'input',
label: 'Specific reason why cleanup is needed: ',
tooltip: 'Required.',
size: 35
};
break;
case 'Close paraphrasing':
checkbox.subgroup = {
name: 'closeParaphrasing',
type: 'input',
label: 'Source: ',
tooltip: 'Source that has been closely paraphrased'
};
break;
case 'Copy edit':
checkbox.subgroup = {
name: 'copyEdit',
type: 'input',
label: '"This article may require copy editing for..." ',
tooltip: 'e.g. "consistent spelling". Optional.',
size: 35
};
break;
case 'Copypaste':
checkbox.subgroup = {
name: 'copypaste',
type: 'input',
label: 'Source URL: ',
tooltip: 'If known.',
size: 50
};
break;
case 'Expand language':
checkbox.subgroup = [ {
name: 'expandLanguageLangCode',
type: 'input',
label: 'Language code: ',
tooltip: 'Language code of the language from which article is to be expanded from'
}, {
name: 'expandLanguageArticle',
type: 'input',
label: 'Name of article: ',
tooltip: 'Name of article to be expanded from, without the interwiki prefix'
}
];
break;
case 'Expert needed':
checkbox.subgroup = [
{
name: 'expertNeeded',
type: 'input',
label: 'Name of relevant WikiProject: ',
tooltip: 'Optionally, enter the name of a WikiProject which might be able to help recruit an expert. Don\'t include the "WikiProject" prefix.'
},
{
name: 'expertNeededReason',
type: 'input',
label: 'Reason: ',
tooltip: 'Short explanation describing the issue. Either Reason or Talk link is required.'
},
{
name: 'expertNeededTalk',
type: 'input',
label: 'Talk discussion: ',
tooltip: 'Name of the section of this article\'s talk page where the issue is being discussed. Do not give a link, just the name of the section. Either Reason or Talk link is required.'
}
];
break;
case 'Globalize':
checkbox.subgroup = {
name: 'globalizeRegion',
type: 'input',
label: 'Over-represented country or region'
};
break;
case 'History merge':
checkbox.subgroup = [
{
name: 'histmergeOriginalPage',
type: 'input',
label: 'Other article: ',
tooltip: 'Name of the page that should be merged into this one (required).'
},
{
name: 'histmergeReason',
type: 'input',
label: 'Reason: ',
tooltip: 'Short explanation describing the reason a history merge is needed. Should probably begin with "because" and end with a period.'
},
{
name: 'histmergeSysopDetails',
type: 'input',
label: 'Extra details: ',
tooltip: 'For complex cases, provide extra instructions for the reviewing administrator.'
}
];
break;
case 'Merge':
case 'Merge from':
case 'Merge to':
var otherTagName = 'Merge';
switch (tag) {
case 'Merge from':
otherTagName = 'Merge to';
break;
case 'Merge to':
otherTagName = 'Merge from';
break;
// no default
}
checkbox.subgroup = [
{
name: 'mergeTarget',
type: 'input',
label: 'Other article(s): ',
tooltip: 'If specifying multiple articles, separate them with pipe characters: Article one|Article two'
},
{
name: 'mergeTagOther',
type: 'checkbox',
list: [
{
label: 'Tag the other article with a {{' + otherTagName + '}} tag',
checked: true,
tooltip: 'Only available if a single article name is entered.'
}
]
}
];
if (mw.config.get('wgNamespaceNumber') === 0) {
checkbox.subgroup.push({
name: 'mergeReason',
type: 'textarea',
label: 'Rationale for merge (will be posted on ' +
(tag === 'Merge to' ? 'the other article\'s' : 'this article\'s') + ' talk page):',
tooltip: 'Optional, but strongly recommended. Leave blank if not wanted. Only available if a single article name is entered.'
});
}
break;
case 'Not English':
case 'Rough translation':
checkbox.subgroup = [
{
name: 'translationLanguage',
type: 'input',
label: 'Language of article (if known): ',
tooltip: 'Consider looking at [[WP:LRC]] for help. If listing the article at PNT, please try to avoid leaving this box blank, unless you are completely unsure.'
}
];
if (tag === 'Not English') {
checkbox.subgroup.push({
name: 'translationNotify',
type: 'checkbox',
list: [
{
label: 'Notify article creator',
checked: true,
tooltip: "Places {{uw-notenglish}} on the creator's talk page."
}
]
});
}
if (mw.config.get('wgNamespaceNumber') === 0) {
checkbox.subgroup.push({
name: 'translationPostAtPNT',
type: 'checkbox',
list: [
{
label: 'List this article at Wikipedia:Pages needing translation into English (PNT)',
checked: true
}
]
});
checkbox.subgroup.push({
name: 'translationComments',
type: 'textarea',
label: 'Additional comments to post at PNT',
tooltip: 'Optional, and only relevant if "List this article ..." above is checked.'
});
}
break;
case 'Notability':
checkbox.subgroup = {
name: 'notability',
type: 'select',
list: [
{ label: "{{notability}}: article's subject may not meet the general notability guideline", value: 'none' },
{ label: '{{notability|Academics}}: notability guideline for academics', value: 'Academics' },
{ label: '{{notability|Biographies}}: notability guideline for biographies', value: 'Biographies' },
{ label: '{{notability|Books}}: notability guideline for books', value: 'Books' },
{ label: '{{notability|Companies}}: notability guidelines for companies and organizations', value: 'Companies' },
{ label: '{{notability|Events}}: notability guideline for events', value: 'Events' },
{ label: '{{notability|Films}}: notability guideline for films', value: 'Films' },
{ label: '{{notability|Places}}: notability guideline for places', value: 'Places' },
{ label: '{{notability|Music}}: notability guideline for music', value: 'Music' },
{ label: '{{notability|Neologisms}}: notability guideline for neologisms', value: 'Neologisms' },
{ label: '{{notability|Numbers}}: notability guideline for numbers', value: 'Numbers' },
{ label: '{{notability|Products}}: notability guideline for products and services', value: 'Products' },
{ label: '{{notability|Sport}}: notability guideline for sports and athletics', value: 'Sport' },
{ label: '{{notability|Television}}: notability guideline for television shows', value: 'Television' },
{ label: '{{notability|Web}}: notability guideline for web content', value: 'Web' }
]
};
break;
default:
break;
}
return checkbox;
};
var makeCheckboxesForAlreadyPresentTags = function() {
container.append({ type: 'header', id: 'tagHeader0', label: 'Tags already present' });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv0' });
var checkboxes = [];
var unCheckedTags = e.target.form.getUnchecked('alreadyPresentArticleTags') || [];
Twinkle.tag.alreadyPresentTags.forEach(function(tag) {
var description = Twinkle.tag.article.tags[tag];
var checkbox =
{
value: tag,
label: '{{' + tag + '}}' + (description ? ': ' + description : ''),
checked: unCheckedTags.indexOf(tag) === -1
// , subgroup: { type: 'input', name: 'removeReason', label: 'Reason', tooltip: 'Enter reason for removing this tag' }
// TODO: add option for providing reason for removal
};
checkboxes.push(checkbox);
});
subdiv.append({
type: 'checkbox',
name: 'alreadyPresentArticleTags',
list: checkboxes
});
};
if (sortorder === 'cat') { // categorical sort order
// function to iterate through the tags and create a checkbox for each one
var doCategoryCheckboxes = function(subdiv, array) {
var checkboxes = [];
$.each(array, function(k, tag) {
var description = Twinkle.tag.article.tags[tag];
if (Twinkle.tag.alreadyPresentTags.indexOf(tag) === -1) {
checkboxes.push(makeCheckbox(tag, description));
}
});
subdiv.append({
type: 'checkbox',
name: 'articleTags',
list: checkboxes
});
};
if (Twinkle.tag.alreadyPresentTags.length > 0) {
makeCheckboxesForAlreadyPresentTags();
}
var i = 1;
// go through each category and sub-category and append lists of checkboxes
$.each(Twinkle.tag.article.tagCategories, function(title, content) {
container.append({ type: 'header', id: 'tagHeader' + i, label: title });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv' + i++ });
if (Array.isArray(content)) {
doCategoryCheckboxes(subdiv, content);
} else {
$.each(content, function(subtitle, subcontent) {
subdiv.append({ type: 'div', label: [ Morebits.htmlNode('b', subtitle) ] });
doCategoryCheckboxes(subdiv, subcontent);
});
}
});
} else { // alphabetical sort order
if (Twinkle.tag.alreadyPresentTags.length > 0) {
makeCheckboxesForAlreadyPresentTags();
container.append({ type: 'header', id: 'tagHeader1', label: 'Available tags' });
}
var checkboxes = [];
$.each(Twinkle.tag.article.tags, function(tag, description) {
if (Twinkle.tag.alreadyPresentTags.indexOf(tag) === -1) {
checkboxes.push(makeCheckbox(tag, description));
}
});
container.append({
type: 'checkbox',
name: 'articleTags',
list: checkboxes
});
}
// append any custom tags
if (Twinkle.getFriendlyPref('customTagList').length) {
container.append({ type: 'header', label: 'Custom tags' });
container.append({ type: 'checkbox', name: 'articleTags',
list: Twinkle.getFriendlyPref('customTagList').map(function(el) {
el.checked = Twinkle.tag.checkedTags.indexOf(el.value) !== -1;
return el;
})
});
}
var $workarea = $(e.target.form).find('div#tagWorkArea');
var rendered = container.render();
$workarea.empty().append(rendered);
// Used in quick filter event function
allCheckboxDivs = $workarea.find('[name=articleTags], [name=alreadyPresentArticleTags]').parent();
allHeaders = $workarea.find('h5, .quickformDescription');
// clear search, because the search results are not preserved over mode change
e.target.form.quickfilter.value = '';
// style adjustments
$workarea.find('h5').css({ 'font-size': '110%' });
$workarea.find('h5:not(:first-child)').css({ 'margin-top': '1em' });
$workarea.find('div').filter(':has(span.quickformDescription)').css({ 'margin-top': '0.4em' });
Morebits.quickForm.getElements(e.target.form, 'articleTags').forEach(generateLinks);
var alreadyPresentTags = Morebits.quickForm.getElements(e.target.form, 'alreadyPresentArticleTags');
if (alreadyPresentTags) {
alreadyPresentTags.forEach(generateLinks);
}
// tally tags added/removed, update statusNode text
var statusNode = document.getElementById('tw-tag-status');
$('[name=articleTags], [name=alreadyPresentArticleTags]').click(function() {
if (this.name === 'articleTags') {
if (this.checked) {
Twinkle.tag.status.numAdded++;
} else {
Twinkle.tag.status.numAdded--;
}
} else if (this.name === 'alreadyPresentArticleTags') {
if (this.checked) {
Twinkle.tag.status.numRemoved--;
} else {
Twinkle.tag.status.numRemoved++;
}
}
var firstPart = 'Adding ' + Twinkle.tag.status.numAdded + ' tag' + (Twinkle.tag.status.numAdded > 1 ? 's' : '');
var secondPart = 'Removing ' + Twinkle.tag.status.numRemoved + ' tag' + (Twinkle.tag.status.numRemoved > 1 ? 's' : '');
statusNode.textContent =
(Twinkle.tag.status.numAdded ? ' ' + firstPart : '') +
(Twinkle.tag.status.numRemoved ? (Twinkle.tag.status.numAdded ? '; ' : ' ') + secondPart : '');
});
};
/**
* Adds a link to each template's description page
* @param {Morebits.quickForm.element} checkbox associated with the template
*/
var generateLinks = function(checkbox) {
var link = Morebits.htmlNode('a', '>');
link.setAttribute('class', 'tag-template-link');
var tagname = checkbox.values;
link.setAttribute('href', mw.util.getUrl(
(tagname.indexOf(':') === -1 ? 'Template:' : '') +
(tagname.indexOf('|') === -1 ? tagname : tagname.slice(0, tagname.indexOf('|')))
));
link.setAttribute('target', '_blank');
$(checkbox).parent().append(['\u00A0', link]);
};
// Tags for ARTICLES start here
Twinkle.tag.article = {};
// A list of all article tags, in alphabetical order
// To ensure tags appear in the default "categorized" view, add them to the tagCategories hash below.
Twinkle.tag.article.tags = {
'Advert': 'written like an advertisement',
'All plot': 'almost entirely a plot summary',
'Autobiography': 'autobiography and may not be written neutrally',
'BLP sources': 'BLP that needs additional sources for verification',
'BLP unsourced': 'BLP that has no sources at all (use BLP PROD instead for new articles)',
'Citation style': 'unclear or inconsistent citation style',
'Cleanup': 'requires cleanup',
'Cleanup bare URLs': 'uses bare URLs for references, which are prone to link rot',
'Cleanup-PR': 'reads like a press release or news article',
'Cleanup reorganize': "needs reorganization to comply with Wikipedia's layout guidelines",
'Cleanup rewrite': "needs to be rewritten entirely to comply with Wikipedia's quality standards",
'Cleanup tense': 'does not follow guidelines on use of different tenses.',
'Close paraphrasing': 'contains close paraphrasing of a non-free copyrighted source',
'COI': 'creator or major contributor may have a conflict of interest',
'Condense': 'too many section headers dividing up content',
'Confusing': 'confusing or unclear',
'Context': 'insufficient context for those unfamiliar with the subject',
'Copy edit': 'requires copy editing for grammar, style, cohesion, tone, or spelling',
'Copypaste': 'appears to have been copied and pasted from another location',
'Current': 'documents a current event',
'Dead end': 'article has no links to other articles',
'Disputed': 'questionable factual accuracy',
'Essay-like': 'written like a personal reflection, personal essay, or argumentative essay',
'Expand language': 'should be expanded with text translated from a foreign-language article',
'Expert needed': 'needs attention from an expert on the subject',
'External links': 'external links may not follow content policies or guidelines',
'Fanpov': "written from a fan's point of view",
'Fiction': 'fails to distinguish between fact and fiction',
'Globalize': 'may not represent a worldwide view of the subject',
'GOCEinuse': 'currently undergoing a major copy edit by the Guild of Copy Editors',
'History merge': 'another page should be history merged into this one',
'Hoax': 'may partially or completely be a hoax',
'Improve categories': 'needs additional or more specific categories',
'Incomprehensible': 'very hard to understand or incomprehensible',
'In-universe': 'subject is fictional and needs rewriting to provide a non-fictional perspective',
'In use': 'undergoing a major edit for a short while',
'Lead missing': 'no lead section',
'Lead rewrite': 'lead section needs to be rewritten to comply with guidelines',
'Lead too long': 'lead section is too long for the length of the article',
'Lead too short': 'lead section is too short and should be expanded to summarize key points',
'Like resume': 'written like a resume',
'Long plot': 'plot summary is too long or excessively detailed',
'Manual': 'written like a manual or guidebook',
'Merge': 'should be merged with another given article',
'Merge from': 'another given article should be merged into this one',
'Merge to': 'should be merged into another given article',
'More citations needed': 'needs additional references or sources for verification',
'More footnotes': 'has some references, but insufficient inline citations',
'No footnotes': 'has references, but lacks inline citations',
'No plot': 'needs a plot summary',
'Non-free': 'may contain excessive or improper use of copyrighted materials',
'Notability': 'subject may not meet the general notability guideline',
'Not English': 'written in a language other than English and needs translation',
'One source': 'relies largely or entirely on a single source',
'Original research': 'contains original research',
'Orphan': 'linked to from no other articles',
'Over-coverage': 'extensive bias or disproportional coverage towards one or more specific regions',
'Overlinked': 'too many duplicate and/or irrelevant links to other articles',
'Overly detailed': 'excessive amount of intricate detail',
'Over-quotation': 'too many or too-lengthy quotations for an encyclopedic entry',
'Peacock': 'contains wording that promotes the subject in a subjective manner without adding information',
'POV': 'does not maintain a neutral point of view',
'Primary sources': 'relies too much on references to primary sources, and needs secondary sources',
'Prose': 'written in a list format but may read better as prose',
'Recentism': 'slanted towards recent events',
'Rough translation': 'poor translation from another language',
'Sections': 'needs to be divided into sections by topic',
'Self-published': 'contains excessive or inappropriate references to self-published sources',
'Sources exist': 'notable topic, sources are available that could be added to article',
'Technical': 'too technical for most readers to understand',
'Third-party': 'relies too heavily on sources too closely associated with the subject',
'Tone': 'tone or style may not reflect the encyclopedic tone used on Wikipedia',
'Too few opinions': 'may not include all significant viewpoints',
'Uncategorized': 'not added to any categories',
'Under construction': 'in the process of an expansion or major restructuring',
'Underlinked': 'needs more wikilinks to other articles',
'Undue weight': 'lends undue weight to certain ideas, incidents, or controversies',
'Unfocused': 'lacks focus or is about more than one topic',
'Unreferenced': 'does not cite any sources at all',
'Unreliable sources': 'some references may not be reliable',
'Undisclosed paid': 'may have been created or edited in return for undisclosed payments',
'Update': 'needs additional up-to-date information added',
'Very long': 'too long to read and navigate comfortably',
'Weasel': 'neutrality or verifiability is compromised by the use of weasel words'
};
// A list of tags in order of category
// Tags should be in alphabetical order within the categories
// Add new categories with discretion - the list is long enough as is!
Twinkle.tag.article.tagCategories = {
'Cleanup and maintenance tags': {
'General cleanup': [
'Cleanup', // has a subgroup with text input
'Cleanup rewrite',
'Copy edit' // has a subgroup with text input
],
'Potentially unwanted content': [
'Close paraphrasing',
'Copypaste', // has a subgroup with text input
'External links',
'Non-free'
],
'Structure, formatting, and lead section': [
'Cleanup reorganize',
'Condense',
'Lead missing',
'Lead rewrite',
'Lead too long',
'Lead too short',
'Sections',
'Very long'
],
'Fiction-related cleanup': [
'All plot',
'Fiction',
'In-universe',
'Long plot',
'No plot'
]
},
'General content issues': {
'Importance and notability': [
'Notability' // has a subgroup with subcategories
],
'Style of writing': [
'Advert',
'Cleanup tense',
'Essay-like',
'Fanpov',
'Like resume',
'Manual',
'Cleanup-PR',
'Over-quotation',
'Prose',
'Technical',
'Tone'
],
'Sense (or lack thereof)': [
'Confusing',
'Incomprehensible',
'Unfocused'
],
'Information and detail': [
'Context',
'Expert needed',
'Overly detailed',
'Undue weight'
],
'Timeliness': [
'Current',
'Update'
],
'Neutrality, bias, and factual accuracy': [
'Autobiography',
'COI',
'Disputed',
'Hoax',
'Globalize',
'Over-coverage',
'Peacock',
'POV',
'Recentism',
'Too few opinions',
'Undisclosed paid',
'Weasel'
],
'Verifiability and sources': [
'BLP sources',
'BLP unsourced',
'More citations needed',
'One source',
'Original research',
'Primary sources',
'Self-published',
'Sources exist',
'Third-party',
'Unreferenced',
'Unreliable sources'
]
},
'Specific content issues': {
'Language': [
'Not English', // has a subgroup with several options
'Rough translation', // has a subgroup with several options
'Expand language'
],
'Links': [
'Dead end',
'Orphan',
'Overlinked',
'Underlinked'
],
'Referencing technique': [
'Citation style',
'Cleanup bare URLs',
'More footnotes',
'No footnotes'
],
'Categories': [
'Improve categories',
'Uncategorized'
]
},
'Merging': [
'History merge',
'Merge', // these three have a subgroup with several options
'Merge from',
'Merge to'
],
'Informational': [
'GOCEinuse',
'In use',
'Under construction'
]
};
// Contains those article tags that *do not* work inside {{multiple issues}}.
Twinkle.tag.multipleIssuesExceptions = [
'Copypaste',
'Expand language',
'GOCEinuse',
'History merge',
'Improve categories',
'In use',
'Merge',
'Merge from',
'Merge to',
'Not English',
'Rough translation',
'Uncategorized',
'Under construction'
];
// Tags for REDIRECTS start here
Twinkle.tag.spellingList = [
{
label: '{{R from acronym}}: redirect from an acronym (e.g. POTUS) to its expanded form',
value: 'R from acronym'
},
{
label: '{{R from alternative spelling}}: redirect from a title with a different spelling',
value: 'R from alternative spelling'
},
{
label: '{{R from initialism}}: redirect from an initialism (e.g. AGF) to its expanded form',
value: 'R from initialism'
},
{
label: '{{R from member}}: redirect from a member of a group to a related topic such as the group, organization, or team of membership',
value: 'R from member'
},
{
label: '{{R from misspelling}}: redirect from a misspelling or typographical error',
value: 'R from misspelling'
},
{
label: '{{R from other capitalisation}}: redirect from a title with another method of capitalisation',
value: 'R from other capitalisation'
},
{
label: '{{R from plural}}: redirect from a plural word to the singular equivalent',
value: 'R from plural'
},
{
label: '{{R from related word}}: redirect from a related word',
value: 'R from related word'
},
{
label: '{{R to list entry}}: redirect to a "list of minor entities"-type article which contains brief descriptions of subjects not notable enough to have separate articles',
value: 'R to list entry'
},
{
label: '{{R to section}}: similar to {{R to list entry}}, but when list is organized in sections, such as list of characters in a fictional universe.',
value: 'R to section'
},
{
label: '{{R with possibilities}}: redirect from a more specific title to a more general, less detailed article, hence something which can and should be expanded',
value: 'R with possibilities'
}
];
Twinkle.tag.alternativeList = [
{
label: '{{R from alternative language}}: redirect from an English name to a name in another language, or vice-versa',
value: 'R from alternative language',
subgroup: [
{
name: 'altLangFrom',
type: 'input',
label: 'From language (two-letter code): ',
tooltip: 'Enter the two-letter code of the language the redirect name is in; such as en for English, de for German'
},
{
name: 'altLangTo',
type: 'input',
label: 'To language (two-letter code): ',
tooltip: 'Enter the two-letter code of the language the target name is in; such as en for English, de for German'
},
{
name: 'altLangInfo',
type: 'div',
label: $.parseHTML('<p>For a list of language codes, see <a href="/wiki/Wp:Template_messages/Redirect_language_codes">Wikipedia:Template messages/Redirect language codes</a></p>')
}
]
},
{
label: '{{R from alternative name}}: redirect from a title that is another name, a pseudonym, a nickname, or a synonym',
value: 'R from alternative name'
},
{
label: '{{R from ASCII}}: redirect from a title in basic ASCII to the formal article title, with differences that are not diacritical marks (accents, umlauts, etc.)',
value: 'R from ASCII'
},
{
label: '{{R from historic name}}: redirect from another name with a significant historic past as a region, state, city or such, but which is no longer known by that title or name',
value: 'R from historic name'
},
{
label: '{{R from incorrect name}}: redirect from an erroneus name that is unsuitable as a title',
value: 'R from incorrect name'
},
{
label: '{{R from long name}}: redirect from a title that is a complete or more complete name',
value: 'R from long name'
},
{
label: '{{R from name and country}}: redirect from the specific name to the briefer name',
value: 'R from name and country'
},
{
label: '{{R from phrase}}: redirect from a phrase to a more general relevant article covering the topic',
value: 'R from phrase'
},
{