사용자:Hsl0/연구소/1.js
보이기
참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.
- 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
- 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
- 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
var api = new mw.Api();
var gadgetsList = Object.keys(mw.loader.moduleRegistry).reduce(function(arr, key) {
if(key.startsWith('ext.gadget.')) arr.push(key.slice(11));
return arr;
}, []);
var needed = [];
var ignored = mw.user.options.get('userjs-gadgethelper-ignored');
ignored = ignored? ignored.split('|') : [];
var allowed = getAllowedGadgets();
var ignoredChanged = 0;
function getAllowedGadgets() {
var allowed = [];
var options = mw.user.options.values;
for(var key in options) {
if(key.startsWith('gadget-') && +options[key]) allowed.push(key.slice(7));
}
return allowed;
}
function getSelected(form) {
return $(form).find('input[type=checkbox]:checked').map(function() {
return this.name;
}).get().filter(function(name) {
return name;
});
}
function getUnselected(form) {
return $(form).find('input[type=checkbox]:not(:checked)').map(function() {
return this.name;
}).get().filter(function(name) {
return name;
});
}
$('.gadgethelper').each(function() {
needed = needed.concat(this.dataset.using.split(' '));
});
needed = needed.filter(function(gadget) {
return gadgetsList.includes(gadget) && !allowed.includes(gadget);
});
function SelectDialog(config) {
SelectDialog.super.call(this, config);
}
OO.inheritClass(SelectDialog, OO.ui.ProcessDialog);
SelectDialog.static.name = 'GadgetSelectDialog';
SelectDialog.static.title = '소도구 선택';
SelectDialog.static.actions = [
{
modes: 'default',
action: 'execute',
label: '실행',
flags: ['primary', 'progressive']
},
{
modes: 'ignored',
action: 'clear',
label: '해제',
flags: ['primary', 'progressive']
},
{
modes: 'default',
action: 'close',
label: '닫기',
flags: 'safe'
},
{
modes: 'ignored',
action: 'cancel',
label: '취소',
flags: 'safe'
},
{
modes: 'default',
action: 'go-ignored',
label: '무시된 소도구 보기'
},
];
if(!mw.user.isAnon()) SelectDialog.static.actions.push({
modes: 'default',
action: 'go-allowed',
label: '항상 실행하는 소도구 관리'
});
SelectDialog.prototype.initialize = function() {
SelectDialog.super.prototype.initialize.apply(this, arguments);
this.defaultMessage = new OO.ui.PanelLayout({
expanded: false,
classes: ['gadgethelper-message'],
text: '이 문서가 정상적으로 작동하려면 다음 소도구가 필요합니다. 일시적으로 실행할 소도구를 선택해 주세요.'
});
this.defaultForm = new OO.ui.FormLayout();
this.defaultPanel = new OO.ui.PanelLayout({
padded: true,
expanded: true,
content: [this.defaultMessage, this.defaultForm]
});
this.loading = new OO.ui.PanelLayout({
padded: true,
expanded: false,
text: '소도구 정보를 불러오고 있습니다... 잠시만 기다려 주세요.'
});
this.executing = new OO.ui.PanelLayout({
padded: true,
expanded: false,
hidden: true,
text: '소도구를 실행하는 중입니다...'
});
this.executing.toggle(false);
this.saving = new OO.ui.PanelLayout({
padded: true,
expanded: false,
hidden: true,
text: '설정을 저장하고 있습니다...'
});
this.saving.toggle(false);
this.ignoredMessage = new OO.ui.PanelLayout({
expanded: false,
classes: ['gadgethelper-message'],
text: '무시한 소도구의 목록입니다. 해제할 소도구를 선택해 주세요.'
});
this.ignoredForm = new OO.ui.FormLayout();
this.ignoredPanel = new OO.ui.PanelLayout({
padded: true,
expanded: true,
content: [this.ignoredMessage, this.ignoredForm]
});
this.stackLayout = new OO.ui.StackLayout({
expanded: false,
items: [this.loading, this.defaultPanel, this.ignoredPanel]
})
this.$body.append(this.executing.$element)
.append(this.saving.$element)
.append(this.stackLayout.$element);
};
SelectDialog.prototype.createDefaultForm = function() {
var form = this.defaultForm;
var auto = false;
this.defaultForm.clearItems();
var all = new OO.ui.CheckboxInputWidget({
selected: true
});
all.on('change', function(state) {
if(!auto) {
auto = true;
form.items.forEach(function(item) {
if(item instanceof OO.ui.HorizontalLayout) {
var checkbox = item.items[0].fieldWidget;
if(!checkbox.isDisabled()) checkbox.setSelected(state);
}
});
auto = false;
}
});
this.defaultForm.addItems([
new OO.ui.FieldLayout(all, {
label: '모두 선택',
align: 'inline',
classes: ['gadgethelper-selectall']
})
]);
this.defaultForm.addItems(needed.filter(function(gadget) {
return !ignored.includes(gadget);
}).map(function(gadget) {
var ignore = new OO.ui.ButtonWidget({
classes: ['gadgethelper-ignorebutton'],
label: '무시',
flags: 'destructive',
framed: false
});
ignore.on('click', function() {
ignore.clearFlags();
if(input.isDisabled()) {
var index = ignored.indexOf(gadget);
if(index > -1) ignored.splice(index, 1);
input.setDisabled(false);
if(index > 0) ignoredChanged--;
ignore.setLabel('무시');
ignore.setFlags('destructive');
} else {
ignoredChanged++;
ignored.push(gadget);
input.setSelected(false);
input.setDisabled(true);
ignore.setLabel('무시 해제');
ignore.setFlags('progressive');
}
});
var input = new OO.ui.CheckboxInputWidget({
name: gadget,
selected: true,
classes: ['gadgethelper-checkbox']
});
input.on('change', function() {
if(!auto) {
auto = true;
all.setSelected(false);
auto = false;
}
});
return new OO.ui.HorizontalLayout({
classes: ['gadgethelper-item'],
items: [
new OO.ui.FieldLayout(input, {
label: mw.msg('gadget-' + gadget),
align: 'inline'
}),
ignore
]
});
}));
};
SelectDialog.prototype.getSetupProcess = function(data) {
var dialog = this;
return SelectDialog.super.prototype.getSetupProcess.call(this, data)
.next(this.waitFor('load', api.loadMessagesIfMissing(needed.map(function(key) {
return 'gadget-' + key;
}))))
.next(function() {
dialog.createDefaultForm();
dialog.stackLayout.setItem(dialog.defaultPanel);
dialog.actions.setMode('default');
});
};
SelectDialog.prototype.saveIgnored = function() {
if(ignoredChanged) {
ignoredChanged = 0;
return api.saveOption('userjs-gadgethelper-ignored', ignored.join('|')).then(function() {
mw.user.options.set('userjs-gadgethelper-ignored', ignored.join('|'));
dialog.ignoredForm.clearItems();
dialog.createDefaultForm();
});
} else return Promise.resolve();
}
SelectDialog.prototype.waitFor = function(action, process) {
var dialog = this;
this.actions.setMode('wait');
switch(action) {
case 'load':
this.stackLayout.setItem(this.loading);
return process;
break;
case 'save':
this.saving.toggle(true);
return process.then(function() {
dialog.saving.toggle(false);
})
break;
case 'execute':
this.executing.toggle(true);
return process.then(function() {
dialog.executing.toggle(false);
})
break;
default:
throw new TypeError('잘못된 동작입니다');
}
};
SelectDialog.prototype.getActionProcess = function(action) {
var process = SelectDialog.super.prototype.getActionProcess.call(this, action);
var dialog = this;
switch(action) {
case 'execute':
return process
.next(function() {
dialog.defaultMessage.toggle(false);
dialog.defaultForm.items.forEach(function(item) {
if(item instanceof OO.ui.HorizontalLayout) {
item.items[0].fieldWidget.setDisabled(true);
item.items[1].setDisabled(true);
} else item.fieldWidget.setDisabled(true);
});
})
.next(Promise.all([
this.waitFor('save', this.saveIgnored()),
this.waitFor('execute', mw.loader.using(getSelected(this.defaultForm.$element).map(function(gadget) {
return 'ext.gadget.' + gadget;
})))
]))
.next(function() {
dialog.close();
});
break;
case 'clear':
return process.next(function() {
dialog.ignoredMessage.toggle(false);
dialog.ignoredForm.items.forEach(function(item) {
if(item instanceof OO.ui.HorizontalLayout) {
item.items[0].fieldWidget.setDisabled(true);
item.items[1].setDisabled(true);
} else item.fieldWidget.setDisabled(true);
});
ignored = getUnselected(dialog.ignoredForm.$element);
ignoredChanged = true;
return dialog.waitFor('save', dialog.saveIgnored());
}).next(function() {
dialog.ignoredMessage.toggle(true);
dialog.stackLayout.setItem(dialog.defaultPanel);
dialog.actions.setMode('default');
});
break;
case 'close':
return process.next(function() {
dialog.defaultMessage.toggle(false);
dialog.defaultForm.items.forEach(function(item) {
if(item instanceof OO.ui.HorizontalLayout) {
item.items[0].fieldWidget.setDisabled(true);
item.items[1].setDisabled(true);
} else item.fieldWidget.setDisabled(true);
});
}).next(this.waitFor('save', this.saveIgnored())).next(function() {
dialog.close();
});
break;
case 'cancel':
return process.next(function() {
dialog.stackLayout.setItem(dialog.defaultPanel);
dialog.actions.setMode('default');
});
break;
case 'go-ignored':
return process.next(Promise.all([
this.waitFor('save', this.saveIgnored()),
this.waitFor('load', api.loadMessagesIfMissing(ignored.map(function(key) {
return 'gadget-' + key;
})))
])).next(function() {
if(!dialog.ignoredForm.items.length) {
var all = new OO.ui.CheckboxInputWidget();
all.on('change', function(checked) {
dialog.ignoredForm.$element.find('input[type=checkbox]').prop('checked', checked);
});
dialog.ignoredForm.addItems([
new OO.ui.FieldLayout(all, {
label: '모두 선택',
align: 'inline'
})
]);
dialog.ignoredForm.addItems(ignored.map(function(gadget) {
return new OO.ui.FieldLayout(new OO.ui.CheckboxInputWidget({
name: gadget
}), {
label: mw.msg('gadget-' + gadget),
align: 'inline'
});
}));
}
dialog.stackLayout.setItem(dialog.ignoredPanel);
dialog.actions.setMode('ignored');
});
break;
case 'go-allowed':
return process.next(function() {
open('/wiki/%ED%8A%B9%EC%88%98:%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95#mw-prefsection-gadgets');
});
break;
}
return process.next(function() {
throw new TypeError('Wrong action called');
});
};
SelectDialog.prototype.getBodyHeight = function() {
return this.stackLayout.currentItem.$element.innerHeight(true);
};
if(needed.length) {
var windowManager = new OO.ui.WindowManager();
windowManager.$element.appendTo(document.body);
var dialog = new SelectDialog({
size: 'large'
});
windowManager.addWindows([dialog]);
windowManager.openWindow(dialog);
}