summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
authorivan <ivan>2005-01-27 10:21:18 +0000
committerivan <ivan>2005-01-27 10:21:18 +0000
commit6cf964d0dc008621fb30fd2da28e2c44f29c6364 (patch)
tree74fd5536bb89960db22d03cc95b6374711de60ef /httemplate
parente4ae5122522f2d45c68a38eaef337a82029f2fc1 (diff)
DHTML progress bar for glacial rate adding and editing, closes: Bug#1100
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/docs/install.html1
-rwxr-xr-xhttemplate/edit/process/rate.cgi4
-rw-r--r--httemplate/edit/rate.cgi97
-rw-r--r--httemplate/elements/jsrsClient.js356
-rw-r--r--httemplate/elements/qlib/box.js29
-rw-r--r--httemplate/elements/qlib/boxctrl.js48
-rw-r--r--httemplate/elements/qlib/boxres.js42
-rw-r--r--httemplate/elements/qlib/button.js74
-rw-r--r--httemplate/elements/qlib/buttonres.js23
-rw-r--r--httemplate/elements/qlib/control.js51
-rw-r--r--httemplate/elements/qlib/counter.js81
-rw-r--r--httemplate/elements/qlib/imagelist.js25
-rw-r--r--httemplate/elements/qlib/label.js72
-rw-r--r--httemplate/elements/qlib/messagebox.js57
-rw-r--r--httemplate/elements/qlib/progress.js73
-rw-r--r--httemplate/elements/qlib/sound.js47
-rw-r--r--httemplate/elements/qlib/sprite.js125
-rw-r--r--httemplate/elements/qlib/window.js25
-rw-r--r--httemplate/elements/qlib/wndctrl.js322
-rw-r--r--httemplate/images/progressbar-empty.pngbin0 -> 90 bytes
-rw-r--r--httemplate/images/progressbar-full.pngbin0 -> 79 bytes
-rw-r--r--httemplate/misc/progress.html88
22 files changed, 1584 insertions, 56 deletions
diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html
index 86e2a6b..898eb9e 100644
--- a/httemplate/docs/install.html
+++ b/httemplate/docs/install.html
@@ -58,6 +58,7 @@ Before installing, you need:
<li><a href="http://search.cpan.org/search?dist=NetAddr-IP">NetAddr-IP</a>
<li><a href="http://search.cpan.org/search?dist=Chart">Chart</a>
<li><a href="http://search.cpan.org/search?dist=Crypt-PasswdMD5">Crypt::PasswdMD5</a>
+ <li><a href="http://search.cpan.org/search?dist=JavaScript-RPC">JavaScript::RPC (JavaScript::RPC::Server::CGI)</a>
<li><a href="http://search.cpan.org/search?dist=ApacheDBI">Apache::DBI</a> <i>(optional but recommended for better webinterface performance)</i>
</ul>
</ul>
diff --git a/httemplate/edit/process/rate.cgi b/httemplate/edit/process/rate.cgi
new file mode 100755
index 0000000..df7c467
--- /dev/null
+++ b/httemplate/edit/process/rate.cgi
@@ -0,0 +1,4 @@
+<%
+my $server = new FS::rate::JSRPC;
+$server->process;
+%>
diff --git a/httemplate/edit/rate.cgi b/httemplate/edit/rate.cgi
index 4a4b70e..3443f81 100644
--- a/httemplate/edit/rate.cgi
+++ b/httemplate/edit/rate.cgi
@@ -1,52 +1,7 @@
<%
-my($rate, $error);
-
-if ( $cgi->param('magic') eq 'process' ) {
-
- my $ratenum = $cgi->param('ratenum');
-
- my $old = qsearchs('rate', { 'ratenum' => $ratenum } ) if $ratenum;
-
- my @rate_detail = map {
- my $regionnum = $_->regionnum;
- if ( $cgi->param("sec_granularity$regionnum") ) {
- new FS::rate_detail {
- 'dest_regionnum' => $regionnum,
- map { $_ => scalar($cgi->param("$_$regionnum")) }
- qw( min_included min_charge sec_granularity )
- };
- } else {
- new FS::rate_detail {
- 'dest_regionnum' => $regionnum,
- 'min_included' => 0,
- 'min_charge' => 0,
- 'sec_granularity' => '60'
- };
- }
- } qsearch('rate_region', {} );
-
- $rate = new FS::rate ( {
- map {
- $_, scalar($cgi->param($_));
- } fields('rate')
- } );
-
- if ( $ratenum ) {
- warn "$rate replacing $old ($ratenum)\n";
- $error = $rate->replace($old, 'rate_detail' => \@rate_detail );
- } else {
- warn "inserting $rate\n";
- $error = $rate->insert( 'rate_detail' => \@rate_detail );
- $ratenum = $rate->getfield('ratenum');
- }
-
- unless ( $error ) {
- print $cgi->redirect("${p}browse/rate.cgi");
- myexit;
- }
-
-} elsif ( $cgi->keywords ) {
+my $rate;
+if ( $cgi->keywords ) {
my($query) = $cgi->keywords;
$query =~ /^(\d+)$/;
$rate = qsearchs( 'rate', { 'ratenum' => $1 } );
@@ -77,12 +32,41 @@ END
))
%>
-<% if ( $error ) { %>
-<FONT SIZE="+1" COLOR="#ff0000">Error: <%= $error %></FONT><BR>
-<% } %>
+<!-- <FORM ACTION="<%=$p1%>rate.cgi" NAME="OneTrueForm" METHOD=POST onSubmit="document.OneTrueForm.submit.disabled=true"> -->
+
+<SCRIPT TYPE="text/javascript" SRC="../elements/jsrsClient.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript">
+function process () {
+ document.OneTrueForm.submit.disabled=true;
+
+ var Hash = new Array();
+ var x = 0;
+ var fieldName;
+ for (var i = 0; i<document.OneTrueForm.elements.length; i++) {
+ fieldName = document.OneTrueForm.elements[i].name;
+ if ( (fieldName.indexOf('rate') > -1)
+ || (fieldName.indexOf('min_') > -1)
+ || (fieldName.indexOf('sec_') > -1)
+ )
+ {
+ Hash[x++] = fieldName;
+ Hash[x++] = document.OneTrueForm.elements[i].value;
+ }
+ }
+
+ jsrsPOST = true;
+ jsrsExecute( 'process/rate.cgi', myCallback, 'process_rate', Hash );
+
+ function myCallback( jobnum ) {
+ var progressWindow = window.open('../../misc/progress.html?jobnum=' + jobnum + ';url=<%=$p%>browse/rate.cgi', 'progressWindow', 'toolbar=no,location=no,directories=no,scrollbars=no,menubar=no,status=no,width=420,height=128');
+ progressWindow.opener = self;
+ //progressWindow.opener = document;
+ }
+
+}
+</SCRIPT>
-<FORM ACTION="<%=$p1%>rate.cgi" NAME="OneTrueForm" METHOD=POST onSubmit="document.OneTrueForm.submit.disabled=true">
-<INPUT TYPE="hidden" NAME="magic" VALUE="process">
+<FORM NAME="OneTrueForm">
<INPUT TYPE="hidden" NAME="ratenum" VALUE="<%= $rate->ratenum %>">
Rate plan
@@ -135,11 +119,12 @@ Rate plan
</TABLE>
-<BR><INPUT NAME="submit" TYPE="submit" VALUE="<%=
+<BR><INPUT NAME="submit" TYPE="button" VALUE="<%=
$rate->ratenum ? "Apply changes" : "Add rate plan"
-%>">
-Please be patient, <%= $rate->ratenum ? 'editing' : 'adding' %>
-a rate plan can take a few minutes...
+%>" onClick="document.OneTrueForm.submit.disabled=true; process();">
+Please make sure to allow popups from this site in order to view the progress window.
+<!-- Please be patient, <%= $rate->ratenum ? 'editing' : 'adding' %>
+a rate plan can take a few minutes... -->
</FORM>
</BODY>
diff --git a/httemplate/elements/jsrsClient.js b/httemplate/elements/jsrsClient.js
new file mode 100644
index 0000000..3a2572c
--- /dev/null
+++ b/httemplate/elements/jsrsClient.js
@@ -0,0 +1,356 @@
+//
+// jsrsClient.js - javascript remote scripting client include
+//
+// Author: Brent Ashley [jsrs@megahuge.com]
+//
+// make asynchronous remote calls to server without client page refresh
+//
+// see license.txt for copyright and license information
+
+/*
+see history.txt for full history
+2.0 26 Jul 2001 - added POST capability for IE/MOZ
+2.2 10 Aug 2003 - added Opera support
+2.3(beta) 10 Oct 2003 - added Konqueror support - **needs more testing**
+*/
+
+// callback pool needs global scope
+var jsrsContextPoolSize = 0;
+var jsrsContextMaxPool = 10;
+var jsrsContextPool = new Array();
+var jsrsBrowser = jsrsBrowserSniff();
+var jsrsPOST = true;
+var containerName;
+
+// constructor for context object
+function jsrsContextObj( contextID ){
+
+ // properties
+ this.id = contextID;
+ this.busy = true;
+ this.callback = null;
+ this.container = contextCreateContainer( contextID );
+
+ // methods
+ this.GET = contextGET;
+ this.POST = contextPOST;
+ this.getPayload = contextGetPayload;
+ this.setVisibility = contextSetVisibility;
+}
+
+// method functions are not privately scoped
+// because Netscape's debugger chokes on private functions
+function contextCreateContainer( containerName ){
+ // creates hidden container to receive server data
+ var container;
+ switch( jsrsBrowser ) {
+ case 'NS':
+ container = new Layer(100);
+ container.name = containerName;
+ container.visibility = 'hidden';
+ container.clip.width = 100;
+ container.clip.height = 100;
+ break;
+
+ case 'IE':
+ document.body.insertAdjacentHTML( "afterBegin", '<span id="SPAN' + containerName + '"></span>' );
+ var span = document.all( "SPAN" + containerName );
+ var html = '<iframe name="' + containerName + '" src=""></iframe>';
+ span.innerHTML = html;
+ span.style.display = 'none';
+ container = window.frames[ containerName ];
+ break;
+
+ case 'MOZ':
+ var span = document.createElement('SPAN');
+ span.id = "SPAN" + containerName;
+ document.body.appendChild( span );
+ var iframe = document.createElement('IFRAME');
+ iframe.name = containerName;
+ iframe.id = containerName;
+ span.appendChild( iframe );
+ container = iframe;
+ break;
+
+ case 'OPR':
+ var span = document.createElement('SPAN');
+ span.id = "SPAN" + containerName;
+ document.body.appendChild( span );
+ var iframe = document.createElement('IFRAME');
+ iframe.name = containerName;
+ iframe.id = containerName;
+ span.appendChild( iframe );
+ container = iframe;
+ break;
+
+ case 'KONQ':
+ var span = document.createElement('SPAN');
+ span.id = "SPAN" + containerName;
+ document.body.appendChild( span );
+ var iframe = document.createElement('IFRAME');
+ iframe.name = containerName;
+ iframe.id = containerName;
+ span.appendChild( iframe );
+ container = iframe;
+
+ // Needs to be hidden for Konqueror, otherwise it'll appear on the page
+ span.style.display = none;
+ iframe.style.display = none;
+ iframe.style.visibility = hidden;
+ iframe.height = 0;
+ iframe.width = 0;
+
+ break;
+ }
+ return container;
+}
+
+function contextPOST( rsPage, func, parms ){
+
+ var d = new Date();
+ var unique = d.getTime() + '' + Math.floor(1000 * Math.random());
+ var doc = (jsrsBrowser == "IE" ) ? this.container.document : this.container.contentDocument;
+ doc.open();
+ doc.write('<html><body>');
+ doc.write('<form name="jsrsForm" method="post" target="" ');
+ doc.write(' action="' + rsPage + '?U=' + unique + '">');
+ doc.write('<input type="hidden" name="C" value="' + this.id + '">');
+
+ // func and parms are optional
+ if (func != null){
+ doc.write('<input type="hidden" name="F" value="' + func + '">');
+
+ if (parms != null){
+ if (typeof(parms) == "string"){
+ // single parameter
+ doc.write( '<input type="hidden" name="P0" '
+ + 'value="[' + jsrsEscapeQQ(parms) + ']">');
+ } else {
+ // assume parms is array of strings
+ for( var i=0; i < parms.length; i++ ){
+ doc.write( '<input type="hidden" name="P' + i + '" '
+ + 'value="[' + jsrsEscapeQQ(parms[i]) + ']">');
+ }
+ } // parm type
+ } // parms
+ } // func
+
+ doc.write('</form></body></html>');
+ doc.close();
+ doc.forms['jsrsForm'].submit();
+}
+
+function contextGET( rsPage, func, parms ){
+
+ // build URL to call
+ var URL = rsPage;
+
+ // always send context
+ URL += "?C=" + this.id;
+
+ // func and parms are optional
+ if (func != null){
+ URL += "&F=" + escape(func);
+
+ if (parms != null){
+ if (typeof(parms) == "string"){
+ // single parameter
+ URL += "&P0=[" + escape(parms+'') + "]";
+ } else {
+ // assume parms is array of strings
+ for( var i=0; i < parms.length; i++ ){
+ URL += "&P" + i + "=[" + escape(parms[i]+'') + "]";
+ }
+ } // parm type
+ } // parms
+ } // func
+
+ // unique string to defeat cache
+ var d = new Date();
+ URL += "&U=" + d.getTime();
+
+ // make the call
+ switch( jsrsBrowser ) {
+ case 'NS':
+ this.container.src = URL;
+ break;
+ case 'IE':
+ this.container.document.location.replace(URL);
+ break;
+ case 'MOZ':
+ this.container.src = '';
+ this.container.src = URL;
+ break;
+ case 'OPR':
+ this.container.src = '';
+ this.container.src = URL;
+ break;
+ case 'KONQ':
+ this.container.src = '';
+ this.container.src = URL;
+ break;
+ }
+}
+
+function contextGetPayload(){
+ switch( jsrsBrowser ) {
+ case 'NS':
+ return this.container.document.forms['jsrs_Form'].elements['jsrs_Payload'].value;
+ case 'IE':
+ return this.container.document.forms['jsrs_Form']['jsrs_Payload'].value;
+ case 'MOZ':
+ return window.frames[this.container.name].document.forms['jsrs_Form']['jsrs_Payload'].value;
+ case 'OPR':
+ var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");
+ case 'KONQ':
+ var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");
+ return textElement.value;
+ }
+}
+
+function contextSetVisibility( vis ){
+ switch( jsrsBrowser ) {
+ case 'NS':
+ this.container.visibility = (vis)? 'show' : 'hidden';
+ break;
+ case 'IE':
+ document.all("SPAN" + this.id ).style.display = (vis)? '' : 'none';
+ break;
+ case 'MOZ':
+ document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
+ case 'OPR':
+ document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
+ this.container.width = (vis)? 250 : 0;
+ this.container.height = (vis)? 100 : 0;
+ break;
+ }
+}
+
+// end of context constructor
+
+function jsrsGetContextID(){
+ var contextObj;
+ for (var i = 1; i <= jsrsContextPoolSize; i++){
+ contextObj = jsrsContextPool[ 'jsrs' + i ];
+ if ( !contextObj.busy ){
+ contextObj.busy = true;
+ return contextObj.id;
+ }
+ }
+ // if we got here, there are no existing free contexts
+ if ( jsrsContextPoolSize <= jsrsContextMaxPool ){
+ // create new context
+ var contextID = "jsrs" + (jsrsContextPoolSize + 1);
+ jsrsContextPool[ contextID ] = new jsrsContextObj( contextID );
+ jsrsContextPoolSize++;
+ return contextID;
+ } else {
+ alert( "jsrs Error: context pool full" );
+ return null;
+ }
+}
+
+function jsrsExecute( rspage, callback, func, parms, visibility ){
+ // call a server routine from client code
+ //
+ // rspage - href to asp file
+ // callback - function to call on return
+ // or null if no return needed
+ // (passes returned string to callback)
+ // func - sub or function name to call
+ // parm - string parameter to function
+ // or array of string parameters if more than one
+ // visibility - optional boolean to make container visible for debugging
+
+ // get context
+ var contextObj = jsrsContextPool[ jsrsGetContextID() ];
+ contextObj.callback = callback;
+
+ var vis = (visibility == null)? false : visibility;
+ contextObj.setVisibility( vis );
+
+ if ( jsrsPOST && ((jsrsBrowser == 'IE') || (jsrsBrowser == 'MOZ'))){
+ contextObj.POST( rspage, func, parms );
+ } else {
+ contextObj.GET( rspage, func, parms );
+ }
+
+ return contextObj.id;
+}
+
+function jsrsLoaded( contextID ){
+ // get context object and invoke callback
+ var contextObj = jsrsContextPool[ contextID ];
+ if( contextObj.callback != null){
+ contextObj.callback( jsrsUnescape( contextObj.getPayload() ), contextID );
+ }
+ // clean up and return context to pool
+ contextObj.callback = null;
+ contextObj.busy = false;
+}
+
+function jsrsError( contextID, str ){
+ alert( unescape(str) );
+ jsrsContextPool[ contextID ].busy = false
+}
+
+function jsrsEscapeQQ( thing ){
+ return thing.replace(/'"'/g, '\\"');
+}
+
+function jsrsUnescape( str ){
+ // payload has slashes escaped with whacks
+ return str.replace( /\\\//g, "/" );
+}
+
+function jsrsBrowserSniff(){
+ if (document.layers) return "NS";
+ if (document.all) {
+ // But is it really IE?
+ // convert all characters to lowercase to simplify testing
+ var agt=navigator.userAgent.toLowerCase();
+ var is_opera = (agt.indexOf("opera") != -1);
+ var is_konq = (agt.indexOf("konqueror") != -1);
+ if(is_opera) {
+ return "OPR";
+ } else {
+ if(is_konq) {
+ return "KONQ";
+ } else {
+ // Really is IE
+ return "IE";
+ }
+ }
+ }
+ if (document.getElementById) return "MOZ";
+ return "OTHER";
+}
+
+/////////////////////////////////////////////////
+//
+// user functions
+
+function jsrsArrayFromString( s, delim ){
+ // rebuild an array returned from server as string
+ // optional delimiter defaults to ~
+ var d = (delim == null)? '~' : delim;
+ return s.split(d);
+}
+
+function jsrsDebugInfo(){
+ // use for debugging by attaching to f1 (works with IE)
+ // with onHelp = "return jsrsDebugInfo();" in the body tag
+ var doc = window.open().document;
+ doc.open;
+ doc.write( 'Pool Size: ' + jsrsContextPoolSize + '<br><font face="arial" size="2"><b>' );
+ for( var i in jsrsContextPool ){
+ var contextObj = jsrsContextPool[i];
+ doc.write( '<hr>' + contextObj.id + ' : ' + (contextObj.busy ? 'busy' : 'available') + '<br>');
+ doc.write( contextObj.container.document.location.pathname + '<br>');
+ doc.write( contextObj.container.document.location.search + '<br>');
+ doc.write( '<table border="1"><tr><td>' + contextObj.container.document.body.innerHTML + '</td></tr></table>' );
+ }
+ doc.write('</table>');
+ doc.close();
+ return false;
+}
diff --git a/httemplate/elements/qlib/box.js b/httemplate/elements/qlib/box.js
new file mode 100644
index 0000000..537aac4
--- /dev/null
+++ b/httemplate/elements/qlib/box.js
@@ -0,0 +1,29 @@
+/**
+ * QLIB 1.0 Box Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QBox(parent, name, res, x, y, width, height, body, visible, effects, opacity, zindex) {
+ this.init(parent, name);
+ if (this.res = res) {
+ this.x = x - 0;
+ this.y = y - 0;
+ this.width = width - 0;
+ this.height = (typeof(height) == "number") ? height : null;
+ this.body = body || "&nbsp;";
+ var j = QBox.arguments.length;
+ this.visible = (j > 8) ? visible : true;
+ this.effects = (j > 9) ? effects : (res.effects || 0);
+ this.opacity = (j > 10) ? opacity : (res.opacity != null ? res.opacity : 100);
+ this.zindex = (j > 11) ? zindex : null;
+ this.create();
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QBox.prototype = new QBoxCtrl();
diff --git a/httemplate/elements/qlib/boxctrl.js b/httemplate/elements/qlib/boxctrl.js
new file mode 100644
index 0000000..417b204
--- /dev/null
+++ b/httemplate/elements/qlib/boxctrl.js
@@ -0,0 +1,48 @@
+/**
+ * QLIB 1.0 Box Abstraction
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QBoxCtrl_content() {
+ with (this) {
+ if (res) {
+ this.cwidth = width - res.L - res.R - 8;
+ this.cheight = height && (height - res.T - res.B - 8);
+ var ec = '"><table border="0" cellspacing="0" cellpadding="0"><tr><td></td></tr></table></td>';
+ document.write('<table class="qbox" border="0" cellspacing="0" cellpadding="0" width="' +
+ (width - 8) + (height != null ? '" height="' + (height - 8) : '') + '"><tr><td width="' +
+ res.L + '" height="' + res.T + '"><img src="' + res.TL.src + '" border="0" width="' +
+ res.L + '" height="' + res.T + '"></td><td width="' + cwidth + '" height="' + res.T +
+ '" background="' + res.TC.src + ec + '<td width="' + res.R + '" height="' + res.T +
+ '"><img src="' + res.TR.src + '" border="0" width="' + res.R + '" height="' + res.T +
+ '"></td></tr><tr><td width="' + res.L + (cheight != null ? '" height="' + cheight : '') +
+ '" background="' + res.ML.src + ec + '<td width="' + cwidth + '" bgcolor="' + res.bgcolor +
+ (cheight != null ? '" height="' + cheight : '') + (res.bgtile ? '" background="' +
+ res.bgtile.src : '') + '" align="left" valign="top" class="body" unselectable="on">');
+ if (typeof(body) == "function") {
+ this.body();
+ } else {
+ document.write(body);
+ }
+ document.write('</td><td width="' + res.R + (cheight != null ? '" height="' + cheight : '') +
+ '" background="' + res.MR.src + ec + '</tr><tr><td width="' + res.L + '" height="' + res.B +
+ '"><img src="' + res.BL.src + '" border="0" width="' + res.L + '" height="' + res.B +
+ '"></td><td width="' + cwidth + '" height="' + res.B + '" background="' + res.BC.src + ec +
+ '<td width="' + res.R + '" height="' + res.B + '"><img src="' + res.BR.src +
+ '" border="0" width="' + res.R + '" height="' + res.B + '"></td></tr></table><br>');
+ }
+ }
+}
+
+function QBoxCtrl() {
+ this.res = false;
+ this.body = "&nbsp;";
+ this.cwidth = this.cheight = 0;
+ this.content = QBoxCtrl_content;
+}
+QBoxCtrl.prototype = new QWndCtrl();
diff --git a/httemplate/elements/qlib/boxres.js b/httemplate/elements/qlib/boxres.js
new file mode 100644
index 0000000..0878172
--- /dev/null
+++ b/httemplate/elements/qlib/boxres.js
@@ -0,0 +1,42 @@
+/**
+ * QLIB 1.0 Box Resource
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QBoxRes(t, r, b, l, tc, tr, mr, br, bc, bl, ml, tl, bgcolor, bgtile, effects, opacity) {
+ var args = QBoxRes.arguments.length;
+ this.T = t;
+ this.R = r;
+ this.B = b;
+ this.L = l;
+ this.TC = new Image();
+ this.TC.src = tc;
+ this.TR = new Image(r, t);
+ this.TR.src = tr;
+ this.MR = new Image();
+ this.MR.src = mr;
+ this.BR = new Image(r, b);
+ this.BR.src = br;
+ this.BC = new Image();
+ this.BC.src = bc;
+ this.BL = new Image(l, b);
+ this.BL.src = bl;
+ this.ML = new Image();
+ this.ML.src = ml;
+ this.TL = new Image(l, t);
+ this.TL.src = tl;
+ this.bgcolor = bgcolor || "#FFFFFF";
+ if (bgtile) {
+ this.bgtile = new Image();
+ this.bgtile.src = bgtile;
+ } else {
+ this.bgtile = false;
+ }
+ this.effects = (args > 13) ? effects : null;
+ this.opacity = (args > 14) ? opacity : null;
+}
diff --git a/httemplate/elements/qlib/button.js b/httemplate/elements/qlib/button.js
new file mode 100644
index 0000000..05247d5
--- /dev/null
+++ b/httemplate/elements/qlib/button.js
@@ -0,0 +1,74 @@
+/**
+ * QLIB 1.0 Button Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QButton_update() {
+ with (this) {
+ image.src = ((!enabled && res.imgD) || (value ? res.imgP : res.imgN)).src;
+ }
+}
+
+function QButton_doEvent() {
+ with (this) {
+ if (enabled) {
+ if (res.style == 1) {
+ this.value = value ? 0 : 1;
+ update();
+ }
+ onClick(value, tag);
+ }
+ }
+ return false;
+}
+
+function QButton_enable(state) {
+ this.enabled = state;
+ this.update();
+}
+
+function QButton_set(value) {
+ if (this.enabled) {
+ this.value = value ? 1 : 0;
+ this.update();
+ }
+ return true;
+}
+
+function QButton(parent, name, res, tooltip) {
+ this.init(parent, name);
+ if (res) {
+ this.res = res;
+ this.tip = tooltip || "";
+ this.enabled = true;
+ this.value = 0;
+ this.set = QButton_set;
+ this.enable = QButton_enable;
+ this.update = QButton_update;
+ this.doEvent = QButton_doEvent;
+ this.onClick = QControl.event;
+ with (this) {
+ document.write('<a href="#" hidefocus="true" unselectable="on"' +
+ (tip ? ' title="' + tip + '"' : '') + ' onClick="return ' + name +
+ '.doEvent()" onMouseOver="' + (res.style == 2 ? name + '.set(1);' : '') +
+ 'window.top.status=' + name + '.tip;return true" onMouseOut="' +
+ (!res.style || (res.style == 2) ? name + '.set();' : '') + 'window.top.status=\'\'"' +
+ (!res.style ? ' onMouseDown="return ' + name + '.set(1)" onMouseUp="return ' + name + '.set()"' : '') +
+ '><img class="qbutton" name="' + id + '" src="' + res.imgN.src + '" border="0" width="' +
+ res.width + '" height="' + res.height + '"></a>');
+ this.image = document.images[id] || new Image(1, 1);
+ }
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QButton.prototype = new QControl();
+QButton.NORMAL = 0;
+QButton.CHECKBOX = 1;
+QButton.WEB = 2;
+QButton.SIGNAL = 3;
diff --git a/httemplate/elements/qlib/buttonres.js b/httemplate/elements/qlib/buttonres.js
new file mode 100644
index 0000000..97f6dfc
--- /dev/null
+++ b/httemplate/elements/qlib/buttonres.js
@@ -0,0 +1,23 @@
+/**
+ * QLIB 1.0 Button Resource
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QButtonRes(style, width, height, normal, pressed, disabled) {
+ this.style = style;
+ this.width = width;
+ this.height = height;
+ this.imgN = new Image(width, height);
+ this.imgN.src = normal;
+ this.imgP = new Image(width, height);
+ this.imgP.src = pressed;
+ if (disabled) {
+ this.imgD = new Image(width, height);
+ this.imgD.src = disabled;
+ }
+}
diff --git a/httemplate/elements/qlib/control.js b/httemplate/elements/qlib/control.js
new file mode 100644
index 0000000..f50206e
--- /dev/null
+++ b/httemplate/elements/qlib/control.js
@@ -0,0 +1,51 @@
+/**
+ * QLIB 1.0 Base Abstract Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QControl_init(parent, name) {
+ this.parent = parent || self;
+ this.window = (parent && parent.window) || self;
+ this.document = (parent && parent.document) || self.document;
+ this.name = (parent && parent.name) ? (parent.name + "." + name) : ("self." + name);
+ this.id = "Q";
+ var h = this.hash(this.name);
+ for (var j=0; j<8; j++) {
+ this.id += QControl.HEXTABLE.charAt(h & 15);
+ h >>>= 4;
+ }
+}
+
+function QControl_hash(str) {
+ var h = 0;
+ if (str) {
+ for (var j=str.length-1; j>=0; j--) {
+ h ^= QControl.ANTABLE.indexOf(str.charAt(j)) + 1;
+ for (var i=0; i<3; i++) {
+ var m = (h = h<<7 | h>>>25) & 150994944;
+ h ^= m ? (m == 150994944 ? 1 : 0) : 1;
+ }
+ }
+ }
+ return h;
+}
+
+function QControl_nop() {
+}
+
+function QControl() {
+ this.init = QControl_init;
+ this.hash = QControl_hash;
+ this.window = self;
+ this.document = self.document;
+ this.tag = null;
+}
+QControl.ANTABLE = "w5Q2KkFts3deLIPg8Nynu_JAUBZ9YxmH1XW47oDpa6lcjMRfi0CrhbGSOTvqzEV";
+QControl.HEXTABLE = "0123456789ABCDEF";
+QControl.nop = QControl_nop;
+QControl.event = QControl_nop;
diff --git a/httemplate/elements/qlib/counter.js b/httemplate/elements/qlib/counter.js
new file mode 100644
index 0000000..72aeddb
--- /dev/null
+++ b/httemplate/elements/qlib/counter.js
@@ -0,0 +1,81 @@
+/**
+ * QLIB 1.0 Animated Digital Counter
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QCounter_update() {
+ with (this) {
+ var v = Math.max(value, 0);
+ var mod;
+ for (var j=0; j<size; j++) {
+ mod = Math.floor(v % 10);
+ images[j].src = (v >= 1) || (!j) ? res.list[mod].src : res.list[10].src;
+ v /= 10;
+ }
+ }
+}
+
+function QCounter_count(value, step) {
+ this._cntt = false;
+ this.value += step;
+ if ((step * (this.value - value)) >= 0) {
+ this.value = value - 0; // convert to number
+ } else {
+ this._cntt = setTimeout(this.name + ".count(" + value + "," + step + ")", 50);
+ }
+ this.update();
+}
+
+function QCounter_set(value) {
+ this.setval = value;
+ if (value != this.value) {
+ if (this._cntt) {
+ clearTimeout(this._cntt);
+ this._cntt = false;
+ }
+ var dv = value - this.value;
+ if (this.effect == 2) {
+ dv = dv / Math.min(10, Math.abs(dv));
+ } else if (this.effect == 3) {
+ dv = dv / Math.abs(dv);
+ }
+ this.count(value, dv);
+ }
+}
+
+function QCounter(parent, name, res, size, effect) {
+ this.init(parent, name);
+ if (res) {
+ this.res = res;
+ this.setval = this.value = 0;
+ this.size = size || 4;
+ this.effect = effect || 2;
+ this._cntt = false;
+ this.images = new Array(this.size);
+ this.set = QCounter_set;
+ this.update = QCounter_update;
+ this.count = QCounter_count;
+ with (this) {
+ document.write('<table class="qcounter" width="' + (res.width * size) + '" height="' + res.height +
+ '" border="0" cellspacing="0" cellpadding="0" unselectable="on"><tr>');
+ for (var j=(size - 1); j>=0; j--) {
+ document.write('<td width="' + res.width + '" height="' + res.height +
+ '" unselectable="on"><img name="' + id + j + '" src="' + (j ? res.list[10].src : res.list[0].src) +
+ '" border="0" width="' + res.width + '" height="' + res.height + '"></td>');
+ images[j] = document.images[id + j] || new Image(1, 1);
+ }
+ document.write('</tr></table>');
+ }
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QCounter.prototype = new QControl();
+QCounter.INSTANT = 1;
+QCounter.FAST = 2;
+QCounter.SLOW = 3;
diff --git a/httemplate/elements/qlib/imagelist.js b/httemplate/elements/qlib/imagelist.js
new file mode 100644
index 0000000..9f12de0
--- /dev/null
+++ b/httemplate/elements/qlib/imagelist.js
@@ -0,0 +1,25 @@
+/**
+ * QLIB 1.0 ImageList Resource
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QImageList(width, height) {
+ var len = QImageList.arguments.length - 2;
+ if (len > 0) {
+ this.list = new Array(len);
+ this.length = len;
+ this.width = width;
+ this.height = height;
+ var im;
+ for (var j=0; j<len; j++) {
+ im = new Image(width, height);
+ im.src = QImageList.arguments[j + 2];
+ this.list[j] = im;
+ }
+ }
+} \ No newline at end of file
diff --git a/httemplate/elements/qlib/label.js b/httemplate/elements/qlib/label.js
new file mode 100644
index 0000000..2d8b1e7
--- /dev/null
+++ b/httemplate/elements/qlib/label.js
@@ -0,0 +1,72 @@
+/**
+ * QLIB 1.0 Text Label
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QLabel_set_ie(value) {
+ this.label.innerText = (this.value = value) || "\xA0";
+}
+
+function QLabel_set_dom2(value) {
+ with (this.label) {
+ replaceChild(this.document.createTextNode((this.value = value) || "\xA0"), firstChild);
+ }
+}
+
+function QLabel_set_ns4(value) {
+ this.value = value || "";
+ with (this) {
+ document.open();
+ document.write('<div class="qlabel">' + (clickable ? '<a href="#" title="' + tooltip + '" onClick="return ' +
+ name + '.doEvent()" onMouseOut="window.top.status=\'\'" onMouseOver="window.top.status=' + name +
+ '.tooltip;return true">' + value + '</a>' : value) + '</div>');
+ document.close();
+ }
+}
+
+function QLabel_doEvent() {
+ this.onClick(this.value, this.tag);
+ return false;
+}
+
+function QLabel(parent, name, value, clickable, tooltip) {
+ this.init(parent, name);
+ this.value = value || "";
+ this.clickable = clickable || false;
+ this.tooltip = tooltip || "";
+ this.doEvent = QLabel_doEvent;
+ this.onClick = QControl.event;
+ with (this) {
+ if (document.getElementById || document.all) {
+ document.write(clickable ? '<div class="qlabel" unselectable="on"><a id="' + id + '" href="#" title="' +
+ tooltip + '" onClick="return ' + name + '.doEvent()" onMouseOver="window.top.status=' + name +
+ '.tooltip;return true" onMouseOut="window.top.status=\'\'" hidefocus="true" unselectable="on">' +
+ (value || '&nbsp;') + '</a></div>' : '<div id="' + id + '" class="qlabel" unselectable="on">' +
+ (value || '&nbsp;') + '</div>');
+ this.label = document.getElementById ? document.getElementById(id) :
+ (document.all.item ? document.all.item(id) : document.all[id]);
+ this.set = (label && (label.innerText ? QLabel_set_ie :
+ (label.replaceChild && QLabel_set_dom2))) || QControl.nop;
+ } else if (document.layers) {
+ var suffix = "";
+ for (var j=value.length; j<QLabel.TEXTQUOTA; j++) suffix += " &nbsp;";
+ document.write('<div><ilayer id="i' + id + '"><layer id="' + id + '"><div class="qlabel">' +
+ (clickable ? '<a href="#" title="' + tooltip + '" onClick="return ' + name +
+ '.doEvent()" onMouseOver="window.top.status=' + name +
+ '.tooltip;return true" onMouseOut="window.top.status=\'\'">' + value + suffix + '</a>' :
+ value + suffix) + '</div></layer></ilayer></div>');
+ this.label = (this.label = document.layers["i" + id]) && label.document.layers[id];
+ this.document = label && label.document;
+ this.set = (label && document) ? QLabel_set_ns4 : QControl.nop;
+ } else {
+ document.write("Object is not supported");
+ }
+ }
+}
+QLabel.prototype = new QControl();
+QLabel.TEXTQUOTA = 50;
diff --git a/httemplate/elements/qlib/messagebox.js b/httemplate/elements/qlib/messagebox.js
new file mode 100644
index 0000000..2e45839
--- /dev/null
+++ b/httemplate/elements/qlib/messagebox.js
@@ -0,0 +1,57 @@
+/**
+ * QLIB 1.0 Message Box Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QMessageBox_alert(msg) {
+ if (typeof(msg) == "string") {
+ this.label.set(this.value = msg);
+ }
+ this.center();
+ this.focus();
+ this.show(true);
+}
+
+function QMessageBox_close() {
+ with (this.parent) {
+ if (!onClose(tag)) show(false);
+ }
+}
+
+function QMessageBox_body() {
+ with (this) {
+ document.write('<table border="0" width="' + cwidth + '"><tr><td align="left" valign="top" unselectable="on">');
+ this.label = new QLabel(this, "label", value);
+ document.write('</td></tr><tr><td height="' + (bres.height + 14) + '" align="center" valign="bottom" unselectable="on">');
+ this.button = new QButton(this, "button", bres, "Close");
+ document.write('</td></tr></table>');
+ button.onClick = QMessageBox_close;
+ }
+}
+
+function QMessageBox(parent, name, box, btn, msg, effects, opacity) {
+ this.init(parent, name);
+ if ((this.res = box) && (this.bres = btn)) {
+ this.value = typeof(msg) == "string" ? msg : "";
+ this.width = Math.max(200, Math.floor(Math.sqrt(555 * this.value.length)));
+ this.height = null;
+ this.x = this.y = 0;
+ this.visible = false;
+ this.zindex = null;
+ this.body = QMessageBox_body;
+ var j = QMessageBox.arguments.length;
+ this.effects = j > 5 ? effects : (box.effects != null ? box.effects : 0);
+ this.opacity = j > 6 ? opacity : (box.opacity != null ? box.opacity : 100);
+ this.create();
+ this.alert = QMessageBox_alert;
+ this.onClose = QControl.event;
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QMessageBox.prototype = new QBoxCtrl();
diff --git a/httemplate/elements/qlib/progress.js b/httemplate/elements/qlib/progress.js
new file mode 100644
index 0000000..2de077e
--- /dev/null
+++ b/httemplate/elements/qlib/progress.js
@@ -0,0 +1,73 @@
+/**
+ * QLIB 1.0 Progress Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QProgress_update() {
+ with (this) {
+ var i = low;
+ for (var j=0; j<size; j++) {
+ images[j].src = i < value ? imgsrc1 : imgsrc0;
+ i += delta;
+ }
+ }
+}
+
+function QProgress_set(value) {
+ this.value = value - 0;
+ this.update();
+}
+
+function QProgress_setBounds(low, high) {
+ this.low = Math.min(low, high);
+ this.high = Math.max(low, high);
+ this.delta = (this.high - this.low) / this.size;
+ this.update();
+}
+
+function QProgress(parent, name, res, size, style) {
+ this.init(parent, name);
+ if (res) {
+ this.res = res;
+ this.value = 0;
+ this.low = 0;
+ this.high = 100;
+ this.size = size || 10;
+ this.delta = 100 / this.size;
+ this.style = style || 0;
+ this.images = new Array(this.size);
+ this.imgsrc0 = res.list[0] && res.list[0].src;
+ this.imgsrc1 = res.list[1] && res.list[1].src;
+ this.set = QProgress_set;
+ this.update = QProgress_update;
+ this.setBounds = QProgress_setBounds;
+ with (this) {
+ var hor = this.style < 2;
+ var rev = this.style % 2;
+ document.write('<table class="qprogress" border="0" cellspacing="0" cellpadding="0" unselectable="on" ' +
+ (hor ? 'width="' + (size * res.width) + '" height="' + res.height + '"><tr>' : 'width="' + res.width +
+ '" height="' + (size * res.height) + '">'));
+ for (var j=0; j<size; j++) {
+ document.write((hor ? '' : '<tr>') + '<td width="' + res.width + '" height="' + res.height +
+ '" unselectable="on"><img name="' + id + (rev ? size - j - 1 : j) + '" src="' + res.list[0].src +
+ '" border="0" width="' + res.width + '" height="' + res.height + '"></td>' + (hor ? '' : '</tr>'));
+ }
+ document.write((hor ? '</tr>' : '') + '</table>');
+ for (var j=0; j<size; j++) {
+ images[j] = document.images[id + j] || new Image(1, 1);
+ }
+ }
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QProgress.prototype = new QControl();
+QProgress.NORMAL = 0;
+QProgress.REVERSE = 1;
+QProgress.FALL = 2;
+QProgress.RISE = 3;
diff --git a/httemplate/elements/qlib/sound.js b/httemplate/elements/qlib/sound.js
new file mode 100644
index 0000000..3d1aaf6
--- /dev/null
+++ b/httemplate/elements/qlib/sound.js
@@ -0,0 +1,47 @@
+/**
+ * QLIB 1.0 Preloaded Sound
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QSound_play(loop) {
+ this._out.loop = loop || 0;
+ this._out.src = this._buf.src;
+}
+
+function QSound_stop() {
+ this._out.loop = 0;
+ this._out.src = "";
+}
+
+function QSound_setVolume(volume) {
+ this._out.volume = this.volume = volume;
+}
+
+function QSound(parent, name, src, volume) {
+ this.init(parent, name);
+ this.volume = volume || 0;
+ this.play = this.stop = this.setVolume = QControl.nop;
+ with (this) {
+ document.write('<bgsound id="' + id + '" src="" volume="' + volume + '">');
+ if (document.all && document.all.item) {
+ this._out = document.all.item(id);
+ if (_out && (typeof _out.src != "undefined") && (_out.volume === volume)) {
+ document.write('<bgsound id="b' + id + '" src="' + src + '" volume="-10000">');
+ this._buf = document.all.item("b" + id);
+ if (_buf) {
+ this.play = QSound_play;
+ this.stop = QSound_stop;
+ this.setVolume = QSound_setVolume;
+
+ _out.onreadystatechange = new Function("alert(0)");
+ }
+ }
+ }
+ }
+}
+QSound.prototype = new QControl();
diff --git a/httemplate/elements/qlib/sprite.js b/httemplate/elements/qlib/sprite.js
new file mode 100644
index 0000000..72a68fb
--- /dev/null
+++ b/httemplate/elements/qlib/sprite.js
@@ -0,0 +1,125 @@
+/**
+ * QLIB 1.0 Sprite Object
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QSprite_load(src) {
+ if (src) {
+ this.face = new Image(this.cwidth, this.cheight);
+ this.face.src = src;
+ this.valid = false;
+ }
+}
+
+function QSprite_show(show) {
+ if (show && !this.valid && this.face.complete) {
+ this._img.src = this.face.src;
+ this.valid = true;
+ }
+ this._show(show);
+}
+
+function QSprite_moveTo(x, y) {
+ this.stop();
+ this._move(x, y);
+}
+
+function QSprite_slideTo(x, y) {
+ this.stop();
+ if (this.visible) {
+ this.doSlide(++this._spro, x, y);
+ } else {
+ this.moveTo(x, y);
+ }
+}
+
+function QSprite_shake() {
+ this.stop();
+ if (this.visible) {
+ this.doShake(++this._spro, 0, this.x, this.y);
+ }
+}
+
+function QSprite_stop() {
+ this._spro++;
+ if (this._sprt) {
+ clearTimeout(this._sprt);
+ this._sprt = false;
+ }
+}
+
+function QSprite_doSlide(id, x, y) {
+ if (this._spro == id) {
+ this._sprt = false;
+ var dx = Math.round(x - this.x);
+ var dy = Math.round(y - this.y);
+ if (dx || dy) {
+ if (dx) dx = dx > 0 ? Math.ceil(dx/4) : Math.floor(dx/4);
+ if (dy) dy = dy > 0 ? Math.ceil(dy/4) : Math.floor(dy/4);
+ this._move(this.x + dx, this.y + dy);
+ this._sprt = setTimeout(this.name + ".doSlide(" + id + "," + x + "," + y + ")", 30);
+ } else {
+ this._move(x, y);
+ }
+ }
+}
+
+function QSprite_doShake(id, phase, x, y) {
+ if (this._spro == id) {
+ this._sprt = false;
+ if (phase < 20) {
+ var m = 3 * Math.sin(.16 * phase);
+ this._move(x + m * Math.sin(phase), y + m * Math.cos(phase));
+ this._sprt = setTimeout(this.name + ".doShake(" + id + "," + (++phase) + "," + x + "," + y + ")", 20);
+ } else {
+ this._move(x, y);
+ }
+ }
+}
+
+function QSprite_doClick() {
+ if (!this._sprt) {
+ this.onClick(this.tag);
+ }
+ return false;
+}
+
+function QSprite(parent, name, x, y, width, height, src, visible, effects, opacity, zindex) {
+ this.init(parent, name);
+ this.x = x - 0;
+ this.y = y - 0;
+ this.width = (this.cwidth = width - 0) + 8;
+ this.height = (this.cheight = height - 0) + 8;
+ var j = QSprite.arguments.length;
+ this.visible = (j > 7) ? visible : true;
+ this.effects = (j > 8) ? effects : 0;
+ this.opacity = (j > 9) ? opacity : 100;
+ this.zindex = (j > 10) ? zindex : null;
+ this.valid = !!src;
+ this.content = '<a href="#" title="" onclick="return false" onmousedown="return ' + this.name +
+ '.doClick()" onmouseover="window.top.status=\'\';return true" hidefocus="true" unselectable="on"><img name="' +
+ this.id + '" src="' + (src || '') + '" border="0" width="' + this.cwidth + '" height="' + this.cheight +
+ '" alt="" unselectable="on"></a>';
+ this.doClick = QSprite_doClick;
+ this.doSlide = QSprite_doSlide;
+ this.doShake = QSprite_doShake;
+ this.onClick = QControl.event;
+ this.create();
+ this.face = this._img = this.document.images[this.id] || new Image(1, 1);
+ this._spro = 0;
+ this._sprt = false;
+ this._show = this.show;
+ this._move = this.moveTo;
+ this.load = QSprite_load;
+ this.show = QSprite_show;
+ this.moveTo = QSprite_moveTo;
+ this.slideTo = QSprite_slideTo;
+ this.shake = QSprite_shake;
+ this.stop = QSprite_stop;
+}
+QSprite.prototype = new QWndCtrl();
diff --git a/httemplate/elements/qlib/window.js b/httemplate/elements/qlib/window.js
new file mode 100644
index 0000000..6056fda
--- /dev/null
+++ b/httemplate/elements/qlib/window.js
@@ -0,0 +1,25 @@
+/**
+ * QLIB 1.0 Window Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QWindow(parent, name, x, y, width, height, content, visible, effects, opacity, zindex) {
+ this.init(parent, name);
+ this.x = x - 0;
+ this.y = y - 0;
+ this.width = width - 0;
+ this.height = (typeof(height) == "number") ? height : null;
+ this.content = content;
+ var j = QWindow.arguments.length;
+ this.visible = (j > 7) ? visible : true;
+ this.effects = (j > 8) ? effects : 0;
+ this.opacity = (j > 9) ? opacity : 100;
+ this.zindex = (j > 10) ? zindex : null;
+ this.create();
+}
+QWindow.prototype = new QWndCtrl();
diff --git a/httemplate/elements/qlib/wndctrl.js b/httemplate/elements/qlib/wndctrl.js
new file mode 100644
index 0000000..b3bde4e
--- /dev/null
+++ b/httemplate/elements/qlib/wndctrl.js
@@ -0,0 +1,322 @@
+/**
+ * QLIB 1.0 Window Abstraction
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QWndCtrl_center_ie4() {
+ var b = this.document.body;
+ this.moveTo(b.scrollLeft + Math.max(0, Math.floor((b.clientWidth -
+ this.width) / 2)), b.scrollTop + 100);
+}
+
+function QWndCtrl_center_moz() {
+ this.moveTo(self.pageXOffset + Math.max(0, Math.floor((self.innerWidth -
+ this.width) / 2)), self.pageYOffset + 100);
+}
+
+function QWndCtrl_setEffects_ie4(fx) {
+ this.effects = fx;
+ with (this.wnd) {
+ filters[0].enabled = (fx & 256) != 0;
+ filters[1].enabled = (fx & 512) != 0;
+ filters[2].enabled = (fx & 1024) != 0;
+ filters[4].enabled = (fx & 2048) != 0;
+ }
+}
+
+function QWndCtrl_setEffects_moz(fx) {
+ this.effects = fx;
+}
+
+function QWndCtrl_setOpacity_ie4(op) {
+ this.opacity = Math.max(0, Math.min(100, Math.floor(op - 0)));
+ this.wnd.filters[3].opacity = this.opacity;
+ this.wnd.filters[3].enabled = (this.opacity < 100);
+}
+
+function QWndCtrl_setOpacity_moz(op) {
+ this.opacity = Math.max(0, Math.min(100, Math.floor(op - 0)));
+ this.wnd.style.MozOpacity = this.opacity + "%";
+}
+
+function QWndCtrl_setSize_css(w, h) {
+ this.wnd.style.width = (this.width = Math.floor(w - 0)) + "px";
+ this.wnd.style.height = typeof(h) == "number" ? (this.height = Math.floor(h)) + "px" : "auto";
+}
+
+function QWndCtrl_setSize_ns4(w, h) {
+ this.wnd.clip.width = this.width = Math.floor(w - 0);
+ if (typeof(h) == "number") {
+ this.wnd.clip.height = this.height = Math.floor(h);
+ }
+}
+
+function QWndCtrl_focus() {
+ this.setZIndex(QWndCtrl.TOPZINDEX++);
+}
+
+function QWndCtrl_setZIndex_css(z) {
+ this.wnd.style.zIndex = this.zindex = z || 0;
+}
+
+function QWndCtrl_setZIndex_ns4(z) {
+ this.wnd.zIndex = this.zindex = z || 0;
+}
+
+function QWndCtrl_moveTo_css(x, y) {
+ this.wnd.style.left = (this.x = Math.floor(x - 0)) + "px";
+ this.wnd.style.top = (this.y = Math.floor(y - 0)) + "px";
+}
+
+function QWndCtrl_moveTo_ns4(x, y) {
+ this.wnd.moveTo(this.x = Math.floor(x - 0), this.y = Math.floor(y - 0));
+}
+
+function QWndCtrl_fxhandler() {
+ this.fxhandler = QControl.nop;
+ this.onShow(this.visible, this.tag);
+}
+
+function QWndCtrl_show_ie4(show) {
+ if (this.visible != show) {
+ var fx = false;
+ switch (show ? this.effects & 15 : (this.effects & 240) >>> 4) {
+ case 1:
+ fx = this.wnd.filters[5];
+ break;
+ case 2:
+ (fx = this.wnd.filters[6]).transition = show ? 1 : 0;
+ break;
+ case 3:
+ (fx = this.wnd.filters[6]).transition = show ? 3 : 2;
+ break;
+ case 4:
+ (fx = this.wnd.filters[6]).transition = show ? 5 : 4;
+ break;
+ case 5:
+ (fx = this.wnd.filters[6]).transition = show ? 14 : 13;
+ break;
+ case 6:
+ (fx = this.wnd.filters[6]).transition = show ? 16 : 15;
+ break;
+ case 7:
+ (fx = this.wnd.filters[6]).transition = 12;
+ break;
+ case 8:
+ (fx = this.wnd.filters[6]).transition = 8;
+ break;
+ case 9:
+ (fx = this.wnd.filters[6]).transition = 9;
+ }
+ if (fx) {
+ fx.apply();
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.fxhandler = QWndCtrl_fxhandler;
+ fx.play(0.3);
+ } else {
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.onShow(show, this.tag);
+ }
+ }
+}
+
+function QWndCtrl_fade_moz(op, step) {
+ this._wndt = false;
+ if (step) {
+ op += step;
+ if ((op > 0) && (op < this.opacity)) {
+ this.wnd.style.MozOpacity = op + "%";
+ this._wndt = setTimeout(this.name + ".fade(" + op + "," + step + ")", 50);
+ } else {
+ if (op <= 0) {
+ this.wnd.style.visibility = "hidden";
+ this.visible = false;
+ }
+ this.wnd.style.MozOpacity = this.opacity + "%";
+ this.onShow(this.visible, this.tag);
+ }
+ }
+}
+
+function QWndCtrl_show_moz(show) {
+ if (this.visible != show) {
+ if (this._wndt) {
+ clearTimeout(this._wndt);
+ this._wndt = false;
+ }
+ var step = show ? ((this.effects & 15) == 1) && Math.floor(this.opacity / 5) :
+ ((this.effects & 240) == 16) && -Math.floor(this.opacity / 5);
+ if (step) {
+ if (this.visible) {
+ this.fade(this.opacity - 0, step);
+ } else {
+ this.wnd.style.MozOpacity = "0%";
+ this.wnd.style.visibility = "visible";
+ this.visible = true;
+ this.fade(0, step);
+ }
+ } else {
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.onShow(show, this.tag);
+ }
+ }
+}
+
+function QWndCtrl_show_css(show) {
+ if (this.visible != show) {
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.onShow(show, this.tag);
+ }
+}
+
+function QWndCtrl_show_ns4(show) {
+ if (this.visible != show) {
+ this.wnd.visibility = (this.visible = show) ? "show" : "hidden";
+ this.onShow(show, this.tag);
+ }
+}
+
+function QWndCtrl_create_dom2() {
+ with (this) {
+ this.fxhandler = QControl.nop;
+ var ie4 = document.body && document.body.filters;
+ var moz = document.body && document.body.style &&
+ typeof(document.body.style.MozOpacity) == "string";
+ document.write('<div unselectable="on" id="' + id +
+ (ie4 ? '" onfilterchange="' + name + '.fxhandler()': '') +
+ '" style="position:absolute;left:' + x + 'px;top:' + y +
+ 'px;width:' + width + (height != null ? 'px;height:' + height : '') +
+ 'px;visibility:' + (visible ? 'visible' : 'hidden') +
+ ';overflow:hidden' + (zindex ? ';z-index:' + zindex : '') +
+ (ie4 ? ';filter:Gray(enabled=' + (effects & 256 ? '1' : '0') +
+ ') Xray(enabled=' + (effects & 512 ? '1' : '0') +
+ ') Invert(enabled=' + (effects & 1024 ? '1' : '0') +
+ ') alpha(enabled=' + (opacity < 100 ? '1' : '0') + ',opacity=' + opacity +
+ ') shadow(enabled=' + (effects & 2048 ? '1' : '0') +
+ ',direction=135) BlendTrans(enabled=0) RevealTrans(enabled=0)' : '') +
+ (moz && (opacity < 100) ? ';-moz-opacity:' + opacity + '%' : '') +
+ '"><div unselectable="on" class="qwindow">');
+ if (typeof(content) == "function") {
+ this.content();
+ } else {
+ document.write(content);
+ }
+ document.write('</div></div>');
+ if (this.wnd = document.getElementById ? document.getElementById(id) :
+ (document.all.item ? document.all.item(id) : document.all[id])) {
+ if (wnd.style) {
+ ie4 = ie4 && wnd.filters;
+ moz = moz && typeof(wnd.style.MozOpacity) == "string";
+ this.moveTo = QWndCtrl_moveTo_css;
+ this.setZIndex = QWndCtrl_setZIndex_css;
+ this.focus = QWndCtrl_focus;
+ this.setSize = QWndCtrl_setSize_css;
+ this.show = ie4 ? QWndCtrl_show_ie4 : (moz ? QWndCtrl_show_moz : QWndCtrl_show_css);
+ this.fade = moz ? QWndCtrl_fade_moz : QControl.nop;
+ this.setOpacity = ie4 ? QWndCtrl_setOpacity_ie4 : (moz ? QWndCtrl_setOpacity_moz : QControl.nop);
+ this.setEffects = ie4 ? QWndCtrl_setEffects_ie4 : (moz ? QWndCtrl_setEffects_moz : QControl.nop);
+ this.center = self.innerWidth ? QWndCtrl_center_moz :
+ (document.body && document.body.clientWidth ? QWndCtrl_center_ie4 : QControl.nop);
+ }
+ }
+ }
+}
+
+function QWndCtrl_create_ns4(finalize) {
+ with (this) {
+ if (finalize) {
+ if (_wnde) {
+ parent.window.onload = _wnde;
+ parent.window.onload();
+ }
+ document.open();
+ document.write('<div class="qwindow">');
+ this.content();
+ document.write('</div>');
+ document.close();
+ } else {
+ document.write('<layer id="' + id + '" left="' + x + '" top="' + y +
+ '" width="' + width + '" visibility="' + (visible ? 'show' : 'hidden') +
+ (height != null ? '" height="' + height + '" clip="' + width + ',' + height : '') +
+ (zindex ? '" z-index="' + zindex : '') + (typeof(content) != "function" ?
+ '"><div class="qwindow">' + content + '</div></layer>' : '">&nbsp;</layer>'));
+ if (this.window = this.wnd = document.layers[id]) {
+ if (this.document = wnd.document) {
+ this.show = QWndCtrl_show_ns4;
+ this.moveTo = QWndCtrl_moveTo_ns4;
+ this.setZIndex = QWndCtrl_setZIndex_ns4;
+ this.focus = QWndCtrl_focus;
+ this.center = QWndCtrl_center_moz;
+ this.setSize = QWndCtrl_setSize_ns4;
+ if (typeof(content) == "function") {
+ this._wnde = parent.window.onload;
+ parent.window.onload = new Function(name + ".create(true)");
+ }
+ }
+ }
+ }
+ }
+}
+
+function QWndCtrl_create_na() {
+ this.document.write('Object is not supported.');
+ this.wnd = null;
+}
+
+function QWndCtrl_create() {
+ with (this) {
+ this.create = (document.getElementById || document.all) ? QWndCtrl_create_dom2 :
+ (document.layers ? QWndCtrl_create_ns4 : QWndCtrl_create_na);
+ create();
+ }
+}
+
+function QWndCtrl() {
+ this.x = this.y = 0;
+ this.width = this.height = 0;
+ this.content = "";
+ this.visible = true;
+ this.effects = 0;
+ this.opacity = 100;
+ this.zindex = null;
+ this._wndt = this._wnde = false;
+ this.create = QWndCtrl_create;
+ this.show = QControl.nop;
+ this.focus = QControl.nop;
+ this.center = QControl.nop;
+ this.moveTo = QControl.nop;
+ this.setSize = QControl.nop;
+ this.setOpacity = QControl.nop;
+ this.setEffects = QControl.nop;
+ this.setZIndex = QControl.nop;
+ this.onShow = QControl.event;
+}
+QWndCtrl.prototype = new QControl();
+QWndCtrl.TOPZINDEX = 1000;
+QWndCtrl.GRAY = 256;
+QWndCtrl.XRAY = 512;
+QWndCtrl.INVERT = 1024;
+QWndCtrl.SHADOW = 2048;
+QWndCtrl.FADEIN = 1;
+QWndCtrl.FADEOUT = 16;
+QWndCtrl.BOXIN = 2;
+QWndCtrl.BOXOUT = 32;
+QWndCtrl.CIRCLEIN = 3;
+QWndCtrl.CIRCLEOUT = 48;
+QWndCtrl.WIPEIN = 4;
+QWndCtrl.WIPEOUT = 64;
+QWndCtrl.HBARNIN = 5;
+QWndCtrl.HBARNOUT = 80;
+QWndCtrl.VBARNIN = 6;
+QWndCtrl.VBARNOUT = 96;
+QWndCtrl.DISSOLVEIN = 7;
+QWndCtrl.DISSOLVEOUT = 112;
+QWndCtrl.HBLINDSIN = 8;
+QWndCtrl.HBLINDSOUT = 128;
+QWndCtrl.VBLINDSIN = 9;
+QWndCtrl.VBLINDSOUT = 144;
diff --git a/httemplate/images/progressbar-empty.png b/httemplate/images/progressbar-empty.png
new file mode 100644
index 0000000..318219c
--- /dev/null
+++ b/httemplate/images/progressbar-empty.png
Binary files differ
diff --git a/httemplate/images/progressbar-full.png b/httemplate/images/progressbar-full.png
new file mode 100644
index 0000000..863d8e1
--- /dev/null
+++ b/httemplate/images/progressbar-full.png
Binary files differ
diff --git a/httemplate/misc/progress.html b/httemplate/misc/progress.html
new file mode 100644
index 0000000..cbff08b
--- /dev/null
+++ b/httemplate/misc/progress.html
@@ -0,0 +1,88 @@
+<%
+ my( $jobnum ) = $cgi->param('jobnum');
+ my( $url ) = $cgi->param('url');
+ my $job = '';
+ if ( $jobnum =~ /^(\d+)$/ ) {
+ $job = qsearchs('queue', { 'jobnum' => $jobnum } );
+ }
+ if ( $job && $job->status ne 'failed' ) {
+%>
+
+<HTML>
+ <HEAD>
+ <TITLE>
+ Please wait...
+ </TITLE>
+ <META HTTP-Equiv="Cache-Control" Content="no-cache">
+ <META HTTP-Equiv="Pragma" Content="no-cache">
+ <META HTTP-Equiv="Expires" Content="0">
+
+ <!-- could do more JSRS magic and avoid refreshing... but works for now -->
+ <META HTTP-Equiv="Refresh" Content="5">
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8">
+ <P ALIGN="center">Please wait...
+ <script TYPE="text/javascript" src="../elements/qlib/control.js"></script>
+ <script TYPE="text/javascript" src="../elements/qlib/imagelist.js"></script>
+ <script TYPE="text/javascript" src="../elements/qlib/progress.js"></script>
+ <P ALIGN="center">
+ <script TYPE="text/javascript">
+ // Create imagelist
+ SEGS = new QImageList(4, 23, "../images/progressbar-empty.png", "../images/progressbar-full.png");
+
+ // Create bars
+ bar1 = new QProgress(null, "bar1", SEGS, 100);
+ bar1.set(<%= $job->statustext %>);
+ // bar1.update;
+ </script>
+ <BR><%= $job->statustext %>%
+ <P ALIGN="center">(progress of job #<%= $jobnum %>)
+ </BODY>
+</HTML>
+
+<%
+ } elsif ( !$job ) { #handle job gone case : job sucessful
+ # so close popup, redirect parent window...
+ #eidiot("write success handler (jobnum $jobnum)");
+%>
+
+<HTML>
+ <HEAD>
+ <TITLE>
+ Operation successful
+ </TITLE>
+ <META HTTP-Equiv="Cache-Control" Content="no-cache">
+ <META HTTP-Equiv="Pragma" Content="no-cache">
+ <META HTTP-Equiv="Expires" Content="0">
+
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8">
+ <SCRIPT TYPE="text/javascript">
+ top.opener.window.location.href = '<%= $cgi->param('url') %>';
+ window.close();
+ </SCRIPT>
+ </BODY>
+</HTML>
+
+<%
+ } else {
+%>
+
+ <HEAD>
+ <TITLE>
+ Error
+ </TITLE>
+ <META HTTP-Equiv="Cache-Control" Content="no-cache">
+ <META HTTP-Equiv="Pragma" Content="no-cache">
+ <META HTTP-Equiv="Expires" Content="0">
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8">
+ <P ALIGN="center"><FONT COLOR="#ff0000">Error: <%= $job ? $job->statustext : $jobnum %></FONT>
+ <P ALIGN="center"><INPUT TYPE="button" onClick="top.opener.document.OneTrueForm.submit.disabled=false; window.close();" VALUE="OK">
+ </BODY>
+</HTML>
+
+<% } %>
+
+
+