Subversion Repositories oidplus

Rev

Rev 211 | Rev 215 | Go to most recent revision | View as "text/javascript" | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * OIDplus 2.0
  3.  * Copyright 2019 Daniel Marschall, ViaThinkSoft
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17.  
  18. /*jshint esversion: 6 */
  19.  
  20. function oidplus_loadScript(src) {
  21.         var js = document.createElement('script');
  22.         js.src = src;
  23.         js.onload = function() {
  24.         };
  25.         js.onerror = function() {
  26.         };
  27.         document.head.appendChild(js);
  28. }
  29.  
  30. var ua = window.navigator.userAgent;
  31. if ((ua.indexOf("MSIE ") > 0) || (ua.indexOf("Trident/") > 0)) {
  32.         // Compatibility with Internet Explorer
  33.         oidplus_loadScript('https://polyfill.io/v3/polyfill.min.js?features=fetch%2CURL');
  34. }
  35.  
  36. // $('#html').jstree();
  37.  
  38. current_node = "";
  39. popstate_running = false;
  40.  
  41. String.prototype.explode = function (separator, limit) {
  42.         // https://stackoverflow.com/questions/4514323/javascript-equivalent-to-php-explode
  43.         const array = this.split(separator);
  44.         if (limit !== undefined && array.length >= limit) {
  45.                 array.push(array.splice(limit - 1).join(separator));
  46.         }
  47.         return array;
  48. };
  49.  
  50. String.prototype.htmlentities = function () {
  51.         return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  52. };
  53.  
  54. String.prototype.html_entity_decode = function () {
  55.         return $('<textarea />').html(this).text();
  56. };
  57.  
  58. function getMeta(metaName) {
  59.         const metas = document.getElementsByTagName('meta');
  60.  
  61.         for (let i = 0; i < metas.length; i++) {
  62.                 if (metas[i].getAttribute('name') === metaName) {
  63.                         return metas[i].getAttribute('content');
  64.                 }
  65.         }
  66.  
  67.         return '';
  68. }
  69.  
  70. function getOidPlusSystemTitle() {
  71.         return getMeta('OIDplus-SystemTitle');
  72. }
  73.  
  74. function combine_systemtitle_and_pagetitle(systemtitle, pagetitle) {
  75.         if (systemtitle == pagetitle) {
  76.                 return systemtitle;
  77.         } else {
  78.                 return systemtitle + ' - ' + pagetitle;
  79.         }
  80. }
  81.  
  82. function getTreeLoadURL() {
  83.         var url = new URL(window.location.href);
  84.         var goto = url.searchParams.get("goto");
  85.         return (goto != null) ? "ajax.php?action=tree_load&goto="+encodeURIComponent(goto)
  86.                               : "ajax.php?action=tree_load";
  87. }
  88.  
  89. function reloadContent() {
  90.         // window.location.href = "?goto="+encodeURIComponent(current_node);
  91.         openOidInPanel(current_node, false);
  92.         $('#oidtree').jstree("refresh");
  93. }
  94.  
  95. function x_rec(x_data, i) {
  96.         $('#oidtree').jstree('open_node', x_data[i], function(e, data) {
  97.                 if (i+1 < x_data.length) {
  98.                         x_rec(x_data, i+1);
  99.                 } else {
  100.                         popstate_running = true; // don't call openOidInPanel again
  101.                         try {
  102.                                 $('#oidtree').jstree('select_node', x_data[i]);
  103.                         } catch (err) {
  104.                                 popstate_running = false;
  105.                         } finally {
  106.                                 popstate_running = false;
  107.                         }
  108.                 }
  109.         });
  110. }
  111.  
  112. function openOidInPanel(id, reselect/*=false*/) {
  113.         reselect = (typeof reselect === 'undefined') ? false : reselect;
  114.  
  115.         if (reselect) {
  116.                 $('#oidtree').jstree('deselect_all');
  117.  
  118.                 popstate_running = true; // don't call openOidInPanel during tree selection
  119.                 try {
  120.                         // If the node is already loaded in the tree, select it
  121.                         if (!$('#oidtree').jstree('select_node', id)) {
  122.                                 // If the node is not loaded, then we try to search it.
  123.                                 // If it can be found, then open all parent nodes and select the node
  124.                                 $.ajax({
  125.                                         url:"ajax.php",
  126.                                         method:"POST",
  127.                                         data:{
  128.                                                 action:"tree_search",
  129.                                                 search:id
  130.                                         },
  131.                                         error:function(jqXHR, textStatus, errorThrown) {
  132.                                                 console.error("Error: " + errorThrown);
  133.                                         },
  134.                                         success:function(data) {
  135.                                                 if ("error" in data) {
  136.                                                         console.error(data);
  137.                                                 } else if ((data instanceof Array) && (data.length > 0)) {
  138.                                                         x_rec(data, 0);
  139.                                                 } else {
  140.                                                         console.error(data);
  141.                                                 }
  142.                                         }
  143.                                 });
  144.                         }
  145.                 } catch (err) {
  146.                         popstate_running = false;
  147.                 } finally {
  148.                         popstate_running = false;
  149.                 }
  150.         }
  151.  
  152.         // This loads the actual content
  153.  
  154.         document.title = "";
  155.         $('#real_title').html("&nbsp;");
  156.         $('#real_content').html("Loading...");
  157.         $('#static_link').attr("href", "index.php?goto="+encodeURIComponent(id));
  158.         $("#gotoedit").val(id);
  159.  
  160.         // Normal opening of a description
  161.         fetch('ajax.php?action=get_description&id='+encodeURIComponent(id))
  162.         .then(function(response) {
  163.                 response.json()
  164.                 .then(function(data) {
  165.                         if ("error" in data) {
  166.                                 alert("Failed to load content: " + data.error);
  167.                                 console.error(data.error);
  168.                                 return;
  169.                         }
  170.  
  171.                         data.id = id;
  172.  
  173.                         document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.title);
  174.                         var state = {
  175.                                 "node_id":id,
  176.                                 "titleHTML":(data.icon ? '<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' : '') + data.title.htmlentities(),
  177.                                 "textHTML":data.text,
  178.                                 "staticlinkHREF":"index.php?goto="+encodeURIComponent(id),
  179.                         };
  180.                         if (current_node != id) {
  181.                                 window.history.pushState(state, data.title, "?goto="+encodeURIComponent(id));
  182.                         } else {
  183.                                 window.history.replaceState(state, data.title, "?goto="+encodeURIComponent(id));
  184.                         }
  185.  
  186.                         if (data.icon) {
  187.                                 $('#real_title').html('<img src="'+data.icon+'" width="48" height="48" alt="'+data.title.htmlentities()+'"> ' + data.title.htmlentities());
  188.                         } else {
  189.                                 $('#real_title').html(data.title.htmlentities());
  190.                         }
  191.                         $('#real_content').html(data.text);
  192.                         document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.title);
  193.                         current_node = id;
  194.                 })
  195.                 .catch(function(error) {
  196.                         alert("Failed to load content: " + error);
  197.                         console.error(error);
  198.                 });
  199.         })
  200.         .catch(function(error) {
  201.                 alert("Failed to load content: " + error);
  202.                 console.error(error);
  203.         });
  204. }
  205.  
  206. function updateDesc() {
  207.         $.ajax({
  208.                 url:"ajax.php",
  209.                 method:"POST",
  210.                 data: {
  211.                         action:"Update2",
  212.                         id:current_node,
  213.                         title:(document.getElementById('titleedit') ? document.getElementById('titleedit').value : null),
  214.                         //description:(document.getElementById('description') ? document.getElementById('description').value : null)
  215.                         description:tinyMCE.get('description').getContent()
  216.                 },
  217.                 error:function(jqXHR, textStatus, errorThrown) {
  218.                         alert("Error: " + errorThrown);
  219.                 },
  220.                 success:function(data) {
  221.                         if ("error" in data) {
  222.                                 alert("Error: " + data.error);
  223.                         } else if (data.status == 0) {
  224.                                 alert("Update OK");
  225.                                 //reloadContent();
  226.                                 $('#oidtree').jstree("refresh");
  227.                                 var h1s = document.getElementsByTagName("h1");
  228.                                 for (var i = 0; i < h1s.length; i++) {
  229.                                         var h1 = h1s[i];
  230.                                         h1.innerHTML = document.getElementById('titleedit').value.htmlentities();
  231.                                 }
  232.                                 document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), document.getElementById('titleedit').value);
  233.  
  234.                                 var mce = tinymce.get('description');
  235.                                 if (mce != null) mce.isNotDirty = 1;
  236.                         } else {
  237.                                 alert("Error: " + data.error);
  238.                         }
  239.                 }
  240.         });
  241. }
  242.  
  243. function crudActionSendInvitation(origin, email) {
  244.         // window.location.href = "?goto=oidplus:invite_ra$"+encodeURIComponent(email)+"$"+encodeURIComponent(origin);
  245.         openOidInPanel('oidplus:invite_ra$'+email+'$'+origin, false);
  246. }
  247.  
  248. function crudActionInsert(parent) {
  249.         $.ajax({
  250.                 url:"ajax.php",
  251.                 method:"POST",
  252.                 data:{
  253.                         action:"Insert",
  254.                         id:document.getElementById('id').value,
  255.                         ra_email:document.getElementById('ra_email').value,
  256.                         comment:document.getElementById('comment').value,
  257.                         asn1ids:(document.getElementById('asn1ids') ? document.getElementById('asn1ids').value : null),
  258.                         iris:(document.getElementById('iris') ? document.getElementById('iris').value : null),
  259.                         confidential:(document.getElementById('hide') ? document.getElementById('hide').checked : null),
  260.                         weid:(document.getElementById('weid') ? document.getElementById('weid').checked : null),
  261.                         parent:parent
  262.                 },
  263.                 error:function(jqXHR, textStatus, errorThrown) {
  264.                         alert("Error: " + errorThrown);
  265.                 },
  266.                 success:function(data) {
  267.                         if ("error" in data) {
  268.                                 alert("Error: " + data.error);
  269.                         } else if (data.status == 0/*OK*/) {
  270.                                 //alert("Insert OK");
  271.                                 reloadContent();
  272.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  273.                         } else if (data.status == 1/*RaNotExisting*/) {
  274.                                 if (confirm("Update OK. However, the email address you have entered ("+document.getElementById('ra_email').value+") is not in our system. Do you want to send an invitation, so that the RA can register an account to manage their OIDs?")) {
  275.                                         crudActionSendInvitation(parent, document.getElementById('ra_email').value);
  276.                                 } else {
  277.                                         reloadContent();
  278.                                         // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  279.                                 }
  280.                         } else if (data.status == 2/*RaNotExistingNoInvitation*/) {
  281.                                 //alert("Insert OK");
  282.                                 reloadContent();
  283.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts eine neue zeile zur tabelle hinzufügen
  284.                         } else {
  285.                                 alert("Error: " + data);
  286.                         }
  287.                 }
  288.         });
  289. }
  290.  
  291. function crudActionUpdate(id, parent) {
  292.         $.ajax({
  293.                 url:"ajax.php",
  294.                 method:"POST",
  295.                 data: {
  296.                         action:"Update",
  297.                         id:id,
  298.                         ra_email:document.getElementById('ra_email_'+id).value,
  299.                         comment:document.getElementById('comment_'+id).value,
  300.                         asn1ids:(document.getElementById('asn1ids_'+id) ? document.getElementById('asn1ids_'+id).value : null),
  301.                         iris:(document.getElementById('iris_'+id) ? document.getElementById('iris_'+id).value : null),
  302.                         confidential:(document.getElementById('hide_'+id) ? document.getElementById('hide_'+id).checked : null),
  303.                         parent:parent
  304.                 },
  305.                 error:function(jqXHR, textStatus, errorThrown) {
  306.                         alert("Error: " + errorThrown);
  307.                 },
  308.                 success:function(data) {
  309.                         if ("error" in data) {
  310.                                 alert("Error: " + data.error);
  311.                         } else if (data.status == 0/*OK*/) {
  312.                                 alert("Update OK");
  313.                                 // reloadContent();
  314.                                 $('#oidtree').jstree("refresh");
  315.                         } else if (data.status == 1/*RaNotExisting*/) {
  316.                                 if (confirm("Update OK. However, the email address you have entered ("+document.getElementById('ra_email_'+id).value+") is not in our system. Do you want to send an invitation, so that the RA can register an account to manage their OIDs?")) {
  317.                                         crudActionSendInvitation(parent, document.getElementById('ra_email_'+id).value);
  318.                                 } else {
  319.                                         // reloadContent();
  320.                                         $('#oidtree').jstree("refresh");
  321.                                 }
  322.                         } else if (data.status == 2/*RaNotExistingNoInvitation*/) {
  323.                                 alert("Update OK");
  324.                                 // reloadContent();
  325.                                 $('#oidtree').jstree("refresh");
  326.                         } else {
  327.                                 alert("Error: " + data);
  328.                         }
  329.                 }
  330.         });
  331. }
  332.  
  333. function crudActionDelete(id, parent) {
  334.         if(!window.confirm("Are you sure that you want to delete "+id+"?")) return false;
  335.  
  336.         $.ajax({
  337.                 url:"ajax.php",
  338.                 method:"POST",
  339.                 data: {
  340.                         action:"Delete",
  341.                         id:id,
  342.                         parent:parent
  343.                 },
  344.                 error:function(jqXHR, textStatus, errorThrown) {
  345.                         alert("Error: " + errorThrown);
  346.                 },
  347.                 success:function(data) {
  348.                         if ("error" in data) {
  349.                                 alert("Error: " + data.error);
  350.                         } else if (data.status == 0) {
  351.                                 reloadContent();
  352.                                 // TODO: auf reloadContent() verzichten. stattdessen nur tree links aktualisieren, und rechts die zeile aus der tabelle löschen
  353.                         } else {
  354.                                 alert("Error: " + data.error);
  355.                         }
  356.                 }
  357.         });
  358. }
  359.  
  360. function deleteRa(email, goto) {
  361.         if(!window.confirm("Are you really sure that you want to delete "+email+"? (The OIDs stay active)")) return false;
  362.  
  363.         $.ajax({
  364.                 url:"ajax.php",
  365.                 method:"POST",
  366.                 data: {
  367.                         action:"delete_ra",
  368.                         email:email,
  369.                 },
  370.                 error:function(jqXHR, textStatus, errorThrown) {
  371.                         alert("Error: " + errorThrown);
  372.                 },
  373.                 success:function(data) {
  374.                         if ("error" in data) {
  375.                                 alert("Error: " + data.error);
  376.                         } else if (data.status == 0) {
  377.                                 alert("Done.");
  378.                                 if (goto != null) {
  379.                                         $("#gotoedit").val(goto);
  380.                                         window.location.href = "?goto="+encodeURIComponent(goto);
  381.                                 }
  382.                                 // reloadContent();
  383.                         } else {
  384.                                 alert("Error: " + data.error);
  385.                         }
  386.                 }
  387.         });
  388. }
  389.  
  390. // This function opens the "parentID" node, and then selects the "childID" node (which should be beneath the parent node)
  391. function openAndSelectNode(childID, parentID) {
  392.         if ($('#oidtree').jstree(true).get_node(parentID)) {
  393.                 $('#oidtree').jstree('open_node', parentID, function(e, data) { // open parent node
  394.                         if ($('#oidtree').jstree(true).get_node(childID)) { // is the child there?
  395.                                 $('#oidtree').jstree('deselect_all').jstree('select_node', childID); // select it
  396.                         } else {
  397.                                 // This can happen if the content page contains brand new items which are not in the treeview yet
  398.                                 $("#gotoedit").val(childID);
  399.                                 window.location.href = "?goto="+encodeURIComponent(childID);
  400.                         }
  401.                 }, true);
  402.         } else {
  403.                 // This should usually not happen
  404.                 $("#gotoedit").val(childID);
  405.                 window.location.href = "?goto="+encodeURIComponent(childID);
  406.         }
  407. }
  408.  
  409. $(window).on("popstate", function(e) {
  410.         popstate_running = true;
  411.         try {
  412.                 var data = e.originalEvent.state;
  413.  
  414.                 current_node = data.node_id;
  415.                 $('#oidtree').jstree('deselect_all').jstree('select_node', data.node_id);
  416.                 $('#real_title').html(data.titleHTML);
  417.                 $('#real_content').html(data.textHTML);
  418.                 $('#static_link').attr("href", data.staticlinkHREF);
  419.                 document.title = combine_systemtitle_and_pagetitle(getOidPlusSystemTitle(), data.titleHTML.html_entity_decode());
  420.         } catch (err) {
  421.                 popstate_running = false;
  422.         } finally {
  423.                 popstate_running = false;
  424.         }
  425. });
  426.  
  427. $(document).ready(function () {
  428.  
  429.         // --- JsTree
  430.  
  431.         $('#oidtree')
  432.         .jstree({
  433.                 plugins: ['massload','search','conditionalselect'],
  434.                 'core' : {
  435.                         'data' : {
  436.                                 "url" : getTreeLoadURL(),
  437.                                 "data" : function (node) {
  438.                                         return { "id" : node.id };
  439.                                 }
  440.                         },
  441.                         "multiple": false
  442.                 },
  443.                 'conditionalselect' : function (node) {
  444.                         if (node.original.conditionalselect !== undefined) {
  445.                                 return eval(node.original.conditionalselect);
  446.                         } else {
  447.                                 return true; // allow select
  448.                         }
  449.                 },
  450.         })
  451.         .on('ready.jstree', function (e, data) {
  452.                 var url = new URL(window.location.href);
  453.                 var goto = url.searchParams.get("goto");
  454.                 if (goto == null) goto = "oidplus:system"; // the page was not called with ?goto=...
  455.                 $("#gotoedit").val(goto);
  456.  
  457.                 // By setting current_node, select_node() will not cause ajax.php?action=get_description to load (since we already loaded the first static content via PHP, for search engines mainly)
  458.                 // But then we need to set the history state manually
  459.                 current_node = goto;
  460.                 window.history.replaceState({
  461.                         "node_id":goto,
  462.                         "titleHTML":$('#real_title').html(),
  463.                         "textHTML":$('#real_content').html(),
  464.                         "staticlinkHREF":"index.php?goto="+encodeURIComponent(goto),
  465.                 }, $('#real_title').html(), "?goto="+encodeURIComponent(goto));
  466.  
  467.                 if (goto != null) data.instance.select_node([goto]);
  468.  
  469.                 setTimeout(glayoutWorkaroundA, 100);
  470.                 setTimeout(glayoutWorkaroundB, 100);
  471.         })
  472.         .on('select_node.jstree', function (node, selected, event) {
  473.                 mobileNavClose();
  474.  
  475.                 var id = selected.node.id;
  476.                 if ((!popstate_running) && (current_node != id)) {
  477.                         openOidInPanel(id, false);
  478.                 }
  479.         });
  480.  
  481.         // --- Layout
  482.  
  483.         document.getElementById('system_title_menu').style.display = "block";
  484.  
  485.         $('#oidtree').addClass('ui-layout-west');
  486.         $('#content_window').addClass('ui-layout-center');
  487.         $('#system_title_bar').addClass('ui-layout-north');
  488.         glayout = $('#frames').layout({
  489.                 north__size:                  40,
  490.                 north__slidable:              false,
  491.                 north__closable:              false,
  492.                 north__resizable:             false,
  493.                 west__size:                   450,
  494.                 west__spacing_closed:         20,
  495.                 west__togglerLength_closed:   230,
  496.                 west__togglerAlign_closed:    "top",
  497.                 west__togglerContent_closed:  "O<br>B<br>J<br>E<br>C<br>T<br><br>T<BR>R<BR>E<BR>E",
  498.                 west__togglerTip_closed:      "Open & Pin Menu",
  499.                 west__sliderTip:              "Slide Open Menu",
  500.                 west__slideTrigger_open:      "mouseover",
  501.                 center__maskContents:         true // IMPORTANT - enable iframe masking
  502.         });
  503.  
  504.         $("#gotobox").addClass("mobilehidden");
  505.         document.getElementById('gotobox').style.display = "block";
  506.         $('#gotoedit').keypress(function(event) {
  507.                 var keycode = (event.keyCode ? event.keyCode : event.which);
  508.                 if (keycode == '13') {
  509.                         gotoButtonClicked();
  510.                 }
  511.         });
  512. });
  513.  
  514. function glayoutWorkaroundA() {
  515.         // "Bug A": Sometimes, the design is completely destroyed after reloading the page. It does not help when glayout.resizeAll()
  516.         //          is called at the beginning (e.g. during the ready function), and it does not help if we wait 500ms.
  517.         //          So we do it all the time. It has probably something to do with slow loading times, since the error
  518.         //          does only appear when the page is "blank" for a short while while it is loading.
  519.         glayout.resizeAll();
  520.         setTimeout(glayoutWorkaroundA, 100);
  521. }
  522.  
  523. function glayoutWorkaroundB() {
  524.         // "Bug B": Sometimes, after reload, weird space between oidtree and content window, because oidtree has size of 438px
  525.         document.getElementById("oidtree").style.width = "450px";
  526. }
  527.  
  528. function mobileNavClose() {
  529.         if ($("#system_title_menu").is(":hidden")) {
  530.                 return;
  531.         }
  532.  
  533.         $("#oidtree").slideUp("medium").promise().done(function() {
  534.                 $("#oidtree").addClass("ui-layout-west");
  535.                 $("#oidtree").show();
  536. //              $("#gotobox").hide();
  537.                 $("#gotobox").addClass("mobilehidden");
  538.         });
  539.         $("#system_title_menu").removeClass("active");
  540. }
  541.  
  542. function mobileNavOpen() {
  543.         $("#oidtree").hide();
  544.         $("#oidtree").removeClass("ui-layout-west");
  545.         $("#oidtree").slideDown("medium");
  546. //      $("#gotobox").show();
  547.         $("#gotobox").removeClass("mobilehidden");
  548.         $("#system_title_menu").addClass("active");
  549. }
  550.  
  551. function mobileNavButtonClick(sender) {
  552.         if ($("#oidtree").hasClass("ui-layout-west")) {
  553.                 mobileNavOpen();
  554.         } else {
  555.                 mobileNavClose();
  556.         }
  557. }
  558.  
  559. function mobileNavButtonHover(sender) {
  560.         sender.classList.toggle("hover");
  561. }
  562.  
  563. function gotoButtonClicked() {
  564.         openOidInPanel($("#gotoedit").val(), 1);
  565. }
  566.  
  567. function frdl_weid_change() {
  568.         from_base = 36;
  569.         from_control = "#weid";
  570.         to_base = 10;
  571.         to_control = "#id";
  572.  
  573.         inp = $(from_control).val().trim();
  574.         if (inp == "") {
  575.                 $(to_control).val("");
  576.         } else {
  577.                 x = BigNumber(inp, from_base);
  578.                 if (isNaN(x)) {
  579.                         $(to_control).val("");
  580.                 } else {
  581.                         $(to_control).val(x.toString(to_base));
  582.                 }
  583.         }
  584. }
  585.  
  586. function frdl_oidid_change() {
  587.         from_base = 10;
  588.         from_control = "#id";
  589.         to_base = 36;
  590.         to_control = "#weid";
  591.  
  592.         inp = $(from_control).val().trim();
  593.         if (inp == "") {
  594.                 $(to_control).val("");
  595.         } else {
  596.                 x = BigNumber(inp, from_base);
  597.                 if (isNaN(x)) {
  598.                         $(to_control).val("");
  599.                 } else {
  600.                         $(to_control).val(x.toString(to_base));
  601.                 }
  602.         }
  603. }
  604.