[dev] [commit] r942 - phplib templates/admin templates/common templates/common/bits templates/struct wwwbase wwwbase/admin wwwbase/ajax wwwbase/img/icons wwwbase/js wwwbase/struct wwwbase/styles

automailer at dexonline.ro automailer at dexonline.ro
Mon Aug 19 16:28:42 EEST 2013


Author: cata
Date: Mon Aug 19 16:28:41 2013
New Revision: 942

Log:
Merge struct.{php,ihtml} and lexemEdit.{php,ihtml}. There is no natural dividing line between them.
Control at field level which role can edit what.
Various little fixes for PHP and HTML compliance.

Added:
   templates/admin/lexemEditActions.ihtml
   wwwbase/ajax/getModelByLexemId.php
   wwwbase/img/icons/arrow_refresh.png   (contents, props changed)
   wwwbase/img/icons/disk.png   (contents, props changed)
   wwwbase/img/icons/page_white_copy.png   (contents, props changed)
   wwwbase/js/lexemEdit.js
      - copied, changed from r928, wwwbase/js/struct.js
   wwwbase/js/select2Dev.js
   wwwbase/styles/lexemEdit.css
      - copied, changed from r928, wwwbase/styles/struct.css
Deleted:
   templates/struct/dexEdit.ihtml
   wwwbase/admin/lexemMerge.php
   wwwbase/js/struct.js
   wwwbase/struct/dexEdit.php
   wwwbase/styles/struct.css
Modified:
   phplib/SmartyWrap.php
   phplib/util.php
   templates/admin/lexemEdit.ihtml
   templates/admin/pageLayout.ihtml
   templates/common/bits/ifArray.ihtml
   templates/common/bits/similarModel.ihtml
   templates/common/modele-flexiune.ihtml
   templates/common/moderatori.ihtml
   wwwbase/admin/definitionEdit.php
   wwwbase/admin/index.php
   wwwbase/admin/lexemEdit.php
   wwwbase/contribuie.php
   wwwbase/js/flex.js
   wwwbase/styles/flex.css

Modified: phplib/SmartyWrap.php
==============================================================================
--- phplib/SmartyWrap.php	Mon Aug 19 11:40:12 2013	(r941)
+++ phplib/SmartyWrap.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -161,7 +161,7 @@
       case 'paradigm':           self::$cssFiles[9] = 'paradigm.css?v=1'; break;
       case 'hangman':            self::$cssFiles[10] = 'hangman.css?v=3'; break;
       case 'mill':               self::$cssFiles[11] = 'mill.css?v=1'; break;
-      case 'struct':             self::$cssFiles[12] = 'struct.css?v=1'; break;
+      case 'lexemEdit':          self::$cssFiles[12] = 'lexemEdit.css?v=1'; break;
       case 'jcrop':              self::$cssFiles[13] = 'jquery.Jcrop.min.css?v=2'; break;
       case 'easyui':
         self::$cssFiles[14] = 'easyui/default/easyui.css?v=1';
@@ -196,12 +196,13 @@
       case 'hangman':          self::$jsFiles[13] = 'hangman.js?v=5'; break;
       case 'mill':             self::$jsFiles[14] = 'mill.js?v=2'; break;
       case 'wotd':             self::$jsFiles[15] = 'wotd.js?v=1';
-      case 'struct':           self::$jsFiles[16] = 'struct.js?v=3'; break;
+      case 'lexemEdit':        self::$jsFiles[16] = 'lexemEdit.js?v=3'; break;
       case 'jcrop':            self::$jsFiles[17] = 'jquery.Jcrop.min.js?v=2'; break;
         
       case 'easyui':           self::$jsFiles[18] = 'jquery.easyui.min.js?v=1'; break;
       case 'select2':          self::$jsFiles[19] = 'select2.min.js?v=2'; break;
-      case 'visualTag':        self::$jsFiles[18] = 'visualTag.js'; break;
+      case 'select2Dev':       self::$jsFiles[20] = 'select2Dev.js?v=1'; break;
+      case 'visualTag':        self::$jsFiles[21] = 'visualTag.js'; break;
       default:
         FlashMessage::add("Cannot load JS script {$id}");
         util_redirect(util_getWwwRoot());

Modified: phplib/util.php
==============================================================================
--- phplib/util.php	Mon Aug 19 11:40:12 2013	(r941)
+++ phplib/util.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -143,9 +143,11 @@
   define('PRIV_GUIDE', 0x08);
   define('PRIV_WOTD', 0x10);
   define('PRIV_SUPER', 0x20);
+  define('PRIV_STRUCT', 0x40);
   define('PRIV_VIEW_HIDDEN', PRIV_ADMIN);
-  define('NUM_PRIVILEGES', 6);
-  $GLOBALS['PRIV_NAMES'] = array('Administrator', 'Moderator LOC', 'Moderator', 'Editor al ghidului de exprimare', 'Editor al cuvântului zilei', 'Utilizator privilegiat');
+  define('NUM_PRIVILEGES', 7);
+  $GLOBALS['PRIV_NAMES'] = array('Administrator', 'Moderator LOC', 'Moderator', 'Editor al ghidului de exprimare', 'Editor al cuvântului zilei',
+                                 'Utilizator privilegiat', '«Structurist» al definițiilor');
 
   //Source 
   define('SOURCE_TYPE_HIDDEN', 3);
@@ -215,7 +217,7 @@
 
 function util_getRequestCheckboxArray($name, $separator) {
   $arr = util_getRequestParameter($name);
-  return $arr ? implode($arr, $separator) : '';
+  return $arr ? implode($separator, $arr) : '';
 }
 
 /** Returns an array of values from a parameter in CSV format **/

Modified: templates/admin/lexemEdit.ihtml
==============================================================================
--- templates/admin/lexemEdit.ihtml	Mon Aug 19 11:40:12 2013	(r941)
+++ templates/admin/lexemEdit.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -1,280 +1,351 @@
 {assign var="ifMap" value=$ifMap|default:null}
 {assign var="serchResults" value=$searchResults|default:null}
-<div class="lexemSectionHeader">Proprietăți</div>
 
+{* Stem meaning editor that we clone whenever we append a new meaning *}
+<span id="stemNode">
+  <span class="id"></span>
+  <span class="meaningTags"></span>
+  <span class="meaningTagIds"></span>
+  <span class="internalRep"></span>
+  <span class="htmlRep"></span>
+  <span class="internalComment"></span>
+  <span class="htmlComment"></span>
+  <span class="sources"></span>
+  <span class="sourceIds"></span>
+  <span class="synonyms"></span>
+  <span class="synonymIds"></span>
+  <span class="antonyms"></span>
+  <span class="antonymIds"></span>
+</span>
+      
 <form action="lexemEdit.php" method="post">
-<div class="lexemSection">
   <input type="hidden" name="lexemId" value="{$lexem->id}"/>
-  <table class="editableFields">
-    <tr>
-      <td>Nume:</td>
-      <td>
-        {if $canEditForm}  
-          <input type="text" name="lexemForm" value="{$lexem->form|escape}" size="40"/>
-        {else}
-          <input type="hidden" name="lexemForm" value="{$lexem->form|escape}"/>
-          {$lexem->form|escape}
-        {/if}
+  <input type="hidden" name="jsonMeanings" value=""/>
+  <input type="hidden" name="mergeLexemId" value=""/>
 
-        <span class="tooltip" title="Cuvântul-titlu. Accentul trebuie indicat chiar și pentru lexemele monosilabice, altfel paradigma nu va conține
-        deloc accente. Indicați accentul prin apostrof ('a), nu îl includeți în caracter (á). Valoarea acestui câmp este folosită la căutări și este
-        vizibilă public la afișarea flexiunilor unui cuvânt. Odată ce un lexem a fost inclus în LOC, numele și descrierea lexemului mai pot fi
-        modificate numai de către moderatorii LOC."> </span>
-
-      </td>
-    </tr>
-    <tr>
-      <td>Descriere:</td>
-      <td>
-        {if $canEditForm}  
-          <input type="text" name="lexemDescription" value="{$lexem->description|escape}" size="40"/>
-        {else}
-          <input type="hidden" name="lexemDescription" value="{$lexem->description|escape}"/>
-          {$lexem->description|escape}
-        {/if}
+  {include file="admin/lexemEditActions.ihtml"}
 
-        <span class="tooltip" title="O scurtă explicație, vizibilă public, care diferențiază lexemele omonime. Pentru cuvintele fără omonime, ea poate
-        fi vidă."> </span>
+<div class="box">
+  <div class="boxTitle">Proprietăți</div>
+  <div class="boxContents">
+    <table>
+      <tr>
+        <td><label for="lexemForm">nume:</label></td>
+        <td>
+          {if $canEdit.form}  
+            <input type="text" id="lexemForm" name="lexemForm" value="{$lexem->form|escape}" size="40"/>
+          {else}
+            <input type="hidden" name="lexemForm" value="{$lexem->form|escape}"/>
+            {$lexem->form|escape}
+          {/if}
+          <span class="tooltip" title="Cuvântul-titlu. Accentul trebuie indicat chiar și pentru lexemele monosilabice, altfel paradigma nu va
+          conține deloc accente. Valoarea acestui câmp este folosită la căutări și este vizibilă public la afișarea flexiunilor unui cuvânt. Odată
+          ce un lexem a fost inclus în LOC, numele și descrierea lexemului mai pot fi modificate numai de către moderatorii LOC."> </span>
+        </td>
 
-      </td>
-    </tr>
-    <tr>
-      <td>Etichete:</td>
-      <td>
-        <select id="lexemSourceIds" name="lexemSourceIds[]" multiple="multiple">
-          {foreach from=$sources item=s}
-            <option value="{$s->id}" {if array_key_exists($s->id, $lexemSourceIdMap)}selected="selected"{/if}>{$s->shortName}</option>
-          {/foreach}
-        </select>
-        <br/>
-        <input type="text" name="lexemTags" value="{$lexem->tags|escape}" size="40"/>
-
-        <span class="tooltip" title="O scurtă clasificare, vizibilă public, care marchează sursa flexiunii. Pentru cuvintele cu flexiuni în DOOM-ul
-        curent (DOOM2 în acest moment), ea poate fi vidă. Sursele pot reprezenta dicționare, autori cunoscuți, inclusiv părerea moderatorului, dar
-        trebuie documentate clar aceste situații."> </span>
-
-      </td>
-    </tr>
-    <tr>
-      <td>Inclus în LOC</td>
-      <td>
-        {if $sUser && ($sUser->moderator & $smarty.const.PRIV_LOC)}
-          <input type="checkbox" name="lexemIsLoc" value="1" {if $lexem->isLoc}checked="checked"{/if}/>
-        {else}
-          <input type="hidden" name="lexemIsLoc" value="{if $lexem->isLoc}1{/if}"/>
-          {if $lexem->isLoc}Da{else}Nu{/if}
-        {/if}
+        <td class="rightColumn"><label for="lexemSourceIds">surse:</label></td>
+        <td>
+          {if $canEdit.sources}
+            <select id="lexemSourceIds" name="lexemSourceIds[]" multiple="multiple">
+              {foreach from=$sources item=s}
+                <option value="{$s->id}" {if array_key_exists($s->id, $lexemSourceIdMap)}selected="selected"{/if}>{$s->shortName}</option>
+              {/foreach}
+            </select>
+          {else}
+            {foreach from=$lexemSourceIdMap key=sourceId item=ignored}
+              <input type="hidden" name="lexemSourceIds[]" value="{$sourceId}"/>
+              {$sources[$sourceId]->shortName},
+            {/foreach}
+          {/if}
+        </td>
+      </tr>
+
+      <tr>
+        <td><label for="lexemDescription">descriere:</label></td>
+        <td>
+          {if $canEdit.description}
+            <input type="text" id="lexemDescription" name="lexemDescription" value="{$lexem->description|escape}" size="40"
+                   placeholder="opțională, pentru diferențierea omonimelor"/>
+          {else}
+            <input type="hidden" name="lexemDescription" value="{$lexem->description|escape}"/>
+            {$lexem->description|escape}
+          {/if}
+        </td>
 
-        <span class="tooltip" title="DEX online menține informații despre lexemele acceptate în Lista Oficială de Cuvinte a Federației Române de
-        Scrabble. Acest câmp este vizibil pentru toți moderatorii, dar poate fi modificat numai de către un set restrâns de moderatori care au drept
-        de gestiune a LOC."> </span>
-
-      </td>
-    </tr>
-    <tr>
-      <td>Necesită accent</td>
-      <td>
-        <input type="checkbox" name="needsAccent" value="1" {if !$lexem->noAccent}checked="checked"{/if}/>
-
-        <span class="tooltip" title="Majoritatea lexemelor necesită accent. Excepție fac cuvintele compuse, denumirile științifice de animale și
-        plante, elementele de compunere etc."> </span>
-
-      </td>
-    </tr>
-    {if $homonyms}
-      <tr>
-        <td>Lexeme omonime:</td>
-        <td>
-          {foreach from=$homonyms item=h key=i}
-            {if $i}|{/if}
-            <a href="lexemEdit.php?lexemId={$h->id}"
-              >{include file="common/bits/lexemName.ihtml"
-                        lexem=$h}</a>
-            [{$h->modelType}{$h->modelNumber}{$h->restriction}]
-          {/foreach}
+        <td class="rightColumn"><label for="lexemTags">etichete:</label></td>
+        <td>
+          {if $canEdit.tags}
+            <input type="text" id="lexemTags" name="lexemTags" value="{$lexem->tags|escape}" size="40"
+                   placeholder="explicații despre sursa flexiunii"/>
+          {else}
+            <input type="hidden" name="lexemTags" value="{$lexem->tags|escape}"/>
+            {$lexem->tags|escape}
+          {/if}
+          <span class="tooltip" title="O scurtă clasificare, vizibilă public, care marchează sursa flexiunii. Pentru cuvintele cu flexiuni în DOOM-ul
+          curent (DOOM2 în acest moment), ea poate fi vidă. Sursele pot reprezenta dicționare, autori cunoscuți, inclusiv părerea moderatorului, dar
+          trebuie documentate clar aceste situații."> </span>
         </td>
       </tr>
-    {/if}
-  </table>
-</div>
 
-{if $lexem->modelType == 'T' && !$lexem->isLoc && $homonyms}
-  <div class="lexemSectionHeader">Sugestii pentru dezambiguizare</div>
+      <tr>
+        <td><label for="variantOfId">variantă a lui:</label></td>
+        <td>
+          <input id="variantOfId" name="variantOfId" value="{$lexem->variantOfId}" type="text"/>
+          <span class="tooltip"
+                title="Variantele nu pot avea sensuri, exemple, variante sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
+        </td>
 
-  <div class="lexemSection">
-    <ul>
-      {foreach from=$homonyms item=h}
-        <li>
-          <a href="lexemMerge.php?id1={$lexem->id}&id2={$h->id}">
-            Unifică cu {$h->form} [{$h->modelType}{$h->modelNumber}{$h->restriction}]
-          </a>
-        </li>
-      {/foreach}
-    </ul>
-  </div>
-{/if}
+        <td class="rightColumn"><label for="variantIds">variante:</label></td>
+        <td>
+          <input id="variantIds" name="variantIds" value="{','|implode:$variantIds}" type="text"/>
+          <span class="tooltip"
+                title="Variantele nu pot avea sensuri, exemple, variante sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
+        </td>
+      </tr>
 
-<div class="lexemSectionHeader">Paradigmă</div>
+      <tr>
+        <td><label for="hyphenations">silabisiri:</label></td>
+        <td>
+          <input id="hyphenations" name="hyphenations" type="text" value="{$lexem->hyphenations}" size="40"
+                 placeholder="opționale, despărțite prin virgule">
+        </td>
 
-<div class="lexemSection">
-  {if $sUser && ($sUser->moderator & $smarty.const.PRIV_LOC)}
-    Puteți face etichetarea în trei moduri: (1) alegeți una dintre
-    sugestii; (2) indicați un cuvânt care se flexionează la fel; sau
-    (3) indicați tipul și numărul modelului.
-    <br/><br/>
-
-    <b>1. {include file="common/bits/lexemName.ihtml" lexem=$lexem}</b> se flexionează ca...
-    {foreach from=$suggestedLexems item=l key=i}
-      {if $i}|{/if}
-      {include file="common/bits/lexemName.ihtml" lexem=$l accent=1}
-      {include file="common/bits/similarModel.ihtml" lexem=$lexem similar=$l}
-    {/foreach}
-    <br/><br/>
+        <td class="rightColumn"><label for="lexemIsLoc">inclus în LOC:</label></td>
+        <td>
+          {if $canEdit.isLoc}
+            <input type="checkbox" id="lexemIsLoc" name="lexemIsLoc" value="1" {if $lexem->isLoc}checked="checked"{/if}/>
+          {else}
+            <input type="hidden" name="lexemIsLoc" value="{if $lexem->isLoc}1{/if}"/>
+            {if $lexem->isLoc}Da{else}Nu{/if}
+          {/if}
+          <span class="tooltip" title="DEX online menține Lista Oficială de Cuvinte a Federației Române de Scrabble. Acest câmp poate fi modificat
+          numai de către un set restrâns de administratori ai LOC."> </span>
+        </td>
+      </tr>
 
-    <b>2. {include file="common/bits/lexemName.ihtml" lexem=$lexem}</b> se flexionează ca
-    <input id="similarLexemId" type="text" name="similarLexemId"/>
-    <br/><br/>
-
-    <b>3. {include file="common/bits/lexemName.ihtml" lexem=$lexem}</b> se flexionează conform modelului
-    <select name="modelType" id="modelTypeListId" onchange="return updateModelList(false)">
-      {foreach from=$modelTypes item=mt}
-        <option value="{$mt->code|escape}"
-          {if $mt->code == $lexem->modelType}selected="selected"{/if}
-          >{$mt->code|escape}
-        </option>
-      {/foreach}
-    </select>
-    <select name="modelNumber" id="modelListId">
-      {foreach from=$models item=m}
-        <option value="{$m->number}"
-          {if $m->number == $lexem->modelNumber}selected="selected"{/if}
-          >{$m->number}{if !$m->id}*{/if} ({$m->exponent})
-        </option>
+      <tr>
+        <td><label for="pronunciations">pronunții:</label></td>
+        <td>
+          <input id="pronunciations" name="pronunciations" type="text" value="{$lexem->pronunciations}" size="40"
+                 placeholder="opționale, despărțite prin virgule">
+        </td>
+
+        <td class="rightColumn"><label for="needsAccent">necesită accent:</label></td>
+        <td>        
+          <input type="checkbox" id="needsAccent" name="needsAccent" value="1" {if !$lexem->noAccent}checked="checked"{/if}/>
+          <span class="tooltip" title="Majoritatea lexemelor necesită accent. Excepție fac cuvintele compuse, denumirile științifice de animale și
+          plante, elementele de compunere etc."> </span>
+        </td>
+      </tr>
+
+      {if $homonyms}
+        <tr>
+          <td>omonime:</td>
+          <td>
+            {foreach from=$homonyms item=h key=i}
+              {if $i}|{/if}
+              <a href="lexemEdit.php?lexemId={$h->id}">{include file="common/bits/lexemName.ihtml" lexem=$h}</a>
+              [{$h->modelType}{$h->modelNumber}{$h->restriction}]
+            {/foreach}
+          </td>
+          <td class="rightColumn"></td><td></td>
+        </tr>
+      {/if}
+    </table>
+  </div>
+</div>
+
+<div class="box">
+  <div class="boxTitle">Paradigmă</div>
+  <div class="boxContents">
+
+    {if $canEdit.paradigm}
+      model:   
+      <select name="modelType" id="modelTypeListId" onchange="return updateModelList(false)">
+        {foreach from=$modelTypes item=mt}
+          <option value="{$mt->code|escape}"
+            {if $mt->code == $lexem->modelType}selected="selected"{/if}
+            >{$mt->code|escape}
+          </option>
+        {/foreach}
+      </select>
+      <select name="modelNumber" id="modelListId">
+        {foreach from=$models item=m}
+          <option value="{$m->number}"
+            {if $m->number == $lexem->modelNumber}selected="selected"{/if}
+            >{$m->number}{if !$m->id}*{/if} ({$m->exponent})
+          </option>
+        {/foreach}
+      </select>
+
+      restricții:
+      <input type="checkbox" id="restrS" name="restr[]" value="S" {if $restrS}checked="checked"{/if}/><label for="restrS">Singular</label>
+       
+      <input type="checkbox" id="restrP" name="restr[]" value="P" {if $restrP}checked="checked"{/if}/><label for="restrP">Plural</label>
+       
+      <input type="checkbox" id="restrU" name="restr[]" value="U" {if $restrU}checked="checked"{/if}/><label for="restrU">Unipersonal</label>
+       
+      <input type="checkbox" id="restrI" name="restr[]" value="I" {if $restrI}checked="checked"{/if}/><label for="restrI">Impersonal</label>
+       
+      <input type="checkbox" id="restrT" name="restr[]" value="T" {if $restrT}checked="checked"{/if}/><label for="restrT">Trecut</label>
+      <br/>
+
+      sugestii:
+      {foreach from=$suggestedLexems item=l}
+        {include file="common/bits/lexemName.ihtml" lexem=$l accent=1}
+        {include file="common/bits/similarModel.ihtml" similar=$l} |
       {/foreach}
-    </select>
+      <input id="similarLexemId" type="text" name="similarLexemId"/>
+    {else}
+      <input type="hidden" name="modelType" value="{$lexem->modelType}"/>
+      <input type="hidden" name="modelNumber" value="{$lexem->modelNumber}"/>
+      {if $restrS}<input type="hidden" name="restr[]" value="S"/>{/if}
+      {if $restrP}<input type="hidden" name="restr[]" value="P"/>{/if}
+      {if $restrU}<input type="hidden" name="restr[]" value="U"/>{/if}
+      {if $restrI}<input type="hidden" name="restr[]" value="I"/>{/if}
+      {if $restrT}<input type="hidden" name="restr[]" value="T"/>{/if}
+      <b>{include file="common/bits/lexemName.ihtml" lexem=$lexem}</b> se flexionează conform modelului
+      {$lexem->modelType}{$lexem->modelNumber}{$lexem->restriction}.
+    {/if}
+
+    {if $ifMap}
+      {include file="common/paradigm/current/paradigm.ihtml" lexem=$lexem ifMap=$ifMap}
+    {/if}
+    <br/>
+
+    Comentarii despre paradigmă:
     <br/>
 
-    cu restricțiile
-    <input type="checkbox" id="restrS" name="restr[]" value="S"
-      {if $restrS}checked="checked"{/if}/>
-    <label for="restrS">Singular</label>
-      
-    <input type="checkbox" id="restrP" name="restr[]" value="P"
-      {if $restrP}checked="checked"{/if}/>
-    <label for="restrP">Plural</label>
-      
-    <input type="checkbox" id="restrU" name="restr[]" value="U"
-      {if $restrU}checked="checked"{/if}/>
-    <label for="restrU">Unipersonal</label>
-      
-    <input type="checkbox" id="restrI" name="restr[]" value="I"
-      {if $restrI}checked="checked"{/if}/>
-    <label for="restrI">Impersonal</label>
-      
-    <input type="checkbox" id="restrT" name="restr[]" value="T"
-      {if $restrT}checked="checked"{/if}/>
-    <label for="restrT">Trecut</label>
-  {else}
-    <b>{include file="common/bits/lexemName.ihtml" lexem=$lexem}</b> se flexionează conform modelului
-    {$lexem->modelType}{$lexem->modelNumber}{$lexem->restriction}.
-  {/if}
+    <textarea name="lexemComment" rows="3" cols="60" class="commentTextArea"
+              placeholder="Dacă observați greșeli în paradigmă, notați-le în acest câmp și ele vor fi semnalate unui moderator cu drept de gestiune a LOC."
+              >{$lexem->comment|escape}</textarea>
+  </div>
 </div>
 
-{if $ifMap && !$errorMessage}
-  {include file="common/paradigm/current/paradigm.ihtml" lexem=$lexem ifMap=$ifMap}
-{/if}
-
-<div class="lexemSection">
-  Comentarii despre paradigmă:
-
-  <span class="tooltip" title="Dacă observați greșeli în paradigmă, notați-le în acest câmp și ele vor fi semnalate unui moderator cu drept de
-  gestiune a LOC."> </span>
-
-  <br/>
-  <textarea name="lexemComment" rows="4" cols="60" class="commentTextArea"
-    >{$lexem->comment|escape}</textarea>
+<div class="box">
+  <div class="boxTitle">Sensuri</div>
+  <div id="meaningTreeContainer" class="boxContents">
+    {include file="common/bits/meaningTree.ihtml" meanings=$meanings id="meaningTree"}
+
+    <div id="meaningMenu">
+      <input type="button" id="addMeaningButton" value="adaugă sens"/>
+      <input type="button" id="addSubmeaningButton" value="adaugă subsens"/>
+      <input type="button" id="deleteMeaningButton" value="șterge sens"/>
+    </div>
+  </div>
 </div>
 
-<div class="lexemSectionHeader">Acțiuni</div>
+<div class="box">
+  <div class="boxTitle">Editorul de sensuri</div>
+  <div class="boxContents">
+    <table class="meaningEditor">
+      <tr>
+        <td class="leftColumn" rowspan="5">
+          <textarea id="editorInternalRep" rows="10" cols="10" disabled="disabled" placeholder="sensul definiției..."></textarea>
+        </td>
 
-<div class="lexemSection">
-  <input type="submit" name="refreshLexem" value="Reafișează"/>
-    
-  <input type="submit" name="saveLexem" value="Salvează"/>
-    
-  <input type="submit" name="cloneLexem" value="Clonează"/>
-
-  <span class="tooltip" title="Clonarea creează un lexem aproape identic cu cel în curs de editare. El va avea același nume și aceleași definiții
-  asociate. Descrierea noului lexem va fi prefixată cu cuvântul <b>CLONĂ.</b> Clona va fi creată fără flexiuni (modelul de flexionare temporar T1),
-  chiar dacă lexemul original avea flexiuni. Folosiți clonarea pentru a sparge un lexem nediferențiat în două lexeme omonime. De exemplu, dacă inițial
-  toate definițiile pentru <i>episcop</i> sunt reunite într-un singur lexem, puteți să clonați acest lexem și să adăugați descrierile "prelat" și
-  "aparat". Apoi trebuie să asociați definițiile în mod corect cu cele două lexeme."> </span>
-
-    
-  <input type="submit" name="deleteLexem" value="Șterge"
-       {if $lexem->isLoc}disabled="disabled"{/if}
-       onclick="return confirm('Confirmați ștergerea acestui lexem?');"/>
-
-  <span class="tooltip" title="Acest buton șterge lexemul și formele sale flexionare și disociază definițiile asociate cu acest lexem. Definițiile în
-  sine nu vor fi șterse, dar, dacă nu sunt asociate cu niciun alt lexem, ele vor deveni neasociate, ceea ce înseamnă că nu vor fi niciodată afișate
-  ca rezultat al unei căutări. Probabil trebuie să vă asigurați că definițiile respective sunt asociate cu un alt lexem înainte de a-l șterge pe
-  acesta. <b>Notă:</b> Lexemele care sunt parte din LOC nu pot fi șterse, pentru a preveni modificarea accidentală a LOC. Dacă sunteți moderator cu
-  drept de gestiune a LOC, scoateți întâi lexemul din LOC, după care îl puteți șterge."> </span>
-
-  <br/>
-
-  Asociază definiția cu ID-ul:
-  <input type="text" name="associateDefinitionId"/>
-  <input type="submit" name="associateDefinition" value="Asociază"/>
+        <td>
+          <textarea id="editorInternalComment" rows="3" cols="10" disabled="disabled" placeholder="comentariu..."></textarea>
+        </td>
+      </tr>
 
-  <span class="tooltip" title="Tastați ID-ul definiției pentru a o asocia cu acest lexem. Puteți, mai comod, să vizitați pagina definiției pe care
-  doriți să o asociați și să adăugați acest lexem la lista ei de lexeme (deoarece în acel caz puteți căuta lexemul după nume)."> </span>
+      <tr>
+        <td>
+          <label for="editorSources">surse:</label>
+          <select id="editorSources" multiple="multiple">
+            {foreach from=$sources item=s}
+              <option value="{$s->id}">{$s->shortName}</option>
+            {/foreach}
+          </select>
+        </td>
+      </tr>
 
-</div>
-</form>
+      <tr>
+        <td>
+          <label for="editorTags">etichete:</label>
+          <select id="editorTags" multiple="multiple">
+            {foreach from=$meaningTags item=mt}
+              <option value="{$mt->id}">{$mt->value}</option>
+            {/foreach}
+          </select>
+        </td>
+      </tr>
 
-<div class="lexemSectionHeader">
-  Definiții asociate ({$searchResults|@count}):
+      <tr>
+        <td>
+          <label for="editorSynonyms">sinonime:</label>
+          <input id="editorSynonyms" type="hidden"/>
+        </td>
+      </tr>
+
+      <tr>
+        <td>
+          <label for="editorAntonyms">antonime:</label>
+          <input id="editorAntonyms" type="hidden"/>
+        </td>
+      </tr>
+
+      <tr>
+        <td colspan="2">
+          <input id="editMeaningAcceptButton" type="button" disabled="disabled" value="acceptă"/>
+          <input id="editMeaningCancelButton" type="button" disabled="disabled" value="renunță"/>
+        </td>
+      </tr>
+    </table>
+  </div>
 </div>
 
-<div class="lexemSection">
-  {foreach from=$searchResults item=row}
-    {$row->definition->htmlRep}<br/>
-    <span class="defDetails">
-      Id: {$row->definition->id} |
-      Sursa: {$row->source->shortName|escape} |
-      Trimisă de {$row->user->nick|escape},
-      {$row->definition->createDate|date_format:"%e %b %Y"} |
-      {assign var=status value="`$row->definition->status`"}
-      {assign var=statusName value="`$allStatuses[$status]`"}
-      Starea: {$statusName} |
-
-      <a href="definitionEdit.php?definitionId={$row->definition->id}"
-        >Editează</a> |
-
-      <a href="lexemEdit.php?lexemId={$lexem->id}&dissociateDefinitionId={$row->definition->id}"
-         onclick="return confirmDissociateDefinition({$row->definition->id})"
-        >Disociază</a>
-    </span>
-    <br/><br/>
-  {/foreach}
-
-  {if !count($searchResults)}
-    Nu există nicio definiție. Puteți crea o
-    mini-definiție. Introduceți termenul-destinație, fără alte
-    formatări (bold, italic etc.):<br/>
-
-    <form action="lexemEdit.php" method="post">
-      <input type="hidden" name="lexemId" value="{$lexem->id}"/>
-      <b>{$definitionLexem|escape}</b> v.
-      <input type="text" name="miniDefTarget" size="20"
-             class="miniDefTarget"/>.
-        
-      <input type="submit" name="createDefinition" value="Creează"/>
-    </form>
-  {/if}
+<div class="box">
+  <div class="boxTitle">Definiții asociate ({$searchResults|@count})</div>
+  <div class="boxContents">
+    {foreach from=$searchResults item=row}
+      <div>
+        <div class="defInternalRep">{$row->definition->internalRep|escape}</div>
+        <div class="defHtmlRep">{$row->definition->htmlRep}</div>
+        <span class="defDetails">
+          id: {$row->definition->id}
+          | sursa: {$row->source->shortName|escape}
+          {assign var=status value="`$row->definition->status`"}
+          {assign var=statusName value="`$allStatuses[$status]`"}
+          | starea: {$statusName}
+          {if $canEdit.general}
+            | <a href="definitionEdit.php?definitionId={$row->definition->id}" target="_blank">editează</a>
+            | <a href="lexemEdit.php?lexemId={$lexem->id}&dissociateDefinitionId={$row->definition->id}"
+                 onclick="return confirmDissociateDefinition({$row->definition->id})">disociază</a>
+          {/if}
+          | <a href="#" class="toggleInternalHtmlLink">arată html</a>
+        </span>
+        {if $row->comment}
+          <div class="commentInternalRep">
+            Comentariu: {$row->comment->contents} -
+            <a href="{$wwwRoot}utilizator/{$row->commentAuthor->nick|escape:"url"}">{$row->commentAuthor->nick|escape}</a>
+          </div>
+        {/if}
+      </div>
+    {/foreach}
+
+    {if $canEdit.general}
+      <div class="addDefinition">
+        <input type="text" id="associateDefinitionId" name="associateDefinitionId"/>
+        <input type="submit" name="associateDefinition" value="Asociază"/>
+      </div>
+    {/if}
+
+    {if !count($searchResults) && $canEdit.general}
+      <div class="addDefinition">
+        Puteți crea o mini-definiție. Introduceți termenul-destinație, fără alte formatări (bold, italic etc.):<br/>
+    
+        <b>{$definitionLexem|escape}</b> v. <input type="text" name="miniDefTarget" size="20" class="miniDefTarget"/>.
+          
+        <input type="submit" name="createDefinition" value="Creează"/>
+      </div>
+    {/if}
+  </div>
 </div>
 
+{include file="admin/lexemEditActions.ihtml"}
+</form>
+
 <script>
   $(lexemEditInit);
 </script>

Added: templates/admin/lexemEditActions.ihtml
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ templates/admin/lexemEditActions.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -0,0 +1,37 @@
+<div class="lexemEditActions">
+  <input type="submit" name="refreshLexem" value="Reafișează" class="lexemEditSaveButton"/>
+    
+  <input type="submit" name="saveLexem" value="Salvează" class="lexemEditSaveButton"/>
+
+  {if $canEdit.general}
+      
+    <input type="submit" name="cloneLexem" value="Clonează"/>
+  
+    <span class="tooltip" title="Clonarea creează un lexem aproape identic cu cel în curs de editare. El va avea același nume și aceleași definiții
+    asociate. Descrierea noului lexem va fi prefixată cu cuvântul CLONĂ. Clona va fi creată fără flexiuni (modelul de flexionare temporar T1),
+    chiar dacă lexemul original avea flexiuni. Folosiți clonarea pentru a sparge un lexem nediferențiat în două lexeme omonime. De exemplu, dacă inițial
+    toate definițiile pentru 'episcop' sunt reunite într-un singur lexem, puteți să clonați acest lexem și să adăugați descrierile 'prelat' și
+    'aparat'. Apoi trebuie să asociați definițiile în mod corect cu cele două lexeme."> </span>
+      
+  
+    <input type="submit" name="deleteLexem" value="Șterge" {if $lexem->isLoc}disabled="disabled"{/if}
+           onclick="return confirm('Confirmați ștergerea acestui lexem?');"/>
+    
+    <span class="tooltip" title="Șterge lexemul. Definițiile cu care el era asociat nu vor fi șterse, dar, dacă nu sunt asociate cu niciun alt lexem,
+    ele vor deveni neasociate, ceea ce înseamnă că nu vor fi niciodată afișate ca rezultat al unei căutări. Probabil trebuie să vă asigurați că
+    definițiile respective sunt asociate cu un alt lexem înainte de a-l șterge pe acesta. Notă: Lexemele care sunt parte din LOC nu pot fi șterse,
+    pentru a preveni modificarea accidentală a LOC. Dacă sunteți moderator cu drept de gestiune a LOC, scoateți întâi lexemul din LOC, după care îl
+    puteți șterge."> </span>
+    
+    {if $lexem->modelType == 'T' && !$lexem->isLoc && $homonyms}
+      {foreach from=$homonyms item=h}
+          
+        <input type="submit" class="mergeLexem" id="mergeLexem_{$h->id}" name="mergeLexem"
+               value="Unifică cu {$h->form} {$h->modelType}{$h->modelNumber}{$h->restriction}"/>
+      {/foreach}
+    {/if}
+  {/if}
+  
+    
+  <a href="?lexemId={$lexem->id}">renunță</a>
+</div>

Modified: templates/admin/pageLayout.ihtml
==============================================================================
--- templates/admin/pageLayout.ihtml	Mon Aug 19 11:40:12 2013	(r941)
+++ templates/admin/pageLayout.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -1,10 +1,9 @@
 {assign var=sectionCount value=$sectionCount|default:null}
 {assign var=sectionSources value=$sectionSources|default:false}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
   <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+    <meta charset="utf-8"/>
     {include file="common/bits/cssJs.ihtml"}
     <title>DEX | {$sectionTitle|escape}</title>
   </head>

Modified: templates/common/bits/ifArray.ihtml
==============================================================================
--- templates/common/bits/ifArray.ihtml	Mon Aug 19 11:40:12 2013	(r941)
+++ templates/common/bits/ifArray.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -7,7 +7,7 @@
     {foreach from=$ifArray item=if key=i}
         {if $i}, {/if}
         {if !$if->recommended}<span class="notRecommended" title="formă nerecomandată">{/if}
-          {$if->form|regex_replace:"/\'(a|e|i|o|u|ă|î|â|y)/":"<font class=\"accented\">\$1</font>"}
+          {$if->form|regex_replace:"/\'(a|e|i|o|u|ă|î|â|y)/":"<span class=\"accented\">\$1</span>"}
         {if !$if->recommended}*</span>{/if}
     {/foreach}
   {/strip}

Modified: templates/common/bits/similarModel.ihtml
==============================================================================
--- templates/common/bits/similarModel.ihtml	Mon Aug 19 11:40:12 2013	(r941)
+++ templates/common/bits/similarModel.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -1,14 +1,13 @@
 {strip}
+  {assign var="idText" value="`$similar->modelNumber`_`$similar->restriction`"}
+  {assign var="tag" value="`$similar->modelNumber``$similar->restriction`"}
   {if $similar->modelType == 'V' || $similar->modelType == 'VT'}
-    {assign var="tag" value="`$similar->modelNumber``$similar->restriction`"}
-    <a href="lexemEdit.php?lexemId={$lexem->id}&similarModel=V{$tag}">V{$tag}</a> /
-    <a href="lexemEdit.php?lexemId={$lexem->id}&similarModel=VT{$tag}">VT{$tag}</a>
+    <a href="#" class="similarLink" id="similar_V_{$idText}">V{$tag}</a> /
+    <a href="#" class="similarLink" id="similar_VT_{$idText}">VT{$tag}</a>
   {elseif $similar->modelType == 'A' || $similar->modelType == 'MF'}
-    {assign var="tag" value="`$similar->modelNumber``$similar->restriction`"}
-    <a href="lexemEdit.php?lexemId={$lexem->id}&similarModel=A{$tag}">A{$tag}</a> /
-    <a href="lexemEdit.php?lexemId={$lexem->id}&similarModel=MF{$tag}">MF{$tag}</a>
+    <a href="#" class="similarLink" id="similar_A_{$idText}">A{$tag}</a> /
+    <a href="#" class="similarLink" id="similar_MF_{$idText}">MF{$tag}</a>
   {else}
-    {assign var="tag" value="`$similar->modelType``$similar->modelNumber``$similar->restriction`"}
-    <a href="lexemEdit.php?lexemId={$lexem->id}&similarModel={$tag}">{$tag}</a>
+    <a href="#" class="similarLink" id="similar_{$similar->modelType}_{$idText}">{$similar->modelType}{$tag}</a>
   {/if}
 {/strip}

Modified: templates/common/modele-flexiune.ihtml
==============================================================================
--- templates/common/modele-flexiune.ihtml	Mon Aug 19 11:40:12 2013	(r941)
+++ templates/common/modele-flexiune.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -39,7 +39,7 @@
 {if $modelsToDisplay}
   {foreach from=$modelsToDisplay item=m key=i}
     <div class="scrabbleModelName">
-      {$m->number}. {$m->exponent|regex_replace:"/\'(a|e|i|o|u|ă|î|â)/":"<font class=\"accented\">\$1</font>"}
+      {$m->number}. {$m->exponent|regex_replace:"/\'(a|e|i|o|u|ă|î|â)/":"<span class=\"accented\">\$1</span>"}
     </div>
     {include file="common/paradigm/$selectedLocVersion/paradigm.ihtml"
              lexem=$lexems[$i]

Modified: templates/common/moderatori.ihtml
==============================================================================
--- templates/common/moderatori.ihtml	Mon Aug 19 11:40:12 2013	(r941)
+++ templates/common/moderatori.ihtml	Mon Aug 19 16:28:41 2013	(r942)
@@ -8,6 +8,7 @@
       <th>Ghid de exprimare<br/>(nefolosit)</th>
       <th>Cuvântul zilei</th>
       <th>Acces căutare</th>
+      <th>«Structurist» al definițiilor</th>
     </tr>
     {foreach from=$users item=user}
       <tr>

Deleted: templates/struct/dexEdit.ihtml
==============================================================================
--- templates/struct/dexEdit.ihtml	Mon Aug 19 16:28:41 2013	(r941)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,162 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-    {include file="common/bits/cssJs.ihtml"}
-    <title>DEX | {$pageTitle|escape}</title>
-  </head>
-
-  <body>
-    {include file="common/flashMessages.ihtml"}
-    <form id="meaningForm" action="dexEdit.php" method="post">
-      <input type="hidden" name="jsonMeanings" value=""/>
-      <input type="hidden" name="lexemId" value="{$lexem->id}"/>
-
-      <span id="stemNode">
-        <span class="id"></span>
-        <span class="meaningTags"></span>
-        <span class="meaningTagIds"></span>
-        <span class="internalRep"></span>
-        <span class="htmlRep"></span>
-        <span class="internalComment"></span>
-        <span class="htmlComment"></span>
-        <span class="sources"></span>
-        <span class="sourceIds"></span>
-        <span class="synonyms"></span>
-        <span class="synonymIds"></span>
-        <span class="antonyms"></span>
-        <span class="antonymIds"></span>
-      </span>
-      
-      <div id="saveButtonContainer">
-        <input id="dexEditSaveButton" type="button" value="salvează totul"/>
-        <div>
-          <a href="?lexemId={$lexem->id}">anulează</a> |
-          <a href="{$wwwRoot}admin/lexemEdit.php?lexemId={$lexem->id}">editează lexemul</a>
-        </div>
-      </div>
-
-      <div id="parameters" class="box">
-        <div class="boxTitle">Parametri pentru {include file="common/bits/lexemName.ihtml"}</div>
-        <div class="boxContents">
-          <label for="hyphenations">silabisiri:</label>
-          <input id="hyphenations" name="hyphenations" type="text" value="{$lexem->hyphenations}" size="25"/>
-          <span class="tooltip"
-                title="una sau mai multe silabisiri, despărțite prin virgule"> </span>
-          <br/>
-
-          <label for="pronunciations">pronunții:</label>
-          <input id="pronunciations" name="pronunciations" type="text" value="{$lexem->pronunciations}" size="25"/>
-          <span class="tooltip"
-                title="una sau mai multe pronunții, despărțite prin virgule"> </span>
-          <br/>
-
-          <label>variantă a lui:</label>
-          <input id="variantOfId" name="variantOfId" value="{$lexem->variantOfId}" type="text"/>
-          <span class="tooltip"
-                title="Variantele nu pot avea sensuri, exemple, variante sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
-          <br/>
-
-          <label for="variantIds">variante:</label>
-          <input id="variantIds" name="variantIds" value="{','|implode:$variantIds}" type="text"/>
-          <span class="tooltip"
-                title="Variantele nu pot avea sensuri, exemple, variante sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
-        </div>
-      </div>
-      <div style="clear: both"></div>
-
-      <div class="box">
-        <div class="boxTitle">Sensuri pentru {include file="common/bits/lexemName.ihtml"}</div>
-        <div id="meaningTreeContainer" class="boxContents">
-          {include file="common/bits/meaningTree.ihtml" meanings=$meanings id="meaningTree"}
-
-          <div id="meaningMenu">
-            <input type="button" id="addMeaningButton" value="adaugă sens"/>
-            <input type="button" id="addSubmeaningButton" value="adaugă subsens"/>
-            <input type="button" id="deleteMeaningButton" value="șterge sens"/>
-          </div>
-        </div>
-      </div>
-
-      <div id="dexEditLeftColumn">
-        <div id="meaningEditor" class="box">
-          <div class="boxTitle">Editorul de sensuri</div>
-          <div class="boxContents">
-            <textarea id="editorInternalRep" rows="10" cols="10" disabled="disabled" placeholder="sensul definiției..."></textarea><br/>
-            <textarea id="editorInternalComment" rows="3" cols="10" disabled="disabled" placeholder="comentariu..."></textarea><br/>
-
-            <div class="editorLabel">surse:</div>
-            <div class="editorFieldContainer">
-              <select id="editorSources" multiple="multiple">
-                {foreach from=$sources item=s}
-                  <option value="{$s->id}">{$s->shortName}</option>
-                {/foreach}
-              </select>
-            </div>
-            <div style="clear: both"></div>
-
-            <div class="editorLabel">etichete:</div>
-            <div class="editorFieldContainer">
-              <select id="editorTags" multiple="multiple">
-                {foreach from=$meaningTags item=mt}
-                  <option value="{$mt->id}">{$mt->value}</option>
-                {/foreach}
-              </select>
-            </div>
-            <div style="clear: both"></div>
-      
-            <div class="editorLabel">sinonime:</div>
-            <div class="editorFieldContainer">
-              <input id="editorSynonyms" type="hidden"/>
-            </div>
-            <div style="clear: both"></div>
-      
-            <div class="editorLabel">antonime:</div>
-            <div class="editorFieldContainer">
-              <input id="editorAntonyms" type="hidden"/>
-            </div>
-            <div style="clear: both"></div>
-      
-            <input id="editMeaningAcceptButton" type="button" disabled="disabled" value="acceptă"/>
-            <input id="editMeaningCancelButton" type="button" disabled="disabled" value="renunță"/>
-          </div>
-        </div>
-      </div>
-      
-      <div id="definitionBox" class="dexEditRightColumn box">
-        <div class="boxTitle">Definiții pentru {include file="common/bits/lexemName.ihtml"}</div>
-        <div class="boxContents">
-          {foreach from=$searchResults item=row}
-            <div>
-              <div class="defInternalRep">
-                {$row->definition->internalRep|escape}
-              </div>
-              <div class="defHtmlRep">
-                {$row->definition->htmlRep}
-              </div>
-              <span class="defDetails">
-                sursa: {$row->source->shortName|escape}
-                | id: {$row->definition->id}
-                | <a href="{$wwwRoot}admin/definitionEdit.php?definitionId={$row->definition->id}" target="_blank">editează</a>
-                | <a href="#" class="toggleInternalHtmlLink">arată html</a>
-              </span>
-              {if $row->comment}
-                <div class="commentInternalRep">
-                  Comentariu: {$row->comment->contents} -
-                  <a href="{$wwwRoot}utilizator/{$row->commentAuthor->nick|escape:"url"}"
-                  >{$row->commentAuthor->nick|escape}</a>
-                </div>
-              {/if}
-            </div>
-          {/foreach}
-        </div>
-      </div>
-    </form>
-      
-    <div style="clear: both"></div>
-    
-    <script>
-      $(meaningEditorInit);
-    </script>
-  </body>
-</html>

Modified: wwwbase/admin/definitionEdit.php
==============================================================================
--- wwwbase/admin/definitionEdit.php	Mon Aug 19 11:40:12 2013	(r941)
+++ wwwbase/admin/definitionEdit.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -181,7 +181,7 @@
 SmartyWrap::assign('recentLinks', RecentLink::loadForUser());
 SmartyWrap::assign('sectionTitle', $isOCR ? "Adăugare definiție (OCR)" : "Editare definiție: {$definition->id}");
 SmartyWrap::addCss('jqueryui', 'select2');
-SmartyWrap::addJs('jquery', 'jqueryui', 'struct', 'select2');
+SmartyWrap::addJs('jquery', 'jqueryui', 'select2', 'select2Dev');
 SmartyWrap::displayAdminPage('admin/definitionEdit.ihtml');
 
 /**

Modified: wwwbase/admin/index.php
==============================================================================
--- wwwbase/admin/index.php	Mon Aug 19 11:40:12 2013	(r941)
+++ wwwbase/admin/index.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -13,6 +13,6 @@
 SmartyWrap::assign('models', $models);
 SmartyWrap::assign('sectionTitle', 'Pagina moderatorului');
 SmartyWrap::addCss('jqueryui', 'select2');
-SmartyWrap::addJs('jquery', 'jqueryui', 'select2', 'struct');
+SmartyWrap::addJs('jquery', 'jqueryui', 'select2', 'select2Dev');
 SmartyWrap::displayAdminPage('admin/index.ihtml');
 ?>

Modified: wwwbase/admin/lexemEdit.php
==============================================================================
--- wwwbase/admin/lexemEdit.php	Mon Aug 19 11:40:12 2013	(r941)
+++ wwwbase/admin/lexemEdit.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -1,13 +1,11 @@
 <?php
 require_once("../../phplib/util.php"); 
-
-util_assertModerator(PRIV_EDIT);
+util_assertModerator(PRIV_EDIT | PRIV_STRUCT);
 util_assertNotMirror();
-setlocale(LC_ALL, "ro_RO.utf8");
+
+handleLexemActions();
 
 $lexemId = util_getRequestParameter('lexemId');
-$dissociateDefinitionId = util_getRequestParameter('dissociateDefinitionId');
-$associateDefinitionId = util_getRequestParameter('associateDefinitionId');
 $lexemForm = util_getRequestParameter('lexemForm');
 $lexemDescription = util_getRequestParameter('lexemDescription');
 $lexemSourceIds = util_getRequestParameter('lexemSourceIds');
@@ -17,71 +15,19 @@
 $needsAccent = util_getBoolean('needsAccent');
 $modelType = util_getRequestParameter('modelType');
 $modelNumber = util_getRequestParameter('modelNumber');
-$similarModel = util_getRequestParameter('similarModel');
-$similarLexemId = util_getRequestParameter('similarLexemId');
 $restriction = util_getRequestCheckboxArray('restr', '');
-$miniDefTarget = util_getRequestParameter('miniDefTarget');
+$hyphenations = util_getRequestParameter('hyphenations');
+$pronunciations = util_getRequestParameter('pronunciations');
+$variantIds = util_getRequestCsv('variantIds');
+$variantOfId = util_getRequestParameter('variantOfId');
+$jsonMeanings = util_getRequestParameter('jsonMeanings');
 
 $refreshLexem = util_getRequestParameter('refreshLexem');
 $saveLexem = util_getRequestParameter('saveLexem');
-$cloneLexem = util_getRequestParameter('cloneLexem');
-$deleteLexem = util_getRequestParameter('deleteLexem');
-$createDefinition = util_getRequestParameter('createDefinition');
 
 $lexem = Lexem::get_by_id($lexemId);
 $original = Lexem::get_by_id($lexemId); // Keep a copy so we can test whether certain fields have changed
 
-/*************************** various actions other than the save/refresh buttons ***************************/
-
-if ($associateDefinitionId) {
-  LexemDefinitionMap::associate($lexem->id, $associateDefinitionId);
-  util_redirect("lexemEdit.php?lexemId={$lexem->id}");
-}
-
-if ($dissociateDefinitionId) {
-  LexemDefinitionMap::dissociate($lexem->id, $dissociateDefinitionId);
-  util_redirect("lexemEdit.php?lexemId={$lexem->id}");
-}
-
-if ($createDefinition) {
-  $def = Model::factory('Definition')->create();
-  $def->displayed = 0;
-  $def->userId = session_getUserId();
-  $def->sourceId = Source::get_by_shortName('Neoficial')->id;
-  $def->lexicon = $lexem->formNoAccent;
-  $def->internalRep =
-    '@' . mb_strtoupper(AdminStringUtil::internalize($lexem->form, false)) .
-    '@ v. @' . $miniDefTarget . '.@';
-  $def->htmlRep = AdminStringUtil::htmlize($def->internalRep, $def->sourceId);
-  $def->status = ST_ACTIVE;
-  $def->save();
-
-  LexemDefinitionMap::associate($lexem->id, $def->id);
-
-  util_redirect("lexemEdit.php?lexemId={$lexem->id}");
-  exit;
-}
-
-if ($deleteLexem) {
-  $homonyms = Model::factory('Lexem')->where('formNoAccent', $lexem->formNoAccent)->where_not_equal('id', $lexem->id)->find_many();
-  $lexem->delete();
-  SmartyWrap::assign('lexem', $lexem);
-  SmartyWrap::assign('homonyms', $homonyms);
-  SmartyWrap::assign('sectionTitle', 'Confirmare ștergere lexem');
-  SmartyWrap::displayAdminPage('admin/lexemDeleted.ihtml');
-  return;
-}
-
-if ($cloneLexem) {
-  $newLexem = _cloneLexem($lexem);
-  log_userLog("Cloned lexem {$lexem->id} ({$lexem->form}), new id is {$newLexem->id}");
-  util_redirect("lexemEdit.php?lexemId={$newLexem->id}");
-}
-
-if (!$similarModel && !$similarLexemId && !$refreshLexem && !$saveLexem) {
-  RecentLink::createOrUpdate("Lexem: {$lexem}");
-}
-
 if ($refreshLexem || $saveLexem) {
   // Populate lexem fields from request parameters.
   $lexem->form = AdminStringUtil::formatLexem($lexemForm);
@@ -97,29 +43,18 @@
   }
   $lexem->isLoc = $lexemIsLoc;
   $lexem->noAccent = !$needsAccent;
-
-  // The new model type, number and restrictions can come from three sources:
-  // $similarModel, $similarLexemId or ($modelType, $modelNumber,
-  // $restriction) directly
-  if ($similarModel !== null) {
-    $parts = FlexModel::splitName($similarModel);
-    $lexem->modelType = $parts[0];
-    $lexem->modelNumber = $parts[1];
-    $lexem->restriction = $parts[2];
-  } else if ($similarLexemId) {
-    $similarLexem = Lexem::get_by_id($similarLexemId);
-    $lexem->modelType = $similarLexem->modelType;
-    $lexem->modelNumber = $similarLexem->modelNumber;
-    $lexem->restriction = $similarLexem->restriction;
-  } else if ($modelType !== null) {
-    $lexem->modelType = $modelType;
-    $lexem->modelNumber = $modelNumber;
-    $lexem->restriction = $restriction;
-  }
-
+  $lexem->modelType = $modelType;
+  $lexem->modelNumber = $modelNumber;
+  $lexem->restriction = $restriction;
+  $lexem->hyphenations = $hyphenations;
+  $lexem->pronunciations = $pronunciations;
+  $lexem->variantOfId = $variantOfId ? $variantOfId : null;
+  $variantOf = Lexem::get_by_id($lexem->variantOfId);
+  $meanings = json_decode($jsonMeanings);
   $ifs = $lexem->generateParadigm();
 
-  if (validate($lexem, $ifs)) {
+  if (validate($lexem, $ifs, $variantOf, $variantIds, $meanings)) {
+    // Case 1: Validation passed
     if ($saveLexem) {
       if ($original->modelType == 'VT' && $lexem->modelType != 'VT') {
         $lexem->deleteParticiple($original->modelNumber);
@@ -129,27 +64,51 @@
         $lexem->deleteLongInfinitive();
       }
       $lexem->save();
+      Meaning::saveTree($meanings, $lexem);
       LexemSource::updateList(array('lexemId' => $lexem->id), 'sourceId', $lexemSourceIds);
+      $lexem->updateVariants($variantIds);
       $lexem->regenerateParadigm(); // This generates AND saves the paradigm
 
       log_userLog("Edited lexem {$lexem->id} ({$lexem->form})");
       util_redirect("lexemEdit.php?lexemId={$lexem->id}");
     }
+  } else {
+    // Case 2: Validation failed
   }
+  // Case 1-2: Page was submitted
+    SmartyWrap::assign('variantIds', $variantIds);
+    SmartyWrap::assign('meanings', Meaning::convertTree($meanings));
 } else {
+  // Case 3: First time loading this page
   $ifs = $lexem->generateParadigm();
   $lexemSourceIds = LexemSource::getForLexem($lexem);
+  SmartyWrap::assign('variantIds', $lexem->getVariantIds());
+  SmartyWrap::assign('meanings', Meaning::loadTree($lexem->id));
 }
 
 $definitions = Definition::loadByLexemId($lexem->id);
+foreach ($definitions as $def) {
+  // $def->internalRep = AdminStringUtil::expandAbbreviations($def->internalRep, $def->sourceId);
+}
 $searchResults = SearchResult::mapDefinitionArray($definitions);
 $definitionLexem = mb_strtoupper(AdminStringUtil::internalize($lexem->form, false));
+$meaningTags = Model::factory('MeaningTag')->order_by_asc('value')->find_many();
 
 if (is_array($ifs)) {
   $ifMap = InflectedForm::mapByInflectionRank($ifs);
   SmartyWrap::assign('ifMap', $ifMap);
 }
 
+$canEdit = array(
+  'general' => util_isModerator(PRIV_EDIT),
+  'description' => !$lexem->isLoc || util_isModerator(PRIV_LOC),
+  'form' => !$lexem->isLoc || util_isModerator(PRIV_LOC),
+  'isLoc' => util_isModerator(PRIV_LOC),
+  'paradigm' => util_isModerator(PRIV_LOC),
+  'sources' => util_isModerator(PRIV_LOC | PRIV_EDIT),
+  'tags' => util_isModerator(PRIV_LOC | PRIV_EDIT),
+);
+
 SmartyWrap::assign('lexem', $lexem);
 SmartyWrap::assign('lexemSourceIdMap', util_makeSet($lexemSourceIds));
 SmartyWrap::assign('searchResults', $searchResults);
@@ -161,18 +120,19 @@
 SmartyWrap::assign('restrU', FlexStringUtil::contains($lexem->restriction, 'U'));
 SmartyWrap::assign('restrI', FlexStringUtil::contains($lexem->restriction, 'I'));
 SmartyWrap::assign('restrT', FlexStringUtil::contains($lexem->restriction, 'T'));
+SmartyWrap::assign('meaningTags', $meaningTags);
 SmartyWrap::assign('modelTypes', Model::factory('ModelType')->order_by_asc('code')->find_many());
 SmartyWrap::assign('models', FlexModel::loadByType($lexem->modelType));
-SmartyWrap::assign('canEditForm', !$lexem->isLoc || util_isModerator(PRIV_LOC));
+SmartyWrap::assign('canEdit', $canEdit);
 SmartyWrap::assign('allStatuses', util_getAllStatuses());
-SmartyWrap::addCss('jqueryui', 'paradigm', 'select2');
-SmartyWrap::addJs('jquery', 'jqueryui', 'struct', 'select2');
+SmartyWrap::addCss('easyui', 'jqueryui', 'paradigm', 'select2', 'lexemEdit');
+SmartyWrap::addJs('easyui', 'jqueryui', 'select2', 'select2Dev', 'lexemEdit');
 SmartyWrap::assign('sectionTitle', "Editare lexem: {$lexem->form} {$lexem->modelType}{$lexem->modelNumber}{$lexem->restriction}");
 SmartyWrap::displayAdminPage('admin/lexemEdit.ihtml');
 
 /**************************************************************************/
 
-function validate($lexem, $ifs) {
+function validate($lexem, $ifs, $variantOf, $variantIds, $meanings) {
   if (!$lexem->form) {
     FlashMessage::add('Forma nu poate fi vidă.');
   }
@@ -218,6 +178,35 @@
                               htmlentities($infl->description), $lexem->modelType, $lexem->modelNumber));
   }
 
+  if ($variantOf && !empty($meanings)) {
+    FlashMessage::add("Acest lexem este o variantă a lui {$variantOf} și nu poate avea el însuși sensuri.");
+  }
+  if ($variantOf && !empty($variantIds)) {
+    FlashMessage::add("Acest lexem este o variantă a lui {$variantOf} și nu poate avea el însuși variante.");
+  }
+  if ($variantOf && ($variantOf->id == $lexem->id)) {
+    FlashMessage::add("Lexemul nu poate fi variantă a lui însuși.");
+  }
+
+  foreach ($variantIds as $variantId) {
+    $variant = Lexem::get_by_id($variantId);
+    if ($variant->id == $lexem->id) {
+      FlashMessage::add('Lexemul nu poate fi variantă a lui însuși.');
+    }
+    if ($variant->variantOfId && $variant->variantOfId != $lexem->id) {
+      $other = Lexem::get_by_id($variant->variantOfId);
+      FlashMessage::add("\"{$variant}\" este deja marcat ca variantă a lui \"{$other}\".");
+    }
+    $variantVariantCount = Model::factory('Lexem')->where('variantOfId', $variant->id)->count();
+    if ($variantVariantCount) {
+      FlashMessage::add("\"{$variant}\" are deja propriile lui variante.");
+    }
+    $variantMeaningCount = Model::factory('Meaning')->where('lexemId', $variant->id)->count();
+    if ($variantMeaningCount) {
+      FlashMessage::add("\"{$variant}\" are deja propriile lui sensuri.");
+    }
+  }
+
   return FlashMessage::getMessage() == null;
 }
 
@@ -260,4 +249,73 @@
   return $clone;
 }
 
+/* This page handles a lot of actions. Move the minor ones here so they don't clutter the preview/save actions,
+   which are hairy enough by themselves. */
+function handleLexemActions() {
+  $lexemId = util_getRequestParameter('lexemId');
+  $lexem = Lexem::get_by_id($lexemId);
+
+  $associateDefinitionId = util_getRequestParameter('associateDefinitionId');
+  if ($associateDefinitionId) {
+    LexemDefinitionMap::associate($lexem->id, $associateDefinitionId);
+    util_redirect("lexemEdit.php?lexemId={$lexem->id}");
+  }
+
+  $dissociateDefinitionId = util_getRequestParameter('dissociateDefinitionId');
+  if ($dissociateDefinitionId) {
+    LexemDefinitionMap::dissociate($lexem->id, $dissociateDefinitionId);
+    util_redirect("lexemEdit.php?lexemId={$lexem->id}");
+  }
+
+  $createDefinition = util_getRequestParameter('createDefinition');
+  $miniDefTarget = util_getRequestParameter('miniDefTarget');
+  if ($createDefinition) {
+    $def = Model::factory('Definition')->create();
+    $def->displayed = 0;
+    $def->userId = session_getUserId();
+    $def->sourceId = Source::get_by_shortName('Neoficial')->id;
+    $def->lexicon = $lexem->formNoAccent;
+    $def->internalRep =
+      '@' . mb_strtoupper(AdminStringUtil::internalize($lexem->form, false)) .
+      '@ v. @' . $miniDefTarget . '.@';
+    $def->htmlRep = AdminStringUtil::htmlize($def->internalRep, $def->sourceId);
+    $def->status = ST_ACTIVE;
+    $def->save();
+
+    LexemDefinitionMap::associate($lexem->id, $def->id);
+
+    util_redirect("lexemEdit.php?lexemId={$lexem->id}");
+  }
+
+  $deleteLexem = util_getRequestParameter('deleteLexem');
+  if ($deleteLexem) {
+    $homonyms = Model::factory('Lexem')->where('formNoAccent', $lexem->formNoAccent)->where_not_equal('id', $lexem->id)->find_many();
+    $lexem->delete();
+    SmartyWrap::assign('lexem', $lexem);
+    SmartyWrap::assign('homonyms', $homonyms);
+    SmartyWrap::assign('sectionTitle', 'Confirmare ștergere lexem');
+    SmartyWrap::displayAdminPage('admin/lexemDeleted.ihtml');
+    exit;
+  }
+
+  $cloneLexem = util_getRequestParameter('cloneLexem');
+  if ($cloneLexem) {
+    $newLexem = _cloneLexem($lexem);
+    log_userLog("Cloned lexem {$lexem->id} ({$lexem->form}), new id is {$newLexem->id}");
+    util_redirect("lexemEdit.php?lexemId={$newLexem->id}");
+  }
+
+  $mergeLexem = util_getRequestParameter('mergeLexem');
+  $mergeLexemId = util_getRequestParameter('mergeLexemId');
+  if ($mergeLexem) {
+    $other = Lexem::get_by_id($mergeLexemId);
+    $defs = Definition::loadByLexemId($lexem->id);
+    foreach ($defs as $def) {
+      LexemDefinitionMap::associate($other->id, $def->id);
+    }
+    $lexem->delete();
+    util_redirect("lexemEdit.php?lexemId={$other->id}");
+  }
+}
+
 ?>

Deleted: wwwbase/admin/lexemMerge.php
==============================================================================
--- wwwbase/admin/lexemMerge.php	Mon Aug 19 16:28:41 2013	(r941)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,20 +0,0 @@
-<?php
-require_once("../../phplib/util.php"); 
-util_assertModerator(PRIV_EDIT);
-util_assertNotMirror();
-
-$id1 = util_getRequestParameter('id1');
-$id2 = util_getRequestParameter('id2');
-
-$l1 = Lexem::get_by_id($id1);
-$l2 = Lexem::get_by_id($id2);
-
-$defs = Definition::loadByLexemId($l1->id);
-foreach ($defs as $def) {
-  LexemDefinitionMap::associate($l2->id, $def->id);
-}
-
-$l1->delete();
-util_redirect("lexemEdit.php?lexemId={$l2->id}");
-
-?>

Added: wwwbase/ajax/getModelByLexemId.php
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ wwwbase/ajax/getModelByLexemId.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -0,0 +1,10 @@
+<?php
+require_once("../../phplib/util.php");
+
+$id = util_getRequestParameter('id');
+$l = Lexem::get_by_id($id);
+print json_encode(array('modelType' => $l->modelType,
+                        'modelNumber' => $l->modelNumber,
+                        'restriction' => $l->restriction));
+
+?>

Modified: wwwbase/contribuie.php
==============================================================================
--- wwwbase/contribuie.php	Mon Aug 19 11:40:12 2013	(r941)
+++ wwwbase/contribuie.php	Mon Aug 19 16:28:41 2013	(r942)
@@ -66,7 +66,7 @@
 SmartyWrap::assign('page_title', 'Contribuie cu definiții');
 SmartyWrap::assign('suggestNoBanner', true);
 SmartyWrap::addCss('jqueryui', 'select2');
-SmartyWrap::addJs('jqueryui', 'struct', 'select2');
+SmartyWrap::addJs('jqueryui', 'select2', 'select2Dev');
 SmartyWrap::displayCommonPageWithSkin('contribuie.ihtml');
 
 /**************************************************************************/

Added: wwwbase/img/icons/arrow_refresh.png
==============================================================================
Binary file. No diff available.

Added: wwwbase/img/icons/disk.png
==============================================================================
Binary file. No diff available.

Added: wwwbase/img/icons/page_white_copy.png
==============================================================================
Binary file. No diff available.

Modified: wwwbase/js/flex.js
==============================================================================
--- wwwbase/js/flex.js	Mon Aug 19 11:40:12 2013	(r941)
+++ wwwbase/js/flex.js	Mon Aug 19 16:28:41 2013	(r942)
@@ -7,12 +7,15 @@
   return false;
 }
 
-/** listAllOption -- whether to prepend an option for "list all" **/
-function updateModelList(listAllOption) {
+/**
+ * listAllOption -- whether to prepend an option for "list all"
+ * selectedOption -- value to select once loading is complete (optional)
+**/
+function updateModelList(listAllOption, selectedOption) {
   $.get(wwwRoot + 'ajax/getModelsForLocVersionModelType.php',
         { locVersion: $('#locVersionListId').val(), modelType: $('#modelTypeListId').val() },
         null, 'json')
-    .done(function(data) { populateModelList(data, listAllOption); })
+    .done(function(data) { populateModelList(data, listAllOption, selectedOption); })
     .fail('Nu pot descărca lista de modele.');
   return false;
 }
@@ -30,7 +33,7 @@
   updateModelList(true);
 }
 
-function populateModelList(data, listAllOption) {
+function populateModelList(data, listAllOption, selectedOption) {
   var select = $('#modelListId');
   select.empty();
 
@@ -41,6 +44,9 @@
     var display = dict.number + ' (' + dict.exponent + ')';
     select.append($("<option></option>").attr("value", dict.number).text(display));
   });
+  if (selectedOption) {
+    select.val(selectedOption);
+  }
 }
 
 function blUpdateParadigmVisibility(radioButton) {

Copied and modified: wwwbase/js/lexemEdit.js (from r928, wwwbase/js/struct.js)
==============================================================================
--- wwwbase/js/struct.js	Wed Aug 14 17:21:15 2013	(r928, copy source)
+++ wwwbase/js/lexemEdit.js	Mon Aug 19 16:28:41 2013	(r942)
@@ -1,13 +1,6 @@
 struct_anyChanges = false;
 
-struct_lexemAjax = {
-  data: function(term, page) { return { term: term }; },
-  dataType: 'json',
-  results: function(data, page) { return data; }, 
-  url: wwwRoot + 'ajax/getLexems.php',
-};
-
-function meaningEditorInit() {
+function lexemEditInit() {
   $('#meaningTree').tree({
     animate: true,
     dnd: true,
@@ -59,7 +52,7 @@
     initSelection: select2InitSelectionAjax,
     minimumInputLength: 1,
     multiple: true,
-    width: '217px',
+    width: '333px',
   });
 
   $('#variantOfId').select2({
@@ -68,121 +61,38 @@
     initSelection: select2InitSelectionAjaxSingle,
     minimumInputLength: 1,
     placeholder: 'alegeți un lexem (opțional)',
-    width: '217px',
+    width: '333px',
+  });
+
+  $('#associateDefinitionId').select2({
+    ajax: struct_definitionAjax,
+    formatResult: function(item) {
+      return item.text + ' (' + item.source + ') [' + item.id + ']';
+    },
+    minimumInputLength: 1,
+    placeholder: 'asociază o definiție',
+    width: '400px',
   });
 
   $('#editMeaningAcceptButton').click(acceptMeaningEdit);
   $('#editMeaningCancelButton').click(endMeaningEdit);
-  $('#dexEditSaveButton').click(dexEditSaveEverything);
+  $('.lexemEditSaveButton').click(saveEverything);
   $('.toggleInternalHtmlLink').click(toggleInternalHtmlClick);
   $('.boxTitle').click(boxTitleClick);
 
-  $(window).resize(adjustDefinitionDivHeight);
-  adjustDefinitionDivHeight();
-}
-
-function structIndexInit() {
-  $('#structLexemFinder').select2({
-    ajax: struct_lexemAjax,
-    minimumInputLength: 1,
-    placeholder: 'caută un lexem...',
-    width: '300px',
-  });
-}
-
-function definitionEditInit() {
-  $('#lexemIds').select2({
-    ajax: struct_lexemAjax,
-    escapeMarkup: function(m) { return m; },
-    initSelection: select2InitSelectionAjax,
-    formatSelection: formatLexemWithEditLink,
-    minimumInputLength: 1,
-    multiple: true,
-    width: '600px',
-  });
-}
-
-function lexemEditInit() {
   $('#lexemSourceIds').select2({
+    placeholder: 'surse care atestă flexiunea',
     width: '333px',
   });
   $('#similarLexemId').select2({
     ajax: struct_lexemAjax,
     minimumInputLength: 1,
+    placeholder: 'sau indicați un lexem similar',
     width: '300px',
-  });
-}
-
-function adminIndexInit() {
-  $('#lexemId').select2({
-    ajax: struct_lexemAjax,
-    minimumInputLength: 1,
-    width: '300px',
-  }).on('change', function(e) {
-    $(this).parents('form').submit();
-  });
-}
+  }).on('change', similarLexemChange);
 
-function contribInit() {
-  $('#lexemIds').select2({
-    ajax: struct_lexemAjax,
-    createSearchChoice: allowNewLexems,
-    formatInputTooShort: function () { return 'Vă rugăm să introduceți minim un caracter'; },
-    formatSearching: function () { return 'Căutare...'; },
-    initSelection: select2InitSelectionAjax,
-    minimumInputLength: 1,
-    multiple: true,
-    tokenSeparators: [',', '\\', '@'],
-    width: '600px',
-  });
-}
-
-function formatLexemWithEditLink(lexem) {
-  return lexem.text + ' <a class="select2Edit" href="lexemEdit.php?lexemId=' + lexem.id + '"> </a>';
-}
-
-function allowNewLexems(term, data) {
-  if (!data.length || data[0].text != term) {
-    return { id: '@' + term, text: term + ' (cuvânt nou)'};
-  }
-};
-
-function select2InitSelection(element, callback) {
-  var data = [];
-  $(element.val().split(',')).each(function () {
-    data.push({ id: this, text: this });
-  });
-  callback(data);
-}
-
-function select2InitSelectionAjaxSingle(element, callback) {
-  var id = $(element).val();
-  if (id) {
-    $.ajax(wwwRoot + 'ajax/getLexemById.php?id=' + id, {dataType: 'json'})
-      .done(function(data) {
-        callback({ id: id, text: data });
-      });
-  }
-}
-
-function select2InitSelectionAjax(element, callback) {
-  var data = [];
-
-  $(element.val().split(',')).each(function (index, lexemId) {
-    $.ajax({
-      url: wwwRoot + 'ajax/getLexemById.php?id=' + this,
-      dataType: 'json',
-      success: function(displayValue) {
-        if (displayValue) {
-          data.push({ id: lexemId, text: displayValue });
-        } else {
-          data.push({ id: lexemId, text: lexemId.substr(1) + ' (cuvânt nou)' });
-        }
-      },
-      async: false,
-    });
-  });
-  callback(data);
+  $('.mergeLexem').click(mergeLexemButtonClick);
+  $('.similarLink').click(similarLinkClick);
 }
 
 function addMeaning() {
@@ -220,8 +130,6 @@
   // Now find and select it
   var node = $('#meaningTree').tree('find', randomId);
   $('#meaningTree').tree('select', node.target);
-
-  adjustDefinitionDivHeight();
 }
 
 function deleteMeaning() {
@@ -235,7 +143,6 @@
       $('#meaningTree').tree('remove', node.target);
     }
   }
-  adjustDefinitionDivHeight();
 }
 
 function meaningEditorUnchanged(node) {
@@ -342,7 +249,7 @@
 }
 
 // Iterate a meaning tree node recursively and collect meaning-related fields
-function dexEditTreeWalk(node, results, level) {
+function meaningTreeWalk(node, results, level) {
   var jqNode = $(node.target);
   results.push({ 'id': jqNode.find('span.id').text(),
                  'level' : level,
@@ -355,18 +262,18 @@
                });
   var children = $('#meaningTree').tree('getChildren', node.target);
   for (var i = 0; i < children.length; i++) {
-    dexEditTreeWalk(children[i], results, level + 1);
+    meaningTreeWalk(children[i], results, level + 1);
   }
 }
 
-function dexEditSaveEverything() {
+function saveEverything() {
   if (struct_anyChanges) {
     acceptMeaningEdit();
   }
   var results = new Array();
   var roots = $('#meaningTree').tree('getRoots');
   for (var i = 0; i < roots.length; i++) {
-    dexEditTreeWalk(roots[i], results, 0);
+    meaningTreeWalk(roots[i], results, 0);
   }
   $('input[name=jsonMeanings]').val(JSON.stringify(results));
   $('#meaningForm').submit();
@@ -384,8 +291,30 @@
   $(this).next('.boxContents').slideToggle();
 }
 
-function adjustDefinitionDivHeight() {
-  var windowHeight = $(window).height();
-  var boxTop = $('#definitionBox .boxContents').position().top;
-  $('#definitionBox .boxContents').height(windowHeight - boxTop - 25);
+function mergeLexemButtonClick() {
+  var id = $(this).attr('id').split('_')[1];
+  $('input[name=mergeLexemId]').val(id);
+}
+
+/* Set the model type, model number and restriction values */
+function similarLinkClick() {
+  var parts = $(this).attr('id').split('_');
+  updateParadigm(parts[1], parts[2], parts[3]);
+  return false;
+}
+
+function similarLexemChange(e) {
+  var url = wwwRoot + 'ajax/getModelByLexemId.php?id=' + e.val;
+  $.get(url, null, null, 'json')
+    .done(function(data) {
+      updateParadigm(data.modelType, data.modelNumber, data.restriction);
+    });
+}
+
+function updateParadigm(modelType, modelNumber, restriction) {
+  $('#modelTypeListId').val(modelType); // Does not trigger the onchange event
+  updateModelList(false, modelNumber);
+  $('input[name=restr\\[\\]]').each(function() {
+    $(this).prop('checked', restriction.indexOf($(this).val()) != -1);
+  });
 }

Added: wwwbase/js/select2Dev.js
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ wwwbase/js/select2Dev.js	Mon Aug 19 16:28:41 2013	(r942)
@@ -0,0 +1,108 @@
+/* Custom code built on top of select2.min.js */
+
+struct_lexemAjax = {
+  data: function(term, page) { return { term: term }; },
+  dataType: 'json',
+  results: function(data, page) { return data; }, 
+  url: wwwRoot + 'ajax/getLexems.php',
+};
+
+struct_definitionAjax = {
+  data: function(term, page) { return { term: term }; },
+  dataType: 'json',
+  results: function(data, page) { return data; }, 
+  url: wwwRoot + 'ajax/wotdGetDefinitions.php',
+};
+
+function contribInit() {
+  $('#lexemIds').select2({
+    ajax: struct_lexemAjax,
+    createSearchChoice: allowNewLexems,
+    formatInputTooShort: function () { return 'Vă rugăm să introduceți minim un caracter'; },
+    formatSearching: function () { return 'Căutare...'; },
+    initSelection: select2InitSelectionAjax,
+    minimumInputLength: 1,
+    multiple: true,
+    tokenSeparators: [',', '\\', '@'],
+    width: '600px',
+  });
+}
+
+function adminIndexInit() {
+  $('#lexemId').select2({
+    ajax: struct_lexemAjax,
+    minimumInputLength: 1,
+    width: '300px',
+  }).on('change', function(e) {
+    $(this).parents('form').submit();
+  });
+}
+
+function structIndexInit() {
+  $('#structLexemFinder').select2({
+    ajax: struct_lexemAjax,
+    minimumInputLength: 1,
+    placeholder: 'caută un lexem...',
+    width: '300px',
+  });
+}
+
+function definitionEditInit() {
+  $('#lexemIds').select2({
+    ajax: struct_lexemAjax,
+    escapeMarkup: function(m) { return m; },
+    initSelection: select2InitSelectionAjax,
+    formatSelection: formatLexemWithEditLink,
+    minimumInputLength: 1,
+    multiple: true,
+    width: '600px',
+  });
+}
+
+function formatLexemWithEditLink(lexem) {
+  return lexem.text + ' <a class="select2Edit" href="lexemEdit.php?lexemId=' + lexem.id + '"> </a>';
+}
+
+function allowNewLexems(term, data) {
+  if (!data.length || data[0].text != term) {
+    return { id: '@' + term, text: term + ' (cuvânt nou)'};
+  }
+};
+
+function select2InitSelection(element, callback) {
+  var data = [];
+  $(element.val().split(',')).each(function () {
+    data.push({ id: this, text: this });
+  });
+  callback(data);
+}
+
+function select2InitSelectionAjaxSingle(element, callback) {
+  var id = $(element).val();
+  if (id) {
+    $.ajax(wwwRoot + 'ajax/getLexemById.php?id=' + id, {dataType: 'json'})
+      .done(function(data) {
+        callback({ id: id, text: data });
+      });
+  }
+}
+
+function select2InitSelectionAjax(element, callback) {
+  var data = [];
+
+  $(element.val().split(',')).each(function (index, lexemId) {
+    $.ajax({
+      url: wwwRoot + 'ajax/getLexemById.php?id=' + this,
+      dataType: 'json',
+      success: function(displayValue) {
+        if (displayValue) {
+          data.push({ id: lexemId, text: displayValue });
+        } else {
+          data.push({ id: lexemId, text: lexemId.substr(1) + ' (cuvânt nou)' });
+        }
+      },
+      async: false,
+    });
+  });
+  callback(data);
+}

Deleted: wwwbase/js/struct.js
==============================================================================
--- wwwbase/js/struct.js	Mon Aug 19 16:28:41 2013	(r941)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,391 +0,0 @@
-struct_anyChanges = false;
-
-struct_lexemAjax = {
-  data: function(term, page) { return { term: term }; },
-  dataType: 'json',
-  results: function(data, page) { return data; }, 
-  url: wwwRoot + 'ajax/getLexems.php',
-};
-
-function meaningEditorInit() {
-  $('#meaningTree').tree({
-    animate: true,
-    dnd: true,
-    lines: true,
-    onBeforeSelect: meaningEditorUnchanged,
-    onSelect: beginMeaningEdit,
-  });
-  $('#addMeaningButton').click(addMeaning);
-  $('#addSubmeaningButton').click(addSubmeaning);
-  $('#deleteMeaningButton').click(deleteMeaning);
-
-  $('#editorSources').select2({
-    placeholder: 'adaugă o sursă...',
-    width: '315px',
-  });
-  $('#editorSources').select2('enable', false);
-
-  $('#editorTags').select2({
-    placeholder: 'adaugă o etichetă...',
-    width: '315px',
-  });
-  $('#editorTags').select2('enable', false);
-
-  $('#editorSynonyms').select2({
-    ajax: struct_lexemAjax,
-    initSelection: select2InitSelection,
-    minimumInputLength: 1,
-    multiple: true,
-    placeholder: 'adaugă un sinonim...',
-    width: '315px',
-  });
-  $('#editorSynonyms').select2('enable', false);
-
-  $('#editorAntonyms').select2({
-    ajax: struct_lexemAjax,
-    initSelection: select2InitSelection,
-    minimumInputLength: 1,
-    multiple: true,
-    placeholder: 'adaugă un antonim...',
-    width: '315px',
-  });
-  $('#editorAntonyms').select2('enable', false);
-
-  $('#editorInternalRep, #editorInternalComment, #editorSources, #editorTags, #editorSynonyms, #editorAntonyms').bind(
-    'change keyup input paste', function() { struct_anyChanges = true; });
-
-  $('#variantIds').select2({
-    ajax: struct_lexemAjax,
-    initSelection: select2InitSelectionAjax,
-    minimumInputLength: 1,
-    multiple: true,
-    width: '217px',
-  });
-
-  $('#variantOfId').select2({
-    ajax: struct_lexemAjax,
-    allowClear: true,
-    initSelection: select2InitSelectionAjaxSingle,
-    minimumInputLength: 1,
-    placeholder: 'alegeți un lexem (opțional)',
-    width: '217px',
-  });
-
-  $('#editMeaningAcceptButton').click(acceptMeaningEdit);
-  $('#editMeaningCancelButton').click(endMeaningEdit);
-  $('#dexEditSaveButton').click(dexEditSaveEverything);
-  $('.toggleInternalHtmlLink').click(toggleInternalHtmlClick);
-  $('.boxTitle').click(boxTitleClick);
-
-  $(window).resize(adjustDefinitionDivHeight);
-  adjustDefinitionDivHeight();
-}
-
-function structIndexInit() {
-  $('#structLexemFinder').select2({
-    ajax: struct_lexemAjax,
-    minimumInputLength: 1,
-    placeholder: 'caută un lexem...',
-    width: '300px',
-  });
-}
-
-function definitionEditInit() {
-  $('#lexemIds').select2({
-    ajax: struct_lexemAjax,
-    escapeMarkup: function(m) { return m; },
-    initSelection: select2InitSelectionAjax,
-    formatSelection: formatLexemWithEditLink,
-    minimumInputLength: 1,
-    multiple: true,
-    width: '600px',
-  });
-}
-
-function lexemEditInit() {
-  $('#lexemSourceIds').select2({
-    width: '333px',
-  });
-  $('#similarLexemId').select2({
-    ajax: struct_lexemAjax,
-    minimumInputLength: 1,
-    width: '300px',
-  });
-}
-
-function adminIndexInit() {
-  $('#lexemId').select2({
-    ajax: struct_lexemAjax,
-    minimumInputLength: 1,
-    width: '300px',
-  }).on('change', function(e) {
-    $(this).parents('form').submit();
-  });
-}
-
-function contribInit() {
-  $('#lexemIds').select2({
-    ajax: struct_lexemAjax,
-    createSearchChoice: allowNewLexems,
-    formatInputTooShort: function () { return 'Vă rugăm să introduceți minim un caracter'; },
-    formatSearching: function () { return 'Căutare...'; },
-    initSelection: select2InitSelectionAjax,
-    minimumInputLength: 1,
-    multiple: true,
-    tokenSeparators: [',', '\\', '@'],
-    width: '600px',
-  });
-}
-
-function formatLexemWithEditLink(lexem) {
-  return lexem.text + ' <a class="select2Edit" href="lexemEdit.php?lexemId=' + lexem.id + '"> </a>';
-}
-
-function allowNewLexems(term, data) {
-  if (!data.length || data[0].text != term) {
-    return { id: '@' + term, text: term + ' (cuvânt nou)'};
-  }
-};
-
-function select2InitSelection(element, callback) {
-  var data = [];
-  $(element.val().split(',')).each(function () {
-    data.push({ id: this, text: this });
-  });
-  callback(data);
-}
-
-function select2InitSelectionAjaxSingle(element, callback) {
-  var id = $(element).val();
-  if (id) {
-    $.ajax(wwwRoot + 'ajax/getLexemById.php?id=' + id, {dataType: 'json'})
-      .done(function(data) {
-        callback({ id: id, text: data });
-      });
-  }
-}
-
-function select2InitSelectionAjax(element, callback) {
-  var data = [];
-
-  $(element.val().split(',')).each(function (index, lexemId) {
-    $.ajax({
-      url: wwwRoot + 'ajax/getLexemById.php?id=' + this,
-      dataType: 'json',
-      success: function(displayValue) {
-        if (displayValue) {
-          data.push({ id: lexemId, text: displayValue });
-        } else {
-          data.push({ id: lexemId, text: lexemId.substr(1) + ' (cuvânt nou)' });
-        }
-      },
-      async: false,
-    });
-  });
-  callback(data);
-}
-
-function addMeaning() {
-  if (!meaningEditorUnchanged()) {
-    return false;
-  }
-  var node = $('#meaningTree').tree('getSelected');
-  var parent;
-  if (node) {
-    var parentNode = $('#meaningTree').tree('getParent', node.target);
-    parent = parentNode ? parentNode.target : null;
-  } else {
-    parent = null;
-  }
-  appendAndSelectNode(parent);
-}
-
-function addSubmeaning() {
-  if (!meaningEditorUnchanged()) {
-    return false;
-  }
-  var node = $('#meaningTree').tree('getSelected');
-  if (node) {
-    appendAndSelectNode(node.target);
-  }
-}
-
-function appendAndSelectNode(target) {
-  var randomId = Math.floor(Math.random() * 1000000000) + 1;
-  $('#meaningTree').tree('append', {
-    parent: target,
-    data: [{ 'id' : randomId, 'text': $('#stemNode').html() }]
-  });
-
-  // Now find and select it
-  var node = $('#meaningTree').tree('find', randomId);
-  $('#meaningTree').tree('select', node.target);
-
-  adjustDefinitionDivHeight();
-}
-
-function deleteMeaning() {
-  if (!meaningEditorUnchanged()) {
-    return false;
-  }
-  var node = $('#meaningTree').tree('getSelected');
-  if (node) {
-    var numChildren = $('#meaningTree').tree('getChildren', node.target).length;
-    if (!numChildren || confirm('Confirmați ștergerea sensului și a tuturor subsensurilor?')) {
-      $('#meaningTree').tree('remove', node.target);
-    }
-  }
-  adjustDefinitionDivHeight();
-}
-
-function meaningEditorUnchanged(node) {
-  return !struct_anyChanges || confirm('Aveți deja un sens în curs de modificare. Confirmați renunțarea la modificări?');
-}
-
-function beginMeaningEdit() {
-  struct_anyChanges = false;
-  var domNode = $('#meaningTree').tree('getSelected').target;
-  var node = $(domNode);
-  $('#editorInternalRep, #editorInternalComment, #editMeaningAcceptButton, #editMeaningCancelButton').removeAttr('disabled');
-  $('#editorInternalRep').val(node.find('span.internalRep').text());
-  $('#editorInternalComment').val(node.find('span.internalComment').text());
-  $('#editorSources').select2('val', node.find('span.sourceIds').text().split(','));
-  $('#editorSources').select2('enable');
-  $('#editorTags').select2('val', node.find('span.meaningTagIds').text().split(','));
-  $('#editorTags').select2('enable');
-
-  var synonymIds = node.find('span.synonymIds').text().split(',');
-  var synonyms = node.find('.synonyms .tag');
-  $('#editorSynonyms').select2('data', synonyms.map(function(index) {
-    return { id: synonymIds[index], text: $(this).text() };
-  }));
-  $('#editorSynonyms').select2('enable');
-
-  var antonymIds = node.find('span.antonymIds').text().split(',');
-  var antonyms = node.find('.antonyms .tag');
-  $('#editorAntonyms').select2('data', antonyms.map(function(index) {
-    return { id: antonymIds[index], text: $(this).text() };
-  }));
-  $('#editorAntonyms').select2('enable');
-}
-
-function acceptMeaningEdit() {
-  struct_anyChanges = false;
-  var domNode = $('#meaningTree').tree('getSelected').target;
-  var node = $(domNode);
-
-  // Update internal and HTML definition
-  var internalRep = $('#editorInternalRep').val();
-  node.find('span.internalRep').text(internalRep);
-  $.post(wwwRoot + 'ajax/htmlize.php',
-         { internalRep: internalRep, sourceId: 0 },
-         function(data) { node.find('span.htmlRep').html(data); },
-        'text');
-
-  // Update internal and HTML comment
-  var internalComment = $('#editorInternalComment').val();
-  node.find('span.internalComment').text(internalComment);
-  $.post(wwwRoot + 'ajax/htmlize.php',
-         { internalRep: internalComment, sourceId: 0 },
-         function(data) { node.find('span.htmlComment').html(data); },
-        'text');
-
-  // Update sources and sourceIds
-  var sourceIds = $('#editorSources').val();
-  node.find('span.sourceIds').text(sourceIds ? sourceIds.join(',') : '');
-  node.find('span.sources').text('');
-  $('#editorSources option:selected').each(function() {
-    node.find('span.sources').append('<span class="tag">' + $(this).text() + '</span>');
-  });
-
-  // Update meaning tags and meaningIds
-  var meaningTagIds = $('#editorTags').val();
-  node.find('span.meaningTagIds').text(meaningTagIds ? meaningTagIds.join(',') : '');
-  node.find('span.meaningTags').text('');
-  $('#editorTags option:selected').each(function() {
-    node.find('span.meaningTags').append('<span class="tag">' + $(this).text() + '</span>');
-  });
-
-  // Update synonym tags and synonymIds
-  var synonymData = $('#editorSynonyms').select2('data');
-  node.find('span.synonymIds').text($.map(synonymData, function(rec, i) { return rec.id; }));
-  node.find('span.synonyms').text('');
-  $.map(synonymData, function(rec, i) {
-    node.find('span.synonyms').append('<span class="tag">' + rec.text + '</span>');
-  });
-
-  // Update antonym tags and antonymIds
-  var antonymData = $('#editorAntonyms').select2('data');
-  node.find('span.antonymIds').text($.map(antonymData, function(rec, i) { return rec.id; }));
-  node.find('span.antonyms').text('');
-  $.map(antonymData, function(rec, i) {
-    node.find('span.antonyms').append('<span class="tag">' + rec.text + '</span>');
-  });
-
-  // Now update the tree node
-  $('#meaningTree').tree('update', { target: domNode, text: node.find('.tree-title').html() });
-}
-
-function endMeaningEdit() {
-  struct_anyChanges = false;
-  $('#editorInternalRep, #editorInternalComment, #editMeaningAcceptButton, #editMeaningCancelButton').attr('disabled', 'disabled');
-  $('#editorInternalRep').val('');
-  $('#editorInternalComment').val('');
-  $('#editorSources').select2('val', []);
-  $('#editorSources').select2('enable', false);
-  $('#editorTags').select2('val', []);
-  $('#editorTags').select2('enable', false);
-  $('#editorSynonyms').select2('data', []);
-  $('#editorSynonyms').select2('enable', false);
-  $('#editorAntonyms').select2('data', []);
-  $('#editorAntonyms').select2('enable', false);
-}
-
-// Iterate a meaning tree node recursively and collect meaning-related fields
-function dexEditTreeWalk(node, results, level) {
-  var jqNode = $(node.target);
-  results.push({ 'id': jqNode.find('span.id').text(),
-                 'level' : level,
-                 'internalRep': jqNode.find('span.internalRep').text(),
-                 'internalComment': jqNode.find('span.internalComment').text(),
-                 'sourceIds': jqNode.find('span.sourceIds').text(),
-                 'meaningTagIds': jqNode.find('span.meaningTagIds').text(),
-                 'synonymIds': jqNode.find('span.synonymIds').text(),
-                 'antonymIds': jqNode.find('span.antonymIds').text(),
-               });
-  var children = $('#meaningTree').tree('getChildren', node.target);
-  for (var i = 0; i < children.length; i++) {
-    dexEditTreeWalk(children[i], results, level + 1);
-  }
-}
-
-function dexEditSaveEverything() {
-  if (struct_anyChanges) {
-    acceptMeaningEdit();
-  }
-  var results = new Array();
-  var roots = $('#meaningTree').tree('getRoots');
-  for (var i = 0; i < roots.length; i++) {
-    dexEditTreeWalk(roots[i], results, 0);
-  }
-  $('input[name=jsonMeanings]').val(JSON.stringify(results));
-  $('#meaningForm').submit();
-}
-
-function toggleInternalHtmlClick() {
-  var text = $(this).text();
-  $(this).text((text == 'arată html') ? 'arată text' : 'arată html');
-  $(this).closest('.defDetails').prevAll('.defInternalRep:last').slideToggle();
-  $(this).closest('.defDetails').prevAll('.defHtmlRep:last').slideToggle();
-  return false;
-}
-
-function boxTitleClick() {
-  $(this).next('.boxContents').slideToggle();
-}
-
-function adjustDefinitionDivHeight() {
-  var windowHeight = $(window).height();
-  var boxTop = $('#definitionBox .boxContents').position().top;
-  $('#definitionBox .boxContents').height(windowHeight - boxTop - 25);
-}

Deleted: wwwbase/struct/dexEdit.php
==============================================================================
--- wwwbase/struct/dexEdit.php	Mon Aug 19 16:28:41 2013	(r941)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,89 +0,0 @@
-<?Php
-require_once("../../phplib/util.php"); 
-util_assertModerator(PRIV_EDIT);
-util_assertNotMirror();
-
-$lexemId = util_getRequestIntParameter('lexemId');
-$hyphenations = util_getRequestParameter('hyphenations');
-$pronunciations = util_getRequestParameter('pronunciations');
-$variantIds = util_getRequestCsv('variantIds');
-$variantOfId = util_getRequestParameter('variantOfId');
-$jsonMeanings = util_getRequestParameter('jsonMeanings');
-
-$lexem = Lexem::get_by_id($lexemId);
-
-if ($jsonMeanings) {
-  $lexem->hyphenations = $hyphenations;
-  $lexem->pronunciations = $pronunciations;
-  $lexem->variantOfId = $variantOfId ? $variantOfId : null;
-  $variantOf = Lexem::get_by_id($lexem->variantOfId);
-  $meanings = json_decode($jsonMeanings);
-
-  if (validate($lexem, $variantOf, $variantIds, $meanings)) {
-    // Case 1: Validation passed
-    Meaning::saveTree($meanings, $lexem);
-    $lexem->save();
-    $lexem->updateVariants($variantIds);
-    util_redirect("dexEdit.php?lexemId={$lexem->id}");
-  } else {
-    // Case 2: Validation failed
-    SmartyWrap::assign('variantIds', $variantIds);
-    SmartyWrap::assign('meanings', Meaning::convertTree($meanings));
-  }
-} else {
-  // Case 3: First time loading this page
-  SmartyWrap::assign('variantIds', $lexem->getVariantIds());
-  SmartyWrap::assign('meanings', Meaning::loadTree($lexem->id));
-}
-
-$defs = Definition::loadByLexemId($lexem->id);
-foreach ($defs as $def) {
-  // $def->internalRep = AdminStringUtil::expandAbbreviations($def->internalRep, $def->sourceId);
-}
-$searchResults = SearchResult::mapDefinitionArray($defs);
-$meaningTags = Model::factory('MeaningTag')->order_by_asc('value')->find_many();
-
-SmartyWrap::assign('lexem', $lexem);
-SmartyWrap::assign('meaningTags', $meaningTags);
-SmartyWrap::assign('searchResults', $searchResults);
-SmartyWrap::assign('pageTitle', "Editare lexem: {$lexem->formNoAccent}");
-SmartyWrap::addCss('jqueryui', 'easyui', 'select2', 'struct', 'flex');
-SmartyWrap::addJs('dex', 'jquery', 'easyui', 'jqueryui', 'select2', 'struct');
-SmartyWrap::displayWithoutSkin('struct/dexEdit.ihtml');
-
-/**************************************************************************/
-
-function validate($lexem, $variantOf, $variantIds, $meanings) {
-  if ($variantOf && !empty($meanings)) {
-    FlashMessage::add("Acest lexem este o variantă a lui {$variantOf} și nu poate avea el însuși sensuri.");
-  }
-  if ($variantOf && !empty($variantIds)) {
-    FlashMessage::add("Acest lexem este o variantă a lui {$variantOf} și nu poate avea el însuși variante.");
-  }
-  if ($variantOf && ($variantOf->id == $lexem->id)) {
-    FlashMessage::add("Lexemul nu poate fi variantă a sa însăși.");
-  }
-
-  foreach ($variantIds as $variantId) {
-    $variant = Lexem::get_by_id($variantId);
-    if ($variant->id == $lexem->id) {
-      FlashMessage::add('Un lexem nu poate fi variantă a lui însuși.');
-    }
-    if ($variant->variantOfId && $variant->variantOfId != $lexem->id) {
-      $other = Lexem::get_by_id($variant->variantOfId);
-      FlashMessage::add("\"{$variant}\" este deja marcat ca variantă a lui \"{$other}\".");
-    }
-    $variantVariantCount = Model::factory('Lexem')->where('variantOfId', $variant->id)->count();
-    if ($variantVariantCount) {
-      FlashMessage::add("\"{$variant}\" are deja propriile lui variante.");
-    }
-    $variantMeaningCount = Model::factory('Meaning')->where('lexemId', $variant->id)->count();
-    if ($variantMeaningCount) {
-      FlashMessage::add("\"{$variant}\" are deja propriile lui sensuri.");
-    }
-  }
-
-  return FlashMessage::getMessage() == null;
-}
-
-?>

Modified: wwwbase/styles/flex.css
==============================================================================
--- wwwbase/styles/flex.css	Mon Aug 19 11:40:12 2013	(r941)
+++ wwwbase/styles/flex.css	Mon Aug 19 16:28:41 2013	(r942)
@@ -130,16 +130,6 @@
   margin-left: 30px;
 }
 
-div.lexemSectionHeader {
-  font-size: 110%;
-  font-weight: bold;
-}
-
-div.lexemSection {
-  margin-left: 20px;
-  margin-bottom: 10px;
-}
-
 div.verifyModel {
   border: 1px solid black;
   margin-top: 10px;
@@ -325,11 +315,6 @@
   margin-left: 50px;
 }
 
-input.miniDefTarget {
-  font-family: serif;
-  font-weight: bold;
-}
-
 div.bulkLabelComment {
   font-size: 90%;
   margin-left: 30px;

Copied and modified: wwwbase/styles/lexemEdit.css (from r928, wwwbase/styles/struct.css)
==============================================================================
--- wwwbase/styles/struct.css	Wed Aug 14 17:21:15 2013	(r928, copy source)
+++ wwwbase/styles/lexemEdit.css	Mon Aug 19 16:28:41 2013	(r942)
@@ -1,3 +1,7 @@
+.lexemEditActions {
+  margin: 5px 0px;
+}
+
 .box {
   border: 1px solid #444;
   -webkit-box-shadow: 2px 2px 5px #424242;
@@ -19,45 +23,6 @@
   padding: 5px;
 }
 
-#parameters {
-  margin-right: 250px;
-}
-
-#parameters label {
-  display: inline-block;
-  margin-top: 4px;
-  width: 100px;
-}
-
-#dexEditLeftColumn {
-  float: left;
-}
-
-#dexEditRightColumn {
-  margin-left: 412px;
-}
-
-#definitionBox {
-  overflow: auto;
-}
-
-#meaningEditor {
-  width: 400px;
-}
-
-#saveButtonContainer {
-  float: right;
-  padding-bottom: 5px;
-  padding-right: 10px;
-}
-
-#dexEditSaveButton {
-  font-size: 20px;
-  font-weight: bold;
-  height: 40px;
-  width: 200px;
-}
-
 #stemNode {
   display: none;
 }
@@ -105,22 +70,26 @@
   border-color: #e0a19d;
 }
 
-#editorInternalRep {
-  width: 382px;
+.meaningEditor label {
+  display: inline-block;
+  width: 77px;
 }
 
-#editorInternalComment {
-  width: 382px;
+.meaningEditor td {
+  vertical-align: top;
+}
+
+.leftColumn {
+  padding-right: 10px;
 }
 
-.editorLabel {
-  float: left;
-  margin: 4px 0px;
+#editorInternalRep {
+  height: 190px;
+  width: 510px;
 }
 
-.editorFieldContainer {
-  float: right;
-  margin: 4px 0px;
+#editorInternalComment {
+  width: 390px;
 }
 
 abbr {
@@ -159,6 +128,44 @@
   color: #555555;
 }
 
+div.addDefinition {
+  margin-top: 10px;
+}
+
+td.rightColumn {
+  padding-left: 30px;
+}
+
+input.miniDefTarget {
+  font-family: serif;
+  font-weight: bold;
+}
+
+input[name=cloneLexem] {
+  background: #e5e5e5 url("../img/icons/page_white_copy.png") 2px 0px no-repeat;
+  padding-left: 20px;
+}
+
+input[name=deleteLexem] {
+  background: #e5e5e5 url("../img/icons/cross16.png") 2px 0px no-repeat;
+  padding-left: 20px;
+}
+
+input[name=mergeLexem] {
+  background: #e5e5e5 url("../img/icons/add.png") 2px 0px no-repeat;
+  padding-left: 20px;
+}
+
+input[name=refreshLexem] {
+  background: #e5e5e5 url("../img/icons/arrow_refresh.png") 2px 0px no-repeat;
+  padding-left: 20px;
+}
+
+input[name=saveLexem] {
+  background: #e5e5e5 url("../img/icons/disk.png") 2px 0px no-repeat;
+  padding-left: 20px;
+}
+
 .select2-container-multi, .select2-result {
   font-size: 12px;
 }

Deleted: wwwbase/styles/struct.css
==============================================================================
--- wwwbase/styles/struct.css	Mon Aug 19 16:28:41 2013	(r941)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,164 +0,0 @@
-.box {
-  border: 1px solid #444;
-  -webkit-box-shadow: 2px 2px 5px #424242;
-  box-shadow: 2px 2px 5px #424242;
-  -moz-box-shadow: 2px 2px 5px #424242;
-  margin-bottom: 10px;
-  margin-right: 10px;
-}
-
-.boxTitle {
-  background: #444 url("../img/icons/cog.png") no-repeat 5px 6px;
-  color: white;
-  cursor: pointer;
-  font-weight: bold;
-  padding: 5px 5px 5px 25px;
-}
-
-.boxContents {
-  padding: 5px;
-}
-
-#parameters {
-  margin-right: 250px;
-}
-
-#parameters label {
-  display: inline-block;
-  margin-top: 4px;
-  width: 100px;
-}
-
-#dexEditLeftColumn {
-  float: left;
-}
-
-#dexEditRightColumn {
-  margin-left: 412px;
-}
-
-#definitionBox {
-  overflow: auto;
-}
-
-#meaningEditor {
-  width: 400px;
-}
-
-#saveButtonContainer {
-  float: right;
-  padding-bottom: 5px;
-  padding-right: 10px;
-}
-
-#dexEditSaveButton {
-  font-size: 20px;
-  font-weight: bold;
-  height: 40px;
-  width: 200px;
-}
-
-#stemNode {
-  display: none;
-}
-
-#meaningTreeContainer {
-  overflow: auto;
-}
-
-#meaningTree .id, #meaningTree .internalRep, #meaningTree .internalComment, #meaningTree .sourceIds,
-#meaningTree .meaningTagIds, #meaningTree .synonymIds, #meaningTree .antonymIds {
-  display: none;
-}
-
-#meaningTree .htmlRep {
-  font-size: 14px;
-  margin-right: 10px;
-}
-
-#meaningTree .tag {
-  border-radius: 4px;
-  border-style: solid;
-  border-width: 1px;
-  font-size: 10px;
-  margin-right: 5px;
-  padding: 1px 4px;
-}
-
-#meaningTree .sources span {
-  background: #f7eada;
-  border-color: #e0c29d;
-}
-
-#meaningTree .meaningTags span {
-  background: #dbf7da;
-  border-color: #9fe09d;
-}
-
-#meaningTree .synonyms span {
-  background: #daebf7;
-  border-color: #9dc5e0;
-}
-
-#meaningTree .antonyms span {
-  background: #f7dcda;
-  border-color: #e0a19d;
-}
-
-#editorInternalRep {
-  width: 382px;
-}
-
-#editorInternalComment {
-  width: 382px;
-}
-
-.editorLabel {
-  float: left;
-  margin: 4px 0px;
-}
-
-.editorFieldContainer {
-  float: right;
-  margin: 4px 0px;
-}
-
-abbr {
-  border-bottom: 1px dotted #aaa;
-  cursor: help;
-}
-
-div.defInternalRep {
-  font-family: courier;
-  margin-top: 10px;
-}
-
-div.defHtmlRep {
-  display: none;
-  margin-top: 10px;
-}
-
-.commentInternalRep {
-  color: #333;
-  margin-left:15px;
-  margin-top: 5px;
-  padding: 5px;
-}
-
-span.defDetails {
-  color: #999999;
-  font-family: sans-serif;
-  font-size: 80%;
-}
-
-span.defDetails a {
-  color: #777777;
-}
-
-span.defDetails a:hover {
-  color: #555555;
-}
-
-.select2-container-multi, .select2-result {
-  font-size: 12px;
-}


More information about the Dev mailing list