1let refnotes_admin = (function () { 2 let modified = false; 3 4 5 class NameMap extends Map { 6 constructor(sentinel) { 7 super(); 8 9 this.sentinel = sentinel; 10 } 11 12 get(key) { 13 return key == '' ? this.sentinel : super.get(key); 14 } 15 16 has(key) { 17 return key == '' ? true : super.has(key); 18 } 19 } 20 21 22 class NamedObjectMap extends Map { 23 set(value) { 24 super.set(value.getName(), value); 25 } 26 } 27 28 29 function List(id) { 30 let list = jQuery(id); 31 32 function appendOption(value) { 33 jQuery('<option>') 34 .html(value) 35 .val(value) 36 .prop('sorting', value.replace(/:/g, '-').replace(/(-\w+)$/, '-$1')) 37 .appendTo(list); 38 } 39 40 function sortOptions() { 41 list.append(list.children().get().sort(function (a, b) { 42 return a.sorting > b.sorting ? 1 : -1; 43 })); 44 } 45 46 this.getSelectedValue = function () { 47 return list.val(); 48 } 49 50 this.insertValue = function (value) { 51 appendOption(value); 52 sortOptions(); 53 54 return list.children('[value="' + value + '"]').attr('selected', 'selected').val(); 55 } 56 57 this.reload = function (values) { 58 list.empty(); 59 60 for (let value of values.keys()) { 61 if (value != '') { 62 appendOption(value); 63 } 64 } 65 66 sortOptions(); 67 68 return list.children(':first').attr('selected', 'selected').val(); 69 } 70 71 this.removeValue = function (value) { 72 let option = list.children('[value="' + value + '"]'); 73 74 if (option.length == 1) { 75 list.prop('selectedIndex', option.index() + (option.is(':last-child') ? -1 : 1)); 76 option.remove(); 77 } 78 79 return list.val(); 80 } 81 82 this.renameValue = function (oldValue, newValue) { 83 if (list.children('[value="' + oldValue + '"]').remove().length == 1) { 84 this.insertValue(newValue); 85 } 86 87 return list.val(); 88 } 89 } 90 91 92 let locale = (function () { 93 let lang = new Map(); 94 95 function initialize() { 96 jQuery.each(jQuery('#refnotes-lang').html().split(/:eos:/), function (key, value) { 97 let match = value.match(/^\s*(\w+) : (.+)/); 98 if (match != null) { 99 lang.set(match[1], match[2]); 100 } 101 }); 102 } 103 104 function getString(key) { 105 let string = lang.has(key) ? lang.get(key) : ''; 106 107 if ((string.length > 0) && (arguments.length > 1)) { 108 for (let i = 1; i < arguments.length; i++) { 109 string = string.replace(new RegExp('\\{' + i + '\\}'), arguments[i]); 110 } 111 } 112 113 return string; 114 } 115 116 return { 117 initialize, 118 getString 119 } 120 })(); 121 122 123 let server = (function () { 124 let timer = null; 125 let transaction = null; 126 127 function sendRequest(request, data, success) { 128 if (transaction == null) { 129 transaction = request; 130 131 jQuery.ajax({ 132 cache : false, 133 data : data, 134 global : false, 135 success : success, 136 type : 'POST', 137 timeout : 10000, 138 url : DOKU_BASE + 'lib/exe/ajax.php', 139 beforeSend() { 140 setStatus('info', transaction); 141 }, 142 error(xhr, status, message) { 143 setErrorStatus((status == 'parseerror') ? 'invalid_data' : transaction + '_failed', message); 144 }, 145 dataFilter(data) { 146 let cookie = '{B27067E9-3DDA-4E31-9768-E66F23D18F4A}'; 147 let match = data.match(new RegExp(cookie + '(.+?)' + cookie)); 148 149 if ((match == null) || (match.length != 2)) { 150 throw 'Malformed response'; 151 } 152 153 return match[1]; 154 }, 155 complete() { 156 transaction = null; 157 } 158 }); 159 } 160 else { 161 setErrorStatus(request + '_failed', 'Server is busy'); 162 } 163 } 164 165 function loadSettings() { 166 sendRequest('loading', { 167 call : 'refnotes-admin', 168 action : 'load-settings' 169 }, function (data) { 170 setSuccessStatus('loaded', 3000); 171 reloadSettings(data); 172 }); 173 } 174 175 function saveSettings(settings) { 176 sendRequest('saving', { 177 call : 'refnotes-admin', 178 action : 'save-settings', 179 settings : JSON.stringify(settings) 180 }, function (data) { 181 if (data == 'saved') { 182 modified = false; 183 184 setSuccessStatus('saved', 10000); 185 } 186 else { 187 setErrorStatus('saving_failed', 'Server FS access error'); 188 } 189 }); 190 } 191 192 function setStatus(status, message) { 193 window.clearTimeout(timer); 194 195 if (message.match(/^\w+$/) != null) { 196 message = locale.getString(message); 197 } 198 199 jQuery('#server-status') 200 .removeClass() 201 .addClass(status) 202 .text(message); 203 } 204 205 function setErrorStatus(messageId, details) { 206 setStatus('error', locale.getString(messageId, details)); 207 } 208 209 function setSuccessStatus(messageId, timeout) { 210 setStatus('success', messageId); 211 212 timer = window.setTimeout(function () { 213 setStatus('cleared', 'status'); 214 }, timeout); 215 } 216 217 return { 218 loadSettings, 219 saveSettings 220 } 221 })(); 222 223 224 let general = (function () { 225 let fields = new NamedObjectMap(); 226 let defaults = new Map([ 227 ['replace-footnotes' , false], 228 ['reference-db-enable' , false], 229 ['reference-db-namespace', ':refnotes:'] 230 ]); 231 232 function Field(settingName) { 233 this.element = jQuery('#field-' + settingName); 234 235 this.element.change(this, function (event) { 236 event.data.updateDefault(); 237 modified = true; 238 }); 239 240 this.getName = function () { 241 return settingName; 242 } 243 244 this.updateDefault = function () { 245 this.element.parents('td').toggleClass('default', this.getValue() == defaults.get(settingName)); 246 } 247 248 this.enable = function (enable) { 249 this.element.prop('disabled', !enable); 250 } 251 } 252 253 function CheckField(settingName) { 254 this.baseClass = Field; 255 this.baseClass(settingName); 256 257 this.setValue = function (value) { 258 this.element.attr('checked', value); 259 this.updateDefault(); 260 } 261 262 this.getValue = function () { 263 return this.element.is(':checked'); 264 } 265 266 this.setValue(defaults.get(settingName)); 267 this.enable(false); 268 } 269 270 function TextField(settingName) { 271 this.baseClass = Field; 272 this.baseClass(settingName); 273 274 this.setValue = function (value) { 275 this.element.val(value); 276 this.updateDefault(); 277 } 278 279 this.getValue = function () { 280 return this.element.val(); 281 } 282 283 this.setValue(defaults.get(settingName)); 284 this.enable(false); 285 } 286 287 function initialize() { 288 fields.set(new CheckField('replace-footnotes')); 289 fields.set(new CheckField('reference-db-enable')); 290 fields.set(new TextField('reference-db-namespace')); 291 292 jQuery('#field-reference-db-namespace').css('width', '19em'); 293 } 294 295 function reload(settings) { 296 for (let name in settings) { 297 if (fields.has(name)) { 298 fields.get(name).setValue(settings[name]); 299 } 300 } 301 302 for (let field of fields.values()) { 303 field.enable(true); 304 } 305 } 306 307 function getSettings() { 308 let settings = {}; 309 310 for (let [name, field] of fields) { 311 settings[name] = field.getValue(); 312 } 313 314 return settings; 315 } 316 317 return { 318 initialize, 319 reload, 320 getSettings 321 } 322 })(); 323 324 325 let namespaces = (function () { 326 let list = null; 327 let fields = new NamedObjectMap(); 328 let namespaces = new NameMap(new DefaultNamespace()); 329 let current = namespaces.get(''); 330 let defaults = new Map([ 331 ['refnote-id' , 'numeric'], 332 ['reference-base' , 'super'], 333 ['reference-font-weight', 'normal'], 334 ['reference-font-style' , 'normal'], 335 ['reference-format' , 'right-parent'], 336 ['reference-group' , 'group-none'], 337 ['reference-render' , 'basic'], 338 ['multi-ref-id' , 'ref-counter'], 339 ['note-preview' , 'popup'], 340 ['notes-separator' , '100%'], 341 ['note-text-align' , 'justify'], 342 ['note-font-size' , 'reduced'], 343 ['note-render' , 'basic'], 344 ['note-id-base' , 'super'], 345 ['note-id-font-weight' , 'normal'], 346 ['note-id-font-style' , 'normal'], 347 ['note-id-format' , 'right-parent'], 348 ['back-ref-caret' , 'none'], 349 ['back-ref-base' , 'super'], 350 ['back-ref-font-weight' , 'bold'], 351 ['back-ref-font-style' , 'normal'], 352 ['back-ref-format' , 'note-id'], 353 ['back-ref-separator' , 'comma'], 354 ['scoping' , 'reset'] 355 ]); 356 357 function DefaultNamespace() { 358 this.isReadOnly = function () { 359 return true; 360 } 361 362 this.setName = function (newName) { 363 } 364 365 this.getName = function () { 366 return ''; 367 } 368 369 this.setStyle = function (name, value) { 370 } 371 372 this.getStyle = function (name) { 373 return defaults.get(name); 374 } 375 376 this.getStyleInheritance = function (name) { 377 return 'default'; 378 } 379 380 this.getSettings = function () { 381 return {}; 382 } 383 } 384 385 function Namespace(name, data) { 386 let styles = data ? new Map(Object.entries(data)) : new Map(); 387 388 function getParent() { 389 let parent = name.replace(/\w*:$/, ''); 390 391 while (!namespaces.has(parent)) { 392 parent = parent.replace(/\w*:$/, ''); 393 } 394 395 return namespaces.get(parent); 396 } 397 398 this.isReadOnly = function () { 399 return false; 400 } 401 402 this.setName = function (newName) { 403 name = newName; 404 } 405 406 this.getName = function () { 407 return name; 408 } 409 410 this.setStyle = function (name, value) { 411 if (value == 'inherit') { 412 styles.delete(name); 413 } 414 else { 415 styles.set(name, value); 416 } 417 } 418 419 this.getStyle = function (name) { 420 let result; 421 422 if (styles.has(name)) { 423 result = styles.get(name); 424 } 425 else { 426 result = getParent().getStyle(name); 427 } 428 429 return result; 430 } 431 432 this.getStyleInheritance = function (name) { 433 let result = ''; 434 435 if (!styles.has(name)) { 436 result = getParent().getStyleInheritance(name) || 'inherited'; 437 } 438 439 return result; 440 } 441 442 this.getSettings = function () { 443 let settings = {}; 444 445 for (let [name, style] of styles) { 446 settings[name] = style; 447 } 448 449 return settings; 450 } 451 } 452 453 function Field(styleName) { 454 this.element = jQuery('#field-' + styleName); 455 456 this.getName = function () { 457 return styleName; 458 } 459 460 this.updateInheretance = function () { 461 this.element.parents('td') 462 .removeClass('default inherited') 463 .addClass(current.getStyleInheritance(styleName)); 464 } 465 } 466 467 function SelectField(styleName) { 468 this.baseClass = Field; 469 this.baseClass(styleName); 470 471 let combo = this.element; 472 473 combo.change(this, function (event) { 474 event.data.onChange(); 475 }); 476 477 function setSelection(value) { 478 combo.val(value); 479 } 480 481 this.onChange = function () { 482 let value = combo.val(); 483 484 current.setStyle(styleName, value); 485 486 this.updateInheretance(); 487 488 if ((value == 'inherit') || current.isReadOnly()) { 489 setSelection(current.getStyle(styleName)); 490 } 491 492 modified = true; 493 } 494 495 this.update = function () { 496 this.updateInheretance(); 497 setSelection(current.getStyle(styleName)); 498 combo.prop('disabled', current.isReadOnly()); 499 } 500 } 501 502 function TextField(styleName, validate) { 503 this.baseClass = Field; 504 this.baseClass(styleName); 505 506 let edit = this.element; 507 let button = jQuery('#field-' + styleName + '-inherit'); 508 509 edit.change(this, function (event) { 510 event.data.setValue(validate(edit.val())); 511 }); 512 513 button.click(this, function (event) { 514 event.data.setValue('inherit'); 515 }); 516 517 this.setValue = function (value) { 518 current.setStyle(styleName, value); 519 520 this.updateInheretance(); 521 522 if ((edit.val() != value) || (value == 'inherit') || current.isReadOnly()) { 523 edit.val(current.getStyle(styleName)); 524 } 525 526 modified = true; 527 } 528 529 this.update = function () { 530 this.updateInheretance(); 531 532 edit.val(current.getStyle(styleName)); 533 edit.prop('disabled', current.isReadOnly()); 534 button.prop('disabled', current.isReadOnly()); 535 } 536 } 537 538 function initialize() { 539 list = new List('#select-namespaces'); 540 541 fields.set(new SelectField('refnote-id')); 542 fields.set(new SelectField('reference-base')); 543 fields.set(new SelectField('reference-font-weight')); 544 fields.set(new SelectField('reference-font-style')); 545 fields.set(new SelectField('reference-format')); 546 fields.set(new SelectField('reference-group')); 547 fields.set(new SelectField('reference-render')); 548 fields.set(new SelectField('multi-ref-id')); 549 fields.set(new SelectField('note-preview')); 550 fields.set(new TextField('notes-separator', function (value) { 551 return (value.match(/(?:\d+\.?|\d*\.\d+)(?:%|em|px)|none/) != null) ? value : 'none'; 552 })); 553 fields.set(new SelectField('note-text-align')); 554 fields.set(new SelectField('note-font-size')); 555 fields.set(new SelectField('note-render')); 556 fields.set(new SelectField('note-id-base')); 557 fields.set(new SelectField('note-id-font-weight')); 558 fields.set(new SelectField('note-id-font-style')); 559 fields.set(new SelectField('note-id-format')); 560 fields.set(new SelectField('back-ref-caret')); 561 fields.set(new SelectField('back-ref-base')); 562 fields.set(new SelectField('back-ref-font-weight')); 563 fields.set(new SelectField('back-ref-font-style')); 564 fields.set(new SelectField('back-ref-format')); 565 fields.set(new SelectField('back-ref-separator')); 566 fields.set(new SelectField('scoping')); 567 568 jQuery('#select-namespaces').change(onNamespaceChange); 569 jQuery('#name-namespaces').prop('disabled', true); 570 jQuery('#add-namespaces').click(onAddNamespace).prop('disabled', true); 571 jQuery('#rename-namespaces').click(onRenameNamespace).prop('disabled', true); 572 jQuery('#delete-namespaces').click(onDeleteNamespace).prop('disabled', true); 573 574 updateFields(); 575 } 576 577 function onNamespaceChange(event) { 578 setCurrent(list.getSelectedValue()); 579 } 580 581 function onAddNamespace(event) { 582 try { 583 let name = validateName(jQuery('#name-namespaces').val(), 'ns', namespaces); 584 585 namespaces.set(name, new Namespace(name)); 586 587 setCurrent(list.insertValue(name)); 588 589 modified = true; 590 } 591 catch (error) { 592 alert(error); 593 } 594 } 595 596 function onRenameNamespace(event) { 597 try { 598 let newName = validateName(jQuery('#name-namespaces').val(), 'ns', namespaces); 599 let oldName = current.getName(); 600 601 current.setName(newName); 602 603 namespaces.delete(oldName); 604 namespaces.set(newName, current); 605 606 setCurrent(list.renameValue(oldName, newName)); 607 608 modified = true; 609 } 610 catch (error) { 611 alert(error); 612 } 613 } 614 615 function onDeleteNamespace(event) { 616 if (confirm(locale.getString('delete_ns', current.getName()))) { 617 namespaces.delete(current.getName()); 618 619 setCurrent(list.removeValue(current.getName())); 620 621 modified = true; 622 } 623 } 624 625 function reload(settings) { 626 namespaces.clear(); 627 628 for (let name in settings) { 629 if (name.match(/^:$|^:.+?:$/) != null) { 630 namespaces.set(name, new Namespace(name, settings[name])); 631 } 632 } 633 634 jQuery('#name-namespaces').prop('disabled', false); 635 jQuery('#add-namespaces').prop('disabled', false); 636 637 setCurrent(list.reload(namespaces)); 638 } 639 640 function setCurrent(name) { 641 current = namespaces.get(name); 642 643 updateFields(); 644 } 645 646 function updateFields() { 647 jQuery('#name-namespaces').val(current.getName()); 648 jQuery('#rename-namespaces').prop('disabled', current.isReadOnly()); 649 jQuery('#delete-namespaces').prop('disabled', current.isReadOnly()); 650 651 for (let field of fields.values()) { 652 field.update(); 653 } 654 } 655 656 function getSettings() { 657 let settings = {}; 658 659 for (let [name, namespace] of namespaces) { 660 settings[name] = namespace.getSettings(); 661 } 662 663 return settings; 664 } 665 666 return { 667 initialize, 668 reload, 669 getSettings 670 } 671 })(); 672 673 674 let notes = (function () { 675 let list = null; 676 let fields = new NamedObjectMap(); 677 let notes = new NameMap(new EmptyNote()); 678 let current = notes.get(''); 679 let defaults = new Map([ 680 ['inline' , false], 681 ['use-reference-base' , true], 682 ['use-reference-font-weight', true], 683 ['use-reference-font-style' , true], 684 ['use-reference-format' , true] 685 ]); 686 let inlineAttributes = [ 687 'use-reference-base', 688 'use-reference-font-weight', 689 'use-reference-font-style', 690 'use-reference-format' 691 ]; 692 693 function isInlineAttribute(name) { 694 return inlineAttributes.indexOf(name) != -1; 695 } 696 697 function EmptyNote() { 698 this.isReadOnly = function () { 699 return true; 700 } 701 702 this.setName = function (newName) { 703 } 704 705 this.getName = function () { 706 return ''; 707 } 708 709 this.setText = function (text) { 710 } 711 712 this.getText = function () { 713 return ''; 714 } 715 716 this.setAttribute = function (name, value) { 717 } 718 719 this.getAttribute = function (name) { 720 return defaults.get(name); 721 } 722 723 this.getSettings = function () { 724 return {}; 725 } 726 } 727 728 function Note(name, data) { 729 let attributes = data ? new Map(Object.entries(data)) : new Map(); 730 731 this.isReadOnly = function () { 732 return false; 733 } 734 735 this.setName = function (newName) { 736 name = newName; 737 } 738 739 this.getName = function () { 740 return name; 741 } 742 743 this.setText = function (text) { 744 attributes.set('text', text); 745 } 746 747 this.getText = function () { 748 return attributes.get('text'); 749 } 750 751 this.setAttribute = function (name, value) { 752 attributes.set(name, value); 753 } 754 755 this.getAttribute = function (name) { 756 if (!attributes.has(name) || (isInlineAttribute(name) && !this.getAttribute('inline'))) { 757 return defaults.get(name); 758 } 759 else { 760 return attributes.get(name); 761 } 762 } 763 764 this.getSettings = function () { 765 let settings = {}; 766 767 if (!this.getAttribute('inline')) { 768 for (let i in inlineAttributes) { 769 if (attributes.has(inlineAttributes[i])) { 770 attributes.delete(inlineAttributes[i]); 771 } 772 } 773 } 774 775 for (let [name, attribute] of attributes) { 776 settings[name] = attribute; 777 } 778 779 return settings; 780 } 781 } 782 783 function Field(attributeName) { 784 this.element = jQuery('#field-' + attributeName); 785 786 this.element.change(this, function (event) { 787 current.setAttribute(attributeName, event.data.getValue()); 788 modified = true; 789 }); 790 791 this.getName = function () { 792 return attributeName; 793 } 794 795 this.enable = function (enable) { 796 this.element.prop('disabled', !enable); 797 } 798 } 799 800 function CheckField(attributeName) { 801 this.baseClass = Field; 802 this.baseClass(attributeName); 803 804 this.setValue = function (value) { 805 this.element.attr('checked', value); 806 } 807 808 this.getValue = function () { 809 return this.element.is(':checked'); 810 } 811 812 this.update = function () { 813 this.setValue(current.getAttribute(attributeName)); 814 this.enable(!current.isReadOnly() && (!isInlineAttribute(attributeName) || current.getAttribute('inline'))); 815 } 816 } 817 818 function InlineField() { 819 this.baseClass = CheckField; 820 this.baseClass('inline'); 821 822 this.element.change(this, function (event) { 823 for (let i in inlineAttributes) { 824 fields.get(inlineAttributes[i]).update(); 825 } 826 }); 827 } 828 829 function initialize() { 830 list = new List('#select-notes'); 831 832 fields.set(new InlineField()); 833 fields.set(new CheckField('use-reference-base')); 834 fields.set(new CheckField('use-reference-font-weight')); 835 fields.set(new CheckField('use-reference-font-style')); 836 fields.set(new CheckField('use-reference-format')); 837 838 jQuery('#select-notes').change(onNoteChange); 839 jQuery('#name-notes').prop('disabled', true); 840 jQuery('#add-notes').click(onAddNote).prop('disabled', true); 841 jQuery('#rename-notes').click(onRenameNote).prop('disabled', true); 842 jQuery('#delete-notes').click(onDeleteNote).prop('disabled', true); 843 jQuery('#field-note-text').change(onTextChange); 844 845 updateFields(); 846 } 847 848 function onNoteChange(event) { 849 setCurrent(list.getSelectedValue()); 850 } 851 852 function onAddNote(event) { 853 try { 854 let name = validateName(jQuery('#name-notes').val(), 'note', notes); 855 856 notes.set(name, new Note(name)); 857 858 setCurrent(list.insertValue(name)); 859 860 modified = true; 861 } 862 catch (error) { 863 alert(error); 864 } 865 } 866 867 function onRenameNote(event) { 868 try { 869 let newName = validateName(jQuery('#name-notes').val(), 'note', notes); 870 let oldName = current.getName(); 871 872 current.setName(newName); 873 874 notes.delete(oldName); 875 notes.set(newName, current); 876 877 setCurrent(list.renameValue(oldName, newName)); 878 879 modified = true; 880 } 881 catch (error) { 882 alert(error); 883 } 884 } 885 886 function onDeleteNote(event) { 887 if (confirm(locale.getString('delete_note', current.getName()))) { 888 notes.delete(current.getName()); 889 890 setCurrent(list.removeValue(current.getName())); 891 892 modified = true; 893 } 894 } 895 896 function onTextChange(event) { 897 current.setText(event.target.value); 898 899 modified = true; 900 } 901 902 function reload(settings) { 903 notes.clear(); 904 905 for (let name in settings) { 906 if (name.match(/^:.+?\w$/) != null) { 907 notes.set(name, new Note(name, settings[name])); 908 } 909 } 910 911 jQuery('#name-notes').prop('disabled', false); 912 jQuery('#add-notes').prop('disabled', false); 913 914 setCurrent(list.reload(notes)); 915 } 916 917 function setCurrent(name) { 918 current = notes.get(name); 919 920 updateFields(); 921 } 922 923 function updateFields() { 924 jQuery('#name-notes').val(current.getName()); 925 jQuery('#rename-notes').prop('disabled', current.isReadOnly()); 926 jQuery('#delete-notes').prop('disabled', current.isReadOnly()); 927 jQuery('#field-note-text').val(current.getText()).prop('disabled', current.isReadOnly()); 928 929 for (let field of fields.values()) { 930 field.update(); 931 } 932 } 933 934 function getSettings() { 935 let settings = {}; 936 937 for (let [name, note] of notes) { 938 settings[name] = note.getSettings(); 939 } 940 941 return settings; 942 } 943 944 return { 945 initialize, 946 reload, 947 getSettings 948 } 949 })(); 950 951 952 function initialize() { 953 locale.initialize(); 954 general.initialize(); 955 namespaces.initialize(); 956 notes.initialize(); 957 958 jQuery('#save-config').click(function () { 959 saveSettings(); 960 }); 961 962 window.onbeforeunload = onBeforeUnload; 963 964 jQuery('#server-status').show(); 965 966 server.loadSettings(); 967 } 968 969 function reloadSettings(settings) { 970 general.reload(settings.general); 971 namespaces.reload(settings.namespaces); 972 notes.reload(settings.notes); 973 } 974 975 function saveSettings() { 976 let settings = {}; 977 978 settings.general = general.getSettings(); 979 settings.namespaces = namespaces.getSettings(); 980 settings.notes = notes.getSettings(); 981 982 server.saveSettings(settings); 983 984 scroll(0, 0); 985 } 986 987 function onBeforeUnload(event) { 988 if (modified) { 989 let message = locale.getString('unsaved'); 990 991 (event || window.event).returnValue = message; 992 993 return message; 994 } 995 } 996 997 function validateName(name, type, existing) { 998 let names = name.split(':'); 999 1000 name = (type == 'ns') ? ':' : ''; 1001 1002 for (let i = 0; i < names.length; i++) { 1003 if (names[i] != '') { 1004 /* ECMA regexp doesn't support POSIX character classes, so [a-zA-Z] is used instead of [[:alpha:]] */ 1005 if (names[i].match(/^[a-zA-Z]\w*$/) == null) { 1006 name = ''; 1007 break; 1008 } 1009 1010 name += (type == 'ns') ? names[i] + ':' : ':' + names[i]; 1011 } 1012 } 1013 1014 if (name == '') { 1015 throw locale.getString('invalid_' + type + '_name'); 1016 } 1017 1018 if (existing.has(name)) { 1019 throw locale.getString(type + '_name_exists', name); 1020 } 1021 1022 return name; 1023 } 1024 1025 return { 1026 initialize 1027 } 1028})(); 1029 1030 1031jQuery(function () { 1032 if (jQuery('#refnotes-config').length != 0) { 1033 refnotes_admin.initialize(); 1034 } 1035}); 1036