MediaWiki:Common.js
Материал из PanoramaWiki
Версия от 01:01, 8 октября 2018; Sysadmin (обсуждение | вклад)
Замечание. Возможно, после сохранения вам придётся очистить кэш своего браузера, чтобы увидеть изменения.
- Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl-F5 или Ctrl-R (⌘-R на Mac)
- Google Chrome: Нажмите Ctrl-Shift-R (⌘-Shift-R на Mac)
- Internet Explorer: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl-F5
- Opera: Выберите очистку кэша в меню Инструменты → Настройки
(function (win, doc, nav, params, namespace, undefined) {
'use strict';
var util = {
keycode: {
ESCAPE: 27
},
getRequest: function () {
if (win.XDomainRequest) {
return new win.XDomainRequest();
}
if (win.XMLHttpRequest) {
return new win.XMLHttpRequest();
}
return null;
},
loadScript: function (src, parent, callback) {
var script = doc.createElement('script');
script.src = src;
script.addEventListener('load', function onLoad() {
this.removeEventListener('load', onLoad, false);
callback();
}, false);
parent.appendChild(script);
},
loadResource: function (url, callback) {
var request = this.getRequest();
if (!request) {
return null;
}
request.onload = function () {
callback(this.responseText);
};
request.open('GET', url, true);
win.setTimeout(function () {
request.send();
}, 0);
return request;
},
getStyleList: function (element) {
var value = element.getAttribute('class');
if (!value) {
return [];
}
return value.replace(/\s+/g, ' ').trim().split(' ');
},
hasStyleName: function (element, name) {
var list = this.getStyleList(element);
return !!list.length && list.indexOf(name) >= 0;
},
addStyleName: function (element, name) {
var list = this.getStyleList(element);
list.push(name);
element.setAttribute('class', list.join(' '));
},
removeStyleName: function (element, name) {
var list = this.getStyleList(element), index = list.indexOf(name);
if (index >= 0) {
list.splice(index, 1);
element.setAttribute('class', list.join(' '));
}
},
isSupportedBrowser: function () {
return 'localStorage' in win &&
'querySelector' in doc &&
'addEventListener' in win &&
'getComputedStyle' in win && doc.compatMode === 'CSS1Compat';
}
};
// Button
var Button = function Button(element, contentElement) {
var self = this;
element.addEventListener('click', function (event) {
self.onClick(event);
}, false);
this._element = element;
this._contentElement = contentElement || this._element;
};
Button.prototype.onClick = function () {};
Button.prototype.setText = function (text) {
this._contentElement.textContent = text;
return this;
};
// Select
var Select = function Select(form, itemName) {
var self = this;
form.reset();
form.addEventListener('click', function (event) {
var target = event.target;
if ('value' in target) {
self.onSelect(target.value);
}
}, false);
form.addEventListener('change', function (event) {
var target = event.target;
if (target.checked) {
self.onChange(target.value);
}
}, false);
this._form = form;
this._itemName = itemName;
};
Select.prototype.onSelect = function () {};
Select.prototype.onChange = function () {};
Select.prototype.isHidden = function () {
return this._form.hasAttribute('hidden');
};
Select.prototype.getItems = function () {
return this._form[this._itemName] || [];
};
Select.prototype.getValue = function () {
var i, n, items = this.getItems();
for (i = 0, n = items.length; i < n; i++) {
if (items[i].checked) {
return items[i].value;
}
}
return '';
};
Select.prototype.setValue = function (value) {
var i, n, items = this.getItems();
if (value === this.getValue()) {
return this;
}
for (i = 0, n = items.length; i < n; i++) {
if (items[i].value === value) {
items[i].checked = true;
this.onChange(value);
break;
}
}
return this;
};
Select.prototype.setHidden = function (hidden) {
hidden = !!hidden;
if (hidden !== this.isHidden()) {
this._form[(hidden ? 'set' : 'remove') + 'Attribute']('hidden', '');
this.onHiddenChange(hidden);
}
return this;
};
Select.prototype.onHiddenChange = function () {};
// Widget
var Widget = function Widget(options) {
var self = this,
active,
select = options.select,
element = options.element,
storage = options.storage,
autoMode = options.autoMode,
pageLang = options.pageLang,
userLang = options.userLang,
translator = options.translator,
leftButton = options.leftButton,
rightButton = options.rightButton,
closeButton = options.closeButton,
defaultLang;
this._element = element;
this._pageLang = pageLang;
this._translator = translator;
this.onStateChange = function (name, enable) {
if (name === 'active') {
storage.setValue('active', enable);
}
};
select.onSelect = function (lang) {
this.setHidden(true);
self.translate(lang);
};
select.onChange = function (lang) {
storage.setValue('lang', lang);
rightButton.setText(lang);
self.setState('invalid', lang === pageLang);
};
select.onHiddenChange = function (hidden) {
var docElem = doc.documentElement, formRect;
self.setState('expanded', !hidden);
if (!hidden) {
self.setState('right', false)
.setState('bottom', false);
element.focus();
formRect = this._form.getBoundingClientRect();
if (formRect.right + (win.pageXOffset || docElem.scrollLeft) + 1 >= Math.max(docElem.clientWidth, docElem.scrollWidth)) {
self.setState('right', true);
}
if (formRect.bottom + (win.pageYOffset || docElem.scrollTop) + 1 >= Math.max(docElem.clientHeight, docElem.scrollHeight)) {
self.setState('bottom', true);
}
}
};
element.addEventListener('blur', function () {
select.setHidden(true);
}, false);
element.addEventListener('keydown', function (event) {
switch (event.keyCode) {
case util.keycode.ESCAPE:
select.setHidden(true);
break;
}
}, false);
translator.on('error', function () {
this.abort();
self.setState('busy', false)
.setState('error', true);
});
translator.on('progress', function (progress) {
switch (progress) {
case 0:
self.setState('busy', true)
.setState('active', true);
break;
case 100:
self.setState('done', true)
.setState('busy', false);
break;
}
});
leftButton.onClick = function () {
select.setHidden(true);
self.translate(select.getValue());
};
rightButton.onClick = function () {
if (self.hasState('active')) {
translator.undo();
self.setState('busy', false)
.setState('done', false)
.setState('error', false)
.setState('active', false);
} else {
select.setHidden(!select.isHidden());
}
};
closeButton.onClick = function () {
select.setHidden(true);
};
defaultLang = storage.getValue('lang') || userLang;
if (defaultLang) {
select.setValue(defaultLang);
active = storage.getValue('active');
if (active || (autoMode && active === undefined)) {
this.translate(defaultLang);
}
}
};
Widget.prototype.hasState = function (name) {
return util.hasStyleName(this._element, 'yt-state_' + name);
};
Widget.prototype.setState = function (name, enable) {
var hasState = this.hasState(name);
enable = !!enable;
if (enable === hasState) {
return this;
}
util[(enable ? 'add' : 'remove') + 'StyleName'](
this._element, 'yt-state_' + name
);
this.onStateChange(name, enable);
return this;
};
Widget.prototype.translate = function (targetLang) {
if (targetLang && !this.hasState('active')) {
this._translator.translate(this._pageLang, targetLang);
}
return this;
};
Widget.prototype.onStateChange = function () {};
// Storage
var Storage = function Storage(name) {
this._name = name;
try {
this._data = win.JSON.parse(win.localStorage[name]);
} catch (error) {
this._data = {};
}
};
Storage.prototype.getValue = function (prop) {
return this._data[prop];
};
Storage.prototype.setValue = function (prop, value) {
this._data[prop] = value;
try {
win.localStorage[this._name] = win.JSON.stringify(this._data);
} catch (error) {}
};
var wrapper = doc.getElementById(params.widgetId);
if (!wrapper || !util.isSupportedBrowser()) {
return;
}
var initWidget = function () {
util.loadScript('https://yastatic.net/s3/translate/v18.9.4/js/tr_page.js', wrapper, function () {
util.loadResource('https://translate.yandex.net/website-widget/v1/widget.html',
function (responseText) {
var element;
if (!responseText) {
return;
}
wrapper.innerHTML = responseText;
element = wrapper.querySelector('.yt-widget');
if (params.widgetTheme) {
element.setAttribute('data-theme', params.widgetTheme);
}
new Widget({
select: new Select(element.querySelector('.yt-listbox'), 'yt-lang'),
element: element,
storage: new Storage('yt-widget'),
autoMode: params.autoMode === 'true',
pageLang: params.pageLang,
userLang: (nav.language || nav.userLanguage || '').split('-')[0],
translator: new namespace.PageTranslator({
srv: 'tr-url-widget',
sid: '5d424e35.5bba81e5.19361281',
url: 'https://translate.yandex.net/api/v1/tr.json/translate',
autoSync: true,
maxPortionLength: 600
}),
leftButton: new Button(element.querySelector('.yt-button_type_left')),
rightButton: new Button(
element.querySelector('.yt-button_type_right'),
element.querySelector('.yt-button_type_right > .yt-button__text')
),
closeButton: new Button(element.querySelector('.yt-button_type_close'))
});
}
);
});
};
if (doc.readyState === 'complete' || doc.readyState === 'interactive') {
initWidget();
} else {
doc.addEventListener('DOMContentLoaded', initWidget, false);
}
})(this, this.document, this.navigator, {"pageLang":"","autoMode":"","widgetTheme":"","widgetId":""}, this.yt = this.yt || {});
/* Размещённый здесь код JavaScript будет загружаться пользователям при обращении к каждой странице */