Jump to content

User:Magnus Manske/less edit clutter.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
if ( ( mw.config.get('wgAction') == "submit" || mw.config.get('wgAction') == "edit" ) && mw.config.get('wgNamespaceNumber') == 0 ) {
  addOnloadHook ( less_edit_clutter_init ) ;
}

var lec_parse_references = 1 ;

var lec_parent ;
var lec_tb1 ;
var lec_original ;
var lec_tb_top ;
var lec_tb_ill ;
var lec_tb_cat ;
var lec_tb_bt ;
var lec_tb_ref ;
var lec_active ;
var lec_last_edited = null ;


function less_edit_clutter_init () {
  lec_active = 1 ;
  less_edit_clutter_create_elements () ;
  less_edit_clutter_hook_button ( 'wpSave' ) ;
  less_edit_clutter_hook_button ( 'wpPreview' ) ;
  less_edit_clutter_hook_button ( 'wpDiff' ) ;
  less_edit_clutter_parse_main_textbox () ;
  if(window.AJAXPreview) AJAXPreview.getTextContent = less_edit_clutter_get_rejoined_text ;
}

function less_edit_clutter_insert_at_cursor ( field , value ) {
  if (document.selection) {
    field.focus();
    sel = document.selection.createRange();
    sel.text = value;
  } else if (field.selectionStart || field.selectionStart == '0') {
    var startPos = field.selectionStart;
    var endPos = field.selectionEnd;
    field.value = field.value.substring(0, startPos)+ value+ field.value.substring(endPos, field.value.length);
  }
}

function less_edit_clutter_hook_button ( id ) {
  var b = document.getElementById ( id ) ;
  b.onclick = function () { less_edit_clutter_rejoin() ; return true ; } ;
}

function less_edit_clutter_delete_reference () {
  var si = lec_tb_ref.selectedIndex ;
  if ( !si || si == null ) return ; // Nothing selected
  var text = lec_tb_ref[si].firstChild.nodeValue ;
  text = text.split ( ' : ' ) ;
  var value = text.shift() ;
  text = text.join ( ' : ' ) ;
  text = text.split ( ' | ' ) ;
  var refstuff = text.shift() ;
  text = text.join ( ' | ' ) ;
  
  var key = '<<REF' + value + '>>' ;
  lec_tb_top.value = lec_tb_top.value.split(key).join('') ;
  lec_tb1.value = lec_tb1.value.split(key).join('') ;
  lec_tb_bt.value = lec_tb_bt.value.split(key).join('') ;
  less_edit_clutter_rejoin () ;
  less_edit_clutter_parse_main_textbox () ;
  return false ;
}

function less_edit_clutter_insert_new_reference () {
  if ( lec_last_edited == null ) return ;

  var refstuff = prompt ( "Enter reference name:" , '' ) ;
  if ( null == refstuff ) return ; // Cancel
  var text = prompt ( "Enter reference contents:" , '' ) ;
  if ( null == text ) return ; // Cancel

  var max = lec_tb_ref.length + 2 ;

  less_edit_clutter_insert_at_cursor ( lec_last_edited , '<<REF' + max + '>>' ) ;

  text = max + ' : ' + refstuff + ' | ' + text ;
  
  var opt = document.createElement ( 'option' ) ;
  opt.value = max-1 ;
  opt.appendChild ( document.createTextNode ( text ) ) ;
  lec_tb_ref.appendChild ( opt ) ;
  
  less_edit_clutter_rejoin () ;
  less_edit_clutter_parse_main_textbox () ;
  return false ;
}

function less_edit_clutter_mark_text_range ( ctrl , from , to ) {
  if(ctrl.setSelectionRange) {
    ctrl.focus();
    ctrl.setSelectionRange ( from , to ) ;
  }
  else if (ctrl.createTextRange) {
    var range = ctrl.createTextRange();
    range.collapse ( true ) ;
    range.moveEnd ( 'character', from ) ;
    range.moveStart ( 'character', to ) ;
    range.select();
  }
}

function less_edit_clutter_tb1_select ( ta ) {
  var selection = ta.value.substr(ta.selectionStart, ta.selectionEnd - ta.selectionStart);
  if ( ! /^\<*REF\d+\>*$/.test ( selection ) ) return ;
  var num = selection.match ( /^\<*REF(\d+)\>*$/ ) ;
  num = num.pop() ;
  num-- ;
  lec_tb_ref[num].selected = true ;
}

function less_edit_clutter_find_and_mark ( text , ctrl ) {
  var pos = ctrl.value.search ( text ) ;
  if ( pos < 0 ) return true ; // Continue search
  less_edit_clutter_mark_text_range ( ctrl , pos , pos + text.length ) ;
  return false ;
}

function less_edit_clutter_refsel_changed () {
  var si = lec_tb_ref.selectedIndex + 1 ;
  var key = '<<REF' + si + '>>' ;
  var cont = true ;
  if ( cont ) cont = less_edit_clutter_find_and_mark ( key , lec_tb_top ) ;
  if ( cont ) cont = less_edit_clutter_find_and_mark ( key , lec_tb1 ) ;
  if ( cont ) cont = less_edit_clutter_find_and_mark ( key , lec_tb_bt ) ;
  if ( cont ) alert ( "Something's wrong - could not find reference " + key + "! Better reload this edit in the standard edit box!" ) ;
}

function less_edit_clutter_refsel_double_clicked () {
  var si = lec_tb_ref.selectedIndex ;
  var text = lec_tb_ref[si].firstChild.nodeValue ;
  text = text.split ( ' : ' ) ;
  var value = text.shift() ;
  text = text.join ( ' : ' ) ;
  text = text.split ( ' | ' ) ;
  var refstuff = text.shift() ;
  text = text.join ( ' | ' ) ;
  refstuff = prompt ( "Enter reference name:" , refstuff ) ;
  if ( null == refstuff ) return ; // Cancel
  text = prompt ( "Enter reference contents:" , text ) ;
  if ( null == text ) return ; // Cancel
  lec_tb_ref[si].firstChild.nodeValue = value + ' : ' + refstuff + ' | ' + text ;
}

function less_edit_clutter_get_rejoined_text () {
  if ( lec_active != 1 ) return '' ;
  v = lec_tb_top.value ;
  v = v.replace(/^\s+|\s+$/g,"") ;
  if ( v != '' ) v += "\n" ;
  v += lec_tb1.value ;
  v = v.replace(/^\s+|\s+$/g,"") ;
  if ( v != '' ) v += "\n\n" ;
  v += lec_tb_bt.value ;
  v = v.replace(/^\s+|\s+$/g,"") ;
  if ( v != '' ) v += "\n\n" ;

  // Categories
  n = lec_tb_cat.value.split ( "\n" ) ;
  n = n.sort() ;
  for ( i = 0 ; i < n.length ; i++ ) {
    s = n[i].replace(/^\s+|\s+$/g,"") ;
    if ( s == '' ) continue ;
    v += '[[Category:' + 
         s + "]]\n" ;
  }
  v = v.replace(/^\s+|\s+$/g,"") ;
  if ( v != '' ) v += "\n\n" ;

  // Interlanguage links
  n = lec_tb_ill.value.split ( "\n" ) ;
  n = n.sort() ;
  for ( i = 0 ; i < n.length ; i++ ) {
    s = n[i].replace(/^\s+|\s+$/g,"") ;
    if ( s == '' ) continue ;
    v += '[[' + s + "]]\n" ;
  }
  v = v.replace(/^\s+|\s+$/g,"") ;
  
  if ( lec_parse_references ) {
    for ( var n = lec_tb_ref.firstChild ; n ; n = n.nextSibling ) {
      var text = n.firstChild.nodeValue ;
      text = text.split ( ' : ' ) ;
      var value = text.shift() ;
      text = text.join ( ' : ' ) ;
      text = text.split ( ' | ' ) ;
      var refstuff = text.shift() ;
      text = text.join ( ' | ' ) ;
      if ( refstuff != '' ) {
      	var r = refstuff.match ( /^(.*)::(.*)$/ ) ;
      	if ( r == null ) {
	      	refstuff = ' name="' + refstuff + '"' ;
      	} else {
      		var gn = r.pop() ;
      		var rn = r.pop() ;
      		refstuff = '' ;
      		if ( gn != '' ) refstuff += ' group="' + gn + '"' ;
      		if ( rn != '' ) refstuff += ' name="' + rn + '"' ;
      	}
      	
      }
      text = '<ref' + refstuff + '>' + text + '</ref>' ;
      var key = '<<REF' + value + '>>' ;
      v = v.split(key).join(text) ;
    }
  }
  return v ;
}

function less_edit_clutter_rejoin () {
  if ( lec_active != 1 ) return ;
  lec_tb1.value = less_edit_clutter_get_rejoined_text() ;
}

function less_edit_clutter_create_elements () {
  lec_tb1 = document.getElementById ( 'wpTextbox1' ) ;
  lec_parent = lec_tb1.parentNode ;

  lec_tb_top = document.createElement ( 'textarea' ) ;
  lec_tb_top.id = 'lec_tb_top' ;
  lec_tb_top.name = 'lec_tb_top' ;
  lec_tb_top.cols = 80 ;
  lec_tb_top.rows = 5 ;
  
  lec_tb_ill = document.createElement ( 'textarea' ) ;
  lec_tb_ill.id = 'lec_tb_ill' ;
  lec_tb_ill.name = 'lec_tb_ill' ;
  lec_tb_ill.cols = 30 ;
  lec_tb_ill.rows = 5 ;

  lec_tb_cat = document.createElement ( 'textarea' ) ;
  lec_tb_cat.id = 'lec_tb_cat' ;
  lec_tb_cat.name = 'lec_tb_cat' ;
  lec_tb_cat.cols = 30 ;
  lec_tb_cat.rows = 5 ;

  lec_tb_bt = document.createElement ( 'textarea' ) ;
  lec_tb_bt.id = 'lec_tb_bt' ;
  lec_tb_bt.name = 'lec_tb_bt' ;
  lec_tb_bt.cols = 30 ;
  lec_tb_bt.rows = 5 ;
  
  lec_bottom_table = document.createElement ( 'table' ) ;
  lec_bottom_tbody = document.createElement ( 'tbody' ) ;
  lec_bottom_tr = document.createElement ( 'tr' ) ;
  lec_bottom_tr2 = document.createElement ( 'tr' ) ;
  lec_bottom_td1 = document.createElement ( 'td' ) ;
  lec_bottom_td2 = document.createElement ( 'td' ) ;
  lec_bottom_td3 = document.createElement ( 'td' ) ;

  lec_bottom_td1.style.width = '40%' ;
  lec_bottom_td2.style.width = '30%' ;
  lec_bottom_td3.style.width = '30%' ;

  lec_bottom_td1.appendChild ( document.createTextNode ( 'End templates and magic words' ) ) ;
  lec_bottom_td1.appendChild ( document.createElement ( 'br' ) ) ;
  lec_bottom_td1.appendChild ( lec_tb_bt ) ;

  lec_bottom_td2.appendChild ( document.createTextNode ( 'Categories' ) ) ;
  lec_bottom_td2.appendChild ( document.createElement ( 'br' ) ) ;
  lec_bottom_td2.appendChild ( lec_tb_cat ) ;

  lec_bottom_td3.appendChild ( document.createTextNode ( 'Interlanguage links' ) ) ;
  lec_bottom_td3.appendChild ( document.createElement ( 'br' ) ) ;
  lec_bottom_td3.appendChild ( lec_tb_ill ) ;

  if ( lec_parse_references ) {
    lec_tb1.onselect = function () { less_edit_clutter_tb1_select ( lec_tb1 ) ; } ;
    lec_tb_top.onselect = function () { less_edit_clutter_tb1_select ( lec_tb_top ) ; } ;
    lec_tb_bt.onselect = function () { less_edit_clutter_tb1_select ( lec_tb_bt ) ; } ;

    lec_tb1.onfocus = function () { lec_last_edited = lec_tb1 ; } ;
    lec_tb_top.onfocus = function () { lec_last_edited = lec_tb_top ; } ;
    lec_tb_bt.onfocus = function () { lec_last_edited = lec_tb_bt ; } ;

    lec_tb_ref = document.createElement ( 'select' ) ;
    lec_tb_ref.id = 'lec_tb_ref' ;
    lec_tb_ref.name = 'lec_tb_ref' ;
    lec_tb_ref.size = 5 ;
    lec_tb_ref.style.width = '100%' ;
    lec_tb_ref.onchange = less_edit_clutter_refsel_changed ;
    lec_tb_ref.ondblclick = less_edit_clutter_refsel_double_clicked ;

    var a_new_reference = document.createElement ( 'a' ) ;
    a_new_reference.appendChild ( document.createTextNode ( 'insert new reference' ) ) ;
    a_new_reference.href = '#' ;
    a_new_reference.onclick = less_edit_clutter_insert_new_reference ;

    var a_delete_reference = document.createElement ( 'a' ) ;
    a_delete_reference.appendChild ( document.createTextNode ( 'delete reference' ) ) ;
    a_delete_reference.href = '#' ;
    a_delete_reference.onclick = less_edit_clutter_delete_reference ;

    lec_bottom_td4 = document.createElement ( 'td' ) ;
    lec_bottom_td4.appendChild ( document.createTextNode ( 'References (' ) ) ;
    lec_bottom_td4.appendChild ( a_new_reference ) ;
    lec_bottom_td4.appendChild ( document.createTextNode ( ' | ' ) ) ;
    lec_bottom_td4.appendChild ( a_delete_reference ) ;
    lec_bottom_td4.appendChild ( document.createTextNode ( ')' ) ) ;
    lec_bottom_td4.appendChild ( document.createElement ( 'br' ) ) ;
    lec_bottom_td4.appendChild ( lec_tb_ref ) ;
    lec_bottom_td4.colSpan = '3' ;

    lec_bottom_tr2.appendChild ( lec_bottom_td4 ) ;
    lec_bottom_tbody.appendChild ( lec_bottom_tr2 ) ;
  }
  
  lec_bottom_tr.appendChild ( lec_bottom_td1 ) ;
  lec_bottom_tr.appendChild ( lec_bottom_td2 ) ;
  lec_bottom_tr.appendChild ( lec_bottom_td3 ) ;
  lec_bottom_tbody.appendChild ( lec_bottom_tr ) ;
  lec_bottom_table.appendChild ( lec_bottom_tbody ) ;

  var a = document.createElement ( 'a' ) ;
  a.href = '#' ;
  a.appendChild ( document.createTextNode ( "reload in standard edit box" ) ) ;
  a.onclick = function () {
    u = document.getElementById('lec_div_top') ;
    u.parentNode.removeChild ( u ) ;
    u = document.getElementById('lec_div_bottom') ;
    u.parentNode.removeChild ( u ) ;
    lec_tb1.value = lec_original ;
    lec_active = 0 ;
    return false ;
  }

  var b = document.createElement ( 'a' ) ;
  b.href = '#' ;
  b.appendChild ( document.createTextNode ( "redo for current contents" ) ) ;
  b.onclick = function () {
    less_edit_clutter_rejoin () ;
    less_edit_clutter_parse_main_textbox () ;
    return false ;
  }
  var top = document.createElement ( 'div' ) ;
  top.id = 'lec_div_top' ;

  var adiv = document.createElement ( 'div' ) ;
  adiv.style.display = 'block' ;
  adiv.appendChild ( document.createTextNode ( "Main text (" ) ) ;
  adiv.appendChild ( a ) ;
  adiv.appendChild ( document.createTextNode ( " | " ) ) ;
  adiv.appendChild ( b ) ;
  adiv.appendChild ( document.createTextNode ( ")" ) ) ;

  top.appendChild ( document.createTextNode ( "Header templates and images" ) ) ;
  top.appendChild ( lec_tb_top ) ;
  top.appendChild ( adiv ) ;

  var bottom = document.createElement ( 'div' ) ;
  bottom.id = 'lec_div_bottom' ;

  bottom.appendChild ( document.createTextNode ( 'Elements at the end' ) ) ;
  bottom.appendChild ( lec_bottom_table ) ;

  lec_parent.insertBefore ( bottom , lec_tb1.nextSibling ) ;
  lec_parent.insertBefore ( top , lec_tb1 ) ;

  lec_bottom_table.id = 'lec_tb_bottom' ;
  lec_bottom_table.style.width = '100%' ;
  lec_bottom_table.style.cellSpacing = '2' ;
  lec_bottom_table.style.cellPadding = '2' ;


  less_edit_clutter_append_show_hide ( 'lec_tb_top' ) ;
  less_edit_clutter_append_show_hide ( 'lec_tb_bottom' ) ;
}

function less_edit_clutter_toggle_show_hide ( id , a ) {
  var x = document.getElementById ( id ) ;
  if ( x.style.display == 'none' ) {
    x.style.display = '' ;
    while ( a.firstChild ) a.removeChild ( a.firstChild ) ;
    a.appendChild (  document.createTextNode ( 'hide' ) ) ;
  } else {
    x.style.display = 'none' ;
    while ( a.firstChild ) a.removeChild ( a.firstChild ) ;
    a.appendChild ( document.createTextNode ( 'show' ) ) ;
  }
}

function less_edit_clutter_append_show_hide ( id ) {
  var x = document.getElementById ( id ) ;
  var n = document.createElement ( 'span' ) ;

  var a = document.createElement ( 'a' ) ;
  a.href = '#' ;
  a.onclick = function () { less_edit_clutter_toggle_show_hide ( id , this ) ; return false ; }
  a.appendChild ( document.createTextNode ( 'hide' ) ) ;

  n.appendChild ( document.createTextNode ( ' (' ) ) ;
  n.appendChild ( a ) ;
  n.appendChild ( document.createTextNode ( ')' ) ) ;
  n.appendChild ( document.createElement ( 'br' ) ) ;

  x.parentNode.insertBefore ( n , x ) ;
//  x.style.display = 'none' ;
}

function less_edit_clutter_parse_main_textbox () {
  lec_original = lec_tb1.value ;
  var lines = lec_original.split("\n") ;
  var in_template = 0 ;
  var begin_templates = "" ;
  
  // References
  if ( lec_parse_references && /\<\<REF\d+\>\>/.test ( lec_original ) ) lec_parse_references = 0 ; // Already contains pattern, aborting
  if ( lec_parse_references ) {
    cnt = 1 ;
    v = lec_original ;
    v = v.split ( /\<ref/ig ) ;
    o = v.shift () ;
    refs = new Array () ;
    while ( lec_tb_ref.firstChild ) lec_tb_ref.removeChild ( lec_tb_ref.firstChild ) ;
    for ( i = 0 ; i < v.length ; i++ ) {
      if ( v[i].substr(0,1) != ' ' && v[i].substr(0,1) != '>' ) { // Something that is not a reference tag
        o += '<ref' + v[i] ;
        continue ;
      }
      n = v[i].split ( '>' ) ;
      if ( n.length < 2 ) { o += '<ref' + v[i] ; continue ; }
      
      var attrs = n.shift() ;
      
      var name_attr = attrs ;
      rs = name_attr.match ( /name=\"([^"]*)\"/ ) ;
      if ( rs == null ) rs = name_attr.match ( /name=\'([^']*)\'/ ) ;
      if ( rs == null ) rs = name_attr.match ( /name=([a-zA-Z0-9_\-]*)/ ) ;
      name_attr = rs ;
      if ( null == name_attr ) name_attr = '' ;
      else name_attr = name_attr.pop() ;

      var group_attr = attrs ;
      rs = group_attr.match ( /group=\"([^"]*)\"/ ) ;
      if ( rs == null ) rs = group_attr.match ( /group=\'([^']*)\'/ ) ;
      if ( rs == null ) rs = group_attr.match ( /group=([a-zA-Z0-9_\-]*)/ ) ;
      group_attr = rs ;
      if ( null == group_attr ) group_attr = '' ;
      else group_attr = group_attr.pop() ;
      
      refstuff = name_attr ;
      if ( group_attr != '' ) refstuff += "::" + group_attr ;
      
      
      n = n.join ( '>' ) ;
      n = n.split ( '</ref>' ) ;
      if ( n.length < 2 ) { o += '<ref' + v[i] ; continue ; }
      refcontents = n.shift() ;
//      if ( n.length > 1 ) { o += '<ref' + v[i] ; continue ; }
      n = n.join ( '</ref>' ) ;
      o += '<<REF' + cnt + '>>' + n ;
      refs.push ( cnt + ' : ' + refstuff + ' | ' + refcontents ) ;
      cnt++ ;
    }
    for ( i = 0 ; i < refs.length ; i++ ) {
      var opt = document.createElement ( 'option' ) ;
      opt.value = i ;
      opt.appendChild ( document.createTextNode ( refs[i] ) ) ;
      lec_tb_ref.appendChild ( opt ) ;
    }
    lines = o.split("\n") ;
  }

  // Begin of text
  var in_table = 0 ;
  while ( lines.length > 0 ) {
    var no_ws = lines[0].replace(/^\s+|\s+$/g,"") ;
    var lc = no_ws.toLowerCase() ;
    if ( lc == "" ) {
      lines.shift() ;
      if ( begin_templates != '' ) begin_templates += "\n" ;
    } else if ( lc.match(/^\{\{[^\{\}]*\}\}$/) ) {
      lines.shift() ;
      begin_templates = begin_templates + no_ws + "\n" ;
    } else if ( lc.match(/^\{\{[^\{\}]*$/) ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;
      in_template++ ;
    } else if ( in_template && lc.match(/^[^\}\{]*\}\}\s*$/) ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;
      in_template-- ;
    } else if ( in_template > 0 ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;
    } else if ( lc.match(/^[-_]+$/) || lc.match(/^\s*\<hr\s*\/*\>\s*$/) ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;
    } else if ( lc.match(/^\[\[image\:.*\]\]$/) ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;
    } else if ( lc.match(/^\[\[file\:.*\]\]$/) ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;
      
    } else if ( lc.match(/^:/) ) { // Indented "For other uses..."
      begin_templates = begin_templates + lines.shift() + "\n" ;
      
    } else if ( lc.match(/^\{\|/) ) { // Table open
      in_table++ ;
      begin_templates = begin_templates + lines.shift() + "\n" ;
    } else if ( lc.match(/^\s*\|\}/) && in_table > 0 ) { // Table close
      in_table-- ;
      begin_templates = begin_templates + lines.shift() + "\n" ;
    } else if ( in_table > 0 ) {
      begin_templates = begin_templates + lines.shift() + "\n" ;

    } else break ;
  }

  begin_templates = begin_templates.replace(/^\s+|\s+$/g,"") ;


  var categories = new Array () ;
  var languages = new Array () ;
  var end_templates = "" ;
  
  // End of text
  in_template = 0 ;
  end_templates_append = "" ;
  while ( lines.length > 0 ) {
    var lp = lines.length - 1 ;
    var no_ws = lines[lp].replace(/^\s+|\s+$/g,"") ;
    var lc = no_ws.toLowerCase() ;
    if ( lc == "" ) {
      lines.pop() ;
      if ( end_templates != '' ) end_templates = "\n" + end_templates ;
    } else if ( lc.substr ( 0 , 11 ) == "[[category:" ) {
      lines.pop() ;
      var s = no_ws.substr ( 11 ) ;
      s = s.replace ( /\]\]$/ , "" ) ;
      categories.push ( s ) ;
    } else if ( lc.match(/^\[\[\w+\:.*\]\]$/) ) {
      lines.pop() ;
      var s = no_ws.substr ( 2 ) ;
      s = s.replace ( /\]\]$/ , "" ) ;
      languages.push ( s ) ;
    } else if ( lc.match(/^\{\{defaultsort\s*[\|\:].*\}\}$/) ) {
      end_templates_append += "\n\n" + lines.pop() ;
    } else if ( lc.match(/^\<!--.*-->$/) ) {
      end_templates = lines.pop() + "\n" + end_templates ;
    } else if ( lc.match(/^\{\{.*\}\}$/) ) {
      end_templates = lines.pop() + "\n" + end_templates ;
    } else if ( lc.match(/^[^\{\}]*\}\}$/) ) {
      end_templates = lines.pop() + "\n" + end_templates ;
      in_template++ ;
    } else if ( lc.match(/^\{\{[^\{\}]*$/) ) {
      end_templates = lines.pop() + "\n" + end_templates ;
      in_template-- ;
    } else if ( in_template > 0 ) {
      end_templates = lines.pop() + "\n" + end_templates ;
    } else break ;
  }

  var oet ;
  do {
    oet = end_templates ;
    end_templates = end_templates.split("\n\n\n").join("\n\n") ;
  } while ( end_templates != oet ) ;
  end_templates = end_templates.replace(/^\s+|\s+$/g,"") ;
  end_templates_append = end_templates_append.replace(/^\s+|\s+$/g,"") ;
  if ( end_templates != '' && end_templates_append != '' ) end_templates += "\n\n" ;
  end_templates += end_templates_append ;

  // Set boxes
  lec_tb_top.value = begin_templates ;
  lec_tb_cat.value = categories.sort().join("\n") ;
  lec_tb_ill.value = languages.sort().join("\n") ;
  lec_tb_bt.value = end_templates ;
  lec_tb1.value = lines.join("\n") ;
}