diff options
author | ivan <ivan> | 2005-01-27 10:21:18 +0000 |
---|---|---|
committer | ivan <ivan> | 2005-01-27 10:21:18 +0000 |
commit | 6cf964d0dc008621fb30fd2da28e2c44f29c6364 (patch) | |
tree | 74fd5536bb89960db22d03cc95b6374711de60ef /httemplate | |
parent | e4ae5122522f2d45c68a38eaef337a82029f2fc1 (diff) |
DHTML progress bar for glacial rate adding and editing, closes: Bug#1100
Diffstat (limited to 'httemplate')
22 files changed, 1584 insertions, 56 deletions
diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html index 86e2a6b8c..898eb9ef8 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 000000000..df7c4672e --- /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 4a4b70ea3..3443f81d4 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 000000000..3a2572ccb --- /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 000000000..537aac4c8 --- /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 || " ";
+ 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 000000000..417b204e4 --- /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 = " ";
+ 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 000000000..087817211 --- /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 000000000..05247d5f8 --- /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 000000000..97f6dfccc --- /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 000000000..f50206e27 --- /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 000000000..72aeddbdb --- /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 000000000..9f12de053 --- /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 000000000..2d8b1e710 --- /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 || ' ') + '</a></div>' : '<div id="' + id + '" class="qlabel" unselectable="on">' +
+ (value || ' ') + '</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 += " ";
+ 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 000000000..2e458393d --- /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 000000000..2de077eac --- /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 000000000..3d1aaf660 --- /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 000000000..72a68fb7c --- /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 000000000..6056fda9b --- /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 000000000..b3bde4e92 --- /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>' : '"> </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 Binary files differnew file mode 100644 index 000000000..318219c77 --- /dev/null +++ b/httemplate/images/progressbar-empty.png diff --git a/httemplate/images/progressbar-full.png b/httemplate/images/progressbar-full.png Binary files differnew file mode 100644 index 000000000..863d8e1ee --- /dev/null +++ b/httemplate/images/progressbar-full.png diff --git a/httemplate/misc/progress.html b/httemplate/misc/progress.html new file mode 100644 index 000000000..cbff08b7b --- /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> + +<% } %> + + + |