From d5cd84d22b4e25a9310c14763086e42a97fb9c9e Mon Sep 17 00:00:00 2001
From: Juan Ferrer Toribio <juan.ferrer.toribio@gmail.com>
Date: Tue, 15 Dec 2015 16:22:46 +0100
Subject: [PATCH] =?UTF-8?q?Dise=C3=B1o=20responsive=20mejorado,=20a=C3=B1a?=
 =?UTF-8?q?didos=20efectos=20mediante=20transiciones=20CSS,=20errores=20en?=
 =?UTF-8?q?=20Safari=20solucionados,=20errores=20de=20estilo=20solucionado?=
 =?UTF-8?q?s,=20CSS=20optimizado?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 debian/changelog                           |   2 +-
 web/forms/account/conf/ui.xml              |   2 +-
 web/forms/admin/connections/connections.js |  16 +-
 web/forms/admin/connections/ui.xml         |   2 +-
 web/forms/cms/home/style.css               |  18 +-
 web/forms/cms/home/ui.xml                  |  46 ++---
 web/forms/ecomerce/catalog/catalog.js      |   4 +-
 web/forms/ecomerce/catalog/style.css       |  30 +--
 web/forms/ecomerce/catalog/ui.xml          |   4 +-
 web/forms/ecomerce/checkout/style.css      |   6 +-
 web/forms/ecomerce/confirm/confirm.js      |  22 ++-
 web/forms/ecomerce/confirm/style.css       |  22 +--
 web/forms/ecomerce/confirm/ui.xml          |  34 ++--
 web/image/dark/{order.svg => place.svg}    |   0
 web/image/{order.svg => place.svg}         |   0
 web/image/youtube.svg                      |  16 +-
 web/js/hedera/app.js                       |  66 ++++++-
 web/js/hedera/form.js                      |   2 +-
 web/js/hedera/gui.css                      | 123 +++++++------
 web/js/hedera/gui.js                       | 108 +++--------
 web/js/hedera/gui.xml                      |  26 ++-
 web/js/hedera/login.css                    |  82 +++++----
 web/js/hedera/login.js                     |   2 +-
 web/js/hedera/login.xml                    |   2 +-
 web/js/hedera/report.js                    |   4 -
 web/js/hedera/style.css                    |  47 ++---
 web/js/htk/field/select.js                 | 202 ++++++++-------------
 web/js/htk/popup.js                        | 197 +++++++++++++++-----
 web/js/htk/style.css                       |  61 +++++--
 29 files changed, 620 insertions(+), 526 deletions(-)
 rename web/image/dark/{order.svg => place.svg} (100%)
 rename web/image/{order.svg => place.svg} (100%)

diff --git a/debian/changelog b/debian/changelog
index ac49c216..6fe5db8a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-hedera-web (1.305-deb8) stable; urgency=low
+hedera-web (1.312-deb8) stable; urgency=low
 
   * Initial Release.
 
diff --git a/web/forms/account/conf/ui.xml b/web/forms/account/conf/ui.xml
index a2773aa0..6473c5ce 100755
--- a/web/forms/account/conf/ui.xml
+++ b/web/forms/account/conf/ui.xml
@@ -25,7 +25,7 @@
 </div>
 <div id="actions">
 	<htk-button
-		image="image/dark/shipping.svg"
+		image="image/dark/place.svg"
 		tip="_Addresses"
 		on-click="onAddressesClick"
 		showText="true"/>
diff --git a/web/forms/admin/connections/connections.js b/web/forms/admin/connections/connections.js
index 928cef6c..ba3fd12f 100755
--- a/web/forms/admin/connections/connections.js
+++ b/web/forms/admin/connections/connections.js
@@ -3,16 +3,22 @@ Vn.Connections = new Class
 ({
 	Extends: Vn.Form
 	
-	,_intervalId: null
-	
-	,activate: function ()
+	,_timeoutId: null
+
+	,onModelStatusChange: function (model, status)
 	{
-		this._intervalId = setInterval (this.onRefreshClick.bind (this), 60000);
+		if (!model.ready)
+			return;
+
+		if (this._timeoutId)
+			clearTimeout (this._timeoutId);
+			
+		this._timeoutId = setTimeout (this.onRefreshClick.bind (this), 60000);
 	}
 	
 	,deactivate: function ()
 	{
-		clearTimeout (this._intervalId);
+		clearTimeout (this._timeoutId);
 	}
 	
 	,onRefreshClick: function ()
diff --git a/web/forms/admin/connections/ui.xml b/web/forms/admin/connections/ui.xml
index 4d4ff1ee..6e8a7880 100755
--- a/web/forms/admin/connections/ui.xml
+++ b/web/forms/admin/connections/ui.xml
@@ -21,7 +21,7 @@
 <div id="form" class="connections">
 	<div class="box">
 		<htk-repeater form-id="iter">
-			<db-model property="model" id="sessions">
+			<db-model property="model" id="sessions" on-status-changed="onModelStatusChange">
 				<custom>
 					SELECT s.id, e.user_id, c.Cliente, e.date_time login, is_new,
 					s.date_time last_activity, a.platform, a.browser, a.version
diff --git a/web/forms/cms/home/style.css b/web/forms/cms/home/style.css
index 9dac9a27..8f75629b 100755
--- a/web/forms/cms/home/style.css
+++ b/web/forms/cms/home/style.css
@@ -1,14 +1,22 @@
 
 /* News panel */
 
-.home
-{
-	margin: .5em;
-}
 .column
 {
+	margin: .5em;
 	max-width: 120em;
 }
+.action-bar button.start-order
+{
+	background-color: #EF5350;
+	margin: .7em .4em;
+	padding: .5em;
+	box-shadow: 0 0 0.4em rgba(1, 1, 1, 0.4);
+}
+.action-bar button.start-order:hover
+{
+	background-color: #F44336;
+}
 
 /* New */
 
@@ -19,7 +27,7 @@
 	color: #222;
 	border: none;
 	border-radius: 0.1em;
-	box-shadow: 0 0.2em 0.2em #CCC;
+	box-shadow: 0 0.2em 0.2em rgba(1, 1, 1, 0.2);
 	margin: .5em;
 }
 .new .top
diff --git a/web/forms/cms/home/ui.xml b/web/forms/cms/home/ui.xml
index fae1dc95..1189ba9b 100755
--- a/web/forms/cms/home/ui.xml
+++ b/web/forms/cms/home/ui.xml
@@ -4,6 +4,7 @@
 </div>
 <div id="actions" class="catalog-actions">
 	<htk-button
+		class="start-order"
 		image="image/dark/new-order.svg"
 		tip="_Start order"
 		on-click="onStartOrderClick"
@@ -11,31 +12,32 @@
 </div>
 <div id="form" class="home">
 	<div class="column mansonry" id="news-column">
-	<htk-repeater form-id="new">
-		<db-model property="model">
+		<htk-repeater form-id="new">
+			<db-model property="model">
+				<custom>
+					SELECT title, date_time, text, image, id  FROM news
+						WHERE tag != 'course'
+						ORDER BY priority, date_time DESC
+				</custom>
+			</db-model>
 			<custom>
-				SELECT title, date_time, text, image, id  FROM news
-					WHERE tag != 'course'
-					ORDER BY priority, date_time DESC
-			</custom>
-		</db-model>
-		<custom>
-			<div class="masonry-box">
-			<div class="new">
-				<div class="top">
-					<h2><htk-text form="new" column="title"/></h2>
-<!--				<p class="new-info">
-						<htk-text format="_%a, %e %b %Y" form="new" column="date_time"/>
-					</p>
--->					<div class="new-text">
-						<htk-html form="new" column="text"/>
+				<div class="masonry-box">
+				<div class="new">
+					<div class="top">
+						<h2><htk-text form="new" column="title"/></h2>
+	<!--				<p class="new-info">
+							<htk-text format="_%a, %e %b %Y" form="new" column="date_time"/>
+						</p>
+	-->					<div class="new-text">
+							<htk-html form="new" column="text"/>
+						</div>
 					</div>
+					<htk-image directory="news/full" form="new" column="image" editable="false"/>
 				</div>
-				<htk-image directory="news/full" form="new" column="image" editable="false"/>
-			</div>
-			</div>
-		</custom>
-	</htk-repeater>
+				</div>
+			</custom>
+		</htk-repeater>
+		<div class="clear"/>
 	</div>
 </div>
 </vn>
diff --git a/web/forms/ecomerce/catalog/catalog.js b/web/forms/ecomerce/catalog/catalog.js
index 6529fe68..c98a68b7 100755
--- a/web/forms/ecomerce/catalog/catalog.js
+++ b/web/forms/ecomerce/catalog/catalog.js
@@ -179,7 +179,7 @@ Vn.Catalog = new Class
 	{
 		if (!this._menuShown)
 			return;
-	
+
 		this.gui.hideBackground ();
 		Vn.Node.removeClass (this.$('right-panel'), 'show');
 		document.removeEventListener ('click', this.hideMenuCallback);
@@ -469,7 +469,7 @@ Vn.Filter = new Class
 		this.parent (props);
 	}
 	
-	,_onClick: function ()
+	,_onClick: function (e)
 	{
 		if (this._model && this._model.status === Db.Model.Status.CLEAN)
 			this._model.refresh ();
diff --git a/web/forms/ecomerce/catalog/style.css b/web/forms/ecomerce/catalog/style.css
index 25cf129b..3b05f6c1 100755
--- a/web/forms/ecomerce/catalog/style.css
+++ b/web/forms/ecomerce/catalog/style.css
@@ -1,30 +1,13 @@
 .catalog
 {
-	position: relative;
-	width: 100%;
-	height: 100%;
-	min-height: 25em;
-}
-.catalog div.center
-{
-	position: absolute;
-	top: 0;
-	bottom: 0;
-	left: 0;
-	right: 17em;
+	margin-right: 17em;
 }
 
 /* Main */
 
-.catalog div.main
+.catalog > .main
 {
-	position: absolute;
-	top: 0;
-	bottom: 0;
-	left: 0;
-	right: 0;
-	overflow: auto;
-	padding: .4em;
+	padding: .5em;
 }
 .htk-toast
 {
@@ -43,7 +26,7 @@
 
 .right-panel
 {
-	position: absolute;
+	position: fixed;
 	top: 3.9em;
 	bottom: 0;
 	right: 0;
@@ -96,7 +79,6 @@
 }
 .right-panel select
 {
-	margin: 0 auto;
 	width: 100%;
 }
 .vn-filter > ul
@@ -308,9 +290,9 @@ td.third-category
 		transform: translateZ(0) translateX(-17em);
 		-webkit-transform: translateZ(0) translateX(-17em);
 	}
-	.catalog div.center
+	.catalog
 	{
-		right: 0;
+		margin-right: 0;
 	}
 }
 
diff --git a/web/forms/ecomerce/catalog/ui.xml b/web/forms/ecomerce/catalog/ui.xml
index 25a86f42..e068abc6 100755
--- a/web/forms/ecomerce/catalog/ui.xml
+++ b/web/forms/ecomerce/catalog/ui.xml
@@ -121,9 +121,7 @@
 	</button>
 </div>
 <div id="form" class="catalog">
-	<div class="center">
-		<div id="main" class="main"/>
-	</div>
+	<div id="main" class="main"/>
 </div>
 <div id="list-view" class="list-view">
 	<div class="box">
diff --git a/web/forms/ecomerce/checkout/style.css b/web/forms/ecomerce/checkout/style.css
index 854768e3..9fa8fdb3 100755
--- a/web/forms/ecomerce/checkout/style.css
+++ b/web/forms/ecomerce/checkout/style.css
@@ -18,9 +18,9 @@
 {
 	font-size: 1.4em;
 }
-.answers select
+.answers .htk-select
 {
-	min-width: 8em;
+	max-width: 8em;
 	display: block;
 	margin: 0 auto;
 	font-size: 1.6em;
@@ -78,7 +78,7 @@
 {
 	color: white;
 }
-.htk-assistant button
+.htk-assistant .thin
 {
 	float: right;
 }
diff --git a/web/forms/ecomerce/confirm/confirm.js b/web/forms/ecomerce/confirm/confirm.js
index 2f0b9e89..7650911b 100755
--- a/web/forms/ecomerce/confirm/confirm.js
+++ b/web/forms/ecomerce/confirm/confirm.js
@@ -62,27 +62,29 @@ Vn.Confirm = new Class
 
 	,onConfirm: function (query, resultSet)
 	{
+		this.disableButtons (false);
+
 		var res = resultSet.fetchResult ();
-		var debt = resultSet.fetchValue ();
 	
 		if (res)
 		{
 			Vn.Cookie.unset ('order');
-			this.pay = debt > this.$('order-form').get ('credit');
 
-			this.popup = new Htk.Popup ();
-			this.popup.setChildNode (this.$('success-dialog'));
-			this.popup.showCenter ();
+			var debt = resultSet.fetchValue ();
+			this._pay = debt > this.$('order-form').get ('credit');
+
+			this.$('success-dialog').show ();
 		}
-		else
-			this.disableButtons (false);
 	}
 	
 	,onAcceptClick: function ()
 	{
-		this.popup.hide ();
-		
-		if (this.pay)
+		this.$('success-dialog').hide ();
+	}
+	
+	,onPopupClose: function ()
+	{
+		if (this._pay)
 			Vn.Tpv.pay (this.conn, this.$('total').value,
 				this.$('order-form').get ('company_id'));
 		else
diff --git a/web/forms/ecomerce/confirm/style.css b/web/forms/ecomerce/confirm/style.css
index 7676263c..975a4f62 100755
--- a/web/forms/ecomerce/confirm/style.css
+++ b/web/forms/ecomerce/confirm/style.css
@@ -14,11 +14,10 @@
 .confirm .form
 {
 	margin: 0 auto;
-	padding: 3em 4em;
+	padding: 2.5em 3em;
 	color: #555;
 }
-.confirm .form p,
-.confirm .form select,
+.confirm .form p.important,
 .confirm .form button
 {
 	font-size: 1.4em;
@@ -31,10 +30,6 @@
 {
 	margin: .2em 0;
 }
-.confirm .form p.small
-{
-	font-size: 1em;
-}
 .button-bar
 {
 	margin-top: 2em;
@@ -52,26 +47,17 @@
 
 .success-dialog
 {
-	padding: 2em;
-	min-width: 30em;
+	padding: 1em;
 	max-width: 35em;
-}
-.success-dialog *
-{
 	font-weight: normal;
 	color: #555;
 }
-.success-dialog p,
-.success-dialog button
-{
-	font-size: 1.4em;
-}
 .success-dialog img
 {
 	float: left;
 	height: 3em;
 	margin-top: 0;
-	margin-right: 1.5em;
+	margin-right: 1em;
 }
 .success-dialog p
 {
diff --git a/web/forms/ecomerce/confirm/ui.xml b/web/forms/ecomerce/confirm/ui.xml
index 4bf79116..86c05146 100755
--- a/web/forms/ecomerce/confirm/ui.xml
+++ b/web/forms/ecomerce/confirm/ui.xml
@@ -40,33 +40,33 @@
 	<div class="box">
 		<div class="form">
 			<div class="section">
-				<p>
+				<p class="important">
 					<t>Arrival</t> 
 					<htk-text format="_%A, %e of %B" form="order-form" column="date_send"/>
 				</p>
-				<p class="small">
+				<p>
 					<span id="method"><t>Agency</t></span> 
 					<htk-text form="order-form" column="agency"/>
 				</p>
 			</div>
 			<div id="address" class="section">
-				<p>
+				<p class="important">
 					<htk-text form="order-form" column="consignee"/>
 				</p>
-				<p class="small">
+				<p>
 					<htk-text form="order-form" column="address"/>
 				</p>
-				<p class="small">
+				<p>
 					<htk-text form="order-form" column="zip_code"/>, 
 					<htk-text form="order-form" column="city"/>
 				</p>
 			</div>
 			<div class="section">
-				<p>
+				<p class="important">
 					<t>Total</t> 
 					<htk-text id="total" format="%.2d€"/>
 				</p>
-				<p class="small">
+				<p>
 					(<t>TaxBase</t> <htk-text form="total-form" column="tax_base" format="%.2d€"/> +
 					<t>VAT</t> <htk-text form="total-form" column="vat" format="%.2d€"/>)
 				</p>
@@ -83,15 +83,17 @@
 		</div>
 	</div>
 </div>
-<div id="success-dialog" class="success-dialog">
-	<div>
-		<img src="image/ok.svg" alt="_Ok"/>
-		<p><t>OrderPlacedSuccessfully</t></p>
+<htk-popup id="success-dialog" modal="true" on-closed="onPopupClose">
+	<div property="child-node" class="success-dialog">
+		<div>
+			<img src="image/ok.svg" alt="_Ok"/>
+			<p><t>OrderPlacedSuccessfully</t></p>
+			<div class="clear"/>
+		</div>
+		<button on-click="onAcceptClick" class="thin confirm-order">
+			<t>Accept</t>
+		</button>
 		<div class="clear"/>
 	</div>
-	<button on-click="onAcceptClick" class="thin confirm-order">
-		<t>Accept</t>
-	</button>
-	<div class="clear"/>
-</div>
+</htk-popup>
 </vn>
diff --git a/web/image/dark/order.svg b/web/image/dark/place.svg
similarity index 100%
rename from web/image/dark/order.svg
rename to web/image/dark/place.svg
diff --git a/web/image/order.svg b/web/image/place.svg
similarity index 100%
rename from web/image/order.svg
rename to web/image/place.svg
diff --git a/web/image/youtube.svg b/web/image/youtube.svg
index 80fc42d6..c38c48c4 100644
--- a/web/image/youtube.svg
+++ b/web/image/youtube.svg
@@ -13,7 +13,7 @@
    height="23.999996"
    id="svg11927"
    version="1.1"
-   inkscape:version="0.48.5 r10040"
+   inkscape:version="0.91 r13725"
    sodipodi:docname="youtube.svg">
   <defs
      id="defs3" />
@@ -25,9 +25,9 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="7.919596"
-     inkscape:cx="64.326307"
-     inkscape:cy="46.777283"
+     inkscape:zoom="34.458339"
+     inkscape:cx="12"
+     inkscape:cy="11.999998"
      inkscape:current-layer="layer1"
      showgrid="false"
      units="mm"
@@ -37,7 +37,7 @@
      fit-margin-right="0"
      fit-margin-bottom="0"
      inkscape:window-width="1920"
-     inkscape:window-height="1014"
+     inkscape:window-height="1016"
      inkscape:window-x="1920"
      inkscape:window-y="27"
      inkscape:window-maximized="1" />
@@ -49,7 +49,7 @@
         <dc:format>image/svg+xml</dc:format>
         <dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
+        <dc:title></dc:title>
       </cc:Work>
     </rdf:RDF>
   </metadata>
@@ -59,8 +59,8 @@
      id="layer1"
      transform="translate(-65.660672,-187.08936)">
     <path
-       style="fill:#c30000;fill-opacity:1;stroke:none;display:inline"
-       d="m 68.556274,210.90728 c -2.293676,-0.68242 -2.880675,-2.99702 -2.89518,-11.41603 -0.01025,-5.94721 0.16327,-7.96905 0.8512,-9.91843 0.533461,-1.51166 1.175311,-1.99041 3.044687,-2.27101 1.814868,-0.27242 11.459518,-0.28621 15.293323,-0.0219 5.345509,0.48245 4.737665,4.05194 4.797521,11.13 0.06208,7.3381 -0.07728,8.93495 -0.942901,10.80584 -0.857753,1.85393 -0.528524,1.79528 -10.467487,1.86487 -5.046388,0.0354 -9.231633,-0.0396 -9.681163,-0.17336 z m 14.0137,-11.9128 c -9.225924,-6.1861 1.31465,0.90117 -8.167349,-5.4762 0.0541,2.97456 0.0086,8.38462 0.04076,11.04998 9.474932,-6.37668 -1.004697,0.69337 8.126587,-5.57378 z"
+       style="display:inline;fill:#c30000;fill-opacity:1;stroke:none"
+       d="m 68.556274,210.90728 c -2.293676,-0.68242 -2.880675,-2.99702 -2.89518,-11.41603 -0.01025,-5.94721 0.16327,-7.96905 0.8512,-9.91843 0.533461,-1.51166 1.175311,-1.99041 3.044687,-2.271 1.814867,-0.27243 11.459517,-0.28622 15.293322,-0.0219 5.345509,0.48245 4.737665,4.05194 4.797522,11.13 0.06208,7.3381 -0.07728,8.93495 -0.942902,10.80584 -0.857753,1.85393 -0.528524,1.79528 -10.467486,1.86487 -5.046389,0.0354 -9.231633,-0.0396 -9.681163,-0.17336 z m 14.013699,-11.9128 c -9.225923,-6.1861 1.31465,0.90117 -8.167348,-5.4762 0.0541,2.97456 0.0086,8.38462 0.04076,11.04998 9.474933,-6.37668 -1.004697,0.69337 8.126587,-5.57378 z"
        id="path11905"
        inkscape:connector-curvature="0"
        sodipodi:nodetypes="cssscccsccccc" />
diff --git a/web/js/hedera/app.js b/web/js/hedera/app.js
index b256cf8c..ca483d23 100644
--- a/web/js/hedera/app.js
+++ b/web/js/hedera/app.js
@@ -18,17 +18,20 @@ Vn.App = new Class
 		});
 		this._isGuest.on ('changed', this._onGuestChange, this);
 
-		this._conn = new Db.Conn ();
+		var conn = new Db.Conn ();
+		this.link ({_conn: conn}, {'error': this._onConnError});
 	}
 	
 	,run: function ()
 	{
+		var guest = Vn.Cookie.check ('hedera_guest');
+	
 		if (Vn.Cookie.check ('vn_pass'))
 		{
 			this._conn.open (null, null, null,
 				this._onAutoLogin.bind (this));
 		}
-		else if (this._isGuest.value || Vn.Cookie.check ('hedera_guest'))
+		else if (this._isGuest.value || guest)
 		{
 			this._guestLogin ();
 		}
@@ -38,6 +41,9 @@ Vn.App = new Class
 			login.on ('login', this._onLogin, this);
 			login.show ();
 		}
+		
+		if (guest)
+			Vn.Cookie.unset ('hedera_guest');
 	}
 	
 	,_onGuestChange: function ()
@@ -62,7 +68,6 @@ Vn.App = new Class
 		if (!success)
 		{
 			this._isGuest.value = false;
-			Vn.Cookie.unset ('hedera_guest');
 			this.run ();
 		}
 		else
@@ -117,6 +122,61 @@ Vn.App = new Class
 	{
 		this.unref ();
 	}
+
+	,_onConnError: function (conn, error)
+	{
+		if (error instanceof Vn.Error)
+		switch (error.domain)
+		{
+			case 'Auth':
+				Htk.Toast.showError (_('You\'ve been too idle'));
+				if (this._gui)
+					this._gui.logout ();
+				break;
+			case 'Version':
+				this._newVersion (error);
+				break;
+			case 'User':
+				Htk.Toast.showError (error.message);
+				break;
+			default:
+				console.error (error.message);
+				Htk.Toast.showError (_('There was an internal error'));
+		}
+		else
+		{
+			console.error (error);
+			Htk.Toast.showError (_('There was an internal error'));
+			this._notifyError (error);
+		}
+	}
+	
+	,_newVersion: function (error)
+	{
+		if (this.newVersionBlock || this.skipVersion)
+			return;
+			
+		this.newVersionBlock = true;
+
+		var reload;
+		var message = _('New version available') +"\n\n"+ error.message;
+
+		if (error.code == 'criticalVersion')
+		{
+			alert (message)
+			reload = true;
+		}
+		else
+		{
+			reload = confirm (message);
+			this.skipVersion = true;
+		}
+
+		if (reload)
+			location.reload ();
+			
+		this.newVersionBlock = false;
+	}
 	
 	,_notifyError: function (error)
 	{
diff --git a/web/js/hedera/form.js b/web/js/hedera/form.js
index f7e400d0..720cd96f 100755
--- a/web/js/hedera/form.js
+++ b/web/js/hedera/form.js
@@ -54,7 +54,7 @@ Vn.Form = new Class
 			
 		if (this.node)
 		{
-			this.gui.formHolder.appendChild (this.node);
+			this.gui.setForm (this.node);
 			this.gui.setTitle (res.$('title'));
 			this.gui.setActions (res.$('actions'));
 			this.activate ();
diff --git a/web/js/hedera/gui.css b/web/js/hedera/gui.css
index c3b48b55..27c910d9 100755
--- a/web/js/hedera/gui.css
+++ b/web/js/hedera/gui.css
@@ -1,39 +1,38 @@
 
 .vn-gui
 {
-	position: absolute;
-	top: 0;
-	bottom: 0;
-	left: 0;
-	right: 0;
+	height: inherit;
 }
 
 /* Font */
 
 .vn-gui .welcome,
+.vn-gui .supplant > span,
 .vn-gui .menu-title,
 .vn-gui .main-menu a
 {
 	font-size: 1.1em;
 }
 
-/* Header */
+/* Navigation bar */
 
-.vn-gui .top-bar,
+.vn-gui .navbar,
 .vn-gui .exit
 {
 	height: 3.9em;
 }
-.vn-gui .top-bar
+.vn-gui .navbar
 {
-	position: relative;
+	position: fixed;
 	background-color: #009688;
-	width: 100%;
+	left: 15em;
+	top: 0;
+	right: 0;
 	z-index: 1;
 	overflow: hidden;
 	box-shadow: 0 0.1em 0.1em rgba(1, 1, 1, 0.3);
 }
-.vn-gui .top-bar
+.vn-gui .navbar
 {
 	color: white;
 }
@@ -68,7 +67,7 @@
 	padding-right: 0;
 	margin: 0;
 }
-.vn-gui .top-bar > .htk-spinner
+.vn-gui .navbar > .htk-spinner
 {
 	float: left;
 	margin: 1.05em .8em;
@@ -124,27 +123,40 @@
 	height: 1.4em;
 }
 
-/* Body */
+/* Background */
 
-.vn-gui > .body
+.vn-gui > .background
 {
-	position: absolute;
+	z-index: 10;
+	position: fixed;
 	top: 0;
-	bottom: 0;
-	left: 15em;
-	right: 0;
-}
-.vn-gui .content
-{
-	position: absolute;
-	top: 3.9em;
-	bottom: 0;
 	left: 0;
 	right: 0;
+	bottom: 0;
+	visibility: hidden;
+	background-color: rgba(1, 1, 1, 0.7);
+	opacity: 0;
+}
+.vn-gui > .background.show
+{
+	visibility: visible;
+	transition: opacity 200ms ease-out;
+	opacity: 1;
 }
 
 /* Left panel */
 
+.vn-gui .left-panel
+{
+	z-index: 20;
+	position: fixed;
+	left: 0;
+	bottom: 0;
+	top: 0;
+	background-color: white;
+	z-index: 20;
+	box-shadow: 0 0.2em 0.2em rgba(1, 1, 1, 0.4);
+}
 .vn-gui .menu-header
 {
 	background-color: #333;
@@ -171,8 +183,6 @@
 }
 .vn-gui .supplant > span
 {
-	font-size: 1.1em;
-	
 	max-width: 10em;
 	display: inline-block;
 	text-overflow: ellipsis;
@@ -184,34 +194,12 @@
 	float: right;
 	padding: .2em;
 }
-.vn-gui .background
-{
-	z-index: 10;
-	position: absolute;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
-	background-color: rgba(10, 10, 10, 0.6);
-	display: none;
-}
 .vn-gui .left-panel,
 .vn-gui .main-menu > li,
 .vn-gui ul.submenu
 {
 	width: 15em;
 }
-.vn-gui .left-panel
-{
-	z-index: 20;
-	position: absolute;
-	left: 0;
-	bottom: 0;
-	top: 0;
-	background-color: white;
-	z-index: 20;
-	box-shadow: 0 0.2em 0.2em rgba(1, 1, 1, 0.4);
-}
 .vn-gui .menu-overflow
 {
 	position: absolute;
@@ -313,28 +301,41 @@
 	height: 1.8em;
 }
 
-/* Form holder */
+/* Body */
 
+.vn-gui > .body
+{
+	margin-left: 15em;
+	padding-top: 3.9em;
+	height: inherit;
+	box-sizing: border-box;
+	height: inherit;
+}
 .vn-gui .form-holder
 {
-	position: absolute;
-	top: 0em;
-	bottom: 0;
-	right: 0;
-	left: 0;
-	overflow: auto;
+	position: relative;
+	height: inherit;
+	opacity: 0;
+	transform: translateZ(0) translateX(-2em);
+}
+.vn-gui .form-holder.show
+{
+	transition: 250ms ease-out all;
+	opacity: 1;
+	transform: translateZ(0) translateX(0em);
 }
 
 /* Transitions */
 
 .vn-gui > .body
 {
-	transition-property: left, right;
+	transition-property: margin-left, margin-right;
 	transition-duration: 200ms;
 }
-.vn-gui .top-bar
+.vn-gui >.navbar
 {
-	transition: background-color 300ms;
+	transition-property: left, background-color;
+	transition-duration: 200ms;
 }
 
 /* Desktop */
@@ -360,10 +361,14 @@
 	{
 		display: none;
 	}
-	.vn-gui > .body
+	.vn-gui > .navbar
 	{
 		left: 0;
 	}
+	.vn-gui > .body
+	{
+		margin-left: 0;
+	}
 	.vn-gui .menu-button
 	{
 		display: block;
diff --git a/web/js/hedera/gui.js b/web/js/hedera/gui.js
index 8960bd21..9ab55c77 100755
--- a/web/js/hedera/gui.js
+++ b/web/js/hedera/gui.js
@@ -13,10 +13,7 @@ Vn.Gui = new Class
 			,set: function (x)
 			{
 				this.link ({_conn: x},
-				{
-					 'error': this.onConnError
-					,'loading-changed': this._onConnLoadChange
-				});
+					{'loading-changed': this._onConnLoadChange });
 
 				var sql = 'SELECT default_form, image_dir, image_host FROM config;'
 					+'SELECT production_domain, test_domain FROM config;'
@@ -48,7 +45,6 @@ Vn.Gui = new Class
 		this.builderInit ('js/hedera/gui.xml');
 	
 		this.loadingCount = 0;
-		this.formHolder = this.$('form-holder');
 
 		this.hash = Vn.Hash;
 		this.hashParam = new Vn.HashParam ({key: 'form'});
@@ -88,6 +84,11 @@ Vn.Gui = new Class
 		Vn.Node.remove (this.node);
 	}
 	
+	,logout: function ()
+	{
+		this.onLogoutClick ();
+	}
+	
 	,onLogoutClick: function ()
 	{
 		this._conn.close (this.onConnClose.bind (this));
@@ -100,12 +101,12 @@ Vn.Gui = new Class
 
 	,showBackground: function ()
 	{
-		Vn.Node.show (this.$('background'));
+		Vn.Node.addClass (this.$('background'), 'show');
 	}
 
 	,hideBackground: function ()
 	{
-		Vn.Node.hide (this.$('background'));
+		Vn.Node.removeClass (this.$('background'), 'show');
 	}
 
 	,showMenu: function ()
@@ -197,54 +198,6 @@ Vn.Gui = new Class
 
 		this._onFormChange ();
 	}
-	
-	,notifyError: function (error)
-	{
-		if (error instanceof Error)
-		{
-			var httpRequest = new Vn.HttpRequest ()
-			httpRequest.add
-			({
-				 'file': error.fileName
-				,'line': error.lineNumber
-				,'message': error.message
-				,'stack': error.stack
-			});
-			httpRequest.send ('log.php');
-		}
-	}
-
-	,errorHandler: function (error)
-	{
-		if (error instanceof Vn.Error)
-		switch (error.domain)
-		{
-			case 'Auth':
-				Htk.Toast.showError (_('You\'ve been too idle'));
-				this.signalEmit ('logout');
-				break;
-			case 'Version':
-				this.newVersion (error);
-				break;
-			case 'User':
-				Htk.Toast.showError (error.message);
-				break;
-			default:
-				console.error (error.message);
-				Htk.Toast.showError (_('There was an internal error'));
-		}
-		else
-		{
-			console.error (error);
-			Htk.Toast.showError (_('There was an internal error'));
-			this.notifyError (error);
-		}
-	}
-
-	,onConnError: function (conn, error)
-	{
-		this.errorHandler (error);
-	}
 
 	,_onConnLoadChange: function (conn, isLoading)
 	{
@@ -273,33 +226,6 @@ Vn.Gui = new Class
 			this.$('loader').stop ();
 	}
 	
-	,newVersion: function (error)
-	{
-		if (this.newVersionBlock || this.skipVersion)
-			return;
-			
-		this.newVersionBlock = true;
-
-		var reload;
-		var message = _('New version available') +"\n\n"+ error.message;
-
-		if (error.code == 'criticalVersion')
-		{
-			alert (message)
-			reload = true;
-		}
-		else
-		{
-			reload = confirm (message);
-			this.skipVersion = true;
-		}
-
-		if (reload)
-			location.reload ();
-			
-		this.newVersionBlock = false;
-	}
-	
 	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu
 
 	,createMenu: function (res, sectionMap, parent, ul)
@@ -428,6 +354,23 @@ Vn.Gui = new Class
 
 		this.activeForm = new formInfo.klass (this, formInfo);
 		this.activeForm.open ();
+		
+	}
+	
+	,setForm: function (form)
+	{
+		Vn.Node.removeChilds (this.$('form-holder'));
+
+		if (form)
+		{
+			this.$('form-holder').appendChild (form);
+			setTimeout (this._onSetFormTimeout.bind (this), 0);
+		}
+	}
+	
+	,_onSetFormTimeout: function ()
+	{
+		Vn.Node.addClass (this.$('form-holder'), 'show');
 	}
 	
 	,setTitle: function (title)
@@ -450,6 +393,7 @@ Vn.Gui = new Class
 	{
 		if (this.activeForm)
 		{
+			Vn.Node.removeClass (this.$('form-holder'), 'show');
 			this.activeForm.close ();
 			this.activeForm.unref ();
 			this.activeForm = null;
diff --git a/web/js/hedera/gui.xml b/web/js/hedera/gui.xml
index c7536824..694232f4 100755
--- a/web/js/hedera/gui.xml
+++ b/web/js/hedera/gui.xml
@@ -1,5 +1,16 @@
 <vn>
 <div id="main" class="vn-gui">
+	<div id="top-bar" class="navbar">
+		<button id="menu-button" class="menu-button">
+			<img src="image/dark/menu.svg" alt="_Menu"/>
+		</button>
+		<button class="exit" on-click="onLogoutClick" title="_Exit">
+			<img src="image/dark/exit.svg" alt="_Exit"/>
+		</button>
+		<div id="action-bar" class="action-bar"/>
+		<div id="title" class="title"/>
+		<htk-spinner id="loader" class="loader dark"/>
+	</div>
 	<div id="left-panel" class="left-panel">
 		<div class="menu-overflow">
 			<div class="menu-header" id="menu-header">
@@ -31,20 +42,7 @@
 		</div>
 	</div>
 	<div class="body">
-		<div id="top-bar" class="top-bar">
-			<button id="menu-button" class="menu-button">
-				<img src="image/dark/menu.svg" alt="_Menu"/>
-			</button>
-			<button class="exit" on-click="onLogoutClick" title="_Exit">
-				<img src="image/dark/exit.svg" alt="_Exit"/>
-			</button>
-			<div id="action-bar" class="action-bar"/>
-			<div id="title" class="title"/>
-			<htk-spinner id="loader" class="loader dark"/>
-		</div>
-		<div class="content">
-			<div id="form-holder" class="form-holder"/>
-		</div>
+		<div id="form-holder" class="form-holder"/>
 	</div>
 	<div id="background" class="background"/>
 </div>
diff --git a/web/js/hedera/login.css b/web/js/hedera/login.css
index e44a06db..ab2ad192 100755
--- a/web/js/hedera/login.css
+++ b/web/js/hedera/login.css
@@ -1,60 +1,48 @@
 
-.vn-login,
-.vn-login label,
-.vn-login button,
-.vn-login input,
-.vn-login textarea,
-.vn-login p,
-.vn-login a
+body
 {
-	font-size: 1.1em;
-	font-weight: normal;
-/*	text-shadow: 0 0.2em 0.2em #AAA; */
+	overflow: auto;
+	height: 100%;
 }
 
-/* Header */
-
 .vn-login
 {
 	color: #333;
+	font-size: 1.2em;
+	font-weight: normal;
+	height: inherit;
 }
-.vn-login .header
+
+/* Navigation bar */
+
+.vn-login .navbar
 {
 	z-index: 10;
-	position: absolute;
+	position: fixed;
 	background-color: #333;
 	width: 100%;
 	height: 3.5em;
+	top: 0;
+	color: white;
 	
 }
-.vn-login .header div
+.vn-login .navbar div
 {
 	margin-top: 1em;
 	text-align: center;
 }
-.vn-login .header a
-{
-	color: white;
-}
 
 /* Body */
 
 .vn-login .body
 {
-	position: absolute;
-	top: 3.5em;
-	left: 0;
-	right: 0;
-	bottom: 0;
-/*	background-image: url("background.png");
-    background-repeat: repeat;
-*/
+	height: inherit;
+
 }
 .vn-login .column
 {
 	position: relative;
 	margin: 0 auto;
-	overflow: auto;
 	max-width: 40em;
 	height: 100%;
 	background-color: white;
@@ -66,7 +54,7 @@
 .vn-login .login
 {
 	position: absolute;
-	margin-top: -17em;
+	margin-top: -16em;
 	padding: 1em;
 	max-width: 45em;
 	top: 50%;
@@ -74,6 +62,20 @@
 	right: 0;
 	
 }
+@media (max-height: 700px)
+{
+	.vn-login
+	{
+		height: auto;
+	}
+	.vn-login .login
+	{
+		position: relative;
+		top: 0;
+		margin-top: 3.5em;
+		padding: 1.5em 1em;
+	}
+}
 .vn-login .logo img
 {
 	display: block;
@@ -87,25 +89,24 @@
 	text-align: right;
 	margin: 0.2em auto;
 	font-weight: bold;
-	height: 1.6em;
+	height: 1.4em;
 }
 .vn-login .form-inputs
 {
 	margin: 0 auto;
-	max-width: 16em;
+	max-width: 15em;
 }
 .vn-login label
 {
 	margin: 0;
 }
-.vn-login div.form-group label
+.vn-login .form-group label
 {
 	display: block;
+	font-size: inherit;
 }
 .vn-login input
 {
-	border-radius: 0.1em;
-	box-shadow: 0 0.1em 0.1em #AAA;
 	margin: 0.3em;
 }
 .vn-login input[type=text],
@@ -118,6 +119,13 @@
 	border: 1px solid #AAA;
 	height: 2.6em;
 }
+.vn-login input[type=text],
+.vn-login input[type=password],
+.vn-login input[type=submit]
+{
+	border-radius: 0.1em;
+	box-shadow: 0 0.1em 0.1em #AAA;
+}
 .vn-login td.entry
 {
 	text-align: left;
@@ -178,8 +186,14 @@
 	margin-top: 2em;
 	text-align: center;
 }
+.vn-login .links a
+{
+	display: inline-block;
+	margin: 0 .1em;
+}
 .vn-login .links img
 {
 	height: 1.8em;
+	width: 1.8em;
 }
 
diff --git a/web/js/hedera/login.js b/web/js/hedera/login.js
index b84e771b..a8c84f7d 100755
--- a/web/js/hedera/login.js
+++ b/web/js/hedera/login.js
@@ -56,7 +56,7 @@ Vn.Login = new Class
 	,show: function ()
 	{
 		document.body.appendChild (this.node);
-	
+
 		if (Vn.Cookie.check ('vn_user'))
 			this.$('user').value = Vn.Cookie.get ('vn_user');
 			
diff --git a/web/js/hedera/login.xml b/web/js/hedera/login.xml
index 338baf4f..4060adb1 100755
--- a/web/js/hedera/login.xml
+++ b/web/js/hedera/login.xml
@@ -1,6 +1,6 @@
 <vn>
 <div id="main" class="vn-login">
-	<div class="header">
+	<div class="navbar">
 		<div>
 		<a href="#!form=cms/about&amp;guest=true">
 			<t>I want to know more</t>
diff --git a/web/js/hedera/report.js b/web/js/hedera/report.js
index 4f881da8..e3a29b5b 100755
--- a/web/js/hedera/report.js
+++ b/web/js/hedera/report.js
@@ -64,10 +64,6 @@ Vn.Report = new Class
 		{
 			Htk.Toast.showError (
 				_('Please unlock popups and try again'));
-			
-			if (callback)
-				callback (null);
-
 			return false;
 		}
 		
diff --git a/web/js/hedera/style.css b/web/js/hedera/style.css
index f105eaff..5b0f0ed8 100755
--- a/web/js/hedera/style.css
+++ b/web/js/hedera/style.css
@@ -5,7 +5,11 @@
 {
 	body { font-size: 11pt; }
 }
-@media (min-resolution: 95dpi) and (max-resolution: 119dpi)
+@media (max-resolution: 119dpi) and (min-device-width: 1340px)
+{
+	body { font-size: 12pt; }
+}
+@media (max-resolution: 119dpi) and (min-device-width: 1900px)
 {
 	body { font-size: 13pt; }
 }
@@ -23,8 +27,8 @@
 body
 {
 	color: #333;
-	margin: 0;
 	font-family: 'Open Sans', 'Verdana', 'Sans';
+	margin: 0;
 }
 label,
 button,
@@ -35,13 +39,13 @@ option
 {
 	font-size: inherit;
 	font-family: inherit;
+	color: inherit;
 }
 iframe
 {
 	border: none;
 }
-fieldset,
-div
+fieldset
 {
 	margin: 0;
 }
@@ -58,7 +62,7 @@ a:link,
 a:visited,
 a:active
 {
-	color: #000;
+	color: inherit;
 	text-decoration: none;
 }
 a:hover
@@ -70,6 +74,10 @@ a img
 {
 	padding: 1px;
 }
+a img:hover
+{
+	opacity: 0.9;
+}
 h1, h2, h3, h4, h5, h6
 {
 	margin: 0;
@@ -90,7 +98,9 @@ p
 
 /* Focus outline */
 
-*:focus
+a:focus,
+input:focus,
+button:focus
 {
 	outline: 1px solid rgba(1, 1, 1, 0.15);
 	-moz-outline-radius: .1em;
@@ -104,7 +114,6 @@ input[type=reset]::-moz-focus-inner
 }
 select:-moz-focusring
 {
-	outline: none;
 /*	color: transparent;
     text-shadow: 0 0 0 #333;*/
 }
@@ -121,17 +130,18 @@ select,
 {
 	border: none;
 	border-bottom: 1px solid #999;
-	margin: .2em;
+	margin: .2em 0;
 	box-sizing: border-box;
 	color: #333;
-/*	border-radius: 0.1em;
-	border: .1em solid #CCD;
-	box-shadow: 0 0.1em 0.1em #CCC;*/
+	border-radius: 0;
+	text-align: left;
+	width: 100%;
 }
 input[type=text],
 input[type=password],
 input[type=number],
-textarea
+textarea,
+.input
 {
 	padding: 0 .2em;
 }
@@ -139,7 +149,8 @@ input[type=text],
 input[type=password],
 input[type=file],
 input[type=number],
-select
+select,
+.input
 {
 	height: 2.2em;
 }
@@ -152,7 +163,8 @@ input[type=text]:focus,
 input[type=password]:focus,
 input[type=file]:focus,
 input[type=number]:focus,
-textarea:focus
+textarea:focus,
+.input:focus
 {
 	border-color: #333;
 }
@@ -193,7 +205,6 @@ input[type=reset]
 {
 	border: none;
 	background-color: transparent;
-	color: white;
 	padding: 0.5em;
 	cursor: pointer;
 	border-radius: 0.1em;
@@ -233,15 +244,9 @@ input.button:disabled
 
 button.thin
 {
-	background-color: transparent;
-	border: none;
 	color: #008D77;
 	text-transform: uppercase;
 }
-button.thin:hover
-{
-	background-color: rgba(1,1,1,0.1);
-}
 button.thin:disabled
 {
 	color: gray;
diff --git a/web/js/htk/field/select.js b/web/js/htk/field/select.js
index 8efb36a2..c7ef024f 100755
--- a/web/js/htk/field/select.js
+++ b/web/js/htk/field/select.js
@@ -1,3 +1,4 @@
+
 Htk.Select = new Class
 ({
 	Extends: Htk.Field
@@ -13,7 +14,7 @@ Htk.Select = new Class
 			type: Db.Model
 			,set: function (x)
 			{
-				this.link ({_model: x}, {'status-changed': this._onModelChange});
+				this.link ({_model: x}, {'status-changed-after': this._onModelChange});
 				this._onModelChange ();
 			}
 			,get: function ()
@@ -76,9 +77,7 @@ Htk.Select = new Class
 			,set: function (x)
 			{
 				this._placeholder = x;
-
-				if (this._placeholderNode)
-					Vn.Node.setText (this._placeholderNode, x);
+				this._refreshShowText (x);
 			}
 			,get: function ()
 			{
@@ -113,15 +112,10 @@ Htk.Select = new Class
 
 	,initialize: function (props)
 	{
-		var select = this.createElement ('select');
-		select.addEventListener ('change', this._onChange.bind (this));
-		
-		// Webkit bug: Does not refresh select options
-		if (navigator.userAgent.match (/WebKit/))
-			select.addEventListener ('mousedown',
-				this._onWebkitMouseDown.bind (this));
-		
-		this._addPlaceholder (this._placeholder);
+		var button = this.createElement ('button');
+		button.className = 'htk-select input';
+		button.addEventListener ('mousedown', this._onButtonMouseDown.bind (this));
+
 		this.parent (props);
 	}
 
@@ -140,109 +134,104 @@ Htk.Select = new Class
 		}
 	}
 	
-	,setRow: function (row)
+	,_setRow: function (row)
 	{
-		if (row != -1)
-			this.node.selectedIndex = row + this.getIndexIncrement ();
-		else if (this._placeholder)
-			this.node.selectedIndex = 0;
-		else
-			this.node.selectedIndex = -1;
-	
 		this._row = row;
+		this._refreshShowText ();
 		this.iterChanged ();
 	}
 	
-	,_onChange: function (event)
+	,_onButtonMouseDown: function (e)
 	{
+		if (this._popup)
+		{
+			this._popup.hide ();
+			return;
+		}
+	
+		var model = this._model;
+
+		var menu = document.createElement ('div');
+		menu.className = 'htk-select-menu';
+		
+		var grid = new Htk.Grid ({showHeader: false});
+		menu.appendChild (grid.getNode ());
+		
+		var gridNode = grid.getNode ();
+		gridNode.addEventListener ('click', this._onGridClicked.bind (this, grid));
+		
+		var column = new Htk.ColumnText ({columnIndex: this.showColumnIndex});
+		grid.appendColumn (column);
+		grid.model = model;
+		
+		var popup = this._popup = new Htk.Popup ({childNode: menu});
+		popup.on ('closed', this._onPopupClose.bind (this));
+		popup.show (this.node);
+
+		this.signalEmit ('menu-show');
+		
+		e.stopPropagation ();
+	}
+	
+	,_onGridClicked: function (grid, e)
+	{
+		var target = e.target;
+		var parentNode = target.parentNode;
+		
+		while (parentNode !== grid.tbody)
+		{
+			target = parentNode;
+			parentNode = parentNode.parentNode;
+		}
+
 		var value;
-		var row = this.node.selectedIndex - this.getIndexIncrement ();
+		var row = target.rowIndex - 1;
 
 		if (row >= 0)
 			value = this._model.getByIndex (row, this.valueColumnIndex);
 		else
 			value = null;
 
-		this.setRow (row);
+		this._setRow (row);
 		this.valueChanged (value);
-	}
-	
-	,getIndexIncrement: function ()
-	{
-		var inc = 0;
-	
-		if (this._placeholder)
-			inc++;
-		if (!this._notNull)
-			inc++;
-			
-		return inc;
-	}
-	
-	,addOption: function (value, text)
-	{
-		var option = document.createElement ('option');
-		option.value = value;
+		this._popup.hide ();
 		
-		if (text)
-			option.appendChild (document.createTextNode (text));
-
-		this.node.appendChild (option);
+		e.stopPropagation ();
 	}
 	
-	,_addPlaceholder: function (text)
+	,_onPopupClose: function ()
 	{
-		var option = document.createElement ('option');
-		option.className = 'htk-option';
-		option.disabled = true;
-		option.selected = true;
-		option.value = null;
-		Vn.Node.setText (option, text ? text : '');
-		this.node.appendChild (option);
-		this._placeholderNode = option;
+		this._popup = null;
+		this.signalEmit ('menu-hide');
+	}
+	
+	,_refreshShowText: function ()
+	{
+		if (this._row !== -1)
+			var showText = this._model.getByIndex (this._row, this.showColumnIndex);
+		else if (this._placeholder)
+			var showText = this._placeholder;
+		else
+			var showText = '';
+
+		Vn.Node.setText (this.node, showText);
 	}
 	
 	,_onModelChange: function ()
 	{
-		var placeholder = null;
 		var model = this._model;
 		this.signalEmit ('status-changed');
-	
-		Vn.Node.removeChilds (this.node);
+		
+		if (this._popup)
+			this._popup.reset ();
 
-		switch (model.status)
-		{
-			case Db.Model.Status.ERROR:
-				placeholder = _('Error');
-				break;
-			case Db.Model.Status.LOADING:
-				placeholder = _('Loading...');
-				break;
-			default:
-				placeholder = this._placeholder;
-		}
-		
-		if (placeholder)
-			this._addPlaceholder (placeholder);
-		
 		if (model.ready)
 		{
-			var data = model.data;
-
-			if (!this.notNull)
-				this.addOption (null, null);
-
-			for (var i = 0; i < data.length; i++)
-				this.addOption (data[i][this.showColumnIndex], data[i][1]);
-			
-			this.selectOption ();
+			this._selectOption ();
 			this.signalEmit ('ready');
-			
 		}
 		else
-			this.setRow (-1);
-			
-		this._webkitRefreshOptions ();
+			this._setRow (-1);
 	}
 	
 	,setEditable: function (editable)
@@ -250,7 +239,7 @@ Htk.Select = new Class
 		this.node.disabled = !editable;
 	}
 
-	,selectOption: function ()
+	,_selectOption: function ()
 	{
 		var row;
 	
@@ -259,46 +248,11 @@ Htk.Select = new Class
 		else
 			row = -1;
 
-		this.setRow (row);
+		this._setRow (row);
 	}
 
 	,putValue: function (value)
 	{
-		this.selectOption ();
-	}
-	
-	// Webkit bug: Does not refresh select options
-	
-	,_webkitRefreshOptions: function ()
-	{
-		if (document.activeElement === this.node && this._webkitRefresh)
-		{
-			if (this._model.ready)			
-				this._webkitRefresh = false;
-		
-			this.node.blur();
-			this.node.focus ();
-			setTimeout (this._onWebkitTimeout.bind (this), 0);
-		}
-	}
-	
-	,_onWebkitMouseDown: function ()
-	{
-		if (this._webkitBlock)
-			return;
-	
-		this._webkitRefresh = true;
-	}
-	
-	,_onWebkitTimeout: function ()
-	{
-		this._webkitBlock = true;
-
-		var e = document.createEvent('MouseEvents');
-		e.initMouseEvent ('mousedown',
-			true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
-		this.node.dispatchEvent(e);
-
-		this._webkitBlock = false;
+		this._selectOption ();
 	}
 });
diff --git a/web/js/htk/popup.js b/web/js/htk/popup.js
index 3c31c9af..6261c963 100755
--- a/web/js/htk/popup.js
+++ b/web/js/htk/popup.js
@@ -5,8 +5,61 @@ Htk.Popup = new Class
 ({
 	Extends: Htk.Widget
 	,Tag: 'htk-popup'
+	,Properties:
+	{
+		/**
+		 * The popup child.
+		 **/
+		child:
+		{ 
+			type: Htk.Widget
+			,set: function (x)
+			{
+				this._child = x;
+				this.setChildNode (x.getNode ());
+			}
+			,get: function ()
+			{
+				return this._child;
+			}
+		}
+		/**
+		 * The popup child Node.
+		 **/
+		,childNode:
+		{ 
+			type: Object
+			,set: function (x)
+			{
+				this._child = null;
+				this.setChildNode (x);
+			}
+			,get: function ()
+			{
+				return this.node.firstChild;
+			}
+		}
+		/**
+		 * Indicates how the dialog must be displayed.
+		 **/
+		,modal:
+		{ 
+			type: Boolean
+			,set: function (x)
+			{
+				this._modal = x;
+			}
+			,get: function ()
+			{
+				return this._modal;
+			}
+		}
+	}
 
 	,_parent: null
+	,_modal: false
+	,_isOpen: false
+	,_child: null
 
 	,initialize: function (props)
 	{
@@ -29,78 +82,126 @@ Htk.Popup = new Class
 
 	,show: function (parent)
 	{
-		document.body.appendChild (this.node);
-		
-		this.node.addEventListener ('mousedown', this.stopEvent);
-		
-		this.hideHandler = this.hide.bind (this);
-		document.addEventListener ('mousedown', this.hideHandler);
-		
 		this._parent = parent;
+		this.open ();
+	}
+
+	,isModal: function ()
+	{
+		return this._modal || Vn.isMobile ();
+	}
+	
+	,open: function ()
+	{
+		this.node.addEventListener ('mousedown', this._stopEvent);
+
+		this._hideHandler = this.hide.bind (this);
+		document.addEventListener ('mousedown', this._hideHandler);
+
+		if (this.isModal ())
+		{
+			this._background = document.createElement ('div');
+			this._background.className = 'htk-background';
+			document.body.appendChild (this._background);
+
+			setTimeout (this._onOpacityTimeout.bind (this), 0);
+
+			Vn.Node.addClass (this.node, 'modal');
+		}
+		
+		this._isOpen = true;
+		document.body.appendChild (this.node);
+		this.reset ();
+		setTimeout (this._onResetTimeout.bind (this), 200);
+	}
+	
+	,_onOpacityTimeout: function ()
+	{
+		if (this._background)
+			this._background.style.opacity = 1;
+	}
+
+	,_onResetTimeout: function ()
+	{
 		this.reset ();
 	}
 	
 	,reset: function ()
 	{
-		if (!this._parent)
+		if (!this._isOpen)
 			return;
-	
-		var spacing = 5;
-		var rect = this._parent.getBoundingClientRect ();
-		var left = rect.left;
-		var top = rect.top + spacing + this._parent.offsetHeight;
 
+		var margin = 20;
+		var dblMargin = margin * 2;
 		var width = this.node.offsetWidth;
 		var height = this.node.offsetHeight;
+		var innerWidth = Vn.Browser.getInnerWidth ();
+		var innerHeight = Vn.Browser.getInnerHeight ();
+		var style = this.node.style;
 
-		if (left + width > Vn.Browser.getInnerWidth ())
-			left -= width - this._parent.offsetWidth;
-		if (top + height > Vn.Browser.getInnerHeight ())
-			top -= height + this._parent.offsetHeight + spacing * 2;
-
-		if (left < 0)
-			left = 0;
-		if (top < 0)
-			top = 0;	
+		if (width + dblMargin > innerWidth)
+		{
+			width = innerWidth - dblMargin;
+			style.width = width +'px';
+		}
+		if (height + dblMargin > innerHeight)
+		{
+			height = innerHeight - dblMargin;
+			style.height = height +'px';
+		}
 		
-		this.node.style.top = (top) +'px';
-		this.node.style.left = (left) +'px';
-	}
-	
-	,showCenter: function ()
-	{
-		this._parent = null;
-	
-		this.background = document.createElement ('div');
-		this.background.className = 'htk-background';
-		document.body.appendChild (this.background);
-	
-		document.body.appendChild (this.node);
-		
-		var width = this.node.offsetWidth;
-		var height = this.node.offsetHeight;
+		if (this.isModal ())
+		{
+			style.top = '50%';
+			style.left = '50%';
 
-		this.node.style.top = '50%';
-		this.node.style.left = '50%';
-		this.node.style.marginLeft = (-this.node.offsetWidth / 2) +'px';
-		this.node.style.marginTop =  (-this.node.offsetHeight / 2) +'px';
+			style.marginLeft = (-this.node.offsetWidth / 2) +'px';
+			style.marginTop =  (-this.node.offsetHeight / 2) +'px';
+		}
+		else
+		{
+			var spacing = 4;
+			var rect = this._parent.getBoundingClientRect ();
+			var left = rect.left;
+			var top = rect.top + spacing + this._parent.offsetHeight;
 
+			if (left + width > innerWidth)
+				left -= (left + width) - Vn.Browser.getInnerWidth () + margin;
+			if (top + height > innerHeight)
+				top -= height + this._parent.offsetHeight + spacing * 2;
+
+			if (left < 0)
+				left = margin;
+			if (top < 0)
+				top = margin;
+
+			style.top = (top) +'px';
+			style.left = (left) +'px';
+		}
 	}
 
 	,hide: function ()
 	{
-		if (this.background)		
-			Vn.Node.remove (this.background);
+		if (!this._isOpen)
+			return;
+
+		if (this._background)		
+		{
+			Vn.Node.remove (this._background);
+			Vn.Node.removeClass (this.node, 'modal');
+		}
 	
-		this.node.removeEventListener ('mousedown', this.stopEvent)
-		document.removeEventListener ('mousedown', this.hideHandler);
+		this.node.removeEventListener ('mousedown', this._stopEvent)
+		document.removeEventListener ('mousedown', this._hideHandler);
 		Vn.Node.remove (this.node);
 		this._parent = null;
+		this._isOpen = false;
 		this.signalEmit ('closed');
 	}
 	
-	,stopEvent: function (event)
+	,_stopEvent: function (e)
 	{
-		event.stopPropagation ();
+		e.stopPropagation ();
 	}
 });
+
diff --git a/web/js/htk/style.css b/web/js/htk/style.css
index 05051635..5da8cf9a 100755
--- a/web/js/htk/style.css
+++ b/web/js/htk/style.css
@@ -132,11 +132,41 @@ td.cell-image img
 	margin: auto;
 }
 
-/* Combo */
+/* Select */
 
-.htk-option
+.htk-select
 {
-/*	color: #999;*/
+	width: 100%;
+	height: 2em;
+	text-align: left;
+}
+.htk-select-menu
+{
+	height: 100%;
+	max-height: 80em;
+	overflow: auto;
+	min-width: 14em;
+}
+.htk-select-menu tbody > tr
+{
+	border-top: none;
+	height: 2.5em;
+}
+.htk-select-menu td.message
+{
+	padding: 1em;
+}
+.htk-select-menu tr:hover
+{
+	background-color: rgba(1, 1, 1, 0.1);
+	cursor: pointer;
+}
+.htk-select-menu td
+{
+	max-width: 11em;
+	overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
 }
 
 /* Button */
@@ -248,17 +278,6 @@ td.cell-image img
 	color: white;
 }
 
-/* Date chooser */
-
-.htk-date-chooser > button
-{
-	margin: 0;
-	text-align: left;
-	width: 100%;
-	padding: .4em .2em;
-	border-radius: 0;
-}
-
 /* Image */
 
 .htk-image.editable:hover
@@ -342,8 +361,18 @@ td.cell-image img
 	position: fixed;
 	background-color: white;
 	border-radius: 0.1em;
-	box-shadow: 0 0 0.4em #666;
+	box-shadow: 0 0 0.4em rgba(1, 1, 1, 0.6);
+	box-sizing: content-box;
 }
+.htk-popup > *
+{
+	border-radius: 0.1em;
+}
+.htk-popup.modal
+{
+	font-size: 1.2em;
+}
+
 .htk-background
 {
 	position: fixed;
@@ -353,6 +382,8 @@ td.cell-image img
 	bottom: 0;
 	z-index: 190;
 	background-color: rgba(1, 1, 1, 0.7);
+	opacity: 0;
+	transition: opacity 200ms ease-in-out;
 }
 
 /* Image editor */