Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
bf8fc46784 This commit was manufactured by cvs2svn to create tag 'release-1_2'.
git-svn-id: svn://10.0.0.236/tags/release-1_2@18222 18797224-902f-48f8-a5cc-f745e15eee43
1999-01-21 23:52:54 +00:00
270 changed files with 12261 additions and 43583 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,298 @@
1999-01-06 Leif Hedstrom <leif@netscape.com>
* Conn.pm (nextEntry): Fixed (tried to fix...) the bug with
missing attributes. I hope this will work, at a minimum I'm sure
it won't hurt. The idea is to keep the case on the attribute type
when requesting the values_len().
1999-01-11 Leif Hedstrom <leif@netscape.com>
* API.xs: Added IF statements around all ldap_value_free() calls.
1999-01-05 Leif Hedstrom <leif@netscape.com>
* Conn.pm (getRes): Ooops, didn't return the appropriate
value... :(
(init): Changed test for LDAP_SUCCESS, to always return 0 or 1.
(close): Dito.
(delete): Dito.
(add): Dito.
(modifyRDN): Dito.
(update): Dito.
(simpleAuth): Dito.
* Entry.pm (NEXTKEY): Don't return the last $key if it's one that
should be hidden.
* Conn.pm (newEntry): New method, to create an empty LDAP::Entry
object. It is properly "tied" into the appropriate object.
1999-01-04 Leif Hedstrom <leif@netscape.com>
* Entry.pm (setDN): Added third optional argument, to enfoce DN
normalization.
(getDN): Dito.
(hasDNValue): Dito.
(matchDNValue): Dito.
* Entry.pm (removeValue): Added support for DN normalization
(optional argument).
(addValue): Dito
(getDN): Dito.
1998-12-31 Leif Hedstrom <leif@netscape.com>
* Entry.pm (DESTROY): Added this method, don't know if it actually
makes any sense at all... :(
* Conn.pm (add): Use _oc_order_ to find a list of attributes, to
avoide calling the TIEHASH methods.
(update): Dito.
(ALL): Clean out some "my" definitions.
* Entry.pm (unRemove): New function, to undo remove opertaions on
an attribute.
(DELETE): Bug-fix, don't undef the attribute, it would prevent us
from updating it properly in the Conn::update() method.
(remove): Dito.
* Conn.pm (nextEntry): Return $obj instead of blessing the %entry
(again).
1998-12-25 Leif Hedstrom <leif@netscape.com>
* Conn.pm (POD): Changed examples from $conn -> $entry.
1998-12-17 Leif Hedstrom <leif@netscape.com>
* Conn.pm (DESTROY): undef the Perl data after doing a
ldap_msgfree(), bug #1964.
(search): Dito.
(searchURL): Dito.
(nextEntry): Changed the order of setting numattr, to make sure
it's zero if we don't find anything.
1998-12-16 Leif Hedstrom <leif@netscape.com>
* Entry.pm (FIRSTKEY): Modified to honor the oc_order.
(NEXTKEY): Dito.
(markModified): Made as an alias for attrModified().
* Conn.pm (nextEntry): Added code to handle internal counters for
number of attributes in oc_order. This is used/needed for the
FIRSTKEY and NEXTKEY methods in the Entry/Tie::Hash object.
* Entry.pm (isAttr): New method, to make sure an attribute name
really is a valid LDAP attribute.
(FIRSTKEY): Now we'll handle each() and keys() properly, whooohoo!
(NEXTKEY): Dito.
1998-12-15 Leif Hedstrom <leif@netscape.com>
* Entry.pm (isDeleted): Added new method, almost identical to isModified().
(EXISTS): New method, to implement the EXISTS functionality.
* API.xs (RET_CPP): Test for NULL pointers, bug #1387.
(RET_BVPP): Dito.
* Utils.pm (ldapArgs): Fixed bug where "-s 0" would not be honored
(I'm an idiot, OK?).
1998-12-14 Leif Hedstrom <leif@netscape.com>
* Conn.pm (getRes): New method, to return the internal result message.
(getLD): Use defined() around test for existence.
1998-12-11 Leif Hedstrom <leif@netscape.com>
* Conn.pm (new): Make sure binddn and bindpasswd are set to the
empty string unless specified.
(init): Make sure certdb is defined before trying to use it.
(setDefaultRebindProc): Added default auth method, unless
explicitly specified.
* Utils.pm (askPassword): Added support for Term::ReadKey.
(askPassword): Moved the eval "use ..." here.
(userCredentials): Removed verbose print statement.
(askPassword): Added an optional argument to print a prompt;
* Conn.pm (setDefaultRebindProc): Added a default "auth" value, if
not provided in the call.
1998-12-04 Leif Hedstrom <leif@netscape.com>
* Makefile.PL: Modified so that "silent" install will actually
echo what options it's setting.
It will now croak() if the SDK dir specified doesn't exist.
* INSTALL: Updated to reflect new v1.1 stuff. Added links to the
FAQ.
* README: Dito. Also changed some of the binary install
information, which might not be useful anyways...
* Makefile.PL: Added "filters" to remove .dll and .sl from shared
libraries when creating link options. I also replaced the code to
put the valid library extensions into a variable (bug #1344).
* Makefile.PL: Fixed some crap with the config parsing, and ENV
handling (for silent installs).
1998-12-03 Leif Hedstrom <leif@netscape.com>
* Conn.pm (update): Bug fix, now we empty the hash array before
examining changed attributes (bug #1385).
* Makefile.PL: Added the "-nolinenumbers" XSUBS options (bug #1329).
1998-09-26 Leif Hedstrom <leif@netscape.com>
* Conn.pm (init): Cleaned out _perror() calls.
(delete): Added support for calling delete() with an Entry::
object as paramter.
(new): Cleaned out some dead code for $ref.
* Entry.pm (setValue): New method, to avoid having to use Perl
assignment statements to set an entire attribute value.
1998-09-18 Leif Hedstrom <leif@netscape.com>
* Conn.pm (init): Changed call to ldapssl_client_init() to pass a
0 value as the handle pointer. This avoids a Perl compiler warning.
1998-09-12 Leif Hedstrom <leif@netscape.com>
* LDIF.pm (readEntries): Changed tests for empty arguments, to use
defined().
* Utils.pm (ldapArgs): Bug fix, we used the wrong option for the
certificate (-P) when checking to set the LDAP port.
(normalizeDN): Chagned tests for empty arguments, to use use defined().
* Entry.pm (STORE): Changed tests for empty arguments, to use
defined().
(DELETE): Dito.
(attrModified): Dito.
(isModified): Dito.
(remove): Dito.
(removeValue): Dito.
(addValue): Dito.
(hasValue): Dito.
(matchValue): Dito.
(setDN): Dito.
(size): Dito.
(exists): Dito.
* Conn.pm (printError): Changed test for $str to see if it's defined.
(delete): Cleaned up code around $dn.
(modifyRDN): Cleaned up testes around $dn and $del.
1998-09-11 Leif Hedstrom <leif@netscape.com>
* Conn.pm (modifyRDN): We now preserve the case of the DN/RDN, but
still treat RDNs as CIS when comparing strings.
1998-09-08 Leif Hedstrom <leif@netscape.com>
* Conn.pm (setDefaultRebindProc): Bug fix, it had the Ldapc:: crap
stil in there... :-(.
(simpleAuth): New method, to do simple authentication rebind.
1998-09-07 Leif Hedstrom <leif@netscape.com>
* Makefile.PL: Changed all <> to <STDIN>, to support command line
arguments for MakeMaker.
1998-09-03 Leif Hedstrom <leif@netscape.com>
* Conn.pm (nextEntry): Fixed bug with case sensitivity.
1998-08-18 Leif Hedstrom <leif@netscape.com>
* Conn.pm (setDefaultRebindProc): It's back!
Officially released PerLDAP v1.0.
1998-08-13 Leif Hedstrom <leif@netscape.com>
* Makefile.PL: Fixed so that automated installs works.
* Conn.pm (update): Fixed narly bug with ldap_modify()...
* All: Cleaned up some hash indexes, to make sure they are
properly quoted, and there are no conflicts to resolve.
* Entry.pm (STORE): Fixed a bug with attribute names not being
properly added to _oc_order_.
(addValue): Dito, added the same code as for STORE.
1998-08-06 Leif Hedstrom <leif@netscape.com>
* Entry.pm (printLDIF): Copied/modified from the Utils.pm library.
(isModified): Added this function, thought it might be useful.
1998-08-03 Leif Hedstrom <leif@netscape.com>
* Conn.pm (modifyRDN): Fixed! It also has an option to take an
"external" DN as an argument, if supplied.
1998-08-02 Leif Hedstrom <leif@netscape.com>
* Conn.pm (getErrorCode): Now takes two optional arguments, to
return the match string, and extra error string. Note that these
two arguments are pointers to strings!
* API.xs(ldap_get_lderrno): Fixed this function, at least it seems
to work now...
* Conn.pm (getLD): Added this function, convenient way to get the
LD from the OO layer.
1998-07-30 Leif Hedstrom <leif@netscape.com>
* Conn.pm (modifyRDN): New method, to rename the RDN of the entry.
* Utils.pm (answer): New function, from LdapUtils.pm.
* Conn.pm (delete): Fixed references to normalizeDN.
* Utils.pm (userCredentials): Added this function, to make it easy
to get credentials when binding as a user.
(normalizeDN): Fixed bugs, because of calling convention...
* Conn.pm (getError): Fixed bug with passing read-only argument.
1998-07-29 Leif Hedstrom <leif@netscape.com>
* Utils.pm (unixCrypt): Moved from my LdapUtils.pm module.
Added askPassword to the export tag.
* Conn.pm (new): Added support for passing a hash array of all the
parameters, as returned by the ldapArgs() function.
* Utils.pm (str2Scope): New function, for converting strings
(subtree) to a numerical scope value (2).
(askPassword): Dito, ask for a password, interactively.
(ldapArgs): Dito, handle common LDAP command line arguments.
* Makefile.PL: Minor change, to do regex match on OS version for
MSWin.
* Entry.pm: Changed all _XXX hash values to also end with a _,
hence making it easier to isolate them (/^_.*_$/).
* Conn.pm (nextEntry): Changed to accept that the attributes are
now arrays, not pointers to arrays. We still consider them as
pointers internally though, it's cleaner API.
* API.pm: Changed to use the native Exporter function to export
tags into EXPORT_OK.
1998-07-22 Leif Hedstrom <leif@netscape.com>
* LDIF.pm (readEntry): Moved from my LdapUtils.pm package.
* Utils.pm (printEntry): Moved from the ::Connection class, and
marked it as "obsolete".
(encodeBase64): Moved from my LdapUtils.pm package.
(decodeBase64): Dito.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,949 @@
#############################################################################
# $Id: Entry.pm,v 1.10 1999-01-21 23:52:42 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# This package defines an object class to manage one single LDAP
# entry. This entry can either be a newly created one, or one
# retrieved from an LDAP server, using the Mozilla::LDAP::Conn class.
#
#############################################################################
package Mozilla::LDAP::Entry;
use Mozilla::LDAP::Utils qw(normalizeDN);
require Tie::Hash;
@ISA = (Tie::StdHash);
#############################################################################
# Creator, make a new tie hash instance, which will keep track of all
# changes made to the hash array. This is needed so we only update modified
# attributes.
#
sub TIEHASH
{
my $class = shift;
my $self = {};
return bless $self, $class;
}
#############################################################################
# Destructor.
#
#sub DESTROY
#{
#}
#############################################################################
# Store method, to keep track of changes.
#
sub STORE
{
my ($self, $attr, $val) = ($_[$[], lc $_[$[ + 1], $_[$[ + 2]);
return unless (defined($val) && ($val ne ""));
return unless (defined($attr) && ($attr ne ""));
if (defined($self->{$attr}))
{
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
unless $self->{"_${attr}_save_"};
}
$self->{$attr} = $val;
$self->{"_${attr}_modified_"} = 1;
# Potentially add the attribute to the OC order list.
if (($attr ne "dn") && !grep(/^$attr$/i, @{$self->{"_oc_order_"}}))
{
push(@{$self->{"_oc_order_"}}, $attr);
$self->{"_oc_numattr_"}++;
}
}
#############################################################################
# Fetch method, this is case insensitive (since LDAP is...).
#
sub FETCH
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return unless defined($self->{$attr});
return if $self->{"_${attr}_deleted_"};
return $self->{$attr};
}
#############################################################################
# Delete method, to keep track of changes. Note that we actually don't
# delete the attribute, just mark it as deleted.
#
sub DELETE
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return unless (defined($attr) && ($attr ne ""));
return unless defined($self->{$attr});
$self->{"_${attr}_deleted_"} = 1;
}
#############################################################################
# See if an attribute/key exists in the entry (could still be undefined).
#
sub EXISTS
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 if $self->{"_${attr}_deleted_"};
return exists $self->{$attr};
}
#############################################################################
# Reset the each()/key() session, and return the first key. This honors
# the oc_order, i.e. the order the attributes were returned in.
#
sub FIRSTKEY
{
my ($self, $idx) = ($_[$[], 0);
my @attrs = @{$self->{"_oc_order_"}};
my $key;
while ($idx < $self->{"_oc_numattr_"})
{
$key = $attrs[$idx++];
next if ($key =~ /^_.+_$/);
next if $self->{"_${key}_deleted_"};
last;
}
$self->{"_oc_keyidx_"} = $idx;
return $key;
}
#############################################################################
# Get the next key, if appropriate.
#
sub NEXTKEY
{
my $self = $_[$[];
my $idx = $self->{"_oc_keyidx_"};
my @attrs = @{$self->{"_oc_order_"}};
my $key;
while ($idx < $self->{"_oc_numattr_"})
{
$key = $attrs[$idx++];
next if ($key =~ /^_.+_$/);
next if $self->{"_${key}_deleted_"};
last;
}
$self->{"_oc_keyidx_"} = $idx;
return if ($key =~ /^_.+_$/);
return if $self->{"_${key}_deleted_"};
return $key;
}
#############################################################################
# Mark an attribute as changed. Normally you shouldn't have to use this,
# unless you're doing something really weird...
#
sub attrModified
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
return 0 if $self->{"_${attr}_deleted_"};
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
unless $self->{"_${attr}_save_"};
$self->{"_self_obj_"}->{"_${attr}_modified_"} = 1;
return 1;
}
*markModified = \*attrModified;
#############################################################################
# Ask if a particular attribute has been modified already. Return True or
# false depending on the internal status of the attribute.
#
sub isModified
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
return $self->{"_self_obj_"}->{"_${attr}_modified_"};
}
#############################################################################
# Ask if a particular attribute has been deleted already. Return True or
# false depending on the internal status of the attribute.
#
sub isDeleted
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
return $self->{"_self_obj_"}->{"_${attr}_deleted_"};
}
#############################################################################
# Test if a attribute name is actually a real attribute, and not part of
# the internal structures.
#
sub isAttr
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
return 0 if $self->{"_${attr}_deleted_"};
return ($attr !~ /^_.+_$/);
}
#############################################################################
# Remove an attribute from the entry, basically the same as the DELETE
# method. We also make an alias for "delete" here, just in case (and to be
# somewhat backward compatible).
#
sub remove
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
$self->{"_self_obj_"}->{"_${attr}_deleted_"} = 1;
return 1;
}
*delete = \*remove;
#############################################################################
# Undo a remove(), or set of removeValues() fairly useless, to restore an
# attribute to it's original state. This is fairly useless, but hey...
#
sub unRemove
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
undef $self->{"_self_obj_"}->{"_${attr}_deleted_"};
if (defined $self->{"_${attr}_save_"})
{
@{$self->{$attr}} = @{$self->{"_${attr}_save_"}};
undef @{$selfl->{"_${key}_save_"}};
}
return 1;
}
*unDelete = \*unRemove;
#############################################################################
# Delete a value from an attribute, if it exists. NOTE: If it was the last
# value, we'll actually remove the entire attribute! We should then also
# remove it from the _oc_order_ list...
#
sub removeValue
{
my ($self, $attr, $val, $norm) = ($_[$[], lc $_[$[ + 1], $_[$[ + 2],
$_[$[ + 3]);
my $i = 0;
local $_;
return 0 unless (defined($val) && ($val ne ""));
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
$val = normalizeDN($val) if (defined($norm) && $norm);
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}} unless
defined $self->{"_${attr}_save_"};
foreach (@{$self->{$attr}})
{
$_ = normalizeDN($_) if (defined($norm) && $norm);
if ($_ eq $val)
{
splice(@{$self->{$attr}}, $i, 1);
if ($self->size($attr) > 0)
{
$self->{"_self_obj_"}->{"_${attr}_modified_"} = 1;
}
else
{
$self->{"_self_obj_"}->{"_${attr}_deleted_"} = 1;
}
return 1;
}
$i++;
}
return 0;
}
*deleteValue = \*removeValue;
#############################################################################
# Just like removeValue(), but force the DN normalization of the value.
#
sub removeDNValue
{
my ($self, $attr, $val) = ($_[$[], lc $_[$[ + 1], $_[$[ + 2]);
return $self->removeValue($attr, $val, 1);
}
*deleteDNValue = \*removeDNValue;
#############################################################################
# Add a value to an attribute. The optional third argument indicates that
# we should not enforce the uniqueness on this attibute, thus bypassing
# the test and always add the value.
#
sub addValue
{
my $self = shift;
my ($attr, $val, $force, $norm) = (lc $_[$[], $_[$[ + 1], $_[$[ + 2],
$_[$[ + 3]);
local $_;
return 0 unless (defined($val) && ($val ne ""));
return 0 unless (defined($attr) && ($attr ne ""));
if (!defined($force) || !$force)
{
my $nval = $val;
$nval = normalizeDN($val) if (defined($norm) && $norm);
foreach (@{$self->{$attr}})
{
$_ = normalizeDN($_) if (defined($norm) && $norm);
return 0 if ($_ eq $nval);
}
}
if (defined($self->{$attr}))
{
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
unless $self->{"_${attr}_save_"};
}
$self->{"_self_obj_"}->{"_${attr}_modified_"} = 1;
push(@{$self->{$attr}}, $val);
# Potentially add the attribute to the OC order list.
if (($attr ne "dn") && !grep(/^$attr$/i, @{$self->{"_oc_order_"}}))
{
push(@{$self->{"_oc_order_"}}, $attr);
$self->{"_oc_numattr_"}++;
}
return 1;
}
#############################################################################
# Just like addValue(), but force the DN normalization of the value. Note
# that we also have an $norm argument here, to normalize the DN value
# before we add it.
#
sub addDNValue
{
my $self = shift;
my ($attr, $val, $force, $norm) = (lc $_[$[], $_[$[ + 1], $_[$[ + 2],
$_[$[ + 2]);
$val = normalizeDN($val) if (defined($norm) && $norm);
return $self->addValue($attr, $val, $force, 1);
}
#############################################################################
# Set the entire value of an attribute, removing whatever was already set.
# The arguments are the name of the attribute, and then one or more values,
# passed as scalar or an array (not pointer).
#
sub setValue
{
my ($self, $attr) = (shift, lc shift);
my (@vals) = @_;
local $_;
return 0 unless (defined(@vals) && ($#vals >= $[));
return 0 unless (defined($attr) && ($attr ne ""));
$self->{$attr} = [@vals];
return 1;
}
#############################################################################
# Return TRUE or FALSE, if the attribute has the specified value. The
# optional third argument says we should do case insensitive search.
#
sub hasValue
{
my($self, $attr, $val, $nocase, $norm) = @_;
return 0 unless (defined($val) && ($val ne ""));
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
$val = normalizeDN($val) if (defined($norm) && $norm);
if ($nocase)
{
foreach (@{$self->{$attr}})
{
$_ = normalizeDN($_) if (defined($norm) && $norm);
return 1 if /^\Q$val\E$/i;
}
}
else
{
foreach (@{$self->{$attr}})
{
$_ = normalizeDN($_) if (defined($norm) && $norm);
return 1 if /^\Q$val\E$/;
}
}
return 0;
}
#############################################################################
# Just like hasValue(), but force the DN normalization of the value.
#
sub hasDNValue
{
my($self, $attr, $val, $nocase) = @_;
return $self->hasValue($attr, $val, $nocase, 1);
}
#############################################################################
# Return TRUE or FALSE, if the attribute matches the specified regexp. The
# optional third argument says we should do case insensitive search.
#
sub matchValue
{
my($self, $attr, $reg, $nocase) = @_;
return 0 unless (defined($reg) && ($reg ne ""));
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
if ($nocase)
{
foreach (@{$self->{$attr}})
{
$_ = normalizeDN($_);
return 1 if /$reg/i;
}
}
else
{
foreach (@{$self->{$attr}})
{
$_ = normalizeDN($_);
return 1 if /$reg/;
}
}
return 0;
}
#############################################################################
# Just like matchValue(), but force the DN normalization of the values.
#
sub matchDNValue
{
my($self, $attr, $reg, $nocase) = @_;
return $self->matchValue($attr, $reg, $nocase, 1);
}
#############################################################################
# Set the DN of this entry.
#
sub setDN
{
my ($self, $val, $norm) = @_;
return 0 unless (defined($val) && ($val ne ""));
$val = normalizeDN($val) if (defined($norm) && $norm);
$self->{"dn"} = $val;
return 1;
}
#############################################################################
# Get the DN of this entry.
#
sub getDN
{
my ($self, $norm) = @_;
return normalizeDN($self->{"dn"}) if (defined($norm) && $norm);
return $self->{"dn"};
}
#############################################################################
#
# Return the number of elements in an attribute.
#
sub size
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
my @val;
return 0 unless (defined($attr) && ($attr ne ""));
return 0 unless defined($self->{$attr});
@val = @{$self->{$attr}};
return $#val + 1;
}
#############################################################################
#
# Return TRUE if the attribute name is in the LDAP entry.
#
sub exists
{
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
return 0 unless (defined($attr) && ($attr ne ""));
return defined($self->{$attr});
}
#############################################################################
# Print an entry, in LDIF format. This is idential to the Utils::printEntry
# function, but this is sort of neat... Note that the support for Base64
# encoding isn't finished.
#
sub printLDIF
{
my ($self, $base64) = @_;
my $attr;
print "dn: ", $self->getDN(),"\n";
foreach $attr (@{$self->{"_oc_order_"}})
{
next if ($attr =~ /^_.+_$/);
next if $self->{"_${attr}_deleted_"};
grep((print "$attr: $_\n"), @{$self->{$attr}});
}
print "\n";
}
#############################################################################
# Mandatory TRUE return value.
#
1;
#############################################################################
# POD documentation...
#
__END__
=head1 NAME
Mozilla::LDAP::Entry.pm - Object class to hold one LDAP entry.
=head1 SYNOPSIS
use Mozilla::LDAP::Conn;
use Mozilla::LDAP::Entry;
=head1 ABSTRACT
The LDAP::Conn object is used to perform LDAP searches, updates, adds and
deletes. All such functions works on LDAP::Entry objects only. All
modifications and additions you'll do to an LDAP entry, will be done
through this object class.
=head1 DESCRIPTION
The LDAP::Entry object class is built on top of the Tie::Hash standard
object class. This gives us several powerful features, the main one being
to keep track of what is changing in the LDAP entry. This makes it very
easy to write LDAP clients that needs to update/modify entries, since
you'll just do the changes, and this object class will take care of the
rest.
We define local functions for STORE, FETCH, DELETE, EXISTS, FIRSTKEY and
NEXTKEY in this object class, and inherit the rest from the super
class. Overloading these specific functions is how we can keep track of
what is changing in the entry, which turns out to be very convenient. We
can also easily "loop" over the attribute types, ignoring internal data,
or deleted attributes.
Most of the methods here either return the requested LDAP value, or a
status code. The status code (either 0 or 1) indicates the failure or
success of a certain operation. 0 (False) meaning the operation failed,
and a return code of 1 (True) means complete success.
One thing to remember is that in LDAP, attribute names are case
insensitive. All methods in this class are aware of this, and will convert
all attribute name arguments to lower case before performing any
operations. This does not mean that the values are case insensitive. On
the contrary, all values are considered case sensitive by this module,
even if the LDAP server itself treats it as a CIS attribute.
=head1 OBJECT CLASS METHODS
The LDAP::Entry class implements many methods you can use to access and
modify LDAP entries. It is strongly recommended that you use this API as
much as possible, and avoid using the internals of the class
directly. Failing to do so may actually break the functionality.
=head2 Creating a new entry
To create a completely new entry, use the B<new> method, for instance
$entry = new Mozilla::LDAP::Entry()
$entry->setDN("uid=leif,ou=people,dc=netscape,dc=com");
$entry->{objectclass} = [ "top", "person", "inetOrgPerson" ];
$entry->addValue("cn", "Leif Hedstrom");
$entry->addValue("sn", "Hedstrom");
$entry->addValue("givenName", "Leif");
$entry->addValue("mail", "leif@netscape.com);
$conn->add($entry);
This is the minimum requirements for an LDAP entry. It must have a DN, and
it must have at least one objectclass. As it turns out, by adding the
I<person> and I<inetOrgPerson> classes, we also must provide some more
attributes, like I<CN> and I<SN>. This is because the object classes have
these attributes marked as "required", and we'd get a schema violation
without those values.
In the example above we use both native API methods to add values, and
setting an attribute entire value set directly. Note that the value set is
a pointer to an array, and not the array itself. In the example above, the
object classes are set using an anonymous array, which the API handles
properly. It's important to be aware that the attribute value list is
indeed a pointer.
Finally, as you can see there's only only one way to add new LDAP entries,
and it's called add(). It normally takes an LDAP::Entry object instance as
argument, but it can also be called with a regular hash array if so
desired.
=head2 Adding and removing attributes and values
This is the main functionality of this module. Use these methods to do any
modifications and updates to your LDAP entries.
=over 13
=item B<attrModified>
This is an internal function, that can be used to force the API to
consider an attribute (value) to have been modified. The only argument is
the name of the attribute. In almost all situation, you never, ever,
should call this. If you do, please contact the developers, and as us to
fix the API. Example
$entry->attrModified("cn");
=item B<isModified>
This is a somewhat more useful method, which will return the internal
modification status of a particular attribute. The argument is the name of
the attribute, and the return value is True or False. If the attribute has
been modified, in any way, we return True (1), otherwise we return False
(0). For example:
if ($entry->isModified("cn")) { # do something }
=item B<isDeleted>
This is almost identical to B<isModified>, except it tests if an attribute
has been deleted. You use it the same way as above, like
if (! $entry->isDeleted("cn")) { # do something }
=item B<isAttr>
This method can be used to decide if an attribute name really is a valid
LDAP attribute in the current entry. Use of this method is fairly limited,
but could potentially be useful. Usage is like previous examples, like
if ($entry->isAttr("cn")) { # do something }
The code section will only be executed if these criterias are true:
1. The name of the attribute is a non-empty string.
2. The name of the attribute does not begin, and end, with an
underscore character (_).
2. The attribute has one or more values in the entry.
=item B<remove>
This will remove the entire attribute, including all it's values, from the
entry. The only argument is the name of the attribute to remove. Let's say
you want to nuke all I<mailAlternateAddress> values (i.e. the entire
attribute should be removed from the entry):
$entry->remove("mailAlternateAddress");
=item B<removeValue>
Remove a value from an attribute, if it exists. Of course, if the
attribute has no such value, we won't try to remove it, and instead return
a False (0) status code. The arguments are the name of the attribute, and
the particular value to remove. Note that values are considered case
sensitive, so make sure you preserve case properly. An example is:
$entry->removeValue("objectclass", "nscpPerson");
=item B<removeDNValue>
This is almost identical to B<removeValue>, except it will normalize the
attribute values before trying to remove them. This is useful if you know
that the attribute is a DN value, but perhaps the values are not cosistent
in all LDAP entries. For example
$dn = "uid=Leif, dc=Netscape, dc=COM";
$entry->removeDNValue("owner", $dn);
will remove the owner "uid=leif,dc=netscape,dc=com", no matter how it's
capitalized and formatted in the entry.
=item B<addValue>
Add a value to an attribute. If the attribute value already exists, or we
couldn't add the value for any other reason, we'll return FALSE (0),
otherwise we return TRUE (1). The first two arguments are the attribute
name, and the value to add.
The optional third argument is a flag, indicating that we want to add the
attribute without checking for duplicates. This is useful if you know the
values are unique already, or if you perhaps want to allow duplicates for
a particular attribute. To add a CN to an existing entry/attribute, do:
$entry->addValue("cn", "Leif Hedstrom");
=item B<addDNValue>
Just like B<addValue>, except this method assume the value is a DN
attribute. For instance
$dn = "uid=Leif, dc=Netscape, dc=COM";
$entry->addDNValue("uniqueMember", $dn);
will only add the DN for "uid=leif" if it does not exist as a DN in the
uniqueMember attribute.
=item B<setValue>
Set the specified attribute to the new value (or values), overwriting
whatever old values it had before. This is a little dangerous, since you
can lose attribute values you didn't intend to remove. Therefore, it's
usually recommended to use B<removeValue()> and B<setValue()>. If you know
exactly what the new values should be like, you can use this method like
$entry->setValue("cn", "Leif Hedstrom", "The Swede");
$entry->setValue("mail", @mailAddresses);
or if it's a single value attribute,
$entry->setValue("uidNumber", "12345");
=item B<hasValue>
Return TRUE or FALSE if the attribute has the specified value. A typical
usage is to see if an entry is of a certain object class, e.g.
if ($entry->hasValue("objectclass", "person", 1)) { # do something }
The (optional) third argument indicates if the string comparison should be
case insensitive or not. The first two arguments are the name and value of
the attribute, as usual.
=item B<hasDNValue>
Exactly like B<hasValue>, except we assume the attribute values are DN
attributes.
=item B<matchValue>
This is very similar to B<hasValue>, except it does a regular expression
match instead of a full string match. It takes the same arguments,
including the optional third argument to specify case insensitive
matching. The usage is identical to the example for hasValue, e.g.
if ($entry->matchValue("objectclass", "pers", 1)) { # do something }
=item B<matchDNValue>
Like B<matchValue>, except the attribute values are considered being DNs.
=item B<setDN>
Set the DN to the specified value. Only do this on new entries, it will
not work well if you try to do this on an existing entry. If you wish to
renamed an entry, use the Mozilla::Conn::modifyRDN method instead.
Eventually we'll provide a complete "rename" method. To set the DN for a
newly created entry, we can do
$entry->setDN("uid=leif,ou=people,dc=netscape,dc=com");
There is an optional third argument, a boolean flag, indicating that we
should normalize the DN before setting it. This will assure a consistent
format of your DNs.
=item B<getDN>
Return the DN for the entry. For instance
print "The DN is: ", $entry->getDN(), "\n";
Just like B<setDN>, this method also has an optional argument, which
indicates we should normalize the DN before returning it to the caller.
=item B<size>
Return the number of values for a particular attribute. For instance
$entry->{cn} = [ "Leif Hedstrom", "The Swede" ];
$numVals = $entry->size("cn");
This will set C<$numVals> to two (2). The only argument is the name of the
attribute, and the return value is the size of the value array.
=item B<exists>
Return TRUE if the specified attribute is defined in the LDAP entry. This
is useful to know if an entry has a particular attribute, regardless of
the value. For instance:
if ($entry->exists("jpegphoto")) { # do something special }
=item B<printLDIF>
Print the entry (on STDOUT) in a format called LDIF (LDAP Data Interchange
Format, RFC xxxx). An example of an LDIF entry is:
dn: uid=leif,ou=people,dc=netscape,dc=com
objectclass: top
objectclass: person
objectclass: inetOrgPerson
uid: leif
cn: Leif Hedstrom
mail: leif@netscape.com
The above would be the result of
$entry->printLDIF();
If you need to write to a file, close STDOUT, and open up a file with that
file handle instead. For more useful LDIF functionality, check out the
Mozilla::LDAP::LDIF.pm module.
=back
=head2 Deleting entries
To delete an LDAP entry from the LDAP server, you have to use the
B<delete> method from the Mozilla::LDAP::Conn module. It will actually
delete any entry, if you provide an legitimate DN.
=head2 Renaming entries
Again, there's no functionality in this object class to rename the entry
(i.e. changing it's DN). For now, there is a way to modify the RDN
component of a DN through the Mozilla::LDAP::Conn module, with
B<modifyRDN>. Eventually we hope to have a complete B<rename> method,
which should be capable of renaming any entry, in any way, including
moving it to a different part of the DIT (Directory Information Tree).
=head1 EXAMPLES
There are plenty of examples to look at, in the examples directory. We are
adding more examples every day (almost).
=head1 INSTALLATION
Installing this package is part of the Makefile supplied in the
package. See the installation procedures which are part of this package.
=head1 AVAILABILITY
This package can be retrieved from a number of places, including:
http://www.mozilla.org/directory/
Your local CPAN server
=head1 CREDITS
Most of this code was developed by Leif Hedstrom, Netscape Communications
Corporation.
=head1 BUGS
None. :)
=head1 SEE ALSO
L<Mozilla::LDAP::Conn>, L<Mozilla::LDAP::API>, and of course L<Perl>.
=cut

View File

@@ -0,0 +1,98 @@
PerLDAP installation instructions
==================================
Building this package is fairly straight forward, but requires some
knowledge about using compilers and compiler tools on your system. If you
are uncomfortable using these tools, we recommend you get one of the
prebuilt binary distributions instead.
Prerequisites
=============
In order to build the module, you'll need
- Perl, version 5.003 or later. We definitely recommend you to use
v5.004 or later.
- An ANSI-C compiler, e.g. gcc-2.x, or Visual C++ 5.0.
- The LDAP client libraries and include files, e.g. the SDK from
Netscape Communications. See the README file for information on
retrieving binaries.
You can download (or CVS checkout) the Directory SDK source, see further
information available on
http://www.mozilla.org/directory/
and the FAQ at
http://www.mozilla.org/directory/faq/perldap-faq.html
Building
========
This package uses the normal Perl5 MakeMaker installation system. To
generate a Makefile appropriate for your platform, run perl on the
provided Makefile.PL script, e.g.
% perl Makefile.PL
You might have to use the command `perl5' or `perl-5.004', depending on
how you installed Perl-5. The script will now ask you a few questions to
find the necessary library and include files. A typical configuration
session is
data 195% perl5 Makefile.PL
PerLDAP - Perl 5 Module for LDAP
================================
Directory containing 'include' and 'lib' directory of the Netscape
LDAP Software Developer Kit (default: /usr): /opt/ldapsdk3
Using LDAPv3 Developer Kit (default: yes)?
Include SSL Support (default: yes)?
Libraries to link with (default: -L/opt/pkg/ldapsdk3/lib -lldapssl30):
Checking if your kit is complete...
Looks good
Writing Makefile for Mozilla::LDAP::API
The important question is where your LDAP SDK is installed, in the example
above the base directory is /opt/ldapsdk3. This directory should have two
subdirectories, named "lib" and "include". If you installed the SDK in the
standard /usr hierarchy, use the default value as provided by the install
script.
Assuming you get no errors or warning, proceed with the build and install:
% make
% make install
That should be it!
Automated Configuration and Installs
====================================
The Makefile.PL script also honors a set of environment variables to make
it possible to do configuration and installs non-interactively. The
variables are
LDAPSDKDIR - Full path to the C SDK base directory
LDAPV3ON - Set to "N" to diable LDAP v3 (on by default)
LDAPSDKSSL - Set to "N" to disable SSL (SSL is default)
With these variables set, you will not be asked any of the questions above
(but it will echo the paramaters). Just run the Makefile.PL script, and
finish the build, e.g.
% perl5 Makefile.PL
% make
% make install

View File

@@ -0,0 +1,274 @@
#############################################################################
# $Id: LDIF.pm,v 1.6 1999-01-21 23:52:42 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Simple routines to read and write LDIF style files. You should open
# the input/output file manually, or use STDIN/STDOUT.
#
#############################################################################
package Mozilla::LDAP::LDIF;
use Mozilla::LDAP::Entry;
use Mozilla::LDAP::Utils(qw(decodeBase64));
#############################################################################
# Creator, the argument (optional) is the file handle.
#
sub new
{
my ($class, $fh) = @_;
my $self = {};
if ($fh)
{
$self->{"_fh_"} = $fh;
$self->{"_canRead_"} = 1;
$self->{"_canWrite_"} = 1;
}
else
{
$self->{"_fh_"} = STDIN;
$self->{"_canRead_"} = 1;
$self->{"_canWrite_"} = 0;
}
return bless $self, $class;
}
#############################################################################
# Destructor, close file descriptors etc. (???)
#
#sub DESTROY
#{
# my $self = shift;
#}
#############################################################################
# Read the next $entry from an ::LDIF object. No arguments
#
sub readOneEntry
{
my ($self) = @_;
my ($attr, $val, $entry, $base64, $fh);
local $_;
return unless $self->{"_canRead_"};
return unless defined($self->{"_fh_"});
# Skip leading empty lines.
$fh = $self->{"_fh_"};
while (<$fh>)
{
chop;
last unless /^\s*$/;
}
return if /^$/; # EOF
$self->{"_canWrite_"} = 0 if $self->{"_canWrite_"};
$entry = new Mozilla::LDAP::Entry();
do
{
# See if it's a continuation line.
if (/^ /o)
{
$val .= substr($_, 1);
}
else
{
if ($val && $attr)
{
if ($attr eq "dn")
{
$entry->setDN($val);
}
else
{
$val = decodeBase64($val) if $base64;
$entry->addValue($attr, "$val", 1);
}
}
($attr, $val) = split(/:\s+/, $_, 2);
$attr = lc $attr;
# Handle base64'ed data.
if ($attr =~ /:$/o)
{
$base64 = 1;
chop($attr);
}
else
{
$base64 = 0;
}
}
$_ = <$fh>;
chop;
} until /^\s*$/;
# Do the last attribute...
if ($attr && ($attr ne "dn"))
{
$val = decodeBase64($val) if $base64;
$entry->addValue($attr, "$val", 1);
}
return $entry;
}
*readEntry = \readOneEntry;
#############################################################################
# Print one entry, to the file handle. Note that we actually use some
# internals from the ::Entry object here, which is a no-no... Also, we need
# to support Base64 encoding of Binary attributes here.
#
sub writeOneEntry
{
my ($self, $entry) = @_;
my ($fh, $attr);
return unless $self->{"_canWrite_"};
$self->{"_canRead_"} = 0 if $self->{"_canRead_"};
$fh = $self->{"_fh_"};
print $fh "dn: ", $entry->getDN(),"\n";
foreach $attr (@{$entry->{"_oc_order_"}})
{
next if ($attr =~ /^_.+_$/);
next if $entry->{"_${attr}_deleted_"};
# TODO: Add support for Binary attributes.
grep((print $fh "$attr: $_\n"), @{$entry->{$attr}});
}
print $fh "\n";
}
*writeEntry = \writeOneEntry;
#############################################################################
# Read multiple entries, and return an array of Entry objects. The argument
# is the number to read, or read them all if not specified.
#
sub readEntries
{
my ($self, $num) = @_;
my $entry;
my (@entries);
return if (defined($num) && ($num ne "") && ($num <= 0));
$num = (-1) unless defined($num);
do
{
$entry = $self->readOneEntry();
push(@entries, $entry) if ($entry);
$num--;
} until (! $entry || $num == 0);
return @entries;
}
#############################################################################
# Write multiple entries, the argument is the array of Entry objects.
#
sub writeEntries
{
my ($self, @entries) = @_;
local $_;
foreach (@entries)
{
$self->writeOneEntry($_);
}
}
#############################################################################
# Mandatory TRUE return value.
#
1;
#############################################################################
# POD documentation...
#
__END__
=head1 NAME
Mozilla::LDAP::LDIF - Read, write and modify LDIF files.
=head1 SYNOPSIS
use Mozilla::LDAP::LDIF;
=head1 ABSTRACT
This package is used to read and write LDIF information from files
(actually, file handles). It can also be used to generate LDIF modify
files from changes made to an entry.
=head1 DESCRIPTION
The LDIF format is a simple, yet useful, text representation of an LDAP
database. The goal of this package is to make it as easy as possible to
read, parse and use LDIF data, possible generated from other information
sources.
=head1 EXAMPLES
There are plenty of examples to look at, in the examples directory. We are
adding more examples every day (almost).
=head1 INSTALLATION
Installing this package is part of the Makefile supplied in the
package. See the installation procedures which are part of this package.
=head1 AVAILABILITY
This package can be retrieved from a number of places, including:
http://www.mozilla.org/directory/
Your local CPAN server
=head1 CREDITS
Most of this code was developed by Leif Hedstrom, Netscape Communications
Corporation.
=head1 BUGS
None. :)
=head1 SEE ALSO
L<Mozilla::LDAP::Conn>, L<Mozilla::LDAP::Entry>, L<Mozilla::LDAP::API>,
and of course L<Perl>.
=cut

View File

@@ -0,0 +1,33 @@
ChangeLog
API.pm
API.xs
MANIFEST
Makefile.PL
constant.h
test.pl
typemap
Entry.pm
Conn.pm
LDIF.pm
Utils.pm
README
INSTALL
MPL-1.0.txt
test_api/search.pl
test_api/write.pl
test_api/api.pl
t/conn.pl
t/entry.pl
t/ChangeLog
examples/ChangeLog
examples/lfinger.pl
examples/qsearch.pl
examples/monitor.pl
examples/ldappasswd.pl
examples/rmentry.pl
examples/tabdump.pl
examples/modattr.pl
examples/rename.pl
examples/psoftsync.pl
examples/changes2ldif.pl
install-bin

View File

@@ -0,0 +1,360 @@
MOZILLA PUBLIC LICENSE
Version 1.0
----------------
1. Definitions.
1.1. ``Contributor'' means each entity that creates or contributes to
the creation of Modifications.
1.2. ``Contributor Version'' means the combination of the Original
Code, prior Modifications used by a Contributor, and the Modifications
made by that particular Contributor.
1.3. ``Covered Code'' means the Original Code or Modifications or the
combination of the Original Code and Modifications, in each case
including portions thereof.
1.4. ``Electronic Distribution Mechanism'' means a mechanism generally
accepted in the software development community for the electronic
transfer of data.
1.5. ``Executable'' means Covered Code in any form other than Source
Code.
1.6. ``Initial Developer'' means the individual or entity identified as
the Initial Developer in the Source Code notice required by Exhibit A.
1.7. ``Larger Work'' means a work which combines Covered Code or
portions thereof with code not governed by the terms of this License.
1.8. ``License'' means this document.
1.9. ``Modifications'' means any addition to or deletion from the
substance or structure of either the Original Code or any previous
Modifications. When Covered Code is released as a series of files, a
Modification is:
A. Any addition to or deletion from the contents of a file
containing Original Code or previous Modifications.
B. Any new file that contains any part of the Original Code or
previous Modifications.
1.10. ``Original Code'' means Source Code of computer software code
which is described in the Source Code notice required by Exhibit A as
Original Code, and which, at the time of its release under this License
is not already Covered Code governed by this License.
1.11. ``Source Code'' means the preferred form of the Covered Code for
making modifications to it, including all modules it contains, plus any
associated interface definition files, scripts used to control
compilation and installation of an Executable, or a list of source code
differential comparisons against either the Original Code or another
well known, available Covered Code of the Contributor's choice. The
Source Code can be in a compressed or archival form, provided the
appropriate decompression or de-archiving software is widely available
for no charge.
1.12. ``You'' means an individual or a legal entity exercising rights
under, and complying with all of the terms of, this License or a future
version of this License issued under Section 6.1. For legal entities,
``You'' includes any entity which controls, is controlled by, or is
under common control with You. For purposes of this definition,
``control'' means (a) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (b) ownership of fifty percent (50%) or more of the
outstanding shares or beneficial ownership of such entity.
2. Source Code License.
2.1. The Initial Developer Grant.
The Initial Developer hereby grants You a world-wide, royalty-free,
non-exclusive license, subject to third party intellectual property
claims:
(a) to use, reproduce, modify, display, perform, sublicense and
distribute the Original Code (or portions thereof) with or without
Modifications, or as part of a Larger Work; and
(b) under patents now or hereafter owned or controlled by Initial
Developer, to make, have made, use and sell (``Utilize'') the
Original Code (or portions thereof), but solely to the extent that
any such patent is reasonably necessary to enable You to Utilize
the Original Code (or portions thereof) and not to any greater
extent that may be necessary to Utilize further Modifications or
combinations.
2.2. Contributor Grant.
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license, subject to third party intellectual property
claims:
(a) to use, reproduce, modify, display, perform, sublicense and
distribute the Modifications created by such Contributor (or
portions thereof) either on an unmodified basis, with other
Modifications, as Covered Code or as part of a Larger Work; and
(b) under patents now or hereafter owned or controlled by
Contributor, to Utilize the Contributor Version (or portions
thereof), but solely to the extent that any such patent is
reasonably necessary to enable You to Utilize the Contributor
Version (or portions thereof), and not to any greater extent that
may be necessary to Utilize further Modifications or combinations.
3. Distribution Obligations.
3.1. Application of License.
The Modifications which You create or to which You contribute are
governed by the terms of this License, including without limitation
Section 2.2. The Source Code version of Covered Code may be distributed
only under the terms of this License or a future version of this
License released under Section 6.1, and You must include a copy of this
License with every copy of the Source Code You distribute. You may not
offer or impose any terms on any Source Code version that alters or
restricts the applicable version of this License or the recipients'
rights hereunder. However, You may include an additional document
offering the additional rights described in Section 3.5.
3.2. Availability of Source Code.
Any Modification which You create or to which You contribute must be
made available in Source Code form under the terms of this License
either on the same media as an Executable version or via an accepted
Electronic Distribution Mechanism to anyone to whom you made an
Executable version available; and if made available via Electronic
Distribution Mechanism, must remain available for at least twelve (12)
months after the date it initially became available, or at least six
(6) months after a subsequent version of that particular Modification
has been made available to such recipients. You are responsible for
ensuring that the Source Code version remains available even if the
Electronic Distribution Mechanism is maintained by a third party.
3.3. Description of Modifications.
You must cause all Covered Code to which you contribute to contain a
file documenting the changes You made to create that Covered Code and
the date of any change. You must include a prominent statement that the
Modification is derived, directly or indirectly, from Original Code
provided by the Initial Developer and including the name of the Initial
Developer in (a) the Source Code, and (b) in any notice in an
Executable version or related documentation in which You describe the
origin or ownership of the Covered Code.
3.4. Intellectual Property Matters
(a) Third Party Claims.
If You have knowledge that a party claims an intellectual property
right in particular functionality or code (or its utilization
under this License), you must include a text file with the source
code distribution titled ``LEGAL'' which describes the claim and
the party making the claim in sufficient detail that a recipient
will know whom to contact. If you obtain such knowledge after You
make Your Modification available as described in Section 3.2, You
shall promptly modify the LEGAL file in all copies You make
available thereafter and shall take other steps (such as notifying
appropriate mailing lists or newsgroups) reasonably calculated to
inform those who received the Covered Code that new knowledge has
been obtained.
(b) Contributor APIs.
If Your Modification is an application programming interface and
You own or control patents which are reasonably necessary to
implement that API, you must also include this information in the
LEGAL file.
3.5. Required Notices.
You must duplicate the notice in Exhibit A in each file of the Source
Code, and this License in any documentation for the Source Code, where
You describe recipients' rights relating to Covered Code. If You
created one or more Modification(s), You may add your name as a
Contributor to the notice described in Exhibit A. If it is not possible
to put such notice in a particular Source Code file due to its
structure, then you must include such notice in a location (such as a
relevant directory file) where a user would be likely to look for such
a notice. You may choose to offer, and to charge a fee for, warranty,
support, indemnity or liability obligations to one or more recipients
of Covered Code. However, You may do so only on Your own behalf, and
not on behalf of the Initial Developer or any Contributor. You must
make it absolutely clear than any such warranty, support, indemnity or
liability obligation is offered by You alone, and You hereby agree to
indemnify the Initial Developer and every Contributor for any liability
incurred by the Initial Developer or such Contributor as a result of
warranty, support, indemnity or liability terms You offer.
3.6. Distribution of Executable Versions.
You may distribute Covered Code in Executable form only if the
requirements of Section 3.1-3.5 have been met for that Covered Code,
and if You include a notice stating that the Source Code version of the
Covered Code is available under the terms of this License, including a
description of how and where You have fulfilled the obligations of
Section 3.2. The notice must be conspicuously included in any notice in
an Executable version, related documentation or collateral in which You
describe recipients' rights relating to the Covered Code. You may
distribute the Executable version of Covered Code under a license of
Your choice, which may contain terms different from this License,
provided that You are in compliance with the terms of this License and
that the license for the Executable version does not attempt to limit
or alter the recipient's rights in the Source Code version from the
rights set forth in this License. If You distribute the Executable
version under a different license You must make it absolutely clear
that any terms which differ from this License are offered by You alone,
not by the Initial Developer or any Contributor. You hereby agree to
indemnify the Initial Developer and every Contributor for any liability
incurred by the Initial Developer or such Contributor as a result of
any such terms You offer.
3.7. Larger Works.
You may create a Larger Work by combining Covered Code with other code
not governed by the terms of this License and distribute the Larger
Work as a single product. In such a case, You must make sure the
requirements of this License are fulfilled for the Covered Code.
4. Inability to Comply Due to Statute or Regulation.
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Code due to statute
or regulation then You must: (a) comply with the terms of this License
to the maximum extent possible; and (b) describe the limitations and
the code they affect. Such description must be included in the LEGAL
file described in Section 3.4 and must be included with all
distributions of the Source Code. Except to the extent prohibited by
statute or regulation, such description must be sufficiently detailed
for a recipient of ordinary skill to be able to understand it.
5. Application of this License.
This License applies to code to which the Initial Developer has
attached the notice in Exhibit A, and to related Covered Code.
6. Versions of the License.
6.1. New Versions.
Netscape Communications Corporation (``Netscape'') may publish revised
and/or new versions of the License from time to time. Each version will
be given a distinguishing version number.
6.2. Effect of New Versions.
Once Covered Code has been published under a particular version of the
License, You may always continue to use it under the terms of that
version. You may also choose to use such Covered Code under the terms
of any subsequent version of the License published by Netscape. No one
other than Netscape has the right to modify the terms applicable to
Covered Code created under this License.
6.3. Derivative Works.
If you create or use a modified version of this License (which you may
only do in order to apply it to code which is not already Covered Code
governed by this License), you must (a) rename Your license so that the
phrases ``Mozilla'', ``MOZILLAPL'', ``MOZPL'', ``Netscape'', ``NPL'' or
any confusingly similar phrase do not appear anywhere in your license
and (b) otherwise make it clear that your version of the license
contains terms which differ from the Mozilla Public License and
Netscape Public License. (Filling in the name of the Initial Developer,
Original Code or Contributor in the notice described in Exhibit A shall
not of themselves be deemed to be modifications of this License.)
7. DISCLAIMER OF WARRANTY.
COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN ``AS IS'' BASIS,
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
8. TERMINATION.
This License and the rights granted hereunder will terminate
automatically if You fail to comply with terms herein and fail to cure
such breach within 30 days of becoming aware of the breach. All
sublicenses to the Covered Code which are properly granted shall
survive any termination of this License. Provisions which, by their
nature, must remain in effect beyond the termination of this License
shall survive.
9. LIMITATION OF LIABILITY.
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL
DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER
PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND
ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE
BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
10. U.S. GOVERNMENT END USERS.
The Covered Code is a ``commercial item,'' as that term is defined in
48 C.F.R. 2.101 (Oct. 1995), consisting of ``commercial computer
software'' and ``commercial computer software documentation,'' as such
terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
all U.S. Government End Users acquire Covered Code with only those
rights set forth herein.
11. MISCELLANEOUS.
This License represents the complete agreement concerning subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. This License shall be governed by
California law provisions (except to the extent applicable law, if any,
provides otherwise), excluding its conflict-of-law provisions. With
respect to disputes in which at least one party is a citizen of, or an
entity chartered or registered to do business in, the United States of
America: (a) unless otherwise agreed in writing, all disputes relating
to this License (excepting any dispute relating to intellectual
property rights) shall be subject to final and binding arbitration,
with the losing party paying all costs of arbitration; (b) any
arbitration relating to this Agreement shall be held in Santa Clara
County, California, under the auspices of JAMS/EndDispute; and (c) any
litigation relating to this Agreement shall be subject to the
jurisdiction of the Federal Courts of the Northern District of
California, with venue lying in Santa Clara County, California, with
the losing party responsible for costs, including without limitation,
court costs and reasonable attorneys fees and expenses. The application
of the United Nations Convention on Contracts for the International
Sale of Goods is expressly excluded. Any law or regulation which
provides that the language of a contract shall be construed against the
drafter shall not apply to this License.
12. RESPONSIBILITY FOR CLAIMS.
Except in cases where another Contributor has failed to comply with
Section 3.4, You are responsible for damages arising, directly or
indirectly, out of Your utilization of rights under this License, based
on the number of copies of Covered Code you made available, the
revenues you received from utilizing such rights, and other relevant
factors. You agree to work with affected parties to distribute
responsibility on an equitable basis.
EXHIBIT A.
``The contents of this file are subject to the Mozilla Public License
Version 1.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.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.
The Original Code is ______________________________________.
The Initial Developer of the Original Code is ________________________.
Portions created by ______________________ are Copyright (C) ______
_______________________. All Rights Reserved.
Contributor(s): ______________________________________.''

View File

@@ -0,0 +1,173 @@
#############################################################################
# $Id: Makefile.PL,v 1.14 1999-01-21 23:52:42 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# The Makefile "source".
#
#############################################################################
use ExtUtils::MakeMaker;
use Config;
use Carp;
$perlpath = $Config{'perlpath'};
$osname = $Config{'osname'};
$ldapsdk_loc = $ENV{"LDAPSDKDIR"}; # Full Path to C SDK Top-Level
$ldapsdk_ssl = $ENV{"LDAPSDKSSL"}; # N to exclude SSL
$ldapsdk_ver = $ENV{"LDAPV3ON"}; # N to exclude LDAP v3 features
$libexts = "so|sl|a|lib";
print "\nPerLDAP - Perl 5 Module for LDAP\n";
print "================================\n";
$silent = 1;
print "Directory containing 'include' and 'lib' directory of the Netscape\n";
print "LDAP Software Developer Kit (default: /usr): ";
if (!$ldapsdk_loc)
{
$silent = 0;
chomp ($ldapsdk_loc = <STDIN>);
$ldapsdk_loc = "/usr" unless $ldapsdk_loc =~ /\S/;
} else {
print "$ldapsdk_loc\n";
}
croak("Directory $ldapsdk_loc does not exist!") unless -d $ldapsdk_loc;
if ($osname =~ /mswin/i)
{
$dir_sep = "\\";
} else {
$dir_sep = "/";
}
$include_ldap = $ldapsdk_loc . $dir_sep . "include";
$lib_ldap = $ldapsdk_loc . $dir_sep . "lib";
print "Using LDAPv3 Developer Kit (default: yes)? ";
if (!$ldapsdk_ver)
{
$silent = 0;
chomp ($ldapsdk_ver = <STDIN>);
} else {
print "YES\n";
}
$v3_def = "-DLDAPV3" unless ($ldapsdk_ver =~ /^n/i);
print "Include SSL Support (default: yes)? ";
if (!$ldapsdk_ssl)
{
$silent = 0;
chomp ($ldapsdk_ssl = <STDIN>);
} else {
print "YES\n";
}
$ssl_def = "-DUSE_SSL" unless ($ldapsdk_ssl =~ /^n/i);
opendir(DIR,$lib_ldap);
@files = grep{/ldap|lber/} readdir(DIR);
closedir(DIR);
if (!((@ldaplib = grep{/ldapssl.*\.($libexts)$/} @files) && $ssl_def))
{
@ldaplib = grep{/ldap.*\.($libexts)$/} @files;
@lberlib = grep{/lber.*\.($libexts)$/} @files;
}
if ($#ldaplib < 0)
{
die "No LDAP libraries found.";
}
if ($#ldaplib > 0)
{
print "Located multiple libraries:\n";
foreach $alib (@ldaplib)
{
print " - $alib\n";
}
}
$lline_ldap = $ldaplib[0];
$lline_ldap =~ s/^lib//;
$lline_ldap =~ s/\.($libexts)$//;
$lline = "-L$lib_ldap -l$lline_ldap";
if ($#lberlib >= 0 && $lline =~ /ldap$/)
{
$lline_lber = $lberlib[0];
$lline_lber =~ s/^lib//;
$lline_lber =~ s/\.($libexts)$//;
$lline .= " -l$lline_lber";
}
print "Libraries to link with (default: $lline): ";
if (!$silent)
{
chomp ($lib_line = <STDIN>);
$lib_line = $lline unless $lib_line =~ /\S/;
} else {
print "\n";
}
if ($osname =~ /mswin/i)
{
$myextlib = "$lib_ldap\\$ldaplib[0]";
if ($lber_lib)
{
$myextlib .= " $lib_ldap\\$lberlib[0]";
}
} else {
$myextlib = "";
}
@extras = ();
push(@extras,
CAPI => 'TRUE')
if ($] >= 5.005 and $^O eq 'MSWin32'
and $Config{archname} =~ /-object\b/i);
push(@extras,
ABSTRACT => 'Perl methods for LDAP C API calls',
AUTHOR => 'Netscape Communications Corp., Inc. and Clayton Donley')
if ($ExtUtils::MakeMaker::Version >= 5.4301);
WriteMakefile(
'NAME' => 'Mozilla::LDAP::API',
'DISTNAME' => 'PerLDAP',
'VERSION_FROM' => 'API.pm',
($include_ldap ne "/usr/include" ? (
'INC' => "-I$include_ldap",
) : (
'INC' => "",
)),
'LIBS' => [$lib_line],
'MYEXTLIB' => $myextlib,
'DEFINE' => "$v3_def $ssl_def",
'XSOPT' => "-nolinenumbers",
@extras
);

View File

@@ -0,0 +1,183 @@
#############################################################################
# #
# PerLDAP v1.0 - A Perl Developers' Kit for LDAP #
# #
#############################################################################
What is PerLDAP?
================
PerLDAP is a set of modules written in Perl and C that allow developers to
leverage their existing Perl knowledge to easily access and manage LDAP-
enabled directories. PerLDAP makes it very easy to search, add, delete,
and modify directory entries. For example, Perl developers can easily
build web applications to access information stored in a directory or
create directory sync tools between directories and other services.
PerLDAP is an open source development project, the result of a joint effort
between Netscape and Clayton Donley, an open source developer. PerLDAP
currently provides the basic functions to allow Perl users to access and
manipulate directories easily. Based on developer feedback and
involvement, PerLDAP will continue to evolve to include additional
functionality in future releases.
Installing PerLDAP Binaries
===========================
You will first need version 3.0 of the LDAP C SDK from Netscape. This is
available from the DevEdge page at:
http://developer.netscape.com/tech/directory/
You will also need Perl v5.004, available at http://www.perl.com/.
Earlier, or later, versions of Perl will NOT work with these binaries. If
you wish to use v5.005, you will need to compile PerLDAP from source.
On Unix (Solaris Only...HPUX, IRIX, AIX to follow):
1. Be sure that the libraries from the C SDK are installed in locations
referenced by the environment variable LD_LIBRARY_PATH, or one of the
default system lib directories (e.g. /usr/lib). Alternatively you can
later also copy the SDK libraries to the same "site" directory where
Perl installed the PerLDAP libraries.
2. Save the file in a temporary location
3. Unzip the file by entering the command:
gunzip <filename>.tar.gz
4. Untar the resulting tar file by entering the command:
tar xvof <filename>.tar
5. Change to the extract directory:
cd PerLDAP-1.1
6. Execute the following command in as the super-user (root):
perl install-bin
On Windows NT:
1. Put the LDAP C SDK DLL in the same directory as the perl.exe
binary. You can also set your PATH to point to the directory where you
have the C SDK installed. Alternatively, you can put the DLL in the
system32 folder, but avoid that if possible.
2. Save the file in a temporary location
3. Unzip the file by entering the command:
I don't have a tool for creating self-extracting archives...
4. Change to the extract directory:
cd PerLDAP-1.1
5. Execute the following command:
perl install-bin
Compiling the PerLDAP Sources
=============================
The source to PerLDAP is available on the Mozilla site at:
http://www.mozilla.org/directory/
You can either retrieve the .tar file with the source distribution, or use
CVS to checkout the module directly. The name of the CVS module is
PerLDAP, and it checks out the directory
mozilla/directory/perldap
Further instructions for using CVS and Mozilla is available at
http://www.mozilla.org/cvs.html
and an FAQ is at
http://www.mozilla.org/directory/faq/perldap-faq.html
Instructions for building the source can be found in the INSTALL file
in the source distribution.
Getting Started
===============
Documentation for this module is in standard Perl 'pod' format. HTML
versions of this documentation can also be found on the Netscape DevEdge
site at: http://developer.netscape.com/tech/directory/.
Additionally, many good examples can be found in the 'examples' directory.
Modules and Examples Included
=============================
Mozilla::LDAP::API - Low level interface between Perl and the LDAP C API
Mozilla::LDAP::Entry - Perl methods for manipulating entry objects
Mozilla::LDAP::Conn - Perl methods for performing LDAP operations
Mozilla::LDAP::LDIF - Perl methods for utilizing LDIF
Mozilla::LDAP::Utils - Some convenient LDAP related utilities
test_api/search.pl - Tests low level API search calls
test_api/write.pl - Tests low level API write calls
test_api/api.pl - Tests ALL low level LDAPv2 calls
examples/lfinger.pl - LDAP version of the regular Unix finger command.
examples/qsearch.pl - Simple ldapsearch replacement.
examples/monitor.pl - Retrieve status information from an LDAP server.
examples/ldappasswd.pl - Change the LDAP password for a user.
examples/rmentry.pl - Remove an entire entry from the database.
examples/rename.pl - Rename (modRDN) an entry.
examples/tabdump.pl - Dump LDAP information into a tab separated file.
examples/psoftsync.pl - Synchronize LDAP with a PeopleSoft "dump" file.
All examples support the "standard" LDAP command line options, which are
-h hostname LDAP server name
-p port # LDAP port, default is 389 (or 636 for SSL)
-b base DN LDAP Base-DN
-D bind DN LDAP bind DN (connect to server as this "user")
-w bind pswd Password to bind to the server
-P certfile Use SSL, with the publick keys from this file
Note that the examples currently only support Simple Authentication
(passwords), the Client Authentication features (using certificates) will
be used in the next release. All examples also honors the environment
variable LDAP_BASEDN, set it to your systems base DN, e.g.
% setenv LDAP_BASEDN 'dc=netscape,dc=com'
or for Bourne shell
# LDAP_BASEDN='dc=netscape,dc=com'; export LDAP_BASEDN
Reporting problems and bugs
===========================
Address all bug reports and comments to the Mozilla newsgroups at:
news://news.mozilla.org/netscape.public.mozilla.directory
License/Copyright
=================
Portions by Netscape (c) Copyright 1998 Netscape Communications Corp, Inc.
Portions by Clayton Donley (c) Copyright 1998 Clayton Donley
Please read the MPL-1.0.txt file included for information on the Mozilla
Public License, which covers all files in this distribution.
Known Bugs
==========
There are a number of issues still outstanding at the time of release. Most
of these are already in the process of being resolved.
- There is a possible memory leak in the search routines. The OO layer
is also more memory than it should.
- The Rebind operation on NT does NOT work properly when set to a Perl
function. This is being investigated.
- Some of the documentation is incomplete.

View File

@@ -0,0 +1,380 @@
#############################################################################
# $Id: Utils.pm,v 1.11 1999-01-21 23:52:43 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Lots of Useful Little Utilities, for LDAP related operations.
#
#############################################################################
package Mozilla::LDAP::Utils;
use Mozilla::LDAP::API qw(:constant);
use Mozilla::LDAP::Conn;
use vars qw(@ISA %EXPORT_TAGS);
require Exporter;
@ISA = qw(Exporter);
%EXPORT_TAGS = (
all => [qw(normalizeDN
isUrl
printEntry
printentry
encodeBase64
decodeBase64
str2Scope
askPassword
ldapArgs
unixCrypt
userCredentials
answer)]
);
# Add Everything in %EXPORT_TAGS to @EXPORT_OK
Exporter::export_ok_tags('all');
#############################################################################
# Normalize the DN string (first argument), and return the new, normalized,
# string (DN). This is useful to make sure that two syntactically
# identical DNs compare (eq) as the same string.
#
sub normalizeDN
{
my ($dn) = @_;
my (@vals);
return "" unless (defined($dn) && ($dn ne ""));
@vals = Mozilla::LDAP::API::ldap_explode_dn(lc $dn, 0);
return join(",", @vals);
}
#############################################################################
# Checks if a string is a properly formed LDAP URL.
#
sub isURL
{
return ldap_is_ldap_url($_[0]);
}
#############################################################################
# Print an entry, in LDIF format. This is sort of obsolete, we encourage
# you to use the :;LDAP::LDIF class instead.
#
sub printEntry
{
my $entry = $_[0];
my $attr;
local $_;
print "dn: ", $entry->{"dn"},"\n";
foreach $attr (@{$entry->{"_oc_order_"}})
{
next if ($attr =~ /^_.+_$/);
next if $entry->{"_${attr}_deleted_"};
foreach (@{$entry->{$attr}})
{
print "$attr: $_\n";
}
}
print "\n";
}
*printentry = \*printEntry;
#############################################################################
# Perform Base64 encoding, this is based on MIME::Base64.pm, written
# by Gisle Aas <gisle@aas.no>. If possible, use the MIME:: package instead.
#
sub encodeBase64
{
my $res = "";
my $eol = "$_[1]";
my $padding;
pos($_[0]) = 0; # ensure start at the beginning
while ($_[0] =~ /(.{1,45})/gs) {
$res .= substr(pack('u', $1), 1);
chop($res);
}
$res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs
$padding = (3 - length($_[0]) % 3) % 3;
$res =~ s/.{$padding}$/'=' x $padding/e if $padding;
if (length $eol) {
$res =~ s/(.{1,76})/$1$eol/g;
}
return $res;
}
#############################################################################
# Perform Base64 decoding, this is based on MIME::Base64.pm, written
# by Gisle Aas <gisle@aas.no>. If possible, use the MIME:: package instead.
#
sub decodeBase64
{
my $str = shift;
my $res = "";
my $len;
$str =~ tr|A-Za-z0-9+=/||cd;
Carp::croak("Base64 decoder requires string length to be a multiple of 4")
if length($str) % 4;
$str =~ s/=+$//; # remove padding
$str =~ tr|A-Za-z0-9+/| -_|; # convert to uuencoded format
while ($str =~ /(.{1,60})/gs)
{
$len = chr(32 + length($1)*3/4);
$res .= unpack("u", $len . $1 ); # uudecode
}
return $res;
}
#############################################################################
# Convert a "human" readable string to an LDAP scope value
#
sub str2Scope
{
my $str = $_[0];
return $str if ($str =~ /^[0-9]+$/);
if ($str =~ /^sub/i)
{
return LDAP_SCOPE_SUBTREE;
}
elsif ($str =~ /^base/i)
{
return LDAP_SCOPE_BASE;
}
elsif ($str =~ /^one/i)
{
return LDAP_SCOPE_ONELEVEL;
}
# Default...
return LDAP_SCOPE_SUBTREE;
}
#############################################################################
# Ask for a password, without displaying it on the TTY.
#
sub askPassword
{
my $prompt = $_[0];
my $hasReadKey = 0;
eval "use Term::ReadKey";
$hasReadKey=1 unless ($@);
print "LDAP password: " if $prompt;
if ($hasReadKey)
{
ReadMode(2);
chop($_ = ReadLine(0));
ReadMode(0);
}
else
{
system('/bin/stty -echo');
chop($_ = <STDIN>);
system('/bin/stty echo');
}
print "\n";
return $_;
}
#############################################################################
# Handle some standard LDAP options, and construct a nice little structure
# that we can use later on. We really should have some appropriate defaults,
# perhaps from an Mozilla::LDAP::Config module.
#
sub ldapArgs
{
my ($bind, $base) = @_;
my %ld;
$main::opt_v = $main::opt_n if defined($main::opt_n);
$main::opt_p = LDAPS_PORT if (!defined($main::opt_p) &&
defined($main::opt_P) &&
($main::opt_P ne ""));
$ld{"host"} = $main::opt_h || "ldap";
$ld{"port"} = $main::opt_p || LDAP_PORT;
$ld{"root"} = $main::opt_b || $base || $ENV{'LDAP_BASEDN'};
$ld{"bind"} = $main::opt_D || $bind || "";
$ld{"pswd"} = $main::opt_w || "";
$ld{"cert"} = $main::opt_P || "";
$ld{"scope"} = (defined($main::opt_s) ? $main::opt_s : LDAP_SCOPE_SUBTREE);
if (($ld{"bind"} ne "") && ($ld{"pswd"} eq ""))
{
$ld{pswd} = askPassword(1);
}
return %ld;
}
#############################################################################
# Create a Unix-type password, using the "crypt" function. A random salt
# is always generated, perhaps it should be an optional argument?
#
sub unixCrypt
{
my $ascii =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
my $salt = substr($ascii, rand(62), 1) . substr($ascii, rand(62), 1);
srand(time ^ $$);
crypt($_[0], $salt);
}
#############################################################################
# Try to find a user to bind as, and possibly ask for the password. Pass
# a pointer to the hash array with LDAP parameters to this function.
#
sub userCredentials
{
my ($ld) = @_;
my ($conn, $entry, $pswd);
if ($ld->{"bind"} eq "")
{
$conn = new Mozilla::LDAP::Conn($ld);
die "Could't connect to LDAP server " . $ld->{"host"} unless $conn;
$search = "(&(objectclass=inetOrgPerson)(uid=$ENV{USER}))";
$entry = $conn->search($ld->{"root"}, "subtree", $search, 0, ("uid"));
return 0 if (!$entry || $conn->nextEntry());
$conn->close();
$ld->{"bind"} = $entry->getDN();
}
if ($ld->{"pswd"} eq "")
{
$ld->{"pswd"} = Mozilla::LDAP::Utils::askPassword(1);
}
}
#############################################################################
# Ask a Y/N question, return "Y" or "N".
#
sub answer
{
die "Default string must be Y or N."
unless (($_[0] eq "Y") || ($_[0] eq "N"));
chop($_ = <STDIN>);
return $_[0] if /^$/;
return "Y" if /^[yY]/;
return "N" if /^[nN]/;
}
#############################################################################
# Mandatory TRUE return value.
#
1;
#############################################################################
# POD documentation...
#
__END__
=head1 NAME
Mozilla::LDAP::Utils.pm - Collection of useful little utilities.
=head1 SYNOPSIS
use Mozilla::LDAP::Utils;
=head1 ABSTRACT
=head1 DESCRIPTION
=head1 OBJECT CLASS METHODS
=over 13
=item B<normalizeDN>
This function will remove all extraneous white spaces in the DN, and also
change all upper case characters to lower case. The only argument is the
DN string to normalize, and the return value is the new, clean DN.
=back
=head1 EXAMPLES
There are plenty of examples to look at, in the examples directory. We are
adding more examples every day (almost).
=head1 INSTALLATION
Installing this package is part of the Makefile supplied in the
package. See the installation procedures which are part of this package.
=head1 AVAILABILITY
This package can be retrieved from a number of places, including:
http://www.mozilla.org/directory/
Your local CPAN server
=head1 CREDITS
Most of this code was developed by Leif Hedstrom, Netscape Communications
Corporation.
=head1 BUGS
None. :)
=head1 SEE ALSO
L<Mozilla::LDAP::Conn>, L<Mozilla::LDAP::Entry>, L<Mozilla::LDAP::API>, and
of course L<Perl>.
=cut

View File

@@ -0,0 +1,954 @@
/*
*******************************************************************************
* $Id: constant.h,v 1.7 1998-08-13 09:14:14 leif Exp $
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is PerLDAP. The Initial Developer of the Original
* Code is Netscape Communications Corp. and Clayton Donley. Portions
* created by Netscape are Copyright (C) Netscape Communications
* Corp., portions created by Clayton Donley are Copyright (C) Clayton
* Donley. All Rights Reserved.
*
* Contributor(s):
*
* DESCRIPTION
* Constants.
*
*******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
#include <ldap.h>
static int
not_here(s)
char *s;
{
croak("%s not implemented on this architecture", s);
return -1;
}
double
constant(name, arg)
char *name;
int arg;
{
errno = 0;
if (name[0] == 'L' && name[1] == 'D' && name[2] == 'A' && name[3] == 'P'
&& name[4] == '_')
{
switch (name[5]) {
case 'A':
if (strEQ(name, "LDAP_ADMINLIMIT_EXCEEDED"))
#ifdef LDAP_ADMINLIMIT_EXCEEDED
return LDAP_ADMINLIMIT_EXCEEDED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_AFFECTS_MULTIPLE_DSAS"))
#ifdef LDAP_AFFECTS_MULTIPLE_DSAS
return LDAP_AFFECTS_MULTIPLE_DSAS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_ALIAS_DEREF_PROBLEM"))
#ifdef LDAP_ALIAS_DEREF_PROBLEM
return LDAP_ALIAS_DEREF_PROBLEM;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_ALIAS_PROBLEM"))
#ifdef LDAP_ALIAS_PROBLEM
return LDAP_ALIAS_PROBLEM;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_ALREADY_EXISTS"))
#ifdef LDAP_ALREADY_EXISTS
return LDAP_ALREADY_EXISTS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_AUTH_METHOD_NOT_SUPPORTED"))
#ifdef LDAP_AUTH_METHOD_NOT_SUPPORTED
return LDAP_AUTH_METHOD_NOT_SUPPORTED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_AUTH_NONE"))
#ifdef LDAP_AUTH_NONE
return LDAP_AUTH_NONE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_AUTH_SASL"))
#ifdef LDAP_AUTH_SASL
return LDAP_AUTH_SASL;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_AUTH_SIMPLE"))
#ifdef LDAP_AUTH_SIMPLE
return LDAP_AUTH_SIMPLE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_AUTH_UNKNOWN"))
#ifdef LDAP_AUTH_UNKNOWN
return LDAP_AUTH_UNKNOWN;
#else
goto not_there;
#endif
break;
case 'B':
if (strEQ(name, "LDAP_BUSY"))
#ifdef LDAP_BUSY
return LDAP_BUSY;
#else
goto not_there;
#endif
break;
case 'C':
if (strEQ(name, "LDAP_CACHE_CHECK"))
#ifdef LDAP_CACHE_CHECK
return LDAP_CACHE_CHECK;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CACHE_LOCALDB"))
#ifdef LDAP_CACHE_LOCALDB
return LDAP_CACHE_LOCALDB;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CACHE_POPULATE"))
#ifdef LDAP_CACHE_POPULATE
return LDAP_CACHE_POPULATE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CHANGETYPE_ADD"))
#ifdef LDAP_CHANGETYPE_ADD
return LDAP_CHANGETYPE_ADD;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CHANGETYPE_ANY"))
#ifdef LDAP_CHANGETYPE_ANY
return LDAP_CHANGETYPE_ANY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CHANGETYPE_DELETE"))
#ifdef LDAP_CHANGETYPE_DELETE
return LDAP_CHANGETYPE_DELETE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CHANGETYPE_MODDN"))
#ifdef LDAP_CHANGETYPE_MODDN
return LDAP_CHANGETYPE_MODDN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CHANGETYPE_MODIFY"))
#ifdef LDAP_CHANGETYPE_MODIFY
return LDAP_CHANGETYPE_MODIFY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CLIENT_LOOP"))
#ifdef LDAP_CLIENT_LOOP
return LDAP_CLIENT_LOOP;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_COMPARE_FALSE"))
#ifdef LDAP_COMPARE_FALSE
return LDAP_COMPARE_FALSE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_COMPARE_TRUE"))
#ifdef LDAP_COMPARE_TRUE
return LDAP_COMPARE_TRUE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CONFIDENTIALITY_REQUIRED"))
#ifdef LDAP_CONFIDENTIALITY_REQUIRED
return LDAP_CONFIDENTIALITY_REQUIRED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CONNECT_ERROR"))
#ifdef LDAP_CONNECT_ERROR
return LDAP_CONNECT_ERROR;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_CONSTRAINT_VIOLATION"))
#ifdef LDAP_CONSTRAINT_VIOLATION
return LDAP_CONSTRAINT_VIOLATION;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_DECODING_ERROR"))
#ifdef LDAP_DECODING_ERROR
return LDAP_DECODING_ERROR;
#else
goto not_there;
#endif
break;
case 'D':
if (strEQ(name, "LDAP_DEREF_ALWAYS"))
#ifdef LDAP_DEREF_ALWAYS
return LDAP_DEREF_ALWAYS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_DEREF_FINDING"))
#ifdef LDAP_DEREF_FINDING
return LDAP_DEREF_FINDING;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_DEREF_NEVER"))
#ifdef LDAP_DEREF_NEVER
return LDAP_DEREF_NEVER;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_DEREF_SEARCHING"))
#ifdef LDAP_DEREF_SEARCHING
return LDAP_DEREF_SEARCHING;
#else
goto not_there;
#endif
break;
case 'E':
if (strEQ(name, "LDAP_ENCODING_ERROR"))
#ifdef LDAP_ENCODING_ERROR
return LDAP_ENCODING_ERROR;
#else
goto not_there;
#endif
break;
case 'F':
if (strEQ(name, "LDAP_FILTER_ERROR"))
#ifdef LDAP_FILTER_ERROR
return LDAP_FILTER_ERROR;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_FILT_MAXSIZ"))
#ifdef LDAP_FILT_MAXSIZ
return LDAP_FILT_MAXSIZ;
#else
goto not_there;
#endif
break;
case 'I':
if (strEQ(name, "LDAP_INAPPROPRIATE_AUTH"))
#ifdef LDAP_INAPPROPRIATE_AUTH
return LDAP_INAPPROPRIATE_AUTH;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_INAPPROPRIATE_MATCHING"))
#ifdef LDAP_INAPPROPRIATE_MATCHING
return LDAP_INAPPROPRIATE_MATCHING;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_INSUFFICIENT_ACCESS"))
#ifdef LDAP_INSUFFICIENT_ACCESS
return LDAP_INSUFFICIENT_ACCESS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_INVALID_CREDENTIALS"))
#ifdef LDAP_INVALID_CREDENTIALS
return LDAP_INVALID_CREDENTIALS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_INVALID_DN_SYNTAX"))
#ifdef LDAP_INVALID_DN_SYNTAX
return LDAP_INVALID_DN_SYNTAX;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_INVALID_SYNTAX"))
#ifdef LDAP_INVALID_SYNTAX
return LDAP_INVALID_SYNTAX;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_IS_LEAF"))
#ifdef LDAP_IS_LEAF
return LDAP_IS_LEAF;
#else
goto not_there;
#endif
break;
case 'L':
if (strEQ(name, "LDAP_LOCAL_ERROR"))
#ifdef LDAP_LOCAL_ERROR
return LDAP_LOCAL_ERROR;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_LOOP_DETECT"))
#ifdef LDAP_LOOP_DETECT
return LDAP_LOOP_DETECT;
#else
goto not_there;
#endif
break;
case 'M':
if (strEQ(name, "LDAP_MOD_ADD"))
#ifdef LDAP_MOD_ADD
return LDAP_MOD_ADD;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MOD_BVALUES"))
#ifdef LDAP_MOD_BVALUES
return LDAP_MOD_BVALUES;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MOD_DELETE"))
#ifdef LDAP_MOD_DELETE
return LDAP_MOD_DELETE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MOD_REPLACE"))
#ifdef LDAP_MOD_REPLACE
return LDAP_MOD_REPLACE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MORE_RESULTS_TO_RETURN"))
#ifdef LDAP_MORE_RESULTS_TO_RETURN
return LDAP_MORE_RESULTS_TO_RETURN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MSG_ALL"))
#ifdef LDAP_MSG_ALL
return LDAP_MSG_ALL;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MSG_ONE"))
#ifdef LDAP_MSG_ONE
return LDAP_MSG_ONE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_MSG_RECEIVED"))
#ifdef LDAP_MSG_RECEIVED
return LDAP_MSG_RECEIVED;
#else
goto not_there;
#endif
break;
case 'N':
if (strEQ(name, "LDAP_NAMING_VIOLATION"))
#ifdef LDAP_NAMING_VIOLATION
return LDAP_NAMING_VIOLATION;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NOT_ALLOWED_ON_NONLEAF"))
#ifdef LDAP_NOT_ALLOWED_ON_NONLEAF
return LDAP_NOT_ALLOWED_ON_NONLEAF;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NOT_ALLOWED_ON_RDN"))
#ifdef LDAP_NOT_ALLOWED_ON_RDN
return LDAP_NOT_ALLOWED_ON_RDN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NOT_SUPPORTED"))
#ifdef LDAP_NOT_SUPPORTED
return LDAP_NOT_SUPPORTED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NO_LIMIT"))
#ifdef LDAP_NO_LIMIT
return LDAP_NO_LIMIT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NO_MEMORY"))
#ifdef LDAP_NO_MEMORY
return LDAP_NO_MEMORY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NO_OBJECT_CLASS_MODS"))
#ifdef LDAP_NO_OBJECT_CLASS_MODS
return LDAP_NO_OBJECT_CLASS_MODS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NO_RESULTS_RETURNED"))
#ifdef LDAP_NO_RESULTS_RETURNED
return LDAP_NO_RESULTS_RETURNED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NO_SUCH_ATTRIBUTE"))
#ifdef LDAP_NO_SUCH_ATTRIBUTE
return LDAP_NO_SUCH_ATTRIBUTE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_NO_SUCH_OBJECT"))
#ifdef LDAP_NO_SUCH_OBJECT
return LDAP_NO_SUCH_OBJECT;
#else
goto not_there;
#endif
break;
case 'O':
if (strEQ(name, "LDAP_OBJECT_CLASS_VIOLATION"))
#ifdef LDAP_OBJECT_CLASS_VIOLATION
return LDAP_OBJECT_CLASS_VIOLATION;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPERATIONS_ERROR"))
#ifdef LDAP_OPERATIONS_ERROR
return LDAP_OPERATIONS_ERROR;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_CACHE_ENABLE"))
#ifdef LDAP_OPT_CACHE_ENABLE
return LDAP_OPT_CACHE_ENABLE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_CACHE_FN_PTRS"))
#ifdef LDAP_OPT_CACHE_FN_PTRS
return LDAP_OPT_CACHE_FN_PTRS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_CACHE_STRATEGY"))
#ifdef LDAP_OPT_CACHE_STRATEGY
return LDAP_OPT_CACHE_STRATEGY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_CLIENT_CONTROLS"))
#ifdef LDAP_OPT_CLIENT_CONTROLS
return LDAP_OPT_CLIENT_CONTROLS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_DEREF"))
#ifdef LDAP_OPT_DEREF
return LDAP_OPT_DEREF;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_DESC"))
#ifdef LDAP_OPT_DESC
return LDAP_OPT_DESC;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_DNS"))
#ifdef LDAP_OPT_DNS
return LDAP_OPT_DNS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_DNS_FN_PTRS"))
#ifdef LDAP_OPT_DNS_FN_PTRS
return LDAP_OPT_DNS_FN_PTRS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_ERROR_NUMBER"))
#ifdef LDAP_OPT_ERROR_NUMBER
return LDAP_OPT_ERROR_NUMBER;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_ERROR_STRING"))
#ifdef LDAP_OPT_ERROR_STRING
return LDAP_OPT_ERROR_STRING;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_HOST_NAME"))
#ifdef LDAP_OPT_HOST_NAME
return LDAP_OPT_HOST_NAME;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_IO_FN_PTRS"))
#ifdef LDAP_OPT_IO_FN_PTRS
return LDAP_OPT_IO_FN_PTRS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_MEMALLOC_FN_PTRS"))
#ifdef LDAP_OPT_MEMALLOC_FN_PTRS
return LDAP_OPT_MEMALLOC_FN_PTRS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_PREFERRED_LANGUAGE"))
#ifdef LDAP_OPT_PREFERRED_LANGUAGE
return LDAP_OPT_PREFERRED_LANGUAGE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_PROTOCOL_VERSION"))
#ifdef LDAP_OPT_PROTOCOL_VERSION
return LDAP_OPT_PROTOCOL_VERSION;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_REBIND_ARG"))
#ifdef LDAP_OPT_REBIND_ARG
return LDAP_OPT_REBIND_ARG;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_REBIND_FN"))
#ifdef LDAP_OPT_REBIND_FN
return LDAP_OPT_REBIND_FN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_RECONNECT"))
#ifdef LDAP_OPT_RECONNECT
return LDAP_OPT_RECONNECT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_REFERRALS"))
#ifdef LDAP_OPT_REFERRALS
return LDAP_OPT_REFERRALS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_REFERRAL_HOP_LIMIT"))
#ifdef LDAP_OPT_REFERRAL_HOP_LIMIT
return LDAP_OPT_REFERRAL_HOP_LIMIT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_RESTART"))
#ifdef LDAP_OPT_RESTART
return LDAP_OPT_RESTART;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_RETURN_REFERRALS"))
#ifdef LDAP_OPT_RETURN_REFERRALS
return LDAP_OPT_RETURN_REFERRALS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_SERVER_CONTROLS"))
#ifdef LDAP_OPT_SERVER_CONTROLS
return LDAP_OPT_SERVER_CONTROLS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_SIZELIMIT"))
#ifdef LDAP_OPT_SIZELIMIT
return LDAP_OPT_SIZELIMIT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_SSL"))
#ifdef LDAP_OPT_SSL
return LDAP_OPT_SSL;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_THREAD_FN_PTRS"))
#ifdef LDAP_OPT_THREAD_FN_PTRS
return LDAP_OPT_THREAD_FN_PTRS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OPT_TIMELIMIT"))
#ifdef LDAP_OPT_TIMELIMIT
return LDAP_OPT_TIMELIMIT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_OTHER"))
#ifdef LDAP_OTHER
return LDAP_OTHER;
#else
goto not_there;
#endif
break;
case 'P':
if (strEQ(name, "LDAP_PARAM_ERROR"))
#ifdef LDAP_PARAM_ERROR
return LDAP_PARAM_ERROR;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_PARTIAL_RESULTS"))
#ifdef LDAP_PARTIAL_RESULTS
return LDAP_PARTIAL_RESULTS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_PORT"))
#ifdef LDAP_PORT
return LDAP_PORT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_PORT_MAX"))
#ifdef LDAP_PORT_MAX
return LDAP_PORT_MAX;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_PROTOCOL_ERROR"))
#ifdef LDAP_PROTOCOL_ERROR
return LDAP_PROTOCOL_ERROR;
#else
goto not_there;
#endif
break;
case 'R':
if (strEQ(name, "LDAP_REFERRAL"))
#ifdef LDAP_REFERRAL
return LDAP_REFERRAL;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_REFERRAL_LIMIT_EXCEEDED"))
#ifdef LDAP_REFERRAL_LIMIT_EXCEEDED
return LDAP_REFERRAL_LIMIT_EXCEEDED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RESULTS_TOO_LARGE"))
#ifdef LDAP_RESULTS_TOO_LARGE
return LDAP_RESULTS_TOO_LARGE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_ADD"))
#ifdef LDAP_RES_ADD
return LDAP_RES_ADD;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_ANY"))
#ifdef LDAP_RES_ANY
return LDAP_RES_ANY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_BIND"))
#ifdef LDAP_RES_BIND
return LDAP_RES_BIND;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_COMPARE"))
#ifdef LDAP_RES_COMPARE
return LDAP_RES_COMPARE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_DELETE"))
#ifdef LDAP_RES_DELETE
return LDAP_RES_DELETE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_EXTENDED"))
#ifdef LDAP_RES_EXTENDED
return LDAP_RES_EXTENDED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_MODIFY"))
#ifdef LDAP_RES_MODIFY
return LDAP_RES_MODIFY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_MODRDN"))
#ifdef LDAP_RES_MODRDN
return LDAP_RES_MODRDN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_RENAME"))
#ifdef LDAP_RES_RENAME
return LDAP_RES_RENAME;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_SEARCH_ENTRY"))
#ifdef LDAP_RES_SEARCH_ENTRY
return LDAP_RES_SEARCH_ENTRY;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_SEARCH_REFERENCE"))
#ifdef LDAP_RES_SEARCH_REFERENCE
return LDAP_RES_SEARCH_REFERENCE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_RES_SEARCH_RESULT"))
#ifdef LDAP_RES_SEARCH_RESULT
return LDAP_RES_SEARCH_RESULT;
#else
goto not_there;
#endif
break;
case 'S':
if (strEQ(name, "LDAP_SASL_BIND_IN_PROGRESS"))
#ifdef LDAP_SASL_BIND_IN_PROGRESS
return LDAP_SASL_BIND_IN_PROGRESS;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SASL_SIMPLE"))
#ifdef LDAP_SASL_SIMPLE
return LDAP_SASL_SIMPLE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SCOPE_BASE"))
#ifdef LDAP_SCOPE_BASE
return LDAP_SCOPE_BASE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SCOPE_ONELEVEL"))
#ifdef LDAP_SCOPE_ONELEVEL
return LDAP_SCOPE_ONELEVEL;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SCOPE_SUBTREE"))
#ifdef LDAP_SCOPE_SUBTREE
return LDAP_SCOPE_SUBTREE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SECURITY_NONE"))
#ifdef LDAP_SECURITY_NONE
return LDAP_SECURITY_NONE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SERVER_DOWN"))
#ifdef LDAP_SERVER_DOWN
return LDAP_SERVER_DOWN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SIZELIMIT_EXCEEDED"))
#ifdef LDAP_SIZELIMIT_EXCEEDED
return LDAP_SIZELIMIT_EXCEEDED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SORT_CONTROL_MISSING"))
#ifdef LDAP_SORT_CONTROL_MISSING
return LDAP_SORT_CONTROL_MISSING;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_STRONG_AUTH_NOT_SUPPORTED"))
#ifdef LDAP_STRONG_AUTH_NOT_SUPPORTED
return LDAP_STRONG_AUTH_NOT_SUPPORTED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_STRONG_AUTH_REQUIRED"))
#ifdef LDAP_STRONG_AUTH_REQUIRED
return LDAP_STRONG_AUTH_REQUIRED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_SUCCESS"))
#ifdef LDAP_SUCCESS
return LDAP_SUCCESS;
#else
goto not_there;
#endif
break;
case 'T':
if (strEQ(name, "LDAP_TIMELIMIT_EXCEEDED"))
#ifdef LDAP_TIMELIMIT_EXCEEDED
return LDAP_TIMELIMIT_EXCEEDED;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_TIMEOUT"))
#ifdef LDAP_TIMEOUT
return LDAP_TIMEOUT;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_TYPE_OR_VALUE_EXISTS"))
#ifdef LDAP_TYPE_OR_VALUE_EXISTS
return LDAP_TYPE_OR_VALUE_EXISTS;
#else
goto not_there;
#endif
break;
case 'U':
if (strEQ(name, "LDAP_UNAVAILABLE"))
#ifdef LDAP_UNAVAILABLE
return LDAP_UNAVAILABLE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_UNAVAILABLE_CRITICAL_EXTENSION"))
#ifdef LDAP_UNAVAILABLE_CRITICAL_EXTENSION
return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_UNDEFINED_TYPE"))
#ifdef LDAP_UNDEFINED_TYPE
return LDAP_UNDEFINED_TYPE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_UNWILLING_TO_PERFORM"))
#ifdef LDAP_UNWILLING_TO_PERFORM
return LDAP_UNWILLING_TO_PERFORM;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_URL_ERR_BADSCOPE"))
#ifdef LDAP_URL_ERR_BADSCOPE
return LDAP_URL_ERR_BADSCOPE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_URL_ERR_MEM"))
#ifdef LDAP_URL_ERR_MEM
return LDAP_URL_ERR_MEM;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_URL_ERR_NODN"))
#ifdef LDAP_URL_ERR_NODN
return LDAP_URL_ERR_NODN;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_URL_ERR_NOTLDAP"))
#ifdef LDAP_URL_ERR_NOTLDAP
return LDAP_URL_ERR_NOTLDAP;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_URL_ERR_PARAM"))
#ifdef LDAP_URL_ERR_PARAM
return LDAP_URL_ERR_PARAM;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_URL_OPT_SECURE"))
#ifdef LDAP_URL_OPT_SECURE
return LDAP_URL_OPT_SECURE;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_USER_CANCELLED"))
#ifdef LDAP_USER_CANCELLED
return LDAP_USER_CANCELLED;
#else
goto not_there;
#endif
break;
case 'V':
if (strEQ(name, "LDAP_VERSION"))
#ifdef LDAP_VERSION
return LDAP_VERSION;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_VERSION1"))
#ifdef LDAP_VERSION1
return LDAP_VERSION1;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_VERSION2"))
#ifdef LDAP_VERSION2
return LDAP_VERSION2;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_VERSION3"))
#ifdef LDAP_VERSION3
return LDAP_VERSION3;
#else
goto not_there;
#endif
if (strEQ(name, "LDAP_VERSION_MAX"))
#ifdef LDAP_VERSION_MAX
return LDAP_VERSION_MAX;
#else
goto not_there;
#endif
break;
}
} else {
if (strEQ(name, "LDAPS_PORT"))
#ifdef LDAPS_PORT
return LDAPS_PORT;
#else
goto not_there;
#endif
}
errno = EINVAL;
return 0;
not_there:
errno = ENOENT;
return 0;
}

View File

@@ -0,0 +1,31 @@
1999-01-05 Leif Hedstrom <leif@netscape.com>
* psoftsync.pl (delAttr): Fixed annoying bug where I missed to
"my" $entry.
1999-01-04 Leif Hedstrom <leif@netscape.com>
* modattr.pl: Bug fixes for handling bad cases better (like
missing attribute, adding empty values etc).
1998-12-11 Leif Hedstrom <leif@netscape.com>
* modattr.pl: Modified slightly to enable the rebind proc.
1998-08-03 Leif Hedstrom <leif@netscape.com>
* psoftsync.pl: New file, also merged in some modules from
LdapUtils.pm, to make sure this works. NOTE: This script currently
doesn't work, since all "modify" operations are horked.
1998-07-30 Leif Hedstrom <leif@netscape.com>
* tabdump.pl: Actually works!
* ldappasswd.pl: Cleaned out some code, and moved it over to the
::Utils module.
1998-07-29 Leif Hedstrom <leif@netscape.com>
* qsearch.pl: First working version.

View File

@@ -0,0 +1,118 @@
#!/usr/bin/perl5
#############################################################################
# $Id: changes2ldif.pl,v 1.2 1999-01-21 23:52:46 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Search the changelog, and produce an LDIF file suitable for ldapmodify
# for instance. This should be merged into LDIF.pm eventually.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
use strict;
no strict "vars";
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "changes2ldif";
$USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert [min [max]]";
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('nvb:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
$ld{root} = "cn=changelog" if (!defined($ld{root}) || $ld{root} eq "");
#################################################################################
# Instantiate an LDAP object, which also binds to the LDAP server.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
#################################################################################
# Create the search filter.
#
$min = $ARGV[$[];
$max = $ARGV[$[ + 1];
if ($min ne "")
{
if ($max ne "")
{
$search = "(&(changenumber>=$min)(changenumber<=$max))";
}
else
{
$search = "(changenumber>=$min)";
}
}
else
{
$search = "(changenumber=*)";
}
#################################################################################
# Do the searches, and print the results.
#
$entry = $conn->search($ld{root}, "ONE", "$search");
while ($entry)
{
print "dn: ", $entry->{targetdn}[0], "\n";
$type = $entry->{changetype}[0];
print "changetype: $type\n";
if ($type =~ /modify/i)
{
# Should we filter out modifiersname and modifytimestamp ? We do chop
# off the trailing \0 though.
chop($entry->{changes}[0]);
print $entry->{changes}[0], "\n";
}
elsif ($type =~ /add/i)
{
print $entry->{changes}[0], "\n";
}
else
{
print "\n";
}
$entry = $conn->nextEntry;
}
#################################################################################
# Close the connection.
#
$ld{conn}->close if $ld{conn};

View File

@@ -0,0 +1,104 @@
#!/usr/bin/perl5
#############################################################################
# $Id: ldappasswd.pl,v 1.6 1998-08-13 09:13:23 leif Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# This is an LDAP version of the normal passwd/yppasswd command found
# on most Unix systems. Note that this will only use the {crypt}
# encryption/hash algorithm (at this point).
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#############################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "ldappasswd";
$USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert search ...";
@ATTRIBUTES = ("uid", "userpassword");
#############################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('nvb:s:h:D:w:P:')) {
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n;
#############################################################################
# Ask for the new password, and confirm it's correct.
#
do
{
print "New password: ";
$new = Mozilla::LDAP::Utils::askPassword();
print "New password (again): ";
$new2 = Mozilla::LDAP::Utils::askPassword();
print "Passwords didn't match, try again!\n\n" if ($new ne $new2);
} until ($new eq $new2);
print "\n";
$crypted = Mozilla::LDAP::Utils::unixCrypt("$new");
#############################################################################
# Now do all the searches, one by one. If there are no search criteria, we
# will change the password for the user running the script.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
foreach $search ($#ARGV >= $[ ? @ARGV : $ld{bind})
{
$entry = $conn->search($search, "subtree", "ALL", 0, @ATTRIBUTES);
$entry = $conn->search($ld{root}, "subtree", $search, 0, @ATTRIBUTES)
unless $entry;
print "No such user: $search\n" unless $entry;
while ($entry)
{
$entry->{userpassword} = ["{crypt}" . $crypted];
print "Changing password for: $entry->{dn}\n" if $opt_v;
if (!$opt_n)
{
$conn->update($entry);
$conn->printError() if $conn->getErrorCode();
}
$entry = $conn->nextEntry();
}
}
#############################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,128 @@
#!/usr/bin/perl5
#############################################################################
# $Id: lfinger.pl,v 1.10 1998-08-13 09:13:08 leif Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# "finger" version using LDAP information (using RFC 2307 objectclass).
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#############################################################################
# Constants, shouldn't have to edit these... The HIDE mechanism is a very
# Netscape internal specific feature. We use this objectclass to mark some
# entries to be "hidden", and some of our applications will honor this. With
# more recent versions of the Directory Server this can be accomplished more
# effectively with appropriate ACI/ACLs.
#
$APPNAM = "lfinger";
$USAGE = "$APPNAM -m -b base -h host -D bind -w pswd -P cert user_info";
@ATTRIBUTES = ("uid", "cn", "homedirectory", "loginshell", "pager",
"telephonenumber", "facsimiletelephonenumber", "mobile");
$HIDE = "(objectclass=nscphidethis)";
#############################################################################
# Print a "finger" entry.
#
sub printIt
{
my($entry) = @_;
print "Login name: $entry->{uid}[0]";
print " " x (39 - 11 - length($entry->{uid}[0]));
print "In real life: $entry->{cn}[0]\n";
if ($entry->{homedirectory}[0] || $entry->{loginshell}[0])
{
print "Directory: $entry->{homedirectory}[0]";
print " " x (39 - 10 - length($entry->{homedirectory}[0]));
print "Shell: $entry->{loginshell}[0]\n";
}
if ($entry->{telephonenumber}[0] || $entry->{pager}[0])
{
print "Phone: $entry->{telephonenumber}[0]";
print " " x (39 - 6 - length($entry->{telephonenumber}[0]));
print "Pager: $entry->{pager}[0]\n";
}
if ($entry->{mobile}[0] || $entry->{facsimiletelephonenumber}[0])
{
print "Mobile: $entry->{mobile}[0]";
print " " x (39 - 7 - length($entry->{mobile}[0]));
print "Fax: $entry->{facsimiletelephonenumber}[0]\n";
}
print "\n";
}
#############################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('mb:h:D:p:w:P:') || !defined($ARGV[$[]))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
$user=$ARGV[$[];
#############################################################################
# Instantiate an LDAP object, which also binds to the LDAP server.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
#############################################################################
# Ok, lets generate the filter, and do the search!
#
if ($opt_m)
{
$search = "(&(uid=$user)(!$HIDE))";
}
else
{
$search = "(&(|(cn=*$user*)(uid=*$user*)(telephonenumber=*$user*))(!$HIDE))";
}
$entry = $conn->search($ld{root}, "subtree", $search, 0, @ATTRIBUTES);
$conn->printError() if $conn->getErrorCode();
while($entry)
{
printIt($entry);
$entry = $conn->nextEntry();
}
#############################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,331 @@
#!/usr/bin/perl5
#############################################################################
# $Id: modattr.pl,v 1.8 1999-01-21 23:52:46 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# This script can be used to do a number of different modification
# operations on a script. Like adding/deleting values, or entire
# attributes.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
use strict;
no strict "vars";
#############################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "modattr";
$USAGE = "$APPNAM [-dnvW] -b base -h host -D bind -w pswd -P cert attr=value filter";
#############################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('adnvWb:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n;
#############################################################################
# Let's process the changes requested, and commit them unless the "-n"
# option was given.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
$conn->setDefaultRebindProc($ld{bind}, $ld{pswd});
($change, $search) = @ARGV;
if (($change eq "") || ($search eq ""))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
($attr, $value) = split(/=/, $change, 2);
$entry = $conn->search($ld{root}, $ld{scope}, $search);
while ($entry)
{
$changed = 0;
if ($opt_d)
{
if (defined $entry->{$attr})
{
if ($value)
{
$changed = $entry->removeValue($attr, $value);
if ($changed && $opt_v)
{
print "Removed value from ", $entry->getDN(), "\n" if $opt_v;
}
}
else
{
delete $entry->{$attr};
print "Deleted attribute $attr for ", $entry->getDN(), "\n" if $opt_v;
$changed = 1;
}
}
else
{
print "No attribute values for: $attr\n";
}
}
else
{
if (!defined($value) || !$value)
{
print "No value provided for the attribute $attr\n";
}
elsif ($opt_a)
{
$changed = $entry->addValue($attr, $value);
if ($changed && $opt_v)
{
print "Added attribute to ", $entry->getDN(), "\n" if $opt_v;
}
}
else
{
$entry->setValue($attr, $value);
$changed = 1;
print "Set attribute for ", $entry->getDN(), "\n" if $opt_v;
}
}
if ($changed && ! $opt_n)
{
$conn->update($entry);
$conn->printError() if $conn->getErrorCode();
}
$entry = $conn->nextEntry();
}
#############################################################################
# Close the connection.
#
$conn->close if $conn;
#############################################################################
# POD documentation...
#
__END__
=head1 NAME
modattr - Modify an attribute for one or more LDAP entries
=head1 SYNOPSIS
modattr [-adnvW] -b base -h host -D bind DN -w pwd -P cert attr=value filter
=head1 ABSTRACT
This command line utility can be used to modify one attribute for one or
more LDAP entries. As simple as this sounds, this turns out to be a very
common operation. For instance, let's say you want to change "mailHost"
for all users on a machine named I<dredd>, to be I<judge>. With this
script all you have to do is
modattr mailHost=judge '(mailHost=dredd)'
=head1 DESCRIPTION
There are four primary operations that can be made with this utility:
=over 4
=item *
Set an attribute to a (single) specified value.
=item *
Add a value to an attribute (for multi-value attributes).
=item *
Delete a value from an attribute. If it's the last value (or if it's a
single value), this will remove the entire attribute.
=item *
Delete an entire attribute, even if it has multiple values.
=back
The first three requires an option of the form B<attr=value>, while the
last one only takes the name of the attribute as the option. The last
argument is always an LDAP search filter, specifying which entries the
operation should be applied to.
=head1 OPTIONS
All but the first two command line options for this tool are standard LDAP
options, to set parameters for the LDAP connection. The two new options
are I<-a> and I<-d> to add and remove attribute values.
Without either of these two options specified (they are both optional),
the default action is to set the attribute to the specified value. That
will effectively remove any existing values for this attribute.
=over 12
=item -a
Specify that the operation is an I<add>, to add a value to the
attribute. If there is no existing value for this attribute, we'll create
a new attribute, otherwise we add the new value if it's not already there.
=item -d
Delete the attribute value, or the entire attribute if there's no value
specified. As you can see this option has two forms, and it's function
depends on the last arguments. Be careful here, if you forget to specify
the value to delete, you will remove all of them.
=item -h <host>
Name of the LDAP server to connect to.
=item -p <port>
TCP port for the LDAP connection.
=item -b <DN>
Base DN for the search
=item -D <bind>
User (DN) to bind as. We support a few convenience shortcuts here, like
I<root>, I<user> and I<repl>.
=item -w <passwd>
This specifies the password to use when connecting to the LDAP
server. This is strongly discouraged, and without this option the script
will ask for the password interactively.
=item -s <scope>
Search scope, default is I<sub>, the other possible values are I<base> and
I<one>. You can also specify the numeric scopes, I<0>, I<1> or I<2>.
=item -P
Use SSL for the LDAP connection, using the specified cert.db file for
certificate information.
=item -n
Don't do anything, only show the changes that would have been made. This
is very convenient, and can save you from embarrassing mistakes.
=item -v
Verbose output.
=back
The last two arguments are special for this script. The first
argument specifies the attribute (and possibly the value) to operate on,
and the last argument is a properly formed LDAP search filter.
=head1 EXAMPLES
We'll give one example for each of the four operations this script can
currently handle. Since the script itself is quite flexible, you'll
probably find you can use this script for a lot of other applications, or
call it from other scripts. Note that we don't specify any LDAP specific
options here, we assume you have configured your defaults properly.
To set the I<description> attribute for user "leif", you would do
modattr 'description=Company Swede' '(uid=leif)'
The examples shows how to use this command without either of the I<-a> or
the I<-d> argument. To add an e-mail alias (alternate address) to the same
user, you would do
modattr -a 'mailAlternateAddress=theSwede@netscape.com' '(uid=leif)'
To remove an object class from all entries which uses it, you could do
modattr -d 'objectclass=dummyClass' '(objectclass=dummyClass)'
This example is not great, since unless you've assured that no entries
uses any of the attributes in this class, you'll get schema
violations. But don't despair, you can use this tool to clean up all
entries first! To completely remove all usage of an attribute named
I<dummyAttr>, you'd simply do
modattr -d dummyAttr '(dummyAttr=*)'
This shows the final format of this command, notice how we don't specify a
value, to assure that the entire attribute is removed. This is potentially
dangerous, so again be careful.
=head1 INSTALLATION
In order to use this script, you'll need Perl version 5.004 or later, the
LDAP SDK, and also the LDAP Perl module (aka PerLDAP). Once you've installed
these packages, just copy this file to where you keep your admin binaries,
e.g. /usr/local/bin.
In order to get good performance, you should make sure you have indexes on
the attributes you typically use with this script. Our experience has been
that in most cases the standard indexes in the Directory Server are
sufficient, e.g. I<CN>, I<UID> and I<MAIL>.
=head1 AVAILABILITY
This package can be retrieved from a number of places, including:
http://www.mozilla.org/directory/
Your local CPAN server
=head1 CREDITS
This little tool was developed internally at Netscape, by Leif Hedstrom.
=head1 BUGS
None, of course...
=head1 SEE ALSO
L<Mozilla::LDAP::API> and L<Perl>
=cut

View File

@@ -0,0 +1,67 @@
#!/usr/bin/perl5
#############################################################################
# $Id: monitor.pl,v 1.2 1998-08-13 09:12:05 leif Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Ask the directory server for it's monitor entry, to see some
# performance and usage stats.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "monitor";
$USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert";
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('b:h:D:p:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs("", "cn=monitor");
#################################################################################
# Instantiate an LDAP object, which also binds to the LDAP server, and then
# do the simple search.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
$entry = $conn->search($ld{root}, "base", "objectclass=*");
Mozilla::LDAP::Utils::printEntry($entry)
if ($entry);
#################################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,615 @@
#!/usr/bin/perl5
#############################################################################
# $Id: psoftsync.pl,v 1.5 1999-01-21 23:52:47 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Synchronise some LDAP info with a PeopleSoft "dump". This "dump" file
# is a "tab" separated file, as generated by an SQL utility on the
# Oracle server.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#############################################################################
# Local configurations, check these out . Note that SYNCS and ORDER has to
# have the same fields, this is because the hash array doesn't preserve
# the order of it's entries... :-( The "codes" are bit fields, where the
# three LSB are used as
#
# 1 Force the update, even if attribute is empty (i.e. delete it)
# 2 The attribute is the base for a DN (e.g. "manager").
# 4 The attribute should be deleted if the user is not in PeopleSoft.
# 8 Don't warn if the attribute is missing in the Psoft file (-W option).
# 16 Always delete this attribute in the PeopleSoft entry.
# 32 Delete this attribute if the account has "expired".
#
%SYNCS = (
"nscpharold" => 1 + 4,
"uid" => 0,
"" => 0,
"" => 0,
"employeenumber" => 1 + 4 + 32,
"departmentnumber" => 1 + 4,
"" => 0,
"" => 0,
"" => 0,
"manager" => 1 + 2,
"title" => 1 + 4 + 16 + 32,
"ou" => 1 + 4 + 32,
"businesscategory" => 1 + 4 + 32,
"employeetype" => 0,
"nscppersonexpdate" => 1 + 8
);
@ORDER = (
"nscpharold",
"uid",
"",
"",
"employeenumber",
"departmentnumber",
"",
"",
"",
"manager",
"title",
"ou",
"businesscategory",
"employeetype",
"nscppersonexpdate"
);
# This is used for mapping the employeeType attribute into a readable format.
%EMPCODES = (
"A" => "Applicant",
"C" => "Contractor",
"E" => "Employee",
"O" => "OEM Partner",
"T" => "Interim",
"V" => "Vendor"
);
# Expiration policy for other attributes, the EXPDELAY is a convenience
# default setting.
$EXPDELAY = 24 * 7;
%EXPIRES = (
"carlicense" => $EXPDELAY,
"mailautoreplymode" => $EXPDELAY,
"mailautoreplytext" => $EXPDELAY,
"mailforwardingaddress" => $EXPDELAY,
"facsimiletelephonenumber" => $EXPDELAY
);
$NOTYPE = "Unknown";
$DELIMITER = "%%";
$SENDMAIL = "/usr/lib/sendmail";
$SEARCH = "(&(uid=*)(!(objectclass=pseudoAccount)))";
$MAILTO = "leif\@netscape.com";
#$LDAP_DEBUG = 1;
#############################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "psoftsync";
$USAGE = "$APPNAM [-nvW] -b base -h host -D bind -w passwd -P cert PS_file";
@ATTRIBUTES = uniq(@ORDER);
push(@ATTRIBUTES, "objectclass");
$TODAY = `/usr/bin/date '+%Y%m%d'`;
chop($TODAY);
#############################################################################
# Print an error for the PeopleSoft data. Note that we use the "__XXX__" fields
# here, to avoid the problem when an attribute is "expired" or modified.
#
sub psoftError
{
my ($str, $entry) = @_;
print "Error: $str: ";
print $entry->key(), " (";
print $entry->{__employeenumber__}, ", ";
print $entry->{__employeetype__}, ", ";
print $entry->{__departmentnumber__}, ")\n";
}
#############################################################################
# Read in a PeopleSoft file, and create all the entries.
#
sub readDump
{
my ($file) = @_;
my (@info, %entries);
my $val;
if (!open(PSOFT, $file))
{
print "Error: Can't read file $file\n";
exit(1);
}
while (<PSOFT>)
{
next unless /$DELIMITER/;
@info = split(/\s*%%\s*/);
$entry = new PsoftEntry($info[$[]);
foreach $attr (@ORDER)
{
$val = shift(@info);
next if ($attr eq "");
$entry->add($attr, $val, $SYNCS{$attr});
}
#
# Perhaps we should do some sanity checks here on the PeopleSoft data?
#
# Clean up some data if the user has expired ("best before...")
if ($entry->expired($entry->{nscppersonexpdate}))
{
foreach $attr (@ORDER)
{
next unless $attr;
delete($entry->{$attr}) if ($SYNCS{$attr} & 32);
}
}
if ($entry->{uid})
{
$entries{$entry->{uid}} = $entry;
}
elsif ($opt_W)
{
psoftError("No UID", $entry);
}
}
close(PSOFT);
return %entries;
}
#############################################################################
# Make a list "uniq", just like the Unix command.
#
sub uniq { # uniq(elements[])
my %tmp;
grep($tmp{$_}++, @_);
return sort(keys(%tmp));
}
#############################################################################
# Delete an attribute from an entry.
#
sub delAttr { # delAttr(ENTRY, ATTR)
my ($entry, $attr) = @_;
if (defined($entry->{$attr}))
{
$out->write("Deleted $attr for user: $entry->{uid}[0]") if $opt_v;
delete($entry->{$attr});
return 1;
}
return 0;
}
#############################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('nvMWb:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n;
$out = new Mail();
if ($opt_M)
{
$out->set("to", $MAILTO);
$out->set("subject", "Hoth: PeopleSoft synchronization report");
}
else
{
$out->echo();
$out->nomail();
}
#############################################################################
# Read in all the PeopleSoft entries, and then instantiate an LDAP object,
# which also binds to the LDAP server.
#
%psoft = readDump(@ARGV[$[]);
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
#############################################################################
# Now process all the users, one by one.
#
$entry = $conn->search($ld{root}, "subtree", $SEARCH, 0, @ATTRIBUTES);
while ($entry)
{
$uid = $entry->{"uid"}[0];
$changed = 0;
$psent = $psoft{$uid};
if (!$psent)
{
print "Error: LDAP user $uid: No entry in PeopleSoft\n" if $opt_W;
foreach $attr (@ORDER)
{
next unless $attr;
$changed += delAttr($entry, $attr) if ($SYNCS{$attr} & 4);
}
if ($entry->{employeetype}[0] ne "$NOTYPE")
{
$entry->{employeetype} = ["$NOTYPE"];
$changed = 1;
$out->write("Set employeeType to $NOTYPE for user: $uid") if $opt_v;
}
}
else
{
$psent->handled(1);
foreach $attr (@ORDER)
{
next unless $attr;
if (!defined($psent->{$attr}) || ($psent->{$attr} eq ""))
{
$changed += delAttr($entry, $attr) if ($SYNCS{$attr} & 1);
}
elsif ($entry->{$attr}[0] ne $psent->{$attr})
{
$entry->{$attr} = [$psent->{$attr}];
$changed = 1;
$out->write("Set $attr to $psent->{$attr} for user: $uid") if $opt_v;
}
}
# Now handle the Expire date special case...
if ($psent->expired() ne "")
{
if ($entry->addValue("objectclass", "nscphidethis"))
{
$changed = 1;
$out->write("Expiring the user: $uid") if $opt_v;
}
# Expire other attributes, IFF the expire is over a certain
# treshhold (e.g. a week).
}
elsif ($entry->removeValue("objectclass", "nscphidethis"))
{
$changed = 1;
$out->write("Enabling the user: $uid") if $opt_v;
}
}
$conn->update($entry) if ($changed && ! $opt_n);
$entry = $conn->nextEntry();
}
#############################################################################
# Close the LDAP connection.
#
$conn->close if $conn;
#############################################################################
# Post process, figure out which PSoft entries have no entry in LDAP.
#
if ($opt_W)
{
foreach (keys(%psoft))
{
$ent=$psoft{$_};
psoftError("No LDAP entry", $ent) unless $ent->handled();
}
}
#############################################################################
# Package to an entry from the PeopleSoft database.
#
package PsoftEntry;
#############################################################################
# Creator.
#
sub new
{
my ($class, $key) = @_;
my $self = {};
bless $self, ref $class || $class;
$self->{__key__} = $key;
return $self;
}
#############################################################################
# Add an attribute/field to the entry.
#
sub add
{
my ($self, $attr, $val, $lev) = @_;
return if ($lev & 16);
$attr = lc $attr;
if ($attr eq "employeetype")
{
if (defined($main::EMPCODES{$val}))
{
$self->{$attr} = $main::EMPCODES{$val};
}
else
{
$self->{$attr} = $main::NOTYPE;
}
$self->{__employeetype__} = $val;
}
elsif (!defined($val) || ($val eq ""))
{
main::psoftError("No attribute $attr", $self)
if ($main::opt_W && ($lev & 1) && !($lev & 8));
}
else
{
$self->{$attr} = ($lev & 2) ? "uid=$val,$main::ld{root}" : $val;
$self->{"__${attr}__"} = $val;
}
}
#############################################################################
# Return the value for an attribute/field.
#
sub get
{
my ($self, $attr) = @_;
return $self->{$attr};
}
#############################################################################
# Mark the entry as "expired". If there is no "date" argument, we'll return
# the current entries expire status.
#
sub expired
{
my ($self, $date) = @_;
if ($date)
{
# Only expire entries with reasonable expire dates...
if (length($date) != 8)
{
main::psoftError("Bad expire date", $self) if $main::opt_W;
return 0;
}
if ($date lt $main::TODAY)
{
$self->{employeetype} = "$main::NOTYPE";
$self->{__expired__} = 1;
return 1;
}
}
return $self->{__expired__};
}
#############################################################################
# Mark the entry as "handled", i.e. it exists in LDAP.
#
sub handled
{
my ($self, $flag) = @_;
$self->{__handled__} = 1 if $flag;
return $self->{__handled__};
}
#############################################################################
# Return the "key" of this entry, typically the name field.
#
sub key
{
my ($self) = @_;
return $self->{__key__};
}
#################################################################################
# This sub-package will send mail to some recipients, IFF there is anything to
# send, or your force it to send. Note that the Subject doesn't qualify it to
# send a message (force it to send if you have to).
#
package Mail;
#################################################################################
# The constructor, which optionally takes the TO, FROM and SUBJECT.
#
sub new
{
my ($class, $to, $from, $subject) = @_;
my $self = {};
bless $self, ref $class || $class;
$self->{to} = $to || "root";
$self->{from} = $from || "ldap";
$self->{subject} = $subject || "Output from LDAP script\n";
@{$self->{message}} = ();
$self->{send} = 0;
$self->{nomail} = 0;
$self->{echo} = 0;
return $self;
}
#################################################################################
# Destructor, which will also send the message, if appropriate.
#
sub DESTROY
{
my ($self) = @_;
if ($self->{send} && !$self->{nomail})
{
$self->send();
$self->{send} = 0;
}
}
#################################################################################
# Set a field for this entry, e.g. From:, To: etc.
#
sub set
{
my ($self, $field, $string) = @_;
if ($field && $string)
{
$field = lc $field;
$self->{$field} = $string;
}
}
#################################################################################
# Add a line to the message, the argument is the string.
#
sub write
{
my ($self, $string) = @_;
if ($string ne "")
{
push(@{$self->{message}}, $string);
print "$string\n" if $self->{echo};
$self->{send}++;
}
}
#################################################################################
# Force the object to send the message, no matter if there's anything in the
# body or not.
#
sub force
{
my ($self) = @_;
$self->{send} = 1;
$self->{nomail} = 0;
}
#################################################################################
# Don't send the mail, this is the oppositte to "force...
#
sub nomail
{
my ($self) = @_;
$self->{send} = 0;
$self->{nomail} = 1;
}
#################################################################################
# Enable echo-mode, where we will also print everything to STDOUT.
#
sub echo
{
my ($self) = @_;
$self->{echo} = 1;
}
#################################################################################
# Actually send the message. This is automatically done by the DESTROY method,
# but we can force it to do it this way.
#
sub send
{
my ($self) = @_;
if ($self->{send} && !$self->{nomail})
{
open(MAILER, "|$main::SENDMAIL -t");
print MAILER "From: $self->{from}\n";
print MAILER "To: $self->{to}\n";
print MAILER "Subject: $self->{subject}\n\n";
foreach (@{$self->{message}})
{
print MAILER "$_\n";
}
print MAILER ".\n";
close(MAILER);
$self->{send} = 0;
}
}

View File

@@ -0,0 +1,98 @@
#!/usr/bin/perl5
#############################################################################
# $Id: qsearch.pl,v 1.8 1999-01-21 23:52:47 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Quick Search, like ldapsearch, but in Perl. Look how simple it is.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
use strict;
no strict "vars";
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "qsearch";
$USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert filter [attr...]";
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('b:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
#################################################################################
# Now do all the searches, one by one.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
foreach (@ARGV)
{
if (/\=/)
{
push(@srch, $_);
}
else
{
push(@attr, $_);
}
}
foreach $search (@srch)
{
if ($#attr >= $[)
{
$entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @attr);
}
else
{
$entry = $conn->search($ld{root}, $ld{scope}, "$search");
}
print "Searched for `$search':\n\n";
$conn->printError() if $conn->getErrorCode();
while ($entry)
{
$entry->printLDIF();
$entry = $conn->nextEntry;
}
print "\n";
}
#################################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,98 @@
#!/usr/bin/perl5
#############################################################################
# $Id: rename.pl,v 1.4 1999-01-21 23:52:47 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Rename an LDAP entry, changing it's DN. Note that currently this only
# works with RDNs.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#############################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "rename";
$USAGE = "$APPNAM [-nvI] -b base -h host -D bind -w pswd -P cert filter new_rdn";
#############################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('nvIb:h:D:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n;
($search, $rdn) = @ARGV;
if (($search eq "") || ($rdn eq ""))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
#############################################################################
# Instantiate an LDAP object, which also binds to the LDAP server.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
$key = "Y" if $opt_I;
$entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @ATTRIBUTES);
$conn->printError() if $conn->getErrorCode();
if (! $entry || $conn->nextEntry())
{
print "Error: The search did not return exactly one match, abort!\n";
exit;
}
if (! $opt_I)
{
print "Rename ", $entry->getDN(), " with $rdn [N]? ";
$key = Mozilla::LDAP::Utils::answer("N") unless $opt_I;
}
if ($key eq "Y")
{
# Note: I have to explicitly specify the original DN below, since the call
# to nextEntry() above blows the DN away from the ::Conn object.
if (! $opt_n)
{
$conn->modifyRDN($rdn, $entry->getDN());
$conn->printError() if $conn->getErrorCode();
}
print "Renamed $entry->{dn}\n" if $opt_v;
}
#################################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,94 @@
#!/usr/bin/perl5
#############################################################################
# $Id: rmentry.pl,v 1.4 1999-01-21 23:52:47 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Remove one or several LDAP objects. By default this tool is
# interactive, which can be disabled with the "-I" option (but
# please be careful...).
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "rmentry";
$USAGE = "$APPNAM [-nvI] -b base -h host -D bind -w pswd -P cert filter ...";
@ATTRIBUTES = ("uid");
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('nvIb:h:D:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n;
#################################################################################
# Do the search, and process all the entries.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
$key = "Y" if $opt_I;
foreach $search (@ARGV)
{
$entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @ATTRIBUTES);
$conn->printError() if $conn->getErrorCode();
while ($entry)
{
if (! $opt_I)
{
print "Delete $entry->{dn} [N]? ";
$key = Mozilla::LDAP::Utils::answer("N") unless $opt_I;
}
if ($key eq "Y")
{
if (! $opt_n)
{
$conn->delete($entry);
$conn->printError() if $conn->getErrorCode();
}
print "Deleted $entry->{dn}\n" if $opt_v;
}
$entry = $conn->nextEntry();
}
}
#################################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,81 @@
#!/usr/bin/perl5
#############################################################################
# $Id: tabdump.pl,v 1.3 1998-08-13 09:11:10 leif Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Generate a TAB separate "dump" of entries matching the search criteria,
# using the list of attributes specified.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "tabdump";
$USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert attr1,attr2,.. srch";
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('nvb:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs();
$attributes = $ARGV[$[];
$search = $ARGV[$[ + 1];
die "Need to specify a list of attributes and the search filter.\n"
unless ($attributes && $search);
#################################################################################
# Do the searches, and produce the output.
#
$conn = new Mozilla::LDAP::Conn(\%ld);
die "Could't connect to LDAP server $ld{host}" unless $conn;
@attr = split(/,/, $attributes);
$entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @attr);
$conn->printError() if $conn->getErrorCode();
while ($entry)
{
foreach (@attr)
{
print $entry->{$_}[0], "\t";
}
print "\n";
$entry = $conn->nextEntry;
}
#################################################################################
# Close the connection.
#
$conn->close if $conn;

View File

@@ -0,0 +1,59 @@
#!/usr/bin/perl -w
#############################################################################
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Perl Script to Install PerLDAP Binaries without a Makefile.
# For use with the binary distribution of PerLDAP.
#
#############################################################################
use File::Path;
use File::Copy;
use Config;
print "\n##############################################\n";
print "# Installing Netscape PerLDAP v1.0 #\n";
print "##############################################\n\n";
$ARCH_LIB = $Config{'sitearchexp'} . "/auto/Mozilla/LDAP/API";
$PERL_LIB = $Config{'sitelibexp'};
print "Creating Directory '$ARCH_LIB'...\n";
File::Path::mkpath "$ARCH_LIB";
print "Creating Directory '$PERL_LIB/Mozilla/LDAP'...\n";
File::Path::mkpath "$PERL_LIB/Mozilla/LDAP";
print "Copying Architecture Dependent Files...\n";
foreach $file (glob "blib/arch/auto/Mozilla/LDAP/API/*")
{
copy($file,"$ARCH_LIB");
}
print "Copying Module Components...\n";
foreach $file (glob "blib/lib/Mozilla/LDAP/*")
{
copy($file,"$PERL_LIB/Mozilla/LDAP");
}
print "Finished!\n\n";
exit 0;

View File

@@ -0,0 +1,6 @@
1999-01-05 Leif Hedstrom <leif@netscape.com>
* entry.pl: New script, to test all Entry:: methods.
* conn.pl (attributeEQ): Added test for modifyRDN().

View File

@@ -0,0 +1,270 @@
#!/usr/bin/perl5
#############################################################################
# $Id: conn.pl,v 1.2 1999-01-21 23:52:50 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Test most (all?) of the LDAP::Mozilla::Conn methods.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
use Mozilla::LDAP::API;
use strict;
no strict "vars";
#################################################################################
# Configurations, modify these as needed.
#
$BIND = "uid=ldapadmin";
$BASE = "o=Netscape Communications Corp.,c=US";
$PEOPLE = "ou=people";
$GROUPS = "ou=groups";
$UID = "leif-test";
$CN = "test-group-1";
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "conn.pl";
$USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert";
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('b:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs($BIND, $BASE);
#################################################################################
# Get an LDAP connection
#
sub getConn
{
my $conn;
if ($main::reuseConn)
{
if (!defined($main::mainConn))
{
$main::mainConn = new Mozilla::LDAP::Conn(\%main::ld);
die "Could't connect to LDAP server $main::ld{host}"
unless $main::mainConn;
}
return $main::mainConn;
}
else
{
$conn = new Mozilla::LDAP::Conn(\%main::ld);
die "Could't connect to LDAP server $main::ld{host}" unless $conn;
}
return $conn;
}
#################################################################################
# Some small help functions...
#
sub dotPrint
{
my $str = shift;
print $str . '.' x (20 - length($str));
}
sub attributeEQ
{
my @a, @b;
my $i;
@a = @{$_[0]};
@b = @{$_[1]};
return 1 if (($#a < 0) && ($#b < 0));
return 0 unless ($#a == $#b);
@a = sort(@a);
@b = sort(@b);
for ($i = 0; $i <= $#a; $i++)
{
return 0 unless ($a[$i] eq $b[$i]);;
}
return 1; # We passed all the tests, we're ok.
}
#################################################################################
# Test adding, deleting and retrieving entries.
#
$filter = "(uid=$UID)";
$conn = getConn();
$nentry = $conn->newEntry();
$nentry->setDN("uid=$UID, $PEOPLE, $BASE");
$nentry->{objectclass} = [ "top", "person", "inetOrgPerson", "mailRecipient" ];
$nentry->addValue("uid", $UID);
$nentry->addValue("sn", "Hedstrom");
$nentry->addValue("givenName", "Leif");
$nentry->addValue("cn", "Leif Hedstrom");
$nentry->addValue("cn", "Leif P. Hedstrom");
$nentry->addValue("cn", "The Swede");
$nentry->addValue("mail", "leif\@ogre.com");
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
$conn->delete($ent->getDN()) if $ent;
dotPrint("Conn/newEntry");
$conn->add($nentry) || print "not ";
print "ok\n";
dotPrint("Conn/delete");
$conn->delete($nentry) || print "not ";
print "ok\n";
dotPrint("Conn/add");
$conn->add($nentry) || print "not ";
print "ok\n";
dotPrint("Conn/delete(DN)");
$conn->delete($nentry->getDN()) || print "not ";
print "ok\n";
$conn->add($nentry) || die "Can't create entry again...\n";
dotPrint("Conn/search");
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
$err = 0;
foreach (keys (%{$nentry}))
{
$err = 1 unless (defined($ent->{$_})
&& attributeEQ($nentry->{$_}, $ent->{$_}));
}
print "not " if $err;
print "ok\n";
$conn->close();
#################################################################################
# Test LDAP URL handling.
#
$conn = getConn();
$url1 = "ldap:///" . $ld{root} . "??sub?$filter";
$url2 = "ldaps:///" . $ld{root} . "??sub?$filter";
$badurl1 = "ldap:" . $ld{root} . "??sub?$filter";
$badurl2 = "http://" . $ld{root} . "??sub?$filter";
dotPrint("Conn/isURL");
print "not " unless ($conn->isURL($url1) && $conn->isURL($url2) &&
!$conn->isURL($badurl2) && !$conn->isURL($badurl1));
print "ok\n";
dotPrint("Conn/searchURL");
$ent = $conn->searchURL($url1);
$err = 0;
foreach (keys (%{$nentry}))
{
$err = 1 unless (defined($ent->{$_})
&& attributeEQ($nentry->{$_}, $ent->{$_}));
}
print "not " if $err;
print "ok\n";
$conn->close();
#################################################################################
# Test some small internal stuff.
#
$conn = getConn();
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
print "Can't locate entry again" unless $ent;
dotPrint("Conn/getLD+getRes");
$err = 0;
$cld = $conn->getLD();
$res = $conn->getRes();
$err = 1 unless $cld;
$err = 1 unless $res;
$count = Mozilla::LDAP::API::ldap_count_entries($cld, $res);
$err = 1 unless ($count == 1);
print "not " if $err;
print "ok\n";
$conn->close();
#################################################################################
# Test the simple authentication method
#
$conn = new Mozilla::LDAP::Conn($ld{host}, $ld{port});
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
die "Can't locate entry again" unless $ent;
dotPrint("Conn/simpleAuth");
$err = 0;
$conn->simpleAuth($ld{bind}, $ld{pswd}) || ($err = 1);
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
$err = 1 unless $ent;
print "not " if $err;
print "ok\n";
$conn->close();
#################################################################################
# Test the modifyRDN functionality
#
$conn = getConn();
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
die "Can't locate entry again" unless $ent;
dotPrint("Conn/modifyRDN");
$err = 0;
$rdn = "uid=$UID-rdn";
$conn->modifyRDN($rdn, $ent->getDN()) || ($err = 1);
$filter = "($rdn)";
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
$err = 1 unless $ent;
print "not " if $err;
print "ok\n";
$conn->delete($ent->getDN()) if $ent;
#################################################################################
# Test error handling (ToDo!)
#

View File

@@ -0,0 +1,150 @@
#!/usr/bin/perl5
#############################################################################
# $Id: entry.pl,v 1.2 1999-01-21 23:52:50 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Test most (all?) of the LDAP::Mozilla::Conn methods.
#
#############################################################################
use Getopt::Std; # To parse command line arguments.
use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils; # LULU, utilities.
use Mozilla::LDAP::API;
use strict;
no strict "vars";
#################################################################################
# Configurations, modify these as needed.
#
$BIND = "uid=ldapadmin";
$BASE = "o=Netscape Communications Corp.,c=US";
$PEOPLE = "ou=people";
$GROUPS = "ou=groups";
$UID = "leif-test";
$CN = "test-group-1";
#################################################################################
# Constants, shouldn't have to edit these...
#
$APPNAM = "entry.pl";
$USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert";
#################################################################################
# Check arguments, and configure some parameters accordingly..
#
if (!getopts('b:h:D:p:s:w:P:'))
{
print "usage: $APPNAM $USAGE\n";
exit;
}
%ld = Mozilla::LDAP::Utils::ldapArgs($BIND, $BASE);
#################################################################################
# Get an LDAP connection
#
sub getConn
{
my $conn;
if ($main::reuseConn)
{
if (!defined($main::mainConn))
{
$main::mainConn = new Mozilla::LDAP::Conn(\%main::ld);
die "Could't connect to LDAP server $main::ld{host}"
unless $main::mainConn;
}
return $main::mainConn;
}
else
{
$conn = new Mozilla::LDAP::Conn(\%main::ld);
die "Could't connect to LDAP server $main::ld{host}" unless $conn;
}
return $conn;
}
#################################################################################
# Some small help functions...
#
sub dotPrint
{
my $str = shift;
print $str . '.' x (20 - length($str));
}
sub attributeEQ
{
my @a, @b;
my $i;
@a = @{$_[0]};
@b = @{$_[1]};
return 1 if (($#a < 0) && ($#b < 0));
return 0 unless ($#a == $#b);
@a = sort(@a);
@b = sort(@b);
for ($i = 0; $i <= $#a; $i++)
{
return 0 unless ($a[$i] eq $b[$i]);;
}
return 1; # We passed all the tests, we're ok.
}
#################################################################################
# Setup the test entries.
#
$filter = "(uid=$UID)";
$conn = getConn();
$nentry = $conn->newEntry();
$nentry->setDN("uid=$UID, $PEOPLE, $BASE");
$nentry->{objectclass} = [ "top", "person", "inetOrgPerson", "mailRecipient" ];
$nentry->addValue("uid", $UID);
$nentry->addValue("sn", "Hedstrom");
$nentry->addValue("givenName", "Leif");
$nentry->addValue("cn", "Leif Hedstrom");
$nentry->addValue("cn", "Leif P. Hedstrom");
$nentry->addValue("cn", "The Swede");
$nentry->addValue("description", "Test1");
$nentry->addValue("description", "Test2");
$nentry->addValue("description", "Test3");
$nentry->addValue("description", "Test4");
$nentry->addValue("description", "Test5");
$nentry->addValue("mail", "leif\@ogre.com");
$ent = $conn->search($ld{root}, $ld{scope}, $filter);
$conn->delete($ent->getDN()) if $ent;
$conn->add($nentry);
$conn->close();

View File

@@ -0,0 +1,162 @@
#############################################################################
# $Id: test.pl,v 1.6 1998-08-13 09:14:44 leif Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
#
#############################################################################
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
BEGIN { $| = 1; print "1..8\n"; }
END {print "modinit - not ok\n" unless $loaded;}
use Mozilla::LDAP::API qw(:constant :api :ssl);
$loaded = 1;
print "modinit - ok\n";
######################### End of black magic.
$attrs = [];
$ldap_host = $ENV{"LDAPHOST"};
$filter = $ENV{"TESTFILTER"};
$BASEDN = $ENV{"LDAPBASE"};
if (!$ldap_host)
{
print "\nEnter LDAP Server: ";
chomp($ldap_host = <>);
}
if (!$filter)
{
print "Enter Search Filter (ex. uid=abc123): ";
chomp($filter = <>);
}
if (!$BASEDN)
{
print "Enter LDAP Search Base (ex. o=Org, c=US): ";
chomp($BASEDN = <>);
}
print "\n";
##
## Initialize LDAP Connection
##
if (($ld = ldap_init($ldap_host,LDAP_PORT)) == -1)
{
print "open - not ok\n";
exit -1;
}
print "open - ok\n";
##
## Bind as DN, PASSWORD (NULL,NULL) on LDAP connection $ld
##
if (ldap_simple_bind_s($ld,"","") != LDAP_SUCCESS)
{
ldap_perror($ld,"bind_s");
print "bind - not ok\n";
exit -1;
}
print "bind - ok\n";
##
## ldap_search_s - Synchronous Search
##
if (ldap_search_s($ld,$BASEDN,LDAP_SCOPE_SUBTREE,$filter,$attrs,0,$result) != LDAP_SUCCESS)
{
ldap_perror($ld,"search_s");
print "search - not ok\n";
}
print "search - ok\n";
##
## ldap_count_entries - Count Matched Entries
##
if (($count = ldap_count_entries($ld,$result)) == -1)
{
ldap_perror($ld,"count_entry");
print "count - not ok\n";
}
print "count - ok - $count\n";
##
## first_entry - Get First Matched Entry
## next_entry - Get Next Matched Entry
##
for ($ent = ldap_first_entry($ld,$result); $ent; $ent = ldap_next_entry($ld,$ent))
{
##
## ldap_get_dn - Get DN for Matched Entries
##
if (($dn = ldap_get_dn($ld,$ent)) ne "")
{
print "getdn - ok - $dn\n";
} else {
ldap_perror($ld,"get_dn");
print "getdn - not ok\n";
}
for ($attr = ldap_first_attribute($ld,$ent,$ber); $attr; $attr = ldap_next_attribute($ld,$ent,$ber))
{
print "firstatt - ok - $attr\n";
##
## ldap_get_values
##
@vals = ldap_get_values($ld,$ent,$attr);
if ($#vals >= 0)
{
foreach $val (@vals)
{
print "getvals - ok - $val\n";
}
} else {
print "getvals - not ok\n";
}
}
}
##
## Unbind LDAP Connection
##
ldap_unbind($ld);

View File

@@ -0,0 +1,280 @@
#!/usr/bin/perl -w
#############################################################################
# $Id: api.pl,v 1.7 1999-01-21 23:52:52 leif%netscape.com Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# api.pl - Test all LDAPv2 API function
# Author: Clayton Donley <donley@wwa.com>
#
# Performs all API calls directly in order to test for possible issues
# on a particular platform.
#
#############################################################################
use Mozilla::LDAP::API qw(:api :constant);
use strict;
my $BASE = "ou=Test,o=Test,c=US";
my $DN = "cn=Directory Manager";
my $PASS = "abcd1234";
my $HOST = "";
my $PORT = 389;
if (!$HOST)
{
print "Please edit the variables at the top of this file.\n";
exit -1;
}
print "\nPerLDAP API TestSuite\n";
print "\nNote: Failures in earlier tests will cause later tests to fail.\n";
print "\n";
my $howmany = 10;
# Initialize the Connection
{
my $ld = ldap_init($HOST,$PORT);
if ($ld <0)
{
print "init - Failed!\n";
die;
}
print "init - OK\n";
# Set an LDAP Session Option
if (ldap_set_option($ld,LDAP_OPT_PROTOCOL_VERSION,LDAP_VERSION3)
!= LDAP_SUCCESS)
{
print "set_option - Failed!\n";
} else {
print "set_option - OK\n";
}
# Get an LDAP Session Option
my $option;
ldap_get_option($ld,LDAP_OPT_REFERRALS,$option);
if ($option != 1)
{
print "get_option - Failed!\n";
} else {
print "get_option - OK\n";
}
# Anonymous Bind
if (ldap_simple_bind_s($ld,"","") != LDAP_SUCCESS)
{
print "anon_bind - Failed!\n";
} else {
print "anon_bind - OK\n";
}
# Authenticated Simple Bind
if (ldap_simple_bind_s($ld,$DN,$PASS) != LDAP_SUCCESS)
{
print "simple_bind - Failed!\n";
} else {
print "simple_bind - OK\n";
}
# Set Rebind Process
my $rebindproc = sub { return($DN,$PASS,LDAP_AUTH_SIMPLE); };
ldap_set_rebind_proc($ld,$rebindproc);
print "set_rebind - OK\n";
# Add an OrgUnit Entry
my $entry = {
"objectclass" => ["top","organizationalUnit"],
"ou" => "Test",
};
if (ldap_add_s($ld,$BASE,$entry) != LDAP_SUCCESS)
{
print "add_org - Failed!\n";
} else {
print "add_org - OK\n";
}
# Add People
foreach my $number (1..$howmany)
{
$entry = {
"objectclass" => ["top","person"],
"cn" => "Mozilla $number",
"sn" => ["$number"],
};
if (ldap_add_s($ld,"cn=Mozilla $number,$BASE",$entry)
!= LDAP_SUCCESS)
{
print "add_user_$number - Failed!\n";
} else {
print "add_user_$number - OK\n";
}
}
# Modify People
foreach my $number (1..$howmany)
{
$entry = {
"sn" => {"ab",["Test"]},
"telephoneNumber" => {"ab",[123.456]},
# "telephoneNumber" => "800-555-111$number",
};
if (ldap_modify_s($ld,"cn=Mozilla $number,$BASE",$entry)
!= LDAP_SUCCESS)
{
print "mod_user_$number - Failed!\n";
} else {
print "mod_user_$number - OK\n";
}
}
# Search People
my $filter = "(sn=Test)";
my $attrs = ["cn","sn"];
my $res;
if (ldap_search_s($ld,$BASE,LDAP_SCOPE_SUBTREE,$filter,$attrs,0,$res)
!= LDAP_SUCCESS)
{
print "search_user - Failed!\n";
} else {
print "search_user - OK\n";
}
# Count Results
if (ldap_count_entries($ld,$res) != $howmany)
{
print "count_res - Failed!\n";
} else {
print "count_res - OK\n";
}
# Sort Results
if (ldap_sort_entries($ld,$res,"sn") != LDAP_SUCCESS)
{
print "sort_ent - Failed!\n";
} else {
print "sort_ent - OK\n";
}
# Multisort Results
if (ldap_multisort_entries($ld,$res,["sn","telephoneNumber"]) != LDAP_SUCCESS)
{
print "multisort - Failed!\n";
} else {
print "multisort - OK\n";
}
# Get First Entry
my $ent = ldap_first_entry($ld,$res);
if (!$ent)
{
print "first_entry - Failed!\n";
} else {
print "first_entry - OK\n";
}
# Get Next Entry
$ent = ldap_next_entry($ld,$ent);
if (!$ent)
{
print "next_entry - Failed!\n";
} else {
print "next_entry - OK\n";
}
# Get DN
my $dn = ldap_get_dn($ld,$ent);
if (!$dn)
{
print "get_dn - Failed!\n";
} else {
print "get_dn - OK\n";
}
# Get First Attribute
my $ber;
my $attr = ldap_first_attribute($ld,$ent,$ber);
if (!$attr)
{
print "first_attr - Failed!\n";
} else {
print "first_attr - OK\n";
}
# Get Next Attribute
$attr = ldap_next_attribute($ld,$ent,$ber);
if (!$attr)
{
print "next_attr - Failed!\n";
} else {
print "next_attr - OK\n";
}
# Get Attribute Values
my @vals = ldap_get_values($ld,$ent,$attr);
if ($#vals < 0)
{
print "get_values - Failed!\n";
} else {
print "get_values - OK\n";
}
# Free structures pointed to by $ber and $res to prevent memory leak
ldap_ber_free($ber,1);
ldap_msgfree($res);
# Compare Attribute Values
foreach my $number (1..$howmany)
{
if(ldap_compare_s($ld,"cn=Mozilla $number,$BASE","sn",$number)
!= LDAP_COMPARE_TRUE)
{
print "comp_user_$number - Failed!\n";
} else {
print "comp_user_$number - OK\n";
}
}
# Delete Users
foreach my $number (1..$howmany)
{
if (ldap_delete_s($ld,"cn=Mozilla $number,$BASE") != LDAP_SUCCESS)
{
print "del_user_$number - Failed!\n";
} else {
print "del_user_$number - OK\n";
}
}
if (ldap_delete_s($ld,"$BASE") != LDAP_SUCCESS)
{
print "del_org - Failed!\n";
} else {
print "del_org - OK\n";
}
# Unbind
ldap_unbind($ld);
}

View File

@@ -0,0 +1,131 @@
#!/usr/bin/perl
#############################################################################
# $Id: search.pl,v 1.4 1998-08-13 04:40:01 clayton Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerlDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Test the search capabilities of the API, similar to write.pl.
#
#############################################################################
use Mozilla::LDAP::API qw(:api :constant);
use strict;
my $ldap_host = "";
my $BASEDN = "o=Org,c=US";
my $filter = $ARGV[0];
if (!$ldap_host)
{
print "Edit the top portion of this file before continuing.\n";
exit -1;
}
my $attrs = [];
my ($ld,$result,$count);
##
## Initialize LDAP Connection
##
if (($ld = ldap_init($ldap_host,LDAP_PORT)) == -1)
{
die "Can not open LDAP connection to $ldap_host";
}
##
## Bind as DN, PASSWORD (NULL,NULL) on LDAP connection $ld
##
if (ldap_simple_bind_s($ld,"","") != LDAP_SUCCESS)
{
ldap_perror($ld,"bind_s");
die;
}
##
## ldap_search_s - Synchronous Search
##
if (ldap_search_s($ld,$BASEDN,LDAP_SCOPE_SUBTREE,$filter,$attrs,0,$result) != LDAP_SUCCESS)
{
ldap_perror($ld,"search_s");
die;
}
##
## ldap_count_entries - Count Matched Entries
##
if (($count = ldap_count_entries($ld,$result)) == -1)
{
ldap_perror($ld,"count_entry");
die;
}
##
## first_entry - Get First Matched Entry
## next_entry - Get Next Matched Entry
##
for (my $ent = ldap_first_entry($ld,$result); $ent; $ent = ldap_next_entry($ld,$ent))
{
##
## ldap_get_dn - Get DN for Matched Entries
##
my ($dn,$attr,@vals,$val,$ber);
if (($dn = ldap_get_dn($ld,$ent)) ne "")
{
print "dn: $dn\n";
} else {
ldap_perror($ld,"get_dn");
die;
}
for ($attr = ldap_first_attribute($ld,$ent,$ber); $attr; $attr = ldap_next_attribute($ld,$ent,$ber))
{
##
## ldap_get_values
##
@vals = ldap_get_values($ld,$ent,$attr);
if ($#vals >= 0)
{
foreach $val (@vals)
{
print "$attr: $val\n";
}
}
}
ldap_ber_free($ber,0);
}
ldap_msgfree($result);
##
## Unbind LDAP Connection
##
ldap_unbind($ld);

View File

@@ -0,0 +1,110 @@
#!/usr/bin/perl -w
#############################################################################
# $Id: write.pl,v 1.4 1998-08-13 04:40:02 clayton Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerlDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# write.pl - Test of LDAP Modify Operations in Perl5
# Author: Clayton Donley <donley@wwa.com>
#
# This utility is mostly to demonstrate all the write operations
# that can be done with LDAP through this PERL5 module.
#
#############################################################################
use strict;
use Mozilla::LDAP::API qw(:constant :api);
# This is the entry we will be adding. Do not use a pre-existing entry.
my $ENTRYDN = "cn=Test Guy, o=Org, c=US";
# This is the DN and password for an Administrator
my $ROOTDN = "cn=DSManager,o=Org,c=US";
my $ROOTPW = "";
my $ldap_server = "";
if (!$ldap_server)
{
print "Edit the top portion of this file before continuing.\n";
exit -1;
}
my $ld = ldap_init($ldap_server,LDAP_PORT);
if ($ld == -1)
{
die "Connection to LDAP Server Failed";
}
if (ldap_simple_bind_s($ld,$ROOTDN,$ROOTPW) != LDAP_SUCCESS)
{
ldap_perror($ld,"bind_s");
die;
}
my %testwrite = (
"cn" => "Test User",
"sn" => "User",
"givenName" => "Test",
"telephoneNumber" => "8475551212",
"objectClass" => ["top","person","organizationalPerson",
"inetOrgPerson"],
"mail" => "tuser\@my.org",
);
if (ldap_add_s($ld,$ENTRYDN,\%testwrite) != LDAP_SUCCESS)
{
ldap_perror($ld,"add_s");
die;
}
print "Entry Added.\n";
%testwrite = (
"telephoneNumber" => "7085551212",
"mail" => {"a",["Test_User\@my.org"]},
);
if (ldap_modify_s($ld,$ENTRYDN,\%testwrite) != LDAP_SUCCESS)
{
ldap_perror($ld,"modify_s");
die;
}
print "Entry Modified.\n";
#
# Delete the entry for $ENTRYDN
#
if (ldap_delete_s($ld,$ENTRYDN) != LDAP_SUCCESS)
{
ldap_perror($ld,"delete_s");
die;
}
print "Entry Deleted.\n";
# Unbind to LDAP server
ldap_unbind($ld);
exit;

View File

@@ -0,0 +1,70 @@
#############################################################################
# $Id: typemap,v 1.4 1998-08-13 09:15:00 leif Exp $
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is PerLDAP. The Initial Developer of the Original
# Code is Netscape Communications Corp. and Clayton Donley. Portions
# created by Netscape are Copyright (C) Netscape Communications
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
# Donley. All Rights Reserved.
#
# Contributor(s):
#
# DESCRIPTION
# Typemap to declare XSUB data types.
#
#############################################################################
const int T_IV
char * T_PV
const char * T_PV
char ** T_charptrptr
LDAP * T_PTR
LDAPMessage * T_PTR
LDAPMessage ** T_PTR
BerElement * T_PTR
LDAPControl * T_PTR
LDAPVersion * T_PTR
struct berval T_berval
struct berval ** T_bervalptrptr
FriendlyMap * T_PTR
LDAPsortkey ** T_PTR
LDAPVirtualList * T_PTR
LDAPURLDesc * T_PTR
LDAPControl ** T_PTR
LDAPFiltDesc * T_PTR
LDAPFiltInfo * T_PTR
LDAPMemCache * T_PTR
LDAPMemCache ** T_PTR
struct ldap_thread_fns * T_PTR
LDAPMod ** T_PTR
LDAP_CMP_CALLBACK * T_PTR
LDAP_REBINDPROC_CALLBACK * T_PTR
struct timeval T_timeval
#########
INPUT
T_timeval
$var.tv_sec = atof((char *)SvPV($arg,na));
$var.tv_usec = 0
T_berval
$var.bv_val = (char *)SvPV($arg,na);
$var.bv_len = na
T_charptrptr
$var = (char **)avref2charptrptr($arg)
T_bervalptrptr
$var = (struct berval **)avref2berptrptr($arg)
OUTPUT
T_charptrptr
$arg = charptrptr2avref($var);
T_bervalptrptr
$arg = berptrptr2avref((struct berval **)$var);

View File

@@ -1,5 +0,0 @@
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>

View File

@@ -1,69 +0,0 @@
<?php
/* SVN FILE: $Id: app_controller.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* Short description for file.
*
* This file is application-wide controller file. You can put all
* application-wide controller-related methods here.
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.cake
* @since CakePHP v 0.2.9
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Short description for class.
*
* Add your application-wide methods in the class below, your controllers
* will inherit them.
*
* @package cake
* @subpackage cake.cake
*/
uses('Sanitize');
class AppController extends Controller {
/**
* This function is intended to be used with url parameters when passing them to
* a view. (This is useful when echoing values out in <input> tags, etc.
* Note that the keys to the arrays are escaped as well.
*
* @param array dirty parameters
* @return array cleaned values
*/
function decodeAndSanitize($params)
{
$clean = array();
foreach ($params as $var => $val) {
$var = $this->Sanitize->html(urldecode($var));
$val = $this->Sanitize->html(urldecode($val));
$clean[$var] = $val;
}
return $clean;
}
}
?>

View File

@@ -1,72 +0,0 @@
<?php
/* SVN FILE: $Id: app_model.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* Application model for Cake.
*
* This file is application-wide model file. You can put all
* application-wide model-related methods here.
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.cake
* @since CakePHP v 0.2.9
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Application model for Cake.
*
* Add your application-wide methods in the class below, your models
* will inherit them.
*
* @package cake
* @subpackage cake.cake
*/
uses('sanitize');
class AppModel extends Model {
/**
* Will clean arrays for input into SQL.
* Note that the array keys are getting cleaned here as well. If you're using strings
* (with escapable characters in them) as keys to your array, be extra careful.
*
* @access public
* @param array to be cleaned
* @return array with sql escaped
*/
function cleanArrayForSql($array)
{
$sanitize = new Sanitize();
$clean = array();
foreach ($array as $var => $val)
{
$var = $sanitize->sql($var);
$val = $sanitize->sql($val);
$clean[$var] = $val;
}
return $clean;
}
}
?>

View File

@@ -1,76 +0,0 @@
;<?php die() ?>
; SVN FILE: $Id: acl.ini.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $
;/**
; * Short description for file.
; *
; *
; * PHP versions 4 and 5
; *
; * CakePHP : Rapid Development Framework <http://www.cakephp.org/>
; * Copyright (c) 2006, Cake Software Foundation, Inc.
; * 1785 E. Sahara Avenue, Suite 490-204
; * Las Vegas, Nevada 89104
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @filesource
; * @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
; * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
; * @package cake
; * @subpackage cake.app.config
; * @since CakePHP v 0.10.0.1076
; * @version $Revision: 1.1.1.1 $
; * @modifiedby $LastChangedBy: phpnut $
; * @lastmodified $Date: 2006-05-24 19:14:24 $
; * @license http://www.opensource.org/licenses/mit-license.php The MIT License
; */
; acl.ini.php - Cake ACL Configuration
; ---------------------------------------------------------------------
; Use this file to specify user permissions.
; aco = access control object (something in your application)
; aro = access request object (something requesting access)
;
; User records are added as follows:
;
; [uid]
; groups = group1, group2, group3
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; Group records are added in a similar manner:
;
; [gid]
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; The allow, deny, and groups sections are all optional.
; NOTE: groups names *cannot* ever be the same as usernames!
;
; ACL permissions are checked in the following order:
; 1. Check for user denies (and DENY if specified)
; 2. Check for user allows (and ALLOW if specified)
; 3. Gather user's groups
; 4. Check group denies (and DENY if specified)
; 5. Check group allows (and ALLOW if specified)
; 6. If no aro, aco, or group information is found, DENY
;
; ---------------------------------------------------------------------
;-------------------------------------
;Users
;-------------------------------------
[username-goes-here]
groups = group1, group2
deny = aco1, aco2
allow = aco3, aco4
;-------------------------------------
;Groups
;-------------------------------------
[groupname-goes-here]
deny = aco5, aco6
allow = aco7, aco8

View File

@@ -1,50 +0,0 @@
<?php
/* SVN FILE: $Id: bootstrap.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* Short description for file.
*
* Long description for file
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP v 0.10.8.2117
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
*
* This file is loaded automatically by the app/webroot/index.php file after the core bootstrap.php is loaded
* This is an application wide file to load any function that is not used within a class define.
* You can also use this to include or require any files in your application.
*
*/
/**
* The settings below can be used to set additional paths to models, views and controllers.
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
*
* $modelPaths = array('full path to models', 'second full path to models', 'etc...');
* $viewPaths = array('this path to views', 'second full path to views', 'etc...');
* $controllerPaths = array('this path to controllers', 'second full path to controllers', 'etc...');
*
*/
//EOF
?>

View File

@@ -1,153 +0,0 @@
<?php
/* SVN FILE: $Id: core.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* This is core configuration file.
*
* Use it to configure core behaviour ofCake.
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP v 0.2.9
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* If you do not have mod rewrite on your system
* or if you prefer to use CakePHP pretty urls.
* uncomment the line below.
* Note: If you do have mod rewrite but prefer the
* CakePHP pretty urls, you also have to remove the
* .htaccess files
* release/.htaccess
* release/app/.htaccess
* release/app/webroot/.htaccess
*/
//define ('BASE_URL', env('SCRIPT_NAME'));
/**
* Set debug level here:
* - 0: production
* - 1: development
* - 2: full debug with sql
* - 3: full debug with sql and dump of the current object
*
* In production, the "flash messages" redirect after a time interval.
* With the other debug levels you get to click the "flash message" to continue.
*
*/
define('DEBUG', 0);
/**
* Turn of caching checking wide.
* You must still use the controller var cacheAction inside you controller class.
* You can either set it controller wide, or in each controller method.
* use var $cacheAction = true; or in the controller method $this->cacheAction = true;
*/
define ('CACHE_CHECK', false);
/**
* Error constant. Used for differentiating error logging and debugging.
* Currently PHP supports LOG_DEBUG
*/
define ('LOG_ERROR', 2);
/**
* CakePHP includes 3 types of session saves
* database or file. Set this to your preferred method.
* If you want to use your own save handler place it in
* app/config/name.php DO NOT USE file or database as the name.
* and use just the name portion below.
*
* Setting this to cake will save files to /cakedistro/tmp directory
* Setting it to php will use the php default save path
* Setting it to database will use the database
*
*
*/
define('CAKE_SESSION_SAVE', 'php');
/**
* Set a random string of used in session.
*
*/
define('CAKE_SESSION_STRING', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
/**
* Set the name of session cookie
*
*/
define('CAKE_SESSION_COOKIE', 'CAKEPHP');
/**
* Set level of Cake security.
*
*/
define('CAKE_SECURITY', 'high');
/**
* Set Cake Session time out.
* If CAKE_SECURITY define is set
* high: multiplied by 10
* medium: is multiplied by 100
* low is: multiplied by 300
*
* Number below is seconds.
*/
define('CAKE_SESSION_TIMEOUT', '120');
/**
* Uncomment the define below to use cake built in admin routes.
* You can set this value to anything you want.
* All methods related to the admin route should be prefixed with the
* name you set CAKE_ADMIN to.
* For example: admin_index, admin_edit
*/
//define('CAKE_ADMIN', 'admin');
/**
* The define below is used to turn cake built webservices
* on or off. Default setting is off.
*/
define('WEBSERVICES', 'off');
/**
* Compress output CSS (removing comments, whitespace, repeating tags etc.)
* This requires a/var/cache directory to be writable by the web server (caching).
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use Controller::cssTag().
*/
define('COMPRESS_CSS', false);
/**
* If set to true, helpers would output data instead of returning it.
*/
define('AUTO_OUTPUT', false);
/**
* If set to false, session would not automatically be started.
*/
define('AUTO_SESSION', true);
/**
* Set the max size of file to use md5() .
*/
define('MAX_MD5SIZE', (5*1024)*1024 );
/**
* To use Access Control Lists with Cake...
*/
define('ACL_CLASSNAME', 'DB_ACL');
define('ACL_FILENAME', 'dbacl'.DS.'db_acl');
?>

View File

@@ -1,79 +0,0 @@
<?php
/* SVN FILE: $Id: database.php.default,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* This is core configuration file.
*
* Use it to configure core behaviour ofCake.
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP v 0.2.9
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* In this file you set up your database connection details.
*
* @package cake
* @subpackage cake.config
*/
/**
* Database configuration class.
* You can specify multiple configurations for production, development and testing.
*
* driver =>
* mysql, postgres, sqlite, adodb-drivername, pear-drivername
*
* connect =>
* MySQL set the connect to either mysql_pconnect of mysql_connect
* PostgreSQL set the connect to either pg_pconnect of pg_connect
* SQLite set the connect to sqlite_popen sqlite_open
* ADOdb set the connect to one of these
* (http://phplens.com/adodb/supported.databases.html) and
* append it '|p' for persistent connection. (mssql|p for example, or just mssql for not persistent)
*
* host =>
* the host you connect to the database
* MySQL 'localhost' to add a port number use 'localhost:port#'
* PostgreSQL 'localhost' to add a port number use 'localhost port=5432'
*
*/
class DATABASE_CONFIG
{
var $default = array('driver' => 'mysql',
'connect' => 'mysql_connect',
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'project_name',
'prefix' => '');
var $test = array('driver' => 'mysql',
'connect' => 'mysql_connect',
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'project_name-test',
'prefix' => '');
}
?>

View File

@@ -1,74 +0,0 @@
<?php
/* SVN FILE: $Id: inflections.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* Custom Inflected Words.
*
* This file is used to hold words that are not matched in the normail Inflector::pluralize() and
* Inflector::singularize()
*
* PHP versions 4 and %
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP v 1.0.0.2312
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* This is a key => value array of regex used to match words.
* If key matches then the value is returned.
*
* $pluralRules = array('/(s)tatus$/i' => '\1\2tatuses', '/^(ox)$/i' => '\1\2en', '/([m|l])ouse$/i' => '\1ice');
*/
$pluralRules = array();
/**
* This is a key only array of plural words that should not be inflected.
* Notice the last comma
*
* $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox');
*/
$uninflectedPlural = array();
/**
* This is a key => value array of plural irregular words.
* If key matches then the value is returned.
*
* $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers')
*/
$irregularPlural = array();
/**
* This is a key => value array of regex used to match words.
* If key matches then the value is returned.
*
* $singularRules = array('/(s)tatuses$/i' => '\1\2tatus', '/(matr)ices$/i' =>'\1ix','/(vert|ind)ices$/i')
*/
$singularRules = array();
/**
* This is a key only array of singular words that should not be inflected.
* You should not have to change this value below if you do change it use same format
* as the $uninflectedPlural above.
*/
$uninflectedSingular = $uninflectedPlural;
/**
* This is a key => value array of singular irregular words.
* Most of the time this will be a reverse of the above $irregularPlural array
* You should not have to change this value below if you do change it use same format
*
* $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother')
*/
$irregularSingular = array_flip($irregularPlural);
?>

View File

@@ -1,51 +0,0 @@
<?php
/* SVN FILE: $Id: routes.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* Short description for file.
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different urls to chosen controllers and their actions (functions).
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP v 0.2.9
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Here, we are connecting '/' (base path) to controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
* to use (in this case, /app/views/pages/home.thtml)...
*/
$Route->connect ('/', array('controller'=>'results', 'action'=>'', ''));
/**
* ...and connect the rest of 'Pages' controller's urls.
*/
$Route->connect ('/pages/*', array('controller'=>'pages', 'action'=>'display'));
/**
* Then we connect url '/test' to our test controller. This is helpfull in
* developement.
*/
$Route->connect ('/tests', array('controller'=>'tests', 'action'=>'index'));
?>

View File

@@ -1,30 +0,0 @@
CREATE TABLE `acos` (
`id` int(11) NOT NULL auto_increment,
`model` varchar(255) NOT NULL default '',
`object_id` int(11) default NULL,
`alias` varchar(255) NOT NULL default '',
`lft` int(11) default NULL,
`rght` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `aros` (
`id` int(11) NOT NULL auto_increment,
`model` varchar(255) NOT NULL default '',
`user_id` int(11) default NULL,
`alias` varchar(255) NOT NULL default '',
`lft` int(11) default NULL,
`rght` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `aros_acos` (
`id` int(11) NOT NULL auto_increment,
`aro_id` int(11) default NULL,
`aco_id` int(11) default NULL,
`_create` int(1) NOT NULL default '0',
`_read` int(1) NOT NULL default '0',
`_update` int(1) NOT NULL default '0',
`_delete` int(11) NOT NULL default '0',
PRIMARY KEY (`id`)
);

View File

@@ -1,11 +0,0 @@
-- @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
-- @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
-- @since CakePHP v 0.10.8.1997
-- @version $Revision: 1.1.1.1 $
CREATE TABLE cake_sessions (
id varchar(255) NOT NULL default '',
data text,
expires int(11) default NULL,
PRIMARY KEY (id)
);

View File

@@ -1,7 +0,0 @@
<?php
class ApplicationsController extends AppController {
var $name = 'Applications';
}
?>

View File

@@ -1,7 +0,0 @@
<?php
class IntentionsController extends AppController {
var $name = 'Intentions';
}
?>

View File

@@ -1,7 +0,0 @@
<?php
class IssuesController extends AppController {
var $name = 'Issues';
}
?>

View File

@@ -1,122 +0,0 @@
<?php
/* Include the CSV library. It would be nice to make this OO sometime */
vendor('csv/csv');
class ResultsController extends AppController {
var $name = 'Results';
/**
* Model's this controller uses
* @var array
*/
var $uses = array('Application','Result');
/**
* Cake Helpers
* @var array
*/
var $helpers = array('Html', 'Javascript', 'Export', 'Pagination','Time');
/**
* Pagination helper variable array
* @access public
* @var array
*/
var $pagination_parameters = array();
/**
* Will hold a sanitize object
* @var object
*/
var $Sanitize;
/**
* Constructor - sets up the sanitizer and the pagination
*/
function ResultsController()
{
parent::AppController();
$this->Sanitize = new Sanitize();
// Pagination Stuff
$this->pagination_parameters['show'] = empty($_GET['show'])? '10' : $this->Sanitize->paranoid($_GET['show']);
$this->pagination_parameters['sortBy'] = empty($_GET['sort'])? 'created' : $this->Sanitize->paranoid($_GET['sort']);
$this->pagination_parameters['direction'] = empty($_GET['direction'])? 'desc': $this->Sanitize->paranoid($_GET['direction']);
$this->pagination_parameters['page'] = empty($_GET['page'])? '1': $this->Sanitize->paranoid($_GET['page']);
$this->pagination_parameters['order'] = $this->modelClass.'.'.$this->pagination_parameters['sortBy'].' '.strtoupper($this->pagination_parameters['direction']);
}
/**
* Front page will show the graph
*/
function index()
{
// Products dropdown
$this->set('products', $this->Application->getApplications());
// Fill in all the data passed in $_GET
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
// We'll need to include the graphing libraries
$this->set('include_graph_libraries', true);
// Core data to show on page
$this->set('descriptionAndTotalsData',$this->Result->getDescriptionAndTotalsData($this->params['url']));
}
/**
* Display a table of user comments
*/
function comments()
{
// Products dropdown
$this->set('products', $this->Application->getApplications());
// Fill in all the data passed in $_GET
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
// Pagination settings
$paging['style'] = 'html';
$paging['link'] = "/results/comments/?product=".urlencode($this->params['url']['product'])."&start_date=".urlencode($this->params['url']['start_date'])."&end_date=".urlencode($this->params['url']['end_date'])."&show={$this->pagination_parameters['show']}&sort={$this->pagination_parameters['sortBy']}&direction={$this->pagination_parameters['direction']}&page=";
$paging['count'] = $this->Result->getCommentCount($this->params['url']);
$paging['page'] = $this->pagination_parameters['page'];
$paging['limit'] = $this->pagination_parameters['show'];
$paging['show'] = array('10','25','50');
// No point in showing them an error if they click on "show 50" but they are
// already on the last page.
if ($paging['count'] < ($this->pagination_parameters['page'] * ($this->pagination_parameters['show']/2))) {
$this->pagination_parameters['page'] = $paging['page'] = 1;
}
// Set pagination array
$this->set('paging',$paging);
// Core data to show on page
$this->set('commentsData',$this->Result->getComments($this->params['url'], $this->pagination_parameters));
}
/**
* Display a csv
*/
function csv()
{
// Get rid of the header/footer/etc.
$this->layout = null;
// Our CSV library sends headers and everything. Keep the view empty!
csv_send_csv($this->Result->getCsvExportData($this->params['url']));
// I'm not exiting here in case someone is going to use post callback stuff.
// In development, that means extra lines get added to our CSVs, but in
// production it should be clean.
}
}
?>

View File

@@ -1,27 +0,0 @@
<?php
/* SVN FILE: $Id: index.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app
* @since CakePHP v 0.10.0.1076
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
require 'webroot'.DIRECTORY_SEPARATOR.'index.php';
?>

View File

@@ -1,24 +0,0 @@
<?php
class Application extends AppModel {
var $name = 'Application';
var $hasOne = array('Result');
var $hasAndBelongsToMany = array(
'Intention' => array('className' => 'Intention'),
'Issue' => array('className' => 'Issue')
);
/**
* This was added because running findAll() on this model does a left join on the
* results table which takes around 10 seconds to grab all the data. All I want
* is a list of the applications...
*
* @return array rows representing each application
*/
function getApplications()
{
return $this->query('SELECT * FROM `applications` ORDER BY `id`');
}
}
?>

View File

@@ -1,12 +0,0 @@
<?php
class Intention extends AppModel {
var $name = 'Intention';
var $hasOne = array('Result');
var $hasAndBelongsToMany = array('Application' =>
array('className' => 'Application')
);
}
?>

View File

@@ -1,10 +0,0 @@
<?php
class Issue extends AppModel {
var $name = 'Issue';
var $hasAndBelongsToMany = array(
'Application' => array('className' => 'Application'),
'Result' => array('className' => 'Result')
);
}
?>

View File

@@ -1,339 +0,0 @@
<?php
class Result extends AppModel {
var $name = 'Result';
var $belongsTo = array('Application', 'Intention');
var $hasAndBelongsToMany = array('Issue' =>
array('className' => 'Issue')
);
/**
* Count's all the comments, according to the parameters.
* @param array URL parameters
* @return Cake's findCount() value
*/
function getCommentCount($params)
{
// Clean parameters
$params = $this->cleanArrayForSql($params);
// We only want to see rows with comments
$_conditions = array("comments NOT LIKE ''");
if (!empty($params['start_date'])) {
$_timestamp = strtotime($params['start_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
array_push($_conditions, "`created` >= '{$_date}'");
}
}
if (!empty($params['end_date'])) {
$_timestamp = strtotime($params['end_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
array_push($_conditions, "`created` <= '{$_date}'");
}
}
if (!empty($params['product'])) {
// product's come in looking like:
// Mozilla Firefox 1.5.0.1
$_exp = explode(' ',urldecode($params['product']));
if(count($_exp) == 3) {
$_product = $_exp[0].' '.$_exp[1];
$_version = $_exp[2];
/* Note that 'Application' is not the actual name of the table! You can
* thank cake for that.*/
array_push($_conditions, "`Application`.`name` LIKE '%{$_product}%'");
array_push($_conditions, "`Application`.`version` LIKE '%{$_version}%'");
} else {
// defaults I guess?
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
}
} else {
// I'm providing a default here, because otherwise all results will be
// returned (across all applications) and that is not desired
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
}
// Do the actual query
$comments = $this->findCount($_conditions);
return $comments;
}
/**
* Will retrieve all the comments within param's and pagination's parameters
* @param array URL parameters
* @param array pagination values from the controller
* @param boolean if privacy is true phone numbers and email addresses will be
* masked
* @return cake result set
*/
function getComments($params, $pagination, $privacy=true)
{
$params = $this->cleanArrayForSql($params);
// We only want to see rows with comments
$_conditions = array("comments NOT LIKE ''");
if (!empty($params['start_date'])) {
$_timestamp = strtotime($params['start_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
array_push($_conditions, "`created` >= '{$_date}'");
}
}
if (!empty($params['end_date'])) {
$_timestamp = strtotime($params['end_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
array_push($_conditions, "`created` <= '{$_date}'");
}
}
if (!empty($params['product'])) {
// product's come in looking like:
// Mozilla Firefox 1.5.0.1
$_exp = explode(' ',urldecode($params['product']));
if(count($_exp) == 3) {
$_product = $_exp[0].' '.$_exp[1];
$_version = $_exp[2];
/* Note that 'Application' is not the actual name of the table! You can
* thank cake for that.*/
array_push($_conditions, "`Application`.`name` LIKE '%{$_product}%'");
array_push($_conditions, "`Application`.`version` LIKE '%{$_version}%'");
} else {
// defaults I guess?
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
}
} else {
// I'm providing a default here, because otherwise all results will be
// returned (across all applications) and that is not desired
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
}
$comments = $this->findAll($_conditions, null, $pagination['order'], $pagination['show'], $pagination['page']);
if ($privacy) {
// Pull out all the email addresses and phone numbers
foreach ($comments as $var => $val) {
// Handle foo@bar.com
$_email_regex = '/\ ?(.+)?@(.+)?\.(.+)?\ ?/';
$comments[$var]['Result']['comments'] = preg_replace($_email_regex,'$1@****.$3',$comments[$var]['Result']['comments']);
$comments[$var]['Result']['intention_text'] = preg_replace($_email_regex,'$1@****.$3',$comments[$var]['Result']['intention_text']);
// Handle xxx-xxx-xxxx
$_phone_regex = '/([0-9]{3})[ .-]?[0-9]{4}/';
$comments[$var]['Result']['comments'] = preg_replace($_phone_regex,'$1-****',$comments[$var]['Result']['comments']);
$comments[$var]['Result']['intention_text'] = preg_replace($_phone_regex,'$1-****',$comments[$var]['Result']['intention_text']);
}
}
return $comments;
}
/**
* This function runs the query to get the export data for the CSV file.
*
* @param array URL parameters
* @param boolean if privacy is true phone numbers and email addresses will be
* masked
* @return array two dimensional array that should be pretty easy to transform
* into a CSV.
*/
function getCsvExportData($params, $privacy=true)
{
$params = $this->cleanArrayForSql($params);
// We have to use a left join here because there isn't always an intention
$_query = "
SELECT
`results`.`id`,
`results`.`created`,
`results`.`intention_text` as `intention_other`,
`results`.`comments`,
`intentions`.`description` as `intention`
FROM `results`
LEFT JOIN `intentions` ON `results`.`intention_id`=`intentions`.`id`
INNER JOIN `applications` ON `applications`.`id` = `results`.`application_id`
WHERE
1=1
";
if (!empty($params['start_date'])) {
$_timestamp = strtotime($params['start_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
$_query .= " AND `results`.`created` >= '{$_date}'";
}
}
if (!empty($params['end_date'])) {
$_timestamp = strtotime($params['end_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
$_query .= " AND `results`.`created` <= '{$_date}'";
}
}
if (!empty($params['product'])) {
// product's come in looking like:
// Mozilla Firefox 1.5.0.1
$_exp = explode(' ',urldecode($params['product']));
if(count($_exp) == 3) {
$_product = $_exp[0].' '.$_exp[1];
$_version = $_exp[2];
$_query .= " AND `applications`.`name` LIKE '{$_product}'";
$_query .= " AND `applications`.`version` LIKE '{$_version}'";
} else {
// defaults I guess?
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
$_query .= " AND `applications`.`version` LIKE '1.5'";
}
} else {
// I'm providing a default here, because otherwise all results will be
// returned (across all applications) and that is not desired
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
$_query .= " AND `applications`.`version` LIKE '1.5'";
}
$_query .= " ORDER BY `results`.`created` ASC";
$res = $this->query($_query);
// Since we're exporting to a CSV, we need to flatten the results into a 2
// dimensional table array
$newdata = array();
foreach ($res as $result) {
$newdata[] = array_merge($result['results'], $result['intentions']);
}
if ($privacy) {
// Pull out all the email addresses and phone numbers
foreach ($newdata as $var => $val) {
// Handle foo@bar.com
$_email_regex = '/\ ?(.+)?@(.+)?\.(.+)?\ ?/';
$newdata[$var]['comments'] = preg_replace($_email_regex,'$1@****.$3',$newdata[$var]['comments']);
$newdata[$var]['intention_other'] = preg_replace($_email_regex,'$1@****.$3',$newdata[$var]['intention_other']);
// Handle xxx-xxx-xxxx
$_phone_regex = '/([0-9]{3})[ .-]?[0-9]{4}/';
$newdata[$var]['comments'] = preg_replace($_phone_regex,'$1-****',$newdata[$var]['comments']);
$newdata[$var]['intention_other'] = preg_replace($_phone_regex,'$1-****',$newdata[$var]['intention_other']);
}
}
// Our CSV library just prints out everything in order, so we have to put the
// column labels on here ourselves
$newdata = array_merge(array(array_keys($newdata[0])), $newdata);
return $newdata;
}
/**
* Will retrieve the information used for graphing.
* @param the url parameters (unescaped)
* @return a result set
*/
function getDescriptionAndTotalsData($params)
{
// Clean parameters for inserting into SQL
$params = $this->cleanArrayForSql($params);
/* It would be nice to drop something like this in the SELECT:
*
* CONCAT(COUNT(*)/(SELECT COUNT(*) FROM our_giant_query_all_over_again)*100,'%') AS `percentage`
*/
$_query = "
SELECT
issues.description,
COUNT( DISTINCT results.id ) AS total
FROM
issues
LEFT JOIN
issues_results ON issues_results.issue_id=issues.id
LEFT JOIN results ON results.id=issues_results.result_id AND results.application_id=applications.id
JOIN applications_issues ON applications_issues.issue_id=issues.id
JOIN applications ON applications.id=applications_issues.application_id
WHERE 1=1
";
if (!empty($params['start_date'])) {
$_timestamp = strtotime($params['start_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
$_query.= " AND `results`.`created` >= '{$_date}'";
}
}
if (!empty($params['end_date'])) {
$_timestamp = strtotime($params['end_date']);
if (!($_timestamp == -1) || $_timestamp == false) {
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
$_query .= " AND `results`.`created` <= '{$_date}'";
}
}
if (!empty($params['product'])) {
// product's come in looking like:
// Mozilla Firefox 1.5.0.1
$_exp = explode(' ',urldecode($params['product']));
if(count($_exp) == 3) {
$_product = $_exp[0].' '.$_exp[1];
$_version = $_exp[2];
$_query .= " AND `applications`.`name` LIKE '{$_product}'";
$_query .= " AND `applications`.`version` LIKE '{$_version}'";
} else {
// defaults I guess?
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
$_query .= " AND `applications`.`version` LIKE '1.5'";
}
} else {
// I'm providing a default here, because otherwise all results will be
// returned (across all applications) and that is not desired
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
$_query .= " AND `applications`.`version` LIKE '1.5'";
}
$_query .= " GROUP BY `issues`.`description`
ORDER BY `issues`.`description` DESC";
return $this->query($_query);
}
}
?>

View File

@@ -1,188 +0,0 @@
<?php
/**
* Functions that take a db result and export it to CSV.
* Usage example:
* <code>
* if ($_GET['csv'])
* {
* $res=db_query("SELECT * FROM fic_courses");
* csv_send_csv($res);
* exit;
* }
* </code>
* @package libs
* @subpackage csv
* @author Richard Faaberg <faabergr@onid.orst.edu>
* @author Mike Morgan <mike.morgan@oregonstate.edu>
*/
/**
* Use a resource or two dimensional array, then send the CSV results to user.
* @param mixed $res MySQL resource / result, or a two dimensional array
* @param string $name name of the export file
* @return bool true if file sent, false otherwise
*/
function csv_send_csv($res,$name=null)
{
// set name of the export file
$filename=(is_null($name))?'export-'.date('Y-m-d').'.csv':$name.'.csv';
// check for valid resource
if ( is_resource($res) )
{
$csv=csv_export_to_csv($res);
}
elseif( is_array($res) && !empty($res) )
{
foreach ($res as $row)
{
if ( !is_array($row) )
;
else
$csv[] = csv_array_to_csv($row)."\n";
}
}
if ( is_array($csv) )
{
// stream csv to user
header("Content-type: application/x-csv");
header('Content-disposition: inline; filename="'.$filename.'"');
header('Cache-Control: private');
header('Pragma: public');
foreach ($csv as $row)
{
echo $row;
}
return true;
}
return false;
}
/**
* Replace quotes inside of a field with double quotes, which is something CSV requires.
* @param string $string unquoted quotes
* @return string $string quoted quotes
*/
function csv_fix_quotes($string)
{
return preg_replace('/"/','""',$string);
}
/**
* Replace line breaks with commas trailed by a space.
* @param string $string string containing line breaks
* @param string string without line breaks
*/
function csv_fix_line_breaks($string)
{
return preg_replace('/(\n\r|\r)/','\n',$string);
}
/**
* Replaces instances of double quotes in a string with a single quote.
* @param string $string the string to perform the replacement on
* @return string the string with "" replaced by "
*/
function csv_unfix_quotes($string)
{
return preg_replace('/""/', '"', $string);
}
/**
* Place quotes outside of every field, which inherently solves space, line break issues.
* @param string $string
* @return string $string with quotes around it
*/
function csv_add_quotes($string)
{
return '"'.$string.'"';
}
/**
* Removes quotes from the beginning and the end of a string.
* @param string $string the string to remove the quotes from
* @return string the string, sans quotes at the beginning and end
*/
function csv_remove_quotes($string)
{
$pattern = "/^\"(.*)\"$/";
$replacement = "$1";
return preg_replace($pattern, $replacement, $string);
}
/**
* Convert an array into a CSV string with quotes around each value.
* @param array $array
* @return string the values in $array surrounded by quotes and separated by commas
*/
function csv_array_to_csv($array)
{
$csv_arr = array();
foreach ($array as $value)
{
$csv_arr[]=csv_add_quotes(csv_fix_quotes(csv_fix_line_breaks($value)));
}
$csv_string=implode(',',$csv_arr);
return $csv_string;
}
/**
* Convert a CSV string into an array.
* Please use sparingly - this creates temp files
* @param string $string the CSV string
* @return array the elements from the CSV string in an array
*/
function csv_csv_to_array($string)
{
$return = array();
$length = strlen($string);
// create a temp file and write the string to it
$tmpfname = tempnam('/tmp', 'csvlib');
$fh = fopen($tmpfname, 'w');
fwrite($fh, $string);
fclose($fh);
// open the file for csv parsing
$csvh = fopen($tmpfname, 'r');
while (($arraydata = fgetcsv($csvh, $length, ',')) !== false)
{
$return = array_merge($return, $arraydata);
}
fclose($csvh);
unlink($tmpfname);
return $return;
}
/**
* Read a CSV file into a two dimensional array
* It returns all the rows in the file, so if the first row are headers, you'd need to take care of that in the returned array
* @param string $filepath the path to the csv file
* @param string $delimiter delimiter, default to ','
* @param string $enclosure enclosure character, default to '"'
* @return &array the two dimensional array with the csv file content, or an empty if an error occured
*/
function &csv_csv_file_to_array($filepath, $delimiter=',', $enclosure='"')
{
$return = array();
if (!file_exists($filepath) || !is_readable($filepath))
return $return;
$fh =& fopen($filepath, 'r');
$size = filesize($filepath)+1;
while ($data =& fgetcsv($fh, $size, $delimiter, $enclosure))
{
$return[] = $data;
}
fclose($fh);
return $return;
}
?>

View File

@@ -1,11 +0,0 @@
<div id="t_footer">
</div>
<!-- t_wrapper -->
</div>
<!-- t_border -->
</div>
</body>
</html>

View File

@@ -1,26 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Mozilla Uninstall Survey Data</title>
<meta name="author" content="Mozilla Corporation" />
<meta name="copyright" content="Mozilla Corporation" />
<?php echo $html->charset('UTF-8'); ?>
<?php echo $html->css('screen'); ?>
<?php if (isset($include_graph_libraries) && $include_graph_libraries):
echo $javascript->link('mochikit/MochiKit.js');
echo $javascript->link('plotkit/Base.js');
echo $javascript->link('plotkit/Layout.js');
echo $javascript->link('plotkit/Canvas.js');
echo $javascript->link('plotkit/SweetCanvas.js');
endif; ?>
</head>
<body>
<div id="t_border">
<div id="t_wrapper">
<a class="skipnav" href="#t_content">Skip Navigation Links</a>
<div id="t_header">
<div id="t_title">
<h1>Mozilla Firefox Uninstall Survey Data</h1>
</div>
</div>

View File

@@ -1,6 +0,0 @@
<div id="t_nav">
<ul>
<li><?php echo $html->link('Results', '/results'); ?></li>
<li><?php echo $html->link('Comments', '/results/comments'); ?></li>
</ul>
</div>

View File

@@ -1,36 +0,0 @@
<?php
/**
* When we're exporting data, we end up having to pass all the parameters
* via $_GET. Since we're doing this a few times per page (each graph, and the
* export hrefs) this helper should make that easier.
*/
class ExportHelper
{
/**
* Method to collect the current $_GET parameters and build another string from
* them.
*
* @param string cake URL that you want prepended to the result. eg: reports/graph/
* @param array the array of GET variables to add. These need to be
* pre-sanitized to print in html! This is designed to
* be used from the calling controller like:
* $params = $this->sanitize->html($url_parameters);
* @param string string to put between url and arguments (probably either '?' or
* '&')
* @param array array of strings which will be ignored
* @return string string with the url variables appeneded to it
*/
function buildUrlString($url, $params, $seperator='?', $ignore=array('url'))
{
$arguments = '';
foreach ($params as $var => $val) {
if (!in_array($var, $ignore)) {
$arguments .= empty($arguments) ? "{$var}={$val}" : "&amp;{$var}={$val}";
}
}
return "{$url}{$seperator}{$arguments}";
}
}
?>

View File

@@ -1,196 +0,0 @@
<?php
class PaginationHelper {
var $helpers = array('Html','Ajax');
var $_pageDetails = array();
var $link = '';
var $show = array();
var $page;
var $style;
/**
* Sets the default pagination options.
*
* @param array $paging an array detailing the page options
*/
function setPaging($paging)
{
if(!empty($paging))
{
$this->link = $paging['link'];
$this->show = $paging['show'];
$this->page = $paging['page'];
$this->style = $paging['style'];
$pageCount = ceil($paging['count'] / $paging['limit'] );
$this->_pageDetails = array(
'page'=>$paging['page'],
'recordCount'=>$paging['count'],
'pageCount' =>$pageCount,
'nextPage'=> ($paging['page'] < $pageCount) ? $paging['page']+1 : '',
'previousPage'=> ($paging['page']>1) ? $paging['page']-1 : '',
'limit'=>$paging['limit']
);
return true;
}
return false;
}
/**
* Displays limits for the query
*
* @param string $text - text to display before limits
* @param string $separator - display a separate between limits
*
**/
function show($text=null, $separator=null)
{
if (empty($this->_pageDetails)) { return false; }
if ( !empty($this->_pageDetails['recordCount']) )
{
$t = '';
if(is_array($this->show))
{
$t = $text.$separator;
foreach($this->show as $value)
{
$link = preg_replace('/show=(.*?)&/','show='.$value.'&',$this->link);
if($this->_pageDetails['limit'] == $value)
{
$t .= '<em>'.$value.'</em>'.$separator;
}
else
{
if($this->style == 'ajax')
{
$t .= $this->Ajax->linkToRemote($value, array("fallback"=>$this->action."#","url" => $link.$this->_pageDetails['page'],"update" => "ajax_update","method"=>"get")).$separator;
}
else
{
$t .= $this->Html->link($value,$link.$this->_pageDetails['page']).$separator;
}
}
}
}
return $t;
}
return false;
}
/**
* Displays current result information
*
* @param string $text - text to preceeding the number of results
*
**/
function result($text)
{
if (empty($this->_pageDetails)) { return false; }
if ( !empty($this->_pageDetails['recordCount']) )
{
if($this->_pageDetails['recordCount'] > $this->_pageDetails['limit'])
{
$start_row = $this->_pageDetails['page'] > 1 ? (($this->_pageDetails['page']-1)*$this->_pageDetails['limit'])+1:'1';
$end_row = ($this->_pageDetails['recordCount'] < ($start_row + $this->_pageDetails['limit']-1)) ? $this->_pageDetails['recordCount'] : ($start_row + $this->_pageDetails['limit']-1);
$t = $text.$start_row.'-'.$end_row.' of '.$this->_pageDetails['recordCount'];
}
else
{
$t = $text.$this->_pageDetails['recordCount'];
}
return $t;
}
return false;
}
/**
* Returns a list of page numbers separated by $separator
*
* @param string $separator - defaults to null
*
**/
function pageNumbers($separator=null)
{
if (empty($this->_pageDetails) || $this->_pageDetails['pageCount'] == 1) { return false; }
$t = array();
$text = '';
$pc = 1;
do
{
if($pc == $this->_pageDetails['page'])
{
$text = '<em>'.$pc.'</em>';
}
else
{
if($this->style == 'ajax')
{
$text = $this->Ajax->linkToRemote($pc, array("fallback"=>$this->action."#","url" =>$this->link.$pc,"update" => "ajax_update","method"=>"get"));
}
else
{
$text = $this->Html->link($pc,$this->link.$pc);
}
}
$t[] = $text;
$pc++;
}
while ($pc<=$this->_pageDetails['pageCount']);
$t = implode($separator, $t);
return $t;
}
/**
* Displays a link to the previous page, where the page doesn't exist then
* display the $text
*
* @param string $text - text display: defaults to next
*
**/
function prevPage($text='prev')
{
if (empty($this->_pageDetails)) { return false; }
if ( !empty($this->_pageDetails['previousPage']) )
{
if($this->style == 'ajax')
{
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['previousPage'],"update" => "ajax_update","method"=>"get"));
}
else
{
$t = $this->Html->link($text,$this->link.$this->_pageDetails['previousPage']);
}
return $t;
}
return false;
}
/**
* Displays a link to the next page, where the page doesn't exist then
* display the $text
*
* @param string $text - text to display: defaults to next
*
**/
function nextPage($text='next')
{
if (empty($this->_pageDetails)) { return false; }
if (!empty($this->_pageDetails['nextPage']))
{
if($this->style == 'ajax')
{
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['nextPage'],"update" => "ajax_update","method"=>"get"));
}
else
{
$t = $this->Html->link($text,$this->link.$this->_pageDetails['nextPage']);
}
return $t;
}
return false;
}
}
?>

View File

@@ -1,8 +0,0 @@
<?php echo $this->renderElement( 'header' ); ?>
<?php echo $this->renderElement( 'nav' ); ?>
<div id="t_content_container">
<div id="t_content">
<?php echo $content_for_layout;?>
</div>
</div>
<?php echo $this->renderElement( 'footer'); ?>

View File

@@ -1,51 +0,0 @@
<h1><?php echo Inflector::humanize($this->name); ?></h1>
<div id="queryform">
<?php echo $html->formTag('/results/comments/','get'); ?>
<span>
<label for="start_date">Start Date:</label>
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
<label for="end_date">End Date:</label>
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
</span>
<label for="product">Product:</label>
<select name="product" id="product">
<?php
foreach ($products as $select) :
$product = $select['applications']['name'].' '.$select['applications']['version'];
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
?>
<option<?=$selected?>><?=$product?></option>
<?php endforeach; ?>
</select>
<input type="submit" name="submit" id="submit" value="Go" />
</form>
<br />
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
</div>
<?php if (!empty($commentsData)) : ?>
<table class="comments" summary="User submitted comments.">
<tr><th>Date Recorded</th><th>Comment</th></tr>
<?php foreach ($commentsData as $var => $val) : ?>
<tr><td><?php echo $time->niceShort($val['Result']['created']); ?></td><td><?php echo nl2br(htmlspecialchars($val['Result']['comments'])); ?></td></tr>
<?php endforeach; ?>
</table>
<?php if($pagination->setPaging($paging)):?>
<ul id="page-numbers">
<li><?php echo $pagination->show('Show ', ' '); ?></li>
<li><?php echo $pagination->result('Results: '); ?></li>
<li><?php echo $pagination->pageNumbers(' '); ?></li>
</ul>
<?php endif;?>
<?php else: ?>
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
<?php endif; ?>

View File

@@ -1,91 +0,0 @@
<h1><?php echo Inflector::humanize($this->name); ?></h1>
<div id="queryform">
<?php echo $html->formTag('/results/','get'); ?>
<span>
<label for="start_date">Start Date:</label>
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
<label for="end_date">End Date:</label>
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
</span>
<label for="product">Product:</label>
<select name="product" id="product">
<?php
foreach ($products as $select) :
$product = $select['applications']['name'].' '.$select['applications']['version'];
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
?>
<option<?=$selected?>><?=$product?></option>
<?php endforeach; ?>
</select>
<input type="submit" name="submit" id="submit" value="Go" />
</form>
<br />
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
</div>
<?php if (!empty($descriptionAndTotalsData)) : ?>
<?php
/* Prepare data for graphing */
$_dataset = '';
$_count = 0;
$_total = 0;
/* We've got to do 2 loops here because I need the totals to calculate
* percentages.
*/
foreach ($descriptionAndTotalsData as $var => $val) {
$_total += $val[0]['total'];
}
foreach ($descriptionAndTotalsData as $var => $val) {
// We're putting this in a js string, so escape the double quotes
$_description = str_replace('"','\"',$val['issues']['description']);
$_percentage = intval(($val[0]['total'] / $_total)*100);
$_dataset .= "[{$_count}, {$val[0]['total']}, \"{$_description} (n={$val[0]['total']}, {$_percentage}%)\"], ";
$_count++;
}
$_dataset = "[{$_dataset}]";
?>
<div id="graphcontainer">
<canvas id="graph" height="400" width="800">
<table class="results" summary="Firefox Uninstallation results.">
<tr><th>Reason for uninstalling</th><th>Total</th></tr>
<?php foreach ($descriptionAndTotalsData as $var => $val) : ?>
<tr><td><?=$val['issues']['description']?></td><td><?=$val[0]['total']?></td></tr>
<?php endforeach; ?>
</table>
</canvas>
</div>
<script type="text/javascript">
var layout = new PlotKit.Layout("bar", {"barOrientation":"horizontal"});
layout.addDataset("results", <?=$_dataset?>);
layout.evaluate();
var canvas = MochiKit.DOM.getElement("graph");
var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout,
{
"drawYAxis" : false,
"drawXAxis" : false,
"backgroundColor" : Color.fromHexString('#78c'),
"strokeColor" : Color.fromHexString('#777'),
"strokeWidth" : 1.0,
"enableEvents" : false
});
plotter.render();
</script>
<div id="exportbox">
<a href="<?php echo $export->buildUrlString('results/comments/',$url_params); ?>">View Any Associated Comments»</a><br />
<a href="<?php echo $export->buildUrlString('results/csv/',$url_params); ?>">Download this Data»</a>
</div>
<?php else: ?>
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
<?php endif; ?>

View File

@@ -1,6 +0,0 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>

View File

@@ -1,116 +0,0 @@
<?php
/* SVN FILE: $Id: css.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
/**
* Short description for file.
*
* Long description for file
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.app.webroot
* @since CakePHP v 0.2.9
* @version $Revision: 1.1.1.1 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-24 19:14:24 $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Enter description here...
*/
require(CONFIGS.'paths.php');
require(CAKE.'basics.php');
require(LIBS.'folder.php');
require(LIBS.'file.php');
require(LIBS.'legacy.php');
/**
* Enter description here...
*
* @param unknown_type $path
* @param unknown_type $name
* @return unknown
*/
function make_clean_css ($path, $name)
{
require(VENDORS.'csspp'.DS.'csspp.php');
$data = file_get_contents($path);
$csspp = new csspp();
$output = $csspp->compress($data);
$ratio = 100-(round(strlen($output)/strlen($data), 3)*100);
$output = " /* file: $name, ratio: $ratio% */ " . $output;
return $output;
}
/**
* Enter description here...
*
* @param unknown_type $path
* @param unknown_type $content
* @return unknown
*/
function write_css_cache ($path, $content)
{
if (!is_dir(dirname($path)))
mkdir(dirname($path));
$cache = new File($path);
return $cache->write($content);
}
if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs))
die('Wrong file name.');
$filename = 'css/'.$regs[1];
$filepath = CSS.$regs[1];
$cachepath = CACHE.'css'.DS.str_replace(array('/','\\'), '-', $regs[1]);
if (!file_exists($filepath))
die('Wrong file name.');
if (file_exists($cachepath))
{
$templateModified = filemtime($filepath);
$cacheModified = filemtime($cachepath);
if ($templateModified > $cacheModified)
{
$output = make_clean_css ($filepath, $filename);
write_css_cache ($cachepath, $output);
}
else
{
$output = file_get_contents($cachepath);
}
}
else
{
$output = make_clean_css ($filepath, $filename);
write_css_cache ($cachepath, $output);
}
header("Date: ".date("D, j M Y G:i:s ", $templateModified).'GMT');
header("Content-Type: text/css");
header("Expires: ".gmdate("D, j M Y H:i:s", time()+DAY)." GMT");
header("Cache-Control: cache");// HTTP/1.1
header("Pragma: cache");// HTTP/1.0
print $output;
?>

View File

@@ -1,195 +0,0 @@
/* CSS Document */
@import url("cake.forms.css");
* {
padding:0;
margin:0;
}
body {
font: 76% Verdana, Arial, Sans-serif;
color: #333;
}
img {
border:0;
}
#wrapper {
text-align:left;
}
#header {
height: 101px;
background: #0D5087 url(../img/cake.header_bg.png) repeat-x left top;
border-bottom: 1px solid #000;
}
#content {
min-height:400px;
background-color: #fff;
padding:2em 4em;
}
#footer {
text-align:center;
padding:1em 0;
font-size:smaller;
border-top:1px solid #333;
background-color: #063260;
color:#fff;
line-height:1.5;
}
#footer a {
color:#fff;
}
h1, h2, h3, h4 {
padding-bottom:0.5em;
}
h1 {
font-family:"Trebuchet MS",Verdana,Arial,Sans-serif;
}
h1, a {
color:#DB8101;
}
h1 em, a em {
color:#008BCC;
font-style: normal;
}
ul.colored a em
h2 {
font-style: italic;
font-weight: bold;
color:#666;
}
a:hover, a:hover em {
color:#A22424;
text-decoration:none;
}
#content p, #content ul, #content ol {
line-height:1.5;
padding-bottom:1em;
}
ul, ol {
margin-left:3em;
}
/* tables */
table {
width: 100%;
background-color: #fff;
border: 1px solid #333;
clear:both;
margin: 0 0 2em 0;
white-space: normal;
}
th {
background-color: #ccc;
border-top: 1px solid #fff;
border-right: 1px solid #666;
border-bottom: 1px solid #666;
text-align: center;
padding:3px;
}
table tr td {
border-right: 1px solid #ccc;
padding:4px 4px;
vertical-align:top;
text-align: center;
}
table tr.altRow td {
background: #f4f4f4;
}
/* scaffold show */
div.related {
clear:both;
display:block;
}
dl {
line-height:2em;
margin:1em;
}
dt {
font-weight: bold;
vertical-align:top;
}
dd {
margin-left:10em;
margin-top:-2em;
vertical-align:top;
}
/* scaffold buttons */
.notice {
color: #DB8101;
background-color: #ddd;
display: block;
padding: 1em;
}
.tip {
color: #DB8101;
background-color: #ddd;
display: block;
padding: 1em;
}
ul.actions {
list-style: none;
text-align:left;
margin:2em 0;
padding: 0;
}
ul.actions li {
margin-left:1em;
list-style: none;
display: inline;
}
ul.actions li a, ul.actions li input {
padding: 2px 12px;
color: #DB8101;
background-color:#ccc;
text-decoration: none;
border: 1px solid #666;
line-height: 24px;
font-weight: bold;
text-align:center;
text-decoration: none;
}
ul.actions li a:hover {
color: #DB8101;
background-color:#fff;
text-decoration: none;
}
td.listactions {
width: 14em;
text-align: center;
white-space: nowrap;
}
td.listactions a {
padding: 0px 8px;
text-align:center;
font-weight: bold;
color: #DB8101;
background-color:#ccc;
text-decoration: none;
border: 1px solid #666;
white-space: nowrap;
}
td.listactions a:hover {
color: #fff;
background-color:#DB8101;
}
/* index links */
ul.colored a {
}
ul.colored a em {
}
a {
font-weight: bold;
}

View File

@@ -1,279 +0,0 @@
/* form.css */
form {
margin: 0 4px;
font-size: 120%;
border-width: 0px 0px 0px 0px;
border-style: solid;
border-color: #DB8101;
}
form fieldset {
font-size: 100%;
border-color: #000000;
border-width: 1px 0px 0px 0px;
border-style: solid none none none;
padding: 10px;
}
form fieldset legend {
font-size: 150%;
font-weight: normal;
color: #000;
padding: 0px 5px;
}
label {
font-size: 150%;
}
label u {
font-style: normal;
text-decoration: underline;
}
input, select, textarea {
font-family: Tahoma, Arial, sans-serif;
font-size: 100%;
color: #000;
}
textarea {
overflow: auto;
}
form div {
clear: left;
display: block;
margin: 5px 0px 0px 0px;
padding: 1px 3px;
}
form fieldset div.notes {
float: right;
width: 158px;
height: auto;
margin: 0px 0px 10px 10px;
padding: 5px;
border: 1px solid #666;
background-color: #ffffe1;
color: #666;
font-size: 88%;
}
form fieldset div.notes h4 {
background-image: url(/images/icon_info.gif);
background-repeat: no-repeat;
background-position: top left;
padding: 3px 0px 3px 27px;
border-width: 0px 0px 1px 0px;
border-style: solid;
border-color: #666;
color: #666;
font-size: 110%;
}
form fieldset div.notes p {
margin: 0em 0em 1.2em 0em;
color: #666;
}
form fieldset div.notes p.last {
margin: 0em;
}
form div fieldset {
clear: none;
border-width: 0px 1px 0px 1px;
border-style: solid;
border-color: #666;
margin: 0px 0px 0px 142px;
padding: 0px 5px 5px 5px;
}
form div fieldset legend {
font-size: 100%;
padding: 0px 3px 0px 9px;
}
form div.required fieldset legend {
font-weight: bold;
}
form div label {
display: block;
float: left;
width: 200px;
background-color: #f4f4f4;
font-size: 16px;
padding: 3px 5px;
margin: 0px 0px 5px 0px;
text-align: right;
}
form div.optional label, label.optional {
font-weight: normal;
}
form div.required label, label.required {
font-weight: bold;
}
form div label.labelCheckbox, form div label.labelRadio {
float: none;
display: block;
margin: 0px 0px 5px 142px;
text-align: left;
}
form div fieldset label.labelCheckbox, form div fieldset label.labelRadio {
margin: 0px 0px 5px 0px;
}
p.error {
color: #DB8101;
background-color: #DBA941;
font-size: 14px;
padding: 1em;
}
form div input, form div select, form div textarea {
padding: 1px 3px;
margin: 0px 0px 0px 0px;
}
form div input.inputFile {
width: 211px;
}
form div select.selectOne, form div select.selectMultiple {
width: 211px;
padding: 1px 3px;
}
form div input.inputCheckbox, form div input.inputRadio, input.inputCheckbox, input.inputRadio {
display: inline;
height: 14px;
width: 14px;
background-color: transparent;
border-width: 0px;
}
form div.submit {
padding: 0px 0px 0px 140px;
clear:both;
display:block;
}
div.submit input {
padding: 2px 12px;
color: #DB8101;
background-color:#ccc;
text-decoration: none;
border: 1px solid #666;
font-size: 14px;
font-weight: bold;
text-align:center;
text-decoration: none;
width: auto;
}
div.submit input:hover {
padding: 2px 12px;
color: #fff;
background-color:#DB8101;
text-decoration: none;
border: 1px solid #666;
font-size: 14px;
font-weight: bold;
text-align:center;
text-decoration: none;
width: auto;
}
form div.submit div input.inputSubmit, form div.submit div input.inputButton {
float: right;
margin: 0px 0px 0px 5px;
}
form div small {
display: block;
margin: 0px 0px 5px 142px;
padding: 1px 3px;
font-size: 88%;
}
/* form.import.css */
form fieldset legend {
line-height: 150%;
}
form input, form select, form textarea {
background-color: #fff;
}
div.optional label:before {
content: '';
}
div.required label:before {
content: '';
}
form div label.labelCheckbox, form div label.labelRadio, label.labelCheckbox, label.labelRadio {
display: block;
width: 190px;
padding: 4px 0px 0px 18px;
text-indent: -18px;
line-height: 120%;
}
form div label.labelCheckbox input.inputCheckbox, form div label.labelRadio input.inputRadio, label.labelCheckbox input.inputCheckbox, label.labelRadio input.inputRadio {
margin: 0;
}
form div fieldset input.inputText, form div fieldset input.inputPassword, form div fieldset input.inputFile, form div fieldset textarea.inputTextarea {
width: 160px;
margin: 0px 0px 0px 18px;
}
form div label.compact {
display: inline;
width: auto;
padding: 4px 10px 0px 0px;
text-indent: 0px;
margin: 0;
}
form div.wide label {
float: none;
display: block;
}
form div label.wide {
width: 348px;
}
form div.wide input.inputText, form div.wide input.inputPassword, form div.wide input.inputFile, form div.wide select, form div.wide textarea {
width: 344px;
margin: 0;
}
form div.notes p, form div small {
line-height: 125%;
}
form div.wide small {
margin: 0px 0px 5px 0px;
}
div.date select {
width:auto;
}
select.autoWidth {
width:auto;
}
option {
padding-left:1em;
}

View File

@@ -1,9 +0,0 @@
form div,
form div label.labelCheckbox, form div label.labelRadio,
form div small,
form div label.labelCheckbox, form div label.labelRadio, label.labelCheckbox, label.labelRadio {
height: expression('1%');
}
form div fieldset input.inputText, form div fieldset input.inputPassword, form div fieldset input.inputFile, form div fieldset textarea.inputTextarea {
margin: expression('0px 0px 0px -124px');
}

View File

@@ -1,133 +0,0 @@
/* Screen Stylesheet */
/* This is temporary while we use the scaffolding */
@import url("cake.default.css");
table { clear:none; }
/* CORE STYLES */
body{
background-color:#788;
}
div#t_title{
background-color:#ddd;
height:50px;
padding-left:8px;
}
div#t_title h1{
font-size:1.7em;
padding-top:10px;
color:#677;
}
div#t_content_container{
}
div#t_content{
padding: 20px 10px 100px 10px;
margin-left:151px;
background-image:url('../img/bg.jpg');
background-position:bottom right;
background-repeat:no-repeat;
min-height:200px;
}
div#t_wrapper{
margin:0px;
padding:0px;
background-color:#fff;
}
div#t_border{
border-left:1px solid #111;
border-right:1px solid #111;
border-bottom:1px solid #111;
margin:0px 30px 0px 30px;
}
div#t_nav {
padding:20px 0px 50px 0px;
float:left;
width:151px;
}
div#t_nav ul {
list-style-type:none;
padding:2px 0px 0px 0px;
margin:0px;
}
div#t_nav ul li{
padding:2px 0px 2px 0px;
}
div#t_nav ul li a{
text-decoration:none;
font-size:.8em;
padding:6px 0px 6px 8px;
margin:0px 0px 0px 0px;
color:#566;
border:none;
}
div#t_nav ul li a:hover{
color:#f80;
}
div#t_nav h3 {
padding:5px 0px 0px 5px;
font-size:.9em;
}
div#t_footer {
clear:both;
border-top:1px solid #111;
}
div#t_content h1 {
margin-bottom:100px;
font-size:1.6em;
}
a.skipnav {
position:absolute;
visibility:hidden;
}
div#queryform {
margin: 5px 20px 5px 20px;
padding-bottom:20px;
width:700px;
}
div#queryform label {
font-size:.8em;
font-weight:bold;
}
div#queryform input[type="text"]{
width:7em;
}
div#exportbox {
}
/* Classes for graph/table data. (Generally just padding) */
.results {
padding: 5px 5px 5px 5px;
margin: 5px 5px 5px 5px;
}
div#notice {
background-color:#ecc;
border:1px dashed #daa;
text-align:center;
padding:6px 6px 6px 6px;
margin:6px 20px 6px 20px;
}
table.comments tr {
}
table.comments tr td{
text-align:left;
border-bottom: 1px solid #222;
}
div.bar_chart_label {
position: absolute;
text-align: left;
font-size: small;
color: #fff;
overflow: hidden;
z-index: 10;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -1,244 +0,0 @@
2006-04-29 v1.3.1 (bug fix release)
- Fix sendXMLHttpRequest sendContent regression
- Internet Explorer fix in MochiKit.Logging (printfire exception)
- Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async
2006-04-26 v1.3 "warp zone"
- IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)
- IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)
- New MochiKit.Base.method as a convenience form of bind that takes the
object before the method
- New MochiKit.Base.flattenArguments for flattening a list of arguments to
a single Array
- Refactored MochiRegExp example to use MochiKit.Signal
- New key_events example demonstrating use of MochiKit.Signal's key handling
capabilities.
- MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
null is used and the string will be considered the first node. This
allows for the more natural P("foo") rather than P(null, "foo").
- MochiKit Interpreter example refactored to use MochiKit.Signal and now
provides multi-line input and a help() function to get MochiKit function
signature from the documentation.
- Native Console Logging for the default MochiKit.Logging logger
- New MochiKit.Async.DeferredList, gatherResults, maybeDeferred
- New MochiKit.Signal example: draggable
- Added sanity checking to Deferred to ensure that errors happen when chaining
is used incorrectly
- Opera sendXMLHttpRequest fix (sends empty string instead of null by default)
- Fix a bug in MochiKit.Color that incorrectly generated hex colors for
component values smaller than 16/255.
- Fix a bug in MochiKit.Logging that prevented logs from being capped at a
maximum size
- MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
Error, so that the errback chain is used instead of the callback chain.
- MochiKit.DOM.appendChildNodes and associated functions now append iterables
in the correct order.
- New MochiKit-based SimpleTest test runner as a replacement for Test.Simple
- MochiKit.Base.isNull no longer matches undefined
- example doctypes changed to HTML4
- isDateLike no longer throws error on null
- New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt
- updated elementDimensions to calculate width from offsetWidth instead
of clientWidth
- formContents now works with FORM tags that have a name attribute
- Documentation now uses MochiKit to generate a function index
2006-01-26 v1.2 "the ocho"
- Fixed MochiKit.Color.Color.lighterColorWithLevel
- Added new MochiKit.Base.findIdentical function to find the index of an
element in an Array-like object. Uses === for identity comparison.
- Added new MochiKit.Base.find function to find the index of an element in
an Array-like object. Uses compare for rich comparison.
- MochiKit.Base.bind will accept a string for func, which will be immediately
looked up as self[func].
- MochiKit.DOM.formContents no longer skips empty form elements for Zope
compatibility
- MochiKit.Iter.forEach will now catch StopIteration to break
- New MochiKit.DOM.elementDimensions(element) for determining the width and
height of an element in the document
- MochiKit.DOM's initialization is now compatible with
HTMLUnit + JWebUnit + Rhino
- MochiKit.LoggingPane will now re-use a ``_MochiKit_LoggingPane`` DIV element
currently in the document instead of always creating one.
- MochiKit.Base now has operator.mul
- MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
a custom value attribute
- Added new MochiKit.Color constructors fromComputedStyle and fromText
- MochiKit.DOM.setNodeAttribute should work now
- MochiKit.DOM now has a workaround for an IE bug when setting the style
property to a string
- MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
name and for properties
- MochiKit.DOM.scrapeText now walks the DOM tree in-order
- MochiKit.LoggingPane now sanitizes the window name to work around IE bug
- MochiKit.DOM now translates usemap to useMap to work around IE bug
- MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks
- Added new MochiKit.DOM documentation on element visibility
- New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
for determining the position of an element in the document
- Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG
2005-11-14 v1.1
- Fixed a bug in numberFormatter with large numbers
- Massively overhauled documentation
- Fast-path for primitives in MochiKit.Base.compare
- New groupby and groupby_as_array in MochiKit.Iter
- Added iterator factory adapter for objects that implement iterateNext()
- Fixed isoTimestamp to handle timestamps with time zone correctly
- Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
LEGEND, FIELDSET
- New MochiKit.DOM formContents and enhancement to queryString to support it
- Updated view_source example to use dp.SyntaxHighlighter 1.3.0
- MochiKit.LoggingPane now uses named windows based on the URL so that
a given URL will get the same LoggingPane window after a reload
(at the same position, etc.)
- MochiKit.DOM now has currentWindow() and currentDocument() context
variables that are set with withWindow() and withDocument(). These
context variables affect all MochiKit.DOM functionality (getElement,
createDOM, etc.)
- MochiKit.Base.items will now catch and ignore exceptions for properties
that are enumerable but not accessible (e.g. permission denied)
- MochiKit.Async.Deferred's addCallback/addErrback/addBoth
now accept additional arguments that are used to create a partially
applied function. This differs from Twisted in that the callback/errback
result becomes the *last* argument, not the first when this feature
is used.
- MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
arguments which are used to create a GET query string
- Did some refactoring to reduce the footprint of MochiKit by a few
kilobytes
- escapeHTML to longer escapes ' (apos) and now uses
String.replace instead of iterating over every char.
- Added DeferredLock to Async
- Renamed getElementsComputedStyle to computedStyle and moved
it from MochiKit.Visual to MochiKit.DOM
- Moved all color support out of MochiKit.Visual and into MochiKit.Color
- Fixed range() to accept a negative step
- New alias to MochiKit.swapDOM called removeElement
- New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
an attribute on a node without raising, roughly equivalent to:
updateNodeAttributes(node, {attr: value})
- New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
a node's attribute or returns null without raising
- Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
directly (addLoadEvent did not leak, since it clears the handler)
2005-10-24 v1.0
- New interpreter example that shows usage of MochiKit.DOM to make
an interactive JavaScript interpreter
- New MochiKit.LoggingPane for use with the MochiKit.Logging
debuggingBookmarklet, with logging_pane example to show its usage
- New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
in order to provide a live regular expression matching tool
- Added advanced number formatting capabilities to MochiKit.Format:
numberFormatter(pattern, placeholder="", locale="default") and
formatLocale(locale="default")
- Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.
- Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE
- Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
to MochiKit.Format
- MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
isoTimestamp(isoString) will convert them to Date objects, and
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC
- Fixed missing errback for sendXMLHttpRequest when the server does not
respond
- Fixed infinite recusion bug when using roundClass("DIV", ...)
- Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
from being cancelled properly
- Workaround in MochiKit.Base bind (and partial) for functions that don't
have an apply method, such as alert
- Reliably return null from the string parsing/manipulation functions if
the input can't be coerced to a string (s + "") or the input makes no sense;
e.g. isoTimestamp(null) and isoTimestamp("") return null
2005-10-08 v0.90
- Fixed ISO compliance with toISODate
- Added missing operator.sub
- Placated Mozilla's strict warnings a bit
- Added JSON serialization and unserialization support to MochiKit.Base:
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
API.
- Fixed a bug in the script loader that failed in some scenarios when a script
tag did not have a "src" attribute (thanks Ian!)
- Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
P, FORM
- Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
and parseQueryString, when available.
2005-08-12 v0.80
- Source highlighting in all examples, moved to a view-source example
- Added some experimental syntax highlighting for the Rounded Corners example,
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib
- Use an indirect binding for the logger conveniences, so that the global
logger could be replaced by setting MochiKit.Logger.logger to something else
(though an observer is probably a better choice).
- Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
which will be looked up with getElement
- Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
node.parentNode)
- Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success
- Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues
- Possible workaround for Safari issue with swapDOM, where it would get
confused because two elements were in the DOM at the same time with the
same id
- Added missing THEAD convenience function to MochiKit.DOM
- Added lstrip, rstrip, strip to MochiKit.Format
- Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
MochiKit.DOM
- MochiKit.Iter.iextend now has a fast-path for array-like objects
- Added HSV color space support to MochiKit.Visual
- Fixed a bug in the sortable_tables example, it now converts types
correctly
- Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
scope
2005-08-04 v0.70
- New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
a little TAL-ish DOM templating attribute language.
- sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
ignore requests with status == 0, which seems to happen for cached or local
requests
- Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.
- Changed scrapeText API to return a string by default. This is API-breaking!
It was dumb to have the default return value be the form you almost never
want. Sorry.
- Added special form to swapDOM(dest, src). If src is null, dest is removed
(where previously you'd likely get a DOM exception).
- Added three new functions to MochiKit.Base for dealing with URL query
strings: urlEncode, queryString, parseQueryString
- MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
new Function(v).
- Another workaround for Internet "worst browser ever" Explorer's setAttribute
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).
- Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM
- Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
now!
2005-07-29 v0.60
- Beefed up the MochiKit.DOM test suite
- Fixed return value for MochiKit.DOM.swapElementClass, could return
false unexpectedly before
- Added an optional "parent" argument to
MochiKit.DOM.getElementsByTagAndClassName
- Added a "packed" version in packed/MochiKit/MochiKit.js
- Changed build script to rewrite the URLs in tests to account for the
JSAN-required reorganization
- MochiKit.Compat to potentially work around IE 5.5 issues
(5.0 still not supported). Test.Simple doesn't seem to work there,
though.
- Several minor documentation corrections
2005-07-27 v0.50
- Initial Release

View File

@@ -1,69 +0,0 @@
MochiKit is dual-licensed software. It is available under the terms of the
MIT License, or the Academic Free License version 2.1. The full text of
each license is included below.
MIT License
===========
Copyright (c) 2005 Bob Ippolito. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Academic Free License v. 2.1
============================
Copyright (c) 2005 Bob Ippolito. All rights reserved.
This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
Licensed under the Academic Free License version 2.1
1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following:
a) to reproduce the Original Work in copies;
b) to prepare derivative works ("Derivative Works") based upon the Original Work;
c) to distribute copies of the Original Work and Derivative Works to the public;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license.
5) This section intentionally omitted.
6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.
9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions.
10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License.
12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.

View File

@@ -1,115 +0,0 @@
Changes
META.json
MANIFEST This list of files
LICENSE.txt
doc/html/MochiKit/Async.html
doc/html/MochiKit/Base.html
doc/html/MochiKit/Color.html
doc/html/MochiKit/DateTime.html
doc/html/MochiKit/DOM.html
doc/html/MochiKit/Format.html
doc/html/MochiKit/index.html
doc/html/MochiKit/Iter.html
doc/html/MochiKit/Logging.html
doc/html/MochiKit/LoggingPane.html
doc/html/MochiKit/Signal.html
doc/html/MochiKit/VersionHistory.html
doc/html/MochiKit/Visual.html
doc/js/toc.js
doc/rst/MochiKit/Async.rst
doc/rst/MochiKit/Base.rst
doc/rst/MochiKit/Color.rst
doc/rst/MochiKit/DateTime.rst
doc/rst/MochiKit/DOM.rst
doc/rst/MochiKit/Format.rst
doc/rst/MochiKit/index.rst
doc/rst/MochiKit/Iter.rst
doc/rst/MochiKit/Logging.rst
doc/rst/MochiKit/LoggingPane.rst
doc/rst/MochiKit/Signal.rst
doc/rst/MochiKit/VersionHistory.rst
doc/rst/MochiKit/Visual.rst
examples/ajax_tables/ajax_tables.css
examples/ajax_tables/ajax_tables.js
examples/ajax_tables/domains.json
examples/ajax_tables/domains.xml
examples/ajax_tables/index.html
examples/color_wheel/color_wheel.css
examples/color_wheel/color_wheel.js
examples/color_wheel/index.html
examples/draggable/draggable.css
examples/draggable/draggable.js
examples/draggable/index.html
examples/interpreter/index.html
examples/interpreter/interpreter.css
examples/interpreter/interpreter.js
examples/key_events/index.html
examples/key_events/key_events.css
examples/key_events/key_events.js
examples/logging_pane/index.html
examples/logging_pane/logging_pane.css
examples/logging_pane/logging_pane.js
examples/mochiregexp/index.html
examples/mochiregexp/mochiregexp.css
examples/mochiregexp/mochiregexp.js
examples/rounded_corners/index.html
examples/rounded_corners/rounded_corners.css
examples/rounded_corners/rounded_corners.js
examples/sortable_tables/index.html
examples/sortable_tables/sortable_tables.css
examples/sortable_tables/sortable_tables.js
examples/view-source/view-source.css
examples/view-source/view-source.html
examples/view-source/view-source.js
examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js
examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js
examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js
examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js
examples/view-source/lib/SyntaxHighlighter/shBrushPython.js
examples/view-source/lib/SyntaxHighlighter/shBrushSql.js
examples/view-source/lib/SyntaxHighlighter/shBrushVb.js
examples/view-source/lib/SyntaxHighlighter/shBrushXml.js
examples/view-source/lib/SyntaxHighlighter/shCore.js
examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css
examples/view-source/lib/SyntaxHighlighter/Tests.html
include/css/documentation.css
include/css/general.css
MochiKit/__package__.js
MochiKit/Async.js
MochiKit/Base.js
MochiKit/Color.js
MochiKit/DateTime.js
MochiKit/DOM.js
MochiKit/Format.js
MochiKit/Iter.js
MochiKit/Logging.js
MochiKit/LoggingPane.js
MochiKit/MochiKit.js
MochiKit/MockDOM.js
MochiKit/Signal.js
MochiKit/Test.js
MochiKit/Visual.js
packed/MochiKit/__package__.js
packed/MochiKit/MochiKit.js
tests/index.html
tests/test_Base.js
tests/test_Color.js
tests/test_DateTime.js
tests/test_Format.js
tests/test_Iter.js
tests/test_Logging.js
tests/test_MochiKit-Async.html
tests/test_MochiKit-Base.html
tests/test_MochiKit-Color.html
tests/test_MochiKit-DateTime.html
tests/test_MochiKit-DOM.html
tests/test_MochiKit-Format.html
tests/test_MochiKit-Iter.html
tests/test_MochiKit-JSAN.html
tests/test_MochiKit-Logging.html
tests/test_MochiKit-MochiKit.html
tests/test_MochiKit-Signal.html
tests/test_Signal.js
tests/SimpleTest/SimpleTest.js
tests/SimpleTest/test.css
tests/SimpleTest/TestRunner.js

View File

@@ -1,17 +0,0 @@
{
"recommends": {
"JSAN": "0.10"
},
"name": "MochiKit",
"license": "mit",
"author": [
"Bob Ippolito <bob@redivi.com>"
],
"abstract": "Python-inspired JavaScript kit",
"generated_by": "MochiKit's build script",
"build_requires": {
"Test.Simple": "0.11"
},
"version": "1.3.1",
"provides": {}
}

View File

@@ -1,606 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Async - manage asynchronous tasks</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Async - manage asynchronous tasks</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
var url = &quot;/src/b/bo/bob/MochiKit.Async/META.json&quot;;
/*
META.json looks something like this:
{&quot;name&quot;: &quot;MochiKit&quot;, &quot;version&quot;: &quot;0.5&quot;}
*/
var d = loadJSONDoc(url);
var gotMetadata = function (meta) {
if (MochiKit.Async.VERSION == meta.version) {
alert(&quot;You have the newest MochiKit.Async!&quot;);
} else {
alert(&quot;MochiKit.Async &quot;
+ meta.version
+ &quot; is available, upgrade!&quot;);
}
};
var metadataFetchFailed = function (err) {
alert(&quot;The metadata for MochiKit.Async could not be fetched :(&quot;);
};
d.addCallbacks(gotMetadata, metadataFetchFailed);
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>MochiKit.Async provides facilities to manage asynchronous
(as in AJAX <a class="footnote-reference" href="#id7" id="id1" name="id1">[1]</a>) tasks. The model for asynchronous computation
used in this module is heavily inspired by Twisted <a class="footnote-reference" href="#id8" id="id2" name="id2">[2]</a>.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<div class="section">
<h2><a id="deferred" name="deferred">Deferred</a></h2>
<p>The Deferred constructor encapsulates a single value that
is not available yet. The most important example of this
in the context of a web browser would be an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
to a server. The importance of the Deferred is that it
allows a consistent API to be exposed for all asynchronous
computations that occur exactly once.</p>
<p>The producer of the Deferred is responsible for doing all
of the complicated work behind the scenes. This often
means waiting for a timer to fire, or waiting for an event
(e.g. <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> of <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>).
It could also be coordinating several events (e.g.
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> with a timeout, or several Deferreds
(e.g. fetching a set of XML documents that should be
processed at the same time).</p>
<p>Since these sorts of tasks do not respond immediately, the
producer of the Deferred does the following steps before
returning to the consumer:</p>
<ol class="arabic simple">
<li>Create a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred();</a> object and keep a reference
to it, because it will be needed later when the value is
ready.</li>
<li>Setup the conditions to create the value requested (e.g.
create a new <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>, set its
<tt class="docutils literal"><span class="pre">onreadystatechange</span></tt>).</li>
<li>Return the <a class="mochiref reference" href="#fn-deferred">Deferred</a> object.</li>
</ol>
<p>Since the value is not yet ready, the consumer attaches
a function to the Deferred that will be called when the
value is ready. This is not unlike <tt class="docutils literal"><span class="pre">setTimeout</span></tt>, or
other similar facilities you may already be familiar with.
The consumer can also attach an &quot;errback&quot; to the
<a class="mochiref reference" href="#fn-deferred">Deferred</a>, which is a callback for error handling.</p>
<p>When the value is ready, the producer simply calls
<tt class="docutils literal"><span class="pre">myDeferred.callback(theValue)</span></tt>. If an error occurred,
it should call <tt class="docutils literal"><span class="pre">myDeferred.errback(theValue)</span></tt> instead.
As soon as this happens, the callback that the consumer
attached to the <a class="mochiref reference" href="#fn-deferred">Deferred</a> is called with <tt class="docutils literal"><span class="pre">theValue</span></tt>
as the only argument.</p>
<p>There are quite a few additional &quot;advanced&quot; features
baked into <a class="mochiref reference" href="#fn-deferred">Deferred</a>, such as cancellation and
callback chains, so take a look at the API
reference if you would like to know more!</p>
</div>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="errors" name="errors">Errors</a></h2>
<p>
<a name="fn-alreadycallederror"></a>
<a class="mochidef reference" href="#fn-alreadycallederror">AlreadyCalledError</a>:</p>
<blockquote>
Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> if <tt class="docutils literal"><span class="pre">.callback</span></tt> or
<tt class="docutils literal"><span class="pre">.errback</span></tt> are called more than once.</blockquote>
<p>
<a name="fn-browsercomplianceerror"></a>
<a class="mochidef reference" href="#fn-browsercomplianceerror">BrowserComplianceError</a>:</p>
<blockquote>
Thrown when the JavaScript runtime is not capable of performing
the given function. Currently, this happens if the browser
does not support <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</blockquote>
<p>
<a name="fn-cancellederror"></a>
<a class="mochidef reference" href="#fn-cancellederror">CancelledError</a>:</p>
<blockquote>
Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> when it is cancelled,
unless a canceller is present and throws something else.</blockquote>
<p>
<a name="fn-genericerror"></a>
<a class="mochidef reference" href="#fn-genericerror">GenericError</a>:</p>
<blockquote>
Results passed to <tt class="docutils literal"><span class="pre">.fail</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> of a <a class="mochiref reference" href="#fn-deferred">Deferred</a>
are wrapped by this <tt class="docutils literal"><span class="pre">Error</span></tt> if <tt class="docutils literal"><span class="pre">!(result</span> <span class="pre">instanceof</span> <span class="pre">Error)</span></tt>.</blockquote>
<p>
<a name="fn-xmlhttprequesterror"></a>
<a class="mochidef reference" href="#fn-xmlhttprequesterror">XMLHttpRequestError</a>:</p>
<blockquote>
Thrown when an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> does not complete successfully
for any reason. The <tt class="docutils literal"><span class="pre">req</span></tt> property of the error is the failed
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object, and for convenience the <tt class="docutils literal"><span class="pre">number</span></tt>
property corresponds to <tt class="docutils literal"><span class="pre">req.status</span></tt>.</blockquote>
</div>
<div class="section">
<h2><a id="constructors" name="constructors">Constructors</a></h2>
<p>
<a name="fn-deferred"></a>
<a class="mochidef reference" href="#fn-deferred">Deferred()</a>:</p>
<blockquote>
Encapsulates a sequence of callbacks in response to a value that
may not yet be available. This is modeled after the Deferred class
from Twisted <a class="footnote-reference" href="#id9" id="id3" name="id3">[3]</a>.</blockquote>
<blockquote>
<p>Why do we want this? JavaScript has no threads, and even if it did,
threads are hard. Deferreds are a way of abstracting non-blocking
events, such as the final response to an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</p>
<p>The sequence of callbacks is internally represented as a list
of 2-tuples containing the callback/errback pair. For example,
the following call sequence:</p>
<pre class="literal-block">
var d = new Deferred();
d.addCallback(myCallback);
d.addErrback(myErrback);
d.addBoth(myBoth);
d.addCallbacks(myCallback, myErrback);
</pre>
<p>is translated into a <a class="mochiref reference" href="#fn-deferred">Deferred</a> with the following internal
representation:</p>
<pre class="literal-block">
[
[myCallback, null],
[null, myErrback],
[myBoth, myBoth],
[myCallback, myErrback]
]
</pre>
<p>The <a class="mochiref reference" href="#fn-deferred">Deferred</a> also keeps track of its current status (fired).
Its status may be one of the following three values:</p>
<blockquote>
<table border="1" class="docutils">
<colgroup>
<col width="14%" />
<col width="86%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Value</th>
<th class="head">Condition</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>-1</td>
<td>no value yet (initial condition)</td>
</tr>
<tr><td>0</td>
<td>success</td>
</tr>
<tr><td>1</td>
<td>error</td>
</tr>
</tbody>
</table>
</blockquote>
<p>A <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the error state if one of the following
conditions are met:</p>
<ol class="arabic simple">
<li>The result given to callback or errback is &quot;<tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>&quot;</li>
<li>The callback or errback threw while executing. If the thrown object
is not <tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>, it will be wrapped with
<a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</li>
</ol>
<p>Otherwise, the <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the success state. The state
of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> determines the next element in the callback
sequence to run.</p>
<p>When a callback or errback occurs with the example deferred chain, something
equivalent to the following will happen (imagine that exceptions are caught
and returned as-is):</p>
<pre class="literal-block">
// d.callback(result) or d.errback(result)
if (!(result instanceof Error)) {
result = myCallback(result);
}
if (result instanceof Error) {
result = myErrback(result);
}
result = myBoth(result);
if (result instanceof Error) {
result = myErrback(result);
} else {
result = myCallback(result);
}
</pre>
<p>The result is then stored away in case another step is added to the
callback sequence. Since the <a class="mochiref reference" href="#fn-deferred">Deferred</a> already has a value
available, any new callbacks added will be called immediately.</p>
<p>There are two other &quot;advanced&quot; details about this implementation that are
useful:</p>
<p>Callbacks are allowed to return <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances,
so you can build complicated sequences of events with (relative) ease.</p>
<p>The creator of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> may specify a canceller. The
canceller is a function that will be called if
<a class="mochiref reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel</a> is called before the
<a class="mochiref reference" href="#fn-deferred">Deferred</a> fires. You can use this to allow an
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to be cleanly cancelled, for example. Note that
cancel will fire the <a class="mochiref reference" href="#fn-deferred">Deferred</a> with a
<a class="mochiref reference" href="#fn-cancellederror">CancelledError</a> (unless your canceller throws or returns
a different <tt class="docutils literal"><span class="pre">Error</span></tt>), so errbacks should be prepared to handle that
<tt class="docutils literal"><span class="pre">Error</span></tt> gracefully for cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.addboth"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.addboth">Deferred.prototype.addBoth(func)</a>:</p>
<blockquote>
<p>Add the same function as both a callback and an errback as the
next element on the callback sequence. This is useful for code
that you want to guarantee to run, e.g. a finalizer.</p>
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the callback or
errback will be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
(its value or error will be passed to the next callback). Note that
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
callbacks.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.addcallback"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.addcallback">Deferred.prototype.addCallback(func[, ...])</a>:</p>
<blockquote>
<p>Add a single callback to the end of the callback sequence.</p>
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the callback will
be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
(its value or error will be passed to the next callback). Note that
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
callbacks.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.addcallbacks"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.addcallbacks">Deferred.prototype.addCallbacks(callback, errback)</a>:</p>
<blockquote>
<p>Add separate callback and errback to the end of the callback
sequence. Either callback or errback may be <tt class="docutils literal"><span class="pre">null</span></tt>,
but not both.</p>
<p>If <tt class="docutils literal"><span class="pre">callback</span></tt> or <tt class="docutils literal"><span class="pre">errback</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
then it will be chained (its value or error will be passed to the
next callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained,
it can no longer accept new callbacks.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.adderrback"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.adderrback">Deferred.prototype.addErrback(func)</a>:</p>
<blockquote>
<p>Add a single errback to the end of the callback sequence.</p>
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the errback will
be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
(its value or error will be passed to the next callback). Note that
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
callbacks.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.callback"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback([result])</a>:</p>
<blockquote>
<p>Begin the callback sequence with a non-<tt class="docutils literal"><span class="pre">Error</span></tt> result. Result
may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should
be called exactly once on a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.cancel"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel()</a>:</p>
<blockquote>
<p>Cancels a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has not yet received a value,
or is waiting on another <a class="mochiref reference" href="#fn-deferred">Deferred</a> as its value.</p>
<p>If a canceller is defined, the canceller is called.
If the canceller did not return an <tt class="docutils literal"><span class="pre">Error</span></tt>, or there
was no canceller, then the errback chain is started
with <a class="mochiref reference" href="#fn-cancellederror">CancelledError</a>.</p>
</blockquote>
<p>
<a name="fn-deferred.prototype.errback"></a>
<a class="mochidef reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback([result])</a>:</p>
<blockquote>
<p>Begin the callback sequence with an error result.
Result may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
but if <tt class="docutils literal"><span class="pre">!(result</span> <span class="pre">instanceof</span> <span class="pre">Error)</span></tt>, it will be wrapped
with <a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</p>
<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should
be called exactly once on a
<a name="fn-deferred"></a>
<a class="mochidef reference" href="#fn-deferred">Deferred</a>.</p>
</blockquote>
<p>
<a name="fn-deferredlock"></a>
<a class="mochidef reference" href="#fn-deferredlock">DeferredLock()</a>:</p>
<blockquote>
<p>A lock for asynchronous systems.</p>
<p>The <tt class="docutils literal"><span class="pre">locked</span></tt> property of a <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> will be <tt class="docutils literal"><span class="pre">true</span></tt> if
it locked, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. Do not change this property.</p>
</blockquote>
<p>
<a name="fn-deferredlock.prototype.acquire"></a>
<a class="mochidef reference" href="#fn-deferredlock.prototype.acquire">DeferredLock.prototype.acquire()</a>:</p>
<blockquote>
Attempt to acquire the lock. Returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that fires on
lock acquisition with the <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> as the value.
If the lock is locked, then the <a class="mochiref reference" href="#fn-deferred">Deferred</a> goes into a waiting
list.</blockquote>
<p>
<a name="fn-deferredlock.prototype.release"></a>
<a class="mochidef reference" href="#fn-deferredlock.prototype.release">DeferredLock.prototype.release()</a>:</p>
<blockquote>
Release the lock. If there is a waiting list, then the first
<a class="mochiref reference" href="#fn-deferred">Deferred</a> in that waiting list will be called back.</blockquote>
<p>
<a name="fn-deferredlist"></a>
<a class="mochidef reference" href="#fn-deferredlist">DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])</a>:</p>
<blockquote>
<p>Combine a list of <a class="mochiref reference" href="#fn-deferred">Deferred</a> into one. Track the callbacks and
return a list of (success, result) tuples, 'success' being a boolean
indicating whether result is a normal result or an error.</p>
<p>Once created, you have access to all <a class="mochiref reference" href="#fn-deferred">Deferred</a> methods, like
addCallback, addErrback, addBoth. The behaviour can be changed by the
following options:</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">fireOnOneCallback</span></tt>:</dt>
<dd>Flag for launching the callback once the first Deferred of the list
has returned.</dd>
<dt><tt class="docutils literal"><span class="pre">fireOnOneErrback</span></tt>:</dt>
<dd>Flag for calling the errback at the first error of a Deferred.</dd>
<dt><tt class="docutils literal"><span class="pre">consumeErrors</span></tt>:</dt>
<dd>Flag indicating that any errors raised in the Deferreds should be
consumed by the DeferredList.</dd>
</dl>
<p>Example:</p>
<pre class="literal-block">
// We need to fetch data from 2 different urls
var d1 = loadJSONDoc(url1);
var d2 = loadJSONDoc(url2);
var l1 = new DeferredList([d1, d2], false, false, true);
l1.addCallback(function (resultList) {
MochiKit.Base.map(function (result) {
if (result[0]) {
alert(&quot;Data is here: &quot; + result[1]);
} else {
alert(&quot;Got an error: &quot; + result[1]);
}
}, resultList);
});
</pre>
</blockquote>
</div>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-calllater"></a>
<a class="mochidef reference" href="#fn-calllater">callLater(seconds, func[, args...])</a>:</p>
<blockquote>
<p>Call <tt class="docutils literal"><span class="pre">func(args...)</span></tt> after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have elapsed.
This is a convenience method for:</p>
<pre class="literal-block">
func = partial.apply(extend(null, arguments, 1));
return wait(seconds).addCallback(function (res) { return func() });
</pre>
<p>Returns a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
</blockquote>
<p>
<a name="fn-dosimplexmlhttprequest"></a>
<a class="mochidef reference" href="#fn-dosimplexmlhttprequest">doSimpleXMLHttpRequest(url[, queryArguments...])</a>:</p>
<blockquote>
<p>Perform a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> and wrap it with a
<a class="mochiref reference" href="#fn-deferred">Deferred</a> that may be cancelled.</p>
<p>Note that currently, only <tt class="docutils literal"><span class="pre">200</span></tt> (OK) and <tt class="docutils literal"><span class="pre">304</span></tt>
(NOT_MODIFIED) are considered success codes at this time, other
status codes will result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
<dd>The URL to GET</dd>
<dt><tt class="docutils literal"><span class="pre">queryArguments</span></tt>:</dt>
<dd><p class="first">If this function is called with more than one argument, a <tt class="docutils literal"><span class="pre">&quot;?&quot;</span></tt>
and the result of <a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a> with
the rest of the arguments are appended to the URL.</p>
<p>For example, this will do a GET request to the URL
<tt class="docutils literal"><span class="pre">http://example.com?bar=baz</span></tt>:</p>
<pre class="last literal-block">
doSimpleXMLHttpRequest(&quot;http://example.com&quot;, {bar: &quot;baz&quot;});
</pre>
</dd>
<dt><em>returns</em>:</dt>
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
instance on success</dd>
</dl>
</blockquote>
<p>
<a name="fn-evaljsonrequest"></a>
<a class="mochidef reference" href="#fn-evaljsonrequest">evalJSONRequest(req)</a>:</p>
<blockquote>
<p>Evaluate a JSON <a class="footnote-reference" href="#id10" id="id4" name="id4">[4]</a> <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
<dd>The request whose <tt class="docutils literal"><span class="pre">.responseText</span></tt> property is to be evaluated</dd>
<dt><em>returns</em>:</dt>
<dd>A JavaScript object</dd>
</dl>
</blockquote>
<p>
<a name="fn-fail"></a>
<a class="mochidef reference" href="#fn-fail">fail([result])</a>:</p>
<blockquote>
<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had <tt class="docutils literal"><span class="pre">.errback(result)</span></tt>
called.</p>
<p>See <tt class="docutils literal"><span class="pre">succeed</span></tt> documentation for rationale.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
<dd>The result to give to <a class="mochiref reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback(result)</a>.</dd>
<dt><em>returns</em>:</dt>
<dd>A <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred()</a></dd>
</dl>
</blockquote>
<p>
<a name="fn-gatherresults"></a>
<a class="mochidef reference" href="#fn-gatherresults">gatherResults(deferreds)</a>:</p>
<blockquote>
A convenience function that returns a <a class="mochiref reference" href="#fn-deferredlist">DeferredList</a>
from the given <tt class="docutils literal"><span class="pre">Array</span></tt> of <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances
that will callback with an <tt class="docutils literal"><span class="pre">Array</span></tt> of just results when
they're available, or errback on the first array.</blockquote>
<p>
<a name="fn-getxmlhttprequest"></a>
<a class="mochidef reference" href="#fn-getxmlhttprequest">getXMLHttpRequest()</a>:</p>
<blockquote>
<p>Return an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> compliant object for the current
platform.</p>
<p>In order of preference:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">XMLHttpRequest()</span></tt></li>
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP')</span></tt></li>
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Microsoft.XMLHTTP')</span></tt></li>
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP.4.0')</span></tt></li>
</ul>
</blockquote>
<p>
<a name="fn-maybedeferred"></a>
<a class="mochidef reference" href="#fn-maybedeferred">maybeDeferred(func[, argument...])</a>:</p>
<blockquote>
<p>Call a <tt class="docutils literal"><span class="pre">func</span></tt> with the given arguments and ensure the result is a
<a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">func</span></tt>:</dt>
<dd>The function to call.</dd>
<dt><em>returns</em>:</dt>
<dd>A new <a class="mochiref reference" href="#fn-deferred">Deferred</a> based on the call to <tt class="docutils literal"><span class="pre">func</span></tt>. If <tt class="docutils literal"><span class="pre">func</span></tt>
does not naturally return a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, its result or error
value will be wrapped by one.</dd>
</dl>
</blockquote>
<p>
<a name="fn-loadjsondoc"></a>
<a class="mochidef reference" href="#fn-loadjsondoc">loadJSONDoc(url)</a>:</p>
<blockquote>
<p>Do a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to a URL and get the response
as a JSON <a class="footnote-reference" href="#id10" id="id5" name="id5">[4]</a> document.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
<dd>The URL to GET</dd>
<dt><em>returns</em>:</dt>
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the evaluated JSON <a class="footnote-reference" href="#id10" id="id6" name="id6">[4]</a>
response upon successful <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></dd>
</dl>
</blockquote>
<p>
<a name="fn-sendxmlhttprequest"></a>
<a class="mochidef reference" href="#fn-sendxmlhttprequest">sendXMLHttpRequest(req[, sendContent])</a>:</p>
<blockquote>
<p>Set an <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> handler on an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object
and send it off. Will return a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will
callback on success.</p>
<p>Note that currently, only <tt class="docutils literal"><span class="pre">200</span></tt> (OK) and <tt class="docutils literal"><span class="pre">304</span></tt>
(NOT_MODIFIED) are considered success codes at this time, other
status codes will result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
<dd>An preconfigured <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object (open has been called).</dd>
<dt><tt class="docutils literal"><span class="pre">sendContent</span></tt>:</dt>
<dd>Optional string or DOM content to send over the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</dd>
<dt><em>returns</em>:</dt>
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
instance on success.</dd>
</dl>
</blockquote>
<p>
<a name="fn-succeed"></a>
<a class="mochidef reference" href="#fn-succeed">succeed([result])</a>:</p>
<blockquote>
<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had <tt class="docutils literal"><span class="pre">.callback(result)</span></tt>
called.</p>
<p>This is useful when you're writing synchronous code to an asynchronous
interface: i.e., some code is calling you expecting a <a class="mochiref reference" href="#fn-deferred">Deferred</a>
result, but you don't actually need to do anything asynchronous. Just
return <tt class="docutils literal"><span class="pre">succeed(theResult)</span></tt>.</p>
<p>See <tt class="docutils literal"><span class="pre">fail</span></tt> for a version of this function that uses a failing
<a class="mochiref reference" href="#fn-deferred">Deferred</a> rather than a successful one.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
<dd>The result to give to <a class="mochiref reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback(result)</a></dd>
<dt><em>returns</em>:</dt>
<dd>a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred</a></dd>
</dl>
</blockquote>
<p>
<a name="fn-wait"></a>
<a class="mochidef reference" href="#fn-wait">wait(seconds[, res])</a>:</p>
<blockquote>
Return a new cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will <tt class="docutils literal"><span class="pre">.callback(res)</span></tt>
after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have elapsed.</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id7" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id7">[1]</a></td><td>AJAX, Asynchronous JavaScript and XML: <a class="reference" href="http://en.wikipedia.org/wiki/AJAX">http://en.wikipedia.org/wiki/AJAX</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id8" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2" name="id8">[2]</a></td><td>Twisted, an event-driven networking framework written in Python: <a class="reference" href="http://twistedmatrix.com/">http://twistedmatrix.com/</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id9" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3" name="id9">[3]</a></td><td>Twisted Deferred Reference: <a class="reference" href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html">http://twistedmatrix.com/projects/core/documentation/howto/defer.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id10" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id10">[4]</a></td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id5">2</a>, <a class="fn-backref" href="#id6">3</a>)</em> JSON, JavaScript Object Notation: <a class="reference" href="http://json.org/">http://json.org/</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,509 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Color - color abstraction with CSS3 support</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Color - color abstraction with CSS3 support</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
// RGB color expressions are supported
assert(
objEqual(Color.whiteColor(), Color.fromString(&quot;rgb(255,100%, 255)&quot;))
);
// So is instantiating directly from HSL or RGB values.
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
// Or even SVG color keyword names, as per CSS3!
assert( Color.fromString(&quot;aquamarine&quot;), &quot;#7fffd4&quot; );
// NSColor-like colors built in
assert( Color.whiteColor().toHexString() == &quot;#ffffff&quot; );
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>MochiKit.Color is an abstraction for handling colors and strings that
represent colors.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<p>MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha.
It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG)
color table.</p>
<p>All of the functionality in this module is exposed through a Color constructor
and its prototype, but a few of its internals are available for direct use at
module level.</p>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="constructors" name="constructors">Constructors</a></h2>
<p>
<a name="fn-color"></a>
<a class="mochidef reference" href="#fn-color">Color()</a>:</p>
<blockquote>
<p>Represents a color. Component values should be integers between <tt class="docutils literal"><span class="pre">0.0</span></tt>
and <tt class="docutils literal"><span class="pre">1.0</span></tt>. You should use one of the <a class="mochiref reference" href="#fn-color">Color</a> factory
functions such as <a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB</a>, <a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL</a>,
etc. instead of constructing <a class="mochiref reference" href="#fn-color">Color</a> objects directly.</p>
<p><a class="mochiref reference" href="#fn-color">Color</a> instances can be compared with
<a class="mochiref reference" href="Base.html#fn-compare">MochiKit.Base.compare</a> (though ordering is on RGB, so is not
particularly meaningful except for equality), and the default <tt class="docutils literal"><span class="pre">toString</span></tt>
implementation returns <a class="mochiref reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>.</p>
<p><a class="mochiref reference" href="#fn-color">Color</a> instances are immutable, and much of the architecture is
inspired by AppKit's NSColor <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a></p>
</blockquote>
<p>
<a name="fn-color.frombackground"></a>
<a class="mochidef reference" href="#fn-color.frombackground">Color.fromBackground(elem)</a>:</p>
<blockquote>
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the background of the provided
element. Equivalent to:</p>
<pre class="literal-block">
c = Color.fromComputedStyle(
elem, &quot;backgroundColor&quot;, &quot;background-color&quot;) || Color.whiteColor();
</pre>
</blockquote>
<p>
<a name="fn-color.fromcomputedstyle"></a>
<a class="mochidef reference" href="#fn-color.fromcomputedstyle">Color.fromComputedStyle(elem, style, mozillaEquivalentCSS)</a>:</p>
<blockquote>
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the result of
<a class="mochiref reference" href="DOM.html#fn-computedstyle">MochiKit.DOM.computedStyle(elem, style, mozillaEquivalentCSS)</a>
or <tt class="docutils literal"><span class="pre">null</span></tt> if not found.</blockquote>
<p>
<a name="fn-color.fromhexstring"></a>
<a class="mochidef reference" href="#fn-color.fromhexstring">Color.fromHexString(hexString)</a>:</p>
<blockquote>
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given hexadecimal color string.
For example, <tt class="docutils literal"><span class="pre">&quot;#FFFFFF&quot;</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt> (white).</blockquote>
<p>
<a name="fn-color.fromhsl"></a>
<a class="mochidef reference" href="#fn-color.fromhsl">Color.fromHSL(hue, saturation, lightness, alpha=1.0)</a>:</p>
<blockquote>
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>, <tt class="docutils literal"><span class="pre">saturation</span></tt>,
<tt class="docutils literal"><span class="pre">lightness</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0.0</span></tt> and
<tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})</a></dd>
</dl>
</blockquote>
<p>
<a name="fn-color.fromhslstring"></a>
<a class="mochidef reference" href="#fn-color.fromhslstring">Color.fromHSLString(hslString)</a>:</p>
<blockquote>
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal hsl color string.
For example, <tt class="docutils literal"><span class="pre">&quot;hsl(0,0%,100%)&quot;</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
HSL values <tt class="docutils literal"><span class="pre">[0/360,</span> <span class="pre">0/360,</span> <span class="pre">360/360]</span></tt> (white).</blockquote>
<p>
<a name="fn-color.fromhsv"></a>
<a class="mochidef reference" href="#fn-color.fromhsv">Color.fromHSV(hue, saturation, value, alpha=1.0)</a>:</p>
<blockquote>
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>, <tt class="docutils literal"><span class="pre">saturation</span></tt>,
<tt class="docutils literal"><span class="pre">value</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0.0</span></tt> and
<tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-color.fromhsv">Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})</a></dd>
</dl>
</blockquote>
<p>
<a name="fn-color.fromname"></a>
<a class="mochidef reference" href="#fn-color.fromname">Color.fromName(colorName)</a>:</p>
<blockquote>
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object corresponding to the given
SVG 1.0 color keyword name <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> as per the W3C CSS3
Color Module <a class="footnote-reference" href="#id8" id="id3" name="id3">[3]</a>. <tt class="docutils literal"><span class="pre">&quot;transparent&quot;</span></tt> is also accepted
as a color name, and will return <a class="mochiref reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>.</blockquote>
<p>
<a name="fn-color.fromrgb"></a>
<a class="mochidef reference" href="#fn-color.fromrgb">Color.fromRGB(red, green, blue, alpha=1.0)</a>:</p>
<blockquote>
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">red</span></tt>, <tt class="docutils literal"><span class="pre">green</span></tt>,
<tt class="docutils literal"><span class="pre">blue</span></tt>, and <tt class="docutils literal"><span class="pre">alpha</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0</span></tt>
and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB({r: red, g: green, b: blue, a: alpha})</a></dd>
</dl>
</blockquote>
<p>
<a name="fn-color.fromrgbstring"></a>
<a class="mochidef reference" href="#fn-color.fromrgbstring">Color.fromRGBString(rgbString)</a>:</p>
<blockquote>
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal rgb color string.
For example, <tt class="docutils literal"><span class="pre">&quot;rgb(255,255,255)&quot;</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt> (white).</blockquote>
<p>
<a name="fn-color.fromtext"></a>
<a class="mochidef reference" href="#fn-color.fromtext">Color.fromText(elem)</a>:</p>
<blockquote>
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the text color of the provided
element. Equivalent to:</p>
<pre class="literal-block">
c = Color.fromComputedStyle(elem, &quot;color&quot;) || Color.whiteColor();
</pre>
</blockquote>
<p>
<a name="fn-color.fromstring"></a>
<a class="mochidef reference" href="#fn-color.fromstring">Color.fromString(rgbOrHexString)</a>:</p>
<blockquote>
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given RGB, HSL, hex, or name.
Will return <tt class="docutils literal"><span class="pre">null</span></tt> if the string can not be parsed by any of these
methods.</p>
<p>See <a class="mochiref reference" href="#fn-color.fromhexstring">Color.fromHexString</a>, <a class="mochiref reference" href="#fn-color.fromrgbstring">Color.fromRGBString</a>,
<a class="mochiref reference" href="#fn-color.fromhslstring">Color.fromHSLString</a> and <a class="mochiref reference" href="#fn-color.fromname">Color.fromName</a> more
information.</p>
</blockquote>
<p>
<a name="fn-color.namedcolors"></a>
<a class="mochidef reference" href="#fn-color.namedcolors">Color.namedColors()</a>:</p>
<blockquote>
Returns an object with properties for each SVG 1.0 color keyword
name <a class="footnote-reference" href="#id7" id="id4" name="id4">[2]</a> supported by CSS3 <a class="footnote-reference" href="#id8" id="id5" name="id5">[3]</a>. Property names are the color keyword
name in lowercase, and the value is a string suitable for
<a class="mochiref reference" href="#fn-color.fromstring">Color.fromString()</a>.</blockquote>
<p>
<a name="fn-color.prototype.colorwithalpha"></a>
<a class="mochidef reference" href="#fn-color.prototype.colorwithalpha">Color.prototype.colorWithAlpha(alpha)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
<tt class="docutils literal"><span class="pre">alpha</span></tt> value.</blockquote>
<p>
<a name="fn-color.prototype.colorwithhue"></a>
<a class="mochidef reference" href="#fn-color.prototype.colorwithhue">Color.prototype.colorWithHue(hue)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
<tt class="docutils literal"><span class="pre">hue</span></tt> value.</blockquote>
<p>
<a name="fn-color.prototype.colorwithsaturation"></a>
<a class="mochidef reference" href="#fn-color.prototype.colorwithsaturation">Color.prototype.colorWithSaturation(saturation)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
<tt class="docutils literal"><span class="pre">saturation</span></tt> value (using the HSL color model).</blockquote>
<p>
<a name="fn-color.prototype.colorwithlightness"></a>
<a class="mochidef reference" href="#fn-color.prototype.colorwithlightness">Color.prototype.colorWithLightness(lightness)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
<tt class="docutils literal"><span class="pre">lightness</span></tt> value.</blockquote>
<p>
<a name="fn-color.prototype.darkercolorwithlevel"></a>
<a class="mochidef reference" href="#fn-color.prototype.darkercolorwithlevel">Color.prototype.darkerColorWithLevel(level)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but darker by the given
<tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</blockquote>
<p>
<a name="fn-color.prototype.lightercolorwithlevel"></a>
<a class="mochidef reference" href="#fn-color.prototype.lightercolorwithlevel">Color.prototype.lighterColorWithLevel(level)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but lighter by the given
<tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</blockquote>
<p>
<a name="fn-color.prototype.blendedcolor"></a>
<a class="mochidef reference" href="#fn-color.prototype.blendedcolor">Color.prototype.blendedColor(other, fraction=0.5)</a>:</p>
<blockquote>
Return a new <a class="mochiref reference" href="#fn-color">Color</a> whose RGBA component values are a weighted sum
of this color and <tt class="docutils literal"><span class="pre">other</span></tt>. Each component of the returned color
is the <tt class="docutils literal"><span class="pre">fraction</span></tt> of other's value plus <tt class="docutils literal"><span class="pre">1</span> <span class="pre">-</span> <span class="pre">fraction</span></tt> of this
color's.</blockquote>
<p>
<a name="fn-color.prototype.islight"></a>
<a class="mochidef reference" href="#fn-color.prototype.islight">Color.prototype.isLight()</a>:</p>
<blockquote>
<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is greater than
<tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color components
are not premultiplied).</p>
</blockquote>
<p>
<a name="fn-color.prototype.isdark"></a>
<a class="mochidef reference" href="#fn-color.prototype.isdark">Color.prototype.isDark()</a>:</p>
<blockquote>
<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is less than or
equal to <tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color components
are not premultiplied).</p>
</blockquote>
<p>
<a name="fn-color.prototype.torgbstring"></a>
<a class="mochidef reference" href="#fn-color.prototype.torgbstring">Color.prototype.toRGBString()</a>:</p>
<blockquote>
<p>Return the decimal <tt class="docutils literal"><span class="pre">&quot;rgb(red,</span> <span class="pre">green,</span> <span class="pre">blue)&quot;</span></tt> string representation of this
color.</p>
<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
<tt class="docutils literal"><span class="pre">&quot;rgba(red,</span> <span class="pre">green,</span> <span class="pre">blue,</span> <span class="pre">alpha)&quot;</span></tt> string representation will be used.</p>
<p>For example:</p>
<pre class="literal-block">
assert( Color.whiteColor().toRGBString() == &quot;rgb(255,255,255)&quot; );
</pre>
</blockquote>
<p>
<a name="fn-color.prototype.tohslstring"></a>
<a class="mochidef reference" href="#fn-color.prototype.tohslstring">Color.prototype.toHSLString()</a>:</p>
<blockquote>
<p>Return the decimal <tt class="docutils literal"><span class="pre">&quot;hsl(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness)&quot;</span></tt>
string representation of this color.</p>
<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
<tt class="docutils literal"><span class="pre">&quot;hsla(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness,</span> <span class="pre">alpha)&quot;</span></tt> string representation
will be used.</p>
<p>For example:</p>
<pre class="literal-block">
assert( Color.whiteColor().toHSLString() == &quot;hsl(0,0,360)&quot; );
</pre>
</blockquote>
<p>
<a name="fn-color.prototype.tohexstring"></a>
<a class="mochidef reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>:</p>
<blockquote>
<p>Return the hexadecimal <tt class="docutils literal"><span class="pre">&quot;#RRGGBB&quot;</span></tt> string representation of this color.</p>
<p>Note that the alpha component is completely ignored for hexadecimal
string representations!</p>
<p>For example:</p>
<pre class="literal-block">
assert( Color.whiteColor().toHexString() == &quot;#FFFFFF&quot; );
</pre>
</blockquote>
<p>
<a name="fn-color.prototype.asrgb"></a>
<a class="mochidef reference" href="#fn-color.prototype.asrgb">Color.prototype.asRGB()</a>:</p>
<blockquote>
Return the RGB (red, green, blue, alpha) components of this color as an
object with <tt class="docutils literal"><span class="pre">r</span></tt>, <tt class="docutils literal"><span class="pre">g</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, and <tt class="docutils literal"><span class="pre">a</span></tt> properties that have
values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
<p>
<a name="fn-color.prototype.ashsl"></a>
<a class="mochidef reference" href="#fn-color.prototype.ashsl">Color.prototype.asHSL()</a>:</p>
<blockquote>
Return the HSL (hue, saturation, lightness, alpha) components of this
color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">l</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
<p>
<a name="fn-color.prototype.ashsv"></a>
<a class="mochidef reference" href="#fn-color.prototype.ashsv">Color.prototype.asHSV()</a>:</p>
<blockquote>
Return the HSV (hue, saturation, value, alpha) components of this
color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">v</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
<p>
<a name="fn-color.blackcolor"></a>
<a class="mochidef reference" href="#fn-color.blackcolor">Color.blackColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 0
(#000000).</blockquote>
<p>
<a name="fn-color.bluecolor"></a>
<a class="mochidef reference" href="#fn-color.bluecolor">Color.blueColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 1
(#0000ff).</blockquote>
<p>
<a name="fn-color.browncolor"></a>
<a class="mochidef reference" href="#fn-color.browncolor">Color.brownColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.6, 0.4, 0.2
(#996633).</blockquote>
<p>
<a name="fn-color.cyancolor"></a>
<a class="mochidef reference" href="#fn-color.cyancolor">Color.cyanColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 1
(#00ffff).</blockquote>
<p>
<a name="fn-color.darkgraycolor"></a>
<a class="mochidef reference" href="#fn-color.darkgraycolor">Color.darkGrayColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1/3, 1/3, 1/3
(#555555).</blockquote>
<p>
<a name="fn-color.graycolor"></a>
<a class="mochidef reference" href="#fn-color.graycolor">Color.grayColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0.5, 0.5
(#808080).</blockquote>
<p>
<a name="fn-color.greencolor"></a>
<a class="mochidef reference" href="#fn-color.greencolor">Color.greenColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 0.
(#00ff00).</blockquote>
<p>
<a name="fn-color.lightgraycolor"></a>
<a class="mochidef reference" href="#fn-color.lightgraycolor">Color.lightGrayColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 2/3, 2/3, 2/3
(#aaaaaa).</blockquote>
<p>
<a name="fn-color.magentacolor"></a>
<a class="mochidef reference" href="#fn-color.magentacolor">Color.magentaColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 1
(#ff00ff).</blockquote>
<p>
<a name="fn-color.orangecolor"></a>
<a class="mochidef reference" href="#fn-color.orangecolor">Color.orangeColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0.5, 0
(#ff8000).</blockquote>
<p>
<a name="fn-color.purplecolor"></a>
<a class="mochidef reference" href="#fn-color.purplecolor">Color.purpleColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0, 0.5
(#800080).</blockquote>
<p>
<a name="fn-color.redcolor"></a>
<a class="mochidef reference" href="#fn-color.redcolor">Color.redColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 0
(#ff0000).</blockquote>
<p>
<a name="fn-color.whitecolor"></a>
<a class="mochidef reference" href="#fn-color.whitecolor">Color.whiteColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 1
(#ffffff).</blockquote>
<p>
<a name="fn-color.yellowcolor"></a>
<a class="mochidef reference" href="#fn-color.yellowcolor">Color.yellowColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 0
(#ffff00).</blockquote>
<p>
<a name="fn-color.transparentcolor"></a>
<a class="mochidef reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>:</p>
<blockquote>
Return a <a class="mochiref reference" href="#fn-color">Color</a> object that is completely transparent
(has alpha component of 0).</blockquote>
</div>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-clampcolorcomponent"></a>
<a class="mochidef reference" href="#fn-clampcolorcomponent">clampColorComponent(num, scale)</a>:</p>
<blockquote>
<p>Returns <tt class="docutils literal"><span class="pre">num</span> <span class="pre">*</span> <span class="pre">scale</span></tt> clamped between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">scale</span></tt>.</p>
<p><a class="mochiref reference" href="#fn-clampcolorcomponent">clampColorComponent</a> is not exported by default when using JSAN.</p>
</blockquote>
<p>
<a name="fn-hsltorgb"></a>
<a class="mochidef reference" href="#fn-hsltorgb">hslToRGB(hue, saturation, lightness, alpha)</a>:</p>
<blockquote>
<p>Computes RGB values from the provided HSL values. The return value is a
mapping with <tt class="docutils literal"><span class="pre">&quot;r&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;g&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;b&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt> keys.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})</a>.</dd>
</dl>
<p><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB</a> is not exported by default when using JSAN.</p>
</blockquote>
<p>
<a name="fn-hsvtorgb"></a>
<a class="mochidef reference" href="#fn-hsvtorgb">hsvToRGB(hue, saturation, value, alpha)</a>:</p>
<blockquote>
<p>Computes RGB values from the provided HSV values. The return value is a
mapping with <tt class="docutils literal"><span class="pre">&quot;r&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;g&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;b&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt> keys.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB({h: hue, s: saturation, v: value, a: alpha})</a>.</dd>
</dl>
<p><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB</a> is not exported by default when using JSAN.</p>
</blockquote>
<p>
<a name="fn-tocolorpart"></a>
<a class="mochidef reference" href="#fn-tocolorpart">toColorPart(num)</a>:</p>
<blockquote>
<p>Convert num to a zero padded hexadecimal digit for use in a hexadecimal
color string. Num should be an integer between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">255</span></tt>.</p>
<p><a class="mochiref reference" href="#fn-tocolorpart">toColorPart</a> is not exported by default when using JSAN.</p>
</blockquote>
<p>
<a name="fn-rgbtohsl"></a>
<a class="mochidef reference" href="#fn-rgbtohsl">rgbToHSL(red, green, blue, alpha)</a>:</p>
<blockquote>
<p>Computes HSL values based on the provided RGB values. The return value is
a mapping with <tt class="docutils literal"><span class="pre">&quot;h&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;s&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;l&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt> keys.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL({r: red, g: green, b: blue, a: alpha})</a>.</dd>
</dl>
<p><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL</a> is not exported by default when using JSAN.</p>
</blockquote>
<p>
<a name="fn-rgbtohsv"></a>
<a class="mochidef reference" href="#fn-rgbtohsv">rgbToHSV(red, green, blue, alpha)</a>:</p>
<blockquote>
<p>Computes HSV values based on the provided RGB values. The return value is
a mapping with <tt class="docutils literal"><span class="pre">&quot;h&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;s&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;v&quot;</span></tt> and <tt class="docutils literal"><span class="pre">&quot;a&quot;</span></tt> keys.</p>
<dl class="docutils">
<dt>Alternate form:</dt>
<dd><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV({r: red, g: green, b: blue, a: alpha})</a>.</dd>
</dl>
<p><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV</a> is not exported by default when using JSAN.</p>
</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id7" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id7">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id8" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id8">[3]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id5">2</a>)</em> W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,798 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.DOM - painless DOM manipulation API</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.DOM - painless DOM manipulation API</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
var rows = [
[&quot;dataA1&quot;, &quot;dataA2&quot;, &quot;dataA3&quot;],
[&quot;dataB1&quot;, &quot;dataB2&quot;, &quot;dataB3&quot;]
];
row_display = function (row) {
return TR(null, map(partial(TD, null), row));
}
var newTable = TABLE({'class': 'prettytable'},
THEAD(null,
row_display([&quot;head1&quot;, &quot;head2&quot;, &quot;head3&quot;])),
TFOOT(null,
row_display([&quot;foot1&quot;, &quot;foot2&quot;, &quot;foot3&quot;])),
TBODY(null,
map(row_display, rows)));
// put that in your document.createElement and smoke it!
swapDOM(oldTable, newTable);
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>As you probably know, the DOM APIs are some of the most painful Java-inspired
APIs you'll run across from a highly dynamic language. Don't worry about that
though, because they provide a reasonable basis to build something that
sucks a lot less.</p>
<p>MochiKit.DOM takes much of its inspiration from Nevow's <a class="footnote-reference" href="#id5" id="id1" name="id1">[1]</a> stan <a class="footnote-reference" href="#id6" id="id2" name="id2">[2]</a>.
This means you choose a tag, give it some attributes, then stuff it full
of <em>whatever objects you want</em>. MochiKit.DOM isn't stupid, it knows that
a string should be a text node, and that you want functions to be called,
and that <tt class="docutils literal"><span class="pre">Array</span></tt>-like objects should be expanded, and stupid <tt class="docutils literal"><span class="pre">null</span></tt> values
should be skipped.</p>
<p>Hell, it will let you return strings from functions, and use iterators from
<a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>. If that's not enough, just teach it new tricks with
<a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>. If you have never used an API like this for
creating DOM elements, you've been wasting your damn time. Get with it!</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<div class="section">
<h2><a id="dom-coercion-rules" name="dom-coercion-rules">DOM Coercion Rules</a></h2>
<p>In order of precedence, <a class="mochiref reference" href="#fn-createdom">createDOM</a> coerces given arguments to DOM
nodes using the following rules:</p>
<ol class="arabic simple">
<li>Functions are called with a <tt class="docutils literal"><span class="pre">this</span></tt> of the parent
node and their return value is subject to the
following rules (even this one).</li>
<li><tt class="docutils literal"><span class="pre">undefined</span></tt> and <tt class="docutils literal"><span class="pre">null</span></tt> are ignored.</li>
<li>Iterables (see <a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>) are flattened
(as if they were passed in-line as nodes) and each
return value is subject to all of these rules.</li>
<li>Values that look like DOM nodes (objects with a
<tt class="docutils literal"><span class="pre">.nodeType</span> <span class="pre">&gt;</span> <span class="pre">0</span></tt>) are <tt class="docutils literal"><span class="pre">.appendChild</span></tt>'ed to the created
DOM fragment.</li>
<li>Strings are wrapped up with <tt class="docutils literal"><span class="pre">document.createTextNode</span></tt></li>
<li>Objects that are not strings are run through the <tt class="docutils literal"><span class="pre">domConverters</span></tt>
<a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a>
(see <a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>).
The value returned by the adapter is subject to these same rules (e.g.
adapters are allowed to return a string, which will be coerced into a
text node).</li>
<li>If no adapter is available, <tt class="docutils literal"><span class="pre">.toString()</span></tt> is used to create a text node.</li>
</ol>
</div>
<div class="section">
<h2><a id="creating-dom-element-trees" name="creating-dom-element-trees">Creating DOM Element Trees</a></h2>
<p><a class="mochiref reference" href="#fn-createdom">createDOM</a> provides you with an excellent facility for creating DOM trees
that is easy on the wrists. One of the best ways to understand how to use
it is to take a look at an example:</p>
<pre class="literal-block">
var rows = [
[&quot;dataA1&quot;, &quot;dataA2&quot;, &quot;dataA3&quot;],
[&quot;dataB1&quot;, &quot;dataB2&quot;, &quot;dataB3&quot;]
];
row_display = function (row) {
return TR(null, map(partial(TD, null), row));
}
var newTable = TABLE({'class': 'prettytable'},
THEAD(null,
row_display([&quot;head1&quot;, &quot;head2&quot;, &quot;head3&quot;])),
TFOOT(null,
row_display([&quot;foot1&quot;, &quot;foot2&quot;, &quot;foot3&quot;])),
TBODY(null,
map(row_display, rows)));
</pre>
<p>This will create a table with the following visual layout (if it
were inserted into the document DOM):</p>
<blockquote>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">head1</th>
<th class="head">head2</th>
<th class="head">head3</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>dataA1</td>
<td>dataA2</td>
<td>dataA3</td>
</tr>
<tr><td>dataB1</td>
<td>dataB2</td>
<td>dataB3</td>
</tr>
<tr><td>foot1</td>
<td>foot2</td>
<td>foot3</td>
</tr>
</tbody>
</table>
</blockquote>
<p>Corresponding to the following HTML:</p>
<pre class="literal-block">
&lt;table class=&quot;prettytable&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td&gt;head1&lt;/td&gt;
&lt;td&gt;head2&lt;/td&gt;
&lt;td&gt;head3&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tfoot&gt;
&lt;tr&gt;
&lt;td&gt;foot1&lt;/td&gt;
&lt;td&gt;foot2&lt;/td&gt;
&lt;td&gt;foot3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tfoot&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dataA1&lt;/td&gt;
&lt;td&gt;dataA2&lt;/td&gt;
&lt;td&gt;dataA3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dataB1&lt;/td&gt;
&lt;td&gt;dataB2&lt;/td&gt;
&lt;td&gt;dataB3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</pre>
</div>
<div class="section">
<h2><a id="dom-context" name="dom-context">DOM Context</a></h2>
<p>In order to prevent having to pass a <tt class="docutils literal"><span class="pre">window</span></tt> and/or <tt class="docutils literal"><span class="pre">document</span></tt>
variable to every MochiKit.DOM function (e.g. when working with a
child window), MochiKit.DOM maintains a context variable for each
of them. They are managed with the <a class="mochiref reference" href="#fn-withwindow">withWindow</a> and
<a class="mochiref reference" href="#fn-withdocument">withDocument</a> functions, and can be acquired with
<a class="mochiref reference" href="#fn-currentwindow">currentWindow()</a> and <a class="mochiref reference" href="#fn-currentdocument">currentDocument()</a></p>
<p>For example, if you are creating DOM nodes in a child window, you
could do something like this:</p>
<pre class="literal-block">
withWindow(child, function () {
var doc = currentDocument();
appendChildNodes(doc.body, H1(null, &quot;This is in the child!&quot;));
});
</pre>
<p>Note that <a class="mochiref reference" href="#fn-withwindow">withWindow(win, ...)</a> also implies
<a class="mochiref reference" href="#fn-withdocument">withDocument(win.document, ...)</a>.</p>
</div>
<div class="section">
<h2><a id="element-visibility" name="element-visibility">Element Visibility</a></h2>
<p>The <a class="mochiref reference" href="#fn-hideelement">hideElement</a> and <a class="mochiref reference" href="#fn-showelement">showElement</a> functions are
provided as a convenience, but only work for elements that are
<tt class="docutils literal"><span class="pre">display:</span> <span class="pre">block</span></tt>. For a general solution to showing, hiding, and checking
the explicit visibility of elements, we recommend using a solution that
involves a little CSS. Here's an example:</p>
<pre class="literal-block">
&lt;style type=&quot;text/css&quot;&gt;
.invisible { display: none; }
&lt;/style&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
function toggleVisible(elem) {
toggleElementClass(&quot;invisible&quot;, elem);
}
function makeVisible(elem) {
removeElementClass(elem, &quot;invisible&quot;);
}
function makeInvisible(elem) {
addElementClass(elem, &quot;invisible&quot;);
}
function isVisible(elem) {
// you may also want to check for
// getElement(elem).style.display == &quot;none&quot;
return !hasElementClass(elem, &quot;invisible&quot;);
};
&lt;/script&gt;
</pre>
<p>MochiKit doesn't ship with such a solution, because there is no reliable and
portable method for adding CSS rules on the fly with JavaScript.</p>
</div>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-$"></a>
<a class="mochidef reference" href="#fn-$">$(id[, ...])</a>:</p>
<blockquote>
An alias for <a class="mochiref reference" href="#fn-getelement">getElement(id[, ...])</a></blockquote>
<p>
<a name="fn-addelementclass"></a>
<a class="mochidef reference" href="#fn-addelementclass">addElementClass(element, className)</a>:</p>
<blockquote>
Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> has <tt class="docutils literal"><span class="pre">className</span></tt> set as part of its
class attribute. This will not disturb other class names.
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
are also acceptable.</blockquote>
<p>
<a name="fn-addloadevent"></a>
<a class="mochidef reference" href="#fn-addloadevent">addLoadEvent(func)</a>:</p>
<blockquote>
<p>Note that <a class="mochiref reference" href="#fn-addloadevent">addLoadEvent</a> can not be used in combination with
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> if the <tt class="docutils literal"><span class="pre">onload</span></tt> event is connected.
Once an event is connected with <a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs
may be used for that same event.</p>
<p>This will stack <tt class="docutils literal"><span class="pre">window.onload</span></tt> functions on top of each other.
Each function added will be called after <tt class="docutils literal"><span class="pre">onload</span></tt> in the
order that they were added.</p>
</blockquote>
<p>
<a name="fn-addtocallstack"></a>
<a class="mochidef reference" href="#fn-addtocallstack">addToCallStack(target, path, func[, once])</a>:</p>
<blockquote>
<p>Note that <a class="mochiref reference" href="#fn-addtocallstack">addToCallStack</a> is not compatible with
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>. Once an event is connected with
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs may be used for that same event.</p>
<p>Set the property <tt class="docutils literal"><span class="pre">path</span></tt> of <tt class="docutils literal"><span class="pre">target</span></tt> to a function that calls the
existing function at that property (if any), then calls <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">target[path]()</span></tt> returns exactly <tt class="docutils literal"><span class="pre">false</span></tt>, then <tt class="docutils literal"><span class="pre">func</span></tt> will
not be called.</p>
<p>If <tt class="docutils literal"><span class="pre">once</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then <tt class="docutils literal"><span class="pre">target[path]</span></tt> is set to <tt class="docutils literal"><span class="pre">null</span></tt> after
the function call stack has completed.</p>
<p>If called several times for the same <tt class="docutils literal"><span class="pre">target[path]</span></tt>, it will create
a stack of functions (instead of just a pair).</p>
</blockquote>
<p>
<a name="fn-appendchildnodes"></a>
<a class="mochidef reference" href="#fn-appendchildnodes">appendChildNodes(node[, childNode[, ...]])</a>:</p>
<blockquote>
<p>Append children to a DOM element using the <a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to add children to
(if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
<dd>All additional arguments, if any, will be coerced into DOM
nodes that are appended as children using the
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
<dt><em>returns</em>:</dt>
<dd>The given DOM element</dd>
</dl>
</blockquote>
<p>
<a name="fn-computedstyle"></a>
<a class="mochidef reference" href="#fn-computedstyle">computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)</a>:</p>
<blockquote>
Looks up a CSS property for the given element. The element can be
specified as either a string with the element's ID or the element
object itself.</blockquote>
<p>
<a name="fn-createdom"></a>
<a class="mochidef reference" href="#fn-createdom">createDOM(name[, attrs[, node[, ...]]])</a>:</p>
<blockquote>
<p>Create a DOM fragment in a really convenient manner, much like
Nevow`s <a class="footnote-reference" href="#id5" id="id3" name="id3">[1]</a> stan <a class="footnote-reference" href="#id6" id="id4" name="id4">[2]</a>.</p>
<p>Partially applied versions of this function for common tags are
available as aliases:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">A</span></tt></li>
<li><tt class="docutils literal"><span class="pre">BUTTON</span></tt></li>
<li><tt class="docutils literal"><span class="pre">BR</span></tt></li>
<li><tt class="docutils literal"><span class="pre">CANVAS</span></tt></li>
<li><tt class="docutils literal"><span class="pre">DIV</span></tt></li>
<li><tt class="docutils literal"><span class="pre">FIELDSET</span></tt></li>
<li><tt class="docutils literal"><span class="pre">FORM</span></tt></li>
<li><tt class="docutils literal"><span class="pre">H1</span></tt></li>
<li><tt class="docutils literal"><span class="pre">H2</span></tt></li>
<li><tt class="docutils literal"><span class="pre">H3</span></tt></li>
<li><tt class="docutils literal"><span class="pre">HR</span></tt></li>
<li><tt class="docutils literal"><span class="pre">IMG</span></tt></li>
<li><tt class="docutils literal"><span class="pre">INPUT</span></tt></li>
<li><tt class="docutils literal"><span class="pre">LABEL</span></tt></li>
<li><tt class="docutils literal"><span class="pre">LEGEND</span></tt></li>
<li><tt class="docutils literal"><span class="pre">LI</span></tt></li>
<li><tt class="docutils literal"><span class="pre">OL</span></tt></li>
<li><tt class="docutils literal"><span class="pre">OPTGROUP</span></tt></li>
<li><tt class="docutils literal"><span class="pre">OPTION</span></tt></li>
<li><tt class="docutils literal"><span class="pre">P</span></tt></li>
<li><tt class="docutils literal"><span class="pre">PRE</span></tt></li>
<li><tt class="docutils literal"><span class="pre">SELECT</span></tt></li>
<li><tt class="docutils literal"><span class="pre">SPAN</span></tt></li>
<li><tt class="docutils literal"><span class="pre">STRONG</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TABLE</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TBODY</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TD</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TEXTAREA</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TFOOT</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TH</span></tt></li>
<li><tt class="docutils literal"><span class="pre">THEAD</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TR</span></tt></li>
<li><tt class="docutils literal"><span class="pre">TT</span></tt></li>
<li><tt class="docutils literal"><span class="pre">UL</span></tt></li>
</ul>
<p>See <a class="reference" href="#creating-dom-element-trees">Creating DOM Element Trees</a> for a comprehensive example.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
<dd>The kind of fragment to create (e.g. 'span'), such as you would
pass to <tt class="docutils literal"><span class="pre">document.createElement</span></tt>.</dd>
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
<dd><p class="first">An object whose properties will be used as the attributes
(e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">'display:block'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
attributes need to be set.</p>
<p>See <a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a> for more information.</p>
<p class="last">For convenience, if <tt class="docutils literal"><span class="pre">attrs</span></tt> is a string, <tt class="docutils literal"><span class="pre">null</span></tt> is used
and the string will be considered the first <tt class="docutils literal"><span class="pre">node</span></tt>.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
<dd>All additional arguments, if any, will be coerced into DOM
nodes that are appended as children using the
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
<dt><em>returns</em>:</dt>
<dd>A DOM element</dd>
</dl>
</blockquote>
<p>
<a name="fn-createdomfunc"></a>
<a class="mochidef reference" href="#fn-createdomfunc">createDOMFunc(tag[, attrs[, node[, ...]]])</a>:</p>
<blockquote>
<p>Convenience function to create a partially applied createDOM
function. You'd want to use this if you add additional convenience
functions for creating tags, or if you find yourself creating
a lot of tags with a bunch of the same attributes or contents.</p>
<p>See <a class="mochiref reference" href="#fn-createdom">createDOM</a> for more detailed descriptions of the arguments.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">tag</span></tt>:</dt>
<dd>The name of the tag</dd>
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
<dd>Optionally specify the attributes to apply</dd>
<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
<dd>Optionally specify any children nodes it should have</dd>
<dt><em>returns</em>:</dt>
<dd>function that takes additional arguments and calls
<a class="mochiref reference" href="#fn-createdom">createDOM</a></dd>
</dl>
</blockquote>
<p>
<a name="fn-currentdocument"></a>
<a class="mochidef reference" href="#fn-currentdocument">currentDocument()</a>:</p>
<blockquote>
Return the current <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
be the same as the global <tt class="docutils literal"><span class="pre">document</span></tt> unless <a class="mochiref reference" href="#fn-withdocument">withDocument</a> or
<a class="mochiref reference" href="#fn-withwindow">withWindow</a> is currently executing.</blockquote>
<p>
<a name="fn-currentwindow"></a>
<a class="mochidef reference" href="#fn-currentwindow">currentWindow()</a>:</p>
<blockquote>
Return the current <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
be the same as the global <tt class="docutils literal"><span class="pre">window</span></tt> unless <a class="mochiref reference" href="#fn-withwindow">withWindow</a> is
currently executing.</blockquote>
<p>
<a name="fn-elementdimensions"></a>
<a class="mochidef reference" href="#fn-elementdimensions">elementDimensions(element)</a>:</p>
<blockquote>
Return the absolute pixel width and height of <tt class="docutils literal"><span class="pre">element</span></tt> as an object with
<tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt> is not in the
document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to be looked up with
<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object with
<tt class="docutils literal"><span class="pre">w</span></tt> and/or <tt class="docutils literal"><span class="pre">h</span></tt> properties.</blockquote>
<p>
<a name="fn-elementposition"></a>
<a class="mochidef reference" href="#fn-elementposition">elementPosition(element[, relativeTo={x: 0, y: 0}])</a>:</p>
<blockquote>
<p>Return the absolute pixel position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document as an
object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt>
is not in the document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to
be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially
as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
<p>If <tt class="docutils literal"><span class="pre">relativeTo</span></tt> is given, then its coordinates are subtracted from
the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt>, e.g.:</p>
<pre class="literal-block">
var elemPos = elementPosition(elem);
var anotherElemPos = elementPosition(anotherElem);
var relPos = elementPosition(elem, anotherElem);
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
assert( relPos.y == (elemPos.y - anotherElemPos.y) );
</pre>
<p><tt class="docutils literal"><span class="pre">relativeTo</span></tt> may be specified as a string to be looked up with
<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object
with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
</blockquote>
<p>
<a name="fn-emithtml"></a>
<a class="mochidef reference" href="#fn-emithtml">emitHTML(dom[, lst])</a>:</p>
<blockquote>
<p>Convert a DOM tree to an <tt class="docutils literal"><span class="pre">Array</span></tt> of HTML string fragments</p>
<p>You probably want to use <a class="mochiref reference" href="#fn-tohtml">toHTML</a> instead.</p>
</blockquote>
<p>
<a name="fn-escapehtml"></a>
<a class="mochidef reference" href="#fn-escapehtml">escapeHTML(s)</a>:</p>
<blockquote>
Make a string safe for HTML, converting the usual suspects (lt,
gt, quot, apos, amp)</blockquote>
<p>
<a name="fn-focusonload"></a>
<a class="mochidef reference" href="#fn-focusonload">focusOnLoad(element)</a>:</p>
<blockquote>
Add an onload event to focus the given element</blockquote>
<p>
<a name="fn-formcontents"></a>
<a class="mochidef reference" href="#fn-formcontents">formContents(elem)</a>:</p>
<blockquote>
Search the DOM tree, starting at <tt class="docutils literal"><span class="pre">elem</span></tt>, for any elements with a
<tt class="docutils literal"><span class="pre">name</span></tt> and <tt class="docutils literal"><span class="pre">value</span></tt> attribute. Return a 2-element <tt class="docutils literal"><span class="pre">Array</span></tt> of
<tt class="docutils literal"><span class="pre">names</span></tt> and <tt class="docutils literal"><span class="pre">values</span></tt> suitable for use with
<a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a>.</blockquote>
<p>
<a name="fn-getelement"></a>
<a class="mochidef reference" href="#fn-getelement">getElement(id[, ...])</a>:</p>
<blockquote>
<p>A small quick little function to encapsulate the <tt class="docutils literal"><span class="pre">getElementById</span></tt>
method. It includes a check to ensure we can use that method.</p>
<p>If the id isn't a string, it will be returned as-is.</p>
<p>Also available as <a class="mochiref reference" href="#fn-$">$(...)</a> for convenience and compatibility with
other JavaScript frameworks.</p>
<p>If multiple arguments are given, an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned.</p>
</blockquote>
<p>
<a name="fn-getelementsbytagandclassname"></a>
<a class="mochidef reference" href="#fn-getelementsbytagandclassname">getElementsByTagAndClassName(tagName, className, parent=document)</a>:</p>
<blockquote>
<p>Returns an array of elements in <tt class="docutils literal"><span class="pre">parent</span></tt> that match the tag name
and class name provided. If <tt class="docutils literal"><span class="pre">parent</span></tt> is a string, it will be looked
up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
<p>If <tt class="docutils literal"><span class="pre">tagName</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt> or <tt class="docutils literal"><span class="pre">&quot;*&quot;</span></tt>, all elements will be searched
for the matching class.</p>
<p>If <tt class="docutils literal"><span class="pre">className</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, all elements matching the provided tag are
returned.</p>
</blockquote>
<p>
<a name="fn-getnodeattribute"></a>
<a class="mochidef reference" href="#fn-getnodeattribute">getNodeAttribute(node, attr)</a>:</p>
<blockquote>
<p>Get the value of the given attribute for a DOM element without
ever raising an exception (will return <tt class="docutils literal"><span class="pre">null</span></tt> on exception).</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to update (if a string is given,
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
<dd><p class="first">The name of the attribute</p>
<p class="last">Note that it will do the right thing for IE, so don't do
the <tt class="docutils literal"><span class="pre">class</span></tt> -&gt; <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
</dd>
<dt><em>returns</em>:</dt>
<dd>The attribute's value, or <tt class="docutils literal"><span class="pre">null</span></tt></dd>
</dl>
</blockquote>
<p>
<a name="fn-getviewportdimensions"></a>
<a class="mochidef reference" href="#fn-getviewportdimensions">getViewportDimensions()</a>:</p>
<blockquote>
Return the pixel width and height of the viewport as an object with <tt class="docutils literal"><span class="pre">w</span></tt>
and <tt class="docutils literal"><span class="pre">h</span></tt> properties. <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</blockquote>
<p>
<a name="fn-haselementclass"></a>
<a class="mochidef reference" href="#fn-haselementclass">hasElementClass(element, className[, ...])</a>:</p>
<blockquote>
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">className</span></tt> is found on the <tt class="docutils literal"><span class="pre">element</span></tt>.
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
are also acceptable.</blockquote>
<p>
<a name="fn-hideelement"></a>
<a class="mochidef reference" href="#fn-hideelement">hideElement(element, ...)</a>:</p>
<blockquote>
<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
<pre class="literal-block">
partial(setDisplayForElement, &quot;none&quot;)
</pre>
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
show/hide mechanism, and a CSS based alternative, see
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
</blockquote>
<p>
<a name="fn-registerdomconverter"></a>
<a class="mochidef reference" href="#fn-registerdomconverter">registerDOMConverter(name, check, wrap[, override])</a>:</p>
<blockquote>
Register an adapter to convert objects that match <tt class="docutils literal"><span class="pre">check(obj,</span> <span class="pre">ctx)</span></tt>
to a DOM element, or something that can be converted to a DOM
element (i.e. number, bool, string, function, iterable).</blockquote>
<p>
<a name="fn-removeelement"></a>
<a class="mochidef reference" href="#fn-removeelement">removeElement(node)</a>:</p>
<blockquote>
<p>Remove and return <tt class="docutils literal"><span class="pre">node</span></tt> from a DOM tree. This is technically
just a convenience for <a class="mochiref reference" href="#fn-swapdom">swapDOM(node, null)</a>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>the DOM element (or string id of one) to be removed</dd>
<dt><em>returns</em></dt>
<dd>The removed element</dd>
</dl>
</blockquote>
<p>
<a name="fn-removeelementclass"></a>
<a class="mochidef reference" href="#fn-removeelementclass">removeElementClass(element, className)</a>:</p>
<blockquote>
Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> does not have <tt class="docutils literal"><span class="pre">className</span></tt> set as part
of its class attribute. This will not disturb other class names.
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
are also acceptable.</blockquote>
<p>
<a name="fn-replacechildnodes"></a>
<a class="mochidef reference" href="#fn-replacechildnodes">replaceChildNodes(node[, childNode[, ...]])</a>:</p>
<blockquote>
<p>Remove all children from the given DOM element, then append any given
childNodes to it (by calling <a class="mochiref reference" href="#fn-appendchildnodes">appendChildNodes</a>).</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to add children to
(if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
<dd>All additional arguments, if any, will be coerced into DOM
nodes that are appended as children using the
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
<dt><em>returns</em>:</dt>
<dd>The given DOM element</dd>
</dl>
</blockquote>
<p>
<a name="fn-scrapetext"></a>
<a class="mochidef reference" href="#fn-scrapetext">scrapeText(node[, asArray=false])</a>:</p>
<blockquote>
<p>Walk a DOM tree in-order and scrape all of the text out of it as a
<tt class="docutils literal"><span class="pre">string</span></tt>.</p>
<p>If <tt class="docutils literal"><span class="pre">asArray</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned with
each individual text node. These two are equivalent:</p>
<pre class="literal-block">
assert( scrapeText(node) == scrapeText(node, true).join(&quot;&quot;) );
</pre>
</blockquote>
<p>
<a name="fn-setdisplayforelement"></a>
<a class="mochidef reference" href="#fn-setdisplayforelement">setDisplayForElement(display, element[, ...])</a>:</p>
<blockquote>
<p>Change the <tt class="docutils literal"><span class="pre">style.display</span></tt> for the given element(s). Usually
used as the partial forms:</p>
<ul class="simple">
<li><a class="mochiref reference" href="#fn-showelement">showElement(element, ...)</a></li>
<li><a class="mochiref reference" href="#fn-hideelement">hideElement(element, ...)</a></li>
</ul>
<p>Elements are looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
are acceptable.</p>
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
show/hide mechanism, and a CSS based alternative, see
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
</blockquote>
<p>
<a name="fn-setelementclass"></a>
<a class="mochidef reference" href="#fn-setelementclass">setElementClass(element, className)</a>:</p>
<blockquote>
Set the entire class attribute of <tt class="docutils literal"><span class="pre">element</span></tt> to <tt class="docutils literal"><span class="pre">className</span></tt>.
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
are also acceptable.</blockquote>
<p>
<a name="fn-setelementdimensions"></a>
<a class="mochidef reference" href="#fn-setelementdimensions">setElementDimensions(element, dimensions[, units='px'])</a>:</p>
<blockquote>
<p>Sets the dimensions of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to update (if a string is given,
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">dimensions</span></tt>:</dt>
<dd>An object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties</dd>
<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
</dl>
</blockquote>
<p>
<a name="fn-setelementposition"></a>
<a class="mochidef reference" href="#fn-setelementposition">setElementPosition(element, position[, units='px'])</a>:</p>
<blockquote>
<p>Sets the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to update (if a string is given,
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">position</span></tt>:</dt>
<dd>An object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties</dd>
<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
</dl>
</blockquote>
<p>
<a name="fn-setnodeattribute"></a>
<a class="mochidef reference" href="#fn-setnodeattribute">setNodeAttribute(node, attr, value)</a>:</p>
<blockquote>
<p>Set the value of the given attribute for a DOM element without
ever raising an exception (will return null on exception). If
setting more than one attribute, you should use
<a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to update (if a string is given,
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
<dd><p class="first">The name of the attribute</p>
<p class="last">Note that it will do the right thing for IE, so don't do
the <tt class="docutils literal"><span class="pre">class</span></tt> -&gt; <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
</dd>
<dt><tt class="docutils literal"><span class="pre">value</span></tt>:</dt>
<dd>The value of the attribute, may be an object to be merged
(e.g. for setting style).</dd>
<dt><em>returns</em>:</dt>
<dd>The given DOM element or <tt class="docutils literal"><span class="pre">null</span></tt> on failure</dd>
</dl>
</blockquote>
<p>
<a name="fn-setopacity"></a>
<a class="mochidef reference" href="#fn-setopacity">setOpacity(element, opacity)</a>:</p>
<blockquote>
Sets <tt class="docutils literal"><span class="pre">opacity</span></tt> for <tt class="docutils literal"><span class="pre">element</span></tt>. Valid <tt class="docutils literal"><span class="pre">opacity</span></tt> values range from 0
(invisible) to 1 (opaque). <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</blockquote>
<p>
<a name="fn-showelement"></a>
<a class="mochidef reference" href="#fn-showelement">showElement(element, ...)</a>:</p>
<blockquote>
<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
<pre class="literal-block">
partial(setDisplayForElement, &quot;block&quot;)
</pre>
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
show/hide mechanism, and a CSS based alternative, see
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
</blockquote>
<p>
<a name="fn-swapdom"></a>
<a class="mochidef reference" href="#fn-swapdom">swapDOM(dest, src)</a>:</p>
<blockquote>
<p>Replace <tt class="docutils literal"><span class="pre">dest</span></tt> in a DOM tree with <tt class="docutils literal"><span class="pre">src</span></tt>, returning <tt class="docutils literal"><span class="pre">src</span></tt>.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">dest</span></tt>:</dt>
<dd>a DOM element (or string id of one) to be replaced</dd>
<dt><tt class="docutils literal"><span class="pre">src</span></tt>:</dt>
<dd>the DOM element (or string id of one) to replace it with, or
<tt class="docutils literal"><span class="pre">null</span></tt> if <tt class="docutils literal"><span class="pre">dest</span></tt> is to be removed (replaced with nothing).</dd>
<dt><em>returns</em>:</dt>
<dd>a DOM element (<tt class="docutils literal"><span class="pre">src</span></tt>)</dd>
</dl>
</blockquote>
<p>
<a name="fn-swapelementclass"></a>
<a class="mochidef reference" href="#fn-swapelementclass">swapElementClass(element, fromClass, toClass)</a>:</p>
<blockquote>
If <tt class="docutils literal"><span class="pre">fromClass</span></tt> is set on <tt class="docutils literal"><span class="pre">element</span></tt>, replace it with <tt class="docutils literal"><span class="pre">toClass</span></tt>.
This will not disturb other classes on that element.
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
are also acceptable.</blockquote>
<p>
<a name="fn-toggleelementclass"></a>
<a class="mochidef reference" href="#fn-toggleelementclass">toggleElementClass(className[, element[, ...]])</a>:</p>
<blockquote>
Toggle the presence of a given <tt class="docutils literal"><span class="pre">className</span></tt> in the class attribute
of all given elements. All elements will be looked up with
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are acceptable.</blockquote>
<p>
<a name="fn-tohtml"></a>
<a class="mochidef reference" href="#fn-tohtml">toHTML(dom)</a>:</p>
<blockquote>
Convert a DOM tree to a HTML string using <a class="mochiref reference" href="#fn-emithtml">emitHTML</a></blockquote>
<p>
<a name="fn-updatenodeattributes"></a>
<a class="mochidef reference" href="#fn-updatenodeattributes">updateNodeAttributes(node, attrs)</a>:</p>
<blockquote>
<p>Update the attributes of a DOM element from a given object.</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
<dd>A reference to the DOM element to update (if a string is given,
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
<dd><p class="first">An object whose properties will be used to set the attributes
(e.g. <tt class="docutils literal"><span class="pre">{'class':</span> <span class="pre">'invisible'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
attributes need to be set. If an object is given for the
attribute value (e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">{'display':</span> <span class="pre">'block'}}</span></tt>)
then <a class="mochiref reference" href="Base.html#fn-updatetree">MochiKit.Base.updatetree</a> will be used to set that
attribute.</p>
<p class="last">Note that it will do the right thing for IE, so don't do
the <tt class="docutils literal"><span class="pre">class</span></tt> -&gt; <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself, and it deals with
setting &quot;on...&quot; event handlers correctly.</p>
</dd>
<dt><em>returns</em>:</dt>
<dd>The given DOM element</dd>
</dl>
</blockquote>
<p>
<a name="fn-withwindow"></a>
<a class="mochidef reference" href="#fn-withwindow">withWindow(win, func)</a>:</p>
<blockquote>
<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win</span></tt> and
the <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win.document</span></tt>. When
<tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a> will be
restored to its previous state.</p>
<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
</blockquote>
<p>
<a name="fn-withdocument"></a>
<a class="mochidef reference" href="#fn-withdocument">withDocument(doc, func)</a>:</p>
<blockquote>
<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">doc</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">doc</span></tt>.
When <tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a>
will be restored to its previous state.</p>
<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id5" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id5">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> Nevow, a web application construction kit for Python: <a class="reference" href="http://nevow.com/">http://nevow.com/</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id6">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> nevow.stan is a domain specific language for Python
(read as &quot;crazy getitem/call overloading abuse&quot;) that Donovan and I
schemed up at PyCon 2003 at this super ninja Python/C++ programmer's
(David Abrahams) hotel room. Donovan later inflicted this upon the
masses in Nevow. Check out the Divmod project page for some
examples: <a class="reference" href="http://nevow.com/Nevow2004Tutorial.html">http://nevow.com/Nevow2004Tutorial.html</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,125 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.DateTime - &quot;what time is it anyway?&quot;</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.DateTime - &quot;what time is it anyway?&quot;</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
stringDate = toISOTimestamp(new Date());
dateObject = isoTimestamp(stringDate);
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>Remote servers don't give you JavaScript Date objects, and they certainly
don't want them from you, so you need to deal with string representations
of dates and timestamps. MochiKit.Date does that.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<p>None.</p>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-isodate"></a>
<a class="mochidef reference" href="#fn-isodate">isoDate(str)</a>:</p>
<blockquote>
Convert an ISO 8601 date (YYYY-MM-DD) to a <tt class="docutils literal"><span class="pre">Date</span></tt> object.</blockquote>
<p>
<a name="fn-isotimestamp"></a>
<a class="mochidef reference" href="#fn-isotimestamp">isoTimestamp(str)</a>:</p>
<blockquote>
<p>Convert any ISO 8601 <a class="footnote-reference" href="#id3" id="id1" name="id1">[1]</a> timestamp (or something reasonably close to it)
to a <tt class="docutils literal"><span class="pre">Date</span></tt> object. Will accept the &quot;de facto&quot; form:</p>
<blockquote>
YYYY-MM-DD hh:mm:ss</blockquote>
<p>or (the proper form):</p>
<blockquote>
YYYY-MM-DDThh:mm:ssZ</blockquote>
<p>If a time zone designator (&quot;Z&quot; or &quot;[+-]HH:MM&quot;) is not present, then the
local timezone is used.</p>
</blockquote>
<p>
<a name="fn-toisotime"></a>
<a class="mochidef reference" href="#fn-toisotime">toISOTime(date)</a>:</p>
<blockquote>
Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to a string in the form of hh:mm:ss</blockquote>
<p>
<a name="fn-toisotimestamp"></a>
<a class="mochidef reference" href="#fn-toisotimestamp">toISOTimestamp(date, realISO=false)</a>:</p>
<blockquote>
<p>Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to something that's ALMOST but not quite an
ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be:</p>
<blockquote>
YYYY-MM-DDThh:mm:ssZ</blockquote>
<p>However, we see junk in SQL and other places that looks like this:</p>
<blockquote>
YYYY-MM-DD hh:mm:ss</blockquote>
<p>So, this function returns the latter form, despite its name, unless
you pass <tt class="docutils literal"><span class="pre">true</span></tt> for <tt class="docutils literal"><span class="pre">realISO</span></tt>.</p>
</blockquote>
<p>
<a name="fn-toisodate"></a>
<a class="mochidef reference" href="#fn-toisodate">toISODate(date)</a>:</p>
<blockquote>
Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an ISO 8601 <a class="footnote-reference" href="#id3" id="id2" name="id2">[1]</a> date string (YYYY-MM-DD)</blockquote>
<p>
<a name="fn-americandate"></a>
<a class="mochidef reference" href="#fn-americandate">americanDate(str)</a>:</p>
<blockquote>
Converts a MM/DD/YYYY date to a <tt class="docutils literal"><span class="pre">Date</span></tt> object</blockquote>
<p>
<a name="fn-topaddedamericandate"></a>
<a class="mochidef reference" href="#fn-topaddedamericandate">toPaddedAmericanDate(date)</a>:</p>
<blockquote>
Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an MM/DD/YYYY date, e.g. 01/01/2001</blockquote>
<p>
<a name="fn-toamericandate"></a>
<a class="mochidef reference" href="#fn-toamericandate">toAmericanDate(date)</a>:</p>
<blockquote>
Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an M/D/YYYY date, e.g. 1/1/2001</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id3" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id3">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>)</em> W3C profile of ISO 8601: <a class="reference" href="http://www.w3.org/TR/NOTE-datetime">http://www.w3.org/TR/NOTE-datetime</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,241 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Format - string formatting goes here</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Format - string formatting goes here</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
assert( truncToFixed(0.12345, 4) == &quot;0.1234&quot; );
assert( roundToFixed(0.12345, 4) == &quot;0.1235&quot; );
assert( twoDigitAverage(1, 0) == &quot;0&quot; );
assert( twoDigitFloat(1.2345) == &quot;1.23&quot; );
assert( twoDigitFloat(1) == &quot;1&quot; );
assert( percentFormat(1.234567) == &quot;123.46%&quot; );
assert( numberFormatter(&quot;###,###%&quot;)(125) == &quot;12,500%&quot; );
assert( numberFormatter(&quot;##.000&quot;)(1.25) == &quot;1.250&quot; );
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>Formatting strings and stringifying numbers is boring, so a couple useful
functions in that domain live here.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<p>None.</p>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<div class="section">
<h2><a id="formatting-numbers" name="formatting-numbers">Formatting Numbers</a></h2>
<p>MochiKit provides an extensible number formatting facility, modeled loosely
after the Number Format Pattern Syntax <a class="footnote-reference" href="#id2" id="id1" name="id1">[1]</a> from Java.
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(pattern[, placeholder=&quot;&quot;[, locale=&quot;default&quot;])</a>
returns a function that converts Number to string using the given information.
<tt class="docutils literal"><span class="pre">pattern</span></tt> is a string consisting of the following symbols:</p>
<table border="1" class="docutils">
<colgroup>
<col width="15%" />
<col width="85%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Symbol</th>
<th class="head">Meaning</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><tt class="docutils literal"><span class="pre">-</span></tt></td>
<td>If given, used as the position of the minus sign
for negative numbers. If not given, the position
to the left of the first number placeholder is used.</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">#</span></tt></td>
<td>The placeholder for a number that does not imply zero
padding.</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">0</span></tt></td>
<td>The placeholder for a number that implies zero padding.
If it is used to the right of a decimal separator, it
implies trailing zeros, otherwise leading zeros.</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">,</span></tt></td>
<td>The placeholder for a &quot;thousands separator&quot;. May be used
at most once, and it must be to the left of a decimal
separator. Will be replaced by <tt class="docutils literal"><span class="pre">locale.separator</span></tt> in the
result (the default is also <tt class="docutils literal"><span class="pre">,</span></tt>).</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">.</span></tt></td>
<td>The decimal separator. The quantity of <tt class="docutils literal"><span class="pre">#</span></tt> or <tt class="docutils literal"><span class="pre">0</span></tt>
after the decimal separator will determine the precision of
the result. If no decimal separator is present, the
fractional precision is <tt class="docutils literal"><span class="pre">0</span></tt> -- meaning that it will be
rounded to the nearest integer.</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">%</span></tt></td>
<td>If present, the number will be multiplied by <tt class="docutils literal"><span class="pre">100</span></tt> and
the <tt class="docutils literal"><span class="pre">%</span></tt> will be replaced by <tt class="docutils literal"><span class="pre">locale.percent</span></tt>.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-formatlocale"></a>
<a class="mochidef reference" href="#fn-formatlocale">formatLocale(locale=&quot;default&quot;)</a>:</p>
<blockquote>
Return a locale object for the given locale. <tt class="docutils literal"><span class="pre">locale</span></tt> may be either a
string, which is looked up in the <tt class="docutils literal"><span class="pre">MochiKit.Format.LOCALE</span></tt> object, or
a locale object. If no locale is given, <tt class="docutils literal"><span class="pre">LOCALE.default</span></tt> is used
(equivalent to <tt class="docutils literal"><span class="pre">LOCALE.en_US</span></tt>).</blockquote>
<p>
<a name="fn-lstrip"></a>
<a class="mochidef reference" href="#fn-lstrip">lstrip(str, chars=&quot;\s&quot;)</a>:</p>
<blockquote>
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading whitespace stripped.</p>
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
</blockquote>
<p>
<a name="fn-numberformatter"></a>
<a class="mochidef reference" href="#fn-numberformatter">numberFormatter(pattern, placeholder=&quot;&quot;, locale=&quot;default&quot;)</a>:</p>
<blockquote>
<p>Return a function <tt class="docutils literal"><span class="pre">formatNumber(aNumber)</span></tt> that formats numbers
as a string according to the given pattern, placeholder and locale.</p>
<p><tt class="docutils literal"><span class="pre">pattern</span></tt> is a string that describes how the numbers should be formatted,
for more information see <a class="reference" href="#formatting-numbers">Formatting Numbers</a>.</p>
<p><tt class="docutils literal"><span class="pre">locale</span></tt> is a string of a known locale (en_US, de_DE, fr_FR, default) or
an object with the following fields:</p>
<table border="1" class="docutils">
<colgroup>
<col width="16%" />
<col width="84%" />
</colgroup>
<tbody valign="top">
<tr><td>separator</td>
<td>The &quot;thousands&quot; separator for this locale (en_US is &quot;,&quot;)</td>
</tr>
<tr><td>decimal</td>
<td>The decimal separator for this locale (en_US is &quot;.&quot;)</td>
</tr>
<tr><td>percent</td>
<td>The percent symbol for this locale (en_US is &quot;%&quot;)</td>
</tr>
</tbody>
</table>
</blockquote>
<p>
<a name="fn-percentformat"></a>
<a class="mochidef reference" href="#fn-percentformat">percentFormat(someFloat)</a>:</p>
<blockquote>
<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf(&quot;%.2f%%&quot;,</span> <span class="pre">someFloat</span> <span class="pre">*</span> <span class="pre">100)</span></tt></p>
<p>In new code, you probably want to use:
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(&quot;#.##%&quot;)(someFloat)</a> instead.</p>
</blockquote>
<p>
<a name="fn-roundtofixed"></a>
<a class="mochidef reference" href="#fn-roundtofixed">roundToFixed(aNumber, precision)</a>:</p>
<blockquote>
<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, rounded to <tt class="docutils literal"><span class="pre">precision</span></tt>
digits with trailing zeros. This is similar to
<tt class="docutils literal"><span class="pre">Number.toFixed(aNumber,</span> <span class="pre">precision)</span></tt>, but this has implementation
consistent rounding behavior (some versions of Safari round 0.5 down!)
and also includes preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less than <tt class="docutils literal"><span class="pre">1</span></tt> (Safari,
again).</p>
<p>For example, <a class="mochiref reference" href="#fn-roundtofixed">roundToFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.14</span></tt> on every
supported platform, where some return <tt class="docutils literal"><span class="pre">.13</span></tt> for <tt class="docutils literal"><span class="pre">(0.1357).toFixed(2)</span></tt>.</p>
</blockquote>
<p>
<a name="fn-rstrip"></a>
<a class="mochidef reference" href="#fn-rstrip">rstrip(str, chars=&quot;\s&quot;)</a>:</p>
<blockquote>
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with trailing whitespace stripped.</p>
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
</blockquote>
<p>
<a name="fn-strip"></a>
<a class="mochidef reference" href="#fn-strip">strip(str, chars=&quot;\s&quot;)</a>:</p>
<blockquote>
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading and trailing whitespace
stripped (equivalent to <a class="mochiref reference" href="#fn-lstrip">lstrip(rstrip(str, chars), chars)</a>).</p>
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
</blockquote>
<p>
<a name="fn-trunctofixed"></a>
<a class="mochidef reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a>:</p>
<blockquote>
<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, truncated to <tt class="docutils literal"><span class="pre">precision</span></tt>
digits with trailing zeros. This is similar to
<tt class="docutils literal"><span class="pre">aNumber.toFixed(precision)</span></tt>, but this truncates rather than rounds and
has implementation consistent behavior for numbers less than 1.
Specifically, <a class="mochiref reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a> will always have a
preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less than <tt class="docutils literal"><span class="pre">1</span></tt>.</p>
<p>For example, <a class="mochiref reference" href="#fn-tofixed">toFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.13</span></tt>.</p>
</blockquote>
<p>
<a name="fn-twodigitaverage"></a>
<a class="mochidef reference" href="#fn-twodigitaverage">twoDigitAverage(numerator, denominator)</a>:</p>
<blockquote>
<p>Calculate an average from a numerator and a denominator and return
it as a string with two digits of precision (e.g. &quot;1.23&quot;).</p>
<p>If the denominator is 0, &quot;0&quot; will be returned instead of <tt class="docutils literal"><span class="pre">NaN</span></tt>.</p>
</blockquote>
<p>
<a name="fn-twodigitfloat"></a>
<a class="mochidef reference" href="#fn-twodigitfloat">twoDigitFloat(someFloat)</a>:</p>
<blockquote>
<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf(&quot;%.2f&quot;,</span> <span class="pre">someFloat)</span></tt></p>
<p>In new code, you probably want to use
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(&quot;#.##&quot;)(someFloat)</a> instead.</p>
</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id2">[1]</a></td><td>Java Number Format Pattern Syntax:
<a class="reference" href="http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html">http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,372 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
theSum = sum(takewhile(
partial(operator.gt, 10),
imap(
partial(operator.mul, 2),
count()
)
)
));
assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>All of the functional programming missing from <a class="mochiref reference" href="Base.html">MochiKit.Base</a> lives
here. The functionality in this module is largely inspired by Python's iteration
protocol <a class="footnote-reference" href="#id4" id="id1" name="id1">[1]</a>, and the itertools module <a class="footnote-reference" href="#id5" id="id2" name="id2">[2]</a>.</p>
<p>MochiKit.Iter defines a standard way to iterate over anything, that you can
extend with <a class="mochiref reference" href="#fn-registeriterator">registerIterator</a>, or by implementing the <tt class="docutils literal"><span class="pre">.iter()</span></tt>
protocol. Iterators are lazy, so it can potentially be cheaper to build a
filter chain of iterators than to build lots of intermediate arrays.
Especially when the data set is very large, but the result is not.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<div class="section">
<h2><a id="iteration-for-javascript" name="iteration-for-javascript">Iteration for JavaScript</a></h2>
<p>The best overview right now is in my Iteration for JavaScript <a class="footnote-reference" href="#id6" id="id3" name="id3">[3]</a> blog entry.
This information will migrate here eventually.</p>
</div>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="errors" name="errors">Errors</a></h2>
<p>
<a name="fn-stopiteration"></a>
<a class="mochidef reference" href="#fn-stopiteration">StopIteration</a>:</p>
<blockquote>
The singleton <a class="mochiref reference" href="Base.html#fn-namederror">MochiKit.Base.NamedError</a> that signifies the end
of an iterator</blockquote>
</div>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-applymap"></a>
<a class="mochidef reference" href="#fn-applymap">applymap(fun, seq[, self])</a>:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">applymap(fun,</span> <span class="pre">seq)</span></tt> --&gt;</dt>
<dd>fun.apply(self, seq0), fun.apply(self, seq1), ...</dd>
</dl>
</blockquote>
<p>
<a name="fn-chain"></a>
<a class="mochidef reference" href="#fn-chain">chain(p, q[, ...])</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">chain(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --&gt; p0, p1, ... plast, q0, q1, ...</blockquote>
<p>
<a name="fn-count"></a>
<a class="mochidef reference" href="#fn-count">count(n=0)</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">count(n=0)</span></tt> --&gt; n, n + 1, n + 2, ...</blockquote>
<p>
<a name="fn-cycle"></a>
<a class="mochidef reference" href="#fn-cycle">cycle(p)</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">cycle(p)</span></tt> --&gt; p0, p1, ... plast, p0, p1, ...</blockquote>
<p>
<a name="fn-dropwhile"></a>
<a class="mochidef reference" href="#fn-dropwhile">dropwhile(pred, seq)</a>:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">dropwhile(pred,</span> <span class="pre">seq)</span></tt> --&gt; seq[n], seq[n + 1], starting when</dt>
<dd>pred(seq[n]) fails</dd>
</dl>
</blockquote>
<p>
<a name="fn-every"></a>
<a class="mochidef reference" href="#fn-every">every(iterable, func)</a>:</p>
<blockquote>
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for every item in
<tt class="docutils literal"><span class="pre">iterable</span></tt>.</blockquote>
<p>
<a name="fn-exhaust"></a>
<a class="mochidef reference" href="#fn-exhaust">exhaust(iterable)</a>:</p>
<blockquote>
Exhausts an iterable without saving the results anywhere,
like <a class="mochiref reference" href="#fn-list">list(iterable)</a> when you don't care what the output is.</blockquote>
<p>
<a name="fn-foreach"></a>
<a class="mochidef reference" href="#fn-foreach">forEach(iterable, func[, self])</a>:</p>
<blockquote>
Call <tt class="docutils literal"><span class="pre">func</span></tt> for each item in <tt class="docutils literal"><span class="pre">iterable</span></tt>, and don't save the results.</blockquote>
<p>
<a name="fn-groupby"></a>
<a class="mochidef reference" href="#fn-groupby">groupby(iterable[, keyfunc])</a>:</p>
<blockquote>
<p>Make an iterator that returns consecutive keys and groups from the
iterable. The key is a function computing a key value for each element.
If not specified or is None, key defaults to an identity function and
returns the element unchanged. Generally, the iterable needs to already be
sorted on the same key function.</p>
<p>The returned group is itself an iterator that shares the underlying
iterable with <a class="mochiref reference" href="#fn-groupby">groupby()</a>. Because the source is shared, when the
groupby object is advanced, the previous group is no longer visible.
So, if that data is needed later, it should be stored as an array:</p>
<pre class="literal-block">
var groups = [];
var uniquekeys = [];
forEach(groupby(data, keyfunc), function (key_group) {
groups.push(list(key_group[1]));
uniquekeys.push(key_group[0]);
});
</pre>
<p>As a convenience, <a class="mochiref reference" href="#fn-groupby_as_array">groupby_as_array()</a> is provided to suit the above
use case.</p>
</blockquote>
<p>
<a name="fn-groupby_as_array"></a>
<a class="mochidef reference" href="#fn-groupby_as_array">groupby_as_array(iterable[, keyfunc])</a>:</p>
<blockquote>
Perform the same task as <a class="mochiref reference" href="#fn-groupby">groupby()</a>, except return an array of
arrays instead of an iterator of iterators.</blockquote>
<p>
<a name="fn-iextend"></a>
<a class="mochidef reference" href="#fn-iextend">iextend(lst, iterable)</a>:</p>
<blockquote>
Just like <a class="mochiref reference" href="#fn-list">list(iterable)</a>, except it pushes results on <tt class="docutils literal"><span class="pre">lst</span></tt>
rather than creating a new one.</blockquote>
<p>
<a name="fn-ifilter"></a>
<a class="mochidef reference" href="#fn-ifilter">ifilter(pred, seq)</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">ifilter(pred,</span> <span class="pre">seq)</span></tt> --&gt; elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt></blockquote>
<p>
<a name="fn-ifilterfalse"></a>
<a class="mochidef reference" href="#fn-ifilterfalse">ifilterfalse(pred, seq)</a>:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">ifilterfalse(pred,</span> <span class="pre">seq)</span></tt> --&gt; elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is</dt>
<dd><tt class="docutils literal"><span class="pre">false</span></tt></dd>
</dl>
</blockquote>
<p>
<a name="fn-imap"></a>
<a class="mochidef reference" href="#fn-imap">imap(fun, p, q[, ...])</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">imap(fun,</span> <span class="pre">p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --&gt; fun(p0, q0, ...), fun(p1, q1, ...), ...</blockquote>
<p>
<a name="fn-islice"></a>
<a class="mochidef reference" href="#fn-islice">islice(seq, [start,] stop[, step])</a>:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">islice(seq,</span> <span class="pre">[start,]</span> <span class="pre">stop[,</span> <span class="pre">step])</span></tt> --&gt; elements from</dt>
<dd>seq[start:stop:step] (in Python slice syntax)</dd>
</dl>
</blockquote>
<p>
<a name="fn-iter"></a>
<a class="mochidef reference" href="#fn-iter">iter(iterable[, sentinel])</a>:</p>
<blockquote>
<p>Convert the given argument to an iterator (object implementing
<tt class="docutils literal"><span class="pre">.next()</span></tt>).</p>
<ol class="arabic simple">
<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator (implements <tt class="docutils literal"><span class="pre">.next()</span></tt>), then it will
be returned as-is.</li>
<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator factory (implements <tt class="docutils literal"><span class="pre">.iter()</span></tt>), then
the result of <tt class="docutils literal"><span class="pre">iterable.iter()</span></tt> will be returned.</li>
<li>Otherwise, the iterator factory <a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a>
is used to find a match.</li>
<li>If no factory is found, it will throw <tt class="docutils literal"><span class="pre">TypeError</span></tt></li>
</ol>
<p>Built-in iterator factories are present for Array-like objects, and
objects that implement the <tt class="docutils literal"><span class="pre">iterateNext</span></tt> protocol (e.g. the result of
Mozilla's <tt class="docutils literal"><span class="pre">document.evaluate</span></tt>).</p>
<p>When used directly, using an iterator should look like this:</p>
<pre class="literal-block">
var it = iter(iterable);
try {
while (var o = it.next()) {
// use o
}
} catch (e) {
if (e != StopIteration) {
throw e;
}
// pass
}
</pre>
<p>This is ugly, so you should use the higher order functions to work
with iterators whenever possible.</p>
</blockquote>
<p>
<a name="fn-izip"></a>
<a class="mochidef reference" href="#fn-izip">izip(p, q[, ...])</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">izip(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --&gt; [p0, q0, ...], [p1, q1, ...], ...</blockquote>
<p>
<a name="fn-list"></a>
<a class="mochidef reference" href="#fn-list">list(iterable)</a>:</p>
<blockquote>
Convert <tt class="docutils literal"><span class="pre">iterable</span></tt> to a new <tt class="docutils literal"><span class="pre">Array</span></tt></blockquote>
<p>
<a name="fn-next"></a>
<a class="mochidef reference" href="#fn-next">next(iterator)</a>:</p>
<blockquote>
Return <tt class="docutils literal"><span class="pre">iterator.next()</span></tt></blockquote>
<p>
<a name="fn-range"></a>
<a class="mochidef reference" href="#fn-range">range([start,] stop[, step])</a>:</p>
<blockquote>
<p>Return an iterator containing an arithmetic progression of integers.</p>
<p><tt class="docutils literal"><span class="pre">range(i,</span> <span class="pre">j)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([i, i + 1, i + 2, ..., j - 1])</a></p>
<p><tt class="docutils literal"><span class="pre">start</span></tt> (!) defaults to <tt class="docutils literal"><span class="pre">0</span></tt>. When <tt class="docutils literal"><span class="pre">step</span></tt> is given, it specifies the
increment (or decrement). The end point is omitted!</p>
<p>For example, <tt class="docutils literal"><span class="pre">range(4)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([0, 1, 2, 3])</a>.
This iterates over exactly the valid indexes for an array of 4 elements.</p>
</blockquote>
<p>
<a name="fn-reduce"></a>
<a class="mochidef reference" href="#fn-reduce">reduce(fn, iterable[, initial])</a>:</p>
<blockquote>
<p>Apply <tt class="docutils literal"><span class="pre">fn(a,</span> <span class="pre">b)</span></tt> cumulatively to the items of an
iterable from left to right, so as to reduce the iterable
to a single value.</p>
<p>For example:</p>
<pre class="literal-block">
reduce(function (a, b) { return x + y; }, [1, 2, 3, 4, 5])
</pre>
<p>calculates:</p>
<pre class="literal-block">
((((1 + 2) + 3) + 4) + 5).
</pre>
<p>If initial is given, it is placed before the items of the sequence
in the calculation, and serves as a default when the sequence is
empty.</p>
<p>Note that the above example could be written more clearly as:</p>
<pre class="literal-block">
reduce(operator.add, [1, 2, 3, 4, 5])
</pre>
<p>Or even simpler:</p>
<pre class="literal-block">
sum([1, 2, 3, 4, 5])
</pre>
</blockquote>
<p>
<a name="fn-registeriteratorfactory"></a>
<a class="mochidef reference" href="#fn-registeriteratorfactory">registerIteratorFactory(name, check, iterfactory[, override])</a>:</p>
<blockquote>
<p>Register an iterator factory for use with the iter function.</p>
<p><tt class="docutils literal"><span class="pre">check</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">a</span></tt> can be
converted into an iterator with <tt class="docutils literal"><span class="pre">iterfactory</span></tt>.</p>
<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns an object with a
<tt class="docutils literal"><span class="pre">.next()</span></tt> method that returns the next value in the sequence.</p>
<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is guaranteed to only be called if <tt class="docutils literal"><span class="pre">check(a)</span></tt>
returns a true value.</p>
<p>If <tt class="docutils literal"><span class="pre">override</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then it will be made the
highest precedence iterator factory. Otherwise, the lowest.</p>
</blockquote>
<p>
<a name="fn-repeat"></a>
<a class="mochidef reference" href="#fn-repeat">repeat(elem[, n])</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">repeat(elem,</span> <span class="pre">[,n])</span></tt> --&gt; elem, elem, elem, ... endlessly or up to n times</blockquote>
<p>
<a name="fn-reversed"></a>
<a class="mochidef reference" href="#fn-reversed">reversed(iterable)</a>:</p>
<blockquote>
Return a reversed array from iterable.</blockquote>
<p>
<a name="fn-some"></a>
<a class="mochidef reference" href="#fn-some">some(iterable, func)</a>:</p>
<blockquote>
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for at least one item in
<tt class="docutils literal"><span class="pre">iterable</span></tt>.</blockquote>
<p>
<a name="fn-sorted"></a>
<a class="mochidef reference" href="#fn-sorted">sorted(iterable[, cmp])</a>:</p>
<blockquote>
Return a sorted array from iterable.</blockquote>
<p>
<a name="fn-sum"></a>
<a class="mochidef reference" href="#fn-sum">sum(iterable, start=0)</a>:</p>
<blockquote>
<p>Returns the sum of a sequence of numbers plus the value
of parameter <tt class="docutils literal"><span class="pre">start</span></tt> (with a default of 0). When the sequence is
empty, returns start.</p>
<p>Equivalent to:</p>
<pre class="literal-block">
reduce(operator.add, iterable, start);
</pre>
</blockquote>
<p>
<a name="fn-takewhile"></a>
<a class="mochidef reference" href="#fn-takewhile">takewhile(pred, seq)</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">takewhile(pred,</span> <span class="pre">seq)</span></tt> --&gt; seq[0], seq[1], ... until pred(seq[n]) fails</blockquote>
<p>
<a name="fn-tee"></a>
<a class="mochidef reference" href="#fn-tee">tee(iterable, n=2)</a>:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">tee(it,</span> <span class="pre">n=2)</span></tt> --&gt; [it1, it2, it3, ... itn] splits one iterator into n</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id4" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id4">[1]</a></td><td>The iteration protocol is described in
PEP 234 - Iterators: <a class="reference" href="http://www.python.org/peps/pep-0234.html">http://www.python.org/peps/pep-0234.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id5" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2" name="id5">[2]</a></td><td>Python's itertools
module: <a class="reference" href="http://docs.python.org/lib/module-itertools.html">http://docs.python.org/lib/module-itertools.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3" name="id6">[3]</a></td><td>Iteration in JavaScript: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,310 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Logging - we're all tired of alert()</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Logging - we're all tired of alert()</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
log(&quot;INFO messages are so boring&quot;);
logDebug(&quot;DEBUG messages are even worse&quot;);
log(&quot;good thing I can pass&quot;, objects, &quot;conveniently&quot;);
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>MochiKit.Logging steals some ideas from Python's logging module <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a>, but
completely forgot about the Java <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> inspiration. This is a KISS module for
logging that provides enough flexibility to do just about anything via
listeners, but without all the cruft.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<div class="section">
<h2><a id="native-console-logging" name="native-console-logging">Native Console Logging</a></h2>
<p>As of MochiKit 1.3, the default logger will log all messages to your browser's
native console. This is currently supported in Safari, Opera 9, and Firefox
when the <a class="reference" href="http://www.joehewitt.com/software/firebug/">FireBug</a> extension is installed.</p>
<p>To disable this behavior:</p>
<pre class="literal-block">
MochiKit.Logging.logger.useNativeLogging = false;
</pre>
</div>
<div class="section">
<h2><a id="bookmarklet-based-debugging" name="bookmarklet-based-debugging">Bookmarklet Based Debugging</a></h2>
<p>JavaScript is at a serious disadvantage without a standard console for
&quot;print&quot; statements. Everything else has one. The closest thing that
you get in a browser environment is the <tt class="docutils literal"><span class="pre">alert</span></tt> function, which is
absolutely evil.</p>
<p>This leaves you with one reasonable solution: do your logging in the page
somehow. The problem here is that you don't want to clutter the page with
debugging tools. The solution to that problem is what we call BBD, or
Bookmarklet Based Debugging <a class="footnote-reference" href="#id8" id="id4" name="id4">[3]</a>.</p>
<p>Simply create a bookmarklet for <a class="reference" href="javascript:MochiKit.Logging.logger.debuggingBookmarklet()">javascript:MochiKit.Logging.logger.debuggingBookmarklet()</a>,
and whack it whenever you want to see what's in the logger. Of course, this
means you must drink the MochiKit.Logging kool-aid. It's tangy and sweet,
don't worry.</p>
<p>Currently this is an ugly <tt class="docutils literal"><span class="pre">alert</span></tt>, but we'll have something spiffy
Real Soon Now, and when we do, you only have to upgrade MochiKit.Logging,
not your bookmarklet!</p>
</div>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="constructors" name="constructors">Constructors</a></h2>
<p>
<a name="fn-logmessage"></a>
<a class="mochidef reference" href="#fn-logmessage">LogMessage(num, level, info)</a>:</p>
<blockquote>
<p>Properties:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
<dd>Identifier for the log message</dd>
<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
<dd>Level of the log message (<tt class="docutils literal"><span class="pre">&quot;INFO&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;WARN&quot;</span></tt>, <tt class="docutils literal"><span class="pre">&quot;DEBUG&quot;</span></tt>,
etc.)</dd>
<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
<dd>All other arguments passed to log function as an <tt class="docutils literal"><span class="pre">Array</span></tt></dd>
<dt><tt class="docutils literal"><span class="pre">timestamp</span></tt>:</dt>
<dd><tt class="docutils literal"><span class="pre">Date</span></tt> object timestamping the log message</dd>
</dl>
</blockquote>
</blockquote>
<p>
<a name="fn-logger"></a>
<a class="mochidef reference" href="#fn-logger">Logger([maxSize])</a>:</p>
<blockquote>
<p>A basic logger object that has a buffer of recent messages
plus a listener dispatch mechanism for &quot;real-time&quot; logging
of important messages.</p>
<p><tt class="docutils literal"><span class="pre">maxSize</span></tt> is the maximum number of entries in the log.
If <tt class="docutils literal"><span class="pre">maxSize</span> <span class="pre">&gt;=</span> <span class="pre">0</span></tt>, then the log will not buffer more than that
many messages. So if you don't like logging at all, be sure to
pass <tt class="docutils literal"><span class="pre">0</span></tt>.</p>
<p>There is a default logger available named &quot;logger&quot;, and several
of its methods are also global functions:</p>
<blockquote>
<tt class="docutils literal"><span class="pre">logger.log</span></tt> -&gt; <tt class="docutils literal"><span class="pre">log</span></tt>
<tt class="docutils literal"><span class="pre">logger.debug</span></tt> -&gt; <tt class="docutils literal"><span class="pre">logDebug</span></tt>
<tt class="docutils literal"><span class="pre">logger.warning</span></tt> -&gt; <tt class="docutils literal"><span class="pre">logWarning</span></tt>
<tt class="docutils literal"><span class="pre">logger.error</span></tt> -&gt; <tt class="docutils literal"><span class="pre">logError</span></tt>
<tt class="docutils literal"><span class="pre">logger.fatal</span></tt> -&gt; <tt class="docutils literal"><span class="pre">logFatal</span></tt></blockquote>
</blockquote>
<p>
<a name="fn-logger.prototype.addlistener"></a>
<a class="mochidef reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener(ident, filter, listener)</a>:</p>
<blockquote>
<p>Add a listener for log messages.</p>
<p><tt class="docutils literal"><span class="pre">ident</span></tt> is a unique identifier that may be used to remove the listener
later on.</p>
<p><tt class="docutils literal"><span class="pre">filter</span></tt> can be one of the following:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">null</span></tt>:</dt>
<dd><tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called for every log message
received.</dd>
<dt><tt class="docutils literal"><span class="pre">string</span></tt>:</dt>
<dd><a class="mochiref reference" href="#fn-loglevelatleast">logLevelAtLeast(filter)</a> will be used as the function
(see below).</dd>
<dt><tt class="docutils literal"><span class="pre">function</span></tt>:</dt>
<dd><tt class="docutils literal"><span class="pre">filter(msg)</span></tt> will be called for every msg, if it returns
true then <tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called.</dd>
</dl>
</blockquote>
<p><tt class="docutils literal"><span class="pre">listener</span></tt> is a function that takes one argument, a log message. A log
message is an object (<a class="mochiref reference" href="#fn-logmessage">LogMessage</a> instance) that has at least these
properties:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
<dd>A counter that uniquely identifies a log message (per-logger)</dd>
<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
<dd>A string or number representing the log level. If string, you
may want to use <tt class="docutils literal"><span class="pre">LogLevel[level]</span></tt> for comparison.</dd>
<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
<dd>An Array of objects passed as additional arguments to the <tt class="docutils literal"><span class="pre">log</span></tt>
function.</dd>
</dl>
</blockquote>
</blockquote>
<p>
<a name="fn-logger.prototype.baselog"></a>
<a class="mochidef reference" href="#fn-logger.prototype.baselog">Logger.prototype.baseLog(level, message[, ...])</a>:</p>
<blockquote>
<p>The base functionality behind all of the log functions.
The first argument is the log level as a string or number,
and all other arguments are used as the info list.</p>
<p>This function is available partially applied as:</p>
<blockquote>
<table border="1" class="docutils">
<colgroup>
<col width="61%" />
<col width="39%" />
</colgroup>
<tbody valign="top">
<tr><td>Logger.debug</td>
<td>'DEBUG'</td>
</tr>
<tr><td>Logger.log</td>
<td>'INFO'</td>
</tr>
<tr><td>Logger.error</td>
<td>'ERROR'</td>
</tr>
<tr><td>Logger.fatal</td>
<td>'FATAL'</td>
</tr>
<tr><td>Logger.warning</td>
<td>'WARNING'</td>
</tr>
</tbody>
</table>
</blockquote>
<p>For the default logger, these are also available as global functions,
see the <a class="mochiref reference" href="#fn-logger">Logger</a> constructor documentation for more info.</p>
</blockquote>
<p>
<a name="fn-logger.prototype.clear"></a>
<a class="mochidef reference" href="#fn-logger.prototype.clear">Logger.prototype.clear()</a>:</p>
<blockquote>
Clear all messages from the message buffer.</blockquote>
<p>
<a name="fn-logger.prototype.debuggingbookmarklet"></a>
<a class="mochidef reference" href="#fn-logger.prototype.debuggingbookmarklet">Logger.prototype.debuggingBookmarklet()</a>:</p>
<blockquote>
<p>Display the contents of the logger in a useful way for browsers.</p>
<p>Currently, if <a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> is loaded, then a pop-up
<a class="mochiref reference" href="LoggingPane.html#fn-loggingpane">MochiKit.LoggingPane.LoggingPane</a> will be used. Otherwise,
it will be an alert with <a class="mochiref reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText()</a>.</p>
</blockquote>
<p>
<a name="fn-logger.prototype.dispatchlisteners"></a>
<a class="mochidef reference" href="#fn-logger.prototype.dispatchlisteners">Logger.prototype.dispatchListeners(msg)</a>:</p>
<blockquote>
Dispatch a log message to all listeners.</blockquote>
<p>
<a name="fn-logger.prototype.getmessages"></a>
<a class="mochidef reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages(howMany)</a>:</p>
<blockquote>
Return a list of up to <tt class="docutils literal"><span class="pre">howMany</span></tt> messages from the message buffer.</blockquote>
<p>
<a name="fn-logger.prototype.getmessagetext"></a>
<a class="mochidef reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText(howMany)</a>:</p>
<blockquote>
<p>Get a string representing up to the last <tt class="docutils literal"><span class="pre">howMany</span></tt> messages in the
message buffer. The default is <tt class="docutils literal"><span class="pre">30</span></tt>.</p>
<p>The message looks like this:</p>
<pre class="literal-block">
LAST {messages.length} MESSAGES:
[{msg.num}] {msg.level}: {m.info.join(' ')}
[{msg.num}] {msg.level}: {m.info.join(' ')}
...
</pre>
<p>If you want some other format, use
<a class="mochiref reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages</a> and do it yourself.</p>
</blockquote>
<p>
<a name="fn-logger.prototype.removelistener"></a>
<a class="mochidef reference" href="#fn-logger.prototype.removelistener">Logger.prototype.removeListener(ident)</a>:</p>
<blockquote>
Remove a listener using the ident given to <a class="mochiref reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener</a></blockquote>
</div>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-alertlistener"></a>
<a class="mochidef reference" href="#fn-alertlistener">alertListener(msg)</a>:</p>
<blockquote>
Ultra-obnoxious <tt class="docutils literal"><span class="pre">alert(...)</span></tt> listener</blockquote>
<p>
<a name="fn-logdebug"></a>
<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
<blockquote>
Log an INFO message to the default logger</blockquote>
<p>
<a name="fn-logdebug"></a>
<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
<blockquote>
Log a DEBUG message to the default logger</blockquote>
<p>
<a name="fn-logerror"></a>
<a class="mochidef reference" href="#fn-logerror">logError(message[, info[, ...]])</a>:</p>
<blockquote>
Log an ERROR message to the default logger</blockquote>
<p>
<a name="fn-logfatal"></a>
<a class="mochidef reference" href="#fn-logfatal">logFatal(message[, info[, ...]])</a>:</p>
<blockquote>
Log a FATAL message to the default logger</blockquote>
<p>
<a name="fn-loglevelatleast"></a>
<a class="mochidef reference" href="#fn-loglevelatleast">logLevelAtLeast(minLevel)</a>:</p>
<blockquote>
Return a function that will match log messages whose level
is at least minLevel</blockquote>
<p>
<a name="fn-logwarning"></a>
<a class="mochidef reference" href="#fn-logwarning">logWarning(message[, info[, ...]])</a>:</p>
<blockquote>
Log a WARNING message to the default logger</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Python's logging module: <a class="reference" href="http://docs.python.org/lib/module-logging.html">http://docs.python.org/lib/module-logging.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id7" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2" name="id7">[2]</a></td><td>PEP 282, where they admit all of the Java influence: <a class="reference" href="http://www.python.org/peps/pep-0282.html">http://www.python.org/peps/pep-0282.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id8" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id4" name="id8">[3]</a></td><td>Original Bookmarklet Based Debugging blather: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/">http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,121 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
// open a pop-up window
createLoggingPane()
// use a div at the bottom of the document
createLoggingPane(true);
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>MochiKit.Logging does not have any browser dependencies and is completely
unobtrusive. MochiKit.LoggingPane is a browser-based colored viewing pane
for your <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> output that can be used as a pop-up or
inline.</p>
<p>It also allows for regex and level filtering! MochiKit.LoggingPane is used
as the default <a class="mochiref reference" href="Logging.html#fn-debuggingbookmarklet">MochiKit.Logging.debuggingBookmarklet()</a> if it is
loaded.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a></li>
</ul>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="constructors" name="constructors">Constructors</a></h2>
<p>
<a name="fn-loggingpane"></a>
<a class="mochidef reference" href="#fn-loggingpane">LoggingPane(inline=false, logger=MochiKit.Logging.logger)</a>:</p>
<blockquote>
<p>A listener for a <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> logger with an interactive
DOM representation.</p>
<p>If <tt class="docutils literal"><span class="pre">inline</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> will be a <tt class="docutils literal"><span class="pre">DIV</span></tt>
at the bottom of the document. Otherwise, it will be in a pop-up
window with a name based on the calling page's URL. If there is an
element in the document with an id of <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt>,
it will be used instead of appending a new <tt class="docutils literal"><span class="pre">DIV</span></tt> to the body.</p>
<p><tt class="docutils literal"><span class="pre">logger</span></tt> is the reference to the <a class="mochiref reference" href="Logging.html#fn-logger">MochiKit.Logging.Logger</a> to
listen to. If not specified, the global default logger is used.</p>
<p>Properties:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">win</span></tt>:</dt>
<dd>Reference to the pop-up window (<tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">inline</span></tt>)</dd>
<dt><tt class="docutils literal"><span class="pre">inline</span></tt>:</dt>
<dd><tt class="docutils literal"><span class="pre">true</span></tt> if the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> is inline</dd>
<dt><tt class="docutils literal"><span class="pre">colorTable</span></tt>:</dt>
<dd><p class="first">An object with property-&gt;value mappings for each log level
and its color. May also be mutated on <tt class="docutils literal"><span class="pre">LoggingPane.prototype</span></tt>
to affect all instances. For example:</p>
<pre class="last literal-block">
MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
DEBUG: &quot;green&quot;,
INFO: &quot;black&quot;,
WARNING: &quot;blue&quot;,
ERROR: &quot;red&quot;,
FATAL: &quot;darkred&quot;
};
</pre>
</dd>
</dl>
</blockquote>
</blockquote>
<p>
<a name="fn-loggingpane.prototype.closepane"></a>
<a class="mochidef reference" href="#fn-loggingpane.prototype.closepane">LoggingPane.prototype.closePane()</a>:</p>
<blockquote>
Close the <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> (close the child window, or
remove the <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> <tt class="docutils literal"><span class="pre">DIV</span></tt> from the document).</blockquote>
</div>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-createloggingpane"></a>
<a class="mochidef reference" href="#fn-createloggingpane">createLoggingPane(inline=false)</a>:</p>
<blockquote>
Create or return an existing <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> for this document
with the given inline setting. This is preferred over using
<a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> directly, as only one <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a>
should be present in a given document.</blockquote>
</div>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,331 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Signal - Simple universal event handling</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Signal - Simple universal event handling</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<p>Signal for DOM events:</p>
<pre class="literal-block">
// DOM events are also signals. Connect freely! The functions will be
// called with the custom event as a parameter.
// calls myClicked.apply(getElement('myID'), event)
connect('myID', 'onclick', myClicked);
// calls wasClicked.apply(myObject, event)
connect('myID', 'onclick', myObject, wasClicked);
// calls myObject.wasClicked(event)
connect('myID', 'onclick', myObject, 'wasClicked');
// the event is normalized, no more e = e || window.event!
myObject.wasClicked = function(e) {
var crossBrowserCoordinates = e.mouse().page;
// e.mouse().page is a MochiKit.DOM.Coordinates object
}
</pre>
<p>Signal for non-DOM events:</p>
<pre class="literal-block">
// otherObject.gotFlash() will be called when 'flash' signalled.
connect(myObject, 'flash', otherObject, 'gotFlash');
// gotBang.apply(otherObject) will be called when 'bang' signalled.
// You can access otherObject from within gotBang as 'this'.
connect(myObject, 'bang', otherObject, gotBang);
// myFunc.apply(myObject) will be called when 'flash' signalled.
// You can access myObject from within myFunc as 'this'.
var ident = connect(myObject, 'flash', myFunc);
// You may disconnect with the return value from connect
disconnect(ident);
// Signal can take parameters. These will be passed along to the connected
// functions.
signal(myObject, 'flash');
signal(myObject, 'bang', 'BANG!');
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>Event handling was never so easy!</p>
<p>This module takes care of all the hard work—figuring out which event
model to use, trying to retrieve the event object, and handling your own
internal events, as well as cleanup when the page is unloaded to clean up IE's
nasty memory leakage.</p>
<p>This event system is largely based on Qt's signal/slot system. Read more on
how that is handled and also how it is used in model/view programming at:
<a class="reference" href="http://doc.trolltech.com/">http://doc.trolltech.com/</a></p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<div class="section">
<h2><a id="using-signal-for-dom-events" name="using-signal-for-dom-events">Using Signal for DOM Events</a></h2>
<p>When using MochiKit.Signal, do not use the browser's native event API. That
means, no <tt class="docutils literal"><span class="pre">onclick=&quot;blah&quot;</span></tt>, no <tt class="docutils literal"><span class="pre">elem.addEventListener(...)</span></tt>, and certainly
no <tt class="docutils literal"><span class="pre">elem.attachEvent(...)</span></tt>. This also means that
<a class="mochiref reference" href="DOM.html#fn-addtocallstack">MochiKit.DOM.addToCallStack</a> and
<a class="mochiref reference" href="DOM.html#fn-addloadevent">MochiKit.DOM.addLoadEvent</a> should not be used in combination with
this module.</p>
<p>Signals for DOM objects are named with the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix, e.g.:
<tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>, etc.</p>
<p>When the signal fires, your slot will be called with one parameter, the custom
event object.</p>
</div>
<div class="section">
<h2><a id="custom-event-objects-for-dom-events" name="custom-event-objects-for-dom-events">Custom Event Objects for DOM events</a></h2>
<p>Signals triggered by DOM events are called with a custom event object as a
parameter. The custom event object presents a consistent view of the event
across all supported platforms and browsers, and provides many conveniences
not available even in a correct W3C implementation.</p>
<p>See the <a class="reference" href="#dom-custom-event-object-reference">DOM Custom Event Object Reference</a> for a detailed API description
of this object.</p>
<p>If you find that you're accessing the native event for any reason, create a
<a class="reference" href="http://trac.mochikit.com/newticket">new ticket</a> and we'll look into normalizing the behavior you're looking for.</p>
</div>
<div class="section">
<h2><a id="memory-usage" name="memory-usage">Memory Usage</a></h2>
<p>Any object that has connected slots (via <a class="mochiref reference" href="#fn-connect">connect()</a>) is referenced
by the Signal mechanism until it is disconnected via <a class="mochiref reference" href="#fn-disconnect">disconnect()</a>
or <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>.</p>
<p>Signal does not leak. It registers an <tt class="docutils literal"><span class="pre">'onunload'</span></tt> event that disconnects all
objects on the page when the browser leaves the page. However, memory usage
will grow during the page view for every connection made until it is
disconnected. Even if the DOM object is removed from the document, it
will still be referenced by Signal until it is explicitly disconnected.</p>
<p>In order to conserve memory during the page view, <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>
any DOM elements that are about to be removed from the document.</p>
</div>
<div class="section">
<h2><a id="using-signal-for-non-dom-objects" name="using-signal-for-non-dom-objects">Using Signal for non-DOM objects</a></h2>
<p>Signals are triggered with the <a class="mochiref reference" href="#fn-signal">signal(src, 'signal', ...)</a>
function. Additional parameters passed to this are passed onto the
connected slots. Explicit signals are not required for DOM events.</p>
<p>Slots that are connected to a signal are called in the following manner
when that signal is signalled:</p>
<ul class="simple">
<li>If the slot was a single function, then it is called with <tt class="docutils literal"><span class="pre">this</span></tt> set
to the object originating the signal with whatever parameters it was
signalled with.</li>
<li>If the slot was an object and a function, then it is called with
<tt class="docutils literal"><span class="pre">this</span></tt> set to the object, and with whatever parameters it was
signalled with.</li>
<li>If the slot was an object and a string, then <tt class="docutils literal"><span class="pre">object[string]</span></tt> is
called with the parameters to the signal.</li>
</ul>
</div>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="signal-api-reference" name="signal-api-reference">Signal API Reference</a></h2>
<p>
<a name="fn-connect"></a>
<a class="mochidef reference" href="#fn-connect">connect(src, signal, dest[, func])</a>:</p>
<blockquote>
<p>Connects a signal to a slot, and return a unique identifier that can be
used to disconnect that signal.</p>
<p><tt class="docutils literal"><span class="pre">src</span></tt> is the object that has the signal. You may pass in a string, in
which case, it is interpreted as an id for an HTML element.</p>
<p><tt class="docutils literal"><span class="pre">signal</span></tt> is a string that represents a signal name. If 'src' is an HTML
Element, <tt class="docutils literal"><span class="pre">window</span></tt>, or the <tt class="docutils literal"><span class="pre">document</span></tt>, then it can be one of the
'on-XYZ' events. You must include the 'on' prefix, and it must be all
lower-case.</p>
<p><tt class="docutils literal"><span class="pre">dest</span></tt> and <tt class="docutils literal"><span class="pre">func</span></tt> describe the slot, or the action to take when the
signal is triggered.</p>
<blockquote>
<ul class="simple">
<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a string, then
<tt class="docutils literal"><span class="pre">dest[func].apply(dest,</span> <span class="pre">...)</span></tt> will be called when the signal
is signalled.</li>
<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a function, then
<tt class="docutils literal"><span class="pre">func.apply(dest,</span> <span class="pre">...)</span></tt> will be called when the signal is
signalled.</li>
<li>If <tt class="docutils literal"><span class="pre">func</span></tt> is undefined and <tt class="docutils literal"><span class="pre">dest</span></tt> is a function, then
<tt class="docutils literal"><span class="pre">func.apply(src,</span> <span class="pre">...)</span></tt> will be called when the signal is
signalled.</li>
</ul>
</blockquote>
<p>No other combinations are allowed and will raise an exception.</p>
<p>The return value can be passed to <a class="mochiref reference" href="#fn-disconnect">disconnect</a> to disconnect
the signal.</p>
</blockquote>
<p>
<a name="fn-disconnect"></a>
<a class="mochidef reference" href="#fn-disconnect">disconnect(ident)</a>:</p>
<blockquote>
To disconnect a signal, pass its ident returned by <a class="mochiref reference" href="#fn-connect">connect()</a>.
This is similar to how the browser's <tt class="docutils literal"><span class="pre">setTimeout</span></tt> and <tt class="docutils literal"><span class="pre">clearTimeout</span></tt>
works.</blockquote>
<p>
<a name="fn-disconnectall"></a>
<a class="mochidef reference" href="#fn-disconnectall">disconnectAll(src[, signal, ...])</a>:</p>
<blockquote>
<p><tt class="docutils literal"><span class="pre">disconnectAll(src)</span></tt> removes all signals from src.</p>
<p><tt class="docutils literal"><span class="pre">disconnectAll(src,</span> <span class="pre">'onmousedown',</span> <span class="pre">'mySignal')</span></tt> will remove all
<tt class="docutils literal"><span class="pre">'onmousedown'</span></tt> and <tt class="docutils literal"><span class="pre">'mySignal'</span></tt> signals from src.</p>
</blockquote>
<p>
<a name="fn-signal"></a>
<a class="mochidef reference" href="#fn-signal">signal(src, signal, ...)</a>:</p>
<blockquote>
This will signal a signal, passing whatever additional parameters on to
the connected slots. <tt class="docutils literal"><span class="pre">src</span></tt> and <tt class="docutils literal"><span class="pre">signal</span></tt> are the same as for
<a class="mochiref reference" href="#fn-connect">connect()</a>.</blockquote>
</div>
<div class="section">
<h2><a id="dom-custom-event-object-reference" name="dom-custom-event-object-reference">DOM Custom Event Object Reference</a></h2>
<p>
<a name="fn-event"></a>
<a class="mochidef reference" href="#fn-event">event()</a>:</p>
<blockquote>
The native event produced by the browser. You should not need to use this.</blockquote>
<p>
<a name="fn-src"></a>
<a class="mochidef reference" href="#fn-src">src()</a>:</p>
<blockquote>
The element that this signal is connected to.</blockquote>
<p>
<a name="fn-type"></a>
<a class="mochidef reference" href="#fn-type">type()</a>:</p>
<blockquote>
The event type (<tt class="docutils literal"><span class="pre">'click'</span></tt>, <tt class="docutils literal"><span class="pre">'mouseover'</span></tt>, <tt class="docutils literal"><span class="pre">'keypress'</span></tt>, etc.) as a
string. Does not include the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix.</blockquote>
<p>
<a name="fn-target"></a>
<a class="mochidef reference" href="#fn-target">target()</a>:</p>
<blockquote>
The element that triggered the event. This may be a child of
<a class="mochiref reference" href="#fn-src">src()</a>.</blockquote>
<p>
<a name="fn-modifier"></a>
<a class="mochidef reference" href="#fn-modifier">modifier()</a>:</p>
<blockquote>
Returns <tt class="docutils literal"><span class="pre">{shift,</span> <span class="pre">ctrl,</span> <span class="pre">meta,</span> <span class="pre">alt,</span> <span class="pre">any}</span></tt>, where each property is <tt class="docutils literal"><span class="pre">true</span></tt>
if its respective modifier key was pressed, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. <tt class="docutils literal"><span class="pre">any</span></tt>
is <tt class="docutils literal"><span class="pre">true</span></tt> if any modifier is pressed, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise.</blockquote>
<p>
<a name="fn-stoppropagation"></a>
<a class="mochidef reference" href="#fn-stoppropagation">stopPropagation()</a>:</p>
<blockquote>
Works like W3C's <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt>.</blockquote>
<p>
<a name="fn-preventdefault"></a>
<a class="mochidef reference" href="#fn-preventdefault">preventDefault()</a>:</p>
<blockquote>
Works like W3C's <tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</blockquote>
<p>
<a name="fn-stop"></a>
<a class="mochidef reference" href="#fn-stop">stop()</a>:</p>
<blockquote>
Shortcut that calls <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt> and <tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</blockquote>
<p>
<a name="fn-key"></a>
<a class="mochidef reference" href="#fn-key">key()</a>:</p>
<blockquote>
<p>Returns <tt class="docutils literal"><span class="pre">{code,</span> <span class="pre">string}</span></tt>.</p>
<p>Use <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> handlers to detect control
characters such as <tt class="docutils literal"><span class="pre">'KEY_F1'</span></tt>. Use the <tt class="docutils literal"><span class="pre">'onkeypressed'</span></tt> handler to
detect &quot;printable&quot; characters, such as <tt class="docutils literal"><span class="pre">'é'</span></tt>.</p>
<p>When a user presses F1, in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> this method
returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">122,</span> <span class="pre">string:</span> <span class="pre">'KEY_F1'}</span></tt>. In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns
<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">0,</span> <span class="pre">string:</span> <span class="pre">''}</span></tt>.</p>
<p>If a user presses Shift+2 on a US keyboard, this method returns
<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">50,</span> <span class="pre">string:</span> <span class="pre">'KEY_2'}</span></tt> in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>.
In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">64,</span> <span class="pre">string:</span> <span class="pre">'&#64;'}</span></tt>.</p>
<p>See <tt class="docutils literal"><span class="pre">_specialKeys</span></tt> in the source code for a comprehensive list of
control characters.</p>
</blockquote>
<p>
<a name="fn-mouse"></a>
<a class="mochidef reference" href="#fn-mouse">mouse()</a>:</p>
<blockquote>
<p>Properties for <tt class="docutils literal"><span class="pre">'onmouse*'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>, and
<tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>:</p>
<blockquote>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">page</span></tt> is a <a class="mochiref reference" href="DOM.html#fn-coordinates">MochiKit.DOM.Coordinates</a> object that
represents the cursor position relative to the HTML document.
Equivalent to <tt class="docutils literal"><span class="pre">pageX</span></tt> and <tt class="docutils literal"><span class="pre">pageY</span></tt> in Safari, Mozilla, and
Opera.</li>
<li><tt class="docutils literal"><span class="pre">client</span></tt> is a <a class="mochiref reference" href="DOM.html#fn-coordinates">MochiKit.DOM.Coordinates</a> object that
represents the cursor position relative to the visible portion of
the HTML document. Equivalent to <tt class="docutils literal"><span class="pre">clientX</span></tt> and <tt class="docutils literal"><span class="pre">clientY</span></tt> on
all browsers.</li>
</ul>
</blockquote>
<p>Properties for <tt class="docutils literal"><span class="pre">'onmouseup'</span></tt>, <tt class="docutils literal"><span class="pre">'onmousedown'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, and
<tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>:</p>
<blockquote>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">mouse().button</span></tt> returns <tt class="docutils literal"><span class="pre">{left,</span> <span class="pre">right,</span> <span class="pre">middle}</span></tt> where each
property is <tt class="docutils literal"><span class="pre">true</span></tt> if the mouse button was pressed, <tt class="docutils literal"><span class="pre">false</span></tt>
otherwise.</li>
</ul>
</blockquote>
<p>Known browser bugs:</p>
<blockquote>
<ul>
<li><p class="first">Current versions of Safari won't signal <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt> when
attached via <tt class="docutils literal"><span class="pre">connect()</span></tt> (<a class="reference" href="http://bugzilla.opendarwin.org/show_bug.cgi?id=7790">Safari Bug 7790</a>).</p>
</li>
<li><p class="first">Mac browsers don't report right-click consistently. Firefox
signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().ctrl</span></tt> to true, Opera
signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().meta</span></tt> to <tt class="docutils literal"><span class="pre">true</span></tt>, and
Safari doesn't signal the slot at all (<a class="reference" href="http://bugzilla.opendarwin.org/show_bug.cgi?id=6595">Safari Bug 6595</a>).</p>
<p>To find a right-click in Safari, Firefox, and IE, you can connect
an element to <tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>. This doesn't work in Opera.</p>
</li>
</ul>
</blockquote>
</blockquote>
<p>
<a name="fn-relatedtarget"></a>
<a class="mochidef reference" href="#fn-relatedtarget">relatedTarget()</a>:</p>
<blockquote>
Returns the document element that the mouse has moved to. This is
generated for <tt class="docutils literal"><span class="pre">'onmouseover'</span></tt> and <tt class="docutils literal"><span class="pre">'onmouseout'</span></tt> events.</blockquote>
</div>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Jonathan Gardner &lt;<a class="reference" href="mailto:jgardner&#64;jonathangardner.net">jgardner&#64;jonathangardner.net</a>&gt;</li>
<li>Beau Hartshorne &lt;<a class="reference" href="mailto:beau&#64;hartshornesoftware.com">beau&#64;hartshornesoftware.com</a>&gt;</li>
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2006 Jonathan Gardner &lt;<a class="reference" href="mailto:jgardner&#64;jonathangardner.net">jgardner&#64;jonathangardner.net</a>&gt;, Beau
Hartshorne &lt;<a class="reference" href="mailto:beau&#64;hartshornesoftware.com">beau&#64;hartshornesoftware.com</a>&gt;, and Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;.
This program is dual-licensed free software; you can redistribute it and/or
modify it under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the
<a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,264 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title></title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<p>2006-04-29 v1.3.1 (bug fix release)</p>
<ul class="simple">
<li>Fix sendXMLHttpRequest sendContent regression</li>
<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
</ul>
<p>2006-04-26 v1.3 &quot;warp zone&quot;</p>
<ul class="simple">
<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
<li>New MochiKit.Base.method as a convenience form of bind that takes the
object before the method</li>
<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
a single Array</li>
<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
<li>New key_events example demonstrating use of MochiKit.Signal's key handling
capabilities.</li>
<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
null is used and the string will be considered the first node. This
allows for the more natural P(&quot;foo&quot;) rather than P(null, &quot;foo&quot;).</li>
<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
provides multi-line input and a help() function to get MochiKit function
signature from the documentation.</li>
<li>Native Console Logging for the default MochiKit.Logging logger</li>
<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
<li>New MochiKit.Signal example: draggable</li>
<li>Added sanity checking to Deferred to ensure that errors happen when chaining
is used incorrectly</li>
<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
component values smaller than 16/255.</li>
<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
maximum size</li>
<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
Error, so that the errback chain is used instead of the callback chain.</li>
<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
in the correct order.</li>
<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
<li>MochiKit.Base.isNull no longer matches undefined</li>
<li>example doctypes changed to HTML4</li>
<li>isDateLike no longer throws error on null</li>
<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
<li>updated elementDimensions to calculate width from offsetWidth instead
of clientWidth</li>
<li>formContents now works with FORM tags that have a name attribute</li>
<li>Documentation now uses MochiKit to generate a function index</li>
</ul>
<p>2006-01-26 v1.2 &quot;the ocho&quot;</p>
<ul class="simple">
<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
<li>Added new MochiKit.Base.findIdentical function to find the index of an
element in an Array-like object. Uses === for identity comparison.</li>
<li>Added new MochiKit.Base.find function to find the index of an element in
an Array-like object. Uses compare for rich comparison.</li>
<li>MochiKit.Base.bind will accept a string for func, which will be immediately
looked up as self[func].</li>
<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
compatibility</li>
<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
height of an element in the document</li>
<li>MochiKit.DOM's initialization is now compatible with
HTMLUnit + JWebUnit + Rhino</li>
<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
currently in the document instead of always creating one.</li>
<li>MochiKit.Base now has operator.mul</li>
<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
a custom value attribute</li>
<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
<li>MochiKit.DOM.setNodeAttribute should work now</li>
<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
property to a string</li>
<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
name and for properties</li>
<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
<li>Added new MochiKit.DOM documentation on element visibility</li>
<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
for determining the position of an element in the document</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
</ul>
<p>2005-11-14 v1.1</p>
<ul class="simple">
<li>Fixed a bug in numberFormatter with large numbers</li>
<li>Massively overhauled documentation</li>
<li>Fast-path for primitives in MochiKit.Base.compare</li>
<li>New groupby and groupby_as_array in MochiKit.Iter</li>
<li>Added iterator factory adapter for objects that implement iterateNext()</li>
<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
LEGEND, FIELDSET</li>
<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
<li>MochiKit.LoggingPane now uses named windows based on the URL so that
a given URL will get the same LoggingPane window after a reload
(at the same position, etc.)</li>
<li>MochiKit.DOM now has currentWindow() and currentDocument() context
variables that are set with withWindow() and withDocument(). These
context variables affect all MochiKit.DOM functionality (getElement,
createDOM, etc.)</li>
<li>MochiKit.Base.items will now catch and ignore exceptions for properties
that are enumerable but not accessible (e.g. permission denied)</li>
<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
now accept additional arguments that are used to create a partially
applied function. This differs from Twisted in that the callback/errback
result becomes the <em>last</em> argument, not the first when this feature
is used.</li>
<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
arguments which are used to create a GET query string</li>
<li>Did some refactoring to reduce the footprint of MochiKit by a few
kilobytes</li>
<li>escapeHTML to longer escapes ' (apos) and now uses
String.replace instead of iterating over every char.</li>
<li>Added DeferredLock to Async</li>
<li>Renamed getElementsComputedStyle to computedStyle and moved
it from MochiKit.Visual to MochiKit.DOM</li>
<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
<li>Fixed range() to accept a negative step</li>
<li>New alias to MochiKit.swapDOM called removeElement</li>
<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
an attribute on a node without raising, roughly equivalent to:
updateNodeAttributes(node, {attr: value})</li>
<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
a node's attribute or returns null without raising</li>
<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
directly (addLoadEvent did not leak, since it clears the handler)</li>
</ul>
<p>2005-10-24 v1.0</p>
<ul class="simple">
<li>New interpreter example that shows usage of MochiKit.DOM to make
an interactive JavaScript interpreter</li>
<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
debuggingBookmarklet, with logging_pane example to show its usage</li>
<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
in order to provide a live regular expression matching tool</li>
<li>Added advanced number formatting capabilities to MochiKit.Format:
numberFormatter(pattern, placeholder=&quot;&quot;, locale=&quot;default&quot;) and
formatLocale(locale=&quot;default&quot;)</li>
<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
to MochiKit.Format</li>
<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
isoTimestamp(isoString) will convert them to Date objects, and
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
<li>Fixed missing errback for sendXMLHttpRequest when the server does not
respond</li>
<li>Fixed infinite recusion bug when using roundClass(&quot;DIV&quot;, ...)</li>
<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
from being cancelled properly</li>
<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
have an apply method, such as alert</li>
<li>Reliably return null from the string parsing/manipulation functions if
the input can't be coerced to a string (s + &quot;&quot;) or the input makes no sense;
e.g. isoTimestamp(null) and isoTimestamp(&quot;&quot;) return null</li>
</ul>
<p>2005-10-08 v0.90</p>
<ul class="simple">
<li>Fixed ISO compliance with toISODate</li>
<li>Added missing operator.sub</li>
<li>Placated Mozilla's strict warnings a bit</li>
<li>Added JSON serialization and unserialization support to MochiKit.Base:
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
API.</li>
<li>Fixed a bug in the script loader that failed in some scenarios when a script
tag did not have a &quot;src&quot; attribute (thanks Ian!)</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
P, FORM</li>
<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
and parseQueryString, when available.</li>
</ul>
<p>2005-08-12 v0.80</p>
<ul class="simple">
<li>Source highlighting in all examples, moved to a view-source example</li>
<li>Added some experimental syntax highlighting for the Rounded Corners example,
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
<li>Use an indirect binding for the logger conveniences, so that the global
logger could be replaced by setting MochiKit.Logger.logger to something else
(though an observer is probably a better choice).</li>
<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
which will be looked up with getElement</li>
<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
node.parentNode)</li>
<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
<li>Possible workaround for Safari issue with swapDOM, where it would get
confused because two elements were in the DOM at the same time with the
same id</li>
<li>Added missing THEAD convenience function to MochiKit.DOM</li>
<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
MochiKit.DOM</li>
<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
<li>Added HSV color space support to MochiKit.Visual</li>
<li>Fixed a bug in the sortable_tables example, it now converts types
correctly</li>
<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
scope</li>
</ul>
<p>2005-08-04 v0.70</p>
<ul class="simple">
<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
a little TAL-ish DOM templating attribute language.</li>
<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
ignore requests with status == 0, which seems to happen for cached or local
requests</li>
<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
<li>Changed scrapeText API to return a string by default. This is API-breaking!
It was dumb to have the default return value be the form you almost never
want. Sorry.</li>
<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
(where previously you'd likely get a DOM exception).</li>
<li>Added three new functions to MochiKit.Base for dealing with URL query
strings: urlEncode, queryString, parseQueryString</li>
<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
starts with &quot;on&quot; (e.g. &quot;onclick&quot;). If v is a string, it will set it to
new Function(v).</li>
<li>Another workaround for Internet &quot;worst browser ever&quot; Explorer's setAttribute
usage in MochiKit.DOM.createDOM (checked -&gt; defaultChecked).</li>
<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
now!</li>
</ul>
<p>2005-07-29 v0.60</p>
<ul class="simple">
<li>Beefed up the MochiKit.DOM test suite</li>
<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
false unexpectedly before</li>
<li>Added an optional &quot;parent&quot; argument to
MochiKit.DOM.getElementsByTagAndClassName</li>
<li>Added a &quot;packed&quot; version in packed/lib/MochiKit/MochiKit.js</li>
<li>Changed build script to rewrite the URLs in tests to account for the
JSAN-required reorganization</li>
<li>MochiKit.Compat to potentially work around IE 5.5 issues
(5.0 still not supported). Test.Simple doesn't seem to work there,
though.</li>
<li>Several minor documentation corrections</li>
</ul>
<p>2005-07-27 v0.50</p>
<ul class="simple">
<li>Initial Release</li>
</ul>
</div>
</body>
</html>

View File

@@ -1,162 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit.Visual - visual effects</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="name" name="name">Name</a></h1>
<p>MochiKit.Visual - visual effects</p>
</div>
<div class="section">
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
<pre class="literal-block">
// round the corners of all h1 elements
roundClass(&quot;h1&quot;, null);
// round the top left corner of the element with the id &quot;title&quot;
roundElement(&quot;title&quot;, {corners: &quot;tl&quot;});
</pre>
</div>
<div class="section">
<h1><a id="description" name="description">Description</a></h1>
<p>MochiKit.Visual provides visual effects and support functions for visuals.</p>
</div>
<div class="section">
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
<ul class="simple">
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a></li>
</ul>
</div>
<div class="section">
<h1><a id="overview" name="overview">Overview</a></h1>
<p>At this time, MochiKit.Visual provides one visual effect: rounded corners
for your HTML elements. These rounded corners are created completely
through CSS manipulations and require no external images or style sheets.
This implementation was adapted from <a class="reference" href="http://www.openrico.org">Rico</a>.</p>
</div>
<div class="section">
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
<div class="section">
<h2><a id="functions" name="functions">Functions</a></h2>
<p>
<a name="fn-roundclass"></a>
<a class="mochidef reference" href="#fn-roundclass">roundClass(tagName[, className[, options]])</a>:</p>
<blockquote>
Rounds all of the elements that match the <tt class="docutils literal"><span class="pre">tagName</span></tt> and <tt class="docutils literal"><span class="pre">className</span></tt>
specifiers, using the options provided. <tt class="docutils literal"><span class="pre">tagName</span></tt> or <tt class="docutils literal"><span class="pre">className</span></tt> can
be <tt class="docutils literal"><span class="pre">null</span></tt> to match all tags or classes. For more information about
the options, see the <a class="mochiref reference" href="#fn-roundelement">roundElement</a> function.</blockquote>
<p>
<a name="fn-roundelement"></a>
<a class="mochidef reference" href="#fn-roundelement">roundElement(element[, options])</a>:</p>
<blockquote>
<p>Immediately round the corners of the specified element.
The element can be given as either a string
with the element ID, or as an element object.</p>
<p>The options mapping has the following defaults:</p>
<table border="1" class="docutils">
<colgroup>
<col width="35%" />
<col width="65%" />
</colgroup>
<tbody valign="top">
<tr><td>corners</td>
<td><tt class="docutils literal"><span class="pre">&quot;all&quot;</span></tt></td>
</tr>
<tr><td>color</td>
<td><tt class="docutils literal"><span class="pre">&quot;fromElement&quot;</span></tt></td>
</tr>
<tr><td>bgColor</td>
<td><tt class="docutils literal"><span class="pre">&quot;fromParent&quot;</span></tt></td>
</tr>
<tr><td>blend</td>
<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
</tr>
<tr><td>border</td>
<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
</tr>
<tr><td>compact</td>
<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
</tr>
</tbody>
</table>
<p>corners:</p>
<blockquote>
<p>specifies which corners of the element should be rounded.
Choices are:</p>
<ul class="simple">
<li>all</li>
<li>top</li>
<li>bottom</li>
<li>tl (top left)</li>
<li>bl (bottom left)</li>
<li>tr (top right)</li>
<li>br (bottom right)</li>
</ul>
<dl class="docutils">
<dt>Example:</dt>
<dd><tt class="docutils literal"><span class="pre">&quot;tl</span> <span class="pre">br&quot;</span></tt>: top-left and bottom-right corners are rounded</dd>
</dl>
</blockquote>
<dl class="docutils">
<dt>blend:</dt>
<dd>specifies whether the color and background color should be blended
together to produce the border color.</dd>
</dl>
</blockquote>
</div>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<table class="docutils footnote" frame="void" id="id1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id1">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id2">[2]</a></td><td>SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id3" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id3">[3]</a></td><td>W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="authors" name="authors">Authors</a></h1>
<ul class="simple">
<li>Kevin Dangoor &lt;<a class="reference" href="mailto:dangoor&#64;gmail.com">dangoor&#64;gmail.com</a>&gt;</li>
<li>Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;</li>
<li>Originally adapted from Rico &lt;<a class="reference" href="http://openrico.org/">http://openrico.org/</a>&gt; (though little remains)</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
<p>Portions adapted from <a class="reference" href="http://www.openrico.org">Rico</a> are available under the terms of the
<a class="reference" href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,319 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>MochiKit Documentation Index</title>
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../../js/toc.js"></script>
</head>
<body>
<div class="document">
<div class="section">
<h1><a id="distribution" name="distribution">Distribution</a></h1>
<p>MochiKit - makes JavaScript suck a bit less</p>
<ul class="simple">
<li><a class="mochiref reference" href="Async.html">MochiKit.Async</a> - manage asynchronous tasks</li>
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a> - functional programming and useful comparisons</li>
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a> - painless DOM manipulation API</li>
<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a> - color abstraction with CSS3 support</li>
<li><a class="mochiref reference" href="DateTime.html">MochiKit.DateTime</a> - &quot;what time is it anyway?&quot;</li>
<li><a class="mochiref reference" href="Format.html">MochiKit.Format</a> - string formatting goes here</li>
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a> - itertools for JavaScript; iteration made HARD,
and then easy</li>
<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> - we're all tired of <tt class="docutils literal"><span class="pre">alert()</span></tt></li>
<li><a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> - interactive <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a>
pane</li>
<li><a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> - simple universal event handling</li>
<li><a class="mochiref reference" href="Visual.html">MochiKit.Visual</a> - visual effects</li>
</ul>
</div>
<div class="section">
<h1><a id="notes" name="notes">Notes</a></h1>
<p>To turn on MochiKit's compatibility mode, do this before loading MochiKit:</p>
<pre class="literal-block">
&lt;script type=&quot;text/javascript&quot;&gt;MochiKit = {__compat__: true};&lt;/script&gt;
</pre>
<p>When compatibility mode is on, you must use fully qualified names for all
MochiKit functions (e.g. <tt class="docutils literal"><span class="pre">MochiKit.Base.map(...)</span></tt>).</p>
</div>
<div class="section">
<h1><a id="screencasts" name="screencasts">Screencasts</a></h1>
<ul class="simple">
<li><a class="reference" href="http://mochikit.com/screencasts/MochiKit_Intro-1">MochiKit 1.1 Intro</a></li>
</ul>
</div>
<div class="section">
<h1><a id="see-also" name="see-also">See Also</a></h1>
<ul class="simple">
<li><a class="reference" href="http://groups.google.com/group/mochikit">Google Groups: MochiKit</a>: The official mailing list for discussions
related to development of and with MochiKit</li>
<li><a class="reference" href="http://mochikit.com/">mochikit.com</a>: MochiKit's home on the web</li>
<li><a class="reference" href="http://bob.pythonmac.org/">from __future__ import *</a>: Bob Ippolito's blog</li>
<li><a class="reference" href="http://openjsan.org/doc/b/bo/bob/lib/MochiKit/">MochiKit on JSAN</a>: the JSAN distribution page for MochiKit</li>
<li><a class="reference" href="http://del.icio.us/tag/mochikit">MochiKit tag on del.icio.us</a>: Recent bookmarks related to MochiKit</li>
<li><a class="reference" href="http://technorati.com/tag/mochikit">MochiKit tag on Technorati</a>: Recent blog entries related to MochiKit</li>
</ul>
</div>
<div class="section">
<h1><a id="version-history" name="version-history">Version History</a></h1>
<p>2006-04-29 v1.3.1 (bug fix release)</p>
<ul class="simple">
<li>Fix sendXMLHttpRequest sendContent regression</li>
<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
</ul>
<p>2006-04-26 v1.3 &quot;warp zone&quot;</p>
<ul class="simple">
<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
<li>New MochiKit.Base.method as a convenience form of bind that takes the
object before the method</li>
<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
a single Array</li>
<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
<li>New key_events example demonstrating use of MochiKit.Signal's key handling
capabilities.</li>
<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
null is used and the string will be considered the first node. This
allows for the more natural P(&quot;foo&quot;) rather than P(null, &quot;foo&quot;).</li>
<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
provides multi-line input and a help() function to get MochiKit function
signature from the documentation.</li>
<li>Native Console Logging for the default MochiKit.Logging logger</li>
<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
<li>New MochiKit.Signal example: draggable</li>
<li>Added sanity checking to Deferred to ensure that errors happen when chaining
is used incorrectly</li>
<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
component values smaller than 16/255.</li>
<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
maximum size</li>
<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
Error, so that the errback chain is used instead of the callback chain.</li>
<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
in the correct order.</li>
<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
<li>MochiKit.Base.isNull no longer matches undefined</li>
<li>example doctypes changed to HTML4</li>
<li>isDateLike no longer throws error on null</li>
<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
<li>updated elementDimensions to calculate width from offsetWidth instead
of clientWidth</li>
<li>formContents now works with FORM tags that have a name attribute</li>
<li>Documentation now uses MochiKit to generate a function index</li>
</ul>
<p>2006-01-26 v1.2 &quot;the ocho&quot;</p>
<ul class="simple">
<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
<li>Added new MochiKit.Base.findIdentical function to find the index of an
element in an Array-like object. Uses === for identity comparison.</li>
<li>Added new MochiKit.Base.find function to find the index of an element in
an Array-like object. Uses compare for rich comparison.</li>
<li>MochiKit.Base.bind will accept a string for func, which will be immediately
looked up as self[func].</li>
<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
compatibility</li>
<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
height of an element in the document</li>
<li>MochiKit.DOM's initialization is now compatible with
HTMLUnit + JWebUnit + Rhino</li>
<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
currently in the document instead of always creating one.</li>
<li>MochiKit.Base now has operator.mul</li>
<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
a custom value attribute</li>
<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
<li>MochiKit.DOM.setNodeAttribute should work now</li>
<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
property to a string</li>
<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
name and for properties</li>
<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
<li>Added new MochiKit.DOM documentation on element visibility</li>
<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
for determining the position of an element in the document</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
</ul>
<p>2005-11-14 v1.1</p>
<ul class="simple">
<li>Fixed a bug in numberFormatter with large numbers</li>
<li>Massively overhauled documentation</li>
<li>Fast-path for primitives in MochiKit.Base.compare</li>
<li>New groupby and groupby_as_array in MochiKit.Iter</li>
<li>Added iterator factory adapter for objects that implement iterateNext()</li>
<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
LEGEND, FIELDSET</li>
<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
<li>MochiKit.LoggingPane now uses named windows based on the URL so that
a given URL will get the same LoggingPane window after a reload
(at the same position, etc.)</li>
<li>MochiKit.DOM now has currentWindow() and currentDocument() context
variables that are set with withWindow() and withDocument(). These
context variables affect all MochiKit.DOM functionality (getElement,
createDOM, etc.)</li>
<li>MochiKit.Base.items will now catch and ignore exceptions for properties
that are enumerable but not accessible (e.g. permission denied)</li>
<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
now accept additional arguments that are used to create a partially
applied function. This differs from Twisted in that the callback/errback
result becomes the <em>last</em> argument, not the first when this feature
is used.</li>
<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
arguments which are used to create a GET query string</li>
<li>Did some refactoring to reduce the footprint of MochiKit by a few
kilobytes</li>
<li>escapeHTML to longer escapes ' (apos) and now uses
String.replace instead of iterating over every char.</li>
<li>Added DeferredLock to Async</li>
<li>Renamed getElementsComputedStyle to computedStyle and moved
it from MochiKit.Visual to MochiKit.DOM</li>
<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
<li>Fixed range() to accept a negative step</li>
<li>New alias to MochiKit.swapDOM called removeElement</li>
<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
an attribute on a node without raising, roughly equivalent to:
updateNodeAttributes(node, {attr: value})</li>
<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
a node's attribute or returns null without raising</li>
<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
directly (addLoadEvent did not leak, since it clears the handler)</li>
</ul>
<p>2005-10-24 v1.0</p>
<ul class="simple">
<li>New interpreter example that shows usage of MochiKit.DOM to make
an interactive JavaScript interpreter</li>
<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
debuggingBookmarklet, with logging_pane example to show its usage</li>
<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
in order to provide a live regular expression matching tool</li>
<li>Added advanced number formatting capabilities to MochiKit.Format:
numberFormatter(pattern, placeholder=&quot;&quot;, locale=&quot;default&quot;) and
formatLocale(locale=&quot;default&quot;)</li>
<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
to MochiKit.Format</li>
<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
isoTimestamp(isoString) will convert them to Date objects, and
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
<li>Fixed missing errback for sendXMLHttpRequest when the server does not
respond</li>
<li>Fixed infinite recusion bug when using roundClass(&quot;DIV&quot;, ...)</li>
<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
from being cancelled properly</li>
<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
have an apply method, such as alert</li>
<li>Reliably return null from the string parsing/manipulation functions if
the input can't be coerced to a string (s + &quot;&quot;) or the input makes no sense;
e.g. isoTimestamp(null) and isoTimestamp(&quot;&quot;) return null</li>
</ul>
<p>2005-10-08 v0.90</p>
<ul class="simple">
<li>Fixed ISO compliance with toISODate</li>
<li>Added missing operator.sub</li>
<li>Placated Mozilla's strict warnings a bit</li>
<li>Added JSON serialization and unserialization support to MochiKit.Base:
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
API.</li>
<li>Fixed a bug in the script loader that failed in some scenarios when a script
tag did not have a &quot;src&quot; attribute (thanks Ian!)</li>
<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
P, FORM</li>
<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
and parseQueryString, when available.</li>
</ul>
<p>2005-08-12 v0.80</p>
<ul class="simple">
<li>Source highlighting in all examples, moved to a view-source example</li>
<li>Added some experimental syntax highlighting for the Rounded Corners example,
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
<li>Use an indirect binding for the logger conveniences, so that the global
logger could be replaced by setting MochiKit.Logger.logger to something else
(though an observer is probably a better choice).</li>
<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
which will be looked up with getElement</li>
<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
node.parentNode)</li>
<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
<li>Possible workaround for Safari issue with swapDOM, where it would get
confused because two elements were in the DOM at the same time with the
same id</li>
<li>Added missing THEAD convenience function to MochiKit.DOM</li>
<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
MochiKit.DOM</li>
<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
<li>Added HSV color space support to MochiKit.Visual</li>
<li>Fixed a bug in the sortable_tables example, it now converts types
correctly</li>
<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
scope</li>
</ul>
<p>2005-08-04 v0.70</p>
<ul class="simple">
<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
a little TAL-ish DOM templating attribute language.</li>
<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
ignore requests with status == 0, which seems to happen for cached or local
requests</li>
<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
<li>Changed scrapeText API to return a string by default. This is API-breaking!
It was dumb to have the default return value be the form you almost never
want. Sorry.</li>
<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
(where previously you'd likely get a DOM exception).</li>
<li>Added three new functions to MochiKit.Base for dealing with URL query
strings: urlEncode, queryString, parseQueryString</li>
<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
starts with &quot;on&quot; (e.g. &quot;onclick&quot;). If v is a string, it will set it to
new Function(v).</li>
<li>Another workaround for Internet &quot;worst browser ever&quot; Explorer's setAttribute
usage in MochiKit.DOM.createDOM (checked -&gt; defaultChecked).</li>
<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
now!</li>
</ul>
<p>2005-07-29 v0.60</p>
<ul class="simple">
<li>Beefed up the MochiKit.DOM test suite</li>
<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
false unexpectedly before</li>
<li>Added an optional &quot;parent&quot; argument to
MochiKit.DOM.getElementsByTagAndClassName</li>
<li>Added a &quot;packed&quot; version in packed/lib/MochiKit/MochiKit.js</li>
<li>Changed build script to rewrite the URLs in tests to account for the
JSAN-required reorganization</li>
<li>MochiKit.Compat to potentially work around IE 5.5 issues
(5.0 still not supported). Test.Simple doesn't seem to work there,
though.</li>
<li>Several minor documentation corrections</li>
</ul>
<p>2005-07-27 v0.50</p>
<ul class="simple">
<li>Initial Release</li>
</ul>
</div>
<div class="section">
<h1><a id="copyright" name="copyright">Copyright</a></h1>
<p>Copyright 2005 Bob Ippolito &lt;<a class="reference" href="mailto:bob&#64;redivi.com">bob&#64;redivi.com</a>&gt;. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,89 +0,0 @@
function function_ref(fn) {
return A({"href": fn[1], "class": "mochiref reference"}, fn[0], BR());
};
function toggle_docs() {
toggleElementClass("invisible", "show_index", "function_index");
return false;
};
function create_toc() {
if (getElement("distribution")) {
return global_index();
}
if (getElement("api-reference")) {
return module_index();
}
};
function doXHTMLRequest(url) {
var req = getXMLHttpRequest();
if (req.overrideMimeType) {
req.overrideMimeType("text/xml");
}
req.open("GET", url, true);
return sendXMLHttpRequest(req).addCallback(function (res) {
return res.responseXML.documentElement;
});
};
function load_request(href, div, doc) {
var functions = withDocument(doc, spider_doc);
forEach(functions, function (func) {
// fix anchors
if (func[1].charAt(0) == "#") {
func[1] = href + func[1];
}
});
var showLink = A({"class": "force-pointer"}, "[+]");
var hideLink = A({"class": "force-pointer"}, "[\u2013]");
var functionIndex = DIV({"id": "function_index", "class": "invisible"},
hideLink,
P(null, map(function_ref, functions))
);
var toggleFunc = function (e) {
toggleElementClass("invisible", showLink, functionIndex);
};
connect(showLink, "onclick", toggleFunc);
connect(hideLink, "onclick", toggleFunc);
replaceChildNodes(div,
showLink,
functionIndex
);
};
function global_index() {
var distList = getElementsByTagAndClassName("ul")[0];
var bullets = getElementsByTagAndClassName("li", null, distList);
for (var i = 0; i < bullets.length; i++) {
var tag = bullets[i];
var firstLink = getElementsByTagAndClassName("a", "mochiref", tag)[0];
var href = getNodeAttribute(firstLink, "href");
var div = DIV(null, "[\u2026]");
appendChildNodes(tag, BR(), div);
var d = doXHTMLRequest(href).addCallback(load_request, href, div);
}
};
function spider_doc() {
return map(
function (tag) {
return [scrapeText(tag), getNodeAttribute(tag, "href")];
},
getElementsByTagAndClassName("a", "mochidef")
);
};
function module_index() {
var sections = getElementsByTagAndClassName("div", "section");
var ptr = sections[1];
var ref = DIV({"class": "section"},
H1(null, "Function Index"),
A({"id": "show_index", "href": "#", "onclick": toggle_docs}, "[show]"),
DIV({"id": "function_index", "class": "invisible"},
A({"href":"#", "onclick": toggle_docs}, "[hide]"),
P(null, map(function_ref, spider_doc()))));
ptr.parentNode.insertBefore(ref, ptr);
};
addLoadEvent(create_toc);

View File

@@ -1,573 +0,0 @@
.. title:: MochiKit.Async - manage asynchronous tasks
Name
====
MochiKit.Async - manage asynchronous tasks
Synopsis
========
::
var url = "/src/b/bo/bob/MochiKit.Async/META.json";
/*
META.json looks something like this:
{"name": "MochiKit", "version": "0.5"}
*/
var d = loadJSONDoc(url);
var gotMetadata = function (meta) {
if (MochiKit.Async.VERSION == meta.version) {
alert("You have the newest MochiKit.Async!");
} else {
alert("MochiKit.Async "
+ meta.version
+ " is available, upgrade!");
}
};
var metadataFetchFailed = function (err) {
alert("The metadata for MochiKit.Async could not be fetched :(");
};
d.addCallbacks(gotMetadata, metadataFetchFailed);
Description
===========
MochiKit.Async provides facilities to manage asynchronous
(as in AJAX [1]_) tasks. The model for asynchronous computation
used in this module is heavily inspired by Twisted [2]_.
Dependencies
============
- :mochiref:`MochiKit.Base`
Overview
========
Deferred
--------
The Deferred constructor encapsulates a single value that
is not available yet. The most important example of this
in the context of a web browser would be an ``XMLHttpRequest``
to a server. The importance of the Deferred is that it
allows a consistent API to be exposed for all asynchronous
computations that occur exactly once.
The producer of the Deferred is responsible for doing all
of the complicated work behind the scenes. This often
means waiting for a timer to fire, or waiting for an event
(e.g. ``onreadystatechange`` of ``XMLHttpRequest``).
It could also be coordinating several events (e.g.
``XMLHttpRequest`` with a timeout, or several Deferreds
(e.g. fetching a set of XML documents that should be
processed at the same time).
Since these sorts of tasks do not respond immediately, the
producer of the Deferred does the following steps before
returning to the consumer:
1. Create a ``new`` :mochiref:`Deferred();` object and keep a reference
to it, because it will be needed later when the value is
ready.
2. Setup the conditions to create the value requested (e.g.
create a new ``XMLHttpRequest``, set its
``onreadystatechange``).
3. Return the :mochiref:`Deferred` object.
Since the value is not yet ready, the consumer attaches
a function to the Deferred that will be called when the
value is ready. This is not unlike ``setTimeout``, or
other similar facilities you may already be familiar with.
The consumer can also attach an "errback" to the
:mochiref:`Deferred`, which is a callback for error handling.
When the value is ready, the producer simply calls
``myDeferred.callback(theValue)``. If an error occurred,
it should call ``myDeferred.errback(theValue)`` instead.
As soon as this happens, the callback that the consumer
attached to the :mochiref:`Deferred` is called with ``theValue``
as the only argument.
There are quite a few additional "advanced" features
baked into :mochiref:`Deferred`, such as cancellation and
callback chains, so take a look at the API
reference if you would like to know more!
API Reference
=============
Errors
------
:mochidef:`AlreadyCalledError`:
Thrown by a :mochiref:`Deferred` if ``.callback`` or
``.errback`` are called more than once.
:mochidef:`BrowserComplianceError`:
Thrown when the JavaScript runtime is not capable of performing
the given function. Currently, this happens if the browser
does not support ``XMLHttpRequest``.
:mochidef:`CancelledError`:
Thrown by a :mochiref:`Deferred` when it is cancelled,
unless a canceller is present and throws something else.
:mochidef:`GenericError`:
Results passed to ``.fail`` or ``.errback`` of a :mochiref:`Deferred`
are wrapped by this ``Error`` if ``!(result instanceof Error)``.
:mochidef:`XMLHttpRequestError`:
Thrown when an ``XMLHttpRequest`` does not complete successfully
for any reason. The ``req`` property of the error is the failed
``XMLHttpRequest`` object, and for convenience the ``number``
property corresponds to ``req.status``.
Constructors
------------
:mochidef:`Deferred()`:
Encapsulates a sequence of callbacks in response to a value that
may not yet be available. This is modeled after the Deferred class
from Twisted [3]_.
.. _`Twisted`: http://twistedmatrix.com/
Why do we want this? JavaScript has no threads, and even if it did,
threads are hard. Deferreds are a way of abstracting non-blocking
events, such as the final response to an ``XMLHttpRequest``.
The sequence of callbacks is internally represented as a list
of 2-tuples containing the callback/errback pair. For example,
the following call sequence::
var d = new Deferred();
d.addCallback(myCallback);
d.addErrback(myErrback);
d.addBoth(myBoth);
d.addCallbacks(myCallback, myErrback);
is translated into a :mochiref:`Deferred` with the following internal
representation::
[
[myCallback, null],
[null, myErrback],
[myBoth, myBoth],
[myCallback, myErrback]
]
The :mochiref:`Deferred` also keeps track of its current status (fired).
Its status may be one of the following three values:
===== ================================
Value Condition
===== ================================
-1 no value yet (initial condition)
0 success
1 error
===== ================================
A :mochiref:`Deferred` will be in the error state if one of the following
conditions are met:
1. The result given to callback or errback is "``instanceof Error``"
2. The callback or errback threw while executing. If the thrown object
is not ``instanceof Error``, it will be wrapped with
:mochiref:`GenericError`.
Otherwise, the :mochiref:`Deferred` will be in the success state. The state
of the :mochiref:`Deferred` determines the next element in the callback
sequence to run.
When a callback or errback occurs with the example deferred chain, something
equivalent to the following will happen (imagine that exceptions are caught
and returned as-is)::
// d.callback(result) or d.errback(result)
if (!(result instanceof Error)) {
result = myCallback(result);
}
if (result instanceof Error) {
result = myErrback(result);
}
result = myBoth(result);
if (result instanceof Error) {
result = myErrback(result);
} else {
result = myCallback(result);
}
The result is then stored away in case another step is added to the
callback sequence. Since the :mochiref:`Deferred` already has a value
available, any new callbacks added will be called immediately.
There are two other "advanced" details about this implementation that are
useful:
Callbacks are allowed to return :mochiref:`Deferred` instances,
so you can build complicated sequences of events with (relative) ease.
The creator of the :mochiref:`Deferred` may specify a canceller. The
canceller is a function that will be called if
:mochiref:`Deferred.prototype.cancel` is called before the
:mochiref:`Deferred` fires. You can use this to allow an
``XMLHttpRequest`` to be cleanly cancelled, for example. Note that
cancel will fire the :mochiref:`Deferred` with a
:mochiref:`CancelledError` (unless your canceller throws or returns
a different ``Error``), so errbacks should be prepared to handle that
``Error`` gracefully for cancellable :mochiref:`Deferred` instances.
:mochidef:`Deferred.prototype.addBoth(func)`:
Add the same function as both a callback and an errback as the
next element on the callback sequence. This is useful for code
that you want to guarantee to run, e.g. a finalizer.
If additional arguments are given, then ``func`` will be replaced
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
differs from `Twisted`_, because the result of the callback or
errback will be the *last* argument passed to ``func``.
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
(its value or error will be passed to the next callback). Note that
once the returned ``Deferred`` is chained, it can no longer accept new
callbacks.
:mochidef:`Deferred.prototype.addCallback(func[, ...])`:
Add a single callback to the end of the callback sequence.
If additional arguments are given, then ``func`` will be replaced
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
differs from `Twisted`_, because the result of the callback will
be the *last* argument passed to ``func``.
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
(its value or error will be passed to the next callback). Note that
once the returned ``Deferred`` is chained, it can no longer accept new
callbacks.
:mochidef:`Deferred.prototype.addCallbacks(callback, errback)`:
Add separate callback and errback to the end of the callback
sequence. Either callback or errback may be ``null``,
but not both.
If ``callback`` or ``errback`` returns a :mochiref:`Deferred`,
then it will be chained (its value or error will be passed to the
next callback). Note that once the returned ``Deferred`` is chained,
it can no longer accept new callbacks.
:mochidef:`Deferred.prototype.addErrback(func)`:
Add a single errback to the end of the callback sequence.
If additional arguments are given, then ``func`` will be replaced
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
differs from `Twisted`_, because the result of the errback will
be the *last* argument passed to ``func``.
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
(its value or error will be passed to the next callback). Note that
once the returned ``Deferred`` is chained, it can no longer accept new
callbacks.
:mochidef:`Deferred.prototype.callback([result])`:
Begin the callback sequence with a non-``Error`` result. Result
may be any value except for a :mochiref:`Deferred`.
Either ``.callback`` or ``.errback`` should
be called exactly once on a :mochiref:`Deferred`.
:mochidef:`Deferred.prototype.cancel()`:
Cancels a :mochiref:`Deferred` that has not yet received a value,
or is waiting on another :mochiref:`Deferred` as its value.
If a canceller is defined, the canceller is called.
If the canceller did not return an ``Error``, or there
was no canceller, then the errback chain is started
with :mochiref:`CancelledError`.
:mochidef:`Deferred.prototype.errback([result])`:
Begin the callback sequence with an error result.
Result may be any value except for a :mochiref:`Deferred`,
but if ``!(result instanceof Error)``, it will be wrapped
with :mochiref:`GenericError`.
Either ``.callback`` or ``.errback`` should
be called exactly once on a :mochidef:`Deferred`.
:mochidef:`DeferredLock()`:
A lock for asynchronous systems.
The ``locked`` property of a :mochiref:`DeferredLock` will be ``true`` if
it locked, ``false`` otherwise. Do not change this property.
:mochidef:`DeferredLock.prototype.acquire()`:
Attempt to acquire the lock. Returns a :mochiref:`Deferred` that fires on
lock acquisition with the :mochiref:`DeferredLock` as the value.
If the lock is locked, then the :mochiref:`Deferred` goes into a waiting
list.
:mochidef:`DeferredLock.prototype.release()`:
Release the lock. If there is a waiting list, then the first
:mochiref:`Deferred` in that waiting list will be called back.
:mochidef:`DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])`:
Combine a list of :mochiref:`Deferred` into one. Track the callbacks and
return a list of (success, result) tuples, 'success' being a boolean
indicating whether result is a normal result or an error.
Once created, you have access to all :mochiref:`Deferred` methods, like
addCallback, addErrback, addBoth. The behaviour can be changed by the
following options:
``fireOnOneCallback``:
Flag for launching the callback once the first Deferred of the list
has returned.
``fireOnOneErrback``:
Flag for calling the errback at the first error of a Deferred.
``consumeErrors``:
Flag indicating that any errors raised in the Deferreds should be
consumed by the DeferredList.
Example::
// We need to fetch data from 2 different urls
var d1 = loadJSONDoc(url1);
var d2 = loadJSONDoc(url2);
var l1 = new DeferredList([d1, d2], false, false, true);
l1.addCallback(function (resultList) {
MochiKit.Base.map(function (result) {
if (result[0]) {
alert("Data is here: " + result[1]);
} else {
alert("Got an error: " + result[1]);
}
}, resultList);
});
Functions
---------
:mochidef:`callLater(seconds, func[, args...])`:
Call ``func(args...)`` after at least ``seconds`` seconds have elapsed.
This is a convenience method for::
func = partial.apply(extend(null, arguments, 1));
return wait(seconds).addCallback(function (res) { return func() });
Returns a cancellable :mochiref:`Deferred`.
:mochidef:`doSimpleXMLHttpRequest(url[, queryArguments...])`:
Perform a simple ``XMLHttpRequest`` and wrap it with a
:mochiref:`Deferred` that may be cancelled.
Note that currently, only ``200`` (OK) and ``304``
(NOT_MODIFIED) are considered success codes at this time, other
status codes will result in an errback with an ``XMLHttpRequestError``.
``url``:
The URL to GET
``queryArguments``:
If this function is called with more than one argument, a ``"?"``
and the result of :mochiref:`MochiKit.Base.queryString` with
the rest of the arguments are appended to the URL.
For example, this will do a GET request to the URL
``http://example.com?bar=baz``::
doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
*returns*:
:mochiref:`Deferred` that will callback with the ``XMLHttpRequest``
instance on success
:mochidef:`evalJSONRequest(req)`:
Evaluate a JSON [4]_ ``XMLHttpRequest``
``req``:
The request whose ``.responseText`` property is to be evaluated
*returns*:
A JavaScript object
:mochidef:`fail([result])`:
Return a :mochiref:`Deferred` that has already had ``.errback(result)``
called.
See ``succeed`` documentation for rationale.
``result``:
The result to give to :mochiref:`Deferred.prototype.errback(result)`.
*returns*:
A ``new`` :mochiref:`Deferred()`
:mochidef:`gatherResults(deferreds)`:
A convenience function that returns a :mochiref:`DeferredList`
from the given ``Array`` of :mochiref:`Deferred` instances
that will callback with an ``Array`` of just results when
they're available, or errback on the first array.
:mochidef:`getXMLHttpRequest()`:
Return an ``XMLHttpRequest`` compliant object for the current
platform.
In order of preference:
- ``new XMLHttpRequest()``
- ``new ActiveXObject('Msxml2.XMLHTTP')``
- ``new ActiveXObject('Microsoft.XMLHTTP')``
- ``new ActiveXObject('Msxml2.XMLHTTP.4.0')``
:mochidef:`maybeDeferred(func[, argument...])`:
Call a ``func`` with the given arguments and ensure the result is a
:mochiref:`Deferred`.
``func``:
The function to call.
*returns*:
A new :mochiref:`Deferred` based on the call to ``func``. If ``func``
does not naturally return a :mochiref:`Deferred`, its result or error
value will be wrapped by one.
:mochidef:`loadJSONDoc(url)`:
Do a simple ``XMLHttpRequest`` to a URL and get the response
as a JSON [4]_ document.
``url``:
The URL to GET
*returns*:
:mochiref:`Deferred` that will callback with the evaluated JSON [4]_
response upon successful ``XMLHttpRequest``
:mochidef:`sendXMLHttpRequest(req[, sendContent])`:
Set an ``onreadystatechange`` handler on an ``XMLHttpRequest`` object
and send it off. Will return a cancellable :mochiref:`Deferred` that will
callback on success.
Note that currently, only ``200`` (OK) and ``304``
(NOT_MODIFIED) are considered success codes at this time, other
status codes will result in an errback with an ``XMLHttpRequestError``.
``req``:
An preconfigured ``XMLHttpRequest`` object (open has been called).
``sendContent``:
Optional string or DOM content to send over the ``XMLHttpRequest``.
*returns*:
:mochiref:`Deferred` that will callback with the ``XMLHttpRequest``
instance on success.
:mochidef:`succeed([result])`:
Return a :mochiref:`Deferred` that has already had ``.callback(result)``
called.
This is useful when you're writing synchronous code to an asynchronous
interface: i.e., some code is calling you expecting a :mochiref:`Deferred`
result, but you don't actually need to do anything asynchronous. Just
return ``succeed(theResult)``.
See ``fail`` for a version of this function that uses a failing
:mochiref:`Deferred` rather than a successful one.
``result``:
The result to give to :mochiref:`Deferred.prototype.callback(result)`
*returns*:
a ``new`` :mochiref:`Deferred`
:mochidef:`wait(seconds[, res])`:
Return a new cancellable :mochiref:`Deferred` that will ``.callback(res)``
after at least ``seconds`` seconds have elapsed.
See Also
========
.. [1] AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX
.. [2] Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/
.. [3] Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
.. [4] JSON, JavaScript Object Notation: http://json.org/
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,481 +0,0 @@
.. title:: MochiKit.Color - color abstraction with CSS3 support
Name
====
MochiKit.Color - color abstraction with CSS3 support
Synopsis
========
::
// RGB color expressions are supported
assert(
objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
);
// So is instantiating directly from HSL or RGB values.
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
// Or even SVG color keyword names, as per CSS3!
assert( Color.fromString("aquamarine"), "#7fffd4" );
// NSColor-like colors built in
assert( Color.whiteColor().toHexString() == "#ffffff" );
Description
===========
MochiKit.Color is an abstraction for handling colors and strings that
represent colors.
Dependencies
============
- :mochiref:`MochiKit.Base`
Overview
========
MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha.
It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG)
color table.
All of the functionality in this module is exposed through a Color constructor
and its prototype, but a few of its internals are available for direct use at
module level.
API Reference
=============
Constructors
------------
:mochidef:`Color()`:
Represents a color. Component values should be integers between ``0.0``
and ``1.0``. You should use one of the :mochiref:`Color` factory
functions such as :mochiref:`Color.fromRGB`, :mochiref:`Color.fromHSL`,
etc. instead of constructing :mochiref:`Color` objects directly.
:mochiref:`Color` instances can be compared with
:mochiref:`MochiKit.Base.compare` (though ordering is on RGB, so is not
particularly meaningful except for equality), and the default ``toString``
implementation returns :mochiref:`Color.prototype.toHexString()`.
:mochiref:`Color` instances are immutable, and much of the architecture is
inspired by AppKit's NSColor [1]_
:mochidef:`Color.fromBackground(elem)`:
Returns a :mochiref:`Color` object based on the background of the provided
element. Equivalent to::
c = Color.fromComputedStyle(
elem, "backgroundColor", "background-color") || Color.whiteColor();
:mochidef:`Color.fromComputedStyle(elem, style, mozillaEquivalentCSS)`:
Returns a :mochiref:`Color` object based on the result of
:mochiref:`MochiKit.DOM.computedStyle(elem, style, mozillaEquivalentCSS)`
or ``null`` if not found.
:mochidef:`Color.fromHexString(hexString)`:
Returns a :mochiref:`Color` object from the given hexadecimal color string.
For example, ``"#FFFFFF"`` would return a :mochiref:`Color` with
RGB values ``[255/255, 255/255, 255/255]`` (white).
:mochidef:`Color.fromHSL(hue, saturation, lightness, alpha=1.0)`:
Return a :mochiref:`Color` object from the given ``hue``, ``saturation``,
``lightness`` values. Values should be numbers between ``0.0`` and
``1.0``.
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
Alternate form:
:mochiref:`Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})`
:mochidef:`Color.fromHSLString(hslString)`:
Returns a :mochiref:`Color` object from the given decimal hsl color string.
For example, ``"hsl(0,0%,100%)"`` would return a :mochiref:`Color` with
HSL values ``[0/360, 0/360, 360/360]`` (white).
:mochidef:`Color.fromHSV(hue, saturation, value, alpha=1.0)`:
Return a :mochiref:`Color` object from the given ``hue``, ``saturation``,
``value`` values. Values should be numbers between ``0.0`` and
``1.0``.
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
Alternate form:
:mochiref:`Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})`
:mochidef:`Color.fromName(colorName)`:
Returns a :mochiref:`Color` object corresponding to the given
SVG 1.0 color keyword name [2]_ as per the W3C CSS3
Color Module [3]_. ``"transparent"`` is also accepted
as a color name, and will return :mochiref:`Color.transparentColor()`.
:mochidef:`Color.fromRGB(red, green, blue, alpha=1.0)`:
Return a :mochiref:`Color` object from the given ``red``, ``green``,
``blue``, and ``alpha`` values. Values should be numbers between ``0``
and ``1.0``.
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
Alternate form:
:mochiref:`Color.fromRGB({r: red, g: green, b: blue, a: alpha})`
:mochidef:`Color.fromRGBString(rgbString)`:
Returns a :mochiref:`Color` object from the given decimal rgb color string.
For example, ``"rgb(255,255,255)"`` would return a :mochiref:`Color` with
RGB values ``[255/255, 255/255, 255/255]`` (white).
:mochidef:`Color.fromText(elem)`:
Returns a :mochiref:`Color` object based on the text color of the provided
element. Equivalent to::
c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
:mochidef:`Color.fromString(rgbOrHexString)`:
Returns a :mochiref:`Color` object from the given RGB, HSL, hex, or name.
Will return ``null`` if the string can not be parsed by any of these
methods.
See :mochiref:`Color.fromHexString`, :mochiref:`Color.fromRGBString`,
:mochiref:`Color.fromHSLString` and :mochiref:`Color.fromName` more
information.
:mochidef:`Color.namedColors()`:
Returns an object with properties for each SVG 1.0 color keyword
name [2]_ supported by CSS3 [3]_. Property names are the color keyword
name in lowercase, and the value is a string suitable for
:mochiref:`Color.fromString()`.
:mochidef:`Color.prototype.colorWithAlpha(alpha)`:
Return a new :mochiref:`Color` based on this color, but with the provided
``alpha`` value.
:mochidef:`Color.prototype.colorWithHue(hue)`:
Return a new :mochiref:`Color` based on this color, but with the provided
``hue`` value.
:mochidef:`Color.prototype.colorWithSaturation(saturation)`:
Return a new :mochiref:`Color` based on this color, but with the provided
``saturation`` value (using the HSL color model).
:mochidef:`Color.prototype.colorWithLightness(lightness)`:
Return a new :mochiref:`Color` based on this color, but with the provided
``lightness`` value.
:mochidef:`Color.prototype.darkerColorWithLevel(level)`:
Return a new :mochiref:`Color` based on this color, but darker by the given
``level`` (between ``0`` and ``1.0``).
:mochidef:`Color.prototype.lighterColorWithLevel(level)`:
Return a new :mochiref:`Color` based on this color, but lighter by the given
``level`` (between ``0`` and ``1.0``).
:mochidef:`Color.prototype.blendedColor(other, fraction=0.5)`:
Return a new :mochiref:`Color` whose RGBA component values are a weighted sum
of this color and ``other``. Each component of the returned color
is the ``fraction`` of other's value plus ``1 - fraction`` of this
color's.
:mochidef:`Color.prototype.isLight()`:
Return ``true`` if the lightness value of this color is greater than
``0.5``.
Note that ``alpha`` is ignored for this calculation (color components
are not premultiplied).
:mochidef:`Color.prototype.isDark()`:
Return ``true`` if the lightness value of this color is less than or
equal to ``0.5``.
Note that ``alpha`` is ignored for this calculation (color components
are not premultiplied).
:mochidef:`Color.prototype.toRGBString()`:
Return the decimal ``"rgb(red, green, blue)"`` string representation of this
color.
If the alpha component is not ``1.0`` (fully opaque), the
``"rgba(red, green, blue, alpha)"`` string representation will be used.
For example::
assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
:mochidef:`Color.prototype.toHSLString()`:
Return the decimal ``"hsl(hue, saturation, lightness)"``
string representation of this color.
If the alpha component is not ``1.0`` (fully opaque), the
``"hsla(hue, saturation, lightness, alpha)"`` string representation
will be used.
For example::
assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
:mochidef:`Color.prototype.toHexString()`:
Return the hexadecimal ``"#RRGGBB"`` string representation of this color.
Note that the alpha component is completely ignored for hexadecimal
string representations!
For example::
assert( Color.whiteColor().toHexString() == "#FFFFFF" );
:mochidef:`Color.prototype.asRGB()`:
Return the RGB (red, green, blue, alpha) components of this color as an
object with ``r``, ``g``, ``b``, and ``a`` properties that have
values between ``0.0`` and ``1.0``.
:mochidef:`Color.prototype.asHSL()`:
Return the HSL (hue, saturation, lightness, alpha) components of this
color as an object with ``h``, ``s``, ``l`` and ``a`` properties
that have values between ``0.0`` and ``1.0``.
:mochidef:`Color.prototype.asHSV()`:
Return the HSV (hue, saturation, value, alpha) components of this
color as an object with ``h``, ``s``, ``v`` and ``a`` properties
that have values between ``0.0`` and ``1.0``.
:mochidef:`Color.blackColor()`:
Return a :mochiref:`Color` object whose RGB values are 0, 0, 0
(#000000).
:mochidef:`Color.blueColor()`:
Return a :mochiref:`Color` object whose RGB values are 0, 0, 1
(#0000ff).
:mochidef:`Color.brownColor()`:
Return a :mochiref:`Color` object whose RGB values are 0.6, 0.4, 0.2
(#996633).
:mochidef:`Color.cyanColor()`:
Return a :mochiref:`Color` object whose RGB values are 0, 1, 1
(#00ffff).
:mochidef:`Color.darkGrayColor()`:
Return a :mochiref:`Color` object whose RGB values are 1/3, 1/3, 1/3
(#555555).
:mochidef:`Color.grayColor()`:
Return a :mochiref:`Color` object whose RGB values are 0.5, 0.5, 0.5
(#808080).
:mochidef:`Color.greenColor()`:
Return a :mochiref:`Color` object whose RGB values are 0, 1, 0.
(#00ff00).
:mochidef:`Color.lightGrayColor()`:
Return a :mochiref:`Color` object whose RGB values are 2/3, 2/3, 2/3
(#aaaaaa).
:mochidef:`Color.magentaColor()`:
Return a :mochiref:`Color` object whose RGB values are 1, 0, 1
(#ff00ff).
:mochidef:`Color.orangeColor()`:
Return a :mochiref:`Color` object whose RGB values are 1, 0.5, 0
(#ff8000).
:mochidef:`Color.purpleColor()`:
Return a :mochiref:`Color` object whose RGB values are 0.5, 0, 0.5
(#800080).
:mochidef:`Color.redColor()`:
Return a :mochiref:`Color` object whose RGB values are 1, 0, 0
(#ff0000).
:mochidef:`Color.whiteColor()`:
Return a :mochiref:`Color` object whose RGB values are 1, 1, 1
(#ffffff).
:mochidef:`Color.yellowColor()`:
Return a :mochiref:`Color` object whose RGB values are 1, 1, 0
(#ffff00).
:mochidef:`Color.transparentColor()`:
Return a :mochiref:`Color` object that is completely transparent
(has alpha component of 0).
Functions
---------
:mochidef:`clampColorComponent(num, scale)`:
Returns ``num * scale`` clamped between ``0`` and ``scale``.
:mochiref:`clampColorComponent` is not exported by default when using JSAN.
:mochidef:`hslToRGB(hue, saturation, lightness, alpha)`:
Computes RGB values from the provided HSL values. The return value is a
mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
Alternate form:
:mochiref:`hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})`.
:mochiref:`hslToRGB` is not exported by default when using JSAN.
:mochidef:`hsvToRGB(hue, saturation, value, alpha)`:
Computes RGB values from the provided HSV values. The return value is a
mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
Alternate form:
:mochiref:`hsvToRGB({h: hue, s: saturation, v: value, a: alpha})`.
:mochiref:`hsvToRGB` is not exported by default when using JSAN.
:mochidef:`toColorPart(num)`:
Convert num to a zero padded hexadecimal digit for use in a hexadecimal
color string. Num should be an integer between ``0`` and ``255``.
:mochiref:`toColorPart` is not exported by default when using JSAN.
:mochidef:`rgbToHSL(red, green, blue, alpha)`:
Computes HSL values based on the provided RGB values. The return value is
a mapping with ``"h"``, ``"s"``, ``"l"`` and ``"a"`` keys.
Alternate form:
:mochiref:`rgbToHSL({r: red, g: green, b: blue, a: alpha})`.
:mochiref:`rgbToHSL` is not exported by default when using JSAN.
:mochidef:`rgbToHSV(red, green, blue, alpha)`:
Computes HSV values based on the provided RGB values. The return value is
a mapping with ``"h"``, ``"s"``, ``"v"`` and ``"a"`` keys.
Alternate form:
:mochiref:`rgbToHSV({r: red, g: green, b: blue, a: alpha})`.
:mochiref:`rgbToHSV` is not exported by default when using JSAN.
See Also
========
.. [1] Application Kit Reference - NSColor: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html
.. [2] SVG 1.0 color keywords: http://www.w3.org/TR/SVG/types.html#ColorKeywords
.. [3] W3C CSS3 Color Module: http://www.w3.org/TR/css3-color/#svg-color
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,782 +0,0 @@
.. title:: MochiKit.DOM - painless DOM manipulation API
Name
====
MochiKit.DOM - painless DOM manipulation API
Synopsis
========
::
var rows = [
["dataA1", "dataA2", "dataA3"],
["dataB1", "dataB2", "dataB3"]
];
row_display = function (row) {
return TR(null, map(partial(TD, null), row));
}
var newTable = TABLE({'class': 'prettytable'},
THEAD(null,
row_display(["head1", "head2", "head3"])),
TFOOT(null,
row_display(["foot1", "foot2", "foot3"])),
TBODY(null,
map(row_display, rows)));
// put that in your document.createElement and smoke it!
swapDOM(oldTable, newTable);
Description
===========
As you probably know, the DOM APIs are some of the most painful Java-inspired
APIs you'll run across from a highly dynamic language. Don't worry about that
though, because they provide a reasonable basis to build something that
sucks a lot less.
MochiKit.DOM takes much of its inspiration from Nevow's [1]_ stan [2]_.
This means you choose a tag, give it some attributes, then stuff it full
of *whatever objects you want*. MochiKit.DOM isn't stupid, it knows that
a string should be a text node, and that you want functions to be called,
and that ``Array``-like objects should be expanded, and stupid ``null`` values
should be skipped.
Hell, it will let you return strings from functions, and use iterators from
:mochiref:`MochiKit.Iter`. If that's not enough, just teach it new tricks with
:mochiref:`registerDOMConverter`. If you have never used an API like this for
creating DOM elements, you've been wasting your damn time. Get with it!
Dependencies
============
- :mochiref:`MochiKit.Base`
- :mochiref:`MochiKit.Iter`
Overview
========
DOM Coercion Rules
------------------
In order of precedence, :mochiref:`createDOM` coerces given arguments to DOM
nodes using the following rules:
1. Functions are called with a ``this`` of the parent
node and their return value is subject to the
following rules (even this one).
2. ``undefined`` and ``null`` are ignored.
3. Iterables (see :mochiref:`MochiKit.Iter`) are flattened
(as if they were passed in-line as nodes) and each
return value is subject to all of these rules.
4. Values that look like DOM nodes (objects with a
``.nodeType > 0``) are ``.appendChild``'ed to the created
DOM fragment.
5. Strings are wrapped up with ``document.createTextNode``
6. Objects that are not strings are run through the ``domConverters``
:mochiref:`MochiKit.Base.AdapterRegistry`
(see :mochiref:`registerDOMConverter`).
The value returned by the adapter is subject to these same rules (e.g.
adapters are allowed to return a string, which will be coerced into a
text node).
7. If no adapter is available, ``.toString()`` is used to create a text node.
Creating DOM Element Trees
--------------------------
:mochiref:`createDOM` provides you with an excellent facility for creating DOM trees
that is easy on the wrists. One of the best ways to understand how to use
it is to take a look at an example::
var rows = [
["dataA1", "dataA2", "dataA3"],
["dataB1", "dataB2", "dataB3"]
];
row_display = function (row) {
return TR(null, map(partial(TD, null), row));
}
var newTable = TABLE({'class': 'prettytable'},
THEAD(null,
row_display(["head1", "head2", "head3"])),
TFOOT(null,
row_display(["foot1", "foot2", "foot3"])),
TBODY(null,
map(row_display, rows)));
This will create a table with the following visual layout (if it
were inserted into the document DOM):
+--------+--------+--------+
| head1 | head2 | head3 |
+========+========+========+
| dataA1 | dataA2 | dataA3 |
+--------+--------+--------+
| dataB1 | dataB2 | dataB3 |
+--------+--------+--------+
| foot1 | foot2 | foot3 |
+--------+--------+--------+
Corresponding to the following HTML::
<table class="prettytable">
<thead>
<tr>
<td>head1</td>
<td>head2</td>
<td>head3</td>
</tr>
</thead>
<tfoot>
<tr>
<td>foot1</td>
<td>foot2</td>
<td>foot3</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>dataA1</td>
<td>dataA2</td>
<td>dataA3</td>
</tr>
<tr>
<td>dataB1</td>
<td>dataB2</td>
<td>dataB3</td>
</tr>
</tbody>
</table>
DOM Context
-----------
In order to prevent having to pass a ``window`` and/or ``document``
variable to every MochiKit.DOM function (e.g. when working with a
child window), MochiKit.DOM maintains a context variable for each
of them. They are managed with the :mochiref:`withWindow` and
:mochiref:`withDocument` functions, and can be acquired with
:mochiref:`currentWindow()` and :mochiref:`currentDocument()`
For example, if you are creating DOM nodes in a child window, you
could do something like this::
withWindow(child, function () {
var doc = currentDocument();
appendChildNodes(doc.body, H1(null, "This is in the child!"));
});
Note that :mochiref:`withWindow(win, ...)` also implies
:mochiref:`withDocument(win.document, ...)`.
Element Visibility
------------------
The :mochiref:`hideElement` and :mochiref:`showElement` functions are
provided as a convenience, but only work for elements that are
``display: block``. For a general solution to showing, hiding, and checking
the explicit visibility of elements, we recommend using a solution that
involves a little CSS. Here's an example::
<style type="text/css">
.invisible { display: none; }
</style>
<script type="text/javascript">
function toggleVisible(elem) {
toggleElementClass("invisible", elem);
}
function makeVisible(elem) {
removeElementClass(elem, "invisible");
}
function makeInvisible(elem) {
addElementClass(elem, "invisible");
}
function isVisible(elem) {
// you may also want to check for
// getElement(elem).style.display == "none"
return !hasElementClass(elem, "invisible");
};
</script>
MochiKit doesn't ship with such a solution, because there is no reliable and
portable method for adding CSS rules on the fly with JavaScript.
API Reference
=============
Functions
---------
:mochidef:`$(id[, ...])`:
An alias for :mochiref:`getElement(id[, ...])`
:mochidef:`addElementClass(element, className)`:
Ensure that the given ``element`` has ``className`` set as part of its
class attribute. This will not disturb other class names.
``element`` is looked up with :mochiref:`getElement`, so string identifiers
are also acceptable.
:mochidef:`addLoadEvent(func)`:
Note that :mochiref:`addLoadEvent` can not be used in combination with
:mochiref:`MochiKit.Signal` if the ``onload`` event is connected.
Once an event is connected with :mochiref:`MochiKit.Signal`, no other APIs
may be used for that same event.
This will stack ``window.onload`` functions on top of each other.
Each function added will be called after ``onload`` in the
order that they were added.
:mochidef:`addToCallStack(target, path, func[, once])`:
Note that :mochiref:`addToCallStack` is not compatible with
:mochiref:`MochiKit.Signal`. Once an event is connected with
:mochiref:`MochiKit.Signal`, no other APIs may be used for that same event.
Set the property ``path`` of ``target`` to a function that calls the
existing function at that property (if any), then calls ``func``.
If ``target[path]()`` returns exactly ``false``, then ``func`` will
not be called.
If ``once`` is ``true``, then ``target[path]`` is set to ``null`` after
the function call stack has completed.
If called several times for the same ``target[path]``, it will create
a stack of functions (instead of just a pair).
:mochidef:`appendChildNodes(node[, childNode[, ...]])`:
Append children to a DOM element using the `DOM Coercion Rules`_.
``node``:
A reference to the DOM element to add children to
(if a string is given, :mochiref:`getElement(node)`
will be used to locate the node)
``childNode``...:
All additional arguments, if any, will be coerced into DOM
nodes that are appended as children using the
`DOM Coercion Rules`_.
*returns*:
The given DOM element
:mochidef:`computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)`:
Looks up a CSS property for the given element. The element can be
specified as either a string with the element's ID or the element
object itself.
:mochidef:`createDOM(name[, attrs[, node[, ...]]])`:
Create a DOM fragment in a really convenient manner, much like
Nevow`s [1]_ stan [2]_.
Partially applied versions of this function for common tags are
available as aliases:
- ``A``
- ``BUTTON``
- ``BR``
- ``CANVAS``
- ``DIV``
- ``FIELDSET``
- ``FORM``
- ``H1``
- ``H2``
- ``H3``
- ``HR``
- ``IMG``
- ``INPUT``
- ``LABEL``
- ``LEGEND``
- ``LI``
- ``OL``
- ``OPTGROUP``
- ``OPTION``
- ``P``
- ``PRE``
- ``SELECT``
- ``SPAN``
- ``STRONG``
- ``TABLE``
- ``TBODY``
- ``TD``
- ``TEXTAREA``
- ``TFOOT``
- ``TH``
- ``THEAD``
- ``TR``
- ``TT``
- ``UL``
See `Creating DOM Element Trees`_ for a comprehensive example.
``name``:
The kind of fragment to create (e.g. 'span'), such as you would
pass to ``document.createElement``.
``attrs``:
An object whose properties will be used as the attributes
(e.g. ``{'style': 'display:block'}``), or ``null`` if no
attributes need to be set.
See :mochiref:`updateNodeAttributes` for more information.
For convenience, if ``attrs`` is a string, ``null`` is used
and the string will be considered the first ``node``.
``node``...:
All additional arguments, if any, will be coerced into DOM
nodes that are appended as children using the
`DOM Coercion Rules`_.
*returns*:
A DOM element
:mochidef:`createDOMFunc(tag[, attrs[, node[, ...]]])`:
Convenience function to create a partially applied createDOM
function. You'd want to use this if you add additional convenience
functions for creating tags, or if you find yourself creating
a lot of tags with a bunch of the same attributes or contents.
See :mochiref:`createDOM` for more detailed descriptions of the arguments.
``tag``:
The name of the tag
``attrs``:
Optionally specify the attributes to apply
``node``...:
Optionally specify any children nodes it should have
*returns*:
function that takes additional arguments and calls
:mochiref:`createDOM`
:mochidef:`currentDocument()`:
Return the current ``document`` `DOM Context`_. This will always
be the same as the global ``document`` unless :mochiref:`withDocument` or
:mochiref:`withWindow` is currently executing.
:mochidef:`currentWindow()`:
Return the current ``window`` `DOM Context`_. This will always
be the same as the global ``window`` unless :mochiref:`withWindow` is
currently executing.
:mochidef:`elementDimensions(element)`:
Return the absolute pixel width and height of ``element`` as an object with
``w`` and ``h`` properties, or ``undefined`` if ``element`` is not in the
document. ``element`` may be specified as a string to be looked up with
:mochiref:`getElement`, a DOM element, or trivially as an object with
``w`` and/or ``h`` properties.
:mochidef:`elementPosition(element[, relativeTo={x: 0, y: 0}])`:
Return the absolute pixel position of ``element`` in the document as an
object with ``x`` and ``y`` properties, or ``undefined`` if ``element``
is not in the document. ``element`` may be specified as a string to
be looked up with :mochiref:`getElement`, a DOM element, or trivially
as an object with ``x`` and/or ``y`` properties.
If ``relativeTo`` is given, then its coordinates are subtracted from
the absolute position of ``element``, e.g.::
var elemPos = elementPosition(elem);
var anotherElemPos = elementPosition(anotherElem);
var relPos = elementPosition(elem, anotherElem);
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
assert( relPos.y == (elemPos.y - anotherElemPos.y) );
``relativeTo`` may be specified as a string to be looked up with
:mochiref:`getElement`, a DOM element, or trivially as an object
with ``x`` and/or ``y`` properties.
:mochidef:`emitHTML(dom[, lst])`:
Convert a DOM tree to an ``Array`` of HTML string fragments
You probably want to use :mochiref:`toHTML` instead.
:mochidef:`escapeHTML(s)`:
Make a string safe for HTML, converting the usual suspects (lt,
gt, quot, apos, amp)
:mochidef:`focusOnLoad(element)`:
Add an onload event to focus the given element
:mochidef:`formContents(elem)`:
Search the DOM tree, starting at ``elem``, for any elements with a
``name`` and ``value`` attribute. Return a 2-element ``Array`` of
``names`` and ``values`` suitable for use with
:mochiref:`MochiKit.Base.queryString`.
:mochidef:`getElement(id[, ...])`:
A small quick little function to encapsulate the ``getElementById``
method. It includes a check to ensure we can use that method.
If the id isn't a string, it will be returned as-is.
Also available as :mochiref:`$(...)` for convenience and compatibility with
other JavaScript frameworks.
If multiple arguments are given, an ``Array`` will be returned.
:mochidef:`getElementsByTagAndClassName(tagName, className, parent=document)`:
Returns an array of elements in ``parent`` that match the tag name
and class name provided. If ``parent`` is a string, it will be looked
up with :mochiref:`getElement`.
If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
for the matching class.
If ``className`` is ``null``, all elements matching the provided tag are
returned.
:mochidef:`getNodeAttribute(node, attr)`:
Get the value of the given attribute for a DOM element without
ever raising an exception (will return ``null`` on exception).
``node``:
A reference to the DOM element to update (if a string is given,
:mochiref:`getElement(node)` will be used to locate the node)
``attr``:
The name of the attribute
Note that it will do the right thing for IE, so don't do
the ``class`` -> ``className`` hack yourself.
*returns*:
The attribute's value, or ``null``
:mochidef:`getViewportDimensions()`:
Return the pixel width and height of the viewport as an object with ``w``
and ``h`` properties. ``element`` is looked up with
:mochiref:`getElement`, so string identifiers are also acceptable.
:mochidef:`hasElementClass(element, className[, ...])`:
Return ``true`` if ``className`` is found on the ``element``.
``element`` is looked up with :mochiref:`getElement`, so string identifiers
are also acceptable.
:mochidef:`hideElement(element, ...)`:
Partial form of :mochiref:`setDisplayForElement`, specifically::
partial(setDisplayForElement, "none")
For information about the caveats of using a ``style.display`` based
show/hide mechanism, and a CSS based alternative, see
`Element Visibility`_.
:mochidef:`registerDOMConverter(name, check, wrap[, override])`:
Register an adapter to convert objects that match ``check(obj, ctx)``
to a DOM element, or something that can be converted to a DOM
element (i.e. number, bool, string, function, iterable).
:mochidef:`removeElement(node)`:
Remove and return ``node`` from a DOM tree. This is technically
just a convenience for :mochiref:`swapDOM(node, null)`.
``node``:
the DOM element (or string id of one) to be removed
*returns*
The removed element
:mochidef:`removeElementClass(element, className)`:
Ensure that the given ``element`` does not have ``className`` set as part
of its class attribute. This will not disturb other class names.
``element`` is looked up with :mochiref:`getElement`, so string identifiers
are also acceptable.
:mochidef:`replaceChildNodes(node[, childNode[, ...]])`:
Remove all children from the given DOM element, then append any given
childNodes to it (by calling :mochiref:`appendChildNodes`).
``node``:
A reference to the DOM element to add children to
(if a string is given, :mochiref:`getElement(node)`
will be used to locate the node)
``childNode``...:
All additional arguments, if any, will be coerced into DOM
nodes that are appended as children using the
`DOM Coercion Rules`_.
*returns*:
The given DOM element
:mochidef:`scrapeText(node[, asArray=false])`:
Walk a DOM tree in-order and scrape all of the text out of it as a
``string``.
If ``asArray`` is ``true``, then an ``Array`` will be returned with
each individual text node. These two are equivalent::
assert( scrapeText(node) == scrapeText(node, true).join("") );
:mochidef:`setDisplayForElement(display, element[, ...])`:
Change the ``style.display`` for the given element(s). Usually
used as the partial forms:
- :mochiref:`showElement(element, ...)`
- :mochiref:`hideElement(element, ...)`
Elements are looked up with :mochiref:`getElement`, so string identifiers
are acceptable.
For information about the caveats of using a ``style.display`` based
show/hide mechanism, and a CSS based alternative, see
`Element Visibility`_.
:mochidef:`setElementClass(element, className)`:
Set the entire class attribute of ``element`` to ``className``.
``element`` is looked up with :mochiref:`getElement`, so string identifiers
are also acceptable.
:mochidef:`setElementDimensions(element, dimensions[, units='px'])`:
Sets the dimensions of ``element`` in the document from an
object with ``w`` and ``h`` properties.
``node``:
A reference to the DOM element to update (if a string is given,
:mochiref:`getElement(node)` will be used to locate the node)
``dimensions``:
An object with ``w`` and ``h`` properties
``units``:
Optionally set the units to use, default is ``px``
:mochidef:`setElementPosition(element, position[, units='px'])`:
Sets the absolute position of ``element`` in the document from an
object with ``x`` and ``y`` properties.
``node``:
A reference to the DOM element to update (if a string is given,
:mochiref:`getElement(node)` will be used to locate the node)
``position``:
An object with ``x`` and ``y`` properties
``units``:
Optionally set the units to use, default is ``px``
:mochidef:`setNodeAttribute(node, attr, value)`:
Set the value of the given attribute for a DOM element without
ever raising an exception (will return null on exception). If
setting more than one attribute, you should use
:mochiref:`updateNodeAttributes`.
``node``:
A reference to the DOM element to update (if a string is given,
:mochiref:`getElement(node)` will be used to locate the node)
``attr``:
The name of the attribute
Note that it will do the right thing for IE, so don't do
the ``class`` -> ``className`` hack yourself.
``value``:
The value of the attribute, may be an object to be merged
(e.g. for setting style).
*returns*:
The given DOM element or ``null`` on failure
:mochidef:`setOpacity(element, opacity)`:
Sets ``opacity`` for ``element``. Valid ``opacity`` values range from 0
(invisible) to 1 (opaque). ``element`` is looked up with
:mochiref:`getElement`, so string identifiers are also acceptable.
:mochidef:`showElement(element, ...)`:
Partial form of :mochiref:`setDisplayForElement`, specifically::
partial(setDisplayForElement, "block")
For information about the caveats of using a ``style.display`` based
show/hide mechanism, and a CSS based alternative, see
`Element Visibility`_.
:mochidef:`swapDOM(dest, src)`:
Replace ``dest`` in a DOM tree with ``src``, returning ``src``.
``dest``:
a DOM element (or string id of one) to be replaced
``src``:
the DOM element (or string id of one) to replace it with, or
``null`` if ``dest`` is to be removed (replaced with nothing).
*returns*:
a DOM element (``src``)
:mochidef:`swapElementClass(element, fromClass, toClass)`:
If ``fromClass`` is set on ``element``, replace it with ``toClass``.
This will not disturb other classes on that element.
``element`` is looked up with :mochiref:`getElement`, so string identifiers
are also acceptable.
:mochidef:`toggleElementClass(className[, element[, ...]])`:
Toggle the presence of a given ``className`` in the class attribute
of all given elements. All elements will be looked up with
:mochiref:`getElement`, so string identifiers are acceptable.
:mochidef:`toHTML(dom)`:
Convert a DOM tree to a HTML string using :mochiref:`emitHTML`
:mochidef:`updateNodeAttributes(node, attrs)`:
Update the attributes of a DOM element from a given object.
``node``:
A reference to the DOM element to update (if a string is given,
:mochiref:`getElement(node)` will be used to locate the node)
``attrs``:
An object whose properties will be used to set the attributes
(e.g. ``{'class': 'invisible'}``), or ``null`` if no
attributes need to be set. If an object is given for the
attribute value (e.g. ``{'style': {'display': 'block'}}``)
then :mochiref:`MochiKit.Base.updatetree` will be used to set that
attribute.
Note that it will do the right thing for IE, so don't do
the ``class`` -> ``className`` hack yourself, and it deals with
setting "on..." event handlers correctly.
*returns*:
The given DOM element
:mochidef:`withWindow(win, func)`:
Call ``func`` with the ``window`` `DOM Context`_ set to ``win`` and
the ``document`` `DOM Context`_ set to ``win.document``. When
``func()`` returns or throws an error, the `DOM Context`_ will be
restored to its previous state.
The return value of ``func()`` is returned by this function.
:mochidef:`withDocument(doc, func)`:
Call ``func`` with the ``doc`` `DOM Context`_ set to ``doc``.
When ``func()`` returns or throws an error, the `DOM Context`_
will be restored to its previous state.
The return value of ``func()`` is returned by this function.
See Also
========
.. [1] Nevow, a web application construction kit for Python: http://nevow.com/
.. [2] nevow.stan is a domain specific language for Python
(read as "crazy getitem/call overloading abuse") that Donovan and I
schemed up at PyCon 2003 at this super ninja Python/C++ programmer's
(David Abrahams) hotel room. Donovan later inflicted this upon the
masses in Nevow. Check out the Divmod project page for some
examples: http://nevow.com/Nevow2004Tutorial.html
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,118 +0,0 @@
.. title:: MochiKit.DateTime - "what time is it anyway?"
Name
====
MochiKit.DateTime - "what time is it anyway?"
Synopsis
========
::
stringDate = toISOTimestamp(new Date());
dateObject = isoTimestamp(stringDate);
Description
===========
Remote servers don't give you JavaScript Date objects, and they certainly
don't want them from you, so you need to deal with string representations
of dates and timestamps. MochiKit.Date does that.
Dependencies
============
None.
API Reference
=============
Functions
---------
:mochidef:`isoDate(str)`:
Convert an ISO 8601 date (YYYY-MM-DD) to a ``Date`` object.
:mochidef:`isoTimestamp(str)`:
Convert any ISO 8601 [1]_ timestamp (or something reasonably close to it)
to a ``Date`` object. Will accept the "de facto" form:
YYYY-MM-DD hh:mm:ss
or (the proper form):
YYYY-MM-DDThh:mm:ssZ
If a time zone designator ("Z" or "[+-]HH:MM") is not present, then the
local timezone is used.
:mochidef:`toISOTime(date)`:
Convert a ``Date`` object to a string in the form of hh:mm:ss
:mochidef:`toISOTimestamp(date, realISO=false)`:
Convert a ``Date`` object to something that's ALMOST but not quite an
ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be:
YYYY-MM-DDThh:mm:ssZ
However, we see junk in SQL and other places that looks like this:
YYYY-MM-DD hh:mm:ss
So, this function returns the latter form, despite its name, unless
you pass ``true`` for ``realISO``.
:mochidef:`toISODate(date)`:
Convert a ``Date`` object to an ISO 8601 [1]_ date string (YYYY-MM-DD)
:mochidef:`americanDate(str)`:
Converts a MM/DD/YYYY date to a ``Date`` object
:mochidef:`toPaddedAmericanDate(date)`:
Converts a ``Date`` object to an MM/DD/YYYY date, e.g. 01/01/2001
:mochidef:`toAmericanDate(date)`:
Converts a ``Date`` object to an M/D/YYYY date, e.g. 1/1/2001
See Also
========
.. [1] W3C profile of ISO 8601: http://www.w3.org/TR/NOTE-datetime
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,211 +0,0 @@
.. title:: MochiKit.Format - string formatting goes here
Name
====
MochiKit.Format - string formatting goes here
Synopsis
========
::
assert( truncToFixed(0.12345, 4) == "0.1234" );
assert( roundToFixed(0.12345, 4) == "0.1235" );
assert( twoDigitAverage(1, 0) == "0" );
assert( twoDigitFloat(1.2345) == "1.23" );
assert( twoDigitFloat(1) == "1" );
assert( percentFormat(1.234567) == "123.46%" );
assert( numberFormatter("###,###%")(125) == "12,500%" );
assert( numberFormatter("##.000")(1.25) == "1.250" );
Description
===========
Formatting strings and stringifying numbers is boring, so a couple useful
functions in that domain live here.
Dependencies
============
None.
Overview
========
Formatting Numbers
------------------
MochiKit provides an extensible number formatting facility, modeled loosely
after the Number Format Pattern Syntax [1]_ from Java.
:mochiref:`numberFormatter(pattern[, placeholder=""[, locale="default"])`
returns a function that converts Number to string using the given information.
``pattern`` is a string consisting of the following symbols:
+-----------+---------------------------------------------------------------+
| Symbol | Meaning |
+===========+===============================================================+
| ``-`` | If given, used as the position of the minus sign |
| | for negative numbers. If not given, the position |
| | to the left of the first number placeholder is used. |
+-----------+---------------------------------------------------------------+
| ``#`` | The placeholder for a number that does not imply zero |
| | padding. |
+-----------+---------------------------------------------------------------+
| ``0`` | The placeholder for a number that implies zero padding. |
| | If it is used to the right of a decimal separator, it |
| | implies trailing zeros, otherwise leading zeros. |
+-----------+---------------------------------------------------------------+
| ``,`` | The placeholder for a "thousands separator". May be used |
| | at most once, and it must be to the left of a decimal |
| | separator. Will be replaced by ``locale.separator`` in the |
| | result (the default is also ``,``). |
+-----------+---------------------------------------------------------------+
| ``.`` | The decimal separator. The quantity of ``#`` or ``0`` |
| | after the decimal separator will determine the precision of |
| | the result. If no decimal separator is present, the |
| | fractional precision is ``0`` -- meaning that it will be |
| | rounded to the nearest integer. |
+-----------+---------------------------------------------------------------+
| ``%`` | If present, the number will be multiplied by ``100`` and |
| | the ``%`` will be replaced by ``locale.percent``. |
+-----------+---------------------------------------------------------------+
API Reference
=============
Functions
---------
:mochidef:`formatLocale(locale="default")`:
Return a locale object for the given locale. ``locale`` may be either a
string, which is looked up in the ``MochiKit.Format.LOCALE`` object, or
a locale object. If no locale is given, ``LOCALE.default`` is used
(equivalent to ``LOCALE.en_US``).
:mochidef:`lstrip(str, chars="\\s")`:
Returns a string based on ``str`` with leading whitespace stripped.
If ``chars`` is given, then that expression will be used instead of
whitespace. ``chars`` should be a string suitable for use in a ``RegExp``
``[character set]``.
:mochidef:`numberFormatter(pattern, placeholder="", locale="default")`:
Return a function ``formatNumber(aNumber)`` that formats numbers
as a string according to the given pattern, placeholder and locale.
``pattern`` is a string that describes how the numbers should be formatted,
for more information see `Formatting Numbers`_.
``locale`` is a string of a known locale (en_US, de_DE, fr_FR, default) or
an object with the following fields:
+-----------+-----------------------------------------------------------+
| separator | The "thousands" separator for this locale (en_US is ",") |
+-----------+-----------------------------------------------------------+
| decimal | The decimal separator for this locale (en_US is ".") |
+-----------+-----------------------------------------------------------+
| percent | The percent symbol for this locale (en_US is "%") |
+-----------+-----------------------------------------------------------+
:mochidef:`percentFormat(someFloat)`:
Roughly equivalent to: ``sprintf("%.2f%%", someFloat * 100)``
In new code, you probably want to use:
:mochiref:`numberFormatter("#.##%")(someFloat)` instead.
:mochidef:`roundToFixed(aNumber, precision)`:
Return a string representation of ``aNumber``, rounded to ``precision``
digits with trailing zeros. This is similar to
``Number.toFixed(aNumber, precision)``, but this has implementation
consistent rounding behavior (some versions of Safari round 0.5 down!)
and also includes preceding ``0`` for numbers less than ``1`` (Safari,
again).
For example, :mochiref:`roundToFixed(0.1357, 2)` returns ``0.14`` on every
supported platform, where some return ``.13`` for ``(0.1357).toFixed(2)``.
:mochidef:`rstrip(str, chars="\\s")`:
Returns a string based on ``str`` with trailing whitespace stripped.
If ``chars`` is given, then that expression will be used instead of
whitespace. ``chars`` should be a string suitable for use in a ``RegExp``
``[character set]``.
:mochidef:`strip(str, chars="\\s")`:
Returns a string based on ``str`` with leading and trailing whitespace
stripped (equivalent to :mochiref:`lstrip(rstrip(str, chars), chars)`).
If ``chars`` is given, then that expression will be used instead of
whitespace. ``chars`` should be a string suitable for use in a ``RegExp``
``[character set]``.
:mochidef:`truncToFixed(aNumber, precision)`:
Return a string representation of ``aNumber``, truncated to ``precision``
digits with trailing zeros. This is similar to
``aNumber.toFixed(precision)``, but this truncates rather than rounds and
has implementation consistent behavior for numbers less than 1.
Specifically, :mochiref:`truncToFixed(aNumber, precision)` will always have a
preceding ``0`` for numbers less than ``1``.
For example, :mochiref:`toFixed(0.1357, 2)` returns ``0.13``.
:mochidef:`twoDigitAverage(numerator, denominator)`:
Calculate an average from a numerator and a denominator and return
it as a string with two digits of precision (e.g. "1.23").
If the denominator is 0, "0" will be returned instead of ``NaN``.
:mochidef:`twoDigitFloat(someFloat)`:
Roughly equivalent to: ``sprintf("%.2f", someFloat)``
In new code, you probably want to use
:mochiref:`numberFormatter("#.##")(someFloat)` instead.
See Also
========
.. [1] Java Number Format Pattern Syntax:
http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,345 +0,0 @@
.. title:: MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy
Name
====
MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy
Synopsis
========
::
theSum = sum(takewhile(
partial(operator.gt, 10),
imap(
partial(operator.mul, 2),
count()
)
)
));
assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );
Description
===========
All of the functional programming missing from :mochiref:`MochiKit.Base` lives
here. The functionality in this module is largely inspired by Python's iteration
protocol [1]_, and the itertools module [2]_.
MochiKit.Iter defines a standard way to iterate over anything, that you can
extend with :mochiref:`registerIterator`, or by implementing the ``.iter()``
protocol. Iterators are lazy, so it can potentially be cheaper to build a
filter chain of iterators than to build lots of intermediate arrays.
Especially when the data set is very large, but the result is not.
Dependencies
============
- :mochiref:`MochiKit.Base`
Overview
========
Iteration for JavaScript
------------------------
The best overview right now is in my Iteration for JavaScript [3]_ blog entry.
This information will migrate here eventually.
API Reference
=============
Errors
------
:mochidef:`StopIteration`:
The singleton :mochiref:`MochiKit.Base.NamedError` that signifies the end
of an iterator
Functions
---------
:mochidef:`applymap(fun, seq[, self])`:
``applymap(fun, seq)`` -->
fun.apply(self, seq0), fun.apply(self, seq1), ...
:mochidef:`chain(p, q[, ...])`:
``chain(p, q, ...)`` --> p0, p1, ... plast, q0, q1, ...
:mochidef:`count(n=0)`:
``count(n=0)`` --> n, n + 1, n + 2, ...
:mochidef:`cycle(p)`:
``cycle(p)`` --> p0, p1, ... plast, p0, p1, ...
:mochidef:`dropwhile(pred, seq)`:
``dropwhile(pred, seq)`` --> seq[n], seq[n + 1], starting when
pred(seq[n]) fails
:mochidef:`every(iterable, func)`:
Return ``true`` if ``func(item)`` is ``true`` for every item in
``iterable``.
:mochidef:`exhaust(iterable)`:
Exhausts an iterable without saving the results anywhere,
like :mochiref:`list(iterable)` when you don't care what the output is.
:mochidef:`forEach(iterable, func[, self])`:
Call ``func`` for each item in ``iterable``, and don't save the results.
:mochidef:`groupby(iterable[, keyfunc])`:
Make an iterator that returns consecutive keys and groups from the
iterable. The key is a function computing a key value for each element.
If not specified or is None, key defaults to an identity function and
returns the element unchanged. Generally, the iterable needs to already be
sorted on the same key function.
The returned group is itself an iterator that shares the underlying
iterable with :mochiref:`groupby()`. Because the source is shared, when the
groupby object is advanced, the previous group is no longer visible.
So, if that data is needed later, it should be stored as an array::
var groups = [];
var uniquekeys = [];
forEach(groupby(data, keyfunc), function (key_group) {
groups.push(list(key_group[1]));
uniquekeys.push(key_group[0]);
});
As a convenience, :mochiref:`groupby_as_array()` is provided to suit the above
use case.
:mochidef:`groupby_as_array(iterable[, keyfunc])`:
Perform the same task as :mochiref:`groupby()`, except return an array of
arrays instead of an iterator of iterators.
:mochidef:`iextend(lst, iterable)`:
Just like :mochiref:`list(iterable)`, except it pushes results on ``lst``
rather than creating a new one.
:mochidef:`ifilter(pred, seq)`:
``ifilter(pred, seq)`` --> elements of seq where ``pred(elem)`` is ``true``
:mochidef:`ifilterfalse(pred, seq)`:
``ifilterfalse(pred, seq)`` --> elements of seq where ``pred(elem)`` is
``false``
:mochidef:`imap(fun, p, q[, ...])`:
``imap(fun, p, q, ...)`` --> fun(p0, q0, ...), fun(p1, q1, ...), ...
:mochidef:`islice(seq, [start,] stop[, step])`:
``islice(seq, [start,] stop[, step])`` --> elements from
seq[start:stop:step] (in Python slice syntax)
:mochidef:`iter(iterable[, sentinel])`:
Convert the given argument to an iterator (object implementing
``.next()``).
1. If ``iterable`` is an iterator (implements ``.next()``), then it will
be returned as-is.
2. If ``iterable`` is an iterator factory (implements ``.iter()``), then
the result of ``iterable.iter()`` will be returned.
3. Otherwise, the iterator factory :mochiref:`MochiKit.Base.AdapterRegistry`
is used to find a match.
4. If no factory is found, it will throw ``TypeError``
Built-in iterator factories are present for Array-like objects, and
objects that implement the ``iterateNext`` protocol (e.g. the result of
Mozilla's ``document.evaluate``).
When used directly, using an iterator should look like this::
var it = iter(iterable);
try {
while (var o = it.next()) {
// use o
}
} catch (e) {
if (e != StopIteration) {
throw e;
}
// pass
}
This is ugly, so you should use the higher order functions to work
with iterators whenever possible.
:mochidef:`izip(p, q[, ...])`:
``izip(p, q, ...)`` --> [p0, q0, ...], [p1, q1, ...], ...
:mochidef:`list(iterable)`:
Convert ``iterable`` to a new ``Array``
:mochidef:`next(iterator)`:
Return ``iterator.next()``
:mochidef:`range([start,] stop[, step])`:
Return an iterator containing an arithmetic progression of integers.
``range(i, j)`` returns :mochiref:`iter([i, i + 1, i + 2, ..., j - 1])`
``start`` (!) defaults to ``0``. When ``step`` is given, it specifies the
increment (or decrement). The end point is omitted!
For example, ``range(4)`` returns :mochiref:`iter([0, 1, 2, 3])`.
This iterates over exactly the valid indexes for an array of 4 elements.
:mochidef:`reduce(fn, iterable[, initial])`:
Apply ``fn(a, b)`` cumulatively to the items of an
iterable from left to right, so as to reduce the iterable
to a single value.
For example::
reduce(function (a, b) { return x + y; }, [1, 2, 3, 4, 5])
calculates::
((((1 + 2) + 3) + 4) + 5).
If initial is given, it is placed before the items of the sequence
in the calculation, and serves as a default when the sequence is
empty.
Note that the above example could be written more clearly as::
reduce(operator.add, [1, 2, 3, 4, 5])
Or even simpler::
sum([1, 2, 3, 4, 5])
:mochidef:`registerIteratorFactory(name, check, iterfactory[, override])`:
Register an iterator factory for use with the iter function.
``check`` is a ``function(a)`` that returns ``true`` if ``a`` can be
converted into an iterator with ``iterfactory``.
``iterfactory`` is a ``function(a)`` that returns an object with a
``.next()`` method that returns the next value in the sequence.
``iterfactory`` is guaranteed to only be called if ``check(a)``
returns a true value.
If ``override`` is ``true``, then it will be made the
highest precedence iterator factory. Otherwise, the lowest.
:mochidef:`repeat(elem[, n])`:
``repeat(elem, [,n])`` --> elem, elem, elem, ... endlessly or up to n times
:mochidef:`reversed(iterable)`:
Return a reversed array from iterable.
:mochidef:`some(iterable, func)`:
Return ``true`` if ``func(item)`` is ``true`` for at least one item in
``iterable``.
:mochidef:`sorted(iterable[, cmp])`:
Return a sorted array from iterable.
:mochidef:`sum(iterable, start=0)`:
Returns the sum of a sequence of numbers plus the value
of parameter ``start`` (with a default of 0). When the sequence is
empty, returns start.
Equivalent to::
reduce(operator.add, iterable, start);
:mochidef:`takewhile(pred, seq)`:
``takewhile(pred, seq)`` --> seq[0], seq[1], ... until pred(seq[n]) fails
:mochidef:`tee(iterable, n=2)`:
``tee(it, n=2)`` --> [it1, it2, it3, ... itn] splits one iterator into n
See Also
========
.. [1] The iteration protocol is described in
PEP 234 - Iterators: http://www.python.org/peps/pep-0234.html
.. [2] Python's itertools
module: http://docs.python.org/lib/module-itertools.html
.. [3] Iteration in JavaScript: http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,284 +0,0 @@
.. title:: MochiKit.Logging - we're all tired of alert()
Name
====
MochiKit.Logging - we're all tired of alert()
Synopsis
========
::
log("INFO messages are so boring");
logDebug("DEBUG messages are even worse");
log("good thing I can pass", objects, "conveniently");
Description
===========
MochiKit.Logging steals some ideas from Python's logging module [1]_, but
completely forgot about the Java [2]_ inspiration. This is a KISS module for
logging that provides enough flexibility to do just about anything via
listeners, but without all the cruft.
Dependencies
============
- :mochiref:`MochiKit.Base`
Overview
========
Native Console Logging
----------------------
As of MochiKit 1.3, the default logger will log all messages to your browser's
native console. This is currently supported in Safari, Opera 9, and Firefox
when the FireBug__ extension is installed.
.. __: http://www.joehewitt.com/software/firebug/
To disable this behavior::
MochiKit.Logging.logger.useNativeLogging = false;
Bookmarklet Based Debugging
---------------------------
JavaScript is at a serious disadvantage without a standard console for
"print" statements. Everything else has one. The closest thing that
you get in a browser environment is the ``alert`` function, which is
absolutely evil.
This leaves you with one reasonable solution: do your logging in the page
somehow. The problem here is that you don't want to clutter the page with
debugging tools. The solution to that problem is what we call BBD, or
Bookmarklet Based Debugging [3]_.
Simply create a bookmarklet for `javascript:MochiKit.Logging.logger.debuggingBookmarklet()`__,
and whack it whenever you want to see what's in the logger. Of course, this
means you must drink the MochiKit.Logging kool-aid. It's tangy and sweet,
don't worry.
.. __: javascript:MochiKit.Logging.logger.debuggingBookmarklet()
Currently this is an ugly ``alert``, but we'll have something spiffy
Real Soon Now, and when we do, you only have to upgrade MochiKit.Logging,
not your bookmarklet!
API Reference
=============
Constructors
------------
:mochidef:`LogMessage(num, level, info)`:
Properties:
``num``:
Identifier for the log message
``level``:
Level of the log message (``"INFO"``, ``"WARN"``, ``"DEBUG"``,
etc.)
``info``:
All other arguments passed to log function as an ``Array``
``timestamp``:
``Date`` object timestamping the log message
:mochidef:`Logger([maxSize])`:
A basic logger object that has a buffer of recent messages
plus a listener dispatch mechanism for "real-time" logging
of important messages.
``maxSize`` is the maximum number of entries in the log.
If ``maxSize >= 0``, then the log will not buffer more than that
many messages. So if you don't like logging at all, be sure to
pass ``0``.
There is a default logger available named "logger", and several
of its methods are also global functions:
``logger.log`` -> ``log``
``logger.debug`` -> ``logDebug``
``logger.warning`` -> ``logWarning``
``logger.error`` -> ``logError``
``logger.fatal`` -> ``logFatal``
:mochidef:`Logger.prototype.addListener(ident, filter, listener)`:
Add a listener for log messages.
``ident`` is a unique identifier that may be used to remove the listener
later on.
``filter`` can be one of the following:
``null``:
``listener(msg)`` will be called for every log message
received.
``string``:
:mochiref:`logLevelAtLeast(filter)` will be used as the function
(see below).
``function``:
``filter(msg)`` will be called for every msg, if it returns
true then ``listener(msg)`` will be called.
``listener`` is a function that takes one argument, a log message. A log
message is an object (:mochiref:`LogMessage` instance) that has at least these
properties:
``num``:
A counter that uniquely identifies a log message (per-logger)
``level``:
A string or number representing the log level. If string, you
may want to use ``LogLevel[level]`` for comparison.
``info``:
An Array of objects passed as additional arguments to the ``log``
function.
:mochidef:`Logger.prototype.baseLog(level, message[, ...])`:
The base functionality behind all of the log functions.
The first argument is the log level as a string or number,
and all other arguments are used as the info list.
This function is available partially applied as:
============== =========
Logger.debug 'DEBUG'
Logger.log 'INFO'
Logger.error 'ERROR'
Logger.fatal 'FATAL'
Logger.warning 'WARNING'
============== =========
For the default logger, these are also available as global functions,
see the :mochiref:`Logger` constructor documentation for more info.
:mochidef:`Logger.prototype.clear()`:
Clear all messages from the message buffer.
:mochidef:`Logger.prototype.debuggingBookmarklet()`:
Display the contents of the logger in a useful way for browsers.
Currently, if :mochiref:`MochiKit.LoggingPane` is loaded, then a pop-up
:mochiref:`MochiKit.LoggingPane.LoggingPane` will be used. Otherwise,
it will be an alert with :mochiref:`Logger.prototype.getMessageText()`.
:mochidef:`Logger.prototype.dispatchListeners(msg)`:
Dispatch a log message to all listeners.
:mochidef:`Logger.prototype.getMessages(howMany)`:
Return a list of up to ``howMany`` messages from the message buffer.
:mochidef:`Logger.prototype.getMessageText(howMany)`:
Get a string representing up to the last ``howMany`` messages in the
message buffer. The default is ``30``.
The message looks like this::
LAST {messages.length} MESSAGES:
[{msg.num}] {msg.level}: {m.info.join(' ')}
[{msg.num}] {msg.level}: {m.info.join(' ')}
...
If you want some other format, use
:mochiref:`Logger.prototype.getMessages` and do it yourself.
:mochidef:`Logger.prototype.removeListener(ident)`:
Remove a listener using the ident given to :mochiref:`Logger.prototype.addListener`
Functions
---------
:mochidef:`alertListener(msg)`:
Ultra-obnoxious ``alert(...)`` listener
:mochidef:`logDebug(message[, info[, ...]])`:
Log an INFO message to the default logger
:mochidef:`logDebug(message[, info[, ...]])`:
Log a DEBUG message to the default logger
:mochidef:`logError(message[, info[, ...]])`:
Log an ERROR message to the default logger
:mochidef:`logFatal(message[, info[, ...]])`:
Log a FATAL message to the default logger
:mochidef:`logLevelAtLeast(minLevel)`:
Return a function that will match log messages whose level
is at least minLevel
:mochidef:`logWarning(message[, info[, ...]])`:
Log a WARNING message to the default logger
See Also
========
.. [1] Python's logging module: http://docs.python.org/lib/module-logging.html
.. [2] PEP 282, where they admit all of the Java influence: http://www.python.org/peps/pep-0282.html
.. [3] Original Bookmarklet Based Debugging blather: http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

View File

@@ -1,114 +0,0 @@
.. title:: MochiKit.LoggingPane - Interactive MochiKit.Logging pane
Name
====
MochiKit.LoggingPane - Interactive MochiKit.Logging pane
Synopsis
========
::
// open a pop-up window
createLoggingPane()
// use a div at the bottom of the document
createLoggingPane(true);
Description
===========
MochiKit.Logging does not have any browser dependencies and is completely
unobtrusive. MochiKit.LoggingPane is a browser-based colored viewing pane
for your :mochiref:`MochiKit.Logging` output that can be used as a pop-up or
inline.
It also allows for regex and level filtering! MochiKit.LoggingPane is used
as the default :mochiref:`MochiKit.Logging.debuggingBookmarklet()` if it is
loaded.
Dependencies
============
- :mochiref:`MochiKit.Base`
- :mochiref:`MochiKit.Logging`
API Reference
=============
Constructors
------------
:mochidef:`LoggingPane(inline=false, logger=MochiKit.Logging.logger)`:
A listener for a :mochiref:`MochiKit.Logging` logger with an interactive
DOM representation.
If ``inline`` is ``true``, then the ``LoggingPane`` will be a ``DIV``
at the bottom of the document. Otherwise, it will be in a pop-up
window with a name based on the calling page's URL. If there is an
element in the document with an id of ``_MochiKit_LoggingPane``,
it will be used instead of appending a new ``DIV`` to the body.
``logger`` is the reference to the :mochiref:`MochiKit.Logging.Logger` to
listen to. If not specified, the global default logger is used.
Properties:
``win``:
Reference to the pop-up window (``undefined`` if ``inline``)
``inline``:
``true`` if the ``LoggingPane`` is inline
``colorTable``:
An object with property->value mappings for each log level
and its color. May also be mutated on ``LoggingPane.prototype``
to affect all instances. For example::
MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
DEBUG: "green",
INFO: "black",
WARNING: "blue",
ERROR: "red",
FATAL: "darkred"
};
:mochidef:`LoggingPane.prototype.closePane()`:
Close the :mochiref:`LoggingPane` (close the child window, or
remove the ``_MochiKit_LoggingPane`` ``DIV`` from the document).
Functions
---------
:mochidef:`createLoggingPane(inline=false)`:
Create or return an existing :mochiref:`LoggingPane` for this document
with the given inline setting. This is preferred over using
:mochiref:`LoggingPane` directly, as only one :mochiref:`LoggingPane`
should be present in a given document.
Authors
=======
- Bob Ippolito <bob@redivi.com>
Copyright
=========
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
free software; you can redistribute it and/or modify it under the terms of the
`MIT License`_ or the `Academic Free License v2.1`_.
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php

Some files were not shown because too many files have changed in this diff Show More