John Gray | 11 Oct 2007 00:43
Favicon

[webmin-devel] Virtualmin and mail server support...

I just started using virtualmin, for the most part I really like it.  I
particularly like the plugin support.  I was able to write a plugin for
a few misc things we need when a virtual server is created quite easily.
(I'd post it, but I doubt its useful to anybody but me).

One of the issues I ran into is that we use exim.  Truth by told I don't
really need virtualmin to do much here, but manage some alias file
entries.  But I had to hack into things to get that going.  I hacked the
create_virtuser and its associates to call down the plugins so they
could manage my exim aliases entries.  That worked quite nicely.  Fairly
minimum changes to the  virtualmin code, but it got the info I needed
down to my own code. (btw, virtualmin believes I'm running postfix).

This all got me thinking about cleaner ways to handle the mail server
support.  Something like the plugin model, where support for different
smtp servers is done with a plugin per smtp server (or several in the
case of qmail).  Obviously a particular install would only want to use
one plugin for that matches its mail server.  This would have a couple
of nice upsides.  One the code would be cleaner (each module would only
have code for one smtp model).  And it makes it easier to add smtp
servers (in my case a highly non-standard exim configuration).  Is the
mail server support just to woven in to easily pull this off?

Is there any plans for anything like this? I sincerely doubt the I'm the
first to think of it.

Any plans to support exim?  I suppose one stumbling block is defining
exactly what a standard exim config is?

Thanks,
(Continue reading)

Jamie Cameron | 11 Oct 2007 06:34

Re: [webmin-devel] Virtualmin and mail server support...

On 10/Oct/2007 15:43 John Gray wrote ..
> I just started using virtualmin, for the most part I really like it.  I
> particularly like the plugin support.  I was able to write a plugin for
> a few misc things we need when a virtual server is created quite easily.
> (I'd post it, but I doubt its useful to anybody but me).

Hi John,

I'm glad to hear that someone else has used the plugin API successfully ..
hopefully it wasn't too baroque. I write a few plugins myself, but the
real test of an API is how easy it is for others to use :)

> One of the issues I ran into is that we use exim.  Truth by told I don't
> really need virtualmin to do much here, but manage some alias file
> entries.  But I had to hack into things to get that going.  I hacked the
> create_virtuser and its associates to call down the plugins so they
> could manage my exim aliases entries.  That worked quite nicely.  Fairly
> minimum changes to the  virtualmin code, but it got the info I needed
> down to my own code. (btw, virtualmin believes I'm running postfix).

The way the code is structured currently, the only way to implement
exim support would be in the core of Virtualmin - plugins cannot yet
add supported mailservers, as the code for handing email aliases and
virtual domains is scattered throughout the core.

I wouldn't be too hard to add exim support though - all the code
that deals with the mail server is in virtual-server-lib-funcs.pl and
feature-mail.pl . If you look for all references to $config{'mail_system'},
you can see the if statements that trigger different behaviour based
on whether the system is running Sendmail, Postfix or Qmail.
(Continue reading)

John Gray | 11 Oct 2007 14:32
Favicon

Re: [webmin-devel] Virtualmin and mail server support...

Jamie Cameron wrote:
> On 10/Oct/2007 15:43 John Gray wrote ..
>   
>> I just started using virtualmin, for the most part I really like it.  I
>> particularly like the plugin support.  I was able to write a plugin for
>> a few misc things we need when a virtual server is created quite easily.
>> (I'd post it, but I doubt its useful to anybody but me).
>>     
>
> Hi John,
>
> I'm glad to hear that someone else has used the plugin API successfully ..
> hopefully it wasn't too baroque. I write a few plugins myself, but the
> real test of an API is how easy it is for others to use :)
>
>   
Hi Jamie,

I can give you a little feedback on the ups and downs of a newbie
creating his/her first plugin.  First off having a template plugin would
be very nice.  I ended copying a very simple plugin, then replacing the
guts with my own.  The next hurdle was getting it registered.  I ended
up running the create_domain.pl through the perl debugger and noticed it
was getting the plugins form some config option that did not have my
plugin listed.  I'm not sure what I missed when adding it through the
web interface, but I ended up adding it to the config by hand.  The last
thing, would be hints on the debugging.  I eventually figured out figure
how to get into my plugin quickly by running the perl debugger on
create_domain.pl or delete_domain.pl and jumping to just the right lines
(maybe this is short coming on my perl debugger knowledge, I can't seem
(Continue reading)

Jean-Christophe Dubois | 11 Oct 2007 20:26
Gravatar

[webmin-devel] [RFC] patches for fdisk modules

Hi,

I proposed this patch on the forum but there was not much attention there. So 
maybe this list is more appropriate.

In my system I have a bunch of SATA disks that are handled as SCSI devices by 
the Linux kernel. As a consequence, in the fdisk module these disks don't get 
the "IDE parameter" or "SMART" links.

The patch below allows these links to be enabled for these disks. I guess 
the "IDE parameter" link is more questionable as not all IDE options are 
available on SATA. However this is working well enough for me.

I may have missed some implication with RAID devices and such but I don't have 
any to test with.

Comments are welcome.

JC

--- fdisk/index.cgi.org	2007-10-10 12:16:50.000000000 +0200
+++ fdisk/index.cgi	2007-10-10 12:21:57.000000000 +0200
 <at>  <at>  -44,12 +44,12  <at>  <at> 

 	# Show links to other modules
 	 <at> links = ( );
-	if ($d->{'type'} eq 'ide' && $ed) {
+	if ($ed && ($d->{'type'} eq 'ide' || ($d->{'type'} eq 'scsi' && 
$d->{'model'} =~ /ATA /))) {
 		# Display link to IDE params form
(Continue reading)

Jamie Cameron | 11 Oct 2007 20:28

Re: [webmin-devel] Virtualmin and mail server support...

On 11/Oct/2007 05:32 John Gray wrote ..
> Jamie Cameron wrote:
> > On 10/Oct/2007 15:43 John Gray wrote ..
> >   
> >> I just started using virtualmin, for the most part I really like it.  I
> >> particularly like the plugin support.  I was able to write a plugin for
> >> a few misc things we need when a virtual server is created quite easily.
> >> (I'd post it, but I doubt its useful to anybody but me).
> >>     
> >
> > Hi John,
> >
> > I'm glad to hear that someone else has used the plugin API successfully ..
> > hopefully it wasn't too baroque. I write a few plugins myself, but the
> > real test of an API is how easy it is for others to use :)
> >
> >   
> Hi Jamie,
> 
> I can give you a little feedback on the ups and downs of a newbie
> creating his/her first plugin.  First off having a template plugin would
> be very nice.

That's a good idea - I'll create one and link to it from the plugin docs.

> I ended copying a very simple plugin, then replacing the
> guts with my own.  The next hurdle was getting it registered.  I ended
> up running the create_domain.pl through the perl debugger and noticed it
> was getting the plugins form some config option that did not have my
> plugin listed.  I'm not sure what I missed when adding it through the
(Continue reading)

Jamie Cameron | 11 Oct 2007 20:33

Re: [webmin-devel] [RFC] patches for fdisk modules

On 11/Oct/2007 11:26 Jean-Christophe Dubois wrote ..
> Hi,
> 
> I proposed this patch on the forum but there was not much attention there. So 
> maybe this list is more appropriate.
> 
> In my system I have a bunch of SATA disks that are handled as SCSI devices by 
> the Linux kernel. As a consequence, in the fdisk module these disks don't get 
> the "IDE parameter" or "SMART" links.
> 
> The patch below allows these links to be enabled for these disks. I guess 
> the "IDE parameter" link is more questionable as not all IDE options are 
> available on SATA. However this is working well enough for me.
> 
> I may have missed some implication with RAID devices and such but I don't have
> any to test with.

Thanks for the patch - I will include this in the next Webmin release.

I read the mailing list much more often than the forums, you if you have
a patch, the best way to get it integrated is to email me directly or post it here..

 - Jamie

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
-
(Continue reading)

Hugo Cornelis | 12 Oct 2007 16:26
Picon
Favicon

Re: [webmin-devel] Virtualmin and mail server support...



Jamie Cameron <jcameron <at> webmin.com> wrote:
Yeah, I find STDERR debugging with Data::Dumper to the best method in
Webmin, as often you are dealing with CGIs that are hard to attach a
regular debugger to.

What I often do to debug perl CGI scripts, is run them over Devel::ptkdb, a debugger that allows to set breakpoints and has an easy to use interface.

To open the debugger window on the right X-server, you can set the DISPLAY variable in the first BEGIN block of the CGI script (e.g. to point to the same display as where you run the browser that makes the http request).

I also use a rotating one shot log to debug scripts.  The rotation is important to track down a sequence of redirections.

Hope this helps.


Hugo



Fussy? Opinionated? Impossible to please? Perfect. Join Yahoo!'s user panel and lay it on us.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
-
Forwarded by the Webmin development list at webmin-devel <at> webmin.com
To remove yourself from this list, go to
http://lists.sourceforge.net/lists/listinfo/webadmin-devel
Jean-Christophe Dubois | 13 Oct 2007 12:38
Gravatar

[webmin-devel] [RFC] cosmetic change for edit_hdparm.cgi

Hi,

When you are on the edit_hdparm form, there is no mention of the disk you are 
dealing with. This is not so bad when you have only one disk and most of the 
time you know for which disk you are editing the parametersµ.

However if you have numerous disks, it doesn't hurt to remind the user which 
disk it is playing with.

This is what this patch is doing.

JC

--- ./fdisk/edit_hdparm.cgi.org	2007-10-11 22:04:39.000000000 +0200
+++ ./fdisk/edit_hdparm.cgi	2007-10-12 18:32:46.000000000 +0200
 <at>  <at>  -33,7 +33,7  <at>  <at> 
 print(
 "<form action=apply_hdparm.cgi><table border cols=1 width=\"100%\"><input 
type=hidden name=drive value=", $d -> { 'device' }, ">",
     "<tr ", $tb, ">",
-    	"<td><b>", $text{ 'hdparm_label' }, "</b></td>",
+    	"<td><b>", $d -> { 'desc' }, " (", $d->{'device'},  "): ", 
$text{ 'hdparm_label' }, "</b></td>",
     "</tr><tr ", $cb, "><td>",
 	"<table width=\"100%\">",
 	    "<tr>",

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
-
Forwarded by the Webmin development list at webmin-devel <at> webmin.com
To remove yourself from this list, go to
http://lists.sourceforge.net/lists/listinfo/webadmin-devel

Jamie Cameron | 13 Oct 2007 23:03

Re: [webmin-devel] [RFC] cosmetic change for edit_hdparm.cgi

That's a good suggestion - I will include this patch in the next Webmin release.

 - Jamie

On 13/Oct/2007 03:38 Jean-Christophe Dubois wrote ..
> Hi,
> 
> When you are on the edit_hdparm form, there is no mention of the disk you are 
> dealing with. This is not so bad when you have only one disk and most of the 
> time you know for which disk you are editing the parametersµ.
> 
> However if you have numerous disks, it doesn't hurt to remind the user which 
> disk it is playing with.
> 
> This is what this patch is doing.
> 
> JC
> 
> --- ./fdisk/edit_hdparm.cgi.org	2007-10-11 22:04:39.000000000 +0200
> +++ ./fdisk/edit_hdparm.cgi	2007-10-12 18:32:46.000000000 +0200
>  <at>  <at>  -33,7 +33,7  <at>  <at> 
>  print(
>  "<form action=apply_hdparm.cgi><table border cols=1 width=\"100%\"><input 
> type=hidden name=drive value=", $d -> { 'device' }, ">",
>      "<tr ", $tb, ">",
> -    	"<td><b>", $text{ 'hdparm_label' }, "</b></td>",
> +    	"<td><b>", $d -> { 'desc' }, " (", $d->{'device'},  "): ", 
> $text{ 'hdparm_label' }, "</b></td>",
>      "</tr><tr ", $cb, "><td>",
>  	"<table width=\"100%\">",
>  	    "<tr>",
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
-
Forwarded by the Webmin development list at webmin-devel <at> webmin.com
To remove yourself from this list, go to
http://lists.sourceforge.net/lists/listinfo/webadmin-devel
Jean-Christophe Dubois | 18 Oct 2007 09:42
Gravatar

[webmin-devel] [RFC] replace "Standby timeout" field in edit_hdparm.cgi with a "slider"

Hi,

The input field for the "Standby timeout" is not very user friendly. Its value varies from 0 to 255 without
any hint of what means each value.

So I propose to replace this simple field with a javascript based slider that will describe in full word what
the timeout value really is. 
It is easier to have a timeout value of "5 minutes" rather than the corresponding 60 field value.

So I Incorporated the work of Erik Arvidsson at http://webfx.eae.net/dhtml/slider/slider.html. 
His code is under "Apache License, Version 2.0" so I assume there should be no problem to incorporate it in webmin.

Maybe these javascript classes could be incorporated more globally in 
webmin so that they become a common services and can be used by other modules.

Regards

JC

diff -urN webmin.org/fdisk/edit_hdparm.cgi webmin/fdisk/edit_hdparm.cgi
--- webmin.org/fdisk/edit_hdparm.cgi	2007-10-17 15:41:33.000000000 +0200
+++ webmin/fdisk/edit_hdparm.cgi	2007-10-17 00:59:54.000000000 +0200
 <at>  <at>  -31,6 +31,13  <at>  <at> 
 }

 print(
+"<script type=\"text/javascript\" src=\"range.js\"></script>
+<script type=\"text/javascript\" src=\"timer.js\"></script>
+<script type=\"text/javascript\" src=\"slider.js\"></script>
+<link type=\"text/css\" rel=\"StyleSheet\" href=\"winclassic.css\" />");
+
+
+print(
 "<form action=apply_hdparm.cgi><table border cols=1 width=\"100%\"><input type=hidden name=drive
value=", $d -> { 'device' }, ">",
     "<tr ", $tb, ">",
     	"<td><b>", $text{ 'hdparm_label' }, "</b></td>",
 <at>  <at>  -52,7 +59,49  <at>  <at> 
 		"<td>", &l_radio( $text{ 'hdparm_conf_r' }, 'r',  <at> yesno ), "</td>",
 		"<td>", &l_radio( $text{ 'hdparm_conf_P' }, 'P',  <at> yesno ), "</td>",
 	    "</tr><tr>",
-		"<td>", &hlink( "<b>". $text{ 'hdparm_conf_S' }. "</b>", "S" ), " ", &p_entry( "S", 6, $hdparm{ 'S' } ), "</td>",
+		"<td>", &hlink( "<b>". $text{ 'hdparm_conf_S' }. "</b>", "S" ), "</td>", "<td>", &p_slider( "S", 0,
251, 0), 
+"<script type=\"text/javascript\">
+
+var s = new Slider(document.getElementById(\"S-slider\"),
+                   document.getElementById(\"S-slider-input\"));
+
+function format_time(t_sec) {
+	
+	if ( t_sec >= 3600 ) {
+		var t_hour = (t_sec - (t_sec % 3600))/3600;
+		return t_hour + \" hours \" + format_time(t_sec % 3600);
+	} else if ( t_sec >= 60 ){
+		var t_min = (t_sec - (t_sec % 60))/60;
+		return t_min + \" minutes \" + format_time(t_sec % 60);;
+	} else if ( t_sec > 0 ){
+		return t_sec + \" seconds \";
+	} else {
+		return \" \";
+	}
+};
+
+s.onchange = function () {
+	var flag = s.getValue();
+	var t_sec = 0;
+	if (flag < 241) {
+		t_sec = flag * 5;
+	} else {
+		t_sec = (flag -240) * 30 * 60;
+	}
+
+	document.getElementById(\"S-id\").value = s.getValue();
+	if (t_sec == 0) {
+		document.getElementById(\"S-text-id\").value = \"always on\";
+	} else {
+		document.getElementById(\"S-text-id\").value = format_time(t_sec);
+	}
+};
+
+s.setValue(0);
+s.setMinimum(0);
+s.setMaximum(251);
+
+</script></td>",
 	    "</tr>",
 	"</table><table>",
 	    "<tr><td>", &l_radio( $text{ 'hdparm_conf_c' }, 'c', ( "0", $text{ 'hdparm_disable' }, "1", $text{
'hdparm_enable' }, "3", $text{ 'hdparm_enable_special' } ) ), "</td></tr>",
 <at>  <at>  -90,11 +139,25  <at>  <at> 
     return $out;
 }

+sub p_slider
+{
+   my ( $name, $min, $max, $default ) =  <at> _;
+   local $out;
+
+   $out .= "<div class=\"slider\" id=\"". $name ."-slider\" tabIndex=\"1\">";
+   $out .= "<input class=\"slider-input\" id=\"".$name."-slider-input\"";
+   $out .= " name=\"".$name."-slider-input\"/></div></td><td>";
+   $out .= " <input type=\"hidden\" name=\"".$name."\" id=\"".$name."-id\" value=".$default." >";
+   $out .= "<input type=text name=\"".$name."-text\" id=\"".$name."-text-id\" readonly
value=\"default\" >";
+
+   return $out;
+}
+
 sub p_entry
 {
     my ( $name, $size, $value ) =  <at> _;

-    $size ? return "</td> <td><input name=". $name. " size=". $size." value=\"". $value."\">" : return
"</td> <td><input name=". $name. " value=\"". $value."\">";
+    $size ? return "</td> <td><input name=\"". $name. "\" id=\"". $name. "-id\" size=". $size." value=\"".
$value."\">" : return "</td> <td><input name=\"". $name. "\" id=\"". $name. "-id\" value=\"". $value."\">";
 }

 sub p_select_wdl
diff -urN webmin.org/fdisk/range.js webmin/fdisk/range.js
--- webmin.org/fdisk/range.js	1970-01-01 01:00:00.000000000 +0100
+++ webmin/fdisk/range.js	2007-10-18 09:34:03.000000000 +0200
 <at>  <at>  -0,0 +1,132  <at>  <at> 
+/*----------------------------------------------------------------------------\
+|                                Range Class                                  |
+|-----------------------------------------------------------------------------|
+|                         Created by Erik Arvidsson                           |
+|                  (http://webfx.eae.net/contact.html#erik)                   |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| Used to  model the data  used  when working  with  sliders,  scrollbars and |
+| progress bars.  Based  on  the  ideas of  the javax.swing.BoundedRangeModel |
+| interface  defined  by  Sun  for  Java;   http://java.sun.com/products/jfc/ |
+| swingdoc-api-1.0.3/com/sun/java/swing/BoundedRangeModel.html                |
+|-----------------------------------------------------------------------------|
+|                Copyright (c) 2002, 2005, 2006 Erik Arvidsson                |
+|-----------------------------------------------------------------------------|
+| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
+| use this file except in compliance with the License.  You may obtain a copy |
+| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
+| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
+| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
+| License  for the  specific language  governing permissions  and limitations |
+| under the License.                                                          |
+|-----------------------------------------------------------------------------|
+| 2002-10-14 | Original version released                                      |
+| 2005-10-27 | Use Math.round instead of Math.floor                           |
+| 2006-05-28 | Changed license to Apache Software License 2.0.                |
+|-----------------------------------------------------------------------------|
+| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
+\----------------------------------------------------------------------------*/
+
+
+function Range() {
+	this._value = 0;
+	this._minimum = 0;
+	this._maximum = 100;
+	this._extent = 0;
+
+	this._isChanging = false;
+}
+
+Range.prototype.setValue = function (value) {
+	value = Math.round(parseFloat(value));
+	if (isNaN(value)) return;
+	if (this._value != value) {
+		if (value + this._extent > this._maximum)
+			this._value = this._maximum - this._extent;
+		else if (value < this._minimum)
+			this._value = this._minimum;
+		else
+			this._value = value;
+		if (!this._isChanging && typeof this.onchange == "function")
+			 this.onchange();
+	}
+};
+
+Range.prototype.getValue = function () {
+	return this._value;
+};
+
+Range.prototype.setExtent = function (extent) {
+	if (this._extent != extent) {
+		if (extent < 0)
+			this._extent = 0;
+		else if (this._value + extent > this._maximum)
+			this._extent = this._maximum - this._value;
+		else
+			this._extent = extent;
+		if (!this._isChanging && typeof this.onchange == "function")
+			this.onchange();
+	}
+};
+
+Range.prototype.getExtent = function () {
+	return this._extent;
+};
+
+Range.prototype.setMinimum = function (minimum) {
+	if (this._minimum != minimum) {
+		var oldIsChanging = this._isChanging;
+		this._isChanging = true;
+
+		this._minimum = minimum;
+
+		if (minimum > this._value)
+			this.setValue(minimum);
+		if (minimum > this._maximum) {
+			this._extent = 0;
+			this.setMaximum(minimum);
+			this.setValue(minimum)
+		}
+		if (minimum + this._extent > this._maximum)
+			this._extent = this._maximum - this._minimum;
+
+		this._isChanging = oldIsChanging;
+		if (!this._isChanging && typeof this.onchange == "function")
+			this.onchange();
+	}
+};
+
+Range.prototype.getMinimum = function () {
+	return this._minimum;
+};
+
+Range.prototype.setMaximum = function (maximum) {
+	if (this._maximum != maximum) {
+		var oldIsChanging = this._isChanging;
+		this._isChanging = true;
+
+		this._maximum = maximum;
+
+		if (maximum < this._value)
+			this.setValue(maximum - this._extent);
+		if (maximum < this._minimum) {
+			this._extent = 0;
+			this.setMinimum(maximum);
+			this.setValue(this._maximum);
+		}
+		if (maximum < this._minimum + this._extent)
+			this._extent = this._maximum - this._minimum;
+		if (maximum < this._value + this._extent)
+			this._extent = this._maximum - this._value;
+
+		this._isChanging = oldIsChanging;
+		if (!this._isChanging && typeof this.onchange == "function")
+			this.onchange();
+	}
+};
+
+Range.prototype.getMaximum = function () {
+	return this._maximum;
+};
diff -urN webmin.org/fdisk/slider.js webmin/fdisk/slider.js
--- webmin.org/fdisk/slider.js	1970-01-01 01:00:00.000000000 +0100
+++ webmin/fdisk/slider.js	2007-10-18 09:34:49.000000000 +0200
 <at>  <at>  -0,0 +1,489  <at>  <at> 
+/*----------------------------------------------------------------------------\
+|                                Slider 1.02                                  |
+|-----------------------------------------------------------------------------|
+|                         Created by Erik Arvidsson                           |
+|                  (http://webfx.eae.net/contact.html#erik)                   |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| A  slider  control that  degrades  to an  input control  for non  supported |
+| browsers.                                                                   |
+|-----------------------------------------------------------------------------|
+|                Copyright (c) 2002, 2003, 2006 Erik Arvidsson                |
+|-----------------------------------------------------------------------------|
+| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
+| use this file except in compliance with the License.  You may obtain a copy |
+| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
+| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
+| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
+| License  for the  specific language  governing permissions  and limitations |
+| under the License.                                                          |
+|-----------------------------------------------------------------------------|
+| Dependencies: timer.js - an OO abstraction of timers                        |
+|               range.js - provides the data model for the slider             |
+|               winclassic.css or any other css file describing the look      |
+|-----------------------------------------------------------------------------|
+| 2002-10-14 | Original version released                                      |
+| 2003-03-27 | Added a test in the constructor for missing oElement arg       |
+| 2003-11-27 | Only use mousewheel when focused                               |
+| 2006-05-28 | Changed license to Apache Software License 2.0.                |
+|-----------------------------------------------------------------------------|
+| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
+\----------------------------------------------------------------------------*/
+
+Slider.isSupported = typeof document.createElement != "undefined" &&
+	typeof document.documentElement != "undefined" &&
+	typeof document.documentElement.offsetWidth == "number";
+
+
+function Slider(oElement, oInput, sOrientation) {
+	if (!oElement) return;
+	this._orientation = sOrientation || "horizontal";
+	this._range = new Range();
+	this._range.setExtent(0);
+	this._blockIncrement = 10;
+	this._unitIncrement = 1;
+	this._timer = new Timer(100);
+
+
+	if (Slider.isSupported && oElement) {
+
+		this.document = oElement.ownerDocument || oElement.document;
+
+		this.element = oElement;
+		this.element.slider = this;
+		this.element.unselectable = "on";
+
+		// add class name tag to class name
+		this.element.className = this._orientation + " " + this.classNameTag + " " + this.element.className;
+
+		// create line
+		this.line = this.document.createElement("DIV");
+		this.line.className = "line";
+		this.line.unselectable = "on";
+		this.line.appendChild(this.document.createElement("DIV"));
+		this.element.appendChild(this.line);
+
+		// create handle
+		this.handle = this.document.createElement("DIV");
+		this.handle.className = "handle";
+		this.handle.unselectable = "on";
+		this.handle.appendChild(this.document.createElement("DIV"));
+		this.handle.firstChild.appendChild(
+			this.document.createTextNode(String.fromCharCode(160)));
+		this.element.appendChild(this.handle);
+	}
+
+	this.input = oInput;
+
+	// events
+	var oThis = this;
+	this._range.onchange = function () {
+		oThis.recalculate();
+		if (typeof oThis.onchange == "function")
+			oThis.onchange();
+	};
+
+	if (Slider.isSupported && oElement) {
+		this.element.onfocus		= Slider.eventHandlers.onfocus;
+		this.element.onblur			= Slider.eventHandlers.onblur;
+		this.element.onmousedown	= Slider.eventHandlers.onmousedown;
+		this.element.onmouseover	= Slider.eventHandlers.onmouseover;
+		this.element.onmouseout		= Slider.eventHandlers.onmouseout;
+		this.element.onkeydown		= Slider.eventHandlers.onkeydown;
+		this.element.onkeypress		= Slider.eventHandlers.onkeypress;
+		this.element.onmousewheel	= Slider.eventHandlers.onmousewheel;
+		this.handle.onselectstart	=
+		this.element.onselectstart	= function () { return false; };
+
+		this._timer.ontimer = function () {
+			oThis.ontimer();
+		};
+
+		// extra recalculate for ie
+		window.setTimeout(function() {
+			oThis.recalculate();
+		}, 1);
+	}
+	else {
+		this.input.onchange = function (e) {
+			oThis.setValue(oThis.input.value);
+		};
+	}
+}
+
+Slider.eventHandlers = {
+
+	// helpers to make events a bit easier
+	getEvent:	function (e, el) {
+		if (!e) {
+			if (el)
+				e = el.document.parentWindow.event;
+			else
+				e = window.event;
+		}
+		if (!e.srcElement) {
+			var el = e.target;
+			while (el != null && el.nodeType != 1)
+				el = el.parentNode;
+			e.srcElement = el;
+		}
+		if (typeof e.offsetX == "undefined") {
+			e.offsetX = e.layerX;
+			e.offsetY = e.layerY;
+		}
+
+		return e;
+	},
+
+	getDocument:	function (e) {
+		if (e.target)
+			return e.target.ownerDocument;
+		return e.srcElement.document;
+	},
+
+	getSlider:	function (e) {
+		var el = e.target || e.srcElement;
+		while (el != null && el.slider == null)	{
+			el = el.parentNode;
+		}
+		if (el)
+			return el.slider;
+		return null;
+	},
+
+	getLine:	function (e) {
+		var el = e.target || e.srcElement;
+		while (el != null && el.className != "line")	{
+			el = el.parentNode;
+		}
+		return el;
+	},
+
+	getHandle:	function (e) {
+		var el = e.target || e.srcElement;
+		var re = /handle/;
+		while (el != null && !re.test(el.className))	{
+			el = el.parentNode;
+		}
+		return el;
+	},
+	// end helpers
+
+	onfocus:	function (e) {
+		var s = this.slider;
+		s._focused = true;
+		s.handle.className = "handle hover";
+	},
+
+	onblur:	function (e) {
+		var s = this.slider
+		s._focused = false;
+		s.handle.className = "handle";
+	},
+
+	onmouseover:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		var s = this.slider;
+		if (e.srcElement == s.handle)
+			s.handle.className = "handle hover";
+	},
+
+	onmouseout:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		var s = this.slider;
+		if (e.srcElement == s.handle && !s._focused)
+			s.handle.className = "handle";
+	},
+
+	onmousedown:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		var s = this.slider;
+		if (s.element.focus)
+			s.element.focus();
+
+		Slider._currentInstance = s;
+		var doc = s.document;
+
+		if (doc.addEventListener) {
+			doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
+			doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
+		}
+		else if (doc.attachEvent) {
+			doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);
+			doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);
+			doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
+			s.element.setCapture();
+		}
+
+		if (Slider.eventHandlers.getHandle(e)) {	// start drag
+			Slider._sliderDragData = {
+				screenX:	e.screenX,
+				screenY:	e.screenY,
+				dx:			e.screenX - s.handle.offsetLeft,
+				dy:			e.screenY - s.handle.offsetTop,
+				startValue:	s.getValue(),
+				slider:		s
+			};
+		}
+		else {
+			var lineEl = Slider.eventHandlers.getLine(e);
+			s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
+			s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
+			s._increasing = null;
+			s.ontimer();
+		}
+	},
+
+	onmousemove:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+
+		if (Slider._sliderDragData) {	// drag
+			var s = Slider._sliderDragData.slider;
+
+			var boundSize = s.getMaximum() - s.getMinimum();
+			var size, pos, reset;
+
+			if (s._orientation == "horizontal") {
+				size = s.element.offsetWidth - s.handle.offsetWidth;
+				pos = e.screenX - Slider._sliderDragData.dx;
+				reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100;
+			}
+			else {
+				size = s.element.offsetHeight - s.handle.offsetHeight;
+				pos = s.element.offsetHeight - s.handle.offsetHeight -
+					(e.screenY - Slider._sliderDragData.dy);
+				reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100;
+			}
+			s.setValue(reset ? Slider._sliderDragData.startValue :
+						s.getMinimum() + boundSize * pos / size);
+			return false;
+		}
+		else {
+			var s = Slider._currentInstance;
+			if (s != null) {
+				var lineEl = Slider.eventHandlers.getLine(e);
+				s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
+				s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
+			}
+		}
+
+	},
+
+	onmouseup:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		var s = Slider._currentInstance;
+		var doc = s.document;
+		if (doc.removeEventListener) {
+			doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
+			doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
+		}
+		else if (doc.detachEvent) {
+			doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);
+			doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);
+			doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
+			s.element.releaseCapture();
+		}
+
+		if (Slider._sliderDragData) {	// end drag
+			Slider._sliderDragData = null;
+		}
+		else {
+			s._timer.stop();
+			s._increasing = null;
+		}
+		Slider._currentInstance = null;
+	},
+
+	onkeydown:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		//var s = Slider.eventHandlers.getSlider(e);
+		var s = this.slider;
+		var kc = e.keyCode;
+		switch (kc) {
+			case 33:	// page up
+				s.setValue(s.getValue() + s.getBlockIncrement());
+				break;
+			case 34:	// page down
+				s.setValue(s.getValue() - s.getBlockIncrement());
+				break;
+			case 35:	// end
+				s.setValue(s.getOrientation() == "horizontal" ?
+					s.getMaximum() :
+					s.getMinimum());
+				break;
+			case 36:	// home
+				s.setValue(s.getOrientation() == "horizontal" ?
+					s.getMinimum() :
+					s.getMaximum());
+				break;
+			case 38:	// up
+			case 39:	// right
+				s.setValue(s.getValue() + s.getUnitIncrement());
+				break;
+
+			case 37:	// left
+			case 40:	// down
+				s.setValue(s.getValue() - s.getUnitIncrement());
+				break;
+		}
+
+		if (kc >= 33 && kc <= 40) {
+			return false;
+		}
+	},
+
+	onkeypress:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		var kc = e.keyCode;
+		if (kc >= 33 && kc <= 40) {
+			return false;
+		}
+	},
+
+	onmousewheel:	function (e) {
+		e = Slider.eventHandlers.getEvent(e, this);
+		var s = this.slider;
+		if (s._focused) {
+			s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement());
+			// windows inverts this on horizontal sliders. That does not
+			// make sense to me
+			return false;
+		}
+	}
+};
+
+
+
+Slider.prototype.classNameTag = "dynamic-slider-control",
+
+Slider.prototype.setValue = function (v) {
+	this._range.setValue(v);
+	this.input.value = this.getValue();
+};
+
+Slider.prototype.getValue = function () {
+	return this._range.getValue();
+};
+
+Slider.prototype.setMinimum = function (v) {
+	this._range.setMinimum(v);
+	this.input.value = this.getValue();
+};
+
+Slider.prototype.getMinimum = function () {
+	return this._range.getMinimum();
+};
+
+Slider.prototype.setMaximum = function (v) {
+	this._range.setMaximum(v);
+	this.input.value = this.getValue();
+};
+
+Slider.prototype.getMaximum = function () {
+	return this._range.getMaximum();
+};
+
+Slider.prototype.setUnitIncrement = function (v) {
+	this._unitIncrement = v;
+};
+
+Slider.prototype.getUnitIncrement = function () {
+	return this._unitIncrement;
+};
+
+Slider.prototype.setBlockIncrement = function (v) {
+	this._blockIncrement = v;
+};
+
+Slider.prototype.getBlockIncrement = function () {
+	return this._blockIncrement;
+};
+
+Slider.prototype.getOrientation = function () {
+	return this._orientation;
+};
+
+Slider.prototype.setOrientation = function (sOrientation) {
+	if (sOrientation != this._orientation) {
+		if (Slider.isSupported && this.element) {
+			// add class name tag to class name
+			this.element.className = this.element.className.replace(this._orientation,
+									sOrientation);
+		}
+		this._orientation = sOrientation;
+		this.recalculate();
+
+	}
+};
+
+Slider.prototype.recalculate = function() {
+	if (!Slider.isSupported || !this.element) return;
+
+	var w = this.element.offsetWidth;
+	var h = this.element.offsetHeight;
+	var hw = this.handle.offsetWidth;
+	var hh = this.handle.offsetHeight;
+	var lw = this.line.offsetWidth;
+	var lh = this.line.offsetHeight;
+
+	// this assumes a border-box layout
+
+	if (this._orientation == "horizontal") {
+		this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) /
+			(this.getMaximum() - this.getMinimum()) + "px";
+		this.handle.style.top = (h - hh) / 2 + "px";
+
+		this.line.style.top = (h - lh) / 2 + "px";
+		this.line.style.left = hw / 2 + "px";
+		//this.line.style.right = hw / 2 + "px";
+		this.line.style.width = Math.max(0, w - hw - 2)+ "px";
+		this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px";
+	}
+	else {
+		this.handle.style.left = (w - hw) / 2 + "px";
+		this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) /
+			(this.getMaximum() - this.getMinimum()) + "px";
+
+		this.line.style.left = (w - lw) / 2 + "px";
+		this.line.style.top = hh / 2 + "px";
+		this.line.style.height = Math.max(0, h - hh - 2) + "px";	//hard coded border width
+		//this.line.style.bottom = hh / 2 + "px";
+		this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px";	//hard coded border width
+	}
+};
+
+Slider.prototype.ontimer = function () {
+	var hw = this.handle.offsetWidth;
+	var hh = this.handle.offsetHeight;
+	var hl = this.handle.offsetLeft;
+	var ht = this.handle.offsetTop;
+
+	if (this._orientation == "horizontal") {
+		if (this._mouseX > hl + hw &&
+			(this._increasing == null || this._increasing)) {
+			this.setValue(this.getValue() + this.getBlockIncrement());
+			this._increasing = true;
+		}
+		else if (this._mouseX < hl &&
+			(this._increasing == null || !this._increasing)) {
+			this.setValue(this.getValue() - this.getBlockIncrement());
+			this._increasing = false;
+		}
+	}
+	else {
+		if (this._mouseY > ht + hh &&
+			(this._increasing == null || !this._increasing)) {
+			this.setValue(this.getValue() - this.getBlockIncrement());
+			this._increasing = false;
+		}
+		else if (this._mouseY < ht &&
+			(this._increasing == null || this._increasing)) {
+			this.setValue(this.getValue() + this.getBlockIncrement());
+			this._increasing = true;
+		}
+	}
+
+	this._timer.start();
+};
diff -urN webmin.org/fdisk/timer.js webmin/fdisk/timer.js
--- webmin.org/fdisk/timer.js	1970-01-01 01:00:00.000000000 +0100
+++ webmin/fdisk/timer.js	2007-10-18 09:34:25.000000000 +0200
 <at>  <at>  -0,0 +1,62  <at>  <at> 
+/*----------------------------------------------------------------------------\
+|                                 Timer Class                                 |
+|-----------------------------------------------------------------------------|
+|                         Created by Erik Arvidsson                           |
+|                  (http://webfx.eae.net/contact.html#erik)                   |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| Object Oriented Encapsulation  of setTimeout  fires ontimer when the  timer |
+| is triggered. Does not work in IE 5.00                                      |
+|-----------------------------------------------------------------------------|
+|                   Copyright (c) 2002, 2006 Erik Arvidsson                   |
+|-----------------------------------------------------------------------------|
+| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
+| use this file except in compliance with the License.  You may obtain a copy |
+| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
+| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
+| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
+| License  for the  specific language  governing permissions  and limitations |
+| under the License.                                                          |
+|-----------------------------------------------------------------------------|
+| 2002-10-14 | Original version released                                      |
+| 2006-05-28 | Changed license to Apache Software License 2.0.                |
+|-----------------------------------------------------------------------------|
+| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
+\----------------------------------------------------------------------------*/
+
+function Timer(nPauseTime) {
+	this._pauseTime = typeof nPauseTime == "undefined" ? 1000 : nPauseTime;
+	this._timer = null;
+	this._isStarted = false;
+}
+
+Timer.prototype.start = function () {
+	if (this.isStarted())
+		this.stop();
+	var oThis = this;
+	this._timer = window.setTimeout(function () {
+		if (typeof oThis.ontimer == "function")
+			oThis.ontimer();
+	}, this._pauseTime);
+	this._isStarted = false;
+};
+
+Timer.prototype.stop = function () {
+	if (this._timer != null)
+		window.clearTimeout(this._timer);
+	this._isStarted = false;
+};
+
+Timer.prototype.isStarted = function () {
+	return this._isStarted;
+};
+
+Timer.prototype.getPauseTime = function () {
+	return this._pauseTime;
+};
+
+Timer.prototype.setPauseTime = function (nPauseTime) {
+	this._pauseTime = nPauseTime;
+};
diff -urN webmin.org/fdisk/winclassic.css webmin/fdisk/winclassic.css
--- webmin.org/fdisk/winclassic.css	1970-01-01 01:00:00.000000000 +0100
+++ webmin/fdisk/winclassic.css	2007-10-18 09:34:37.000000000 +0200
 <at>  <at>  -0,0 +1,99  <at>  <at> 
+.dynamic-slider-control {
+	position:			relative;
+	background-color:	ThreeDFace;
+	-moz-user-focus:	normal;
+	-moz-user-select:	none;
+	cursor:				default;
+}
+
+.horizontal {
+	width:				200px;
+	height:				29px;
+}
+
+.vertical {
+	width:				29px;
+	height:				200px;
+}
+
+.dynamic-slider-control input {
+	display:	none;
+}
+
+.dynamic-slider-control .handle {
+	position:			absolute;
+	-moz-user-select:	none;
+	cursor:				default;
+	background:			ThreeDFace;
+	border:				1px solid;
+	border-color:		ThreeDHighlight ThreeDDarkShadow
+						ThreeDDarkShadow ThreeDHighlight;
+}
+
+/* inner border */
+.dynamic-slider-control .handle div {
+	font-size:			1px;
+	border:				1px solid;
+	border-color:		ThreeDLightShadow ThreeDShadow
+						ThreeDShadow ThreeDLightShadow;	
+
+	behavior:			url("css/boxsizing.htc");	/* ie path bug */
+	box-sizing:			content-box;
+	-moz-box-sizing:	content-box;
+}
+
+/*	inner sets size
+.dynamic-slider-control.horizontal .handle {
+	width:				12px;
+	height:				22px;
+}
+*/
+
+.dynamic-slider-control.horizontal .handle div {
+	width:				8px;
+	height:				18px;
+}
+
+.dynamic-slider-control.horizontal .handle.hover {}
+
+/* inner sets size
+.dynamic-slider-control.vertical .handle {
+	width:				22px;
+	height:				12px;
+}
+*/
+
+.dynamic-slider-control.vertical .handle div {
+	width:				18px;
+	height:				8px;
+}
+
+.dynamic-slider-control.vertical .handle.hover {}
+
+.dynamic-slider-control .line {
+	
+	behavior:			url("css/boxsizing.htc"); /* ie path bug */
+	box-sizing:			content-box;
+	-moz-box-sizing:	content-box;
+		
+	position:			absolute;
+	font-size:			0.01mm;
+	overflow:			hidden;
+	border:				1px solid;
+	border-color:		ThreeDShadow ThreeDHighlight
+						ThreeDHighlight ThreeDShadow;
+	background:			ThreeDDarkShadow;
+}
+
+.dynamic-slider-control.vertical .line {
+	width:				1px;
+	
+}
+
+.dynamic-slider-control.horizontal .line {
+	height:				1px;
+}
+
+.dynamic-slider-control .line div {
+	display:	none;
+}

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
-
Forwarded by the Webmin development list at webmin-devel <at> webmin.com
To remove yourself from this list, go to
http://lists.sourceforge.net/lists/listinfo/webadmin-devel


Gmane