[KSS-checkins] r50811 - in kukit/kukit.js/trunk: 3rd_party/johnnydebris.net 3rd_party/johnnydebris.net/dommer 3rd_party/johnnydebris.net/jsbase 3rd_party/johnnydebris.net/jsbase/testing 3rd_party/johnnydebris.net/minisax.js kukit tests
gotcha at codespeak.net
gotcha at codespeak.net
Sun Jan 20 20:43:20 CET 2008
Author: gotcha
Date: Sun Jan 20 20:43:18 2008
New Revision: 50811
Added:
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/CHANGES.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/LICENSE.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/README.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/conftest.py
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/dommer.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/example.html
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/run_tests.html
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/test_dommer.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/version.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/LICENSE.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/README.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/__init__.py
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/array.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/conftest.py
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/exception.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/function.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/misclib.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/number.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/server.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/string.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_array.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_misclib.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_number.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_string.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/findtests.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/testbase.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/version.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/conftest.py
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/example.html
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/helpers.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/minisax.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/test_minisax.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/testhandler.js
kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/version.txt
Modified:
kukit/kukit.js/trunk/kukit/kukit.js
kukit/kukit.js/trunk/kukit/utils.js
kukit/kukit.js/trunk/tests/runner.html
kukit/kukit.js/trunk/tests/runtests.js
kukit/kukit.js/trunk/tests/runtests.sh
kukit/kukit.js/trunk/tests/test_utils.js
Log:
* add dommer.js code from Guido Wesdorp (johnnydebris)
This will allow better unit testing of KSS as it implements DOM in js.
* setup of that code in tests infrastructure
* refactor base URL computation to allow unit testing
* tests for base URL computation
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/CHANGES.txt
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/CHANGES.txt Sun Jan 20 20:43:18 2008
@@ -0,0 +1,17 @@
+Changes in the Dommer library
+=============================
+
+Version 0.4
+-----------
+
+ * Changed the unit tests so they can be ran from py.test (using some
+ new JSBase feature, currently this rules out browser testing but that
+ should be fixed later).
+
+ * Fixed some bugs in comment handling.
+
+ * Replaced my old helpers lib with a new one, which has a slightly different
+ way of defining methods (uses a module namespace). Note that this does not
+ change the dependencies, as the functionality required is copied to the
+ main lib on release creation.
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/LICENSE.txt
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/LICENSE.txt Sun Jan 20 20:43:18 2008
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/README.txt
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/README.txt Sun Jan 20 20:43:18 2008
@@ -0,0 +1,60 @@
+Dommer
+======
+
+What is it?
+-----------
+
+Dommer is a DOM level 2 library (currently not complete, not sure if it ever
+will either, but it's a usable subset) that is almost entirely compliant with
+the DOM standard. This allows DOM developers to write proper XML parsing code
+for all browsers that support core JavaScript. DOM for instance properly
+supports namespaces, a feature which IE's DOM support lacks, thus allowing
+XML to be parsed with proper namespace and prefix handling on that platform.
+
+What's missing?
+---------------
+
+Currently a number of features are missing, features marked with a * will most
+probably be added in the near future, others are not certain to be implemented
+at all.
+
+- CDATA*
+- DTD processing
+- HTML support
+- some more exotic DOM functions such as isSupported()
+- (there's probably more I can't remember right now ;)
+
+What's different from the standard?
+-----------------------------------
+
+Since there's no proper way to update one property when another is set in IE,
+all properties on a node should be considered read-only, they should never be
+modified except with dedicated API calls. To allow setting the prefix of a
+node without updating e.g. .nodeName, a new method was added to the Node
+interface, called 'setPrefix'. If this library is used *solely* on platforms
+that *do* support dynamic property updates (__defineGetter__ and
+__defineSetter__), you can set the switch WARN_ON_PREFIX to false and set
+.prefix the conventional way.
+
+Usage
+-----
+
+For an example of how to use the library, see 'example.html'. For API
+documentation, see any DOM level 2 reference.
+
+Note that this library depends on version 0.3 of the 'minisax.js' library,
+and version 0.1 of the JSBase lib, both of which can be downloaded (under the
+same GPL license) from http://johnnydebris.net/javascript/.
+
+Questions, remarks, bug reports, etc.
+-------------------------------------
+
+If you have questions, remarks, bug reports, etc. you can send email to
+johnny at johnnydebris.net. More information and newer versions of this library
+can be found on http://johnnydebris.net.
+
+Note: this product contains some code written by the Kupu developers (some of
+the functionality in helpers.js). Kupu is an HTML editor written in
+JavaScript, released under a BSD-style license. See http://kupu.oscom.org for
+more information about Kupu and its license.
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/conftest.py
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/conftest.py Sun Jan 20 20:43:18 2008
@@ -0,0 +1,18 @@
+# JS unit test support for py.test - (c) 2007 Guido Wesdorp. All rights
+# reserved
+#
+# This software is distributed under the terms of the JSBase
+# License. See LICENSE.txt for license text.
+
+import py
+here = py.magic.autopath().dirpath()
+
+from jsbase.conftest import JSTest, JSChecker, Directory as _Directory
+
+class Directory(_Directory):
+ def run(self):
+ if self.fspath == here:
+ return [p.basename for p in self.fspath.listdir('test_*') if
+ p.ext == '.js']
+ return super(Directory, self).run()
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/dommer.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/dommer.js Sun Jan 20 20:43:18 2008
@@ -0,0 +1,1213 @@
+/* dommer.js - a (mostly) compliant subset of DOM level 2 for JS
+ (c) Guido Wesdorp 2004-2007
+ email johnny at debris.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ dommer.js
+
+ This library provides a mostly compliant subset of the DOM API in core
+ JavaScript. A number of methods aren't implemented, and there are a few
+ semantic differences between the standard and this implementations, but
+ it provides most of DOM level 2's features and is usable in almost all JS
+ environments (also stand-alone ones).
+
+ I started writing this mainly because of IE's lack of proper namespace
+ support, and to have a portable, reliable DOM implementation.
+
+ Non-standard are:
+
+ - Whitespace is never ignored.
+
+ - Because of JS doesn't (by default) allow computing attributes on request,
+ this API doesn't create Element.nodeName on setting element.prefix,
+ therefore a new method was added: Element.setPrefix (note that this
+ is not required if the library is not used on browsers that don't
+ support __defineGetter__ and __defineSetter__ (such as IE)).
+
+ $Id: minisax.js,v 1.5 2004/07/31 00:10:15 johnny Exp $
+
+*/
+
+// If the following switch is set to true, setting Element.prefix
+// will result in an exception. This serves to make sure scripts work
+// cross-browser: IE does not support __defineSetter__, which is used
+// to ensure Element.nodeName is updated if Element.prefix
+// is changed (and also to ensure Element.nodeName and
+// Element.localName can't be changed directly). The lack of this
+// method on IE means that on that platform it is possible to break
+// integrity (by setting .prefix directly, .nodeName will be out-of-date).
+// Note that this means that if you intend to use this lib only on Mozilla
+// (or other browsers that support dynamic properties), you can safely
+// set this to false and set .prefix without breaking integrity.
+var WARN_ON_PREFIX = true;
+
+// give this a namespace...
+try {
+ var global = window;
+} catch(e) {
+ var global = this;
+};
+global.dommer = new function() {
+ /* Exceptions */
+ function DOMException(errorcode, message) {
+ this.code = null;
+ this.error = null;
+ this.message = message
+ for (var attr in DOMException) {
+ if (DOMException[attr] == errorcode) {
+ this.error = attr;
+ break;
+ };
+ };
+ this.code = errorcode;
+ if (!this.error) {
+ this.error = 'Unknown';
+ };
+ this.stack = stack = createStack();
+ this.lineNumber = getLineNo(stack);
+ this.fileName = getFileName(stack);
+ };
+
+ this.DOMException = DOMException;
+
+ // error codes
+ // XXX should we make these global, like in the specs?
+ DOMException.INDEX_SIZE_ERR = 1,
+ DOMException.DOMSTRING_SIZE_ERR = 2;
+ DOMException.HIERARCHY_REQUEST_ERR = 3;
+ DOMException.WRONG_DOCUMENT_ERR = 4;
+ DOMException.INVALID_CHARACTER_ERR = 5;
+ DOMException.NO_DATA_ALLOWED_ERR = 6;
+ DOMException.NO_MODIFICATION_ALLOWED_ERR = 7;
+ DOMException.NOT_FOUND_ERR = 8;
+ DOMException.NOT_SUPPORTED_ERR = 9;
+ DOMException.INUSE_ATTRIBUTE_ERR = 10;
+ DOMException.INVALID_STATE_ERR = 11;
+ DOMException.SYNTAX_ERR = 12;
+ DOMException.INVALID_MODIFICATION_ERR = 13;
+ DOMException.NAMESPACE_ERR = 14;
+ DOMException.INVALID_ACCESS_ERR = 15;
+
+ DOMException.prototype.toString = function() {
+ var ret = 'DOMException: ' + this.error + ' (' + this.code + ')';
+ if (this.message) {
+ ret += ' - ' + this.message;
+ };
+ return ret;
+ };
+
+ /* Node interface */
+ function Node() {
+ this.ELEMENT_NODE = 1;
+ this.ATTRIBUTE_NODE = 2;
+ this.TEXT_NODE = 3;
+ this.CDATA_SECTION_NODE = 4;
+ this.ENTITY_REFERENCE_NODE = 5;
+ this.ENTITY_NODE = 6;
+ this.PROCESSING_INSTRUCTION_NODE = 7;
+ this.COMMENT_NODE = 8;
+ this.DOCUMENT_NODE = 9;
+ this.DOCUMENT_TYPE_NODE = 10;
+ this.DOCUMENT_FRAGMENT_NODE = 11;
+ this.NOTATION_NODE = 12;
+
+ // These are defined in-line rather than on .prototype to allow using
+ // them below, too. This way we don't have to check whether attributes
+ // are already protected while this constructor is ran or not (in JS,
+ // when you set 'Foo.prototype = new Bar;', the Bar constructor is
+ // actually ran, in our case this means that the state of the
+ // superclass changes).
+ this._protectAttribute = function(attr) {
+ /* make an attribute read-only */
+ this.__defineSetter__(attr,
+ function(value) {
+ throw(
+ (new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR, attr))
+ );
+ }
+ );
+ this.__defineGetter__(attr,
+ function() {
+ return this['_' + attr];
+ }
+ );
+ };
+
+ this._setProtected = function(name, value) {
+ /* set a read-only attribute
+
+ THIS IS AN INTERNAL METHOD that should not get used as part
+ of the API
+ */
+ this['_' + name] = value;
+ if (!this.__defineSetter__) {
+ this[name] = value;
+ };
+ };
+
+ this.nodeValue = null;
+ if (this.__defineSetter__) {
+ // on browsers that support __define[GS]etter__, perform integrity
+ // checks
+ // nodeValue should be settable on certain nodeTypes
+ this.__defineSetter__('nodeValue',
+ function(nodeValue) {
+ if (this.nodeType != this.TEXT_NODE &&
+ this.nodeType != this.ATTRIBUTE_NODE &&
+ this.nodeType != this.COMMENT_NODE) {
+ throw(
+ (new DOMException(
+ DOMException.NO_DATA_ALLOWED_ERR,
+ 'nodeValue'))
+ );
+ };
+ // XXX should check on allowed chars here, but not
+ // sure which?
+ this._nodeValue = nodeValue;
+ }
+ );
+ // XXX not sure if we should protect reading .nodeValue
+ this.__defineGetter__('nodeValue',
+ function() {
+ if (this.nodeType != this.TEXT_NODE &&
+ this.nodeType != this.ATTRIBUTE_NODE &&
+ this.nodeType != this.COMMENT_NODE) {
+ throw(
+ (new DOMException(
+ DOMException.NO_DATA_ALLOWED_ERR,
+ 'nodeValue'))
+ );
+ };
+ return this._nodeValue;
+ }
+ );
+ var toprotect = ['nodeType', 'nodeName', 'parentNode',
+ 'childNodes', 'firstChild', 'lastChild',
+ 'previousSibling', 'nextSibling',
+ 'attributes', 'ownerDocument', 'namespaceURI',
+ 'localName'];
+ for (var i=0; i < toprotect.length; i++) {
+ this._protectAttribute(toprotect[i]);
+ };
+ };
+
+ this._setProtected('namespaceURI', null);
+ this._setProtected('prefix', null);
+ this._setProtected('nodeName', null);
+ this._setProtected('localName', null);
+ this._setProtected('parentNode', null);
+ // note that this is shared between subclass instances, so should be
+ // re-set in every .initialize() (so below is just for show)
+ this._setProtected('childNodes', []);
+ this._setProtected('firstChild', null);
+ this._setProtected('lastChild', null);
+ this._setProtected('previousSibling', null);
+ this._setProtected('nextSibling', null);
+ this._setProtected('ownerDocument', null);
+ };
+
+ this.Node = Node;
+
+ var thrownotsupported = function() {throw('not supported');};
+
+ // XXX these should be implemented at some point...
+ Node.prototype.normalize = thrownotsupported;
+ Node.prototype.isSupported = thrownotsupported; // hehehe...
+
+ // non-standard method, use this always instead of setting .prefix
+ // yourself, as this will update the .nodeName property too
+ Node.prototype.setPrefix = function(prefix) {
+ if (this.__defineSetter__) {
+ this._prefix = prefix;
+ this._nodeName = prefix + ':' + this.localName;
+ } else {
+ this.prefix = prefix;
+ this.nodeName = prefix + ':' + this.localName;
+ };
+ };
+
+ Node.prototype.cloneNode = function() {
+ throw(
+ (new DOMException(DOMException.NOT_SUPPORTED_ERR))
+ );
+ };
+
+ Node.prototype.hasChildNodes = function() {
+ return (this.childNodes && this.childNodes.length > 0);
+ };
+
+ Node.prototype.hasAttributes = function() {
+ return (this.attributes !== undefined && this.attributes.length);
+ };
+
+ Node.prototype.appendChild = function(newChild) {
+ this._checkModificationAllowed();
+ this._attach(newChild);
+ };
+
+ Node.prototype.removeChild = function(oldChild) {
+ this._checkModificationAllowed();
+ this._checkIsChild(oldChild);
+ var newChildren = new NodeList();
+ var found = false;
+ for (var i=0; i < this.childNodes.length; i++) {
+ if (this.childNodes[i] === oldChild) {
+ oldChild._setProtected('parentNode', null);
+ var previous = oldChild.previousSibling;
+ if (previous) {
+ oldChild._setProtected('previousSibling', null);
+ previous._setProtected('nextSibling',
+ oldChild.nextSibling);
+ };
+ var next = oldChild.nextSibling;
+ if (next) {
+ next._setProtected('previousSibling', previous);
+ oldChild._setProtected('nextSibling', null);
+ };
+ continue;
+ };
+ newChildren.push(this.childNodes[i]);
+ };
+ this._setProtected('childNodes', newChildren);
+ this._setProtected('firstChild',
+ (this.childNodes.length > 0 ? this.childNodes[0] : null));
+ this._setProtected('lastChild', (
+ this.childNodes.length > 0 ?
+ this.childNodes[this.childNodes.length - 1] : null));
+ };
+
+ Node.prototype.replaceChild = function(newChild, refChild) {
+ this._checkModificationAllowed();
+ this._checkIsChild(refChild);
+ this._attach(newChild, refChild, true);
+ };
+
+ Node.prototype.insertBefore = function(newChild, refChild) {
+ this._checkModificationAllowed();
+ this._checkIsChild(refChild);
+ this._attach(newChild, refChild);
+ };
+
+ Node.prototype._attach = function(newChild, refChild, replace) {
+ // see if the child is in the same document
+ if (newChild.ownerDocument != this.ownerDocument) {
+ throw(
+ (new DOMException(DOMException.WRONG_DOCUMENT_ERR))
+ );
+ };
+ // see if the child is of an allowed type
+ if (newChild.nodeType != newChild.ELEMENT_NODE &&
+ newChild.nodeType != newChild.TEXT_NODE &&
+ newChild.nodeType != newChild.CDATA_SECTION_NODE &&
+ newChild.nodeType != newChild.COMMENT_NODE) {
+ throw(
+ (new DOMException(DOMException.HIERARCHY_REQUEST_ERR))
+ );
+ };
+ // see if the child isn't a (grand)parent of ourselves
+ var currparent = this;
+ while (currparent && currparent.nodeType != newChild.DOCUMENT_NODE) {
+ if (currparent === newChild) {
+ throw(
+ (new DOMException(DOMException.HIERARCHY_REQUEST_ERR))
+ );
+ };
+ currparent = currparent.parentNode;
+ };
+ // seems to be okay, add it
+ newChild._setProtected('parentNode', this);
+ if (!refChild) {
+ if (this.childNodes.length) {
+ this.childNodes[this.childNodes.length - 1]._setProtected(
+ 'nextSibling', newChild);
+ newChild._setProtected('previousSibling',
+ this.childNodes[this.childNodes.length - 1]);
+ };
+ this.childNodes.push(newChild);
+ } else {
+ var newchildren = [];
+ var found = false;
+ for (var i=0; i < this.childNodes.length; i++) {
+ var currChild = this.childNodes[i];
+ if (currChild === refChild) {
+ newchildren.push(newChild);
+ var previous = this.childNodes[i - 1];
+ if (previous) {
+ newChild._setProtected('previousSibling', previous);
+ previous._setProtected('nextSibling', newChild);
+ };
+ if (!replace) {
+ newchildren.push(currChild);
+ currChild._setProtected('previousSibling', newChild);
+ newChild._setProtected('nextSibling', currChild);
+ } else {
+ currChild._setProtected('parentNode', null);
+ currChild._setProtected('previousSibling', null);
+ currChild._setProtected('nextSibling', null);
+ var next = this.childNodes[i + 1];
+ newChild._setProtected('nextSibling', next);
+ next._setProtected('previousSibling', newChild);
+ };
+ found = true;
+ } else {
+ newchildren.push(currChild);
+ };
+ };
+ if (!found) {
+ throw(
+ (new DOMException(DOMException.NOT_FOUND_ERR))
+ );
+ };
+ this._setProtected('childNodes', newchildren);
+ };
+ this._setProtected('firstChild', this.childNodes[0]);
+ this._setProtected('lastChild',
+ this.childNodes[this.childNodes.length - 1]);
+ };
+
+ Node.prototype._checkModificationAllowed = function() {
+ if (this.nodeType != this.ELEMENT_NODE &&
+ this.nodeType != this.DOCUMENT_NODE &&
+ this.nodeType != this.DOCUMENT_FRAGMENT_NODE) {
+ throw(
+ (new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR))
+ );
+ };
+ };
+
+ Node.prototype._checkIsChild = function(refChild) {
+ if (refChild.parentNode !== this) {
+ throw(
+ (new DOMException(DOMException.NOT_FOUND_ERR))
+ );
+ };
+ };
+
+ function DocumentFragment() {
+ this._setProtected('nodeType', 11);
+ };
+
+ DocumentFragment.prototype = new Node;
+ this.DocumentFragment = DocumentFragment;
+
+ function Element() {
+ this._setProtected('nodeType', 1);
+ };
+
+ Element.prototype = new Node;
+ this.Element = Element;
+
+ Element.prototype.initialize = function(namespaceURI, qname,
+ ownerDocument) {
+ // XXX the specs are very vague about an id, it says the DOM
+ // implementation must have info about which attributes are of the id
+ // type, I'll just use the property here for now...
+ this.id = ''; // empty string like in Mozilla, seems weird to me though
+
+ this._setProtected('attributes', []);
+ this._setProtected('childNodes', []);
+ this._setProtected('ownerDocument', ownerDocument);
+
+ // try to ensure integrity by defining getters and setters for certain
+ // properties, since this only works in certain browsers it makes sense to
+ // test your applications on one of those platforms, see also
+ // WARN_ON_PREFIX in the top of the document
+ if (this.__defineSetter__) {
+ this._nodeName = this.nodeName;
+ this.__defineSetter__('nodeName', function() {
+ throw(
+ (new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR)))
+ });
+ this.__defineGetter__('nodeName',
+ function() {return this._nodeName});
+ this.__defineSetter__('prefix',
+ function(value) {
+ if (WARN_ON_PREFIX) {
+ throw('Setting prefix directly ' +
+ 'breaks integrity of the ' +
+ 'XML DOM in Internet ' +
+ 'Explorer browsers!');
+ };
+ this._prefix = value;
+ this._nodeName = this._prefix +
+ this._localName;
+ });
+ this.__defineGetter__('prefix', function() {return this._prefix});
+ };
+ // XXX both the ns and qname need integrity checks
+ this._setProtected('namespaceURI', namespaceURI);
+ if (qname.indexOf(':') > -1) {
+ var tup = qname.split(':');
+ this.setPrefix(tup.shift());
+ this._setProtected('localName', tup.join(':'));
+ } else {
+ this.setPrefix(null);
+ this._setProtected('localName', qname);
+ };
+ if (this.prefix) {
+ this._setProtected('nodeName', this.prefix + ':' + this.localName);
+ } else {
+ this._setProtected('nodeName', this.localName);
+ };
+ };
+
+ Element.prototype.toString = function() {
+ return '<Element "' + this.nodeName + '" (type ' +
+ this.nodeType + ')>';
+ };
+
+ Element.prototype.toXML = function(context) {
+ // context is used when toXML is called recursively
+ // marker
+ var no_prefix_id = '::no_prefix::';
+ if (!context) {
+ context = {
+ namespace_stack: []
+ };
+ };
+ var new_namespaces = {}; // any namespaces that weren't declared yet
+ var current_namespaces = {};
+ var last_namespaces = context.namespace_stack[
+ context.namespace_stack.length - 1];
+ context.namespace_stack.push(current_namespaces);
+ if (last_namespaces) {
+ for (var prefix in last_namespaces) {
+ current_namespaces[prefix] = last_namespaces[prefix];
+ };
+ };
+ var xml = '<' + this.nodeName;
+ var prefix = this.prefix || no_prefix_id;
+ if (this.namespaceURI &&
+ (current_namespaces[prefix] != this.namespaceURI)) {
+ current_namespaces[prefix] = this.namespaceURI;
+ new_namespaces[prefix] = this.namespaceURI;
+ };
+ for (var i=0; i < this.attributes.length; i++) {
+ var attr = this.attributes[i];
+ var aprefix = attr.prefix || no_prefix_id;
+ if (attr.namespaceURI &&
+ current_namespaces[aprefix] != attr.namespaceURI) {
+ current_namespaces[aprefix] = attr.namespaceURI;
+ new_namespaces[aprefix] = attr.namespaceURI;
+ };
+ xml += ' ' + attr.nodeName + '="' +
+ string.entitize(attr.nodeValue) + '"';
+ };
+
+ // take care of any new namespaces
+ for (var prefix in new_namespaces) {
+ xml += ' xmlns';
+ if (prefix != no_prefix_id) {
+ xml += ':' + prefix;
+ };
+ xml += '="' + string.entitize(new_namespaces[prefix]) + '"';
+ };
+
+ if (this.childNodes.length) {
+ xml += '>';
+ for (var i=0; i < this.childNodes.length; i++) {
+ xml += this.childNodes[i].toXML(context);
+ };
+ xml += '</' + this.nodeName + '>';
+ } else {
+ xml += ' />';
+ };
+ context.namespace_stack.pop();
+ return xml;
+ };
+
+ Element.prototype.cloneNode = function(deep) {
+ var el = new Element();
+ el.initialize(this.namespaceURI, this.nodeName, this.ownerDocument);
+ for (var i=0; i < this.attributes.length; i++) {
+ var clone = this.attributes[i].cloneNode();
+ clone._setProtected('ownerElement', el);
+ el.attributes.push(clone);
+ };
+ if (deep) {
+ for (var i=0; i < this.childNodes.length; i++) {
+ var clone = this.childNodes[i].cloneNode(true);
+ clone._setProtected('parentNode', el);
+ el.appendChild(clone);
+ };
+ };
+ return el;
+ };
+
+ Element.prototype.getAttributeNodeNS = function(namespaceURI, qname) {
+ for (var i=0; i < this.attributes.length; i++) {
+ var attr = this.attributes[i];
+ if (attr.namespaceURI == namespaceURI && attr.nodeName == qname) {
+ return attr;
+ };
+ };
+ };
+
+ Element.prototype.getAttributeNode = function(name) {
+ return this.getAttributeNodeNS(undefined, name);
+ };
+
+ Element.prototype.getAttribute = function(name) {
+ var attr = this.getAttributeNode(name)
+ return (attr ? attr.nodeValue : null);
+ };
+
+ Element.prototype.getAttributeNS = function(namespaceURI, name) {
+ var attr = this.getAttributeNodeNS(namespaceURI, name);
+ return (attr ? attr.nodeValue : null);
+ };
+
+ Element.prototype.hasAttributeNS = function(namespaceURI, name) {
+ return !!(this.getAttributeNS(namespaceURI, name));
+ };
+
+ Element.prototype.hasAttribute = function(name) {
+ return this.hasAttributeNS(this.namespaceURI, name);
+ };
+
+ Element.prototype.setAttributeNS = function(namespaceURI, name, value) {
+ for (var i=0; i < this.attributes.length; i++) {
+ var attr = this.attributes[i];
+ if (attr.namespaceURI == namespaceURI && attr.nodeName == name) {
+ attr.nodeValue = value;
+ return;
+ };
+ };
+ var attr = new Attribute();
+ attr.initialize(namespaceURI, name, value, this.ownerDocument);
+ attr._setProtected('ownerElement', this);
+ this.attributes.push(attr);
+ };
+
+ Element.prototype.setAttribute = function(name, value) {
+ this.setAttributeNS(undefined, name, value);
+ };
+
+ Element.prototype.setAttributeNodeNS = function(newAttr) {
+ for (var i=0; i < this.attributes.length; i++) {
+ var attr = this.attributes[i];
+ if (attr.namespaceURI == newAttr.namespaceURI &&
+ attr.nodeName == newAttr.nodeName) {
+ throw(
+ (new DOMException(DOMException.INUSE_ATTRIBUTE_ERR))
+ );
+ };
+ };
+ this.attributes.push(newAttr);
+ };
+
+ Element.prototype.setAttributeNode = function(newAttr) {
+ // XXX should this fail if no namespaceURI is available or something?
+ this.setAttributeNodeNS(newAttr);
+ };
+
+ Element.prototype.removeAttributeNS = function(namespaceURI, name) {
+ for (var i=0; i < this.attributes.length; i++) {
+ var attr = this.attributes[i];
+ if (attr.namespaceURI == namespaceURI && attr.nodeName == name) {
+ delete this.attributes[i];
+ return true;
+ };
+ };
+ return false;
+ };
+
+ Element.prototype.removeAttribute = function(name) {
+ return this.removeAttributeNS(this.namespaceURI, name);
+ };
+
+ Element.prototype.getElementsByTagNameNS = function(namespaceURI,
+ name, ret) {
+ // XXX *very* slow!!!
+ // needs to be optimized later on (probably by using some mapping)
+ if (!ret) {
+ ret = [];
+ };
+ for (var i=0; i < this.childNodes.length; i++) {
+ var child = this.childNodes[i];
+ if (name == child.nodeName || name == '*') {
+ if ((!namespaceURI && !child.namespaceURI) ||
+ (namespaceURI == child.namespaceURI)) {
+ ret.push(child);
+ };
+ };
+ if (child.nodeType == 1) {
+ child.getElementsByTagNameNS(namespaceURI, name, ret);
+ };
+ };
+ return ret;
+ };
+
+ Element.prototype.getElementsByTagName = function(name) {
+ return this.getElementsByTagNameNS(this.namespaceURI, name);
+ };
+
+ Element.prototype.getElementById = function(id) {
+ // XXX *very* slow!!!
+ // needs to be optimized later on (probably by using some mapping)
+ if (this.id == id) {
+ return this;
+ };
+ for (var i=0; i < this.childNodes.length; i++) {
+ var child = this.childNodes[i];
+ if (child.id == id) {
+ return child;
+ };
+ if (child.nodeType == 1) {
+ var found = this.childNodes[i].getElementById(id);
+ if (found) {
+ return found;
+ };
+ };
+ };
+ };
+
+ function TextNode() {
+ this._setProtected('nodeType', 3);
+ this._setProtected('nodeName', '#text');
+ };
+
+ TextNode.prototype = new Node;
+ this.TextNode = TextNode;
+
+ TextNode.prototype.initialize = function(data, ownerDocument) {
+ this._setProtected('ownerDocument', ownerDocument);
+ this._setProtected('childNodes', new NodeList());
+ // nodeValue is not protected
+ this.nodeValue = data;
+ };
+
+ TextNode.prototype.toXML = function() {
+ return string.entitize(this.nodeValue);
+ };
+
+ TextNode.prototype.cloneNode = function() {
+ var node = new TextNode();
+ node.initialize(this.nodeValue, this.ownerDocument);
+ return node;
+ };
+
+ function CommentNode() {
+ /* a comment node */
+ this._setProtected('nodeType', 8);
+ this._setProtected('nodeName', '#comment');
+ };
+
+ CommentNode.prototype = new TextNode;
+ this.CommentNode = CommentNode;
+
+ CommentNode.prototype.initialize = function(data, ownerDocument) {
+ this._setProtected('ownerDocument', ownerDocument);
+ this._setProtected('childNodes', []);
+ this._setProtected('nodeValue', data);
+ };
+
+ CommentNode.prototype.toXML = function() {
+ return "<!--" + this.nodeValue + "-->";
+ };
+
+ // Attribute, subclass of TextNode because of the nice implementation
+ function Attribute() {
+ /* an attribute node */
+ this._setProtected('nodeType', 2);
+ };
+
+ Attribute.prototype = new Node;
+ this.Attribute = Attribute;
+
+ Attribute.prototype.initialize = function(namespaceURI, qname, value,
+ ownerDocument) {
+ // XXX some code duplication here...
+ if (qname.match(/[^a-zA-Z0-9_\-:]/g)) {
+ throw(
+ (new DOMException(DOMException.INVALID_CHARACTER_ERR))
+ );
+ };
+ this._setProtected('ownerDocument', ownerDocument);
+ this._setProtected('namespaceURI', namespaceURI);
+ this._setProtected('nodeValue', value);
+ this._setProtected('childNodes', []);
+
+ // try to ensure integrity by defining getters and setters for certain
+ // properties, since this only works in certain browsers it makes sense to
+ // test your applications on one of those platforms, see also
+ // WARN_ON_PREFIX in the top of the document
+ if (this.__defineSetter__) {
+ this._nodeName = this.nodeName;
+ this.__defineSetter__('nodeName', function() {
+ throw(
+ (new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR)))
+ });
+ this.__defineGetter__('nodeName',
+ function() {return this._nodeName});
+ this.__defineSetter__('prefix',
+ function(value) {
+ if (WARN_ON_PREFIX) {
+ throw('Setting prefix directly ' +
+ 'breaks integrity of the ' +
+ 'XML DOM in Internet ' +
+ 'Explorer browsers!');
+ };
+ this._prefix = value;
+ this._nodeName = this._prefix +
+ this._localName;
+ });
+ this.__defineGetter__('prefix', function() {return this._prefix});
+ this._protectAttribute('ownerElement');
+ };
+ this._setProtected('ownerElement', null);
+ if (qname.indexOf(':') > -1) {
+ var tup = qname.split(':');
+ this.setPrefix(tup.shift());
+ this._setProtected('localName', tup.join(':'));
+ } else {
+ this.setPrefix(null);
+ this._setProtected('localName', qname);
+ };
+ if (this.prefix) {
+ this._setProtected('nodeName', this.prefix + ':' + this.localName);
+ } else {
+ this._setProtected('nodeName', this.localName);
+ };
+ };
+
+ Attribute.prototype.toXML = function() {
+ ret = this.nodeName + '="' + string.entitize(this.nodeValue) + '"';
+ return ret;
+ };
+
+ Attribute.prototype.cloneNode = function() {
+ var attr = new Attribute();
+ attr.initialize(this.namespaceURI, this.nodeName, this.nodeValue,
+ this.ownerDocument);
+ return attr;
+ };
+
+ Attribute.prototype.toString = function() {
+ return this.nodeValue;
+ };
+
+ function Document() {
+ /* the document node */
+ this._setProtected('nodeType', 9);
+ this._setProtected('nodeName', '#document');
+ };
+
+ Document.prototype = new Element;
+ this.Document = Document;
+
+ Document.prototype.initialize = function() {
+ this._setProtected('ownerDocument', this);
+ this._setProtected('childNodes', []);
+ this.documentElement = null;
+ this.namespaceToPrefix = {};
+ };
+
+ Document.prototype.toXML = function() {
+ return this.documentElement.toXML();
+ };
+
+ Document.prototype.appendChild = function(newChild) {
+ if (this.documentElement) {
+ throw(
+ (new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ 'document already has a document element'))
+ );
+ };
+ this._checkModificationAllowed();
+ this._attach(newChild);
+ this.documentElement = newChild;
+ };
+
+
+ Document.prototype.createElement = function(nodeName) {
+ return this.createElementNS(this.namespaceURI, nodeName);
+ };
+
+ Document.prototype.createElementNS = function(namespaceURI, nodeName) {
+ var el = new Element();
+ el.initialize(namespaceURI, nodeName, this);
+ return el;
+ };
+
+ Document.prototype.createTextNode = function(data) {
+ var el = new TextNode();
+ el.initialize(string.deentitize(data), this);
+ return el;
+ };
+
+ Document.prototype.createAttributeNS = function(namespaceURI, nodeName) {
+ var el = new Attribute();
+ el.initialize(namespaceURI, nodeName, null, this);
+ return el;
+ };
+
+ Document.prototype.createAttribute = function(nodeName) {
+ return this.createAttributeNS(undefined, nodeName);
+ };
+
+ Document.prototype.createComment = function(data) {
+ var el = new CommentNode();
+ el.initialize(data, this);
+ return el;
+ };
+
+ Document.prototype.importNode = function(node) {
+ node._setProtected('ownerDocument', this);
+ };
+
+ function DOMHandler() {
+ /* SAX handler to convert a piece of XML to a DOM */
+ };
+
+ this.DOMHandler = DOMHandler;
+
+ DOMHandler.prototype.startDocument = function() {
+ this.document = new Document();
+ this.document.initialize();
+ this.current = null;
+ this.namespaces = new Array();
+ this.namespaceToPrefix = {};
+ };
+
+ DOMHandler.prototype.startElement = function(namespaceURI, nodename,
+ attrs) {
+ if (namespaceURI && !array.contains(this.namespaces, namespaceURI)) {
+ this.namespaces.push(namespaceURI);
+ // update the mapping on the document just to be sure,
+ // that one and the one on this handler should always be in
+ // sync if a start tag is encountered, since instantiating a
+ // Element will set the prefix on that element
+ // XXX ??
+ this.document.namespaceToPrefix = this.namespaceToPrefix;
+ };
+ var node = this.document.createElementNS(namespaceURI, nodename);
+ var prefix = undefined;
+ if (namespaceURI) {
+ prefix = this.namespaceToPrefix[namespaceURI];
+ if (prefix) {
+ node.setPrefix(prefix);
+ };
+ };
+ for (var ans in attrs) {
+ // XXX can be optimized by using a dict and just setting the key
+ if (ans && ans != '' && !array.contains(this.namespaces, ans)) {
+ this.namespaces.push(ans);
+ };
+ var nsattrs = attrs[ans];
+ for (var aname in nsattrs) {
+ if (aname == 'prefix') {
+ continue;
+ };
+ if (ans) {
+ var attr = this.document.createAttributeNS(ans, aname);
+ attr.setPrefix(this.namespaceToPrefix[ans]);
+ attr.nodeValue = nsattrs[aname];
+ node.setAttributeNodeNS(attr);
+ } else {
+ var attr = this.document.createAttribute(aname);
+ attr.nodeValue = nsattrs[aname];
+ node.setAttributeNode(attr);
+ };
+ };
+ };
+ if (!this.current) {
+ this.document.documentElement = node;
+ this.document._setProtected('childNodes', [node]);
+ this.current = node;
+ this.current._setProtected('parentNode', this.document);
+ this.current._setProtected('ownerDocument', this.document);
+ } else {
+ this.current.appendChild(node);
+ this.current = node;
+ };
+ };
+
+ DOMHandler.prototype.characters = function(data) {
+ if (!this.current && string.strip(data) == '') {
+ return;
+ };
+ var node = this.document.createTextNode(data);
+ this.current.appendChild(node);
+ };
+
+ DOMHandler.prototype.comment = function(data) {
+ if (!this.current && string.strip(data) == '') {
+ return;
+ };
+ var node = this.document.createComment(data);
+ if (this.current) {
+ this.current.appendChild(node);
+ } else {
+ this.document.comment = node;
+ };
+ };
+
+ DOMHandler.prototype.endElement = function(namespaceURI, nodename) {
+ var prefix = this.namespaceToPrefix[namespaceURI];
+ if (nodename != this.current.localName ||
+ namespaceURI != this.current.namespaceURI) {
+ throw('non-matching end tag ' + namespaceURI + ':' +
+ prefix + ':' + nodename + ' for start tag ' +
+ this.current.namespaceURI + ':' + this.current.nodeName);
+ };
+ this.current = this.current.parentNode;
+ };
+
+ DOMHandler.prototype.endDocument = function() {
+ };
+
+ function DOM() {
+ /* The DOM API
+
+ Uses regular expressions to convert <xml> to a simple DOM
+
+ Provides:
+
+ DOM.parseXML(xml)
+ - parse the XML, return a document element
+
+ DOM.createDocument()
+ - contains the document node of the DOM (which in turn contains
+ the documentElement)
+
+ DOM.toXML()
+ - returns a serialized XML string
+
+ DOM.buildFromHandler(handler)
+ - build and return a DOM document built from a MiniSAX handler
+ */
+ };
+
+ this.DOM = DOM;
+
+ DOM.prototype.createDocument = function() {
+ var document = new Document();
+ document.initialize();
+ return document;
+ };
+
+ DOM.prototype.toXML = function(docOrEl, encoding) {
+ /* serialize to XML */
+ var xml = '<?xml version="1.0"';
+ if (encoding) {
+ xml += ' encoding="' + encoding + '"';
+ };
+ xml += '?>\n';
+ return xml + docOrEl.toXML();
+ };
+
+ DOM.prototype.parseXML = function(xml) {
+ /* parse XML into a DOM
+
+ returns a Document node
+ */
+ var handler = new DOMHandler();
+ var parser = new SAXParser();
+ parser.initialize(xml, handler);
+ parser.parse();
+ var document = handler.document;
+ this._copyNamespaceMapping(document, handler.namespaceToPrefix);
+ return document;
+ };
+
+ DOM.prototype.buildFromHandler = function(handler) {
+ /* create a DOM from a SAX handler */
+ var document = handler.document;
+ this._copyNamespaceMapping(document, handler.namespaceToPrefix);
+ return document;
+ };
+
+ DOM.prototype._copyNamespaceMapping = function(document, namespaces) {
+ document.namespaceToPrefix = namespaces;
+ };
+
+ // an implementation of an array, exactly the same as the one in JS
+ // (although incomplete) itself, this because friggin' IE has problems
+ // using Array as prototype (it won't update .length on mutations)
+ function BaseArray() {
+ for (var i=0; i < arguments.length; i++) {
+ this[i] = arguments[i];
+ };
+ this.length = arguments.length;
+ };
+
+ BaseArray.prototype.concat = function() {
+ throw('Not supported');
+ };
+
+ BaseArray.prototype.join = function() {
+ throw('Not supported');
+ };
+
+ BaseArray.prototype.pop = function() {
+ var item = this[this.length - 1];
+ delete this[this.length - 1];
+ this.length = this.length - 1;
+ return item;
+ };
+
+ BaseArray.prototype.push = function(item) {
+ this[this.length] = item;
+ this.length = this.length + 1;
+ return item;
+ };
+
+ BaseArray.prototype.reverse = function() {
+ throw('Not supported');
+ };
+
+ BaseArray.prototype.shift = function() {
+ var item = this[0];
+ for (var i=1; i < this.length; i++) {
+ this[i-1] = this[i];
+ };
+ delete this[length - 1];
+ this.length = this.length - 1;
+ return item;
+ };
+
+ BaseArray.prototype.unshift = function(item) {
+ for (var i=0; i < this.length; i++ ) {
+ this[this.length - i] = this[(this.length - i) - 1];
+ };
+ this[0] = item;
+ this.length = this.length + 1;
+ return ;
+ };
+
+ BaseArray.prototype.splice = function() {
+ // XXX we may want to support this later
+ throw('Not supported');
+ };
+
+ BaseArray.prototype.toString = function() {
+ var ret = [];
+ for (var i=1; i < this.length; i++) {
+ ret.push(this[i].toString());
+ };
+ return ret.join(', ');
+ };
+
+ // for subclassing and such...
+ this.BaseArray = BaseArray;
+
+ function NodeList() {
+ };
+
+ NodeList.prototype = new BaseArray;
+ this.NodeList = NodeList;
+
+ NodeList.prototype.item = function(index) {
+ return this[index];
+ };
+
+ function NamedNodeMap() {
+ };
+
+ NamedNodeMap.prototype = new BaseArray;
+ this.NamedNodeMap = NamedNodeMap;
+
+ NamedNodeMap.prototype.item = function(index) {
+ return this[index];
+ };
+
+ NamedNodeMap.prototype.getNamedItem = function(name) {
+ for (var i=0; i < this.length; i++) {
+ if (this[i].nodeName == name) {
+ return this[i];
+ };
+ };
+ return undefined;
+ };
+
+ NamedNodeMap.prototype.setNamedItem = function(arg) {
+ // this should generate exceptions, but I'm not sure when...
+ // XXX how 'bout when arg is not the proper type?!?
+ for (var i=0; i < this.length; i++) {
+ if (this[i].nodeName == arg.nodeName) {
+ this[i] = arg;
+ return;
+ };
+ };
+ this.push(arg);
+ };
+
+ NamedNodeMap.prototype.removeNamedItem = function(name) {
+ // a bit nasty: deleting an element from an array will not actually
+ // free the index, instead something like undefined or null will end
+ // up in its place, so we walk the array here, move every element
+ // behind the item to remove one up, and pop the last item when
+ // we're done
+ var delete_mode = false;
+ for (var i=0; i < this.length; i++) {
+ if (this[i] === name) {
+ delete_mode = true;
+ };
+ if (delete_mode) {
+ this[i] = this[i + 1];
+ };
+ };
+ if (!delete_mode) {
+ throw(
+ (new DOMException(DOMException.NOT_FOUND_ERR))
+ );
+ };
+ // the last element is now in the array twice
+ this.pop();
+ };
+}();
+
+// XXX shouldn't we make these local?
+function createStack() {
+ // somewhat nasty trick to get a stack trace in Moz
+ var stack = undefined;
+ try {notdefined()} catch(e) {stack = e.stack};
+ if (stack) {
+ stack = stack.split('\n');
+ stack.shift();
+ stack.shift();
+ };
+ return stack ? stack.join('\n') : '';
+};
+
+function getLineNo(stack) {
+ /* tries to get the line no in Moz */
+ if (!stack) {
+ return;
+ };
+ stack = stack.toString().split('\n');
+ var chunks = stack[0].split(':');
+ var lineno = chunks[chunks.length - 1];
+ if (lineno != '0') {
+ return lineno;
+ };
+};
+
+function getFileName(stack) {
+ /* tries to get the filename in Moz */
+ if (!stack) {
+ return;
+ };
+ stack = stack.toString().split('\n');
+ var chunks = stack[0].split(':');
+ var filename = chunks[chunks.length - 2];
+ return filename;
+};
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/example.html
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/example.html Sun Jan 20 20:43:18 2008
@@ -0,0 +1,62 @@
+<!--
+
+ example.html - file for testing Dommer, serves also as an example
+ Copyright (C) 2004 Guido Wesdorp
+ email johnny at debris.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-->
+<html>
+ <head>
+ <title>Dommer example</title>
+ <script type="text/javascript" src="../jsbase/array.js"></script>
+ <script type="text/javascript" src="../jsbase/string.js"></script>
+ <script type="text/javascript" src="../minisax.js/minisax.js"></script>
+ <script type="text/javascript" src="dommer.js"></script>
+ <script type="text/javascript">
+ // <![CDATA[
+
+ function run() {
+ // some XML
+ var xml = '<?xml version="1.0" ?>' +
+ '<foo xmlns="http://debris.demon.nl/foo"\n' +
+ 'xmlns:baz="http://debris.demon.nl/baz"\n' +
+ 'xmlns:quux="http://debris.demon.nl/quux"\n' +
+ 'quuux="quu&uux">\n' +
+ '<baz:bar foo="bar" quux:quuux="quuuux">' +
+ '<Qux!>' +
+ '</baz:bar>\n' +
+ '</foo>\n';
+ document.getElementById('startxml').appendChild(
+ document.createTextNode(xml)
+ );
+ var dom = new dommer.DOM();
+ var doc = dom.parseXML(xml);
+ document.getElementById('resultxml').appendChild(
+ document.createTextNode(dom.toXML(doc))
+ );
+ };
+
+ // ]]>
+ </script>
+ </head>
+ <body onload="run();">
+ <h4>Start data:</h4>
+ <pre id="startxml"></pre>
+ <h4>Result:</h4>
+ <pre id="resultxml"></pre>
+ </body>
+</html>
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/run_tests.html
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/run_tests.html Sun Jan 20 20:43:18 2008
@@ -0,0 +1,53 @@
+<!--
+
+ run_tests.html - file for testing Dommer, serves also as an example
+ Copyright (C) 2004-2005 Guido Wesdorp
+ email johnny at debris.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-->
+<html>
+<head>
+<title>Unit tests for Dommer</title>
+<script type="text/javascript" src="../ecmaunit/ecmaunit.js"> </script>
+<script type="text/javascript" src="../jsbase/array.js"> </script>
+<script type="text/javascript" src="../jsbase/string.js"> </script>
+<script type="text/javascript" src="../minisax.js/minisax.js"> </script>
+<script type="text/javascript" src="dommer.js"> </script>
+<script type="text/javascript" src="tests.js"> </script>
+<script type="text/javascript">
+//<![CDATA[
+
+ function runTests() {
+ var body = document.getElementById('body');
+ var testsuite = new TestSuite(new HTMLReporter(body, true));
+ testsuite.registerTest(DOMTestCase);
+ if (navigator.appName.indexOf('Netscape') > -1 ||
+ navigator.appName.indexOf('Konqueror') > -1) {
+ // disable browser tests in IE, for they will fail...
+ testsuite.registerTest(BrowserDOMTestCase);
+ };
+ testsuite.runSuite();
+ };
+
+//]]>
+</script>
+</head>
+
+<body onload="runTests()" id="body">
+<div style="display:none" id="testdiv" ></div>
+</body>
+</html>
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/test_dommer.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/test_dommer.js Sun Jan 20 20:43:18 2008
@@ -0,0 +1,366 @@
+/*
+ tests.js - unit tests for dommer.js
+ Copyright (C) 2004-2005 Guido Wesdorp
+ email johnny at debris.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ $Id: dommer.js,v 1.5 2004/07/31 00:10:15 johnny Exp $
+
+*/
+
+load('../minisax.js/minisax.js');
+load('../jsbase/string.js');
+load('../jsbase/array.js');
+load('dommer.js');
+
+var global = this;
+function setup() {
+ global.dom = new dommer.DOM();
+ global.doc = global.dom.createDocument();
+ global.docfrag = global.doc;
+};
+
+function tearDown() {
+ global.doc = null;
+ delete global.dom;
+};
+
+function test_property_access() {
+ var doc = global.doc;
+ var el = doc.createElement('foo');
+ testing.assertThrows(undefined, function() {el.nodeName = 'foo'});
+};
+
+function test_createElement() {
+ var doc = global.doc;
+
+ var el1 = doc.createElement('foo');
+ testing.assertEquals(el1.nodeType, 1);
+ testing.assertEquals(el1.nodeName.toLowerCase(), 'foo');
+ testing.assertEquals(el1.namespaceURI, null);
+ testing.assertEquals(el1.ownerDocument, doc);
+
+ var el2 = doc.createElementNS('foo:', 'bar');
+ testing.assertEquals(el2.nodeType, 1);
+ testing.assertEquals(el2.nodeName.toLowerCase(), 'bar');
+ testing.assertEquals(el2.namespaceURI, 'foo:');
+ testing.assertEquals(el2.ownerDocument, doc);
+
+ var attr1 = doc.createAttribute('foo');
+ testing.assertEquals(attr1.nodeType, 2);
+ testing.assertEquals(attr1.nodeName, 'foo');
+ testing.assertEquals(attr1.namespaceURI, null);
+};
+
+function test_appendChild() {
+ var doc = global.doc;
+ var docfrag = global.docfrag;
+
+ var el = doc.createElement('foo');
+ docfrag.appendChild(el);
+ if (docfrag == doc) {
+ // not for browser dom
+ testing.assertEquals(doc.documentElement, el);
+ };
+ testing.assertEquals(el.ownerDocument, doc);
+ testing.assertEquals(el.parentNode, docfrag);
+ testing.assertEquals(el.firstChild, null);
+ testing.assertEquals(el.lastChild, null);
+ testing.assertEquals(el.previousSibling, null);
+ testing.assertEquals(el.nextSibling, null);
+ testing.assertEquals(docfrag.childNodes[0], el);
+
+ var el2 = doc.createElement('foo');
+ if (doc == docfrag) {
+ testing.assertThrows(undefined, doc.appendChild, doc, el2);
+ };
+ el.appendChild(el2);
+ testing.assertEquals(el2.parentNode, el);
+ testing.assertEquals(el.childNodes[0], el2);
+ testing.assertEquals(el.firstChild, el2);
+ testing.assertEquals(el.lastChild, el2);
+ testing.assertEquals(el2.previousSibling, null);
+ testing.assertEquals(el2.nextSibling, null);
+
+ var el3 = doc.createElement('foo');
+ el.appendChild(el3);
+ testing.assertEquals(el3.parentNode, el);
+ testing.assertEquals(el.childNodes[1], el3);
+ testing.assertEquals(el.firstChild, el2);
+ testing.assertEquals(el.lastChild, el3);
+ testing.assertEquals(el2.previousSibling, null);
+ testing.assertEquals(el2.nextSibling, el3);
+ testing.assertEquals(el3.previousSibling, el2);
+ testing.assertEquals(el3.nextSibling, null);
+};
+
+function test_removeChild() {
+ var doc = global.doc;
+ var docfrag = global.docfrag;
+
+ var el = doc.createElement('foo');
+ docfrag.appendChild(el);
+
+ var el2 = doc.createElement('bar');
+ testing.assertEquals(el2.parentNode, null);
+ testing.assertEquals(el.firstChild, null);
+ testing.assertEquals(el.lastChild, null);
+ if (doc == docfrag) {
+ testing.assertThrows(dommer.DOMException, el.removeChild, el, el2);
+ };
+
+ el.appendChild(el2);
+ testing.assertEquals(el2.parentNode, el);
+ testing.assertEquals(el.firstChild, el2);
+ testing.assertEquals(el.lastChild, el2);
+ testing.assertEquals(el.childNodes[0], el2);
+
+ el3 = doc.createElement('baz');
+ el.appendChild(el3);
+ testing.assertEquals(el3.parentNode, el);
+ testing.assertEquals(el.firstChild, el2);
+ testing.assertEquals(el.lastChild, el3);
+ testing.assertEquals(el2.nextSibling, el3);
+ testing.assertEquals(el3.previousSibling, el2);
+
+ el.removeChild(el2);
+ testing.assertEquals(el2.parentNode, null);
+ testing.assertEquals(el.firstChild, el3);
+ testing.assertEquals(el.lastChild, el3);
+ testing.assertEquals(el.childNodes[0], el3);
+ testing.assertEquals(el2.nextSibling, null);
+ testing.assertEquals(el3.previousSibling, null);
+};
+
+function test_replaceChild() {
+ var doc = global.doc;
+ var docfrag = global.docfrag;
+
+ var el = doc.createElement('foo');
+ docfrag.appendChild(el);
+
+ var child1 = doc.createElement('bar');
+ var child2 = doc.createElement('baz');
+ var child3 = doc.createElement('qux');
+ el.appendChild(child1);
+
+ testing.assertEquals(el.childNodes.length, 1);
+ testing.assertEquals(el.childNodes[0], child1);
+ testing.assertEquals(child1.parentNode, el);
+
+ el.appendChild(child3);
+ testing.assertEquals(el.firstChild, child1);
+ testing.assertEquals(el.lastChild, child3);
+ testing.assertEquals(child1.nextSibling, child3);
+ testing.assertEquals(child3.previousSibling, child1);
+
+ el.replaceChild(child2, child1);
+ testing.assertEquals(child1.parentNode, null);
+ testing.assertEquals(el.childNodes.length, 2);
+ testing.assertEquals(el.firstChild, child2);
+ testing.assertEquals(el.lastChild, child3);
+ testing.assertEquals(child2.parentNode, el);
+ testing.assertEquals(child1.nextSibling, null);
+ testing.assertEquals(child2.nextSibling, child3);
+ testing.assertEquals(child3.previousSibling, child2);
+};
+
+function test_getAttribute() {
+ var doc = global.doc;
+
+ var el = doc.createElement('foo');
+ el.setAttribute('bar', 'baz');
+ testing.assertFalse(el.getAttribute('foo'));
+ var attr = el.getAttribute('bar');
+ testing.assertEquals(el.getAttribute('bar'), 'baz');
+ var attr = el.getAttributeNode('bar');
+ testing.assertEquals(attr.nodeValue, 'baz');
+ testing.assertEquals(attr.nodeType, 2);
+ testing.assertEquals(attr.namespaceURI, null);
+ testing.assertEquals(attr.ownerDocument, doc);
+ testing.assertEquals(attr.parentNode, null);
+ testing.assertEquals(attr.ownerElement, el);
+
+ el.setAttributeNS('foo:', 'bar', 'baz');
+ var attr = el.getAttributeNodeNS('foo:', 'bar');
+ testing.assertEquals(attr.nodeValue, 'baz');
+ testing.assertEquals(attr.namespaceURI, 'foo:');
+};
+
+function test_setAttribute() {
+ var doc = global.doc;
+
+ var el = doc.createElement('foo');
+ testing.assertThrows(undefined, el.setAttribute, el, 'foo&bar');
+};
+
+function test_toXML() {
+ var doc = global.doc;
+
+ var foo = doc.createElement('foo');
+ testing.assertEquals(foo.toXML(), '<foo />');
+
+ foo.setAttribute('bar', 'baz');
+ testing.assertEquals(foo.getAttributeNode('bar').toXML(), 'bar="baz"');
+ testing.assertEquals(foo.toXML(), '<foo bar="baz" />');
+
+ var parent = doc.createElement('parent');
+ parent.appendChild(foo);
+ testing.assertEquals(parent.toXML(), '<parent><foo bar="baz" /></parent>');
+
+ doc.appendChild(parent);
+ testing.assertEquals(doc.toXML(), '<parent><foo bar="baz" /></parent>');
+ // using DOM.toXML() adds an XML declaration
+ testing.assertEquals(global.dom.toXML(global.doc),
+ '<?xml version="1.0"?>\n<parent><foo bar="baz" /></parent>');
+
+ var elwithns = doc.createElementNS('foo:', 'bar');
+ parent.appendChild(elwithns);
+ testing.assertEquals(elwithns.toXML(), '<bar xmlns="foo:" />');
+ testing.assertEquals(doc.toXML(), '<parent><foo bar="baz" />' +
+ '<bar xmlns="foo:" /></parent>');
+
+ var el1 = doc.createElementNS('foo:', 'bar');
+ el1.setPrefix('foo');
+ var el2 = doc.createElementNS('foo:', 'baz');
+ el2.setPrefix('foo');
+ el1.appendChild(el2);
+ testing.assertEquals(el1.toXML(),
+ '<foo:bar xmlns:foo="foo:"><foo:baz /></foo:bar>');
+
+ var el1 = doc.createElementNS('foo:', 'bar');
+ el1.setPrefix('foo');
+ var el2 = doc.createElementNS('baz:', 'qux');
+ el2.setPrefix('foo');
+ el1.appendChild(el2);
+ testing.assertEquals(el1.toXML(),
+ '<foo:bar xmlns:foo="foo:"><foo:qux xmlns:foo="baz:" /></foo:bar>');
+
+ var el1 = doc.createElementNS('foo:', 'foo:bar');
+ el1.setAttributeNS('baz:', 'baz:qux', 'quux');
+ testing.assertEquals(el1.toXML(),
+ '<foo:bar baz:qux="quux" xmlns:foo="foo:" xmlns:baz="baz:" />');
+};
+
+function test_namedNodeMap() {
+ var nodemap = new dommer.NamedNodeMap();
+
+ var nodes = {};
+ for (var i=0; i < 10; i++) {
+ var node = global.doc.createElement('node-' + i);
+ nodes[i] = node;
+ nodemap.setNamedItem(node);
+ };
+
+ testing.assertEquals(nodemap.length, 10);
+ testing.assertEquals(nodemap[0].nodeName.toLowerCase(), 'node-0');
+ testing.assertEquals(nodemap[0], nodemap.getNamedItem('node-0'));
+ testing.assertEquals(nodemap[nodemap.length - 1],
+ nodemap.getNamedItem('node-9'));
+
+ nodemap.removeNamedItem(nodemap[4]);
+ testing.assertEquals(nodemap.length, 9);
+ testing.assertEquals(nodemap[3], nodes[3]);
+ testing.assertEquals(nodemap[4], nodes[5]);
+ testing.assertEquals(nodemap[8], nodes[9]);
+};
+
+function test_cloneNode() {
+ var doc = global.doc;
+
+ var foo = doc.createElement('foo');
+ foo.setAttribute('bar', 'bar');
+ var baz = doc.createElement('baz');
+ baz.appendChild(foo);
+
+ var clone = baz.cloneNode(false);
+ testing.assertEquals(clone.nodeName.toLowerCase(), 'baz');
+ testing.assertFalse(clone.hasChildNodes());
+
+ var clone = baz.cloneNode(true);
+ testing.assertEquals(clone.nodeName.toLowerCase(), 'baz');
+ testing.assert(clone.hasChildNodes());
+ testing.assertEquals(clone.childNodes.length, 1);
+ testing.assertEquals(clone.childNodes[0].nodeName.toLowerCase(), 'foo');
+ testing.assertEquals(clone.childNodes[0].attributes.length, 1);
+ testing.assertEquals(
+ clone.childNodes[0].attributes[0].nodeName.toLowerCase(), 'bar');
+ testing.assertEquals(clone.childNodes[0].getAttribute('bar'), 'bar');
+};
+
+function test_parseXML() {
+ var dom = new dommer.DOM();
+
+ var xml1 = '<foo />';
+ var doc = dom.parseXML(xml1);
+ testing.assertEquals(doc.documentElement.nodeName, 'foo');
+ testing.assertEquals(doc.childNodes.length, 1);
+ testing.assertEquals(doc.documentElement.childNodes.length, 0);
+
+ var xml2 = '<foo><bar /></foo>';
+ var doc = dom.parseXML(xml2);
+ testing.assertEquals(doc.documentElement.nodeName, 'foo');
+ testing.assertEquals(doc.documentElement.childNodes.length, 1);
+ testing.assertEquals(doc.documentElement.childNodes[0].nodeName, 'bar');
+
+ var xml3 = '<foo><bar baz="baz" /></foo>';
+ var doc = dom.parseXML(xml3);
+ var bar = doc.documentElement.childNodes[0];
+ testing.assertEquals(bar.attributes.length, 1);
+ testing.assertEquals(bar.attributes[0].nodeName, 'baz');
+ testing.assertEquals(bar.attributes[0].nodeValue, 'baz');
+
+ var xml4 = '<foo xmlns="bar:" />';
+ var doc = dom.parseXML(xml4);
+ testing.assertEquals(doc.documentElement.namespaceURI, 'bar:');
+ testing.assertEquals(doc.documentElement.prefix, null);
+
+ var xml5 = '<foo:bar xmlns:foo="baz:" />';
+ var doc = dom.parseXML(xml5);
+ testing.assertEquals(doc.documentElement.nodeName, 'foo:bar');
+ testing.assertEquals(doc.documentElement.localName, 'bar');
+ testing.assertEquals(doc.documentElement.prefix, 'foo');
+ testing.assertEquals(doc.documentElement.namespaceURI, 'baz:');
+
+ var xml6 = '<foo>bar</foo>';
+ var doc = dom.parseXML(xml6);
+ testing.assertEquals(doc.documentElement.childNodes.length, 1);
+ testing.assertEquals(doc.documentElement.firstChild.nodeType, 3);
+ testing.assertEquals(doc.documentElement.firstChild.nodeValue, 'bar');
+
+ var xml7 = '<foo xmlns="foo:" xmlns:bar="bar:" bar:baz="qux" />';
+ var doc = dom.parseXML(xml7);
+ testing.assertEquals(doc.documentElement.attributes.length, 1);
+ testing.assertEquals(doc.documentElement.attributes[0].nodeName,
+ 'bar:baz');
+ testing.assertEquals(doc.documentElement.attributes[0].localName, 'baz');
+ testing.assertEquals(doc.documentElement.attributes[0].nodeValue, 'qux');
+ testing.assertEquals(doc.documentElement.attributes[0].namespaceURI,
+ 'bar:');
+ testing.assertEquals(doc.documentElement.attributes[0].prefix, 'bar');
+
+ var xml8 = '<foo:bar xmlns:foo="foo:"><foo:baz xmlns:foo="bar:" />' +
+ '</foo:bar>';
+ var doc = dom.parseXML(xml8);
+ testing.assertEquals(doc.toXML(), xml8);
+
+ var xml9 = '<foo:bar xmlns:foo="foo:"><bar:baz xmlns:bar="foo:" />' +
+ '</foo:bar>';
+ var expected = '<foo:bar xmlns:foo="foo:"><foo:baz /></foo:bar>';
+ var doc = dom.parseXML(xml9);
+ testing.assertEquals(doc.toXML(), expected);
+};
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/version.txt
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/version.txt Sun Jan 20 20:43:18 2008
@@ -0,0 +1 @@
+0.4
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/LICENSE.txt
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/LICENSE.txt Sun Jan 20 20:43:18 2008
@@ -0,0 +1,31 @@
+JSBase - Copyright (c) 2004-2007, Guido Wesdorp
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of JSBase nor the names of its contributors may
+ be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/README.txt
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/README.txt Sun Jan 20 20:43:18 2008
@@ -0,0 +1,137 @@
+JSBase
+=======
+
+What is it?
+------------
+
+This is a collection of bits of JavaScript helper functionality, to solve
+common problems encountered when programming JavaScript code. The library was
+mostly written because I needed certain generic functionality available for
+using in different JS projects, but will be valuable for anyone writing JS
+code. The strenghts of this library are:
+
+ * everything is written in 'modules', which provide their own namespace and
+ are seperately loadable (certain modules do depend on others, but I tried
+ to keep this down to a minimum)
+
+ * care has been taken that it's possible to use this library *at any time,
+ on any platform*, by not depending on any variables being available, or
+ isolating the instances where a variable (for instance 'window') is
+ required
+
+ * the library should not clash with other libraries
+
+ * no overriding or extending of built-in data types or functionality
+
+ * the library is light-weight, and has no impact on the way the JS is
+ written, although it shows some patterns to use concerning 'OO' programming
+ in JS, it does not make the code harder to read or understand for people
+ that don't know the library by using or enforcing complex patterns
+
+ * the functionality in this library can, with the exception of few very
+ browser-specific functions, can be used in any JS environment (e.g. the
+ unit tests are ran using SpiderMonkey, see 'unit tests' below)
+
+ * the library is simple and self-explanatory (of course this is not an excuse
+ for not providing documentation! my excuse for that is lack of time...)
+
+What kind of functionality should I expect?
+--------------------------------------------
+
+This library provides solutions to problems in the core language (e.g.
+functions to deal more easily with arrays and strings) and somewhat lower level
+problems in JS environments (e.g. a cross-platform print() function to write to
+stdout or the document in some way). There are some helpers to solve browser
+incompatibility problems (e.g. a 'getXMLHttpRequest()' function and
+cross-browser event handling) and wrappers for things that are just very badly
+implemented in browsers (e.g. a schedule() function which you can pass a
+normal callable and additional arguments to, a wrapper to solve the problem
+where 'this' in a method body refers to something else than the object a method
+is implemented on and proper exception classes).
+
+More detailed description of the modules
+------------------------------------------
+
+The modules, with a short description:
+
+ * array.js
+
+ a set of functions to help with arrays, basically stuff that the JS core
+ should have provided for
+
+ * exception.js
+
+ this provides the Exception base class and some subclasses, the excepsions
+ raised by the library use these to allow distinguishing between different
+ exceptions more easily, and also they provide a traceback if the platform
+ allows that (mainly Mozilla-related platforms)
+
+ * function.js
+
+ this currently provides a single function, that helps fixing the 'this'
+ problem, where 'this' inside methods points to something else than the
+ object which the methods are defined on (happens e.g. on event handling
+ in browsers)
+
+ * misclib.js
+
+ a set of miscellaneous functionality, such as a schedule() method for
+ scheduling function calls (to replace window.setTimeout), cross-browser
+ event handling (also fixing memory leaks in IE), a repr() function to
+ create string representations of objects (also recursively, if desired),
+ a dir() function to view the attributes of objects, and a print() function
+ that makes messages visible in different ways, depending on the platform
+ you're on (allowing for presenting text to a user both in browsers and
+ command line environments)
+
+ * number.js
+
+ number related functions
+
+ * server.js
+
+ cross-browser server interaction, some higher-level 'AJAX'-related
+ functions
+
+ * string.js
+
+ string related functions
+
+ * testing.js
+
+ functionality to help debugging and testing your applications, it both
+ harbours a couple of helper functions you can call from your code, as
+ functionality to unit-test that code (with py.test integration, see below)
+
+Unit testing
+-------------
+
+The 'testing.js' module contains some functions that can be used to write very
+simple unit tests (see the module for more information for now). Also there's
+a 'conftest.py' and some stuff in the 'testing' dir that allows you to run
+JavaScript unit tests using the Python 'py.test' unit test runner, part of the
+`py lib`_ library.
+
+.. _`py lib`: http://codespeak.net/py
+
+Other files
+------------
+
+The other files in the directory are documentation and license information
+and such, and unit tests for the package and related files.
+
+Note
+----
+
+Note that the library is currently not in a state in which it can be considered
+a complete solution: it merely provides me personally the stuff I needed the
+period I used it... Hopefully at some point it will be complete enough to use
+by others, but right now don't expect it to solve all your general JS problems
+yet.
+
+Questions, bug reports, etc.
+-----------------------------
+
+If you have questions, bug reports, patches or remarks, please send an email
+to johnny at johnnydebris.net.
+
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/__init__.py
==============================================================================
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/array.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/array.js Sun Jan 20 20:43:18 2008
@@ -0,0 +1,114 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
+ *
+ * This software is distributed under the terms of the JSBase
+ * License. See LICENSE.txt for license text.
+ *
+ *****************************************************************************/
+
+var global = this;
+global.array = new function() {
+ var array = this;
+
+ this.contains = function(a, element, objectequality) {
+ /* see if some value is in a */
+ // DEPRECATED!!! use array.indexOf instead
+ return (this.indexOf(a, element, !objectequality) > -1);
+ };
+
+ this.indexOf = function(a, element, compareValues) {
+ for (var i=0; i < a.length; i++) {
+ if (!compareValues) {
+ if (element === a[i]) {
+ return i;
+ };
+ } else {
+ if (element == a[i]) {
+ return i;
+ };
+ };
+ };
+ return -1;
+ };
+
+ this.removeDoubles = function(a) {
+ var ret = [];
+ for (var i=0; i < a.length; i++) {
+ if (!this.contains(ret, a[i])) {
+ ret.push(a[i]);
+ };
+ };
+ return ret;
+ };
+
+ this.map = function(a, func) {
+ /* apply 'func' to each element in the array (in-place!!) */
+ for (var i=0; i < a.length; i++) {
+ a[i] = func(a[i]);
+ };
+ return this;
+ };
+
+ this.reversed = function(a) {
+ var ret = [];
+ for (var i = a.length; i > 0; i--) {
+ ret.push(a[i - 1]);
+ };
+ return ret;
+ };
+
+ this.StopIteration = function(message) {
+ if (message !== undefined) {
+ this._initialize('StopIteration', message);
+ };
+ };
+
+ if (global.exception) {
+ StopIteration.prototype = global.exception.Exception;
+ };
+
+ var Iterator = this.Iterator = function(a) {
+ if (a) {
+ this._initialize(a);
+ };
+ };
+
+ Iterator._initialize = function(a) {
+ this._array = a;
+ this._i = 0;
+ };
+
+ Iterator.next = function() {
+ if (this._i >= this._array.length) {
+ this._i = 0;
+ throw(StopIteration('no more items'));
+ };
+ return this._i++;
+ };
+
+ this.iterate = function(a) {
+ /* iterate through array 'a'
+
+ this returns the n-th item of array 'a', where n is the number of
+ times this function has been called on 'a' before
+
+ when the items are all visited, the function resets the counter and
+ starts from the start
+
+ note that this annotates the array with information about iteration
+ using the attribute '__iter_index__', remove this or set to 0 to
+ reset
+
+ this does not work well with arrays that have 'undefined' as one of
+ their values!!
+ */
+ if (!a.__iter_index__) {
+ a.__iter_index__ = 0;
+ } else if (a.__iter_index__ >= a.length) {
+ a.__iter_index__ = undefined;
+ return undefined;
+ };
+ return a[a.__iter_index__++];
+ };
+}();
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/conftest.py
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/conftest.py Sun Jan 20 20:43:18 2008
@@ -0,0 +1,166 @@
+# JS unit test support for py.test - (c) 2007 Guido Wesdorp. All rights
+# reserved
+#
+# This software is distributed under the terms of the JSBase
+# License. See LICENSE.txt for license text.
+
+import py
+
+here = py.magic.autopath().dirpath()
+
+class JSTest(py.test.collect.Item):
+ def run(self):
+ path = self.fspath
+ test = self.name.split('/')[-1]
+ paths = [path.strpath,
+ (here / 'exception.js').strpath,
+ (here / 'testing.js').strpath,
+ (here / 'misclib.js').strpath,
+ ]
+ testjs = (here / 'testing/testbase.js').read() % (
+ paths, test, '__main__')
+ curdir = str(py.path.local('.'))
+ py.std.os.chdir(str(self.fspath.dirpath()))
+ try:
+ jspath = self.fspath.new(basename='__testbase_temp.js')
+ try:
+ jspath.write(testjs)
+ pipe = py.std.os.popen('js "%s"' % (jspath,))
+ try:
+ data = {}
+ for line in pipe:
+ done = self._handle_line(line, data)
+ if done:
+ errdata = data[data['current']]
+ if errdata:
+ self.fail(errdata)
+ finally:
+ pipe.close()
+ finally:
+ jspath.remove()
+ finally:
+ py.std.os.chdir(curdir)
+
+ def fail(self, errdata):
+ py.test.fail(
+ '\nJS traceback (most recent last): \n%s\n%s\n' % (
+ (errdata[1:] and
+ self._format_tb(errdata[1:-5]) or
+ 'no traceback available'
+ ),
+ errdata[0],
+ )
+ )
+
+ _handling_traceback = False
+ def _handle_line(self, line, data):
+ line = line[:-1]
+ if line.startswith('end test'):
+ return True
+ if self._handling_traceback and line != 'end traceback':
+ data[data['current']].append(line)
+ if line.startswith('PRINTED: '):
+ print line[9:]
+ elif line.startswith('running test '):
+ testname = line[13:]
+ data['current'] = testname
+ data[testname] = []
+ elif line.startswith('success'):
+ pass
+ elif line.startswith('failure: '):
+ data[data['current']].append(line[9:])
+ elif line.startswith('traceback'):
+ self._handling_traceback = True
+ elif line.startswith('end traceback'):
+ self._handling_traceback = False
+
+ def _format_tb(self, tb):
+ tb.reverse()
+ ret = []
+ for line in tb:
+ line = line.strip()
+ if not line:
+ continue
+ funcsig, lineinfo = line.split('@', 1)
+ fpath, lineno = lineinfo.rsplit(':', 1)
+ fname = py.path.local(fpath).basename
+ # XXX might filter out too much... but it's better than leaving it
+ # all in (since it adds a couple of lines to the end of the tb,
+ # making it harder to find the problem line)
+ if fname in ['__testbase_temp.js', '__testbase_find.js',
+ 'exception.js']:
+ continue
+ lineno = int(lineno)
+ if lineno == 0:
+ fname = "<unknown>"
+ ret.append('File "%s", line %s, in %s' % (
+ fname, lineno, funcsig or '?'))
+ if lineno > 0:
+ line = py.path.local(fpath).readlines()[lineno - 1]
+ ret.append(' %s' % (line.strip(),))
+ return '\n'.join([' %s' % (r,) for r in ret])
+
+class JSChecker(py.test.collect.Module):
+ def __repr__(self):
+ return py.test.collect.Collector.__repr__(self)
+
+ def setup(self):
+ pass
+
+ def teardown(self):
+ pass
+
+ def run(self):
+ findjs = here.join('testing/findtests.js').read() % (
+ self.fspath.strpath, '__main__')
+ curdir = str(py.path.local('.'))
+ py.std.os.chdir(str(self.fspath.dirpath()))
+ tests = []
+ try:
+ jspath = self.fspath.new(basename='__findtests.js')
+ try:
+ jspath.write(findjs)
+ stdin, pipe, stderr = py.std.os.popen3('js "%s"' % (jspath,))
+ try:
+ error = stderr.next()
+ print 'Error read:', error
+ except StopIteration:
+ pass
+ else:
+ if error.find('command not found') > -1:
+ py.test.skip(
+ 'error running "js" (SpiderMonkey), which is '
+ 'required to run JS tests')
+ else:
+ py.test.fail(error)
+ return
+ try:
+ for line in pipe:
+ tests.append(line.strip())
+ finally:
+ py.std.sys.stdout = py.std.sys.__stdout__
+ pipe.close()
+ finally:
+ jspath.remove()
+ finally:
+ py.std.os.chdir(curdir)
+ return ['%s/%s' % (self.fspath.basename, test) for test in tests]
+
+ def join(self, name):
+ if py.path.local(name).dirpath().strpath.endswith('.js'):
+ return JSTest(name, self)
+ return super(JSChecker, self).join(name)
+
+class Directory(py.test.collect.Directory):
+ def run(self):
+ if self.fspath == here:
+ return [p.basename for p in self.fspath.listdir('test_*') if
+ p.ext in ['.py', '.js']]
+ return super(Directory, self).run()
+
+ def join(self, name):
+ if not name.endswith('.js'):
+ return super(Directory, self).join(name)
+ p = self.fspath.join(name)
+ if p.check(file=1):
+ return JSChecker(p, parent=self)
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/exception.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/exception.js Sun Jan 20 20:43:18 2008
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
+ *
+ * This software is distributed under the terms of the JSBase
+ * License. See LICENSE.txt for license text.
+ *
+ *****************************************************************************/
+
+var global = this;
+global.exception = new function() {
+ /* Exception handling in a somewhat coherent manner */
+
+ var exception = this;
+
+ this.Exception = function(message) {
+ /* base class of exceptions */
+ if (message !== undefined) {
+ this._initialize('Exception', message);
+ };
+ };
+
+ this.Exception.prototype._initialize = function(name, message) {
+ this.name = name;
+ this.message = message;
+ var stack = this.stack = exception._createStack();
+ this.lineNo = exception._getLineNo(stack);
+ this.fileName = exception._getFileName(stack);
+ };
+
+ this.Exception.prototype.toString = function() {
+ var lineNo = this.lineNo;
+ var fileName = this.fileName;
+ var stack = this.stack;
+ var exc = this.name + ': ' + this.message + '\n';
+ if (lineNo || fileName || stack) {
+ exc += '\n';
+ };
+ if (fileName) {
+ exc += 'file: ' + fileName;
+ if (lineNo) {
+ exc += ', ';
+ } else {
+ exc += '\n';
+ };
+ };
+ if (lineNo) {
+ exc += 'line: ' + lineNo + '\n';
+ };
+ if (stack) {
+ exc += '\n';
+ var lines = stack.split('\n');
+ for (var i=0; i < lines.length; i++) {
+ var line = lines[i];
+ if (line.charAt(0) == '(') {
+ line = 'function' + line;
+ };
+ exc += line + '\n';
+ };
+ };
+ return exc;
+ };
+
+ this.ValueError = function(message) {
+ /* raised on providing invalid values */
+ if (message !== undefined) {
+ this._initialize('ValueError', message);
+ };
+ };
+
+ this.ValueError.prototype = new this.Exception;
+
+ this.AssertionError = function(message) {
+ /* raised when an assertion fails */
+ if (message !== undefined) {
+ this._initialize('AssertionError', message);
+ };
+ };
+
+ this.AssertionError.prototype = new this.Exception;
+
+ // XXX need to define a load of useful exceptions here
+ this.NotSupported = function(message) {
+ /* raised when a feature is not supported on the running platform */
+ if (message !== undefined) {
+ this._initialize('NotSupported', message);
+ };
+ };
+
+ this.NotSupported.prototype = new this.Exception;
+
+ this.NotFound = function(message) {
+ /* raised when something is not found */
+ if (message !== undefined) {
+ this._initialize('NotFound', message);
+ };
+ };
+
+ this.NotFound.prototype = new this.Exception;
+
+ this.HTTPError = function(status) {
+ if (status !== undefined) {
+ // XXX need to get the message for the error here...
+ this._initialize('HTTPError', status);
+ };
+ };
+
+ this.HTTPError.prototype = new this.Exception;
+
+ this.MissingDependency = function(missing, from) {
+ /* raised when some dependency can not be resolved */
+ if (missing !== undefined) {
+ var message = missing;
+ if (from) {
+ message += ' (from ' + from + ')';
+ };
+ this._initialize('MissingDependency', message);
+ };
+ };
+
+ this.NotFound.prototype = new this.Exception;
+
+ this._createStack = function() {
+ /* somewhat nasty trick to get a stack trace in (works only in Moz) */
+ var stack = undefined;
+ try {notdefined()} catch(e) {stack = e.stack};
+ if (stack) {
+ stack = stack.split('\n');
+ stack.shift();
+ stack.shift();
+ };
+ return stack ? stack.join('\n') : '';
+ };
+
+ this._getLineNo = function(stack) {
+ /* tries to get the line no in (works only in Moz) */
+ if (!stack) {
+ return;
+ };
+ stack = stack.toString().split('\n');
+ var chunks = stack[0].split(':');
+ var lineno = chunks[chunks.length - 1];
+ if (lineno != '0') {
+ return lineno;
+ };
+ };
+
+ this._getFileName = function(stack) {
+ /* tries to get the filename in (works only in Moz) */
+ if (!stack) {
+ return;
+ };
+ stack = stack.toString().split('\n');
+ var chunks = stack[0].split(':');
+ var filename = chunks[chunks.length - 2];
+ return filename;
+ };
+}();
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/function.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/function.js Sun Jan 20 20:43:18 2008
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
+ *
+ * This software is distributed under the terms of the jsbase
+ * License. See LICENSE.txt for license text.
+ *
+ *****************************************************************************/
+
+var global = this;
+global.func = new function() {
+ this.fixContext = function(f, context) {
+ /* Return a function wrapped, so that 'this' points to 'context'
+
+ Under certain circumstances, methods get called with the 'this'
+ variable pointing to something else than the object the method is
+ defined on. In that case, one can use some trick with nested scopes
+ and Function.apply() to get this to refer to the object again. This
+ method provides a generic wrapper, that not only fixes 'this'
+ but also allows passing additional arguments to handlers.
+
+ Example:
+
+ // create an object with a method that will serve as an event
+ // handler later on
+ function Foo() {
+ this.bar = 1;
+ this.baz = function(event, some_arg) {
+ // if the following would be done when this method would not
+ // get wrapped, 'this' would point to the Event object rather
+ // than the Foo one, resulting in a name lookup problem
+ alert('this.bar: ' + this.bar + ', some_arg: ' + some_arg);
+ };
+ };
+
+ // create a Foo
+ var foo = new Foo();
+
+ // get some element to register some event on
+ var el = document.getElementById('some_element');
+
+ // now we're going to register the foo.baz method as an
+ // event handler for the 'onclick' event on the element,
+ // but we're wrapping it first, and pass in some argument just
+ // for show
+ // using the Mozilla style of event registration, see
+ // event.js' registerEventHandler() for a cross-browser way
+ el.addEventListener('click', func.fixContext(foo.bar, foo, 2),
+ false);
+
+ The method will be called with the following arguments:
+
+ - the object that 'this' would point to when the method would have
+ been used unwrapped
+
+ - the additional arguments the fixContext method was called with
+
+ - the arguments the wrapped version was called with
+
+ */
+ var orgargs = [];
+ for (var i=0; i < arguments.length; i++) {
+ if (i == 0 || (context && i == 1)) {
+ continue;
+ };
+ orgargs.push(arguments[i]);
+ };
+ if (!context) {
+ context = window;
+ };
+ var wrapper = function() {
+ var funcargs = [this];
+ for (var i=0; i < orgargs.length; i++) {
+ funcargs.push(orgargs[i]);
+ };
+ for (var i=0; i < arguments.length; i++) {
+ funcargs.push(arguments[i]);
+ };
+ return f.apply(context, funcargs);
+ };
+ return wrapper;
+ };
+}();
Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/misclib.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/misclib.js Sun Jan 20 20:43:18 2008
@@ -0,0 +1,350 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
+ *
+ * This software is distributed under the terms of the JSBase
+ * License. See LICENSE.txt for license text.
+ *
+ *****************************************************************************/
+
+var global = this;
+global.misclib = new function() {
+ /* This lib mostly contains fixes for common problems in JS, additions to
+ the core global functions and wrappers for fixing browser issues.
+
+ See the comments in the code for further explanations.
+ */
+
+ // reference to the lib to reach it from the functions/classes
+ var misclib = this;
+
+ var Timer = function() {
+ /* Wrapper around window.setTimeout, to solve number of problems:
+
+ * setTimeout gets a string rather than a function reference as an
+ argument
+
+ * setTimeout can not handle arguments to the callable properly,
+ since it's evaluated in the window namespace, not in the current
+ scope
+
+ Usage:
+
+ // call the global 'schedule' function to register a function
+ // called 'foo' on the current (imaginary) object, passing in
+ // a variable called 'bar' as an argument, so it gets called
+ // after 1000 msecs
+ window.misclib.schedule(this, this.foo, 1000, bar);
+
+ Note that if you don't care about 'this' inside the function
+ you register, you can just pass in a ref to the 'window' object
+ as the first argument. No lookup is done in the namespace, the
+ first argument is only used as the 'this' variable inside the
+ function.
+ */
+ this.lastid = 0;
+ this.functions = {};
+
+ this.registerCallable = function(object, func, timeout) {
+ /* register a function to be called with a timeout
+
+ args:
+ object - the context in which to call the function ('this')
+ func - the function
+ timeout - timeout in millisecs
+
+ all other args will be passed 1:1 to the function when called
+ */
+ var args = new Array();
+ for (var i=3; i < arguments.length; i++) {
+ args.push(arguments[i]);
+ }
+ var id = this._createUniqueId();
+ this.functions[id] = new Array(object, func, args);
+ // setTimeout will be called in the module namespace, where the
+ // timer_instance variable also resides (see below)
+ setTimeout("window.misclib.timer_instance." +
+ "_handleFunction(" + id + ")", timeout);
+ };
+
+ this._handleFunction = function(id) {
+ /* private method that does the actual function call */
+ var obj = this.functions[id][0];
+ var func = this.functions[id][1];
+ var args = this.functions[id][2];
+ this.functions[id] = null;
+ func.apply(obj, args);
+ };
+
+ this._createUniqueId = function() {
+ /* create a unique id to store the function by */
+ while (this.lastid in this.functions &&
+ this.functions[this.lastid]) {
+ this.lastid++;
+ if (this.lastid > 100000) {
+ this.lastid = 0;
+ }
+ }
+ return this.lastid;
+ };
+ };
+
+ // create a timer instance in the module namespace
+ var timer_instance = this.timer_instance = new Timer();
+
+ // this is the function that should be called to register callables
+ this.schedule = function() {
+ timer_instance.registerCallable.apply(timer_instance, arguments)};
+
+ // cross-browser event registration
+ var events_supported = true;
+ try {
+ window;
+ } catch(e) {
+ events_supported = false;
+ };
+
+ if (events_supported) {
+ // first some privates
+
+ // a registry for events so they can be unregistered on unload of the
+ // body
+ var event_registry = {};
+
+ // an iterator for unique ids
+ var currid = 0;
+
+ // just to make some guy on irc happy, store references to
+ // browser-specific wrappers so we don't have to find out the type of
+ // browser on every registration (yeah, yeah, i admit it was quite a
+ // good tip... ;)
+ var reg_handler = null;
+ var unreg_handler = null;
+ if (window.addEventListener) {
+ reg_handler = function(element, eventname, handler) {
+ // XXX not sure if anyone ever uses the last argument...
+ element.addEventListener(eventname, handler, false);
+ };
+ unreg_handler = function(element, eventname, handler) {
+ element.removeEventListener(eventname, handler, false);
+ };
+ } else if (window.attachEvent) {
+ reg_handler = function(element, eventname, handler) {
+ element.attachEvent('on' + eventname, handler);
+ };
+ dereg_handler = function(element, eventname, handler) {
+ element.detachEvent('on' + eventname, handler);
+ };
+ } else {
+ reg_handler = function(element, eventname, handler) {
+ var message = 'Event registration not supported or not ' +
+ 'understood on this platform';
+ if (global.exception) {
+ throw(new exception.NotSupported(message));
+ } else {
+ throw(message);
+ };
+ };
+ };
+
+ this.addEventHandler = function(element, eventname, handler, context) {
+ /* Method to register an event handler
+
+ Works in standards compliant browsers and IE, and solves a
+ number of different problems. Most obviously it makes that
+ there's only a single function to use and memorize, but also
+ it makes that 'this' inside the function points to the context
+ (usually you'll want to pass in the object the method is
+ defined on), and it fixes memory leaks (IE is infamous for
+ leaking memory, which can lead to problems if you register a
+ lot of event handlers, especially since the memory leakage
+ doesn't disappear on page reloads, see e.g.
+ http://www.bazon.net/mishoo/articles.epl?art_id=824).
+
+ Arguments:
+
+ * element - the object to register the event on
+
+ * eventname - a string describing the event (Mozilla style,
+ so without the 'on')
+
+ * handler - a reference to the function to be called when
+ the event occurs
+
+ * context - the 'this' variable inside the function
+
+ The arguments passed to the handler:
+
+ * event - a reference to the event fired
+
+ * all arguments passed in to this function besides