사용자:Hsl0/연구소/1.js: 두 판 사이의 차이
보이기
imported>Hsl0 편집 요약 없음 |
imported>Hsl0 편집 요약 없음 |
||
24번째 줄: | 24번째 줄: | ||
return $(form).find('input[type=checkbox]:checked').map(function() { | return $(form).find('input[type=checkbox]:checked').map(function() { | ||
return this.name; | return this.name; | ||
}).get(); | }).get().filter(function(name) { | ||
return name; | |||
}); | |||
} | } | ||
30번째 줄: | 32번째 줄: | ||
return $(form).find('input[type=checkbox]:not(:checked)').map(function() { | return $(form).find('input[type=checkbox]:not(:checked)').map(function() { | ||
return this.name; | return this.name; | ||
}).get(); | }).get().filter(function(name) { | ||
return name; | |||
}); | |||
} | } | ||
50번째 줄: | 54번째 줄: | ||
SelectDialog.static.title = '소도구 선택'; | SelectDialog.static.title = '소도구 선택'; | ||
SelectDialog.static.actions = [ | SelectDialog.static.actions = [ | ||
{ | { | ||
modes: 'default', | modes: 'default', | ||
90번째 줄: | 88번째 줄: | ||
modes: 'default', | modes: 'default', | ||
action: 'go-allowed', | action: 'go-allowed', | ||
label: '항상 | label: '항상 실행하는 소도구 관리' | ||
}); | }); | ||
96번째 줄: | 94번째 줄: | ||
SelectDialog.super.prototype.initialize.apply(this, arguments); | 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.defaultForm = new OO.ui.FormLayout(); | ||
this.defaultPanel = new OO.ui.PanelLayout({ | this.defaultPanel = new OO.ui.PanelLayout({ | ||
padded: true, | padded: true, | ||
content: [defaultMessage, this.defaultForm] | 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. | this.ignoredMessage = new OO.ui.PanelLayout({ | ||
expanded: false, | |||
classes: ['gadgethelper-message'], | |||
text: '무시한 소도구의 목록입니다. 해제할 소도구를 선택해 주세요.' | |||
}); | }); | ||
this.ignoredForm = new OO.ui.FormLayout(); | this.ignoredForm = new OO.ui.FormLayout(); | ||
this.ignoredPanel = new OO.ui.PanelLayout({ | this.ignoredPanel = new OO.ui.PanelLayout({ | ||
padded: true, | padded: true, | ||
content: [ignoredMessage, this.ignoredForm] | expanded: true, | ||
content: [this.ignoredMessage, this.ignoredForm] | |||
}); | }); | ||
this.stackLayout = new OO.ui.StackLayout({ | this.stackLayout = new OO.ui.StackLayout({ | ||
items: [this. | expanded: false, | ||
items: [this.loading, this.defaultPanel, this.ignoredPanel] | |||
}) | }) | ||
this.$body.append(this.stackLayout.$element); | this.$body.append(this.executing.$element) | ||
.append(this.saving.$element) | |||
.append(this.stackLayout.$element); | |||
}; | }; | ||
SelectDialog.prototype.createDefaultForm = function() { | SelectDialog.prototype.createDefaultForm = function() { | ||
var form = this.defaultForm; | var form = this.defaultForm; | ||
var auto = false; | |||
this.defaultForm.clearItems(); | this.defaultForm.clearItems(); | ||
130번째 줄: | 157번째 줄: | ||
selected: true | selected: true | ||
}); | }); | ||
all.on('change', function( | 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); | |||
if( | |||
var | |||
if( | |||
} | } | ||
}); | }); | ||
auto = false; | |||
} | |||
} | |||
}); | }); | ||
179번째 줄: | 173번째 줄: | ||
new OO.ui.FieldLayout(all, { | new OO.ui.FieldLayout(all, { | ||
label: '모두 선택', | label: '모두 선택', | ||
align: 'inline' | 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) { | SelectDialog.prototype.getSetupProcess = function(data) { | ||
var dialog = this; | var dialog = this; | ||
return SelectDialog.super.prototype.getSetupProcess.call(this, data) | return SelectDialog.super.prototype.getSetupProcess.call(this, data) | ||
.next(api.loadMessagesIfMissing(needed.map(function(key) { | .next(this.waitFor('load', api.loadMessagesIfMissing(needed.map(function(key) { | ||
return 'gadget-' + key; | return 'gadget-' + key; | ||
}))) | })))) | ||
.next(function() { | .next(function() { | ||
dialog.createDefaultForm(); | dialog.createDefaultForm(); | ||
200번째 줄: | 247번째 줄: | ||
dialog.actions.setMode('default'); | 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('잘못된 동작입니다'); | |||
} | |||
}; | }; | ||
209번째 줄: | 297번째 줄: | ||
case 'execute': | case 'execute': | ||
return process | return process | ||
.next(mw.loader.using(getSelected(this.defaultForm).map(function(gadget) { | .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() { | .next(function() { | ||
dialog.close(); | dialog.close(); | ||
218번째 줄: | 318번째 줄: | ||
case 'clear': | case 'clear': | ||
return process.next(function() { | |||
return process | 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; | break; | ||
case 'close': | case 'close': | ||
return process.next(function() { | 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(); | dialog.close(); | ||
}); | }); | ||
246번째 줄: | 360번째 줄: | ||
case 'go-ignored': | case 'go-ignored': | ||
return process | return process.next(Promise.all([ | ||
this.waitFor('save', this.saveIgnored()), | |||
this.waitFor('load', api.loadMessagesIfMissing(ignored.map(function(key) { | |||
. | |||
return 'gadget-' + 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; | break; | ||
case 'go-allowed': | case 'go-allowed': | ||
299번째 줄: | 409번째 줄: | ||
}; | }; | ||
var windowManager = new OO.ui.WindowManager(); | if(needed.length) { | ||
windowManager.$element.appendTo(document.body); | var windowManager = new OO.ui.WindowManager(); | ||
windowManager.$element.appendTo(document.body); | |||
var dialog = new SelectDialog({ | var dialog = new SelectDialog({ | ||
size: 'large' | |||
}); | }); | ||
windowManager.addWindows([dialog]); | windowManager.addWindows([dialog]); | ||
windowManager.openWindow(dialog); | windowManager.openWindow(dialog); | ||
} |
2021년 1월 1일 (금) 23:28 판
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);
}