User:BrandonXLF/PortletLinks.js

/*** Portlet Link Manager ***/

// Easily add and manage custom portlet linls

// Documentation at en:w:User:BrandonXLF/PortletLinks

// By en:w:User:BrandonXLF

$(function() {

var vars = ['area', 'url', 'text', 'title', 'id', 'nnode', 'key'],

areas = [

'p-cactions',

'p-personal',

'p-personal-sticky-header',

'p-views',

'p-tb',

'left-navigation',

'p-navigation',

'p-interaction',

'footer',

'footer-places'

],

i = 0,

links = JSON.parse(mw.user.options.get('userjs-portletmanager') || '[]');

function randHex() {

return Math.floor(Math.random() * 256).toString(16).padStart(2, '0');

}

function randColor() {

return '#' + randHex() + randHex() + randHex();

}

function startedit(e) {

e.stopPropagation();

$('.plm .focused').removeClass('focused');

var el = $(this);

$('#largeeditor').val(el.val()).off('input keypress paste click').attr('placeholder', '');

$('#largeeditor').on('input keypress paste', function() {

el.addClass('focused');

el.val(this.value);

});

$('#largeeditor').on('click', function(e) {

e.stopPropagation();

el.addClass('focused');

});

}

function syncedit() {

if ($(this).is(':focus')) {

$('#largeeditor').val(this.value);

}

}

function row(link) {

var i = 0,

j = 0,

tr = $('').attr('data-row', '')

.append($('')

.append($('')

.click(function() {

$(this).closest('tr').remove();

})

)

.append(

''

)

);

for (i = 0; i < vars.length; i++) {

var td = $('').appendTo(tr),

input = vars[i] === 'area'

? $('')

.val(link ? link[vars[i]] : '')

.css('width', '100%')

.click(startedit);

input

.on('input keypress paste', syncedit)

.attr('data-name', vars[i])

.appendTo(td);

if (vars[i] === 'area') {

for (j = 0; j < areas.length; j++)

td.children().append(

$('')

.attr('selected', areas[j] == link.area ? '' : null)

);

}

if (vars[i] == 'key')

td.children().css('width', '3em');

}

$('#editor tr:last').before(tr);

}

function addLinks() {

var link;

$('.plm-portletitem').remove();

for (i = 0; i < links.length; i++) {

link = links[i];

try {

var linkEl = mw.util.addPortletLink(

link.area,

/^(https|http|):?\/\/.*/.exec(link.url)

? link.url.replace(/\$PAGENAME\$/g, encodeURIComponent(mw.config.get('wgPageName')))

: mw.util.getUrl(link.url.replace(/\$PAGENAME\$/g, mw.config.get('wgPageName'))),

link.text,

link.id || 'plm-portletitem-' + (i + 1),

link.title,

link.key,

link.nnode

);

linkEl.className += ' plm-portletitem';

} catch (e) {

console.error('PortletLinks.js: Unable to add portlet link to #' + link.area + ' for ' + link.url);

}

}

link = mw.util.addPortletLink('p-navigation', mw.util.getUrl('Special:BlankPage/PortletManager'), '(edit portlet links)');

if (link) link.className += ' plm-portletitem';

}

function save() {

var el = this;

links = [];

$('#editor').find('[data-row]').each(function() {

var item = {};

$(this).find('[data-name]').each(function() {

item[this.getAttribute('data-name')] = this.value;

});

links.push(item);

});

el.src = 'https://upload.wikimedia.org/wikipedia/commons/7/7a/Ajax_loader_metal_512.gif';

el.title = 'Saving...';

el.style.cursor = 'initial';

mw.user.options.set('userjs-portletmanager', JSON.stringify(links));

new mw.Api()

.saveOption('userjs-portletmanager', JSON.stringify(links))

.done(function(r) {

addLinks();

el.src = 'https://upload.wikimedia.org/wikipedia/commons/9/97/PICOL_icon_Floppy_disk.svg';

el.title = 'Save';

el.style.cursor = 'Pointer';

mw.notify(

r.options == 'success'

? 'Saved portlet links successfully!'

: 'An error occurred while saving.',

{

tag: 'portletlinks',

type: r.options == 'success' ? 'notice' : 'error'

}

);

})

.fail(function() {

el.src = 'https://upload.wikimedia.org/wikipedia/commons/9/97/PICOL_icon_Floppy_disk.svg';

el.title = 'Save';

el.style.cursor = 'Pointer';

mw.notify(

'An error occurred while saving.',

{

tag: 'portletlinks',

type: 'error'

}

);

});

}

addLinks();

if (window.location.search.includes('showportlets=true')) {

var el = $('

').prependTo(mw.util.$content);

for (i = 0; i < areas.length; i ++) {

var color = randColor();

$('#' + areas[i]).css({outline: '2px solid ' + color, outlineOffset: Math.round(Math.random() * 2) - 4 + 'px'});

el.append($('

')

.css({

border: '1px solid #000',

display: 'inline-block',

width: '1em',

height: '1em',

background: color,

marginRight: '5px',

verticalAlign: 'middle',

marginBottom: '5px'

}))

.append($('

')

.text(areas[i])

.css({

marginRight: '5px',

verticalAlign: 'middle',

marginBottom: '5px',

display: 'inline-block'

})

);

mw.util.addPortletLink(areas[i], '#', areas[i].toUpperCase());

}

}

if (mw.config.get('wgPageName') === 'Special:BlankPage/PortletManager') {

document.title = 'Manage custom portlet links - ' + mw.config.get('wgSiteName');

mw.util.addCSS(

'.plm input:focus, .plm select:focus, .plm textarea:focus, .plm .focused { outline:0; border-color: #36c; box-shadow: inset 0 0 0 1px #36c; }' +

'.plm button, .plm input, .plm select { border: 1px solid #888; padding: 4px; box-sizing: border-box; }' +

'.plm select { padding: 3px 4px; max-width: 10em; }' +

'#editor th { border: 1px solid #888; padding: 2px; }'

);

$(document).click(function() {

$('.plm .focused').removeClass('focused');

$('#largeeditor').off('input keypress paste click').val('').attr('placeholder', 'Select a cell to edit it.');

});

mw.loader.getScript('https://code.jquery.com/ui/1.12.1/jquery-ui.min.js').then(function() {

mw.util.$content.find('.mw-body-content').empty()

.addClass('plm')

.append('

Manage custom portlet links

')

.append($('

AreaURLTextTooltipIDNext nodeKey
').sortable({items: 'tr:not(.nodrag)', handle: '.drag'}).wrap('
'))

.append('

Remember to save your changes! Your common.js. Your common.css. Show portlets.

AreaThe portlet link region to add the link.
URLThe target URL of the link. Use $PAGENAME$ for the current URL-friendly full page name. Use // to link to a full URL.
TextThe text to show as the link. There is no default.
IDThe ID of the link HTML element.
TooltipTooltip (title) to show for the link.
Next node  CSS selector for the node that comes after the link. Use selector + * to have the selector be the previous node.
KeyThe access key for the link. See the article on access keys for more information.
');

$('#savecell').click(save);

$('#editor').append($('').find('td').append($('+').click(row)).parent());

for (i = 0; i < links.length; i++) row(links[i]);

});

}

});