0
1
Fork 0

Widget imagenes mejorado

This commit is contained in:
Juan Ferrer Toribio 2016-05-02 15:05:49 +02:00
parent 680eb9264a
commit 7e5a0bab06
39 changed files with 335 additions and 549 deletions

View File

@ -8,11 +8,11 @@ require_once (__DIR__.'/../vn-image/configure.php');
set_include_path
(
get_include_path ()
.PATH_SEPARATOR.__DIR__.'/lib'
.PATH_SEPARATOR.__DIR__
);
const _DEVELOPER_MODE = TRUE;
const _CONFIG_DIR = '/home/juan/.config/hedera-web';
const _CONFIG_DIR = '/home/juan/.config';
const _LOG_DIR = '/tmp';
?>

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
hedera-web (1.326-deb8) stable; urgency=low
hedera-web (1.328-deb8) stable; urgency=low
* Initial Release.

2
debian/install vendored
View File

@ -1,4 +1,4 @@
debian/conf/* etc/hedera-web
lib/* usr/share/php
vn usr/share/php
doc/* usr/share/doc/hedera-web
web/* usr/share/hedera-web

View File

@ -4,7 +4,7 @@ namespace Vn\Hedera;
if (!defined (__NAMESPACE__.'\_DEVELOPER_MODE'))
{
define (__NAMESPACE__.'\_CONFIG_DIR', '/etc/hedera-web');
define (__NAMESPACE__.'\_CONFIG_DIR', '/etc');
define (__NAMESPACE__.'\_LOG_DIR', '/var/log');
}

View File

@ -122,13 +122,14 @@ class Web
if (self::$confIncluded)
return;
$customFile = _CONFIG_DIR .'/config.my.php';
$configDir = _CONFIG_DIR .'/hedera-web';
$customFile = "$configDir/config.my.php";
if (!empty ($_SERVER['SERVER_NAME'])
&& preg_match ('/^[\w\-\.]+$/', $_SERVER['SERVER_NAME']))
{
$hostSplit = explode ('.', $_SERVER['SERVER_NAME']);
$hostFile = _CONFIG_DIR .'/config.'. $hostSplit[0] .'.php';
$hostFile = "$configDir/config.{$hostSplit[0]}.php";
}
if (isset ($hostFile) && file_exists ($hostFile))
@ -136,7 +137,7 @@ class Web
elseif (file_exists ($customFile))
$confFile = $customFile;
else
$confFile = _CONFIG_DIR .'/config.php';
$confFile = "$configDir/config.php";
$conf = require ($confFile);
self::$confIncluded = TRUE;

View File

@ -19,7 +19,7 @@ class Tpv
{
global $conf;
$conf = require (Hedera\_CONFIG_DIR .'/config.my.php');
$conf = require (Hedera\_CONFIG_DIR .'/hedera-web/config.my.php');
openlog ('hedera-web', LOG_ODELAY, LOG_LOCAL0);

View File

@ -13,8 +13,4 @@
margin: 0 auto;
max-width: 25em;
}
.address .form-group
{
padding: 0.4em;
}

View File

@ -13,10 +13,6 @@
margin: 0 auto;
max-width: 25em;
}
.conf .form-group
{
padding: 0.4em;
}
.conf .form-group input[type=password]
{
margin-bottom: 0.5em;

View File

@ -20,13 +20,13 @@
{
background-color: rgba(1, 1, 1, 0.05);
}
.cpanel .item > img
.cpanel .item > .htk-image
{
margin: .2em 0;
margin: 0;
margin-right: 1em;
float: left;
max-height: 3em;
max-width: 3em;
max-height: 2.8em;
max-width: 2.8em;
}
.cpanel .item > p
{

View File

@ -34,7 +34,13 @@
<htk-html form="new" column="text"/>
</div>
</div>
<htk-image directory="news/full" form="new" column="image" editable="false"/>
<htk-image
directory="news"
subdir="full"
form="new"
column="image"
editable="false"
full-dir="full"/>
</div>
</div>
</custom>

View File

@ -263,21 +263,17 @@
overflow: visible;
border-bottom: 1px solid #DDD;
}
.list-view .item-box > .image
.list-view .item-box > .htk-image
{
margin: 1em;
width: 3.5em;
height: 3.5em;
float: left;
border-radius: 50%;
overflow: hidden;
}
.list-view .item-box > .image > img
.list-view .item-box > .htk-image > img
{
max-width: 100%;
height: 100%;
display: block;
margin: 0 auto;
border-radius: 50%;
}
.list-view .item-info
{
@ -337,19 +333,12 @@
height: 10em;
overflow: hidden;
}
.grid-view .item-box > .image
.grid-view .item-box > .htk-image
{
width: 10em;
height: 100%;
float: left;
}
.grid-view .item-box > .image > img
{
max-width: 100%;
height: 100%;
display: block;
margin: 0 auto;
}
.grid-view .item-info
{
position: absolute;

View File

@ -126,16 +126,13 @@
model="items-model">
<custom>
<div class="box item-box">
<div class="image">
<htk-image
directory="catalog"
subdir="200x200"
form="item"
column="Foto"
show-full="true"
full-dir="900x900"
editable="true"/>
</div>
<htk-image
directory="catalog"
subdir="200x200"
form="item"
column="Foto"
full-dir="900x900"
editable="true"/>
<div class="item-info">
<htk-button
form="item"

View File

@ -30,15 +30,8 @@
{
float: left;
margin-right: 1em;
height: 5em;
width: 5em;
}
.news .item > .photo > img
{
display: block;
margin: 0 auto;
height: 100%;
max-width: 100%;
height: 4.2em;
width: 4.2em;
border-radius: .3em;
}
.news .item > button

View File

@ -34,15 +34,14 @@
tip="_Remove"
image="image/delete.svg"
on-click="onDeleteClick"/>
<div class="photo">
<htk-image
form="iter"
column="image"
class="photo"
directory="news"
subdir="200x200"
editable="true"/>
</div>
<htk-image
form="iter"
column="image"
class="photo"
directory="news"
subdir="200x200"
full-dir="full"
editable="true"/>
<p class="important">
<htk-text form="iter" column="title"/>
</p>

View File

@ -282,11 +282,17 @@ input.button:disabled
/* Thin button */
input[type=submit].thin,
input[type=button].thin,
input[type=reset].thin,
button.thin
{
color: #008D77;
text-transform: uppercase;
}
input[type=submit].thin:disabled,
input[type=button].thin:disabled,
input[type=reset].thin:disabled,
button.thin:disabled
{
color: gray;
@ -310,7 +316,7 @@ img.editable
.clear
{
clear: both;
clear: both !important;
}
/* Box */
@ -349,16 +355,18 @@ img.editable
{
margin: 0 auto;
}
.form-group
{
padding: 0.4em;
margin-bottom: 1.2em;
}
.form-group:last-child
{
margin-bottom: 0;
}
.form-group > label
{
display: block;
margin: 0;
margin-top: .5em;
margin-bottom: .2em;
font-size: .9em;
color: #222;

View File

@ -10,181 +10,43 @@ Htk.ColumnImage = new Class
directory:
{
type: String
,set: function (x)
{
this._directory = x;
this._basedir = Vn.Config['image_dir'] +'/'+ x;
}
,get: function ()
{
return this._directory;
}
,value: null
},
/**
* The directory where the images are allocated.
* The subdirectory where the images are allocated.
**/
subdir:
{
type: String
,value: null
},
/**
* Whether to show the full image when mouse hover.
**/
showFull:
{
type: Boolean
,value: false
},
/**
* Subdirectory where full images are allocated.
**/
fullDir:
{
type: String
,set: function (x)
{
this._fullDir = x;
}
,get: function ()
{
return this._fullDir;
}
,value: null
}
}
,_directory: null
,_basedir: null
,initialize: function (props)
{
this._cssClass = 'cell-image';
this._fullImage = new Htk.FullImage ();
this.parent (props);
}
,render: function (tr)
{
var image = new Htk.Image ({
directory: this.directory
,subdir: this.subdir
,fullDir: this.fullDir
,value: this.value
});
var td = this.parent (tr);
var img = document.createElement ('img');
img.alt = ''
td.appendChild (img);
var cell =
{
img: img
,value: this.value
,tr: tr
,error: false
,stamp: null
};
this._setSrc (cell);
if (this.showFull)
{
img.addEventListener ('mouseover', this._onMouseOver.bind (this, cell));
img.addEventListener ('mouseout', this._onMouseOut.bind (this));
}
if (this.editable)
{
img.className = 'editable';
img.addEventListener ('dblclick', this._onDoubleClick.bind (this, cell));
img.addEventListener ('error', this._onImageError.bind (this, cell));
}
td.appendChild (image.getNode ());
return td;
}
,_setSrc: function (cell)
{
if (cell.value)
{
var url = this._basedir +'/';
if (this.subdir)
url += this.subdir +'/';
url += cell.value;
if (cell.stamp)
url += '?'+ cell.stamp;
cell.img.src = url;
}
else
this._onImageError (cell);
}
,_onImageError: function (cell)
{
if (!cell.error)
{
cell.error = true;
cell.img.src = 'image/unknown.svg';
}
}
,_onMouseOver: function (cell)
{
if (cell.error)
return;
var src = this._fullDir ? this._fullDir : 'full';
src += '/'+ cell.value;
if (cell.stamp)
src += '?'+ cell.stamp;
this._fullImage.show (this._basedir +'/'+ src);
}
,_onMouseOut: function ()
{
this._fullImage.hide ();
}
,_onDoubleClick: function (cell)
{
var editor = new Htk.ImageEditor ();
editor.setData (cell.value, this._directory);
this.nameChangedHandler = this._onNameChange.bind (this, cell);
editor.on ('name-changed', this.nameChangedHandler);
this.fileUploadedHandler = this._onFileUpload.bind (this, cell);
editor.on ('file-uploaded', this.fileUploadedHandler);
this.editorClosedHandler = this._onEditorClose.bind (this);
editor.on ('closed', this.editorClosedHandler);
this.popup = new Htk.Popup
({
modal: true,
child: editor
});
this.popup.show (cell.img);
}
,_onNameChange: function (cell, editor, value)
{
cell.value = value;
this._setSrc (cell);
this.changed (cell.tr, value);
}
,_onFileUpload: function (cell, editor)
{
cell.stamp = new Date ().getTime ();
this._setSrc (cell);
this.popup.hide ();
}
,_onEditorClose: function (editor)
{
editor.disconnect ('name-changed', this.nameChangedHandler);
editor.disconnect ('file-uploaded', this.fileUploadedHandler);
editor.disconnect ('closed', this.editorClosedHandler);
}
});

View File

@ -18,8 +18,7 @@ Htk.Image = new Class
,set: function (x)
{
this._directory = x;
this._basedir = Vn.Config['image_dir'] +'/'+ x;
this._setSrc ();
this._refreshSrc ();
}
,get: function ()
{
@ -27,7 +26,7 @@ Htk.Image = new Class
}
},
/**
* The directory where the images are allocated.
* The subdirectory where the images are allocated.
**/
subdir:
{
@ -35,7 +34,7 @@ Htk.Image = new Class
,set: function (x)
{
this._subdir = x;
this._setSrc ();
this._refreshSrc ();
}
,get: function ()
{
@ -45,36 +44,13 @@ Htk.Image = new Class
/**
* Whether to show the full image when mouse hover.
**/
showFull:
{
type: Boolean
,set: function (x)
{
if (x && !this._fullImage)
{
if (!fullImage)
fullImage = new Htk.FullImage ();
this._fullImage = fullImage;
this.node.addEventListener ('click', this._onMouseClick.bind (this));
}
this._showFull = x;
}
,get: function ()
{
return this._showFull;
}
},
/**
* Subdirectory where full images are allocated.
**/
fullDir:
{
type: String
,set: function (x)
{
{
this._fullDir = x;
this._refreshClick ();
}
,get: function ()
{
@ -85,100 +61,123 @@ Htk.Image = new Class
,_directory: null
,_subdir: null
,_basedir: null
,_error: false
,_showFull: false
,_fullDir: null
,_error: false
,_editable: false
,initialize: function (props)
,_createNode: function ()
{
this.createElement ('img');
this.node.className = 'htk-image';
this.node.addEventListener ('error', this._onImageError.bind (this));
this.setEditable (this._editable);
this.parent (props);
}
,setEditable: function (editable)
{
if (editable)
{
Vn.Node.addClass (this.node, 'editable');
this.node.addEventListener ('dblclick', this._onDoubleClick.bind (this));
}
else
Vn.Node.removeClass (this.node, 'editable');
this._setEmpty ();
}
,_setSrc: function ()
{
if (this._value)
{
var url = '';
var node = this.createElement ('div');
node.className = 'htk-image';
if (this._basedir)
url += this._basedir +'/';
if (this._subdir)
url += this._subdir +'/';
url += this._value;
if (this._stamp)
url += '?'+ this._stamp;
this._error = false;
this.node.src = url;
this.node.style.display = '';
}
else
this._setEmpty ();
var img = this.img = document.createElement ('img');
img.addEventListener ('error', this._onImageError.bind (this));
node.appendChild (img);
this.setEditable ();
this._refreshClick ();
this._refreshSrc ();
}
,_setEmpty: function ()
,_refreshClick: function ()
{
if (this._value !== null && this._value !== '')
if (!this.node)
return;
if (this.clickHandler)
{
Vn.Node.removeClass (this.node, 'clickable');
this.node.removeEventListener ('click', this.clickHandler);
this.clickHander = null;
}
if (this._fullDir)
{
this.clickHandler = this._onClick.bind (this);
this.node.addEventListener ('click', this.clickHandler);
Vn.Node.addClass (this.node, 'clickable');
}
}
,setEditable: function ()
{
if (!this.node)
return;
if (this.editButton)
{
this.node.removeChild (this.editButton);
this.editButton = null;
}
if (this._editable)
this.node.src = 'image/add-photo.svg';
else
delete this.node.src;
}
{
var button = document.createElement ('button');
button.addEventListener ('click', this._onEditClick.bind (this));
button.title = _('UpdateImage');
this.node.appendChild (button);
var img = document.createElement ('img');
img.src = 'image/add-photo.svg';
button.appendChild (img);
,putValue: function (value)
{
this._setSrc ();
this.editButton = button;
}
}
,_onMouseClick: function ()
{
if (!this._showFull || !this._value || this._error)
return;
var src = this._fullDir ? this._fullDir : 'full';
src += '/'+ this._value;
,_makeSrc: function (subdir)
{
var src = Vn.Config['image_dir'] +'/';
if (this._directory)
src += this._directory +'/';
if (subdir)
src += subdir +'/';
src += this._value;
if (this._stamp)
src += '?'+ this._stamp;
this._fullImage.show (this._basedir +'/'+ src);
return src;
}
,_refreshSrc: function ()
{
if (!this.node)
return;
if (this._value)
{
this._error = false;
this.img.src = this._makeSrc (this._subdir);
}
else
delete this.img.src;
}
,putValue: function (value)
{
this._refreshSrc ();
}
,_onImageError: function ()
{
if (this._error)
return;
this._error = true;
}
,_onDoubleClick: function ()
,_onClick: function ()
{
if (!this._fullDir || !this._value || this._error)
return;
(new Htk.FullImage ()).show (this._makeSrc (this._fullDir));
}
,_onEditClick: function (event)
{
event.stopPropagation ();
var editor = new Htk.ImageEditor ();
editor.setData (this.value, this._directory);
editor.on ('name-changed', this._onNameChange, this);

View File

@ -2,75 +2,52 @@
Htk.FullImage = new Class
({
Extends: Vn.Object
,img: null
,timeout: 0
,loading: false
,visible: false
,hideCalled: false
,closed: false
,initialize: function (props)
,Properties:
{
var div = document.createElement ('div');
div.className = 'htk-full-image';
div.addEventListener ('mouseover', this.cancelHide.bind (this));
div.addEventListener ('mouseout', this.hideNow.bind (this));
var loadingBox = document.createElement ('div');
loadingBox.className = 'htk-full-image-loader';
/**
* Subdirectory where full images are allocated.
**/
fullDir:
{
type: String
,set: function (x)
{
this._fullDir = x;
}
,get: function ()
{
return this._fullDir;
}
}
}
var spinner = new Htk.Spinner ();
loadingBox.appendChild (spinner.getNode ());
this.div = div;
this.loadingBox = loadingBox;
this.spinner = spinner;
this.parent (props);
}
,getLeft: function (width)
{
return parseInt ((Vn.Browser.getInnerWidth () - width) / 2) +'px';
}
,getTop: function (height)
{
return parseInt ((Vn.Browser.getInnerHeight () - height) / 2) +'px';
}
,show: function (src)
{
if (this.closed && this.src == src)
{
var popup = new Htk.Popup ({class: 'htk-full-image', modal: true});
var img = document.createElement ('img');
img.className = 'htk-full-image';
img.addEventListener ('click', this._onImageClick.bind (this, popup));
//img.addEventListener ('error', this._onImageError.bind (this, popup));
img.src = src;
if (!img.complete)
{
this.closed = false;
return;
}
this.cancelHide ();
this.closed = false;
this.src = src
this.img = document.createElement ('img');
this.img.src = src;
this.img.addEventListener ('load', this.imageLoaded.bind (this, this.img));
this.img.addEventListener ('error', this.hideLoading.bind (this));
if (!this.img.complete && !this.loading)
{
document.body.appendChild (this.loadingBox);
this.spinner.start ();
this.loading = true;
img.addEventListener ('load', this._onImageLoad.bind (this, popup, img));
var spinner = new Htk.Spinner ();
spinner.start ();
popup.child = spinner;
}
else
this._onImageLoad (popup, img);
popup.open ();
}
,imageLoaded: function (img)
{
if (img != this.img || this.hideCalled)
return;
var scale = 1.0;
,_onImageLoad: function (popup, img)
{
var scale = null;
var width = img.width;
var height = img.height;
var innerWidth = Vn.Browser.getInnerWidth () - 50;
@ -89,82 +66,21 @@ Htk.FullImage = new Class
height = innerHeight;
}
this.hideLoading ();
this.div.style.left = this.getLeft (width + 2);
this.div.style.top = this.getTop (height + 2);
this.div.style.width = width +'px';
this.div.style.height = height +'px';
if (scale !== 1.0)
if (scale !== null)
{
img.style.width = width +'px';
img.style.height = height +'px';
}
if (this.div.firstChild != null)
this.div.replaceChild (img, this.div.firstChild);
else
this.div.appendChild (img);
img.addEventListener ('click', this.onImageClick.bind (this));
if (!this.visible)
{
document.body.appendChild (this.div);
this.visible = true;
this.onDocumentClickCallback = this.hideNow.bind (this);
document.addEventListener ('click', this.onDocumentClickCallback);
}
}
,onImageClick: function ()
{
this.closed = true;
}
,hide: function ()
{
this.hideCalled = true;
this.hideLoading ();
if (this.visible)
this.timeout = setTimeout (this.hideNow.bind (this), 450);
popup.childNode = img;
popup.reset ();
}
,hideNow: function ()
,_onImageClick: function (popup)
{
if (this.visible)
{
document.body.removeChild (this.div);
this.hideCalled = true;
this.visible = false;
this.timeout = 0;
}
document.removeEventListener ('click', this.onDocumentClickCallback);
this.onDocumentClickCallback = null;
popup.hide ();
}
,cancelHide: function ()
{
if (this.timeout)
{
clearTimeout (this.timeout);
this.timeout = 0;
}
this.hideCalled = false;
}
,hideLoading: function ()
{
if (this.loading)
{
document.body.removeChild (this.loadingBox);
this.spinner.stop ();
this.loading = false;
}
}
,_onImageError: function (popup) {}
});

View File

@ -34,13 +34,13 @@ Htk.ImageEditor = new Class
,onFormSubmit: function ()
{
this.$('submit').disabled = true;
this.$('loader').style.visibility = 'visible';
this.$('spinner').start ();
}
,onIframeLoad: function ()
{
this.$('submit').disabled = false;
this.$('loader').style.visibility = 'hidden';
this.$('spinner').stop ();
try {
var responseText = this.$('iframe').contentDocument.body.textContent;

View File

@ -1,6 +1,5 @@
<vn>
<div id="main" class="htk-image-editor">
<h2><t>UpdateImage</t></h2>
<form
id="form"
method="post"
@ -16,8 +15,9 @@
<input id="file" type="file" name="image"/>
</div>
<div class="footer">
<img id="loader" src="image/loader-black.gif" alt="Loading"/>
<input id="submit" type="submit" class="button"/>
<input id="submit" type="submit" class="thin"/>
<htk-spinner id="spinner"/>
<div class="clear"/>
</div>
<input id="schema" type="hidden" name="schema"/>
<input id="max-size" type="hidden" name="MAX_FILE_SIZE"/>

View File

@ -93,6 +93,12 @@ Htk.Popup = new Class
,open: function ()
{
if (this._isOpen)
{
this.reset ();
return;
}
this.node.addEventListener ('mousedown', this._stopEvent);
this._hideHandler = this.hide.bind (this);

View File

@ -2,6 +2,8 @@ Htk.Spinner = new Class
({
Extends: Htk.Widget
,Tag: 'htk-spinner'
,_started: false
,initialize: function (props)
{
@ -17,11 +19,19 @@ Htk.Spinner = new Class
,start: function ()
{
Vn.Node.addClass (this.spin, 'spinner');
if (!this._started)
{
Vn.Node.addClass (this.spin, 'spinner');
this._started = true;
}
}
,stop: function ()
{
Vn.Node.removeClass (this.spin, 'spinner');
if (this._started)
{
Vn.Node.removeClass (this.spin, 'spinner');
this._started = false;
}
}
});

View File

@ -124,7 +124,7 @@ td.cell-image
{
text-align: center;
}
td.cell-image img
td.cell-image .htk-image
{
max-width: 2.5em;
max-height: 2.5em;
@ -280,38 +280,96 @@ td.cell-image img
/* Image */
.htk-image.editable:hover
.htk-image
{
position: relative;
overflow: hidden;
}
.htk-image.clickable:hover
{
cursor: pointer;
opacity: 0.85;
}
.htk-image > img
{
display: block;
height: 100%;
width: 100%;
}
.htk-image > button
{
position: absolute;
top: 0;
left: 0;
margin: 0;
padding: .15em;
display: none;
}
.htk-image:hover > button
{
display: block;
}
.htk-image > button > img
{
display: block;
height: 1.2em;
height: 1.2em;
}
/* Full image */
.htk-full-image
.htk-full-image img
{
z-index: 100;
position: fixed;
background-color: #FFF;
text-align: center;
box-shadow: 0 0 0.4em #666;
border-radius: .2em;
overflow: hidden;
display: block;
cursor: pointer;
}
.htk-full-image-loader
.htk-full-image .htk-spinner
{
z-index: 110;
position: fixed;
top: 50%;
left: 50%;
margin-top: -1.6em;
margin-left: -1.6em;
background-color: #FFF;
padding: .7em;
box-shadow: 0 0 0.4em #666;
height: 1.8em;
border-radius: 50%;
overflow: hidden;
margin: .6em;
display: block;
}
/* Image editor */
.htk-image-editor
{
width: 20em;
margin: 0 auto;
}
.htk-image-editor h2
{
color: white;
background-color: #009688;
text-align: left;
font-size: 1.3em;
line-height: 1.7em;
font-weight: normal;
padding: 0.6em 0.8em;
margin: 0;
}
.htk-image-editor iframe
{
display: none;
}
.htk-image-editor form
{
padding: 1.5em;
}
.htk-image-editor .footer
{
margin-top: 2em;
}
.htk-image-editor .footer > .htk-spinner
{
padding-right: 1.2em;
height: 1.3em;
width: 1.3em;
}
.htk-image-editor .footer > .htk-spinner,
.htk-image-editor .footer > input
{
float: right;
}
/* Toast */
@ -388,64 +446,6 @@ td.cell-image img
transition: opacity 200ms ease-in-out;
}
/* Image editor */
.htk-image-editor
{
width: 20em;
margin: 0 auto;
}
.htk-image-editor h2
{
color: white;
background-color: #009688;
text-align: left;
font-size: 1.3em;
line-height: 1.7em;
font-weight: normal;
padding: 0.6em 0.8em;
margin: 0;
}
.htk-image-editor iframe
{
display: none;
}
.htk-image-editor form
{
padding: 1.5em;
}
.htk-image-editor .form-group
{
margin-bottom: 0.5em;
}
.htk-image-editor .form-group label
{
display: block;
margin-bottom: 0.3em;
}
.htk-image-editor .form-group input
{
width: 95%;
height: 1.8em;
}
.htk-image-editor .footer
{
margin-top: 1em;
text-align: center;
}
.htk-image-editor .footer img
{
visibility: hidden;
vertical-align: middle;
padding-right: 1em;
}
.htk-image-editor .footer input
{
display: inline;
margin-left: 0.5em;
margin-right: 0.5em;
}
/* Assistant */
.htk-assistant > div
@ -549,26 +549,18 @@ td.cell-image img
.htk-spinner
{
width: 1.8em;
height: 1.8em;
position: relative;
display: inline-block;
box-sizing: border-box;
}
.htk-spinner > .spinner
{
width: 1.8em;
height: 1.8em;
}
.htk-spinner > .spinner:before
{
content: 'Loading…';
position: absolute;
left: 0;
width: 1.2em;
height: 1.2em;
}
.htk-spinner > .spinner:not(:required):before
{
content: '';
position: absolute;
width: inherit;
height: inherit;
box-sizing: border-box;
border-radius: 50%;
border: .3em solid transparent;
border-top-color: #666;
@ -576,7 +568,7 @@ td.cell-image img
animation: spinner 1s linear infinite;
-webkit-animation: spinner 1s linear infinite;
}
.htk-spinner.dark > .spinner:not(:required):before
.htk-spinner.dark > .spinner
{
border-top-color: white;
border-left-color: white;

View File

@ -8,7 +8,8 @@ Htk.Widget = new Class
type: String
,set: function (x)
{
this.node.className = x +' '+ this.node.className;
this._cssClass = x;
this._refreshClass ();
}
,get: function ()
{
@ -40,8 +41,22 @@ Htk.Widget = new Class
,getNode: function ()
{
if (!this.node)
{
this._createNode ();
this._refreshClass ();
}
return this.node;
}
,_createNode () {}
,_refreshClass ()
{
if (this.node && this._cssClass)
this.node.className = this._cssClass +' '+ this.node.className;
}
,$: function (id)
{

View File

@ -11,5 +11,6 @@ Vn.include ('js/hedera/main');
Vn.main (function ()
{
(new Vn.App ()).run ();
app = new Vn.App ();
app.run ();
});