summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/refnotes/admin.js
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/lib/plugins/refnotes/admin.js')
-rw-r--r--platform/www/lib/plugins/refnotes/admin.js1035
1 files changed, 1035 insertions, 0 deletions
diff --git a/platform/www/lib/plugins/refnotes/admin.js b/platform/www/lib/plugins/refnotes/admin.js
new file mode 100644
index 0000000..d3a46dd
--- /dev/null
+++ b/platform/www/lib/plugins/refnotes/admin.js
@@ -0,0 +1,1035 @@
+let refnotes_admin = (function () {
+ let modified = false;
+
+
+ class NameMap extends Map {
+ constructor(sentinel) {
+ super();
+
+ this.sentinel = sentinel;
+ }
+
+ get(key) {
+ return key == '' ? this.sentinel : super.get(key);
+ }
+
+ has(key) {
+ return key == '' ? true : super.has(key);
+ }
+ }
+
+
+ class NamedObjectMap extends Map {
+ set(value) {
+ super.set(value.getName(), value);
+ }
+ }
+
+
+ function List(id) {
+ let list = jQuery(id);
+
+ function appendOption(value) {
+ jQuery('<option>')
+ .html(value)
+ .val(value)
+ .prop('sorting', value.replace(/:/g, '-').replace(/(-\w+)$/, '-$1'))
+ .appendTo(list);
+ }
+
+ function sortOptions() {
+ list.append(list.children().get().sort(function (a, b) {
+ return a.sorting > b.sorting ? 1 : -1;
+ }));
+ }
+
+ this.getSelectedValue = function () {
+ return list.val();
+ }
+
+ this.insertValue = function (value) {
+ appendOption(value);
+ sortOptions();
+
+ return list.children('[value="' + value + '"]').attr('selected', 'selected').val();
+ }
+
+ this.reload = function (values) {
+ list.empty();
+
+ for (let value of values.keys()) {
+ if (value != '') {
+ appendOption(value);
+ }
+ }
+
+ sortOptions();
+
+ return list.children(':first').attr('selected', 'selected').val();
+ }
+
+ this.removeValue = function (value) {
+ let option = list.children('[value="' + value + '"]');
+
+ if (option.length == 1) {
+ list.prop('selectedIndex', option.index() + (option.is(':last-child') ? -1 : 1));
+ option.remove();
+ }
+
+ return list.val();
+ }
+
+ this.renameValue = function (oldValue, newValue) {
+ if (list.children('[value="' + oldValue + '"]').remove().length == 1) {
+ this.insertValue(newValue);
+ }
+
+ return list.val();
+ }
+ }
+
+
+ let locale = (function () {
+ let lang = new Map();
+
+ function initialize() {
+ jQuery.each(jQuery('#refnotes-lang').html().split(/:eos:/), function (key, value) {
+ let match = value.match(/^\s*(\w+) : (.+)/);
+ if (match != null) {
+ lang.set(match[1], match[2]);
+ }
+ });
+ }
+
+ function getString(key) {
+ let string = lang.has(key) ? lang.get(key) : '';
+
+ if ((string.length > 0) && (arguments.length > 1)) {
+ for (let i = 1; i < arguments.length; i++) {
+ string = string.replace(new RegExp('\\{' + i + '\\}'), arguments[i]);
+ }
+ }
+
+ return string;
+ }
+
+ return {
+ initialize,
+ getString
+ }
+ })();
+
+
+ let server = (function () {
+ let timer = null;
+ let transaction = null;
+
+ function sendRequest(request, data, success) {
+ if (transaction == null) {
+ transaction = request;
+
+ jQuery.ajax({
+ cache : false,
+ data : data,
+ global : false,
+ success : success,
+ type : 'POST',
+ timeout : 10000,
+ url : DOKU_BASE + 'lib/exe/ajax.php',
+ beforeSend() {
+ setStatus('info', transaction);
+ },
+ error(xhr, status, message) {
+ setErrorStatus((status == 'parseerror') ? 'invalid_data' : transaction + '_failed', message);
+ },
+ dataFilter(data) {
+ let cookie = '{B27067E9-3DDA-4E31-9768-E66F23D18F4A}';
+ let match = data.match(new RegExp(cookie + '(.+?)' + cookie));
+
+ if ((match == null) || (match.length != 2)) {
+ throw 'Malformed response';
+ }
+
+ return match[1];
+ },
+ complete() {
+ transaction = null;
+ }
+ });
+ }
+ else {
+ setErrorStatus(request + '_failed', 'Server is busy');
+ }
+ }
+
+ function loadSettings() {
+ sendRequest('loading', {
+ call : 'refnotes-admin',
+ action : 'load-settings'
+ }, function (data) {
+ setSuccessStatus('loaded', 3000);
+ reloadSettings(data);
+ });
+ }
+
+ function saveSettings(settings) {
+ sendRequest('saving', {
+ call : 'refnotes-admin',
+ action : 'save-settings',
+ settings : JSON.stringify(settings)
+ }, function (data) {
+ if (data == 'saved') {
+ modified = false;
+
+ setSuccessStatus('saved', 10000);
+ }
+ else {
+ setErrorStatus('saving_failed', 'Server FS access error');
+ }
+ });
+ }
+
+ function setStatus(status, message) {
+ window.clearTimeout(timer);
+
+ if (message.match(/^\w+$/) != null) {
+ message = locale.getString(message);
+ }
+
+ jQuery('#server-status')
+ .removeClass()
+ .addClass(status)
+ .text(message);
+ }
+
+ function setErrorStatus(messageId, details) {
+ setStatus('error', locale.getString(messageId, details));
+ }
+
+ function setSuccessStatus(messageId, timeout) {
+ setStatus('success', messageId);
+
+ timer = window.setTimeout(function () {
+ setStatus('cleared', 'status');
+ }, timeout);
+ }
+
+ return {
+ loadSettings,
+ saveSettings
+ }
+ })();
+
+
+ let general = (function () {
+ let fields = new NamedObjectMap();
+ let defaults = new Map([
+ ['replace-footnotes' , false],
+ ['reference-db-enable' , false],
+ ['reference-db-namespace', ':refnotes:']
+ ]);
+
+ function Field(settingName) {
+ this.element = jQuery('#field-' + settingName);
+
+ this.element.change(this, function (event) {
+ event.data.updateDefault();
+ modified = true;
+ });
+
+ this.getName = function () {
+ return settingName;
+ }
+
+ this.updateDefault = function () {
+ this.element.parents('td').toggleClass('default', this.getValue() == defaults.get(settingName));
+ }
+
+ this.enable = function (enable) {
+ this.element.prop('disabled', !enable);
+ }
+ }
+
+ function CheckField(settingName) {
+ this.baseClass = Field;
+ this.baseClass(settingName);
+
+ this.setValue = function (value) {
+ this.element.attr('checked', value);
+ this.updateDefault();
+ }
+
+ this.getValue = function () {
+ return this.element.is(':checked');
+ }
+
+ this.setValue(defaults.get(settingName));
+ this.enable(false);
+ }
+
+ function TextField(settingName) {
+ this.baseClass = Field;
+ this.baseClass(settingName);
+
+ this.setValue = function (value) {
+ this.element.val(value);
+ this.updateDefault();
+ }
+
+ this.getValue = function () {
+ return this.element.val();
+ }
+
+ this.setValue(defaults.get(settingName));
+ this.enable(false);
+ }
+
+ function initialize() {
+ fields.set(new CheckField('replace-footnotes'));
+ fields.set(new CheckField('reference-db-enable'));
+ fields.set(new TextField('reference-db-namespace'));
+
+ jQuery('#field-reference-db-namespace').css('width', '19em');
+ }
+
+ function reload(settings) {
+ for (let name in settings) {
+ if (fields.has(name)) {
+ fields.get(name).setValue(settings[name]);
+ }
+ }
+
+ for (let field of fields.values()) {
+ field.enable(true);
+ }
+ }
+
+ function getSettings() {
+ let settings = {};
+
+ for (let [name, field] of fields) {
+ settings[name] = field.getValue();
+ }
+
+ return settings;
+ }
+
+ return {
+ initialize,
+ reload,
+ getSettings
+ }
+ })();
+
+
+ let namespaces = (function () {
+ let list = null;
+ let fields = new NamedObjectMap();
+ let namespaces = new NameMap(new DefaultNamespace());
+ let current = namespaces.get('');
+ let defaults = new Map([
+ ['refnote-id' , 'numeric'],
+ ['reference-base' , 'super'],
+ ['reference-font-weight', 'normal'],
+ ['reference-font-style' , 'normal'],
+ ['reference-format' , 'right-parent'],
+ ['reference-group' , 'group-none'],
+ ['reference-render' , 'basic'],
+ ['multi-ref-id' , 'ref-counter'],
+ ['note-preview' , 'popup'],
+ ['notes-separator' , '100%'],
+ ['note-text-align' , 'justify'],
+ ['note-font-size' , 'normal'],
+ ['note-render' , 'basic'],
+ ['note-id-base' , 'super'],
+ ['note-id-font-weight' , 'normal'],
+ ['note-id-font-style' , 'normal'],
+ ['note-id-format' , 'right-parent'],
+ ['back-ref-caret' , 'none'],
+ ['back-ref-base' , 'super'],
+ ['back-ref-font-weight' , 'bold'],
+ ['back-ref-font-style' , 'normal'],
+ ['back-ref-format' , 'note-id'],
+ ['back-ref-separator' , 'comma'],
+ ['scoping' , 'reset']
+ ]);
+
+ function DefaultNamespace() {
+ this.isReadOnly = function () {
+ return true;
+ }
+
+ this.setName = function (newName) {
+ }
+
+ this.getName = function () {
+ return '';
+ }
+
+ this.setStyle = function (name, value) {
+ }
+
+ this.getStyle = function (name) {
+ return defaults.get(name);
+ }
+
+ this.getStyleInheritance = function (name) {
+ return 'default';
+ }
+
+ this.getSettings = function () {
+ return {};
+ }
+ }
+
+ function Namespace(name, data) {
+ let styles = data ? new Map(Object.entries(data)) : new Map();
+
+ function getParent() {
+ let parent = name.replace(/\w*:$/, '');
+
+ while (!namespaces.has(parent)) {
+ parent = parent.replace(/\w*:$/, '');
+ }
+
+ return namespaces.get(parent);
+ }
+
+ this.isReadOnly = function () {
+ return false;
+ }
+
+ this.setName = function (newName) {
+ name = newName;
+ }
+
+ this.getName = function () {
+ return name;
+ }
+
+ this.setStyle = function (name, value) {
+ if (value == 'inherit') {
+ styles.delete(name);
+ }
+ else {
+ styles.set(name, value);
+ }
+ }
+
+ this.getStyle = function (name) {
+ let result;
+
+ if (styles.has(name)) {
+ result = styles.get(name);
+ }
+ else {
+ result = getParent().getStyle(name);
+ }
+
+ return result;
+ }
+
+ this.getStyleInheritance = function (name) {
+ let result = '';
+
+ if (!styles.has(name)) {
+ result = getParent().getStyleInheritance(name) || 'inherited';
+ }
+
+ return result;
+ }
+
+ this.getSettings = function () {
+ let settings = {};
+
+ for (let [name, style] of styles) {
+ settings[name] = style;
+ }
+
+ return settings;
+ }
+ }
+
+ function Field(styleName) {
+ this.element = jQuery('#field-' + styleName);
+
+ this.getName = function () {
+ return styleName;
+ }
+
+ this.updateInheretance = function () {
+ this.element.parents('td')
+ .removeClass('default inherited')
+ .addClass(current.getStyleInheritance(styleName));
+ }
+ }
+
+ function SelectField(styleName) {
+ this.baseClass = Field;
+ this.baseClass(styleName);
+
+ let combo = this.element;
+
+ combo.change(this, function (event) {
+ event.data.onChange();
+ });
+
+ function setSelection(value) {
+ combo.val(value);
+ }
+
+ this.onChange = function () {
+ let value = combo.val();
+
+ current.setStyle(styleName, value);
+
+ this.updateInheretance();
+
+ if ((value == 'inherit') || current.isReadOnly()) {
+ setSelection(current.getStyle(styleName));
+ }
+
+ modified = true;
+ }
+
+ this.update = function () {
+ this.updateInheretance();
+ setSelection(current.getStyle(styleName));
+ combo.prop('disabled', current.isReadOnly());
+ }
+ }
+
+ function TextField(styleName, validate) {
+ this.baseClass = Field;
+ this.baseClass(styleName);
+
+ let edit = this.element;
+ let button = jQuery('#field-' + styleName + '-inherit');
+
+ edit.change(this, function (event) {
+ event.data.setValue(validate(edit.val()));
+ });
+
+ button.click(this, function (event) {
+ event.data.setValue('inherit');
+ });
+
+ this.setValue = function (value) {
+ current.setStyle(styleName, value);
+
+ this.updateInheretance();
+
+ if ((edit.val() != value) || (value == 'inherit') || current.isReadOnly()) {
+ edit.val(current.getStyle(styleName));
+ }
+
+ modified = true;
+ }
+
+ this.update = function () {
+ this.updateInheretance();
+
+ edit.val(current.getStyle(styleName));
+ edit.prop('disabled', current.isReadOnly());
+ button.prop('disabled', current.isReadOnly());
+ }
+ }
+
+ function initialize() {
+ list = new List('#select-namespaces');
+
+ fields.set(new SelectField('refnote-id'));
+ fields.set(new SelectField('reference-base'));
+ fields.set(new SelectField('reference-font-weight'));
+ fields.set(new SelectField('reference-font-style'));
+ fields.set(new SelectField('reference-format'));
+ fields.set(new SelectField('reference-group'));
+ fields.set(new SelectField('reference-render'));
+ fields.set(new SelectField('multi-ref-id'));
+ fields.set(new SelectField('note-preview'));
+ fields.set(new TextField('notes-separator', function (value) {
+ return (value.match(/(?:\d+\.?|\d*\.\d+)(?:%|em|px)|none/) != null) ? value : 'none';
+ }));
+ fields.set(new SelectField('note-text-align'));
+ fields.set(new SelectField('note-font-size'));
+ fields.set(new SelectField('note-render'));
+ fields.set(new SelectField('note-id-base'));
+ fields.set(new SelectField('note-id-font-weight'));
+ fields.set(new SelectField('note-id-font-style'));
+ fields.set(new SelectField('note-id-format'));
+ fields.set(new SelectField('back-ref-caret'));
+ fields.set(new SelectField('back-ref-base'));
+ fields.set(new SelectField('back-ref-font-weight'));
+ fields.set(new SelectField('back-ref-font-style'));
+ fields.set(new SelectField('back-ref-format'));
+ fields.set(new SelectField('back-ref-separator'));
+ fields.set(new SelectField('scoping'));
+
+ jQuery('#select-namespaces').change(onNamespaceChange);
+ jQuery('#name-namespaces').prop('disabled', true);
+ jQuery('#add-namespaces').click(onAddNamespace).prop('disabled', true);
+ jQuery('#rename-namespaces').click(onRenameNamespace).prop('disabled', true);
+ jQuery('#delete-namespaces').click(onDeleteNamespace).prop('disabled', true);
+
+ updateFields();
+ }
+
+ function onNamespaceChange(event) {
+ setCurrent(list.getSelectedValue());
+ }
+
+ function onAddNamespace(event) {
+ try {
+ let name = validateName(jQuery('#name-namespaces').val(), 'ns', namespaces);
+
+ namespaces.set(name, new Namespace(name));
+
+ setCurrent(list.insertValue(name));
+
+ modified = true;
+ }
+ catch (error) {
+ alert(error);
+ }
+ }
+
+ function onRenameNamespace(event) {
+ try {
+ let newName = validateName(jQuery('#name-namespaces').val(), 'ns', namespaces);
+ let oldName = current.getName();
+
+ current.setName(newName);
+
+ namespaces.delete(oldName);
+ namespaces.set(newName, current);
+
+ setCurrent(list.renameValue(oldName, newName));
+
+ modified = true;
+ }
+ catch (error) {
+ alert(error);
+ }
+ }
+
+ function onDeleteNamespace(event) {
+ if (confirm(locale.getString('delete_ns', current.getName()))) {
+ namespaces.delete(current.getName());
+
+ setCurrent(list.removeValue(current.getName()));
+
+ modified = true;
+ }
+ }
+
+ function reload(settings) {
+ namespaces.clear();
+
+ for (let name in settings) {
+ if (name.match(/^:$|^:.+?:$/) != null) {
+ namespaces.set(name, new Namespace(name, settings[name]));
+ }
+ }
+
+ jQuery('#name-namespaces').prop('disabled', false);
+ jQuery('#add-namespaces').prop('disabled', false);
+
+ setCurrent(list.reload(namespaces));
+ }
+
+ function setCurrent(name) {
+ current = namespaces.get(name);
+
+ updateFields();
+ }
+
+ function updateFields() {
+ jQuery('#name-namespaces').val(current.getName());
+ jQuery('#rename-namespaces').prop('disabled', current.isReadOnly());
+ jQuery('#delete-namespaces').prop('disabled', current.isReadOnly());
+
+ for (let field of fields.values()) {
+ field.update();
+ }
+ }
+
+ function getSettings() {
+ let settings = {};
+
+ for (let [name, namespace] of namespaces) {
+ settings[name] = namespace.getSettings();
+ }
+
+ return settings;
+ }
+
+ return {
+ initialize,
+ reload,
+ getSettings
+ }
+ })();
+
+
+ let notes = (function () {
+ let list = null;
+ let fields = new NamedObjectMap();
+ let notes = new NameMap(new EmptyNote());
+ let current = notes.get('');
+ let defaults = new Map([
+ ['inline' , false],
+ ['use-reference-base' , true],
+ ['use-reference-font-weight', true],
+ ['use-reference-font-style' , true],
+ ['use-reference-format' , true]
+ ]);
+ let inlineAttributes = [
+ 'use-reference-base',
+ 'use-reference-font-weight',
+ 'use-reference-font-style',
+ 'use-reference-format'
+ ];
+
+ function isInlineAttribute(name) {
+ return inlineAttributes.indexOf(name) != -1;
+ }
+
+ function EmptyNote() {
+ this.isReadOnly = function () {
+ return true;
+ }
+
+ this.setName = function (newName) {
+ }
+
+ this.getName = function () {
+ return '';
+ }
+
+ this.setText = function (text) {
+ }
+
+ this.getText = function () {
+ return '';
+ }
+
+ this.setAttribute = function (name, value) {
+ }
+
+ this.getAttribute = function (name) {
+ return defaults.get(name);
+ }
+
+ this.getSettings = function () {
+ return {};
+ }
+ }
+
+ function Note(name, data) {
+ let attributes = data ? new Map(Object.entries(data)) : new Map();
+
+ this.isReadOnly = function () {
+ return false;
+ }
+
+ this.setName = function (newName) {
+ name = newName;
+ }
+
+ this.getName = function () {
+ return name;
+ }
+
+ this.setText = function (text) {
+ attributes.set('text', text);
+ }
+
+ this.getText = function () {
+ return attributes.get('text');
+ }
+
+ this.setAttribute = function (name, value) {
+ attributes.set(name, value);
+ }
+
+ this.getAttribute = function (name) {
+ if (!attributes.has(name) || (isInlineAttribute(name) && !this.getAttribute('inline'))) {
+ return defaults.get(name);
+ }
+ else {
+ return attributes.get(name);
+ }
+ }
+
+ this.getSettings = function () {
+ let settings = {};
+
+ if (!this.getAttribute('inline')) {
+ for (let i in inlineAttributes) {
+ if (attributes.has(inlineAttributes[i])) {
+ attributes.delete(inlineAttributes[i]);
+ }
+ }
+ }
+
+ for (let [name, attribute] of attributes) {
+ settings[name] = attribute;
+ }
+
+ return settings;
+ }
+ }
+
+ function Field(attributeName) {
+ this.element = jQuery('#field-' + attributeName);
+
+ this.element.change(this, function (event) {
+ current.setAttribute(attributeName, event.data.getValue());
+ modified = true;
+ });
+
+ this.getName = function () {
+ return attributeName;
+ }
+
+ this.enable = function (enable) {
+ this.element.prop('disabled', !enable);
+ }
+ }
+
+ function CheckField(attributeName) {
+ this.baseClass = Field;
+ this.baseClass(attributeName);
+
+ this.setValue = function (value) {
+ this.element.attr('checked', value);
+ }
+
+ this.getValue = function () {
+ return this.element.is(':checked');
+ }
+
+ this.update = function () {
+ this.setValue(current.getAttribute(attributeName));
+ this.enable(!current.isReadOnly() && (!isInlineAttribute(attributeName) || current.getAttribute('inline')));
+ }
+ }
+
+ function InlineField() {
+ this.baseClass = CheckField;
+ this.baseClass('inline');
+
+ this.element.change(this, function (event) {
+ for (let i in inlineAttributes) {
+ fields.get(inlineAttributes[i]).update();
+ }
+ });
+ }
+
+ function initialize() {
+ list = new List('#select-notes');
+
+ fields.set(new InlineField());
+ fields.set(new CheckField('use-reference-base'));
+ fields.set(new CheckField('use-reference-font-weight'));
+ fields.set(new CheckField('use-reference-font-style'));
+ fields.set(new CheckField('use-reference-format'));
+
+ jQuery('#select-notes').change(onNoteChange);
+ jQuery('#name-notes').prop('disabled', true);
+ jQuery('#add-notes').click(onAddNote).prop('disabled', true);
+ jQuery('#rename-notes').click(onRenameNote).prop('disabled', true);
+ jQuery('#delete-notes').click(onDeleteNote).prop('disabled', true);
+ jQuery('#field-note-text').change(onTextChange);
+
+ updateFields();
+ }
+
+ function onNoteChange(event) {
+ setCurrent(list.getSelectedValue());
+ }
+
+ function onAddNote(event) {
+ try {
+ let name = validateName(jQuery('#name-notes').val(), 'note', notes);
+
+ notes.set(name, new Note(name));
+
+ setCurrent(list.insertValue(name));
+
+ modified = true;
+ }
+ catch (error) {
+ alert(error);
+ }
+ }
+
+ function onRenameNote(event) {
+ try {
+ let newName = validateName(jQuery('#name-notes').val(), 'note', notes);
+ let oldName = current.getName();
+
+ current.setName(newName);
+
+ notes.delete(oldName);
+ notes.set(newName, current);
+
+ setCurrent(list.renameValue(oldName, newName));
+
+ modified = true;
+ }
+ catch (error) {
+ alert(error);
+ }
+ }
+
+ function onDeleteNote(event) {
+ if (confirm(locale.getString('delete_note', current.getName()))) {
+ notes.delete(current.getName());
+
+ setCurrent(list.removeValue(current.getName()));
+
+ modified = true;
+ }
+ }
+
+ function onTextChange(event) {
+ current.setText(event.target.value);
+
+ modified = true;
+ }
+
+ function reload(settings) {
+ notes.clear();
+
+ for (let name in settings) {
+ if (name.match(/^:.+?\w$/) != null) {
+ notes.set(name, new Note(name, settings[name]));
+ }
+ }
+
+ jQuery('#name-notes').prop('disabled', false);
+ jQuery('#add-notes').prop('disabled', false);
+
+ setCurrent(list.reload(notes));
+ }
+
+ function setCurrent(name) {
+ current = notes.get(name);
+
+ updateFields();
+ }
+
+ function updateFields() {
+ jQuery('#name-notes').val(current.getName());
+ jQuery('#rename-notes').prop('disabled', current.isReadOnly());
+ jQuery('#delete-notes').prop('disabled', current.isReadOnly());
+ jQuery('#field-note-text').val(current.getText()).prop('disabled', current.isReadOnly());
+
+ for (let field of fields.values()) {
+ field.update();
+ }
+ }
+
+ function getSettings() {
+ let settings = {};
+
+ for (let [name, note] of notes) {
+ settings[name] = note.getSettings();
+ }
+
+ return settings;
+ }
+
+ return {
+ initialize,
+ reload,
+ getSettings
+ }
+ })();
+
+
+ function initialize() {
+ locale.initialize();
+ general.initialize();
+ namespaces.initialize();
+ notes.initialize();
+
+ jQuery('#save-config').click(function () {
+ saveSettings();
+ });
+
+ window.onbeforeunload = onBeforeUnload;
+
+ jQuery('#server-status').show();
+
+ server.loadSettings();
+ }
+
+ function reloadSettings(settings) {
+ general.reload(settings.general);
+ namespaces.reload(settings.namespaces);
+ notes.reload(settings.notes);
+ }
+
+ function saveSettings() {
+ let settings = {};
+
+ settings.general = general.getSettings();
+ settings.namespaces = namespaces.getSettings();
+ settings.notes = notes.getSettings();
+
+ server.saveSettings(settings);
+
+ scroll(0, 0);
+ }
+
+ function onBeforeUnload(event) {
+ if (modified) {
+ let message = locale.getString('unsaved');
+
+ (event || window.event).returnValue = message;
+
+ return message;
+ }
+ }
+
+ function validateName(name, type, existing) {
+ let names = name.split(':');
+
+ name = (type == 'ns') ? ':' : '';
+
+ for (let i = 0; i < names.length; i++) {
+ if (names[i] != '') {
+ /* ECMA regexp doesn't support POSIX character classes, so [a-zA-Z] is used instead of [[:alpha:]] */
+ if (names[i].match(/^[a-zA-Z]\w*$/) == null) {
+ name = '';
+ break;
+ }
+
+ name += (type == 'ns') ? names[i] + ':' : ':' + names[i];
+ }
+ }
+
+ if (name == '') {
+ throw locale.getString('invalid_' + type + '_name');
+ }
+
+ if (existing.has(name)) {
+ throw locale.getString(type + '_name_exists', name);
+ }
+
+ return name;
+ }
+
+ return {
+ initialize
+ }
+})();
+
+
+jQuery(function () {
+ if (jQuery('#refnotes-config').length != 0) {
+ refnotes_admin.initialize();
+ }
+});