Compare commits
1 Commits
v1
...
tags/Last1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
973a54719f |
5
mozilla/js/src/liveconnect/MANIFEST
Normal file
5
mozilla/js/src/liveconnect/MANIFEST
Normal file
@@ -0,0 +1,5 @@
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
jsjava.h
|
||||
nsILiveconnect.h
|
||||
89
mozilla/js/src/liveconnect/Makefile
Normal file
89
mozilla/js/src/liveconnect/Makefile
Normal file
@@ -0,0 +1,89 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
|
||||
DEPTH = ../../..
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
ifdef NSJVM
|
||||
DIRS = classes
|
||||
endif
|
||||
|
||||
MODULE = java
|
||||
LIBRARY_NAME = jsj
|
||||
|
||||
REQUIRES = java js applet nspr img util layer xpcom
|
||||
|
||||
CSRCS = jsj.c \
|
||||
jsj_JSObject.c \
|
||||
jsj_JavaArray.c \
|
||||
jsj_JavaClass.c \
|
||||
jsj_JavaMember.c \
|
||||
jsj_JavaObject.c \
|
||||
jsj_JavaPackage.c \
|
||||
jsj_array.c \
|
||||
jsj_class.c \
|
||||
jsj_convert.c \
|
||||
jsj_field.c \
|
||||
jsj_hash.c \
|
||||
jsj_method.c \
|
||||
jsj_utils.c \
|
||||
nsCLiveconnect.c \
|
||||
nsCLiveconnectFactory.c
|
||||
|
||||
|
||||
LLIBS=$(LIBNSPR) $(DIST)/lib/js$(MOZ_BITS)$(VERSION_NUMBER).lib \
|
||||
$(DIST)/lib/xpcom32.lib
|
||||
|
||||
|
||||
ifdef NSJVM
|
||||
JNI_GEN = netscape.javascript.JSObject netscape.javascript.JSException
|
||||
endif
|
||||
|
||||
EXPORTS = jsjava.h \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSObject.h \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSException.h \
|
||||
nsILiveconnect.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
######################################################################
|
||||
|
||||
# Generate jsj_nodl.c (so that you can check it in)
|
||||
# These make rules only works on IRIX...sigh
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
jsj_nodl.c: $(OBJDIR)/stubs.o Makefile $(DEPTH)/config/nodl.pl
|
||||
rm -f $@
|
||||
$(PERL) $(DEPTH)/config/nodl.pl "jsj_nodl_tab" \
|
||||
`nm -Bn $(OBJDIR)/stubs.o | egrep Java_.*_stub | awk '{print $$3;}'` > $@
|
||||
endif
|
||||
|
||||
ifdef JAVA_OR_OJI
|
||||
$(OBJDIR)/stubs.o: \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSObject.c \
|
||||
$(JNI_GEN_DIR)/netscape_javascript_JSException.c \
|
||||
$(NULL)
|
||||
else
|
||||
$(OBJDIR)/stubs.o:
|
||||
endif
|
||||
|
||||
90
mozilla/js/src/liveconnect/Makefile.in
Normal file
90
mozilla/js/src/liveconnect/Makefile.in
Normal file
@@ -0,0 +1,90 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
ifdef NSJVM
|
||||
DIRS = classes
|
||||
endif
|
||||
|
||||
|
||||
MODULE = java
|
||||
LIBRARY_NAME = jsj
|
||||
|
||||
REQUIRES = java js applet nspr img util layer xpcom caps oji plugin
|
||||
|
||||
CSRCS = jsj.c \
|
||||
jsj_JSObject.c \
|
||||
jsj_JavaArray.c \
|
||||
jsj_JavaClass.c \
|
||||
jsj_JavaMember.c \
|
||||
jsj_JavaObject.c \
|
||||
jsj_JavaPackage.c \
|
||||
jsj_array.c \
|
||||
jsj_class.c \
|
||||
jsj_convert.c \
|
||||
jsj_field.c \
|
||||
jsj_hash.c \
|
||||
jsj_method.c \
|
||||
jsj_utils.c
|
||||
nsCLiveconnect.c \
|
||||
nsCLiveconnectFactory.c
|
||||
|
||||
|
||||
ifdef NSJVM
|
||||
JNI_GEN = netscape.javascript.JSObject netscape.javascript.JSException
|
||||
endif
|
||||
|
||||
EXPORTS = $(srcdir)/jsjava.h \
|
||||
$(srcdir)/$(JNI_GEN_DIR)/netscape_javascript_JSObject.h \
|
||||
$(srcdir)/$(JNI_GEN_DIR)/netscape_javascript_JSException.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
######################################################################
|
||||
|
||||
# Generate jsj_nodl.c (so that you can check it in)
|
||||
# These make rules only works on IRIX...sigh
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
jsj_nodl.c: $(OBJDIR)/stubs.o Makefile $(topsrcdir)/config/nodl.pl
|
||||
rm -f $@
|
||||
$(PERL) $(topsrcdir)/config/nodl.pl "jsj_nodl_tab" \
|
||||
`nm -Bn $(OBJDIR)/stubs.o | egrep Java_.*_stub | awk '{print $$3;}'` > $@
|
||||
endif
|
||||
|
||||
ifdef JAVA_OR_OJI
|
||||
$(OBJDIR)/stubs.o: \
|
||||
$(JRI_GEN_DIR)/netscape_javascript_JSObject.c \
|
||||
$(JRI_GEN_DIR)/netscape_javascript_JSException.c \
|
||||
$(NULL)
|
||||
else
|
||||
$(OBJDIR)/stubs.o:
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include "jni.h"
|
||||
|
||||
/* Header for class netscape_javascript_JSException */
|
||||
|
||||
#ifndef _Included_netscape_javascript_JSException
|
||||
#define _Included_netscape_javascript_JSException
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
102
mozilla/js/src/liveconnect/_jni/netscape_javascript_JSObject.h
Normal file
102
mozilla/js/src/liveconnect/_jni/netscape_javascript_JSObject.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include "jni.h"
|
||||
|
||||
/* Header for class netscape_javascript_JSObject */
|
||||
|
||||
#ifndef _Included_netscape_javascript_JSObject
|
||||
#define _Included_netscape_javascript_JSObject
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: initClass
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getMember
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getSlot
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot
|
||||
(JNIEnv *, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setMember
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember
|
||||
(JNIEnv *, jobject, jstring, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setSlot
|
||||
* Signature: (ILjava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot
|
||||
(JNIEnv *, jobject, jint, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: removeMember
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: call
|
||||
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call
|
||||
(JNIEnv *, jobject, jstring, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: eval
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: toString
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getWindow
|
||||
* Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: finalize
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
65
mozilla/js/src/liveconnect/classes/Makefile
Normal file
65
mozilla/js/src/liveconnect/classes/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
|
||||
DEPTH = ../../../..
|
||||
|
||||
MODULE = java
|
||||
|
||||
#
|
||||
# the idea is that the install phase for those modules will
|
||||
# make their own signed jar files
|
||||
# there are some exceptions here that we deal with
|
||||
# stuff in modules and in ns/js/jsj
|
||||
#
|
||||
JMODS = netscape/javascript netscape/javascript/adapters
|
||||
|
||||
#
|
||||
# JDIRS is dependant on JAVA_DESTPATH in config/rules.m[a]k.
|
||||
# Be sure to touch that directory if you add a new directory to
|
||||
# JDIRS, or else it will not build. FIXME
|
||||
#
|
||||
JDIRS = $(JMODS)
|
||||
|
||||
JAR_JSJ = jsj10.jar
|
||||
JAR_JSJ_CLASSES = $(JMODS)
|
||||
|
||||
#
|
||||
# jars to build at install time
|
||||
#
|
||||
JARS = $(JAR_JSJ)
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
JAVA_SOURCEPATH = $(DEPTH)/js/src/liveconnect/classes
|
||||
|
||||
doc::
|
||||
$(JAVADOC) -d $(DIST)/doc netscape.javascript
|
||||
|
||||
natives_list:: FORCE
|
||||
rm -rf $@
|
||||
find . -name "*.class" -print | sed 's@\./\(.*\)\.class$$@\1@' | \
|
||||
sed 's@/@.@g' | xargs $(JVH) -natives | sort > $@
|
||||
|
||||
check_natives:: natives_list
|
||||
rm -f found_natives
|
||||
nm -B ../$(OBJDIR)/*.o \
|
||||
| egrep "Java.*_stub" | awk '{ print $$3; }' | sort > found_natives
|
||||
diff found_natives natives_list
|
||||
|
||||
FORCE:
|
||||
70
mozilla/js/src/liveconnect/classes/Makefile.in
Normal file
70
mozilla/js/src/liveconnect/classes/Makefile.in
Normal file
@@ -0,0 +1,70 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = java
|
||||
|
||||
#
|
||||
# the idea is that the install phase for those modules will
|
||||
# make their own signed jar files
|
||||
# there are some exceptions here that we deal with
|
||||
# stuff in modules and in ns/js/jsj
|
||||
#
|
||||
JMODS = netscape/javascript netscape/javascript/adapters
|
||||
|
||||
#
|
||||
# JDIRS is dependant on JAVA_DESTPATH in config/rules.m[a]k.
|
||||
# Be sure to touch that directory if you add a new directory to
|
||||
# JDIRS, or else it will not build. FIXME
|
||||
#
|
||||
JDIRS = $(JMODS)
|
||||
|
||||
JAR_JSJ = jsj10.jar
|
||||
JAR_JSJ_CLASSES = $(JMODS)
|
||||
|
||||
#
|
||||
# jars to build at install time
|
||||
#
|
||||
JARS = $(JAR_JSJ)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
JAVA_SOURCEPATH = $(topsrcdir)/js/src/liveconnect/classes
|
||||
|
||||
doc::
|
||||
$(JAVADOC) -d $(DIST)/doc netscape.javascript
|
||||
|
||||
natives_list:: FORCE
|
||||
rm -rf $@
|
||||
find . -name "*.class" -print | sed 's@\./\(.*\)\.class$$@\1@' | \
|
||||
sed 's@/@.@g' | xargs $(JVH) -natives | sort > $@
|
||||
|
||||
check_natives:: natives_list
|
||||
rm -f found_natives
|
||||
nm -B ../$(OBJDIR)/*.o \
|
||||
| egrep "Java.*_stub" | awk '{ print $$3; }' | sort > found_natives
|
||||
diff found_natives natives_list
|
||||
|
||||
FORCE:
|
||||
78
mozilla/js/src/liveconnect/classes/makefile.win
Normal file
78
mozilla/js/src/liveconnect/classes/makefile.win
Normal file
@@ -0,0 +1,78 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
IGNORE_MANIFEST=1
|
||||
#
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Makefile to build the JavaScript-Java tree
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
DEPTH = ..\..\..\..
|
||||
|
||||
JAVA_SOURCEPATH=$(DEPTH)\js\src\liveconnect\classes
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define the files necessary to build the target (ie. OBJS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
JMOZ = \
|
||||
netscape/javascript \
|
||||
$(NULL)
|
||||
|
||||
|
||||
all::
|
||||
|
||||
MODULE=java
|
||||
JMODS=netscape/javascript
|
||||
!ifdef JAVA_OR_NSJVM
|
||||
JDIRS=$(JMODS)
|
||||
JAR_JSJ_CLASSES=$(JMODS)
|
||||
JAR_NAME = jsj10.jar
|
||||
!endif
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
!ifdef JAVA_OR_NSJVM
|
||||
install::
|
||||
cd $(JAVA_DESTPATH)
|
||||
@echo +++ building/updating $(JAR_NAME)
|
||||
-for %i in ($(JAR_JSJ_CLASSES:/=\)) do @$(ZIP_PROG) $(ZIP_FLAGS) $(JAR_NAME) %i\*.class
|
||||
cd $(MAKEDIR)
|
||||
|
||||
!ifdef REGENERATE
|
||||
install::
|
||||
cd $(JAVA_DESTPATH)
|
||||
@echo +++ updating $(DEPTH)\nav-java\stubs\classes\$(JAR_NAME) for checkin
|
||||
-for %i in ($(JAR_JSJ_CLASSES:/=\)) do @$(ZIP_PROG) $(ZIP_FLAGS) ..\..\nav-java\stubs\classes\$(JAR_NAME) %i\*.class
|
||||
cd $(MAKEDIR)
|
||||
!endif
|
||||
!endif
|
||||
|
||||
javadoc:
|
||||
-mkdir $(XPDIST)\javadoc 2> NUL
|
||||
echo $(JAVADOC) -sourcepath . -d $(XPDIST)\javadoc $(JDIRS:/=.)
|
||||
$(JAVADOC) -sourcepath . -d $(XPDIST)\javadoc $(JDIRS:/=.)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Insert copyright and license here 19** */
|
||||
|
||||
package netscape.javascript;
|
||||
|
||||
/**
|
||||
* JSException is an exception which is thrown when JavaScript code
|
||||
* returns an error.
|
||||
*/
|
||||
|
||||
public
|
||||
class JSException extends Exception {
|
||||
String filename;
|
||||
int lineno;
|
||||
String source;
|
||||
int tokenIndex;
|
||||
|
||||
/**
|
||||
* Constructs a JSException without a detail message.
|
||||
* A detail message is a String that describes this particular exception.
|
||||
*/
|
||||
public JSException() {
|
||||
super();
|
||||
filename = "unknown";
|
||||
lineno = 0;
|
||||
source = "";
|
||||
tokenIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSException with a detail message.
|
||||
* A detail message is a String that describes this particular exception.
|
||||
* @param s the detail message
|
||||
*/
|
||||
public JSException(String s) {
|
||||
super(s);
|
||||
filename = "unknown";
|
||||
lineno = 0;
|
||||
source = "";
|
||||
tokenIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSException with a detail message and all the
|
||||
* other info that usually comes with a JavaScript error.
|
||||
* @param s the detail message
|
||||
*/
|
||||
public JSException(String s, String filename, int lineno,
|
||||
String source, int tokenIndex) {
|
||||
super(s);
|
||||
this.filename = filename;
|
||||
this.lineno = lineno;
|
||||
this.source = source;
|
||||
this.tokenIndex = tokenIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/* -*- Mode: C; tab-width: 4; -*- */
|
||||
|
||||
/* Insert copyright and license here 19** */
|
||||
|
||||
/* more doc todo:
|
||||
* threads
|
||||
* gc
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package netscape.javascript;
|
||||
|
||||
import java.applet.Applet;
|
||||
|
||||
/**
|
||||
* JSObject allows Java to manipulate objects that are
|
||||
* defined in JavaScript.
|
||||
* Values passed from Java to JavaScript are converted as
|
||||
* follows:<ul>
|
||||
* <li>JSObject is converted to the original JavaScript object
|
||||
* <li>Any other Java object is converted to a JavaScript wrapper,
|
||||
* which can be used to access methods and fields of the java object.
|
||||
* Converting this wrapper to a string will call the toString method
|
||||
* on the original object, converting to a number will call the
|
||||
* floatValue method if possible and fail otherwise. Converting
|
||||
* to a boolean will try to call the booleanValue method in the
|
||||
* same way.
|
||||
* <li>Java arrays are wrapped with a JavaScript object that understands
|
||||
* array.length and array[index]
|
||||
* <li>A Java boolean is converted to a JavaScript boolean
|
||||
* <li>Java byte, char, short, int, long, float, and double are converted
|
||||
* to JavaScript numbers
|
||||
* </ul>
|
||||
* Values passed from JavaScript to Java are converted as follows:<ul>
|
||||
* <li>objects which are wrappers around java objects are unwrapped
|
||||
* <li>other objects are wrapped with a JSObject
|
||||
* <li>strings, numbers and booleans are converted to String, Float,
|
||||
* and Boolean objects respectively
|
||||
* </ul>
|
||||
* This means that all JavaScript values show up as some kind
|
||||
* of java.lang.Object in Java. In order to make much use of them,
|
||||
* you will have to cast them to the appropriate subclass of Object,
|
||||
* e.g. <code>(String) window.getMember("name");</code> or
|
||||
* <code>(JSObject) window.getMember("document");</code>.
|
||||
*/
|
||||
public final class JSObject {
|
||||
/* the internal object data */
|
||||
private int internal;
|
||||
|
||||
/**
|
||||
* initialize
|
||||
*/
|
||||
private static native void initClass();
|
||||
static {
|
||||
// On MRJ, this property won't exist, because the library is preloaded.
|
||||
String liveConnectLibrary = System.getProperty("netscape.jsj.dll", null);
|
||||
if (liveConnectLibrary != null) {
|
||||
System.loadLibrary(liveConnectLibrary);
|
||||
initClass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* it is illegal to construct a JSObject manually
|
||||
*/
|
||||
private JSObject(int jsobj_addr) {
|
||||
internal = jsobj_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a named member of a JavaScript object.
|
||||
* Equivalent to "this.<i>name</i>" in JavaScript.
|
||||
*/
|
||||
public native Object getMember(String name);
|
||||
|
||||
/**
|
||||
* Retrieves an indexed member of a JavaScript object.
|
||||
* Equivalent to "this[<i>index</i>]" in JavaScript.
|
||||
*/
|
||||
// public Object getMember(int index) { return getSlot(index); }
|
||||
public native Object getSlot(int index);
|
||||
|
||||
/**
|
||||
* Sets a named member of a JavaScript object.
|
||||
* Equivalent to "this.<i>name</i> = <i>value</i>" in JavaScript.
|
||||
*/
|
||||
public native void setMember(String name, Object value);
|
||||
|
||||
/**
|
||||
* Sets an indexed member of a JavaScript object.
|
||||
* Equivalent to "this[<i>index</i>] = <i>value</i>" in JavaScript.
|
||||
*/
|
||||
// public void setMember(int index, Object value) {
|
||||
// setSlot(index, value);
|
||||
// }
|
||||
public native void setSlot(int index, Object value);
|
||||
|
||||
/**
|
||||
* Removes a named member of a JavaScript object.
|
||||
*/
|
||||
public native void removeMember(String name);
|
||||
|
||||
/**
|
||||
* Calls a JavaScript method.
|
||||
* Equivalent to "this.<i>methodName</i>(<i>args</i>[0], <i>args</i>[1], ...)" in JavaScript.
|
||||
*/
|
||||
public native Object call(String methodName, Object args[]);
|
||||
|
||||
/**
|
||||
* Evaluates a JavaScript expression. The expression is a string
|
||||
* of JavaScript source code which will be evaluated in the context
|
||||
* given by "this".
|
||||
*/
|
||||
public native Object eval(String s);
|
||||
|
||||
/**
|
||||
* Converts a JSObject to a String.
|
||||
*/
|
||||
public native String toString();
|
||||
|
||||
// should use some sort of identifier rather than String
|
||||
// is "property" the right word?
|
||||
// native String[] listProperties();
|
||||
|
||||
|
||||
/**
|
||||
* get a JSObject for the window containing the given applet
|
||||
*/
|
||||
public static native JSObject getWindow(Applet applet);
|
||||
|
||||
/**
|
||||
* Finalization decrements the reference count on the corresponding
|
||||
* JavaScript object.
|
||||
*/
|
||||
protected native void finalize();
|
||||
|
||||
/**
|
||||
* Override java.lang.Object.equals() because identity is not preserved
|
||||
* with instances of JSObject.
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
JSObject jsobj;
|
||||
|
||||
if (!(obj instanceof JSObject))
|
||||
return false;
|
||||
jsobj = (JSObject)obj;
|
||||
return (internal == jsobj.internal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/* ** */
|
||||
/**
|
||||
* The JSProxy interface allows applets and plugins to
|
||||
* share javascript contexts.
|
||||
*/
|
||||
|
||||
package netscape.javascript;
|
||||
import java.applet.Applet;
|
||||
|
||||
public interface JSProxy {
|
||||
Object getMember(JSObject jso, String name);
|
||||
Object getSlot(JSObject jso, int index);
|
||||
void setMember(JSObject jso, String name, Object value);
|
||||
void setSlot(JSObject jso, int index, Object value);
|
||||
void removeMember(JSObject jso, String name);
|
||||
Object call(JSObject jso, String methodName, Object args[]);
|
||||
Object eval(JSObject jso, String s);
|
||||
String toString(JSObject jso);
|
||||
JSObject getWindow(Applet applet);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package netscape.javascript;
|
||||
|
||||
/**
|
||||
* Runs a JavaScript object with a run() method in a separate thread.
|
||||
*/
|
||||
public class JSRunnable implements Runnable {
|
||||
private JSObject runnable;
|
||||
|
||||
public JSRunnable(JSObject runnable) {
|
||||
this.runnable = runnable;
|
||||
synchronized(this) {
|
||||
new Thread(this).start();
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
runnable.call("run", null);
|
||||
synchronized(this) {
|
||||
notifyAll();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.err.println(t);
|
||||
t.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/* ** */
|
||||
|
||||
package netscape.javascript;
|
||||
import java.io.*;
|
||||
|
||||
public class JSUtil {
|
||||
|
||||
/* Return the stack trace of an exception or error as a String */
|
||||
public static String getStackTrace(Throwable t) {
|
||||
ByteArrayOutputStream captureStream;
|
||||
PrintStream p;
|
||||
|
||||
captureStream = new ByteArrayOutputStream();
|
||||
p = new PrintStream(captureStream);
|
||||
|
||||
t.printStackTrace(p);
|
||||
p.flush();
|
||||
|
||||
return captureStream.toString();
|
||||
}
|
||||
}
|
||||
876
mozilla/js/src/liveconnect/jsj.c
Normal file
876
mozilla/js/src/liveconnect/jsj.c
Normal file
@@ -0,0 +1,876 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the top-level initialization code and the implementation of the
|
||||
* public API.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsjava.h" /* LiveConnect external API */
|
||||
|
||||
/*
|
||||
* At certain times during initialization, there may be no JavaScript context
|
||||
* available to direct error reports to, in which case the error messages
|
||||
* are sent to this function. The caller is responsible for free'ing
|
||||
* the js_error_msg argument.
|
||||
*/
|
||||
static void
|
||||
report_java_initialization_error(JNIEnv *jEnv, const char *js_error_msg)
|
||||
{
|
||||
const char *error_msg, *java_error_msg;
|
||||
|
||||
java_error_msg = NULL;
|
||||
#if 0 /* This can never work here, because jsj_GetJavaErrorMessage relies on
|
||||
jlThrowable_toString which is set up by the initialization that calls
|
||||
this function. */
|
||||
if (jEnv) {
|
||||
java_error_msg = jsj_GetJavaErrorMessage(jEnv);
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
}
|
||||
#endif
|
||||
if (java_error_msg) {
|
||||
error_msg = PR_smprintf("initialization error: %s (%s)\n",
|
||||
js_error_msg, java_error_msg);
|
||||
free((void*)java_error_msg);
|
||||
} else {
|
||||
error_msg = PR_smprintf("initialization error: %s\n",
|
||||
js_error_msg);
|
||||
}
|
||||
|
||||
jsj_LogError(error_msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Opaque JVM handles to Java classes and methods required for Java reflection.
|
||||
* These are computed and cached during initialization.
|
||||
*/
|
||||
|
||||
jclass jlObject; /* java.lang.Object */
|
||||
jclass jlrMethod; /* java.lang.reflect.Method */
|
||||
jclass jlrField; /* java.lang.reflect.Field */
|
||||
jclass jlVoid; /* java.lang.Void */
|
||||
jclass jlrConstructor; /* java.lang.reflect.Constructor */
|
||||
jclass jlThrowable; /* java.lang.Throwable */
|
||||
jclass jlSystem; /* java.lang.System */
|
||||
jclass jlClass; /* java.lang.Class */
|
||||
jclass jlBoolean; /* java.lang.Boolean */
|
||||
jclass jlDouble; /* java.lang.Double */
|
||||
jclass jlString; /* java.lang.String */
|
||||
jclass njJSObject; /* netscape.javascript.JSObject */
|
||||
jclass njJSException; /* netscape.javascript.JSException */
|
||||
jclass njJSUtil; /* netscape.javascript.JSUtil */
|
||||
|
||||
jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */
|
||||
jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */
|
||||
jmethodID jlClass_getFields; /* java.lang.Class.getFields() */
|
||||
jmethodID jlClass_getName; /* java.lang.Class.getName() */
|
||||
jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */
|
||||
jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */
|
||||
jmethodID jlClass_isArray; /* java.lang.Class.isArray() */
|
||||
|
||||
jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */
|
||||
jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */
|
||||
jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */
|
||||
jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */
|
||||
|
||||
jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */
|
||||
jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */
|
||||
|
||||
jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */
|
||||
jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */
|
||||
jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */
|
||||
|
||||
jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */
|
||||
jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */
|
||||
jmethodID jlDouble_Double; /* java.lang.Double constructor */
|
||||
jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */
|
||||
|
||||
jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */
|
||||
jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */
|
||||
|
||||
jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */
|
||||
|
||||
jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */
|
||||
|
||||
jmethodID njJSException_JSException; /* netscape.javascript.JSexception constructor */
|
||||
jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */
|
||||
jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */
|
||||
jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */
|
||||
jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */
|
||||
jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */
|
||||
jfieldID njJSException_source; /* netscape.javascript.JSException.source */
|
||||
jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */
|
||||
|
||||
/* Obtain a reference to a Java class */
|
||||
#define LOAD_CLASS(qualified_name, class) \
|
||||
{ \
|
||||
jclass _##class = (*jEnv)->FindClass(jEnv, #qualified_name); \
|
||||
if (_##class == 0) { \
|
||||
(*jEnv)->ExceptionClear(jEnv); \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't load class " #qualified_name); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
class = (*jEnv)->NewGlobalRef(jEnv, _##class); \
|
||||
}
|
||||
|
||||
/* Obtain a methodID reference to a Java method or constructor */
|
||||
#define _LOAD_METHOD(qualified_class, method, mvar, signature, class, is_static)\
|
||||
if (is_static) { \
|
||||
class##_##mvar = \
|
||||
(*jEnv)->GetStaticMethodID(jEnv, class, #method, signature); \
|
||||
} else { \
|
||||
class##_##mvar = \
|
||||
(*jEnv)->GetMethodID(jEnv, class, #method, signature); \
|
||||
} \
|
||||
if (class##_##mvar == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't get mid for " #qualified_class "." #method "()"); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
/* Obtain a methodID reference to a Java instance method */
|
||||
#define LOAD_METHOD(qualified_class, method, signature, class) \
|
||||
_LOAD_METHOD(qualified_class, method, method, signature, class, JS_FALSE)
|
||||
|
||||
/* Obtain a methodID reference to a Java static method */
|
||||
#define LOAD_STATIC_METHOD(qualified_class, method, signature, class) \
|
||||
_LOAD_METHOD(qualified_class, method, method, signature, class, JS_TRUE)
|
||||
|
||||
/* Obtain a methodID reference to a Java constructor */
|
||||
#define LOAD_CONSTRUCTOR(qualified_class, method, signature, class) \
|
||||
_LOAD_METHOD(qualified_class,<init>, method, signature, class, JS_FALSE)
|
||||
|
||||
/* Obtain a fieldID reference to a Java instance or static field */
|
||||
#define _LOAD_FIELDID(qualified_class, field, signature, class, is_static) \
|
||||
if (is_static) { \
|
||||
class##_##field = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\
|
||||
} else { \
|
||||
class##_##field = (*jEnv)->GetFieldID(jEnv, class, #field, signature);\
|
||||
} \
|
||||
if (class##_##field == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't get fid for " #qualified_class "." #field); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
/* Obtain a fieldID reference to a Java instance field */
|
||||
#define LOAD_FIELDID(qualified_class, field, signature, class) \
|
||||
_LOAD_FIELDID(qualified_class, field, signature, class, JS_FALSE)
|
||||
|
||||
/* Obtain the value of a static field in a Java class */
|
||||
#define LOAD_FIELD_VAL(qualified_class, field, signature, class, type) \
|
||||
{ \
|
||||
jfieldID field_id; \
|
||||
field_id = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\
|
||||
if (field_id == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't get fid for " #qualified_class "." #field); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
class##_##field = \
|
||||
(*jEnv)->GetStatic##type##Field(jEnv, class, field_id); \
|
||||
if (class##_##field == 0) { \
|
||||
report_java_initialization_error(jEnv, \
|
||||
"Can't read static field " #qualified_class "." #field); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Obtain the value of a static field in a Java class, which is known to
|
||||
contain an object value. */
|
||||
#define LOAD_FIELD_OBJ(qualified_class, field, signature, class) \
|
||||
LOAD_FIELD_VAL(qualified_class, field, signature, class, Object); \
|
||||
class##_##field = (*jEnv)->NewGlobalRef(jEnv, class##_##field);
|
||||
|
||||
/*
|
||||
* Load the Java classes, and the method and field descriptors required for Java reflection.
|
||||
* Returns JS_TRUE on success, JS_FALSE on failure.
|
||||
*/
|
||||
static JSBool
|
||||
init_java_VM_reflection(JSJavaVM *jsjava_vm, JNIEnv *jEnv)
|
||||
{
|
||||
/* Load Java system classes and method, including java.lang.reflect classes */
|
||||
LOAD_CLASS(java/lang/Object, jlObject);
|
||||
LOAD_CLASS(java/lang/Class, jlClass);
|
||||
LOAD_CLASS(java/lang/reflect/Method, jlrMethod);
|
||||
LOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor);
|
||||
LOAD_CLASS(java/lang/reflect/Field, jlrField);
|
||||
LOAD_CLASS(java/lang/Throwable, jlThrowable);
|
||||
LOAD_CLASS(java/lang/System, jlSystem);
|
||||
LOAD_CLASS(java/lang/Boolean, jlBoolean);
|
||||
LOAD_CLASS(java/lang/Double, jlDouble);
|
||||
LOAD_CLASS(java/lang/String, jlString);
|
||||
LOAD_CLASS(java/lang/Void, jlVoid);
|
||||
|
||||
LOAD_METHOD(java.lang.Class, getMethods, "()[Ljava/lang/reflect/Method;",jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getConstructors, "()[Ljava/lang/reflect/Constructor;",jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getFields, "()[Ljava/lang/reflect/Field;", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getName, "()Ljava/lang/String;", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, isArray, "()Z", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getComponentType, "()Ljava/lang/Class;", jlClass);
|
||||
LOAD_METHOD(java.lang.Class, getModifiers, "()I", jlClass);
|
||||
|
||||
LOAD_METHOD(java.lang.reflect.Method, getName, "()Ljava/lang/String;", jlrMethod);
|
||||
LOAD_METHOD(java.lang.reflect.Method, getParameterTypes, "()[Ljava/lang/Class;", jlrMethod);
|
||||
LOAD_METHOD(java.lang.reflect.Method, getReturnType, "()Ljava/lang/Class;", jlrMethod);
|
||||
LOAD_METHOD(java.lang.reflect.Method, getModifiers, "()I", jlrMethod);
|
||||
|
||||
LOAD_METHOD(java.lang.reflect.Constructor, getParameterTypes, "()[Ljava/lang/Class;", jlrConstructor);
|
||||
LOAD_METHOD(java.lang.reflect.Constructor, getModifiers, "()I", jlrConstructor);
|
||||
|
||||
LOAD_METHOD(java.lang.reflect.Field, getName, "()Ljava/lang/String;", jlrField);
|
||||
LOAD_METHOD(java.lang.reflect.Field, getType, "()Ljava/lang/Class;", jlrField);
|
||||
LOAD_METHOD(java.lang.reflect.Field, getModifiers, "()I", jlrField);
|
||||
|
||||
LOAD_METHOD(java.lang.Throwable, toString, "()Ljava/lang/String;", jlThrowable);
|
||||
LOAD_METHOD(java.lang.Throwable, getMessage, "()Ljava/lang/String;", jlThrowable);
|
||||
|
||||
LOAD_METHOD(java.lang.Double, doubleValue, "()D", jlDouble);
|
||||
|
||||
LOAD_METHOD(java.lang.Boolean, booleanValue, "()Z", jlBoolean);
|
||||
|
||||
LOAD_STATIC_METHOD(java.lang.System, identityHashCode, "(Ljava/lang/Object;)I", jlSystem);
|
||||
|
||||
LOAD_CONSTRUCTOR(java.lang.Boolean, Boolean, "(Z)V", jlBoolean);
|
||||
LOAD_CONSTRUCTOR(java.lang.Double, Double, "(D)V", jlDouble);
|
||||
|
||||
LOAD_FIELD_OBJ(java.lang.Void, TYPE, "Ljava/lang/Class;", jlVoid);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if XP_MAC
|
||||
|
||||
/**
|
||||
* Workaround for the fact that MRJ loads a different instance of the shared library.
|
||||
*/
|
||||
|
||||
#include "netscape_javascript_JSObject.h"
|
||||
|
||||
static JSObject_RegisterNativeMethods(JNIEnv* jEnv)
|
||||
{
|
||||
// Manually load the required native methods.
|
||||
static JNINativeMethod nativeMethods[] = {
|
||||
"initClass", "()V", (void*)&Java_netscape_javascript_JSObject_initClass,
|
||||
"getMember", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getMember,
|
||||
"getSlot", "(I)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getSlot,
|
||||
"setMember", "(Ljava/lang/String;Ljava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setMember,
|
||||
"setSlot", "(ILjava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setSlot,
|
||||
"removeMember", "(Ljava/lang/String;)V", (void*)&Java_netscape_javascript_JSObject_removeMember,
|
||||
"call", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_call,
|
||||
"eval", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_eval,
|
||||
|
||||
"toString", "()Ljava/lang/String;", (void*)&Java_netscape_javascript_JSObject_toString,
|
||||
"getWindow", "(Ljava/applet/Applet;)Lnetscape/javascript/JSObject;", (void*)&Java_netscape_javascript_JSObject_getWindow,
|
||||
"finalize", "()V", (void*)&Java_netscape_javascript_JSObject_finalize,
|
||||
/* "equals", "(Ljava/lang/Object;)Z", (void*)&Java_netscape_javascript_JSObject_equals */
|
||||
};
|
||||
(*jEnv)->RegisterNatives(jEnv, njJSObject, nativeMethods, sizeof(nativeMethods) / sizeof(JNINativeMethod));
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
report_java_initialization_error(jEnv, "Couldn't initialize JSObject native methods.");
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
}
|
||||
/* call the initClass method, since we nailed the static initializer for testing. */
|
||||
Java_netscape_javascript_JSObject_initClass(jEnv, njJSObject);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Load Netscape-specific Java extension classes, methods, and fields */
|
||||
static JSBool
|
||||
init_netscape_java_classes(JSJavaVM *jsjava_vm, JNIEnv *jEnv)
|
||||
{
|
||||
LOAD_CLASS(netscape/javascript/JSObject, njJSObject);
|
||||
LOAD_CLASS(netscape/javascript/JSException, njJSException);
|
||||
LOAD_CLASS(netscape/javascript/JSUtil, njJSUtil);
|
||||
|
||||
#if XP_MAC
|
||||
JSObject_RegisterNativeMethods(jEnv);
|
||||
#endif
|
||||
|
||||
LOAD_CONSTRUCTOR(netscape.javascript.JSObject,
|
||||
JSObject, "(I)V", njJSObject);
|
||||
LOAD_CONSTRUCTOR(netscape.javascript.JSException,
|
||||
JSException, "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V",
|
||||
njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSObject,
|
||||
internal, "I", njJSObject);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
lineno, "I", njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
tokenIndex, "I", njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
source, "Ljava/lang/String;", njJSException);
|
||||
LOAD_FIELDID(netscape.javascript.JSException,
|
||||
filename, "Ljava/lang/String;", njJSException);
|
||||
|
||||
LOAD_STATIC_METHOD(netscape.javascript.JSUtil,
|
||||
getStackTrace, "(Ljava/lang/Throwable;)Ljava/lang/String;",
|
||||
njJSUtil);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSJavaVM *jsjava_vm_list = NULL;
|
||||
|
||||
/*
|
||||
* Called once per Java VM, this function initializes the classes, fields, and
|
||||
* methods required for Java reflection. If java_vm is NULL, a new Java VM is
|
||||
* created, using the provided classpath in addition to any default classpath.
|
||||
* The classpath argument is ignored, however, if java_vm_arg is non-NULL.
|
||||
*/
|
||||
JSJavaVM *
|
||||
JSJ_ConnectToJavaVM(SystemJavaVM *java_vm_arg, void* initargs)
|
||||
{
|
||||
SystemJavaVM* java_vm;
|
||||
JSJavaVM *jsjava_vm;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
PR_ASSERT(JSJ_callbacks);
|
||||
PR_ASSERT(JSJ_callbacks->attach_current_thread);
|
||||
PR_ASSERT(JSJ_callbacks->detach_current_thread);
|
||||
PR_ASSERT(JSJ_callbacks->get_java_vm);
|
||||
|
||||
jsjava_vm = (JSJavaVM*)malloc(sizeof(JSJavaVM));
|
||||
if (!jsjava_vm)
|
||||
return NULL;
|
||||
memset(jsjava_vm, 0, sizeof(JSJavaVM));
|
||||
|
||||
java_vm = java_vm_arg;
|
||||
|
||||
/* If a Java VM was passed in, try to attach to it on the current thread. */
|
||||
if (java_vm) {
|
||||
jEnv = JSJ_callbacks->attach_current_thread(java_vm);
|
||||
if (jEnv == NULL) {
|
||||
jsj_LogError("Failed to attach to Java VM thread\n");
|
||||
free(jsjava_vm);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PRBool ok;
|
||||
PR_ASSERT(JSJ_callbacks->create_java_vm);
|
||||
PR_ASSERT(JSJ_callbacks->destroy_java_vm);
|
||||
|
||||
ok = JSJ_callbacks->create_java_vm(&java_vm, &jEnv, initargs);
|
||||
if (!ok || java_vm == NULL) {
|
||||
jsj_LogError("Failed to create Java VM\n");
|
||||
free(jsjava_vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remember that we created the VM so that we know to destroy it later */
|
||||
jsjava_vm->jsj_created_java_vm = JS_TRUE;
|
||||
}
|
||||
|
||||
jsjava_vm->java_vm = java_vm;
|
||||
jsjava_vm->main_thread_env = jEnv;
|
||||
|
||||
/* Load the Java classes, and the method and field descriptors required for
|
||||
Java reflection. */
|
||||
if (!init_java_VM_reflection(jsjava_vm, jEnv)) {
|
||||
JSJ_DisconnectFromJavaVM(jsjava_vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* JVM initialization for netscape.javascript.JSObject is performed
|
||||
* independently of the other classes that are initialized in
|
||||
* init_java_VM_reflection, because we allow it to fail. In the case
|
||||
* of failure, LiveConnect is still operative, but only when calling
|
||||
* from JS to Java and not vice-versa.
|
||||
*/
|
||||
init_netscape_java_classes(jsjava_vm, jEnv);
|
||||
|
||||
/* Put this VM on the list of all created VMs */
|
||||
jsjava_vm->next = jsjava_vm_list;
|
||||
jsjava_vm_list = jsjava_vm;
|
||||
|
||||
return jsjava_vm;
|
||||
}
|
||||
|
||||
JSJCallbacks *JSJ_callbacks = NULL;
|
||||
|
||||
/* Called once to set up callbacks for all instances of LiveConnect */
|
||||
void
|
||||
JSJ_Init(JSJCallbacks *callbacks)
|
||||
{
|
||||
PR_ASSERT(callbacks);
|
||||
JSJ_callbacks = callbacks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
* reflection and by defining JavaPackage objects for the default Java packages
|
||||
* as properties of global_obj. Additional packages may be pre-defined by
|
||||
* setting the predefined_packages argument. (Pre-defining a Java package at
|
||||
* initialization time is not necessary, but it will make package lookup faster
|
||||
* and, more importantly, will avoid unnecessary network accesses if classes
|
||||
* are being loaded over the network.)
|
||||
*/
|
||||
JSBool
|
||||
JSJ_InitJSContext(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *predefined_packages)
|
||||
{
|
||||
/* Initialize the JavaScript classes used for reflection */
|
||||
if (!jsj_init_JavaObject(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
/* if (!jsj_init_JavaMember(cx, global_obj))
|
||||
return JS_FALSE; */
|
||||
|
||||
if (!jsj_init_JavaPackage(cx, global_obj, predefined_packages))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!jsj_init_JavaClass(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!jsj_init_JavaArray(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!jsj_init_JavaMember(cx, global_obj))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Eliminate a reference to a Java class */
|
||||
#define UNLOAD_CLASS(qualified_name, class) \
|
||||
if (class) { \
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, class); \
|
||||
class = NULL; \
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine severs the connection to a Java VM, freeing all related resources.
|
||||
* It shouldn't be called until the global scope has been cleared in all related
|
||||
* JSContexts (so that all LiveConnect objects are finalized) and a JavaScript
|
||||
* GC is performed. Otherwise, accessed to free'ed memory could result.
|
||||
*/
|
||||
void
|
||||
JSJ_DisconnectFromJavaVM(JSJavaVM *jsjava_vm)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
SystemJavaVM *java_vm;
|
||||
JSJavaVM *j, **jp;
|
||||
|
||||
java_vm = jsjava_vm->java_vm;
|
||||
jEnv = jsjava_vm->main_thread_env;
|
||||
|
||||
/* Drop all references to Java objects and classes */
|
||||
jsj_DiscardJavaObjReflections(jEnv);
|
||||
jsj_DiscardJavaClassReflections(jEnv);
|
||||
|
||||
if (jsjava_vm->jsj_created_java_vm) {
|
||||
(void)JSJ_callbacks->destroy_java_vm(java_vm, jEnv);
|
||||
} else {
|
||||
UNLOAD_CLASS(java/lang/Object, jlObject);
|
||||
UNLOAD_CLASS(java/lang/Class, jlClass);
|
||||
UNLOAD_CLASS(java/lang/reflect/Method, jlrMethod);
|
||||
UNLOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor);
|
||||
UNLOAD_CLASS(java/lang/reflect/Field, jlrField);
|
||||
UNLOAD_CLASS(java/lang/Throwable, jlThrowable);
|
||||
UNLOAD_CLASS(java/lang/System, jlSystem);
|
||||
UNLOAD_CLASS(java/lang/Boolean, jlBoolean);
|
||||
UNLOAD_CLASS(java/lang/Double, jlDouble);
|
||||
UNLOAD_CLASS(java/lang/String, jlString);
|
||||
UNLOAD_CLASS(java/lang/Void, jlVoid);
|
||||
UNLOAD_CLASS(netscape/javascript/JSObject, njJSObject);
|
||||
UNLOAD_CLASS(netscape/javascript/JSException, njJSException);
|
||||
UNLOAD_CLASS(netscape/javascript/JSUtil, njJSUtil);
|
||||
}
|
||||
|
||||
|
||||
/* Remove this VM from the list of all JSJavaVM objects. */
|
||||
for (jp = &jsjava_vm_list; (j = *jp) != NULL; jp = &j->next) {
|
||||
if (j == jsjava_vm) {
|
||||
*jp = jsjava_vm->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PR_ASSERT(j);
|
||||
|
||||
free(jsjava_vm);
|
||||
}
|
||||
|
||||
static JSJavaThreadState *thread_list = NULL;
|
||||
|
||||
static JSJavaThreadState *
|
||||
new_jsjava_thread_state(JSJavaVM *jsjava_vm, const char *thread_name, JNIEnv *jEnv)
|
||||
{
|
||||
JSJavaThreadState *jsj_env;
|
||||
|
||||
jsj_env = (JSJavaThreadState *)malloc(sizeof(JSJavaThreadState));
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
memset(jsj_env, 0, sizeof(JSJavaThreadState));
|
||||
|
||||
jsj_env->jEnv = jEnv;
|
||||
jsj_env->jsjava_vm = jsjava_vm;
|
||||
if (thread_name)
|
||||
jsj_env->name = strdup(thread_name);
|
||||
|
||||
/* THREADSAFETY - need to protect against races */
|
||||
jsj_env->next = thread_list;
|
||||
thread_list = jsj_env;
|
||||
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
static JSJavaThreadState *
|
||||
find_jsjava_thread(JNIEnv *jEnv)
|
||||
{
|
||||
JSJavaThreadState *e, **p, *jsj_env;
|
||||
jsj_env = NULL;
|
||||
|
||||
/* THREADSAFETY - need to protect against races in manipulating the thread list */
|
||||
|
||||
/* Search for the thread state among the list of all created
|
||||
LiveConnect threads */
|
||||
for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) {
|
||||
if (e->jEnv == jEnv) {
|
||||
jsj_env = e;
|
||||
*p = jsj_env->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move a found thread to head of list for faster search next time. */
|
||||
if (jsj_env)
|
||||
thread_list = jsj_env;
|
||||
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJavaThreadState *)
|
||||
JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *name, JNIEnv **java_envp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
SystemJavaVM *java_vm;
|
||||
JSJavaThreadState *jsj_env;
|
||||
|
||||
/* Try to attach a Java thread to the current native thread */
|
||||
java_vm = jsjava_vm->java_vm;
|
||||
jEnv = JSJ_callbacks->attach_current_thread(java_vm);
|
||||
if (jEnv == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If we found an existing thread state, just return it. */
|
||||
jsj_env = find_jsjava_thread(jEnv);
|
||||
if (jsj_env)
|
||||
return jsj_env;
|
||||
|
||||
/* Create a new wrapper around the thread/VM state */
|
||||
jsj_env = new_jsjava_thread_state(jsjava_vm, name, jEnv);
|
||||
|
||||
if (java_envp)
|
||||
*java_envp = jEnv;
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
static JSJavaVM *
|
||||
map_java_vm_to_jsjava_vm(SystemJavaVM *java_vm)
|
||||
{
|
||||
JSJavaVM *v;
|
||||
for (v = jsjava_vm_list; v; v = v->next) {
|
||||
if (v->java_vm == java_vm)
|
||||
return v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unfortunately, there's no standard means to associate any private data with
|
||||
* a JNI thread environment, so we need to use the Java environment pointer as
|
||||
* the key in a lookup table that maps it to a JSJavaThreadState structure,
|
||||
* where we store all our per-thread private data. If no existing thread state
|
||||
* is found, a new one is created.
|
||||
*
|
||||
* If an error occurs, returns NULL and sets the errp argument to an error
|
||||
* message, which the caller is responsible for free'ing.
|
||||
*/
|
||||
JSJavaThreadState *
|
||||
jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp)
|
||||
{
|
||||
JSJavaThreadState *jsj_env;
|
||||
SystemJavaVM *java_vm;
|
||||
JSJavaVM *jsjava_vm;
|
||||
|
||||
/* If we found an existing thread state, just return it. */
|
||||
jsj_env = find_jsjava_thread(jEnv);
|
||||
if (jsj_env)
|
||||
return jsj_env;
|
||||
|
||||
/* No one set up a LiveConnect thread state for a given Java thread.
|
||||
Invoke the callback to create one on-the-fly. */
|
||||
|
||||
/* First, figure out which Java VM is calling us */
|
||||
java_vm = JSJ_callbacks->get_java_vm(jEnv);
|
||||
if (jsjava_vm == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Get our private JavaVM data */
|
||||
jsjava_vm = map_java_vm_to_jsjava_vm(java_vm);
|
||||
if (!jsjava_vm) {
|
||||
*errp = PR_smprintf("Total weirdness: No JSJavaVM wrapper ever created "
|
||||
"for JavaVM 0x%08x", java_vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsj_env = new_jsjava_thread_state(jsjava_vm, NULL, jEnv);
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to specify a particular JSContext as *the* JavaScript
|
||||
* execution environment to be used when LiveConnect is accessed from the given
|
||||
* Java thread, i.e. by using one of the methods of netscape.javascript.JSObject.
|
||||
* (There can only be one such JS context for a given Java thread. To
|
||||
* multiplex JSContexts among a single thread, this function must be called
|
||||
* before Java is invoked on that thread.) The return value is the previous
|
||||
* context associated with the given Java thread.
|
||||
*/
|
||||
PR_IMPLEMENT(JSContext *)
|
||||
JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env)
|
||||
{
|
||||
JSContext *old_context;
|
||||
old_context = jsj_env->cx;
|
||||
jsj_env->cx = cx;
|
||||
return old_context;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env)
|
||||
{
|
||||
SystemJavaVM *java_vm;
|
||||
JNIEnv* jEnv;
|
||||
JSJavaThreadState *e, **p;
|
||||
|
||||
/* Disassociate the current native thread from its corresponding Java thread */
|
||||
java_vm = jsj_env->jsjava_vm->java_vm;
|
||||
jEnv = jsj_env->jEnv;
|
||||
if (!JSJ_callbacks->detach_current_thread(java_vm, jEnv))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Destroy the LiveConnect execution environment passed in */
|
||||
jsj_ClearPendingJSErrors(jsj_env);
|
||||
|
||||
/* THREADSAFETY - need to protect against races */
|
||||
for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) {
|
||||
if (e == jsj_env) {
|
||||
*p = jsj_env->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(jsj_env);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, vp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifndef MOZILLA_CLIENT
|
||||
|
||||
/* The convenience functions below present a complete, but simplified
|
||||
LiveConnect API which is designed to handle the special case of a single
|
||||
Java-VM, single-threaded operation, and use of only one JSContext. */
|
||||
|
||||
/* We can get away with global variables in our single-threaded,
|
||||
single-JSContext case. */
|
||||
static JSJavaVM * the_jsj_vm = NULL;
|
||||
static JSContext * the_cx = NULL;
|
||||
static JSJavaThreadState * the_jsj_thread = NULL;
|
||||
static JSObject * the_global_js_obj = NULL;
|
||||
|
||||
/* Trivial implementation of callback function */
|
||||
static JSJavaThreadState *
|
||||
default_map_js_context_to_jsj_thread(JSContext *cx, char **errp)
|
||||
{
|
||||
return the_jsj_thread;
|
||||
}
|
||||
|
||||
/* Trivial implementation of callback function */
|
||||
static JSContext *
|
||||
default_map_jsj_thread_to_js_context(JSJavaThreadState *jsj_env, JNIEnv *jEnv, char **errp)
|
||||
{
|
||||
return the_cx;
|
||||
}
|
||||
|
||||
/* Trivial implementation of callback function */
|
||||
static JSObject *
|
||||
default_map_java_object_to_js_object(JNIEnv *jEnv, jobject hint, char **errp)
|
||||
{
|
||||
return the_global_js_obj;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
default_create_java_vm(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs)
|
||||
{
|
||||
jint err;
|
||||
const char* user_classpath = (const char*)initargs;
|
||||
|
||||
/* No Java VM supplied, so create our own */
|
||||
JDK1_1InitArgs vm_args;
|
||||
|
||||
/* Magic constant indicates JRE version 1.1 */
|
||||
vm_args.version = 0x00010001;
|
||||
JNI_GetDefaultJavaVMInitArgs(&vm_args);
|
||||
|
||||
/* Prepend the classpath argument to the default JVM classpath */
|
||||
if (user_classpath) {
|
||||
#ifdef XP_UNIX
|
||||
const char *full_classpath = PR_smprintf("%s:%s", user_classpath, vm_args.classpath);
|
||||
#else
|
||||
const char *full_classpath = PR_smprintf("%s;%s", user_classpath, vm_args.classpath);
|
||||
#endif
|
||||
if (!full_classpath) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
vm_args.classpath = (char*)full_classpath;
|
||||
}
|
||||
|
||||
err = JNI_CreateJavaVM((JavaVM**)jvm, initialEnv, &vm_args);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
default_destroy_java_vm(SystemJavaVM* jvm, JNIEnv* initialEnv)
|
||||
{
|
||||
JavaVM* java_vm = (JavaVM*)jvm;
|
||||
jint err = (*java_vm)->DestroyJavaVM(java_vm);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
static JNIEnv* PR_CALLBACK
|
||||
default_attach_current_thread(SystemJavaVM* jvm)
|
||||
{
|
||||
JavaVM* java_vm = (JavaVM*)jvm;
|
||||
JNIEnv* env = NULL;
|
||||
jint err = (*java_vm)->AttachCurrentThread(java_vm, &env, NULL);
|
||||
return env;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
default_detach_current_thread(SystemJavaVM* jvm, JNIEnv* env)
|
||||
{
|
||||
JavaVM* java_vm = (JavaVM*)jvm;
|
||||
/* assert that env is the JNIEnv of the current thread */
|
||||
jint err = (*java_vm)->DetachCurrentThread(java_vm);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
static SystemJavaVM* PR_CALLBACK
|
||||
default_get_java_vm(JNIEnv* env)
|
||||
{
|
||||
JavaVM* java_vm = NULL;
|
||||
jint err = (*env)->GetJavaVM(env, &java_vm);
|
||||
return (SystemJavaVM*)java_vm;
|
||||
}
|
||||
|
||||
/* Trivial implementations of callback functions */
|
||||
JSJCallbacks jsj_default_callbacks = {
|
||||
default_map_jsj_thread_to_js_context,
|
||||
default_map_js_context_to_jsj_thread,
|
||||
default_map_java_object_to_js_object,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
default_create_java_vm,
|
||||
default_destroy_java_vm,
|
||||
default_attach_current_thread,
|
||||
default_detach_current_thread,
|
||||
default_get_java_vm
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
* reflection and by defining JavaPackage objects for the default Java packages
|
||||
* as properties of global_obj. If java_vm is NULL, a new Java VM is
|
||||
* created, using the provided classpath in addition to any default classpath.
|
||||
* The classpath argument is ignored, however, if java_vm is non-NULL.
|
||||
*/
|
||||
JSBool
|
||||
JSJ_SimpleInit(JSContext *cx, JSObject *global_obj, SystemJavaVM *java_vm, const char *classpath)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
|
||||
PR_ASSERT(!the_jsj_vm);
|
||||
the_jsj_vm = JSJ_ConnectToJavaVM(java_vm, (void*)classpath);
|
||||
if (!the_jsj_vm)
|
||||
return JS_FALSE;
|
||||
|
||||
JSJ_Init(&jsj_default_callbacks);
|
||||
|
||||
if (!JSJ_InitJSContext(cx, global_obj, NULL))
|
||||
goto error;
|
||||
the_cx = cx;
|
||||
the_global_js_obj = global_obj;
|
||||
|
||||
the_jsj_thread = JSJ_AttachCurrentThreadToJava(the_jsj_vm, "main thread", &jEnv);
|
||||
if (!the_jsj_thread)
|
||||
goto error;
|
||||
JSJ_SetDefaultJSContextForJavaThread(cx, the_jsj_thread);
|
||||
return JS_TRUE;
|
||||
|
||||
error:
|
||||
JSJ_SimpleShutdown();
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up all LiveConnect resources. Destroy the Java VM if it was
|
||||
* created by LiveConnect.
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_SimpleShutdown()
|
||||
{
|
||||
PR_ASSERT(the_jsj_vm);
|
||||
JSJ_DisconnectFromJavaVM(the_jsj_vm);
|
||||
the_jsj_vm = NULL;
|
||||
the_cx = NULL;
|
||||
the_global_js_obj = NULL;
|
||||
the_jsj_thread = NULL;
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_CLIENT */
|
||||
76
mozilla/js/src/liveconnect/jsj1640.rc
Normal file
76
mozilla/js/src/liveconnect/jsj1640.rc
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
// Version stamp for this .DLL
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ver.h>
|
||||
|
||||
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
|
||||
FILEVERSION 4 // major, minor, release (alpha 1), build #
|
||||
|
||||
PRODUCTVERSION 4
|
||||
|
||||
FILEFLAGSMASK 0
|
||||
|
||||
FILEFLAGS 0 // final version
|
||||
|
||||
FILEOS VOS_DOS_WINDOWS16
|
||||
|
||||
FILETYPE VFT_DLL
|
||||
|
||||
FILESUBTYPE 0 // not used
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "StringFileInfo"
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
|
||||
|
||||
BEGIN
|
||||
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
|
||||
VALUE "FileDescription", "Netscape 16-bit JavaScript-Java Module\0"
|
||||
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
|
||||
VALUE "InternalName", "JSJ1640\0"
|
||||
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
|
||||
VALUE "OriginalFilename","JSJ1640.DLL\0"
|
||||
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
1243
mozilla/js/src/liveconnect/jsj_JSObject.c
Normal file
1243
mozilla/js/src/liveconnect/jsj_JSObject.c
Normal file
File diff suppressed because it is too large
Load Diff
403
mozilla/js/src/liveconnect/jsj_JavaArray.c
Normal file
403
mozilla/js/src/liveconnect/jsj_JavaArray.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the definition of the JavaScript JavaArray class.
|
||||
* Instances of JavaArray are used to reflect Java arrays.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/* Shorthands for ASCII (7-bit) decimal and hex conversion. */
|
||||
#define JS7_ISDEC(c) (((c) >= '0') && ((c) <= '9'))
|
||||
#define JS7_UNDEC(c) ((c) - '0')
|
||||
|
||||
/*
|
||||
* Convert any jsval v to an integer jsval if ToString(v)
|
||||
* contains a base-10 integer that fits into 31 bits.
|
||||
* Otherwise return v.
|
||||
*/
|
||||
static jsval
|
||||
try_convert_to_jsint(JSContext *cx, jsval idval)
|
||||
{
|
||||
const jschar *cp;
|
||||
JSString *jsstr;
|
||||
|
||||
jsstr = JS_ValueToString(cx, idval);
|
||||
if (!jsstr)
|
||||
return idval;
|
||||
|
||||
cp = JS_GetStringChars(jsstr);
|
||||
if (JS7_ISDEC(*cp)) {
|
||||
jsuint index = JS7_UNDEC(*cp++);
|
||||
jsuint oldIndex = 0;
|
||||
jsuint c = 0;
|
||||
if (index != 0) {
|
||||
while (JS7_ISDEC(*cp)) {
|
||||
oldIndex = index;
|
||||
c = JS7_UNDEC(*cp);
|
||||
index = 10*index + c;
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
if (*cp == 0 &&
|
||||
(oldIndex < (JSVAL_INT_MAX / 10) ||
|
||||
(oldIndex == (JSVAL_INT_MAX / 10) && c < (JSVAL_INT_MAX % 10)))) {
|
||||
return INT_TO_JSVAL(index);
|
||||
}
|
||||
}
|
||||
return idval;
|
||||
}
|
||||
|
||||
|
||||
static JSBool
|
||||
access_java_array_element(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JSObject *obj,
|
||||
jsid id,
|
||||
jsval *vp,
|
||||
JSBool do_assignment)
|
||||
{
|
||||
jsval idval;
|
||||
jarray java_array;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
jsize array_length, index;
|
||||
JavaSignature *array_component_signature;
|
||||
|
||||
/* printf("In JavaArray_getProperty\n"); */
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper) {
|
||||
const char *property_name;
|
||||
if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) &&
|
||||
(property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) {
|
||||
if (!strcmp(property_name, "constructor")) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
JS_ReportError(cx, "illegal operation on JavaArray prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
java_array = java_wrapper->java_obj;
|
||||
|
||||
PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_ARRAY);
|
||||
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
|
||||
if (!JSVAL_IS_INT(idval))
|
||||
idval = try_convert_to_jsint(cx, idval);
|
||||
|
||||
if (!JSVAL_IS_INT(idval)) {
|
||||
/*
|
||||
* Usually, properties of JavaArray objects are indexed by integers, but
|
||||
* Java arrays also inherit all the methods of java.lang.Object, so a
|
||||
* string-valued property is also possible.
|
||||
*/
|
||||
if (JSVAL_IS_STRING(idval)) {
|
||||
const char *member_name;
|
||||
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
|
||||
if (do_assignment) {
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
|
||||
JS_ReportError(cx, "Attempt to write to invalid Java array "
|
||||
"element \"%s\"", member_name);
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(member_name, "length")) {
|
||||
array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array);
|
||||
if (array_length < 0)
|
||||
return JS_FALSE;
|
||||
if (vp)
|
||||
*vp = INT_TO_JSVAL(array_length);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Check to see if we're reflecting a Java array method */
|
||||
return JavaObject_getPropertyById(cx, obj, id, vp);
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "invalid Java array index expression");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
index = JSVAL_TO_INT(idval);
|
||||
|
||||
#if 0
|
||||
array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array);
|
||||
if (array_length < 0)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Just let Java throw an exception instead of checking array bounds here */
|
||||
if (index < 0 || index >= array_length) {
|
||||
JS_ReportError(cx, "Java array index %d out of range", index);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
array_component_signature = class_descriptor->array_component_signature;
|
||||
|
||||
if (!vp)
|
||||
return JS_TRUE;
|
||||
|
||||
if (do_assignment) {
|
||||
return jsj_SetJavaArrayElement(cx, jEnv, java_array, index,
|
||||
array_component_signature, *vp);
|
||||
} else {
|
||||
return jsj_GetJavaArrayElement(cx, jEnv, java_array, index,
|
||||
array_component_signature, vp);
|
||||
}
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaArray_getPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
return access_java_array_element(cx, jEnv, obj, id, vp, JS_FALSE);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaArray_setPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
return access_java_array_element(cx, jEnv, obj, id, vp, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
return access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot define a new property in a JavaArray");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_setAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Silently ignore all setAttribute attempts */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
*vp = JSVAL_FALSE;
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
JS_ReportError(cx, "Properties of JavaArray objects may not be deleted");
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/* Attempts to delete permanent properties are silently ignored
|
||||
by ECMAScript. */
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
/* printf("In JavaArray_defaultValue()\n"); */
|
||||
return JavaObject_convert(cx, obj, JSTYPE_STRING, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JNIEnv *jEnv;
|
||||
jsize array_length, index;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
/* Check for prototype object */
|
||||
if (!java_wrapper) {
|
||||
*statep = JSVAL_NULL;
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
array_length = jsj_GetJavaArrayLength(cx, jEnv, java_wrapper->java_obj);
|
||||
if (array_length < 0)
|
||||
return JS_FALSE;
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
*statep = INT_TO_JSVAL(0);
|
||||
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(array_length);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
index = JSVAL_TO_INT(*statep);
|
||||
if (index < array_length) {
|
||||
JS_ValueToId(cx, INT_TO_JSVAL(index), idp);
|
||||
index++;
|
||||
*statep = INT_TO_JSVAL(index);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through ... */
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
*statep = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaArray_checkAccess(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSACC_WATCH:
|
||||
JS_ReportError(cx, "Cannot place watchpoints on JavaArray object properties");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSACC_IMPORT:
|
||||
JS_ReportError(cx, "Cannot export a JavaArray object's properties");
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
JSObjectOps JavaArray_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
NULL, /* newObjectMap */
|
||||
NULL, /* destroyObjectMap */
|
||||
JavaArray_lookupProperty,
|
||||
JavaArray_defineProperty,
|
||||
JavaArray_getPropertyById, /* getProperty */
|
||||
JavaArray_setPropertyById, /* setProperty */
|
||||
JavaArray_getAttributes,
|
||||
JavaArray_setAttributes,
|
||||
JavaArray_deleteProperty,
|
||||
JavaArray_defaultValue,
|
||||
JavaArray_newEnumerate,
|
||||
JavaArray_checkAccess,
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
NULL, /* thisObject */
|
||||
NULL, /* dropProperty */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL /* hasInstance */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
JavaArray_getObjectOps(JSContext *cx, JSClass *clazz)
|
||||
{
|
||||
return &JavaArray_ops;
|
||||
}
|
||||
|
||||
JSClass JavaArray_class = {
|
||||
"JavaArray", JSCLASS_HAS_PRIVATE,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, JavaObject_convert, JavaObject_finalize,
|
||||
JavaArray_getObjectOps,
|
||||
};
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
|
||||
/* Initialize the JS JavaArray class */
|
||||
JSBool
|
||||
jsj_init_JavaArray(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
JavaArray_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
JavaArray_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
|
||||
if (!JS_InitClass(cx, global_obj,
|
||||
0, &JavaArray_class, 0, 0,
|
||||
0, 0, 0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
586
mozilla/js/src/liveconnect/jsj_JavaClass.c
Normal file
586
mozilla/js/src/liveconnect/jsj_JavaClass.c
Normal file
@@ -0,0 +1,586 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of JS's JavaClass class.
|
||||
*
|
||||
* A JavaClass is JavaScript's representation of a Java class.
|
||||
* Its parent JS object is always a JavaPackage object. A JavaClass is not an
|
||||
* exact reflection of Java's corresponding java.lang.Class object. Rather,
|
||||
* the properties of a JavaClass are the static methods and properties of the
|
||||
* corresponding Java class.
|
||||
*
|
||||
* Note that there is no runtime equivalent to the JavaClass class in Java.
|
||||
* (Although there are instances of java.lang.String and there are static
|
||||
* methods of java.lang.String that can be invoked, there's no such thing as
|
||||
* a first-class object that can be referenced simply as "java.lang.String".)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
static JSBool
|
||||
JavaClass_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
char *name;
|
||||
JSString *str;
|
||||
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor)
|
||||
return JS_FALSE;
|
||||
|
||||
switch(type) {
|
||||
|
||||
|
||||
case JSTYPE_STRING:
|
||||
/* Convert '/' to '.' so that it looks like Java language syntax. */
|
||||
if (!class_descriptor->name)
|
||||
break;
|
||||
name = PR_smprintf("[JavaClass %s]", class_descriptor->name);
|
||||
if (!name) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
str = JS_NewString(cx, name, strlen(name));
|
||||
if (!str) {
|
||||
free(name);
|
||||
/* It's not necessary to call JS_ReportOutOfMemory(), as
|
||||
JS_NewString() will do so on failure. */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
lookup_static_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
JavaClassDescriptor **class_descriptorp,
|
||||
jsid id, JavaMemberDescriptor **memberp)
|
||||
{
|
||||
jsval idval;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
const char *member_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor) {
|
||||
*class_descriptorp = NULL;
|
||||
*memberp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (class_descriptorp)
|
||||
*class_descriptorp = class_descriptor;
|
||||
|
||||
member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (!member_descriptor) {
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
if (!JSVAL_IS_STRING(idval)) {
|
||||
JS_ReportError(cx, "invalid JavaClass property expression. "
|
||||
"(methods and fields of a JavaClass object can only be identified by their name)");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
|
||||
/* Why do we have to do this ? */
|
||||
if (!strcmp(member_name, "prototype")) {
|
||||
*memberp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "Java class %s has no public static field or method named \"%s\"",
|
||||
class_descriptor->name, member_name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (memberp)
|
||||
*memberp = member_descriptor;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaClass_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jsval idval;
|
||||
jclass java_class;
|
||||
const char *member_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* printf("In JavaClass_getProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
if (!member_descriptor) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
|
||||
if (member_descriptor->field) {
|
||||
if (!member_descriptor->methods) {
|
||||
return jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, vp);
|
||||
} else {
|
||||
PR_ASSERT(0);
|
||||
}
|
||||
} else {
|
||||
JSFunction *function;
|
||||
|
||||
/* TODO - eliminate JSFUN_BOUND_METHOD */
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
function = JS_NewFunction(cx, jsj_JavaStaticMethodWrapper, 0,
|
||||
JSFUN_BOUND_METHOD, obj, member_name);
|
||||
if (!function)
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(JS_GetFunctionObject(function));
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaClass_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jclass java_class;
|
||||
const char *member_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsval idval;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* printf("In JavaClass_setProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Check for the case where there is a method with the given name, but no field
|
||||
with that name */
|
||||
if (!member_descriptor->field)
|
||||
goto no_such_field;
|
||||
|
||||
/* Silently fail if field value is final (immutable), as required by ECMA spec */
|
||||
if (member_descriptor->field->modifiers & ACC_FINAL)
|
||||
return JS_TRUE;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
return jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, *vp);
|
||||
|
||||
no_such_field:
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
JS_ReportError(cx, "No static field named \"%s\" in Java class %s",
|
||||
member_name, class_descriptor->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the private native data associated with the JavaPackage object.
|
||||
*/
|
||||
PR_STATIC_CALLBACK(void)
|
||||
JavaClass_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
|
||||
JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor)
|
||||
return;
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return;
|
||||
|
||||
/* printf("Finalizing %s\n", class_descriptor->name); */
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);
|
||||
}
|
||||
|
||||
|
||||
static JSBool
|
||||
JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
JSErrorReporter old_reporter;
|
||||
|
||||
/* printf("In JavaClass_lookupProperty()\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
old_reporter = JS_SetErrorReporter(cx, NULL);
|
||||
if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
|
||||
*objp = obj;
|
||||
*propp = (JSProperty*)1;
|
||||
} else {
|
||||
*objp = NULL;
|
||||
*propp = NULL;
|
||||
}
|
||||
|
||||
JS_SetErrorReporter(cx, old_reporter);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot define a new property in a JavaClass");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_setAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Silently ignore all setAttribute attempts */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
*vp = JSVAL_FALSE;
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
JS_ReportError(cx, "Properties of JavaClass objects may not be deleted");
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/* Attempts to delete permanent properties are silently ignored
|
||||
by ECMAScript. */
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
/* printf("In JavaClass_defaultValue()\n"); */
|
||||
return JavaClass_convert(cx, obj, JSTYPE_STRING, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
|
||||
/* Check for prototype JavaClass object */
|
||||
if (!class_descriptor) {
|
||||
*statep = JSVAL_NULL;
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor);
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor);
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(class_descriptor->num_instance_members);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
member_descriptor = JSVAL_TO_PRIVATE(*statep);
|
||||
if (member_descriptor) {
|
||||
*idp = member_descriptor->id;
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor->next);
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* Fall through ... */
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
*statep = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaClass_checkAccess(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSACC_WATCH:
|
||||
JS_ReportError(cx, "Cannot place watchpoints on JavaClass object properties");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSACC_IMPORT:
|
||||
JS_ReportError(cx, "Cannot export a JavaClass object's properties");
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the JavaScript instanceof operator for JavaClass objects by using
|
||||
* the equivalent Java instanceof operation.
|
||||
*/
|
||||
static JSBool
|
||||
JavaClass_hasInstance(JSContext *cx, JSObject *obj, jsval candidate_jsval,
|
||||
JSBool *has_instancep)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JSClass *js_class;
|
||||
JSBool has_instance;
|
||||
JSObject *candidate_obj;
|
||||
jclass java_class;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
has_instance = JS_FALSE;
|
||||
class_descriptor = JS_GetPrivate(cx, obj);
|
||||
if (!class_descriptor) {
|
||||
JS_ReportError(cx, "illegal operation on JavaClass prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the thing to the left of the instanceof operator is a
|
||||
* Java object.
|
||||
*/
|
||||
if (!JSVAL_IS_OBJECT(candidate_jsval))
|
||||
goto done;
|
||||
candidate_obj = JSVAL_TO_OBJECT(candidate_jsval);
|
||||
js_class = JS_GetClass(candidate_obj);
|
||||
if ((js_class != &JavaObject_class) && (js_class != &JavaArray_class))
|
||||
goto done;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
java_wrapper = JS_GetPrivate(cx, candidate_obj);
|
||||
if (!java_wrapper) {
|
||||
JS_ReportError(cx, "illegal operation on prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
java_obj = java_wrapper->java_obj;
|
||||
/* Get JNI pointer */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
has_instance = (*jEnv)->IsInstanceOf(jEnv, java_obj, java_class);
|
||||
|
||||
done:
|
||||
*has_instancep = has_instance;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObjectOps JavaClass_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
NULL, /* newObjectMap */
|
||||
NULL, /* destroyObjectMap */
|
||||
JavaClass_lookupProperty,
|
||||
JavaClass_defineProperty,
|
||||
JavaClass_getPropertyById, /* getProperty */
|
||||
JavaClass_setPropertyById, /* setProperty */
|
||||
JavaClass_getAttributes,
|
||||
JavaClass_setAttributes,
|
||||
JavaClass_deleteProperty,
|
||||
JavaClass_defaultValue,
|
||||
JavaClass_newEnumerate,
|
||||
JavaClass_checkAccess,
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
NULL, /* thisObject */
|
||||
NULL, /* dropProperty */
|
||||
jsj_JavaConstructorWrapper, /* call */
|
||||
jsj_JavaConstructorWrapper, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
JavaClass_hasInstance, /* hasInstance */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
JavaClass_getObjectOps(JSContext *cx, JSClass *clazz)
|
||||
{
|
||||
return &JavaClass_ops;
|
||||
}
|
||||
|
||||
JSClass JavaClass_class = {
|
||||
"JavaClass", JSCLASS_HAS_PRIVATE,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, JavaClass_convert, JavaClass_finalize,
|
||||
JavaClass_getObjectOps,
|
||||
};
|
||||
|
||||
static JSObject *
|
||||
jsj_new_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JSObject *JavaClass_obj;
|
||||
|
||||
JavaClass_obj = JS_NewObject(cx, &JavaClass_class, 0, parent_obj);
|
||||
if (!JavaClass_obj)
|
||||
return NULL;
|
||||
|
||||
JS_SetPrivate(cx, JavaClass_obj, (void *)class_descriptor);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* printf("JavaClass \'%s\' created\n", class_descriptor->name); */
|
||||
#endif
|
||||
|
||||
return JavaClass_obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj,
|
||||
const char *simple_class_name,
|
||||
jclass java_class)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JSObject *JavaClass_obj;
|
||||
|
||||
class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class);
|
||||
if (!class_descriptor)
|
||||
return NULL;
|
||||
|
||||
JavaClass_obj = jsj_new_JavaClass(cx, jEnv, parent_obj, class_descriptor);
|
||||
if (!JavaClass_obj)
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, parent_obj, simple_class_name,
|
||||
OBJECT_TO_JSVAL(JavaClass_obj), 0, 0,
|
||||
JSPROP_PERMANENT|JSPROP_READONLY|JSPROP_ENUMERATE))
|
||||
return NULL;
|
||||
return JavaClass_obj;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The getClass() native JS method is defined as a property of the global
|
||||
* object. Given a JavaObject it returns the corresponding JavaClass. This
|
||||
* is useful for accessing static methods and fields.
|
||||
*
|
||||
* js> getClass(new java.lang.String("foo"))
|
||||
* [JavaClass java.lang.String]
|
||||
*/
|
||||
static JSBool
|
||||
getClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSObject *obj_arg, *JavaClass_obj;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (argc != 1 ||
|
||||
!JSVAL_IS_OBJECT(argv[0]) ||
|
||||
!(obj_arg = JSVAL_TO_OBJECT(argv[0])) ||
|
||||
(!JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) &&
|
||||
!JS_InstanceOf(cx, obj_arg, &JavaArray_class, 0))) {
|
||||
JS_ReportError(cx, "getClass expects a Java object argument");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj_arg);
|
||||
if (!java_wrapper) {
|
||||
JS_ReportError(cx, "getClass called on prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
|
||||
JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor);
|
||||
if (!JavaClass_obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(JavaClass_obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
JSBool
|
||||
jsj_init_JavaClass(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
JavaClass_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
JavaClass_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
|
||||
/* Define JavaClass class */
|
||||
if (!JS_InitClass(cx, global_obj, 0, &JavaClass_class, 0, 0, 0, 0, 0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_DefineFunction(cx, global_obj, "getClass", getClass, 0,
|
||||
JSPROP_READONLY))
|
||||
return JS_FALSE;
|
||||
|
||||
return jsj_InitJavaClassReflectionsTable();
|
||||
}
|
||||
|
||||
134
mozilla/js/src/liveconnect/jsj_JavaMember.c
Normal file
134
mozilla/js/src/liveconnect/jsj_JavaMember.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright (C) 1998 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of JS's JavaMember class.
|
||||
* JavaMember's are a strange beast required only to handle the special case
|
||||
* of a public field and a public method that appear in the same class and
|
||||
* have the same name. When such a field/method is used in Java, the compiler
|
||||
* can statically determine from context whether the field or the method is
|
||||
* being referenced, but that is not possible with JavaScript. For example:
|
||||
*
|
||||
* ambiguousVal = javaObj.fieldOrMethod; // ambiguousVal is a JavaMember object
|
||||
* a = ambiguousVal(); // ambiguousVal used as a method value
|
||||
* b = ambiguousVal + 4; // ambiguousVal used as a field value
|
||||
*
|
||||
* A JavaMember instance carries both the captured value of the Java field and
|
||||
* the method value until the context that the value is to be used in is known,
|
||||
* at which point conversion forces the use of one or the other.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/* Private, native portion of a JavaMember */
|
||||
typedef struct JavaMethodOrFieldValue {
|
||||
jsval method_val;
|
||||
jsval field_val;
|
||||
} JavaMethodOrFieldValue;
|
||||
|
||||
JSObject *
|
||||
jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val)
|
||||
{
|
||||
JavaMethodOrFieldValue *member_val;
|
||||
JSObject *JavaMember_obj;
|
||||
|
||||
member_val = (JavaMethodOrFieldValue *)JS_malloc(cx, sizeof(*member_val));
|
||||
if (!member_val)
|
||||
return NULL;
|
||||
|
||||
JavaMember_obj = JS_NewObject(cx, &JavaMember_class, 0, 0);
|
||||
if (!JavaMember_obj) {
|
||||
JS_free(cx, member_val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_SetPrivate(cx, JavaMember_obj, (void *)member_val);
|
||||
member_val->method_val = method_val;
|
||||
JS_AddRoot(cx, &member_val->method_val);
|
||||
member_val->field_val = field_val;
|
||||
if (JSVAL_IS_GCTHING(field_val))
|
||||
JS_AddRoot(cx, &member_val->field_val);
|
||||
|
||||
return JavaMember_obj;
|
||||
}
|
||||
|
||||
static void
|
||||
JavaMember_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JavaMethodOrFieldValue *member_val;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return;
|
||||
|
||||
member_val = JS_GetPrivate(cx, obj);
|
||||
if (!member_val)
|
||||
return;
|
||||
JS_RemoveRoot(cx, &member_val->method_val);
|
||||
if (JSVAL_IS_GCTHING(member_val->method_val))
|
||||
JS_RemoveRoot(cx, &member_val->method_val);
|
||||
JS_free(cx, member_val);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaMember_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
JavaMethodOrFieldValue *member_val;
|
||||
|
||||
member_val = JS_GetPrivate(cx, obj);
|
||||
if (!member_val) {
|
||||
if (type == JSTYPE_OBJECT) {
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "illegal operation on JavaObject prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case JSTYPE_VOID:
|
||||
case JSTYPE_STRING:
|
||||
case JSTYPE_NUMBER:
|
||||
case JSTYPE_BOOLEAN:
|
||||
case JSTYPE_OBJECT:
|
||||
*vp = member_val->field_val;
|
||||
return JS_TRUE;
|
||||
|
||||
case JSTYPE_FUNCTION:
|
||||
*vp = member_val->method_val;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JSClass JavaMember_class = {
|
||||
"JavaMember", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JavaMember_convert, JavaMember_finalize
|
||||
};
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
JSBool
|
||||
jsj_init_JavaMember(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
if (!JS_InitClass(cx, global_obj,
|
||||
0, &JavaMember_class, 0, 0,
|
||||
0, 0,
|
||||
0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
686
mozilla/js/src/liveconnect/jsj_JavaObject.c
Normal file
686
mozilla/js/src/liveconnect/jsj_JavaObject.c
Normal file
@@ -0,0 +1,686 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of JS's JavaObject class.
|
||||
*
|
||||
* An instance of JavaObject is the JavaScript reflection of a Java object.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsj_hash.h" /* Hash table with Java object as key */
|
||||
|
||||
|
||||
/*
|
||||
* This is a hash table that maps from Java objects to JS objects.
|
||||
* It is used to ensure that the same JS object is obtained when a Java
|
||||
* object is reflected more than once, so that JS object equality tests
|
||||
* work in the expected manner, i.e. the "==" and "===" operators.
|
||||
*
|
||||
* The table entry keys are Java objects (of type jobject) and the entry values
|
||||
* are JSObject pointers. Because the jobject type is an opaque handle and
|
||||
* not necessarily a pointer, the hashing and key comparison functions must
|
||||
* invoke the appropriate JVM functions.
|
||||
*
|
||||
* When the corresponding JS object instance is finalized, the entry is
|
||||
* removed from the table, and a Java GC root for the Java object is removed.
|
||||
*/
|
||||
static JSJHashTable *java_obj_reflections = NULL;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
static PRMonitor *java_obj_reflections_monitor = NULL;
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
init_java_obj_reflections_table()
|
||||
{
|
||||
java_obj_reflections =
|
||||
JSJ_NewHashTable(512, jsj_HashJavaObject, jsj_JavaObjectComparator,
|
||||
NULL, NULL, NULL);
|
||||
if (!java_obj_reflections)
|
||||
return JS_FALSE;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
java_obj_reflections_monitor = PR_NewNamedMonitor("java_obj_reflections");
|
||||
if (!java_obj_reflections_monitor) {
|
||||
PR_HashTableDestroy(java_obj_reflections);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
jsj_WrapJavaObject(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
jobject java_obj,
|
||||
jclass java_class)
|
||||
{
|
||||
JSJHashNumber hash_code;
|
||||
JSClass *js_class;
|
||||
JSObject *js_wrapper_obj;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
js_wrapper_obj = NULL;
|
||||
|
||||
hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_EnterMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
|
||||
hep = JSJ_HashTableRawLookup(java_obj_reflections,
|
||||
hash_code, java_obj, (void*)jEnv);
|
||||
he = *hep;
|
||||
if (he) {
|
||||
js_wrapper_obj = (JSObject *)he->value;
|
||||
if (js_wrapper_obj)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* No existing reflection found. Construct a new one */
|
||||
class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class);
|
||||
if (!class_descriptor)
|
||||
goto done;
|
||||
if (class_descriptor->type == JAVA_SIGNATURE_ARRAY) {
|
||||
js_class = &JavaArray_class;
|
||||
} else {
|
||||
PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_CLASS);
|
||||
js_class = &JavaObject_class;
|
||||
}
|
||||
|
||||
/* Create new JS object to reflect Java object */
|
||||
js_wrapper_obj = JS_NewObject(cx, js_class, NULL, NULL);
|
||||
if (!js_wrapper_obj)
|
||||
goto done;
|
||||
|
||||
/* Create private, native portion of JavaObject */
|
||||
java_wrapper =
|
||||
(JavaObjectWrapper *)JS_malloc(cx, sizeof(JavaObjectWrapper));
|
||||
if (!java_wrapper) {
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);
|
||||
goto done;
|
||||
}
|
||||
JS_SetPrivate(cx, js_wrapper_obj, java_wrapper);
|
||||
java_wrapper->class_descriptor = class_descriptor;
|
||||
|
||||
java_obj = (*jEnv)->NewGlobalRef(jEnv, java_obj);
|
||||
java_wrapper->java_obj = java_obj;
|
||||
if (!java_obj)
|
||||
goto out_of_memory;
|
||||
|
||||
/* Add the JavaObject to the hash table */
|
||||
he = JSJ_HashTableRawAdd(java_obj_reflections, hep, hash_code,
|
||||
java_obj, js_wrapper_obj, (void*)jEnv);
|
||||
if (!he) {
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_obj);
|
||||
goto out_of_memory;
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_ExitMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
|
||||
return js_wrapper_obj;
|
||||
|
||||
out_of_memory:
|
||||
/* No need to free js_wrapper_obj, as it will be finalized by GC. */
|
||||
JS_ReportOutOfMemory(cx);
|
||||
js_wrapper_obj = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_java_obj_reflection_from_hashtable(jobject java_obj, JNIEnv *jEnv)
|
||||
{
|
||||
JSJHashNumber hash_code;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_EnterMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
|
||||
hep = JSJ_HashTableRawLookup(java_obj_reflections, hash_code,
|
||||
java_obj, (void*)jEnv);
|
||||
he = *hep;
|
||||
|
||||
PR_ASSERT(he);
|
||||
if (he)
|
||||
JSJ_HashTableRawRemove(java_obj_reflections, hep, he, (void*)jEnv);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_ExitMonitor(java_obj_reflections_monitor);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
JavaObject_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper)
|
||||
return;
|
||||
java_obj = java_wrapper->java_obj;
|
||||
|
||||
if (java_obj) {
|
||||
remove_java_obj_reflection_from_hashtable(java_obj, jEnv);
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_obj);
|
||||
}
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor);
|
||||
JS_free(cx, java_wrapper);
|
||||
}
|
||||
|
||||
/* Trivial helper for jsj_DiscardJavaObjReflections(), below */
|
||||
static PRIntn
|
||||
enumerate_remove_java_obj(JSJHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
JNIEnv *jEnv = (JNIEnv*)arg;
|
||||
jobject java_obj;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JSObject *java_wrapper_obj;
|
||||
|
||||
java_wrapper_obj = (JSObject *)he->value;
|
||||
java_wrapper = JS_GetPrivate(NULL, java_wrapper_obj);
|
||||
java_obj = java_wrapper->java_obj;
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_obj);
|
||||
java_wrapper->java_obj = NULL;
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
/* This shutdown routine discards all JNI references to Java objects
|
||||
that have been reflected into JS, even if there are still references
|
||||
to them from JS. */
|
||||
void
|
||||
jsj_DiscardJavaObjReflections(JNIEnv *jEnv)
|
||||
{
|
||||
if (java_obj_reflections) {
|
||||
JSJ_HashTableEnumerateEntries(java_obj_reflections,
|
||||
enumerate_remove_java_obj,
|
||||
(void*)jEnv);
|
||||
JSJ_HashTableDestroy(java_obj_reflections);
|
||||
java_obj_reflections = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PR_CALLBACK JSBool
|
||||
JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper) {
|
||||
if (type == JSTYPE_OBJECT) {
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "illegal operation on JavaObject prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
java_obj = java_wrapper->java_obj;
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
|
||||
switch (type) {
|
||||
case JSTYPE_OBJECT:
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSTYPE_FUNCTION:
|
||||
JS_ReportError(cx, "can't convert Java object to function");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSTYPE_VOID:
|
||||
case JSTYPE_STRING:
|
||||
/* Either extract a C-string from the java.lang.String object
|
||||
or call the Java toString() method */
|
||||
return jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, vp);
|
||||
|
||||
case JSTYPE_NUMBER:
|
||||
/* Call Java doubleValue() method, if applicable */
|
||||
return jsj_ConvertJavaObjectToJSNumber(cx, jEnv, class_descriptor, java_obj, vp);
|
||||
|
||||
case JSTYPE_BOOLEAN:
|
||||
/* Call booleanValue() method, if applicable */
|
||||
return jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, class_descriptor, java_obj, vp);
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
JavaObjectWrapper **java_wrapperp,
|
||||
jsid id,
|
||||
JavaMemberDescriptor **member_descriptorp)
|
||||
{
|
||||
jsval idval;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
const char *member_name, *property_name;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
if (!java_wrapper) {
|
||||
if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) &&
|
||||
(property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) {
|
||||
if (!strcmp(property_name, "constructor")) {
|
||||
*java_wrapperp = NULL;
|
||||
*member_descriptorp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
JS_ReportError(cx, "illegal operation on JavaObject prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_CLASS ||
|
||||
class_descriptor->type == JAVA_SIGNATURE_ARRAY);
|
||||
|
||||
member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (!member_descriptor) {
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
if (!JSVAL_IS_STRING(idval)) {
|
||||
JS_ReportError(cx, "invalid JavaObject property expression. "
|
||||
"(methods and field properties of a JavaObject object can only be strings)");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
|
||||
JS_ReportError(cx, "Java class %s has no public instance field or "
|
||||
"method named \"%s\"",
|
||||
class_descriptor->name, member_name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Success. Handle the multiple return values */
|
||||
if (java_wrapperp)
|
||||
*java_wrapperp = java_wrapper;
|
||||
if (member_descriptorp)
|
||||
*member_descriptorp = member_descriptor;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_CALLBACK JSBool
|
||||
JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jobject java_obj;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JNIEnv *jEnv;
|
||||
JSObject *funobj;
|
||||
jsval field_val, method_val;
|
||||
JSBool success;
|
||||
|
||||
/* printf("In JavaObject_getProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Handle access to "constructor" property of prototype object with
|
||||
silent failure. */
|
||||
if (!member_descriptor) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
java_obj = java_wrapper->java_obj;
|
||||
field_val = method_val = JSVAL_VOID;
|
||||
|
||||
/* If a field member, get the value of the field */
|
||||
if (member_descriptor->field) {
|
||||
success = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, &field_val);
|
||||
if (!success)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* If a method member, build a wrapper around the Java method */
|
||||
if (member_descriptor->methods) {
|
||||
/* Create a function object with this JavaObject as its parent, so that
|
||||
JSFUN_BOUND_METHOD binds it as the default 'this' for the function. */
|
||||
funobj = JS_CloneFunctionObject(cx, member_descriptor->invoke_func_obj, obj);
|
||||
if (!funobj)
|
||||
return JS_FALSE;
|
||||
method_val = OBJECT_TO_JSVAL(funobj);
|
||||
}
|
||||
|
||||
#if TEST_JAVAMEMBER
|
||||
/* Always create a JavaMember object, even though it's inefficient */
|
||||
obj = jsj_CreateJavaMember(cx, method_val, field_val);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
#else /* !TEST_JAVAMEMBER */
|
||||
|
||||
if (member_descriptor->field) {
|
||||
if (!member_descriptor->methods) {
|
||||
/* Return value of Java field */
|
||||
*vp = field_val;
|
||||
} else {
|
||||
/* Handle special case of access to a property that could refer
|
||||
to either a Java field or a method that share the same name.
|
||||
In Java, such ambiguity is not possible because the compiler
|
||||
can statically determine which is being accessed. */
|
||||
obj = jsj_CreateJavaMember(cx, method_val, field_val);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Return wrapper around Java method */
|
||||
*vp = method_val;
|
||||
}
|
||||
|
||||
#endif /* !TEST_JAVAMEMBER */
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(JSBool)
|
||||
JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
jobject java_obj;
|
||||
const char *member_name;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsval idval;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
/* printf("In JavaObject_setProperty\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Check for the case where there is a method with the give name, but no field
|
||||
with that name */
|
||||
if (!member_descriptor->field)
|
||||
goto no_such_field;
|
||||
|
||||
/* Silently fail if field value is final (immutable), as required by ECMA spec */
|
||||
if (member_descriptor->field->modifiers & ACC_FINAL)
|
||||
return JS_TRUE;
|
||||
|
||||
java_obj = java_wrapper->java_obj;
|
||||
return jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, *vp);
|
||||
|
||||
no_such_field:
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
JS_ReportError(cx, "No instance field named \"%s\" in Java class %s",
|
||||
member_name, class_descriptor->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JNIEnv *jEnv;
|
||||
JSErrorReporter old_reporter;
|
||||
|
||||
/* printf("In JavaObject_lookupProperty()\n"); */
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
old_reporter = JS_SetErrorReporter(cx, NULL);
|
||||
if (lookup_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
|
||||
*objp = obj;
|
||||
*propp = (JSProperty*)1;
|
||||
} else {
|
||||
*objp = NULL;
|
||||
*propp = NULL;
|
||||
}
|
||||
|
||||
JS_SetErrorReporter(cx, old_reporter);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot define a new property in a JavaObject");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_setAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp)
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Silently ignore all setAttribute attempts */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
{
|
||||
JSVersion version = JS_GetVersion(cx);
|
||||
|
||||
*vp = JSVAL_FALSE;
|
||||
|
||||
if (!JSVERSION_IS_ECMA(version)) {
|
||||
JS_ReportError(cx, "Properties of JavaObject objects may not be deleted");
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/* Attempts to delete permanent properties are silently ignored
|
||||
by ECMAScript. */
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
/* printf("In JavaObject_defaultValue()\n"); */
|
||||
return JavaObject_convert(cx, obj, type, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
java_wrapper = JS_GetPrivate(cx, obj);
|
||||
/* Check for prototype object */
|
||||
if (!java_wrapper) {
|
||||
*statep = JSVAL_NULL;
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
class_descriptor = java_wrapper->class_descriptor;
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
|
||||
/* Get the Java per-thread environment pointer for this JSContext */
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor);
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor);
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(class_descriptor->num_instance_members);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
member_descriptor = JSVAL_TO_PRIVATE(*statep);
|
||||
if (member_descriptor) {
|
||||
*idp = member_descriptor->id;
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor->next);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through ... */
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
*statep = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaObject_checkAccess(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSACC_WATCH:
|
||||
JS_ReportError(cx, "Cannot place watchpoints on JavaObject object properties");
|
||||
return JS_FALSE;
|
||||
|
||||
case JSACC_IMPORT:
|
||||
JS_ReportError(cx, "Cannot export a JavaObject object's properties");
|
||||
return JS_FALSE;
|
||||
|
||||
default:
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
JSObjectOps JavaObject_ops = {
|
||||
/* Mandatory non-null function pointer members. */
|
||||
NULL, /* newObjectMap */
|
||||
NULL, /* destroyObjectMap */
|
||||
JavaObject_lookupProperty,
|
||||
JavaObject_defineProperty,
|
||||
JavaObject_getPropertyById, /* getProperty */
|
||||
JavaObject_setPropertyById, /* setProperty */
|
||||
JavaObject_getAttributes,
|
||||
JavaObject_setAttributes,
|
||||
JavaObject_deleteProperty,
|
||||
JavaObject_defaultValue,
|
||||
JavaObject_newEnumerate,
|
||||
JavaObject_checkAccess,
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
NULL, /* thisObject */
|
||||
NULL, /* dropProperty */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
JavaObject_getObjectOps(JSContext *cx, JSClass *clazz)
|
||||
{
|
||||
return &JavaObject_ops;
|
||||
}
|
||||
|
||||
JSClass JavaObject_class = {
|
||||
"JavaObject", JSCLASS_HAS_PRIVATE,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, JavaObject_convert, JavaObject_finalize,
|
||||
JavaObject_getObjectOps,
|
||||
};
|
||||
|
||||
extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps;
|
||||
|
||||
|
||||
JSBool
|
||||
jsj_init_JavaObject(JSContext *cx, JSObject *global_obj)
|
||||
{
|
||||
JavaObject_ops.newObjectMap = js_ObjectOps.newObjectMap;
|
||||
JavaObject_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap;
|
||||
|
||||
if (!JS_InitClass(cx, global_obj,
|
||||
0, &JavaObject_class, 0, 0,
|
||||
0, 0,
|
||||
0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
return init_java_obj_reflections_table();
|
||||
}
|
||||
500
mozilla/js/src/liveconnect/jsj_JavaPackage.c
Normal file
500
mozilla/js/src/liveconnect/jsj_JavaPackage.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the native code implementation of the JavaPackage class.
|
||||
*
|
||||
* A JavaPackage is JavaScript's representation of a Java package. The
|
||||
* JavaPackage object contains only a string, which is the path to the package,
|
||||
* e.g. "java/lang". The JS properties of a JavaPackage are either nested packages
|
||||
* or a JavaClass object, which represents the path to a Java class.
|
||||
*
|
||||
* Note that there is no equivalent to a JavaPackage object in Java. Example:
|
||||
* Although there are instances of java.lang.String and there are static methods
|
||||
* of java.lang.String that can be invoked, there's no such thing as a java.lang
|
||||
* object in Java that exists at run time.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsjava.h"
|
||||
|
||||
|
||||
JSClass JavaPackage_class; /* Forward declaration */
|
||||
|
||||
/*
|
||||
* The native part of a JavaPackage object. It gets stored in the object's
|
||||
* private slot.
|
||||
*/
|
||||
typedef struct {
|
||||
const char * path; /* e.g. "java/lang" or NULL if top level package */
|
||||
int flags; /* e.g. PKG_SYSTEM, PKG_CLASS */
|
||||
} JavaPackage_Private;
|
||||
|
||||
static JSObject *
|
||||
define_JavaPackage(JSContext *cx, JSObject *parent_obj,
|
||||
const char *obj_name, const char *path, int flags)
|
||||
{
|
||||
JSObject *package_obj;
|
||||
JavaPackage_Private *package;
|
||||
|
||||
package_obj = JS_DefineObject(cx, parent_obj, obj_name, &JavaPackage_class, 0,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
if (!package_obj)
|
||||
return NULL;
|
||||
|
||||
/* Attach private, native data to the JS object */
|
||||
package = (JavaPackage_Private *)JS_malloc(cx, sizeof(JavaPackage_Private));
|
||||
JS_SetPrivate(cx, package_obj, (void *)package);
|
||||
if (path)
|
||||
package->path = JS_strdup(cx, path);
|
||||
else
|
||||
package->path = "";
|
||||
|
||||
package->flags = flags;
|
||||
|
||||
/* Check for OOM */
|
||||
if (!package->path) {
|
||||
JS_DeleteProperty(cx, parent_obj, obj_name);
|
||||
JS_free(cx, package);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return package_obj;
|
||||
}
|
||||
|
||||
/* JavaPackage uses standard JS getProperty */
|
||||
|
||||
/*
|
||||
* Don't allow user-defined properties to be set on Java package objects, e.g.
|
||||
* it is illegal to write "java.lang.myProperty = 4". We probably could relax
|
||||
* this restriction, but it's potentially confusing and not clearly useful.
|
||||
*/
|
||||
static JSBool
|
||||
JavaPackage_setProperty(JSContext *cx, JSObject *obj, jsval slot, jsval *vp)
|
||||
{
|
||||
JavaPackage_Private *package = JS_GetPrivate(cx, obj);
|
||||
if (!package) {
|
||||
JS_ReportError(cx, "illegal attempt to add property to "
|
||||
"JavaPackage prototype object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_ReportError(cx, "You may not add properties to a JavaPackage object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool quiet_resolve_failure;
|
||||
|
||||
/*
|
||||
* Resolve a component name to be either the name of a class or a package.
|
||||
*/
|
||||
static JSBool
|
||||
JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id)
|
||||
{
|
||||
JavaPackage_Private *package;
|
||||
JSBool ok = JS_TRUE;
|
||||
jclass jclazz;
|
||||
char *subPath, *newPath;
|
||||
const char *path;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
package = (JavaPackage_Private *)JS_GetPrivate(cx, obj);
|
||||
if (!package)
|
||||
return JS_TRUE;
|
||||
|
||||
if (!JSVAL_IS_STRING(id))
|
||||
return JS_TRUE;
|
||||
subPath = JS_GetStringBytes(JSVAL_TO_STRING(id));
|
||||
|
||||
/*
|
||||
* There will be an attempt to invoke the toString() method when producing
|
||||
* the string representation of a JavaPackage. When this occurs, avoid
|
||||
* creating a bogus toString package. (This means that no one can ever
|
||||
* create a package with the simple name "toString", but we'll live with
|
||||
* that limitation.)
|
||||
*/
|
||||
if (!strcmp(subPath, "toString"))
|
||||
return JS_FALSE;
|
||||
|
||||
path = package->path;
|
||||
newPath = PR_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath);
|
||||
if (!newPath) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsj_MapJSContextToJSJThread(cx, &jEnv);
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
Unfortunately, Java provides no way to find out whether a particular
|
||||
name is a package or not. The only way to tell is to try to load the
|
||||
name as a class file and, if that fails, assume it's a package. This
|
||||
makes things work as expected for the most part, but it has three
|
||||
noticeable problems that keep coming up:
|
||||
|
||||
- You can refer to a package like java.lang.i.buried.paul without
|
||||
generating a complaint. Of course, you'll never be able to refer to
|
||||
any classes through it.
|
||||
|
||||
- An annoying consequence of the above is that misspelling a class name
|
||||
results in a cryptic error about packages.
|
||||
|
||||
- In a browser context, i.e. where applets are involved, figuring out
|
||||
whether something is a class may require looking for it over the net
|
||||
using the current classloader. This means that the first time you
|
||||
refer to java.lang.System in a js context, there will be an attempt
|
||||
to search for [[DOCBASE]]/java.class on the server.
|
||||
|
||||
A solution is to explicitly tell jsjava the names of all the (local)
|
||||
packages on the CLASSPATH. (Not implemented yet.)
|
||||
|
||||
*/
|
||||
jclazz = (*jEnv)->FindClass(jEnv, newPath);
|
||||
if (jclazz) {
|
||||
JSObject *newClass;
|
||||
|
||||
newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz);
|
||||
if (!newClass) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* We assume that any failed attempt to load a class is because it
|
||||
doesn't exist. If we wanted to do a better job, we would check
|
||||
the exception type and make sure that it's NoClassDefFoundError */
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
|
||||
/* beard: this has to be done here, so built-in classes will be defined. */
|
||||
/* Painful hack for pre_define_java_packages() */
|
||||
if (quiet_resolve_failure) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no class of the given name, then we must be referring to
|
||||
* a package. However, don't allow bogus sub-packages of pre-defined
|
||||
* system packages to be created.
|
||||
*/
|
||||
if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) {
|
||||
JavaPackage_Private *package;
|
||||
|
||||
package = JS_GetPrivate(cx, obj);
|
||||
if (package->flags & PKG_SYSTEM) {
|
||||
char *msg, *cp;
|
||||
|
||||
msg = PR_smprintf("No Java system package with name \"%s\" was identified "
|
||||
"and no Java class with that name exists either",
|
||||
newPath);
|
||||
|
||||
/* Check for OOM */
|
||||
if (msg) {
|
||||
/* Convert package of form "java/lang" to "java.lang" */
|
||||
for (cp = msg; *cp != '\0'; cp++)
|
||||
if (*cp == '/')
|
||||
*cp = '.';
|
||||
JS_ReportError(cx, msg);
|
||||
free((char*)msg);
|
||||
}
|
||||
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!define_JavaPackage(cx, obj, subPath, newPath, 0)) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* printf("JavaPackage \'%s\' created\n", newPath); */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
free(newPath);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaPackage_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
char *name, *cp;
|
||||
|
||||
JavaPackage_Private *package = JS_GetPrivate(cx, obj);
|
||||
if (!package) {
|
||||
fprintf(stderr, "JavaPackage_resolve: no private data!\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
||||
/* Pretty-printing of JavaPackage */
|
||||
case JSTYPE_VOID: /* Default value */
|
||||
case JSTYPE_NUMBER:
|
||||
case JSTYPE_STRING:
|
||||
/* Convert '/' to '.' so that it looks like Java language syntax. */
|
||||
if (!package->path)
|
||||
break;
|
||||
name = PR_smprintf("[JavaPackage %s]", package->path);
|
||||
if (!name) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
for (cp = name; *cp != '\0'; cp++)
|
||||
if (*cp == '/')
|
||||
*cp = '.';
|
||||
str = JS_NewString(cx, name, strlen(name));
|
||||
if (!str) {
|
||||
free(name);
|
||||
/* It's not necessary to call JS_ReportOutOfMemory(), as
|
||||
JS_NewString() will do so on failure. */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
|
||||
case JSTYPE_OBJECT:
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the private native data associated with the JavaPackage object.
|
||||
*/
|
||||
static void
|
||||
JavaPackage_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JavaPackage_Private *package = JS_GetPrivate(cx, obj);
|
||||
if (!package)
|
||||
return;
|
||||
|
||||
if (package->path)
|
||||
JS_free(cx, (char *)package->path);
|
||||
JS_free(cx, package);
|
||||
}
|
||||
|
||||
/*
|
||||
* The definition of the JavaPackage class
|
||||
*/
|
||||
JSClass JavaPackage_class = {
|
||||
"JavaPackage", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JavaPackage_setProperty,
|
||||
JS_EnumerateStub, JavaPackage_resolve,
|
||||
JavaPackage_convert, JavaPackage_finalize
|
||||
};
|
||||
|
||||
JavaPackageDef
|
||||
standard_java_packages[] = {
|
||||
{"java", NULL, PKG_USER},
|
||||
{"java.applet", NULL, PKG_USER},
|
||||
{"java.awt", NULL, PKG_USER},
|
||||
{"java.awt.datatransfer",
|
||||
NULL, PKG_SYSTEM},
|
||||
{"java.awt.event", NULL, PKG_SYSTEM},
|
||||
{"java.awt.image", NULL, PKG_SYSTEM},
|
||||
{"java.awt.peer", NULL, PKG_SYSTEM},
|
||||
{"java.beans", NULL, PKG_USER},
|
||||
{"java.io", NULL, PKG_SYSTEM},
|
||||
{"java.lang", NULL, PKG_USER},
|
||||
{"java.lang.reflect", NULL, PKG_SYSTEM},
|
||||
{"java.math", NULL, PKG_SYSTEM},
|
||||
{"java.net", NULL, PKG_USER},
|
||||
{"java.rmi", NULL, PKG_USER},
|
||||
{"java.rmi.dgc", NULL, PKG_USER},
|
||||
{"java.rmi.user", NULL, PKG_USER},
|
||||
{"java.rmi.registry", NULL, PKG_USER},
|
||||
{"java.rmi.server", NULL, PKG_USER},
|
||||
{"java.security", NULL, PKG_USER},
|
||||
{"java.security.acl", NULL, PKG_SYSTEM},
|
||||
{"java.security.interfaces",
|
||||
NULL, PKG_SYSTEM},
|
||||
{"java.sql", NULL, PKG_USER},
|
||||
{"java.text", NULL, PKG_USER},
|
||||
{"java.text.resources", NULL, PKG_SYSTEM},
|
||||
{"java.util", NULL, PKG_USER},
|
||||
{"java.util.zip", NULL, PKG_SYSTEM},
|
||||
|
||||
{"netscape", NULL, PKG_USER},
|
||||
{"netscape.applet", NULL, PKG_SYSTEM},
|
||||
{"netscape.application",NULL, PKG_SYSTEM},
|
||||
{"netscape.debug", NULL, PKG_SYSTEM},
|
||||
{"netscape.javascript", NULL, PKG_SYSTEM},
|
||||
{"netscape.ldap", NULL, PKG_SYSTEM},
|
||||
{"netscape.misc", NULL, PKG_SYSTEM},
|
||||
{"netscape.net", NULL, PKG_SYSTEM},
|
||||
{"netscape.plugin", NULL, PKG_SYSTEM},
|
||||
{"netscape.util", NULL, PKG_SYSTEM},
|
||||
{"netscape.secfile", NULL, PKG_SYSTEM},
|
||||
{"netscape.security", NULL, PKG_SYSTEM},
|
||||
{"netscape.WAI", NULL, PKG_SYSTEM},
|
||||
|
||||
{"sun", NULL, PKG_USER},
|
||||
{"Packages", "", PKG_USER},
|
||||
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Pre-define a hierarchy of JavaPackage objects.
|
||||
* Pre-defining a Java package at initialization time is not necessary, but
|
||||
* it will make package lookup faster and, more importantly, will avoid
|
||||
* unnecessary network accesses if classes are being loaded over the network.
|
||||
*/
|
||||
static JSBool
|
||||
pre_define_java_packages(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *predefined_packages)
|
||||
{
|
||||
JSBool package_exists;
|
||||
JSObject *parent_obj;
|
||||
JavaPackageDef *package_def;
|
||||
char *simple_name, *cp, *package_name, *path;
|
||||
int flags;
|
||||
|
||||
if (!predefined_packages)
|
||||
return JS_TRUE;
|
||||
|
||||
/* Iterate over all pre-defined Java packages */
|
||||
for (package_def = predefined_packages; package_def->name; package_def++) {
|
||||
package_name = path = NULL;
|
||||
|
||||
parent_obj = global_obj;
|
||||
package_name = strdup(package_def->name);
|
||||
if (!package_name)
|
||||
goto out_of_memory;
|
||||
|
||||
/* Walk the chain of JavaPackage objects to get to the parent of the
|
||||
rightmost sub-package in the fully-qualified package name. */
|
||||
for (simple_name = strtok(package_name, "."); 1; simple_name = strtok(NULL, ".")) {
|
||||
jsval v;
|
||||
|
||||
if (!simple_name) {
|
||||
JS_ReportError(cx, "Package %s defined twice ?", package_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check to see if the sub-package already exists */
|
||||
quiet_resolve_failure = JS_TRUE;
|
||||
package_exists = JS_LookupProperty(cx, parent_obj, simple_name, &v) && JSVAL_IS_OBJECT(v);
|
||||
quiet_resolve_failure = JS_FALSE;
|
||||
|
||||
if (package_exists) {
|
||||
parent_obj = JSVAL_TO_OBJECT(v);
|
||||
continue;
|
||||
} else {
|
||||
/* New package objects should only be created at the terminal
|
||||
sub-package in a fully-qualified package-name */
|
||||
if (strtok(NULL, ".")) {
|
||||
JS_ReportError(cx, "Illegal predefined package definition for %s",
|
||||
package_def->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (package_def->path) {
|
||||
path = strdup(package_def->path);
|
||||
if (!path)
|
||||
goto out_of_memory;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* The default path is specified, so create it from the
|
||||
* fully-qualified package name.
|
||||
*/
|
||||
path = strdup(package_def->name);
|
||||
if (!path)
|
||||
goto out_of_memory;
|
||||
/* Transform package name, e.g. "java.lang" ==> "java/lang" */
|
||||
for (cp = path; *cp != '\0'; cp++) {
|
||||
if (*cp == '.')
|
||||
*cp = '/';
|
||||
}
|
||||
}
|
||||
flags = package_def->flags;
|
||||
parent_obj = define_JavaPackage(cx, parent_obj, simple_name, path, flags);
|
||||
if (!parent_obj)
|
||||
goto error;
|
||||
|
||||
free(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(package_name);
|
||||
}
|
||||
return JS_TRUE;
|
||||
|
||||
out_of_memory:
|
||||
JS_ReportOutOfMemory(cx);
|
||||
|
||||
error:
|
||||
JS_FREE_IF(cx, package_name);
|
||||
JS_FREE_IF(cx, path);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JavaPackage_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &JavaPackage_class, argv))
|
||||
return JS_FALSE;
|
||||
return JavaPackage_convert(cx, obj, JSTYPE_STRING, rval);
|
||||
}
|
||||
|
||||
static JSFunctionSpec JavaPackage_methods[] = {
|
||||
{"toString", JavaPackage_toString, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
/*
|
||||
* One-time initialization for the JavaPackage class. (This is not
|
||||
* run once per thread, rather it's run once for a given JSContext.)
|
||||
*/
|
||||
JSBool
|
||||
jsj_init_JavaPackage(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *additional_predefined_packages) {
|
||||
|
||||
/* Define JavaPackage class */
|
||||
if (!JS_InitClass(cx, global_obj, 0, &JavaPackage_class,
|
||||
0, 0, 0, JavaPackage_methods, 0, 0))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Add top-level packages, e.g. : java, netscape, sun */
|
||||
if (!pre_define_java_packages(cx, global_obj, standard_java_packages))
|
||||
return JS_FALSE;
|
||||
if (!pre_define_java_packages(cx, global_obj, additional_predefined_packages))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
180
mozilla/js/src/liveconnect/jsj_array.c
Normal file
180
mozilla/js/src/liveconnect/jsj_array.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the code for reading and writing elements of a Java array.
|
||||
*/
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/*
|
||||
* Read the Java value at a given index into a Java array and convert it
|
||||
* to a JS value. The array_component_signature describes the type of
|
||||
* the resulting Java value, which can be a primitive type or an object type.
|
||||
* More specifically it can be an array type in the case of multidimensional
|
||||
* arrays.
|
||||
*/
|
||||
JSBool
|
||||
jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index,
|
||||
JavaSignature *array_component_signature,
|
||||
jsval *vp)
|
||||
{
|
||||
jvalue java_value;
|
||||
JavaSignatureChar component_type;
|
||||
|
||||
#define GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \
|
||||
(*jEnv)->Get##Type##ArrayRegion(jEnv, java_array, index, 1, \
|
||||
&java_value.member); \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_ReportJavaError(cx, jEnv, "Error reading element of " \
|
||||
"Java primitive array"); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
component_type = array_component_signature->type;
|
||||
switch(component_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
java_value.l = (*jEnv)->GetObjectArrayElement(jEnv, java_array, index);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_ReportJavaError(cx, jEnv, "Error reading Java object array");
|
||||
return JS_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
#undef GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return jsj_ConvertJavaValueToJSValue(cx, jEnv, array_component_signature, &java_value, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index,
|
||||
JavaSignature *array_component_signature,
|
||||
jsval js_val)
|
||||
{
|
||||
int dummy_cost;
|
||||
jvalue java_value;
|
||||
JavaSignatureChar component_type;
|
||||
JSBool is_local_ref;
|
||||
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, array_component_signature,
|
||||
&dummy_cost, &java_value, &is_local_ref))
|
||||
return JS_FALSE;
|
||||
|
||||
#define SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \
|
||||
(*jEnv)->Set##Type##ArrayRegion(jEnv, java_array, index, 1, \
|
||||
&java_value.member); \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_ReportJavaError(cx, jEnv, "Error assigning to element of " \
|
||||
"Java primitive array"); \
|
||||
return JS_FALSE; \
|
||||
}
|
||||
|
||||
component_type = array_component_signature->type;
|
||||
switch(component_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
(*jEnv)->SetObjectArrayElement(jEnv, java_array, index, java_value.l);
|
||||
if (is_local_ref) \
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_value.l);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_ReportJavaError(cx, jEnv, "Error assigning to Java object array");
|
||||
return JS_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
#undef SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
605
mozilla/js/src/liveconnect/jsj_class.c
Normal file
605
mozilla/js/src/liveconnect/jsj_class.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the code that constructs and manipulates JavaClassDescriptor
|
||||
* structs, which are the native wrappers for Java classes.
|
||||
* JavaClassDescriptors are used to describe the signatures of methods and
|
||||
* fields. There is a JavaClassDescriptor associated with the reflection of
|
||||
* each Java Object.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsj_hash.h" /* Hash tables */
|
||||
|
||||
/* A one-to-one mapping between all referenced java.lang.Class objects and
|
||||
their corresponding JavaClassDescriptor objects */
|
||||
static JSJHashTable *java_class_reflections;
|
||||
|
||||
/*
|
||||
* Given a JVM handle to a java.lang.Class object, malloc a C-string
|
||||
* containing the UTF8 encoding of the fully qualified name of the class.
|
||||
* It's the caller's responsibility to free the returned string.
|
||||
*
|
||||
* If an error occurs, NULL is returned and the error reporter called.
|
||||
*/
|
||||
const char *
|
||||
jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
jstring java_class_name_jstr;
|
||||
const char *java_class_name;
|
||||
|
||||
/* Get java.lang.String object containing class name */
|
||||
java_class_name_jstr =
|
||||
(*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getName);
|
||||
|
||||
|
||||
if (!java_class_name_jstr)
|
||||
goto error;
|
||||
|
||||
/* Convert to UTF8 encoding and copy */
|
||||
java_class_name = jsj_DupJavaStringUTF(cx, jEnv, java_class_name_jstr);
|
||||
if (!java_class_name)
|
||||
return NULL;
|
||||
|
||||
return java_class_name;
|
||||
|
||||
error:
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java class name using"
|
||||
"java.lang.Class.getName()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert in-place a string of the form "java.lang.String" into "java/lang/String".
|
||||
* Though the former style is conventionally used by Java programmers, the latter is
|
||||
* what the JNI functions require.
|
||||
*/
|
||||
void
|
||||
jsj_MakeJNIClassname(char * class_name)
|
||||
{
|
||||
char * c;
|
||||
for (c = class_name; *c; c++)
|
||||
if (*c == '.')
|
||||
*c = '/';
|
||||
}
|
||||
|
||||
/*
|
||||
* Classify an instance of java.lang.Class as either one of the primitive
|
||||
* types, e.g. int, char, etc., as an array type or as a non-array object type
|
||||
* (subclass of java.lang.Object) by returning the appropriate enum member.
|
||||
*
|
||||
*/
|
||||
static JavaSignatureChar
|
||||
get_signature_type(JSContext *cx, JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JavaSignatureChar type;
|
||||
const char *java_class_name;
|
||||
|
||||
/* Get UTF8 encoding of class name */
|
||||
java_class_name = class_descriptor->name;
|
||||
PR_ASSERT(java_class_name);
|
||||
if (!java_class_name)
|
||||
return JAVA_SIGNATURE_UNKNOWN;
|
||||
|
||||
if (!strcmp(java_class_name, "byte"))
|
||||
type = JAVA_SIGNATURE_BYTE;
|
||||
else if (!strcmp(java_class_name, "char"))
|
||||
type = JAVA_SIGNATURE_CHAR;
|
||||
else if (!strcmp(java_class_name, "float"))
|
||||
type = JAVA_SIGNATURE_FLOAT;
|
||||
else if (!strcmp(java_class_name, "double"))
|
||||
type = JAVA_SIGNATURE_DOUBLE;
|
||||
else if (!strcmp(java_class_name, "int"))
|
||||
type = JAVA_SIGNATURE_INT;
|
||||
else if (!strcmp(java_class_name, "long"))
|
||||
type = JAVA_SIGNATURE_LONG;
|
||||
else if (!strcmp(java_class_name, "short"))
|
||||
type = JAVA_SIGNATURE_SHORT;
|
||||
else if (!strcmp(java_class_name, "boolean"))
|
||||
type = JAVA_SIGNATURE_BOOLEAN;
|
||||
else if (!strcmp(java_class_name, "void"))
|
||||
type = JAVA_SIGNATURE_VOID;
|
||||
else
|
||||
/* Well, I guess it's a Java class, then. */
|
||||
type = JAVA_SIGNATURE_CLASS;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
is_java_array_class(JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
return (*jEnv)->CallBooleanMethod(jEnv, java_class, jlClass_isArray);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the class of a Java array's component type. This is not the same
|
||||
* as the array's element type. For example, the component type of an array
|
||||
* of type SomeType[][][] is SomeType[][], but its element type is SomeType.
|
||||
*
|
||||
* If an error occurs, NULL is returned and an error reported.
|
||||
*/
|
||||
static jclass
|
||||
get_java_array_component_class(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
jclass result;
|
||||
result = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getComponentType);
|
||||
if (!result) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't get Java array component class using "
|
||||
"java.lang.Class.getComponentType()");
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a Java class, fill in the signature structure that describes the class.
|
||||
* If an error occurs, JS_FALSE is returned and the error reporter called.
|
||||
*/
|
||||
static JSBool
|
||||
compute_java_class_signature(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature)
|
||||
{
|
||||
jclass java_class = signature->java_class;
|
||||
|
||||
if (is_java_array_class(jEnv, java_class)) {
|
||||
jclass component_class;
|
||||
|
||||
signature->type = JAVA_SIGNATURE_ARRAY;
|
||||
|
||||
component_class = get_java_array_component_class(cx, jEnv, java_class);
|
||||
if (!component_class)
|
||||
return JS_FALSE;
|
||||
|
||||
signature->array_component_signature =
|
||||
jsj_GetJavaClassDescriptor(cx, jEnv, component_class);
|
||||
if (!signature->array_component_signature)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
signature->type = get_signature_type(cx, signature);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a JavaSignature object into a string format as used by
|
||||
* the JNI functions, e.g. java.lang.Object ==> "Ljava/lang/Object;"
|
||||
* The caller is responsible for freeing the resulting string.
|
||||
*
|
||||
* If an error is encountered, NULL is returned and an error reported.
|
||||
*/
|
||||
const char *
|
||||
jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature)
|
||||
{
|
||||
char *sig;
|
||||
|
||||
if (signature->type == JAVA_SIGNATURE_CLASS) {
|
||||
/* A non-array object class */
|
||||
sig = PR_smprintf("L%s;", signature->name);
|
||||
if (sig)
|
||||
jsj_MakeJNIClassname(sig);
|
||||
|
||||
} else if (signature->type == JAVA_SIGNATURE_ARRAY) {
|
||||
/* An array class */
|
||||
const char *component_signature_string;
|
||||
|
||||
component_signature_string =
|
||||
jsj_ConvertJavaSignatureToString(cx, signature->array_component_signature);
|
||||
if (!component_signature_string)
|
||||
return NULL;
|
||||
sig = PR_smprintf("[%s", component_signature_string);
|
||||
JS_free(cx, (char*)component_signature_string);
|
||||
|
||||
} else {
|
||||
/* A primitive class */
|
||||
sig = PR_smprintf("%c", (char)signature->type);
|
||||
}
|
||||
|
||||
if (!sig) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a JavaSignature object into a human-readable string format as seen
|
||||
* in Java source files, e.g. "byte", or "int[][]" or "java.lang.String".
|
||||
* The caller is responsible for freeing the resulting string.
|
||||
*
|
||||
* If an error is encountered, NULL is returned and an error reported.
|
||||
*/
|
||||
const char *
|
||||
jsj_ConvertJavaSignatureToHRString(JSContext *cx,
|
||||
JavaSignature *signature)
|
||||
{
|
||||
char *sig;
|
||||
JavaSignature *acs;
|
||||
|
||||
if (signature->type == JAVA_SIGNATURE_ARRAY) {
|
||||
/* An array class */
|
||||
const char *component_signature_string;
|
||||
acs = signature->array_component_signature;
|
||||
component_signature_string =
|
||||
jsj_ConvertJavaSignatureToHRString(cx, acs);
|
||||
if (!component_signature_string)
|
||||
return NULL;
|
||||
sig = PR_smprintf("%s[]", component_signature_string);
|
||||
JS_free(cx, (char*)component_signature_string);
|
||||
|
||||
} else {
|
||||
/* A primitive class or a non-array object class */
|
||||
sig = JS_strdup(cx, signature->name);
|
||||
}
|
||||
|
||||
if (!sig) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_java_member_descriptor(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor)
|
||||
{
|
||||
JavaMethodSpec *method, *next_method;
|
||||
if (member_descriptor->field)
|
||||
jsj_DestroyFieldSpec(cx, jEnv, member_descriptor->field);
|
||||
|
||||
method = member_descriptor->methods;
|
||||
while (method) {
|
||||
next_method = method->next;
|
||||
jsj_DestroyMethodSpec(cx, jEnv, method);
|
||||
method = next_method;
|
||||
}
|
||||
|
||||
if (member_descriptor->invoke_func_obj)
|
||||
JS_RemoveRoot(cx, &member_descriptor->invoke_func_obj);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_class_member_descriptors(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor)
|
||||
{
|
||||
JavaMemberDescriptor *next_member;
|
||||
|
||||
while (member_descriptor) {
|
||||
next_member = member_descriptor->next;
|
||||
destroy_java_member_descriptor(cx, jEnv, member_descriptor);
|
||||
member_descriptor = next_member;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JS_FREE_IF(cx, (char *)class_descriptor->name);
|
||||
if (class_descriptor->java_class) {
|
||||
JSJ_HashTableRemove(java_class_reflections,
|
||||
class_descriptor->java_class, (void*)jEnv);
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, class_descriptor->java_class);
|
||||
}
|
||||
|
||||
if (class_descriptor->array_component_signature)
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor->array_component_signature);
|
||||
|
||||
destroy_class_member_descriptors(cx, jEnv, class_descriptor->instance_members);
|
||||
destroy_class_member_descriptors(cx, jEnv, class_descriptor->static_members);
|
||||
destroy_class_member_descriptors(cx, jEnv, class_descriptor->constructors);
|
||||
JS_free(cx, class_descriptor);
|
||||
}
|
||||
|
||||
static JavaClassDescriptor *
|
||||
new_class_descriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = (JavaClassDescriptor *)JS_malloc(cx, sizeof(JavaClassDescriptor));
|
||||
if (!class_descriptor)
|
||||
return NULL;
|
||||
memset(class_descriptor, 0, sizeof(JavaClassDescriptor));
|
||||
|
||||
class_descriptor->name = jsj_GetJavaClassName(cx, jEnv, java_class);
|
||||
if (!class_descriptor->name)
|
||||
goto error;
|
||||
|
||||
java_class = (*jEnv)->NewGlobalRef(jEnv, java_class);
|
||||
if (!java_class) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Unable to reference Java class");
|
||||
goto error;
|
||||
}
|
||||
class_descriptor->java_class = java_class;
|
||||
|
||||
if (!compute_java_class_signature(cx, jEnv, class_descriptor))
|
||||
goto error;
|
||||
|
||||
class_descriptor->modifiers =
|
||||
(*jEnv)->CallIntMethod(jEnv, java_class, jlClass_getModifiers);
|
||||
class_descriptor->ref_count = 1;
|
||||
|
||||
if (!JSJ_HashTableAdd(java_class_reflections, java_class, class_descriptor,
|
||||
(void*)jEnv))
|
||||
goto error;
|
||||
|
||||
return class_descriptor;
|
||||
|
||||
error:
|
||||
destroy_class_descriptor(cx, jEnv, class_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Trivial helper for jsj_DiscardJavaClassReflections(), below */
|
||||
static PRIntn
|
||||
enumerate_remove_java_class(JSJHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
JNIEnv *jEnv = (JNIEnv*)arg;
|
||||
jclass java_class;
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
|
||||
class_descriptor = (JavaClassDescriptor*)he->value;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
(*jEnv)->DeleteGlobalRef(jEnv, java_class);
|
||||
class_descriptor->java_class = NULL;
|
||||
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
/* This shutdown routine discards all JNI references to Java objects
|
||||
that have been reflected into JS, even if there are still references
|
||||
to them from JS. */
|
||||
void
|
||||
jsj_DiscardJavaClassReflections(JNIEnv *jEnv)
|
||||
{
|
||||
if (java_class_reflections) {
|
||||
JSJ_HashTableEnumerateEntries(java_class_reflections,
|
||||
enumerate_remove_java_class,
|
||||
(void*)jEnv);
|
||||
JSJ_HashTableDestroy(java_class_reflections);
|
||||
java_class_reflections = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern JavaClassDescriptor *
|
||||
jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class)
|
||||
{
|
||||
JavaClassDescriptor *class_descriptor;
|
||||
class_descriptor = JSJ_HashTableLookup(java_class_reflections,
|
||||
(const void *)java_class,
|
||||
(void*)jEnv);
|
||||
if (!class_descriptor)
|
||||
return new_class_descriptor(cx, jEnv, java_class);
|
||||
|
||||
PR_ASSERT(class_descriptor->ref_count > 0);
|
||||
class_descriptor->ref_count++;
|
||||
return class_descriptor;
|
||||
}
|
||||
|
||||
void
|
||||
jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!--class_descriptor->ref_count)
|
||||
destroy_class_descriptor(cx, jEnv, class_descriptor);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
reflect_java_methods_and_fields(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_statics_only)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
if (reflect_statics_only)
|
||||
class_descriptor->static_members_reflected = JS_TRUE;
|
||||
else
|
||||
class_descriptor->instance_members_reflected = JS_TRUE;
|
||||
|
||||
if (!jsj_ReflectJavaMethods(cx, jEnv, class_descriptor, reflect_statics_only))
|
||||
return JS_FALSE;
|
||||
if (!jsj_ReflectJavaFields(cx, jEnv, class_descriptor, reflect_statics_only))
|
||||
return JS_FALSE;
|
||||
|
||||
if (reflect_statics_only) {
|
||||
member_descriptor = class_descriptor->static_members;
|
||||
while (member_descriptor) {
|
||||
class_descriptor->num_static_members++;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
} else {
|
||||
member_descriptor = class_descriptor->instance_members;
|
||||
while (member_descriptor) {
|
||||
class_descriptor->num_instance_members++;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetClassStaticMembers(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!class_descriptor->static_members_reflected)
|
||||
reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE);
|
||||
return class_descriptor->static_members;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetClassInstanceMembers(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!class_descriptor->instance_members_reflected)
|
||||
reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_FALSE);
|
||||
return class_descriptor->instance_members;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor);
|
||||
while (member_descriptor) {
|
||||
if (id == member_descriptor->id)
|
||||
return member_descriptor;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetJavaStaticMemberDescriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name_jstr)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsid id;
|
||||
|
||||
if (!JavaStringToId(cx, jEnv, member_name_jstr, &id))
|
||||
return NULL;
|
||||
|
||||
member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (member_descriptor)
|
||||
return member_descriptor;
|
||||
|
||||
member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
|
||||
if (!member_descriptor)
|
||||
return NULL;
|
||||
memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));
|
||||
|
||||
member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr);
|
||||
if (!member_descriptor->name) {
|
||||
JS_free(cx, member_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
member_descriptor->id = id;
|
||||
|
||||
member_descriptor->next = class_descriptor->static_members;
|
||||
class_descriptor->static_members = member_descriptor;
|
||||
|
||||
return member_descriptor;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetJavaClassConstructors(JSContext *cx,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
if (class_descriptor->constructors)
|
||||
return class_descriptor->constructors;
|
||||
|
||||
member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
|
||||
if (!member_descriptor)
|
||||
return NULL;
|
||||
memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));
|
||||
|
||||
member_descriptor->name = JS_strdup(cx, "<init>");
|
||||
if (!member_descriptor->name) {
|
||||
JS_free(cx, member_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class_descriptor->constructors = member_descriptor;
|
||||
|
||||
return member_descriptor;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor)
|
||||
{
|
||||
if (!class_descriptor->static_members_reflected)
|
||||
reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE);
|
||||
return class_descriptor->constructors;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
|
||||
member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor);
|
||||
while (member_descriptor) {
|
||||
if (id == member_descriptor->id)
|
||||
return member_descriptor;
|
||||
member_descriptor = member_descriptor->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JavaMemberDescriptor *
|
||||
jsj_GetJavaMemberDescriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name_jstr)
|
||||
{
|
||||
JavaMemberDescriptor *member_descriptor;
|
||||
jsid id;
|
||||
|
||||
if (!JavaStringToId(cx, jEnv, member_name_jstr, &id))
|
||||
return NULL;
|
||||
|
||||
member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id);
|
||||
if (member_descriptor)
|
||||
return member_descriptor;
|
||||
|
||||
member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
|
||||
if (!member_descriptor)
|
||||
return NULL;
|
||||
memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));
|
||||
|
||||
member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr);
|
||||
if (!member_descriptor->name) {
|
||||
JS_free(cx, member_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
member_descriptor->id = id;
|
||||
|
||||
member_descriptor->next = class_descriptor->instance_members;
|
||||
class_descriptor->instance_members = member_descriptor;
|
||||
|
||||
return member_descriptor;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsj_InitJavaClassReflectionsTable()
|
||||
{
|
||||
java_class_reflections =
|
||||
JSJ_NewHashTable(64, jsj_HashJavaObject, jsj_JavaObjectComparator,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (!java_class_reflections)
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
806
mozilla/js/src/liveconnect/jsj_convert.c
Normal file
806
mozilla/js/src/liveconnect/jsj_convert.c
Normal file
@@ -0,0 +1,806 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* Below is the code that converts between Java and JavaScript values of all
|
||||
* types.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/* Floating-point double utilities, stolen from jsnum.h */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
|
||||
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
|
||||
#else
|
||||
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
|
||||
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
|
||||
#endif
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
|
||||
|
||||
#define JSDOUBLE_IS_NaN(x) \
|
||||
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
|
||||
(JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
|
||||
|
||||
#define JSDOUBLE_IS_INFINITE(x) \
|
||||
((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
|
||||
!JSDOUBLE_LO32(x))
|
||||
|
||||
static JSBool
|
||||
convert_js_obj_to_JSObject_wrapper(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj,
|
||||
JavaSignature *signature,
|
||||
int *cost, jobject *java_value)
|
||||
{
|
||||
if (!njJSObject) {
|
||||
if (java_value)
|
||||
JS_ReportError(cx, "Couldn't convert JavaScript object to an "
|
||||
"instance of netscape.javascript.JSObject "
|
||||
"because that class could not be loaded.");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!(*jEnv)->IsAssignableFrom(jEnv, njJSObject, signature->java_class))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!java_value)
|
||||
return JS_TRUE;
|
||||
|
||||
*java_value = jsj_WrapJSObject(cx, jEnv, js_obj);
|
||||
|
||||
return (*java_value != NULL);
|
||||
}
|
||||
|
||||
jstring
|
||||
jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str)
|
||||
{
|
||||
jstring result;
|
||||
result = (*jEnv)->NewString(jEnv, JS_GetStringChars(js_str),
|
||||
JS_GetStringLength(js_str));
|
||||
if (!result) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance "
|
||||
"of java.lang.String");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a JS value to an instance of java.lang.Object or one of its subclasses,
|
||||
* performing any necessary type coercion. If non-trivial coercion is required,
|
||||
* the cost value is incremented. If the java_value pass-by-reference argument
|
||||
* is non-NULL, the resulting Java value is stored there.
|
||||
*
|
||||
* Returns JS_TRUE if the conversion is possible, JS_FALSE otherwise
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jobject *java_value, JSBool *is_local_refp)
|
||||
{
|
||||
JSString *jsstr;
|
||||
jclass target_java_class;
|
||||
|
||||
PR_ASSERT(signature->type == JAVA_SIGNATURE_CLASS ||
|
||||
signature->type == JAVA_SIGNATURE_ARRAY);
|
||||
|
||||
/* Initialize to default case, in which no new Java object is
|
||||
synthesized to perform the conversion and, therefore, no JNI local
|
||||
references are being held. */
|
||||
*is_local_refp = JS_FALSE;
|
||||
|
||||
/* Get the Java type of the target value */
|
||||
target_java_class = signature->java_class;
|
||||
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
JSObject *js_obj = JSVAL_TO_OBJECT(v);
|
||||
|
||||
/* JS null is always assignable to a Java object */
|
||||
if (!js_obj) {
|
||||
if (java_value)
|
||||
*java_value = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0) ||
|
||||
JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) {
|
||||
|
||||
/* The source value is a Java object wrapped inside a JavaScript
|
||||
object. Unwrap the JS object and return the original Java
|
||||
object if it's class makes it assignment-compatible with the
|
||||
target class using Java's assignability rules. */
|
||||
JavaObjectWrapper *java_wrapper = JS_GetPrivate(cx, js_obj);
|
||||
jobject java_obj = java_wrapper->java_obj;
|
||||
|
||||
if ((*jEnv)->IsInstanceOf(jEnv, java_obj, target_java_class)) {
|
||||
if (java_value)
|
||||
*java_value = java_obj;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
/* Don't allow wrapped Java objects to be converted to strings */
|
||||
goto conversion_error;
|
||||
#else
|
||||
/* Fall through, to attempt conversion to a Java string */
|
||||
#endif
|
||||
|
||||
} else if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) {
|
||||
/* We're dealing with the reflection of a Java class */
|
||||
JavaClassDescriptor *java_class_descriptor = JS_GetPrivate(cx, js_obj);
|
||||
|
||||
/* Check if target type is java.lang.Class class */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlClass, target_java_class)) {
|
||||
if (java_value)
|
||||
*java_value = java_class_descriptor->java_class;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Check if target type is netscape.javascript.JSObject wrapper class */
|
||||
if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) {
|
||||
if (*java_value)
|
||||
*is_local_refp = JS_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through, to attempt conversion to a Java string */
|
||||
|
||||
} else if (JS_InstanceOf(cx, js_obj, &JavaMember_class, 0)) {
|
||||
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_OBJECT, &v))
|
||||
return JS_FALSE;
|
||||
return jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost,
|
||||
java_value, is_local_refp);
|
||||
|
||||
} else {
|
||||
/* Otherwise, see if the target type is the netscape.javascript.JSObject
|
||||
wrapper class or one of its subclasses, in which case a
|
||||
reference is passed to the original JS object by wrapping it
|
||||
inside an instance of netscape.javascript.JSObject */
|
||||
if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Fall through, to attempt conversion to a Java string */
|
||||
}
|
||||
|
||||
} else if (JSVAL_IS_NUMBER(v)) {
|
||||
/* JS numbers, integral or not, can be converted to instances of java.lang.Double */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlDouble, target_java_class)) {
|
||||
if (java_value) {
|
||||
jsdouble d;
|
||||
if (!JS_ValueToNumber(cx, v, &d))
|
||||
goto conversion_error;
|
||||
*java_value = (*jEnv)->NewObject(jEnv, jlDouble, jlDouble_Double, d);
|
||||
if (*java_value) {
|
||||
*is_local_refp = JS_TRUE;
|
||||
} else {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Couldn't construct instance of java.lang.Double");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
(*cost)++;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* Fall through, to attempt conversion to a java.lang.String ... */
|
||||
|
||||
} else if (JSVAL_IS_BOOLEAN(v)) {
|
||||
/* JS boolean values can be converted to instances of java.lang.Boolean */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlBoolean, target_java_class)) {
|
||||
if (java_value) {
|
||||
JSBool b;
|
||||
if (!JS_ValueToBoolean(cx, v, &b))
|
||||
goto conversion_error;
|
||||
*java_value =
|
||||
(*jEnv)->NewObject(jEnv, jlBoolean, jlBoolean_Boolean, b);
|
||||
if (*java_value) {
|
||||
*is_local_refp = JS_TRUE;
|
||||
} else {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance "
|
||||
"of java.lang.Boolean");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
(*cost)++;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* Fall through, to attempt conversion to a java.lang.String ... */
|
||||
}
|
||||
|
||||
/* If no other conversion is possible, see if the target type is java.lang.String */
|
||||
if ((*jEnv)->IsAssignableFrom(jEnv, jlString, target_java_class)) {
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
JSBool is_string = JSVAL_IS_STRING(v);
|
||||
#endif
|
||||
|
||||
/* Convert to JS string, if necessary, and then to a Java Unicode string */
|
||||
jsstr = JS_ValueToString(cx, v);
|
||||
if (jsstr) {
|
||||
if (java_value) {
|
||||
*java_value = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr);
|
||||
if (*java_value) {
|
||||
*is_local_refp = JS_TRUE;
|
||||
} else {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
if (!is_string)
|
||||
(*cost)++;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
conversion_error:
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Valid ranges for Java numeric types */
|
||||
#define jbyte_MAX_VALUE 127.0
|
||||
#define jbyte_MIN_VALUE -128.0
|
||||
#define jchar_MAX_VALUE 65535.0
|
||||
#define jchar_MIN_VALUE 0.0
|
||||
#define jshort_MAX_VALUE 32767.0
|
||||
#define jshort_MIN_VALUE -32768.0
|
||||
#define jint_MAX_VALUE 2147483647.0
|
||||
#define jint_MIN_VALUE -2147483648.0
|
||||
#define jlong_MAX_VALUE 9223372036854775807.0
|
||||
#define jlong_MIN_VALUE -9223372036854775808.0
|
||||
|
||||
/* Utility macro for jsj_ConvertJSValueToJavaValue(), below */
|
||||
#define JSVAL_TO_INTEGRAL_JVALUE(type_name, member_name, member_type, jsval, java_value) \
|
||||
if (!JSVAL_IS_NUMBER(v)) { \
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) \
|
||||
goto conversion_error; \
|
||||
(*cost)++; \
|
||||
} \
|
||||
{ \
|
||||
member_type member_name; \
|
||||
\
|
||||
if (JSVAL_IS_INT(v)) { \
|
||||
jsint ival = JSVAL_TO_INT(v); \
|
||||
member_name = (member_type) ival; \
|
||||
\
|
||||
/* Check to see if the jsval's magnitude is too large to be \
|
||||
representable in the target java type */ \
|
||||
if (member_name != ival) \
|
||||
goto numeric_conversion_error; \
|
||||
} else { \
|
||||
jdouble dval = *JSVAL_TO_DOUBLE(v); \
|
||||
\
|
||||
/* NaN becomes zero when converted to integral value */ \
|
||||
if (JSDOUBLE_IS_NaN(dval)) \
|
||||
member_name = 0; \
|
||||
\
|
||||
/* Unrepresentably large numbers, including infinities, */ \
|
||||
/* cause an error. */ \
|
||||
else if ((dval > member_type ## _MAX_VALUE) || \
|
||||
(dval < member_type ## _MIN_VALUE)) { \
|
||||
goto numeric_conversion_error; \
|
||||
} else \
|
||||
member_name = (member_type) dval; \
|
||||
\
|
||||
/* Don't allow a non-integral number to be converted \
|
||||
to an integral type */ \
|
||||
/* Actually, we have to allow this for LC1 compatibility */ \
|
||||
/* if ((jdouble)member_name != dval) \
|
||||
(*cost)++; */ \
|
||||
} \
|
||||
if (java_value) \
|
||||
java_value->member_name = member_name; \
|
||||
}
|
||||
|
||||
#if XP_MAC
|
||||
|
||||
/* on MRJ jlong is typedef'd to wide, which is a struct. */
|
||||
#include <Math64.h>
|
||||
|
||||
static jsint jlong_to_jsint(jlong lvalue)
|
||||
{
|
||||
SInt64 val = WideToSInt64(lvalue);
|
||||
return S32Set(val);
|
||||
}
|
||||
|
||||
static jlong jsint_to_jlong(jsint ivalue)
|
||||
{
|
||||
SInt64 val = S64Set(ivalue);
|
||||
wide wval =SInt64ToWide(val);
|
||||
return *(jlong*)&wval;
|
||||
}
|
||||
|
||||
static jdouble jlong_to_jdouble(jlong lvalue)
|
||||
{
|
||||
SInt64 val = WideToSInt64(lvalue);
|
||||
return SInt64ToLongDouble(val);
|
||||
}
|
||||
|
||||
static jlong jdouble_to_jlong(jdouble dvalue)
|
||||
{
|
||||
SInt64 val = LongDoubleToSInt64(dvalue);
|
||||
wide wval = SInt64ToWide(val);
|
||||
return *(jlong*)&wval;
|
||||
}
|
||||
|
||||
/* Mac utility macro for jsj_ConvertJSValueToJavaValue(), below */
|
||||
#define JSVAL_TO_JLONG_JVALUE(member_name, member_type, jsvalue, java_value) \
|
||||
if (!JSVAL_IS_NUMBER(jsvalue)) { \
|
||||
if (!JS_ConvertValue(cx, jsvalue, JSTYPE_NUMBER, &jsvalue)) \
|
||||
goto conversion_error; \
|
||||
(*cost)++; \
|
||||
} \
|
||||
{ \
|
||||
member_type member_name; \
|
||||
\
|
||||
if (JSVAL_IS_INT(jsvalue)) { \
|
||||
jsint ival = JSVAL_TO_INT(jsvalue); \
|
||||
member_name = jsint_to_jlong(ival); \
|
||||
\
|
||||
} else { \
|
||||
jdouble dval = *JSVAL_TO_DOUBLE(jsvalue); \
|
||||
\
|
||||
/* NaN becomes zero when converted to integral value */ \
|
||||
if (JSDOUBLE_IS_NaN(dval)) \
|
||||
member_name = jsint_to_jlong(0); \
|
||||
\
|
||||
/* Unrepresentably large numbers, including infinities, */ \
|
||||
/* cause an error. */ \
|
||||
else if ((dval > member_type ## _MAX_VALUE) || \
|
||||
(dval < member_type ## _MIN_VALUE)) { \
|
||||
goto numeric_conversion_error; \
|
||||
} else \
|
||||
member_name = jdouble_to_jlong(dval); \
|
||||
\
|
||||
/* Don't allow a non-integral number to be converted \
|
||||
to an integral type */ \
|
||||
/* Actually, we have to allow this for LC1 compatibility */ \
|
||||
/*if (jlong_to_jdouble(member_name) != dval) \
|
||||
(*cost)++;*/ \
|
||||
} \
|
||||
if (java_value) \
|
||||
java_value->member_name = member_name; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define jlong_to_jdouble(lvalue) ((jdouble) lvalue)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert a JS value to a Java value of the given type signature. The cost
|
||||
* variable is incremented if coercion is required, e.g. the source value is
|
||||
* a string, but the target type is a boolean.
|
||||
*
|
||||
* Returns JS_FALSE if no conversion is possible, either because the jsval has
|
||||
* a type that is wholly incompatible with the Java value, or because a scalar
|
||||
* jsval can't be represented in a variable of the target type without loss of
|
||||
* precision, e.g. the source value is "4.2" but the destination type is byte.
|
||||
* If conversion is not possible and java_value is non-NULL, the JS error
|
||||
* reporter is called with an appropriate message.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v,
|
||||
JavaSignature *signature,
|
||||
int *cost, jvalue *java_value, JSBool *is_local_refp)
|
||||
{
|
||||
JavaSignatureChar type;
|
||||
JSBool success = JS_FALSE;
|
||||
|
||||
/* Initialize to default case, in which no new Java object is
|
||||
synthesized to perform the conversion and, therefore, no JNI local
|
||||
references are being held. */
|
||||
*is_local_refp = JS_FALSE;
|
||||
|
||||
type = signature->type;
|
||||
switch (type) {
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
if (!JSVAL_IS_BOOLEAN(v)) {
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v))
|
||||
goto conversion_error;
|
||||
(*cost)++;
|
||||
}
|
||||
if (java_value)
|
||||
java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
/* A one-character string can be converted into a character */
|
||||
if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) {
|
||||
v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v)));
|
||||
}
|
||||
JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
#if XP_MAC
|
||||
JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value);
|
||||
#else
|
||||
JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
if (!JSVAL_IS_NUMBER(v)) {
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v))
|
||||
goto conversion_error;
|
||||
(*cost)++;
|
||||
}
|
||||
if (java_value) {
|
||||
if (JSVAL_IS_INT(v))
|
||||
java_value->f = (jfloat) JSVAL_TO_INT(v);
|
||||
else
|
||||
java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
if (!JSVAL_IS_NUMBER(v)) {
|
||||
if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v))
|
||||
goto conversion_error;
|
||||
(*cost)++;
|
||||
}
|
||||
if (java_value) {
|
||||
if (JSVAL_IS_INT(v))
|
||||
java_value->d = (jdouble) JSVAL_TO_INT(v);
|
||||
else
|
||||
java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost,
|
||||
&java_value->l, is_local_refp))
|
||||
goto conversion_error;
|
||||
break;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return JS_TRUE;
|
||||
|
||||
numeric_conversion_error:
|
||||
success = JS_TRUE;
|
||||
/* Fall through ... */
|
||||
|
||||
conversion_error:
|
||||
|
||||
if (java_value) {
|
||||
const char *jsval_string;
|
||||
JSString *jsstr;
|
||||
|
||||
jsval_string = NULL;
|
||||
jsstr = JS_ValueToString(cx, v);
|
||||
if (jsstr)
|
||||
jsval_string = JS_GetStringBytes(jsstr);
|
||||
if (!jsval_string)
|
||||
jsval_string = "";
|
||||
|
||||
JS_ReportError(cx, "Unable to convert JavaScript value %s to "
|
||||
"Java value of type %s",
|
||||
jsval_string, signature->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* A utility routine to create a JavaScript Unicode string from a
|
||||
* java.lang.String (Unicode) string.
|
||||
*/
|
||||
JSString *
|
||||
jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str)
|
||||
{
|
||||
JSString *js_str;
|
||||
jboolean is_copy;
|
||||
const jchar *ucs2_str;
|
||||
jchar *copy_ucs2_str;
|
||||
jsize ucs2_str_len, num_bytes;
|
||||
|
||||
ucs2_str_len = (*jEnv)->GetStringLength(jEnv, java_str);
|
||||
ucs2_str = (*jEnv)->GetStringChars(jEnv, java_str, &is_copy);
|
||||
if (!ucs2_str) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Unable to extract native Unicode from Java string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js_str = NULL;
|
||||
|
||||
/* The string data passed into JS_NewUCString() is
|
||||
not copied, so make a copy of the Unicode character vector. */
|
||||
num_bytes = ucs2_str_len * sizeof(jchar);
|
||||
copy_ucs2_str = (jchar*)JS_malloc(cx, num_bytes);
|
||||
if (!copy_ucs2_str)
|
||||
goto done;
|
||||
memcpy(copy_ucs2_str, ucs2_str, num_bytes);
|
||||
|
||||
js_str = JS_NewUCString(cx, (jschar*)copy_ucs2_str, ucs2_str_len);
|
||||
|
||||
done:
|
||||
(*jEnv)->ReleaseStringChars(jEnv, java_str, ucs2_str);
|
||||
return js_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to obtain a JS string representation of a Java object.
|
||||
* The java_obj argument must be of type java.lang.Object or a subclass.
|
||||
* If java_obj is a Java string, it's value is simply extracted and
|
||||
* copied into a JS string. Otherwise, the toString() method is called
|
||||
* on java_obj.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaObjectToJSString(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
JSString *js_str;
|
||||
jstring java_str;
|
||||
jmethodID toString;
|
||||
|
||||
/* Create a Java string, unless java_obj is already a java.lang.String */
|
||||
if ((*jEnv)->IsInstanceOf(jEnv, java_obj, jlString)) {
|
||||
java_str = java_obj;
|
||||
} else {
|
||||
jclass java_class;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
toString = (*jEnv)->GetMethodID(jEnv, java_class, "toString",
|
||||
"()Ljava/lang/String;");
|
||||
if (!toString) {
|
||||
/* All Java objects have a toString method */
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "No toString() method for class %s!",
|
||||
class_descriptor->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
java_str = (*jEnv)->CallObjectMethod(jEnv, java_obj, toString);
|
||||
if (!java_str) {
|
||||
jsj_ReportJavaError(cx, jEnv, "toString() method failed");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract Unicode from java.lang.String instance and convert to JS string */
|
||||
js_str = jsj_ConvertJavaStringToJSString(cx, jEnv, java_str);
|
||||
if (!js_str)
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = STRING_TO_JSVAL(js_str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a Java object to a number by attempting to call the
|
||||
* doubleValue() method on a Java object to get a double result.
|
||||
* This usually only works on instances of java.lang.Double, but the code
|
||||
* is generalized to work with any Java object that supports this method.
|
||||
*
|
||||
* Returns JS_TRUE if the call was successful.
|
||||
* Returns JS_FALSE if conversion is not possible or an error occurs.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
jdouble d;
|
||||
jmethodID doubleValue;
|
||||
jclass java_class;
|
||||
|
||||
java_class = class_descriptor->java_class;
|
||||
doubleValue = (*jEnv)->GetMethodID(jEnv, java_class, "doubleValue", "()D");
|
||||
if (!doubleValue) {
|
||||
/* There is no doubleValue() method for the object. Try toString()
|
||||
instead and the JS engine will attempt to convert the result to
|
||||
a number. */
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
return jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor,
|
||||
java_obj, vp);
|
||||
}
|
||||
|
||||
d = (*jEnv)->CallDoubleMethod(jEnv, java_obj, doubleValue);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "doubleValue() method failed");
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_NewDoubleValue(cx, d, vp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a Java object to a boolean by attempting to call the
|
||||
* booleanValue() method on a Java object to get a boolean result.
|
||||
* This usually only works on instances of java.lang.Boolean, but the code
|
||||
* is generalized to work with any Java object that supports this method.
|
||||
*
|
||||
* Returns JS_TRUE if the call was successful.
|
||||
* Returns JS_FALSE if conversion is not possible or an error occurs.
|
||||
*/
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
jboolean b;
|
||||
jmethodID booleanValue;
|
||||
jclass java_class;
|
||||
|
||||
/* Null converts to false. */
|
||||
if (!java_obj) {
|
||||
*vp = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
java_class = class_descriptor->java_class;
|
||||
booleanValue = (*jEnv)->GetMethodID(jEnv, java_obj, "booleanValue", "()Z");
|
||||
|
||||
/* Non-null Java object does not have a booleanValue() method, so
|
||||
it converts to true. */
|
||||
if (!booleanValue) {
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
*vp = JSVAL_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
b = (*jEnv)->CallBooleanMethod(jEnv, java_obj, booleanValue);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "booleanValue() method failed");
|
||||
return JS_FALSE;
|
||||
}
|
||||
*vp = BOOLEAN_TO_JSVAL(b);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reflect a Java object into a JS value. The source object, java_obj, must
|
||||
* be of type java.lang.Object or a subclass and may, therefore, be an array.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
jclass java_class;
|
||||
JSObject *js_obj;
|
||||
|
||||
/* A null in Java-land is also null in JS */
|
||||
if (!java_obj) {
|
||||
*vp = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
java_class = (*jEnv)->GetObjectClass(jEnv, java_obj);
|
||||
|
||||
/*
|
||||
* If it's an instance of netscape.javascript.JSObject, i.e. a wrapper
|
||||
* around a JS object that has been passed into the Java world, unwrap
|
||||
* it to obtain the original JS object.
|
||||
*/
|
||||
if (njJSObject && (*jEnv)->IsInstanceOf(jEnv, java_obj, njJSObject)) {
|
||||
#ifdef PRESERVE_JSOBJECT_IDENTITY
|
||||
js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_obj, njJSObject_internal));
|
||||
#else
|
||||
js_obj = jsj_UnwrapJSObjectWrapper(jEnv, java_obj);
|
||||
#endif
|
||||
PR_ASSERT(js_obj);
|
||||
if (!js_obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(js_obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Instances of java.lang.String are wrapped so we can call methods on
|
||||
* them, but they convert to a JS string if used in a string context.
|
||||
*/
|
||||
/* TODO - let's get rid of this annoying "feature" */
|
||||
|
||||
/* otherwise, wrap it inside a JavaObject */
|
||||
js_obj = jsj_WrapJavaObject(cx, jEnv, java_obj, java_class);
|
||||
if (!js_obj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(js_obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a Java value (primitive or object) to a JS value.
|
||||
*
|
||||
* This is usually an infallible operation, but JS_FALSE is returned
|
||||
* on an out-of-memory condition and the error reporter is called.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaSignature *signature,
|
||||
jvalue *java_value,
|
||||
jsval *vp)
|
||||
{
|
||||
int32 ival32;
|
||||
|
||||
switch (signature->type) {
|
||||
case JAVA_SIGNATURE_VOID:
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
*vp = INT_TO_JSVAL((jsint)java_value->b);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
*vp = INT_TO_JSVAL((jsint)java_value->c);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
*vp = INT_TO_JSVAL((jsint)java_value->s);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
ival32 = java_value->i;
|
||||
if (INT_FITS_IN_JSVAL(ival32)) {
|
||||
*vp = INT_TO_JSVAL((jsint) ival32);
|
||||
return JS_TRUE;
|
||||
} else {
|
||||
return JS_NewDoubleValue(cx, ival32, vp);
|
||||
}
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
*vp = BOOLEAN_TO_JSVAL((JSBool) java_value->z);
|
||||
return JS_TRUE;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
return JS_NewDoubleValue(cx, jlong_to_jdouble(java_value->j), vp);
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
return JS_NewDoubleValue(cx, java_value->f, vp);
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
return JS_NewDoubleValue(cx, java_value->d, vp);
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_value->l, vp);
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
383
mozilla/js/src/liveconnect/jsj_field.c
Normal file
383
mozilla/js/src/liveconnect/jsj_field.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the code used to reflect Java fields as properties of
|
||||
* JavaObject objects and the code to access those fields.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
|
||||
/*
|
||||
* Add a single field, described by java_field, to the JavaMemberDescriptor
|
||||
* named by field_name within the given JavaClassDescriptor.
|
||||
*
|
||||
* Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error.
|
||||
*/
|
||||
static JSBool
|
||||
add_java_field_to_class_descriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring field_name_jstr,
|
||||
jobject java_field, /* a java.lang.reflect.Field */
|
||||
jint modifiers)
|
||||
{
|
||||
jclass fieldType;
|
||||
jfieldID fieldID;
|
||||
jclass java_class;
|
||||
|
||||
JSBool is_static_field;
|
||||
JavaMemberDescriptor *member_descriptor = NULL;
|
||||
const char *sig_cstr = NULL;
|
||||
const char *field_name = NULL;
|
||||
JavaSignature *signature = NULL;
|
||||
JavaFieldSpec *field_spec = NULL;
|
||||
|
||||
is_static_field = modifiers & ACC_STATIC;
|
||||
if (is_static_field) {
|
||||
member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr);
|
||||
} else {
|
||||
member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr);
|
||||
}
|
||||
if (!member_descriptor)
|
||||
goto error;
|
||||
|
||||
field_spec = (JavaFieldSpec*)JS_malloc(cx, sizeof(JavaFieldSpec));
|
||||
if (!field_spec)
|
||||
goto error;
|
||||
|
||||
field_spec->modifiers = modifiers;
|
||||
|
||||
/* Get the Java class corresponding to the type of the field */
|
||||
fieldType = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getType);
|
||||
if (!fieldType) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Unable to determine type of field using"
|
||||
" java.lang.reflect.Field.getType()");
|
||||
goto error;
|
||||
}
|
||||
|
||||
signature = jsj_GetJavaClassDescriptor(cx, jEnv, fieldType);
|
||||
if (!signature)
|
||||
goto error;
|
||||
field_spec->signature = signature;
|
||||
|
||||
field_name = jsj_DupJavaStringUTF(cx, jEnv, field_name_jstr);
|
||||
if (!field_name)
|
||||
goto error;
|
||||
field_spec->name = field_name;
|
||||
|
||||
/* Compute the JNI-style (string-based) signature of the field type */
|
||||
sig_cstr = jsj_ConvertJavaSignatureToString(cx, signature);
|
||||
if (!sig_cstr)
|
||||
goto error;
|
||||
|
||||
/* Compute the JNI fieldID and cache it for quick field access */
|
||||
java_class = class_descriptor->java_class;
|
||||
if (is_static_field)
|
||||
fieldID = (*jEnv)->GetStaticFieldID(jEnv, java_class, field_name, sig_cstr);
|
||||
else
|
||||
fieldID = (*jEnv)->GetFieldID(jEnv, java_class, field_name, sig_cstr);
|
||||
if (!fieldID) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't get Java field ID for class %s, field %s (sig=%s)",
|
||||
class_descriptor->name, field_name, sig_cstr);
|
||||
goto error;
|
||||
}
|
||||
field_spec->fieldID = fieldID;
|
||||
|
||||
JS_free(cx, (char*)sig_cstr);
|
||||
|
||||
member_descriptor->field = field_spec;
|
||||
|
||||
/* Success */
|
||||
return JS_TRUE;
|
||||
|
||||
error:
|
||||
if (field_spec) {
|
||||
JS_FREE_IF(cx, (char*)field_spec->name);
|
||||
JS_free(cx, field_spec);
|
||||
}
|
||||
JS_FREE_IF(cx, (char*)sig_cstr);
|
||||
if (signature)
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, signature);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up a JavaFieldSpec and all its resources.
|
||||
*/
|
||||
void
|
||||
jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field)
|
||||
{
|
||||
JS_FREE_IF(cx, (char*)field->name);
|
||||
jsj_ReleaseJavaClassDescriptor(cx, jEnv, field->signature);
|
||||
JS_free(cx, field);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a JavaMemberDescriptor to the collection of members in class_descriptor
|
||||
* for every public field of the identified Java class. (A separate collection
|
||||
* is kept in class_descriptor for static and instance members.)
|
||||
* If reflect_only_static_fields is set, instance fields are not reflected. If
|
||||
* it isn't set, only instance fields are reflected and static fields are not
|
||||
* reflected.
|
||||
*
|
||||
* Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error.
|
||||
*/
|
||||
JSBool
|
||||
jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_static_fields)
|
||||
{
|
||||
int i;
|
||||
JSBool ok;
|
||||
jint modifiers;
|
||||
jobject java_field;
|
||||
jstring field_name_jstr;
|
||||
jarray joFieldArray;
|
||||
jsize num_fields;
|
||||
jclass java_class;
|
||||
|
||||
/* Get a java array of java.lang.reflect.Field objects, by calling
|
||||
java.lang.Class.getFields(). */
|
||||
java_class = class_descriptor->java_class;
|
||||
joFieldArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getFields);
|
||||
if (!joFieldArray) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't determine Java object's fields "
|
||||
"using java.lang.Class.getFields()");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Iterate over the class fields */
|
||||
num_fields = (*jEnv)->GetArrayLength(jEnv, joFieldArray);
|
||||
for (i = 0; i < num_fields; i++) {
|
||||
|
||||
/* Get the i'th reflected field */
|
||||
java_field = (*jEnv)->GetObjectArrayElement(jEnv, joFieldArray, i);
|
||||
if (!java_field) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Can't access a Field[] array");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Get the field modifiers, e.g. static, public, private, etc. */
|
||||
modifiers = (*jEnv)->CallIntMethod(jEnv, java_field, jlrField_getModifiers);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't access a Field's modifiers using"
|
||||
"java.lang.reflect.Field.getModifiers()");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Don't allow access to private or protected Java fields. */
|
||||
if (!(modifiers & ACC_PUBLIC))
|
||||
continue;
|
||||
|
||||
/* Reflect all instance fields or all static fields, but not both */
|
||||
if (reflect_only_static_fields != ((modifiers & ACC_STATIC) != 0))
|
||||
continue;
|
||||
|
||||
/* Determine the unqualified name of the field */
|
||||
field_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getName);
|
||||
if (!field_name_jstr) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv,
|
||||
"Can't obtain a Field's name"
|
||||
"java.lang.reflect.Field.getName()");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Add a JavaFieldSpec object to the JavaClassDescriptor */
|
||||
ok = add_java_field_to_class_descriptor(cx, jEnv, class_descriptor, field_name_jstr,
|
||||
java_field, modifiers);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the value of a Java field and return it as a JavaScript value.
|
||||
* If the field is static, then java_obj is a Java class, otherwise
|
||||
* it's a Java instance object.
|
||||
*
|
||||
* Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error.
|
||||
*/
|
||||
JSBool
|
||||
jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jobject java_obj, jsval *vp)
|
||||
{
|
||||
JSBool is_static_field;
|
||||
jvalue java_value;
|
||||
JavaSignature *signature;
|
||||
JavaSignatureChar field_type;
|
||||
jfieldID fieldID = field_spec->fieldID;
|
||||
|
||||
is_static_field = field_spec->modifiers & ACC_STATIC;
|
||||
|
||||
#define GET_JAVA_FIELD(Type,member) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (is_static_field) \
|
||||
java_value.member = \
|
||||
(*jEnv)->GetStatic##Type##Field(jEnv, java_obj, fieldID); \
|
||||
else \
|
||||
java_value.member = \
|
||||
(*jEnv)->Get##Type##Field(jEnv, java_obj, fieldID); \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Error reading Java field"); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
signature = field_spec->signature;
|
||||
field_type = signature->type;
|
||||
switch(field_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
GET_JAVA_FIELD(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
GET_JAVA_FIELD(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
GET_JAVA_FIELD(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
GET_JAVA_FIELD(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
GET_JAVA_FIELD(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
GET_JAVA_FIELD(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
GET_JAVA_FIELD(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
GET_JAVA_FIELD(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
GET_JAVA_FIELD(Object,l);
|
||||
break;
|
||||
|
||||
#undef GET_JAVA_FIELD
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return jsj_ConvertJavaValueToJSValue(cx, jEnv, signature, &java_value, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jclass java_obj, jsval js_val)
|
||||
{
|
||||
JSBool is_static_field, is_local_ref;
|
||||
int dummy_cost;
|
||||
jvalue java_value;
|
||||
JavaSignature *signature;
|
||||
JavaSignatureChar field_type;
|
||||
jfieldID fieldID = field_spec->fieldID;
|
||||
|
||||
is_static_field = field_spec->modifiers & ACC_STATIC;
|
||||
|
||||
#define SET_JAVA_FIELD(Type,member) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (is_static_field) { \
|
||||
(*jEnv)->SetStatic##Type##Field(jEnv, java_obj, fieldID, \
|
||||
java_value.member); \
|
||||
} else { \
|
||||
(*jEnv)->Set##Type##Field(jEnv, java_obj, fieldID,java_value.member);\
|
||||
} \
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) { \
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Error assigning to Java field"); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
signature = field_spec->signature;
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, signature, &dummy_cost,
|
||||
&java_value, &is_local_ref))
|
||||
return JS_FALSE;
|
||||
|
||||
field_type = signature->type;
|
||||
switch(field_type) {
|
||||
case JAVA_SIGNATURE_BYTE:
|
||||
SET_JAVA_FIELD(Byte,b);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CHAR:
|
||||
SET_JAVA_FIELD(Char,c);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_SHORT:
|
||||
SET_JAVA_FIELD(Short,s);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_INT:
|
||||
SET_JAVA_FIELD(Int,i);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_BOOLEAN:
|
||||
SET_JAVA_FIELD(Boolean,z);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_LONG:
|
||||
SET_JAVA_FIELD(Long,j);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_FLOAT:
|
||||
SET_JAVA_FIELD(Float,f);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_DOUBLE:
|
||||
SET_JAVA_FIELD(Double,d);
|
||||
break;
|
||||
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
SET_JAVA_FIELD(Object,l);
|
||||
if (is_local_ref)
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_value.l);
|
||||
break;
|
||||
|
||||
#undef SET_JAVA_FIELD
|
||||
default:
|
||||
PR_ASSERT(0); /* Unknown java type signature */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
487
mozilla/js/src/liveconnect/jsj_hash.c
Normal file
487
mozilla/js/src/liveconnect/jsj_hash.c
Normal file
@@ -0,0 +1,487 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a copy of the NSPR hash-table library, but it has been slightly
|
||||
* modified to allow an additional argument to be passed into the hash
|
||||
* key-comparision function. This is used to maintain thread-safety by
|
||||
* passing in a JNIEnv pointer to the key-comparison function rather
|
||||
* than storing it in a global. All types,function names, etc. have
|
||||
* been renamed from their original NSPR names to protect the innocent.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_hash.h"
|
||||
#include "prtypes.h"
|
||||
#ifdef NSPR20
|
||||
# include "prlog.h"
|
||||
# include "prbit.h"
|
||||
#else
|
||||
# include "prassert.h"
|
||||
#endif
|
||||
|
||||
/* Compute the number of buckets in ht */
|
||||
#define NBUCKETS(ht) (1 << (JSJ_HASH_BITS - (ht)->shift))
|
||||
|
||||
/* The smallest table has 16 buckets */
|
||||
#define MINBUCKETSLOG2 4
|
||||
#define MINBUCKETS (1 << MINBUCKETSLOG2)
|
||||
|
||||
/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
|
||||
#define OVERLOADED(n) ((n) - ((n) >> 3))
|
||||
|
||||
/* Compute the number of entries below which we shrink the table by half */
|
||||
#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
|
||||
|
||||
/*
|
||||
** Stubs for default hash allocator ops.
|
||||
*/
|
||||
static void *
|
||||
DefaultAllocTable(void *pool, size_t size)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeTable(void *pool, void *item)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
free(item);
|
||||
}
|
||||
|
||||
static JSJHashEntry *
|
||||
DefaultAllocEntry(void *pool, const void *key)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool,key)
|
||||
#endif
|
||||
|
||||
return malloc(sizeof(JSJHashEntry));
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeEntry(void *pool, JSJHashEntry *he, PRUintn flag)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
free(he);
|
||||
}
|
||||
|
||||
static JSJHashAllocOps defaultHashAllocOps = {
|
||||
DefaultAllocTable, DefaultFreeTable,
|
||||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
PR_IMPLEMENT(JSJHashTable *)
|
||||
JSJ_NewHashTable(PRUint32 n, JSJHashFunction keyHash,
|
||||
JSJHashComparator keyCompare, JSJHashComparator valueCompare,
|
||||
JSJHashAllocOps *allocOps, void *allocPriv)
|
||||
{
|
||||
JSJHashTable *ht;
|
||||
PRUint32 nb;
|
||||
|
||||
if (n <= MINBUCKETS) {
|
||||
n = MINBUCKETSLOG2;
|
||||
} else {
|
||||
n = PR_CeilingLog2(n);
|
||||
if ((PRInt32)n < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!allocOps) allocOps = &defaultHashAllocOps;
|
||||
|
||||
ht = (*allocOps->allocTable)(allocPriv, sizeof *ht);
|
||||
if (!ht)
|
||||
return 0;
|
||||
memset(ht, 0, sizeof *ht);
|
||||
ht->shift = JSJ_HASH_BITS - n;
|
||||
n = 1 << n;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (n > 16000) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
nb = n * sizeof(JSJHashEntry *);
|
||||
ht->buckets = (*allocOps->allocTable)(allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
ht->keyHash = keyHash;
|
||||
ht->keyCompare = keyCompare;
|
||||
ht->valueCompare = valueCompare;
|
||||
ht->allocOps = allocOps;
|
||||
ht->allocPriv = allocPriv;
|
||||
return ht;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_HashTableDestroy(JSJHashTable *ht)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
JSJHashEntry *he, *next;
|
||||
JSJHashAllocOps *allocOps = ht->allocOps;
|
||||
void *allocPriv = ht->allocPriv;
|
||||
|
||||
n = NBUCKETS(ht);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = ht->buckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
(*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht->buckets);
|
||||
#ifdef DEBUG
|
||||
memset(ht, 0xDB, sizeof *ht);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
}
|
||||
|
||||
/*
|
||||
** Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
#define GOLDEN_RATIO 0x9E3779B9U
|
||||
|
||||
PR_IMPLEMENT(JSJHashEntry **)
|
||||
JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg)
|
||||
{
|
||||
JSJHashEntry *he, **hep, **hep0;
|
||||
JSJHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = hep0 = &ht->buckets[h];
|
||||
while ((he = *hep) != 0) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key, arg)) {
|
||||
/* Move to front of chain if not already there */
|
||||
if (hep != hep0) {
|
||||
*hep = he->next;
|
||||
he->next = *hep0;
|
||||
*hep0 = he;
|
||||
}
|
||||
return hep0;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJHashEntry *)
|
||||
JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep,
|
||||
JSJHashNumber keyHash, const void *key, void *value,
|
||||
void *arg)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
JSJHashEntry *he, *next, **oldbuckets;
|
||||
PRUint32 nb;
|
||||
|
||||
/* Grow the table if it is overloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (ht->nentries >= OVERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->ngrows++;
|
||||
#endif
|
||||
ht->shift--;
|
||||
oldbuckets = ht->buckets;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (2 * n > 16000)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
nb = 2 * n * sizeof(JSJHashEntry *);
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
}
|
||||
|
||||
/* Make a new key value entry */
|
||||
he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
|
||||
if (!he)
|
||||
return 0;
|
||||
he->keyHash = keyHash;
|
||||
he->key = key;
|
||||
he->value = value;
|
||||
he->next = *hep;
|
||||
*hep = he;
|
||||
ht->nentries++;
|
||||
return he;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJHashEntry *)
|
||||
JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg)
|
||||
{
|
||||
JSJHashNumber keyHash;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key, arg);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
if ((he = *hep) != 0) {
|
||||
/* Hit; see if values match */
|
||||
if ((*ht->valueCompare)(he->value, value, arg)) {
|
||||
/* key,value pair is already present in table */
|
||||
return he;
|
||||
}
|
||||
if (he->value)
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
|
||||
he->value = value;
|
||||
return he;
|
||||
}
|
||||
return JSJ_HashTableRawAdd(ht, hep, keyHash, key, value, arg);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
JSJHashEntry *next, **oldbuckets;
|
||||
PRUint32 nb;
|
||||
|
||||
*hep = he->next;
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
|
||||
|
||||
/* Shrink table if it's underloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (--ht->nentries < UNDERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->nshrinks++;
|
||||
#endif
|
||||
ht->shift++;
|
||||
oldbuckets = ht->buckets;
|
||||
nb = n * sizeof(JSJHashEntry*) / 2;
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRBool)
|
||||
JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg)
|
||||
{
|
||||
JSJHashNumber keyHash;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key, arg);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
if ((he = *hep) == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
/* Hit; remove element */
|
||||
JSJ_HashTableRawRemove(ht, hep, he, arg);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *)
|
||||
JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg)
|
||||
{
|
||||
JSJHashNumber keyHash;
|
||||
JSJHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key, arg);
|
||||
hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg);
|
||||
if ((he = *hep) != 0) {
|
||||
return he->value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over the entries in the hash table calling func for each
|
||||
** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg)
|
||||
{
|
||||
JSJHashEntry *he, **hep;
|
||||
PRUint32 i, nbuckets;
|
||||
int rv, n = 0;
|
||||
JSJHashEntry *todo = 0;
|
||||
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
hep = &ht->buckets[i];
|
||||
while ((he = *hep) != 0) {
|
||||
rv = (*f)(he, n, arg);
|
||||
n++;
|
||||
if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
|
||||
*hep = he->next;
|
||||
if (rv & HT_ENUMERATE_REMOVE) {
|
||||
he->next = todo;
|
||||
todo = he;
|
||||
}
|
||||
} else {
|
||||
hep = &he->next;
|
||||
}
|
||||
if (rv & HT_ENUMERATE_STOP) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
hep = &todo;
|
||||
while ((he = *hep) != 0) {
|
||||
JSJ_HashTableRawRemove(ht, hep, he, arg);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef HASHMETER
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_HashTableDumpMeter(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double mean, variance;
|
||||
PRUint32 nchains, nbuckets;
|
||||
PRUint32 i, n, maxChain, maxChainLen;
|
||||
JSJHashEntry *he;
|
||||
|
||||
variance = 0;
|
||||
nchains = 0;
|
||||
maxChainLen = 0;
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
he = ht->buckets[i];
|
||||
if (!he)
|
||||
continue;
|
||||
nchains++;
|
||||
for (n = 0; he; he = he->next)
|
||||
n++;
|
||||
variance += n * n;
|
||||
if (n > maxChainLen) {
|
||||
maxChainLen = n;
|
||||
maxChain = i;
|
||||
}
|
||||
}
|
||||
mean = (double)ht->nentries / nchains;
|
||||
variance = fabs(variance / nchains - mean * mean);
|
||||
|
||||
fprintf(fp, "\nHash table statistics:\n");
|
||||
fprintf(fp, " number of lookups: %u\n", ht->nlookups);
|
||||
fprintf(fp, " number of entries: %u\n", ht->nentries);
|
||||
fprintf(fp, " number of grows: %u\n", ht->ngrows);
|
||||
fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
|
||||
fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
|
||||
/ ht->nlookups);
|
||||
fprintf(fp, "mean hash chain length: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " max hash chain length: %u\n", maxChainLen);
|
||||
fprintf(fp, " max hash chain: [%u]\n", maxChain);
|
||||
|
||||
for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
|
||||
if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
|
||||
break;
|
||||
}
|
||||
#endif /* HASHMETER */
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = JSJ_HashTableEnumerateEntries(ht, dump, fp);
|
||||
#ifdef HASHMETER
|
||||
JSJ_HashTableDumpMeter(ht, dump, fp);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(JSJHashNumber)
|
||||
JSJ_HashString(const void *key)
|
||||
{
|
||||
JSJHashNumber h;
|
||||
const unsigned char *s;
|
||||
|
||||
h = 0;
|
||||
for (s = key; *s; s++)
|
||||
h = (h >> 28) ^ (h << 4) ^ *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_CompareStrings(const void *v1, const void *v2)
|
||||
{
|
||||
return strcmp(v1, v2) == 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
JSJ_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
141
mozilla/js/src/liveconnect/jsj_hash.h
Normal file
141
mozilla/js/src/liveconnect/jsj_hash.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a copy of the NSPR hash-table library, but it has been slightly
|
||||
* modified to allow an additional argument to be passed into the hash
|
||||
* key-comparision function. This is used to maintain thread-safety by
|
||||
* passing in a JNIEnv pointer to the key-comparison function rather
|
||||
* than storing it in a global. All types,function names, etc. have
|
||||
* been renamed from their original NSPR names to protect the innocent.
|
||||
*/
|
||||
|
||||
#ifndef jsj_hash_h___
|
||||
#define jsj_hash_h___
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSJHashEntry JSJHashEntry;
|
||||
typedef struct JSJHashTable JSJHashTable;
|
||||
typedef PRUint32 JSJHashNumber;
|
||||
#define JSJ_HASH_BITS 32
|
||||
typedef JSJHashNumber (*JSJHashFunction)(const void *key, void *arg);
|
||||
typedef PRIntn (*JSJHashComparator)(const void *v1, const void *v2, void *arg);
|
||||
typedef PRIntn (*JSJHashEnumerator)(JSJHashEntry *he, PRIntn i, void *arg);
|
||||
|
||||
/* Flag bits in JSJHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
|
||||
|
||||
typedef struct JSJHashAllocOps {
|
||||
void * (*allocTable)(void *pool, size_t size);
|
||||
void (*freeTable)(void *pool, void *item);
|
||||
JSJHashEntry * (*allocEntry)(void *pool, const void *key);
|
||||
void (*freeEntry)(void *pool, JSJHashEntry *he, PRUintn flag);
|
||||
} JSJHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct JSJHashEntry {
|
||||
JSJHashEntry *next; /* hash chain linkage */
|
||||
JSJHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct JSJHashTable {
|
||||
JSJHashEntry **buckets; /* vector of hash buckets */
|
||||
PRUint32 nentries; /* number of entries in table */
|
||||
PRUint32 shift; /* multiplicative hash shift */
|
||||
JSJHashFunction keyHash; /* key hash function */
|
||||
JSJHashComparator keyCompare; /* key comparison function */
|
||||
JSJHashComparator valueCompare; /* value comparison function */
|
||||
JSJHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef HASHMETER
|
||||
PRUint32 nlookups; /* total number of lookups */
|
||||
PRUint32 nsteps; /* number of hash chains traversed */
|
||||
PRUint32 ngrows; /* number of table expansions */
|
||||
PRUint32 nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
PR_EXTERN(JSJHashTable *)
|
||||
JSJ_NewHashTable(PRUint32 n, JSJHashFunction keyHash,
|
||||
JSJHashComparator keyCompare, JSJHashComparator valueCompare,
|
||||
JSJHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
PR_EXTERN(void)
|
||||
JSJ_HashTableDestroy(JSJHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
PR_EXTERN(JSJHashEntry **)
|
||||
JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg);
|
||||
|
||||
PR_EXTERN(JSJHashEntry *)
|
||||
JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep, JSJHashNumber keyHash,
|
||||
const void *key, void *value, void *arg);
|
||||
|
||||
PR_EXTERN(void)
|
||||
JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg);
|
||||
|
||||
/* Higher level access methods */
|
||||
PR_EXTERN(JSJHashEntry *)
|
||||
JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg);
|
||||
|
||||
PR_EXTERN(PRBool)
|
||||
JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg);
|
||||
|
||||
PR_EXTERN(void *)
|
||||
JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
PR_EXTERN(JSJHashNumber)
|
||||
JSJ_HashString(const void *key);
|
||||
|
||||
/* Compare strings using strcmp(), return true if equal. */
|
||||
PR_EXTERN(int)
|
||||
JSJ_CompareStrings(const void *v1, const void *v2);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
PR_EXTERN(PRIntn)
|
||||
JSJ_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* jsj_hash_h___ */
|
||||
1164
mozilla/js/src/liveconnect/jsj_method.c
Normal file
1164
mozilla/js/src/liveconnect/jsj_method.c
Normal file
File diff suppressed because it is too large
Load Diff
552
mozilla/js/src/liveconnect/jsj_private.h
Normal file
552
mozilla/js/src/liveconnect/jsj_private.h
Normal file
@@ -0,0 +1,552 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* Declarations of private (internal) functions/data/types for
|
||||
* JavaScript <==> Java communication.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _JSJAVA_PVT_H
|
||||
#define _JSJAVA_PVT_H
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
/* NSPR1 compatibility definitions */
|
||||
#ifdef NSPR20
|
||||
# include "prprf.h"
|
||||
# include "prlog.h"
|
||||
# include "plhash.h" /* NSPR hash-tables */
|
||||
#else
|
||||
# include "prprintf.h"
|
||||
# include "prassert.h"
|
||||
# include "prhash.h" /* NSPR hash-tables */
|
||||
# define PRHashNumber prhashcode
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
# include "prosdep.h"
|
||||
#endif
|
||||
|
||||
#include "jsj_hash.h" /* Hash tables */
|
||||
#include "jni.h" /* Java Native Interface */
|
||||
#include "jsapi.h" /* JavaScript engine API */
|
||||
#include "jsjava.h" /* LiveConnect public API */
|
||||
|
||||
|
||||
/*************************** Type Declarations ******************************/
|
||||
|
||||
/* Forward type declarations */
|
||||
typedef struct JavaMemberDescriptor JavaMemberDescriptor;
|
||||
typedef struct JavaMethodSpec JavaMethodSpec;
|
||||
typedef struct JavaClassDescriptor JavaClassDescriptor;
|
||||
typedef struct JavaClassDescriptor JavaSignature;
|
||||
typedef struct CapturedJSError CapturedJSError;
|
||||
typedef struct JavaMemberVal JavaMemberVal;
|
||||
|
||||
/*
|
||||
* This enum uses the same character encoding used by the JDK to encode
|
||||
* Java type signatures, but the enum is easier to debug/compile with.
|
||||
*/
|
||||
typedef enum {
|
||||
JAVA_SIGNATURE_ARRAY = '[',
|
||||
JAVA_SIGNATURE_BYTE = 'B',
|
||||
JAVA_SIGNATURE_CHAR = 'C',
|
||||
JAVA_SIGNATURE_CLASS = 'L',
|
||||
JAVA_SIGNATURE_FLOAT = 'F',
|
||||
JAVA_SIGNATURE_DOUBLE = 'D',
|
||||
JAVA_SIGNATURE_INT = 'I',
|
||||
JAVA_SIGNATURE_LONG = 'J',
|
||||
JAVA_SIGNATURE_SHORT = 'S',
|
||||
JAVA_SIGNATURE_VOID = 'V',
|
||||
JAVA_SIGNATURE_BOOLEAN = 'Z',
|
||||
JAVA_SIGNATURE_UNKNOWN = 0
|
||||
} JavaSignatureChar;
|
||||
|
||||
/* The signature of a Java method consists of the signatures of all its
|
||||
arguments and its return type signature. */
|
||||
typedef struct JavaMethodSignature {
|
||||
jsize num_args; /* Length of arg_signatures array */
|
||||
JavaSignature ** arg_signatures; /* Array of argument signatures */
|
||||
JavaSignature * return_val_signature; /* Return type signature */
|
||||
} JavaMethodSignature;
|
||||
|
||||
/* A descriptor for the reflection of a single Java field */
|
||||
typedef struct JavaFieldSpec {
|
||||
jfieldID fieldID; /* JVM opaque access handle for field */
|
||||
JavaSignature * signature; /* Java type of field */
|
||||
int modifiers; /* Bitfield indicating field qualifiers */
|
||||
const char * name; /* UTF8; TODO - Should support Unicode field names */
|
||||
} JavaFieldSpec;
|
||||
|
||||
/* A descriptor for the reflection of a single Java method.
|
||||
Each overloaded method has a separate corresponding JavaMethodSpec. */
|
||||
struct JavaMethodSpec {
|
||||
jmethodID methodID; /* JVM opaque access handle for method */
|
||||
JavaMethodSignature signature;
|
||||
const char * name; /* UTF8; TODO - Should support Unicode method names */
|
||||
JavaMethodSpec * next; /* next method in chain of overloaded methods */
|
||||
};
|
||||
|
||||
/*
|
||||
* A descriptor for the reflection of a single member of a Java object.
|
||||
* This can represent one or more Java methods and/or a single field.
|
||||
* (When there is more than one method attached to a single JavaMemberDescriptor
|
||||
* they are overloaded methods sharing the same simple name.) This same
|
||||
* descriptor type is used for both static or instance members.
|
||||
*/
|
||||
struct JavaMemberDescriptor {
|
||||
const char * name; /* simple name of field and/or method */
|
||||
jsid id; /* hashed name for quick JS property lookup */
|
||||
JavaFieldSpec * field; /* field with the given name, if any */
|
||||
JavaMethodSpec * methods; /* Overloaded methods which share the same name, if any */
|
||||
JavaMemberDescriptor * next; /* next descriptor in same defining class */
|
||||
JSObject * invoke_func_obj; /* If non-null, JSFunction obj to invoke method */
|
||||
};
|
||||
|
||||
/* This is the native portion of a reflected Java class */
|
||||
struct JavaClassDescriptor {
|
||||
const char * name; /* Name of class, e.g. "java/lang/Byte" */
|
||||
JavaSignatureChar type; /* class category: primitive type, object, array */
|
||||
jclass java_class; /* Opaque JVM handle to corresponding java.lang.Class */
|
||||
int num_instance_members;
|
||||
int num_static_members;
|
||||
JSBool instance_members_reflected;
|
||||
JavaMemberDescriptor * instance_members;
|
||||
JSBool static_members_reflected;
|
||||
JavaMemberDescriptor * static_members;
|
||||
JavaMemberDescriptor * constructors;
|
||||
int modifiers; /* Class declaration qualifiers,
|
||||
e.g. abstract, private */
|
||||
int ref_count; /* # of references to this struct */
|
||||
JavaSignature * array_component_signature; /* Only non-NULL for array classes */
|
||||
};
|
||||
|
||||
/* This is the native portion of a reflected Java method or field */
|
||||
struct JavaMemberVal {
|
||||
jsval field_val; /* Captured value of Java field */
|
||||
jsval invoke_method_func_val; /* JSFunction wrapper around Java method invoker */
|
||||
JavaMemberDescriptor * descriptor;
|
||||
JavaMemberVal * next;
|
||||
};
|
||||
|
||||
/* This is the native portion of a reflected Java object */
|
||||
typedef struct JavaObjectWrapper {
|
||||
jobject java_obj; /* Opaque JVM ref to Java object */
|
||||
JavaClassDescriptor * class_descriptor; /* Java class info */
|
||||
} JavaObjectWrapper;
|
||||
|
||||
/* These are definitions of the Java class/method/field modifier bits.
|
||||
These really shouldn't be hard-coded here. Rather,
|
||||
they should be read from java.lang.reflect.Modifier */
|
||||
#define ACC_PUBLIC 0x0001 /* visible to everyone */
|
||||
#define ACC_STATIC 0x0008 /* instance variable is static */
|
||||
#define ACC_FINAL 0x0010 /* no further subclassing,overriding */
|
||||
#define ACC_INTERFACE 0x0200 /* class is an interface */
|
||||
#define ACC_ABSTRACT 0x0400 /* no definition provided */
|
||||
|
||||
/* A JSJavaVM structure must be created for each Java VM that is accessed
|
||||
via LiveConnect */
|
||||
struct JSJavaVM {
|
||||
/* TODO - all LiveConnect global variables should be migrated into this
|
||||
structure in order to allow more than one LiveConnect-enabled
|
||||
Java VM to exist within the same process. */
|
||||
SystemJavaVM * java_vm;
|
||||
JNIEnv * main_thread_env; /* Main-thread Java environment */
|
||||
JSBool jsj_created_java_vm;
|
||||
int num_attached_threads;
|
||||
JSJavaVM * next; /* next VM among all created VMs */
|
||||
};
|
||||
|
||||
/* Per-thread state that encapsulates the connection to the Java VM */
|
||||
struct JSJavaThreadState {
|
||||
const char * name; /* Thread name, for debugging */
|
||||
JSJavaVM * jsjava_vm; /* All per-JVM state */
|
||||
JNIEnv * jEnv; /* Per-thread opaque handle to Java VM */
|
||||
CapturedJSError * pending_js_errors; /* JS errors to be thrown as Java exceptions */
|
||||
JSContext * cx; /* current JS context for thread */
|
||||
JSJavaThreadState * next; /* next thread state among all created threads */
|
||||
};
|
||||
|
||||
struct JavaToJSSavedState {
|
||||
JSErrorReporter error_reporter;
|
||||
JSJavaThreadState* java_jsj_env;
|
||||
};
|
||||
typedef struct JavaToJSSavedState JavaToJSSavedState;
|
||||
|
||||
|
||||
|
||||
/******************************** Globals ***********************************/
|
||||
|
||||
extern JSJCallbacks *JSJ_callbacks;
|
||||
|
||||
/* JavaScript classes that reflect Java objects */
|
||||
extern JSClass JavaObject_class;
|
||||
extern JSClass JavaArray_class;
|
||||
extern JSClass JavaClass_class;
|
||||
extern JSClass JavaMember_class;
|
||||
|
||||
/*
|
||||
* Opaque JVM handles to Java classes, methods and objects required for
|
||||
* Java reflection. These are computed and cached during initialization.
|
||||
* TODO: These should be moved inside the JSJavaVM struct
|
||||
*/
|
||||
extern jclass jlObject; /* java.lang.Object */
|
||||
extern jclass jlrConstructor; /* java.lang.reflect.Constructor */
|
||||
extern jclass jlThrowable; /* java.lang.Throwable */
|
||||
extern jclass jlSystem; /* java.lang.System */
|
||||
extern jclass jlClass; /* java.lang.Class */
|
||||
extern jclass jlBoolean; /* java.lang.Boolean */
|
||||
extern jclass jlDouble; /* java.lang.Double */
|
||||
extern jclass jlString; /* java.lang.String */
|
||||
extern jclass njJSObject; /* netscape.javascript.JSObject */
|
||||
extern jclass njJSException; /* netscape.javascript.JSException */
|
||||
extern jclass njJSUtil; /* netscape.javascript.JSUtil */
|
||||
|
||||
extern jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */
|
||||
extern jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */
|
||||
extern jmethodID jlClass_getFields; /* java.lang.Class.getFields() */
|
||||
extern jmethodID jlClass_getName; /* java.lang.Class.getName() */
|
||||
extern jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */
|
||||
extern jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */
|
||||
extern jmethodID jlClass_isArray; /* java.lang.Class.isArray() */
|
||||
|
||||
extern jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */
|
||||
extern jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */
|
||||
extern jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */
|
||||
extern jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */
|
||||
|
||||
extern jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */
|
||||
extern jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */
|
||||
|
||||
extern jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */
|
||||
extern jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */
|
||||
extern jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */
|
||||
|
||||
extern jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */
|
||||
extern jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */
|
||||
|
||||
extern jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */
|
||||
extern jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */
|
||||
extern jmethodID jlDouble_Double; /* java.lang.Double constructor */
|
||||
extern jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */
|
||||
|
||||
extern jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */
|
||||
|
||||
extern jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */
|
||||
|
||||
extern jmethodID njJSException_JSException; /* netscape.javascipt.JSexception constructor */
|
||||
extern jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */
|
||||
extern jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */
|
||||
extern jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */
|
||||
extern jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */
|
||||
extern jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */
|
||||
extern jfieldID njJSException_source; /* netscape.javascript.JSException.source */
|
||||
extern jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */
|
||||
|
||||
|
||||
/**************** Java <==> JS conversions and Java types *******************/
|
||||
extern JSBool
|
||||
jsj_ComputeJavaClassSignature(JSContext *cx,
|
||||
JavaSignature *signature,
|
||||
jclass java_class);
|
||||
|
||||
extern const char *
|
||||
jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature);
|
||||
extern const char *
|
||||
jsj_ConvertJavaSignatureToHRString(JSContext *cx,
|
||||
JavaSignature *signature);
|
||||
extern JavaMethodSignature *
|
||||
jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, jobject method,
|
||||
JavaMethodSignature *method_signature);
|
||||
|
||||
extern const char *
|
||||
jsj_ConvertJavaMethodSignatureToString(JSContext *cx,
|
||||
JavaMethodSignature *method_signature);
|
||||
extern const char *
|
||||
jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx,
|
||||
const char *method_name,
|
||||
JavaMethodSignature *method_signature);
|
||||
extern void
|
||||
jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *signature);
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jvalue *java_value, JSBool *is_local_refp);
|
||||
extern JSBool
|
||||
jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jobject *java_value, JSBool *is_local_refp);
|
||||
extern jstring
|
||||
jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str);
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature,
|
||||
jvalue *java_value, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv,
|
||||
jobject java_obj, jsval *vp);
|
||||
|
||||
extern JSString *
|
||||
jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str);
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSString(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSJavaThreadState *
|
||||
jsj_enter_js(JNIEnv *jEnv, jobject java_wrapper_obj,
|
||||
JSContext **cxp, JSObject **js_objp, JavaToJSSavedState* saved_state);
|
||||
extern JSBool
|
||||
jsj_exit_js(JSContext *cx, JSJavaThreadState *jsj_env, JavaToJSSavedState* original_state);
|
||||
|
||||
extern JavaClassDescriptor *
|
||||
jsj_get_jlObject_descriptor(JSContext *cx, JNIEnv *jEnv);
|
||||
|
||||
extern JSBool
|
||||
jsj_remove_js_obj_reflection_from_hashtable(JSContext *cx, JSObject *js_obj);
|
||||
|
||||
extern JSBool
|
||||
jsj_init_js_obj_reflections_table();
|
||||
|
||||
/************************ Java package reflection **************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaPackage(JSContext *, JSObject *,
|
||||
JavaPackageDef *predefined_packages);
|
||||
|
||||
/************************* Java class reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaClass(JSContext *cx, JSObject *global_obj);
|
||||
|
||||
extern void
|
||||
jsj_DiscardJavaClassReflections(JNIEnv *jEnv);
|
||||
|
||||
extern const char *
|
||||
jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class);
|
||||
|
||||
extern JavaClassDescriptor *
|
||||
jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class);
|
||||
|
||||
extern void
|
||||
jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JSObject *
|
||||
jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
const char *unqualified_class_name,
|
||||
jclass jclazz);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetJavaMemberDescriptor(JSContext *cx,
|
||||
JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jsid id);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetJavaStaticMemberDescriptor(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
jstring member_name);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetJavaClassConstructors(JSContext *cx,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetClassInstanceMembers(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JavaMemberDescriptor *
|
||||
jsj_GetClassStaticMembers(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor);
|
||||
|
||||
extern JSBool
|
||||
jsj_InitJavaClassReflectionsTable();
|
||||
|
||||
/************************* Java field reflection ***************************/
|
||||
|
||||
extern JSBool
|
||||
jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jobject java_obj, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jobject java_obj, jsval js_val);
|
||||
extern JSBool
|
||||
jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_static_fields);
|
||||
extern void
|
||||
jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field);
|
||||
|
||||
/************************* Java method reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_JavaInstanceMethodWrapper(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_JavaStaticMethodWrapper(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_JavaConstructorWrapper(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
extern JSBool
|
||||
jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv,
|
||||
JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_static_methods);
|
||||
extern void
|
||||
jsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec);
|
||||
|
||||
/************************* Java member reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaMember(JSContext *, JSObject *);
|
||||
|
||||
extern JSBool
|
||||
jsj_ReflectJavaMethodsAndFields(JSContext *cx, JavaClassDescriptor *class_descriptor,
|
||||
JSBool reflect_only_statics);
|
||||
|
||||
extern JSObject *
|
||||
jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val);
|
||||
|
||||
/************************* Java object reflection **************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaObject(JSContext *, JSObject *);
|
||||
|
||||
extern JSObject *
|
||||
jsj_WrapJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_obj, jclass java_class);
|
||||
|
||||
extern void
|
||||
jsj_DiscardJavaObjReflections(JNIEnv *jEnv);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
|
||||
|
||||
extern void
|
||||
JavaObject_finalize(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_resolve(JSContext *cx, JSObject *obj, jsval id);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
/************************* Java array reflection ***************************/
|
||||
extern JSBool
|
||||
jsj_init_JavaArray(JSContext *cx, JSObject *global_obj);
|
||||
|
||||
extern JSBool
|
||||
jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array,
|
||||
jsize index, JavaSignature *array_component_signature,
|
||||
jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array,
|
||||
jsize index, JavaSignature *array_component_signature,
|
||||
jsval js_val);
|
||||
|
||||
/********************* JavaScript object reflection ************************/
|
||||
extern jobject
|
||||
jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj);
|
||||
|
||||
extern JSObject *
|
||||
jsj_UnwrapJSObjectWrapper(JNIEnv *jEnv, jobject java_wrapper_obj);
|
||||
|
||||
extern void
|
||||
jsj_ClearPendingJSErrors(JSJavaThreadState *jsj_env);
|
||||
|
||||
extern JSBool
|
||||
jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception);
|
||||
|
||||
/**************************** Utilities ************************************/
|
||||
extern void
|
||||
jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...);
|
||||
|
||||
extern void
|
||||
jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...);
|
||||
|
||||
extern const char *
|
||||
jsj_GetJavaErrorMessage(JNIEnv *env);
|
||||
|
||||
extern void
|
||||
jsj_LogError(const char *error_msg);
|
||||
|
||||
PR_CALLBACK JSJHashNumber
|
||||
jsj_HashJavaObject(const void *key, void* env);
|
||||
|
||||
PR_CALLBACK intN
|
||||
jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg);
|
||||
|
||||
extern JSJavaThreadState *
|
||||
jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp);
|
||||
|
||||
extern void
|
||||
jsj_MakeJNIClassname(char *jClassName);
|
||||
|
||||
extern const char *
|
||||
jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object);
|
||||
|
||||
extern jsize
|
||||
jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array);
|
||||
|
||||
extern JSBool
|
||||
JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp);
|
||||
|
||||
extern const char *
|
||||
jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr);
|
||||
|
||||
JSJavaThreadState *
|
||||
jsj_MapJSContextToJSJThread(JSContext *cx, JNIEnv **envp);
|
||||
|
||||
JSJavaThreadState *
|
||||
jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_LOG(args) printf args
|
||||
#endif
|
||||
|
||||
#define JS_FREE_IF(cx, x) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (x) \
|
||||
JS_free(cx, x); \
|
||||
PR_END_MACRO
|
||||
|
||||
#endif /* _JSJAVA_PVT_H */
|
||||
361
mozilla/js/src/liveconnect/jsj_utils.c
Normal file
361
mozilla/js/src/liveconnect/jsj_utils.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains low-level utility code.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jsj_private.h" /* LiveConnect internals */
|
||||
#include "jsjava.h" /* External LiveConnect API */
|
||||
|
||||
|
||||
/*
|
||||
* This is a hash-table utility routine that computes the hash code of a Java
|
||||
* object by calling java.lang.System.identityHashCode()
|
||||
*/
|
||||
PR_CALLBACK JSJHashNumber
|
||||
jsj_HashJavaObject(const void *key, void* env)
|
||||
{
|
||||
PRHashNumber hash_code;
|
||||
jobject java_obj;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
java_obj = (jobject)key;
|
||||
jEnv = (JNIEnv*) env;
|
||||
hash_code = (*jEnv)->CallStaticIntMethod(jEnv, jlSystem,
|
||||
jlSystem_identityHashCode, java_obj);
|
||||
PR_ASSERT(!(*jEnv)->ExceptionOccurred(jEnv));
|
||||
return hash_code;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a hash-table utility routine for comparing two Java objects.
|
||||
* It's not possible to use the == operator to directly compare two jobject's,
|
||||
* since they're opaque references and aren't guaranteed to be simple pointers
|
||||
* or handles (though they may be in some JVM implementations). Instead,
|
||||
* use the JNI routine for comparing the two objects.
|
||||
*/
|
||||
PR_CALLBACK intN
|
||||
jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg)
|
||||
{
|
||||
jobject java_obj1, java_obj2;
|
||||
JNIEnv *jEnv;
|
||||
|
||||
jEnv = (JNIEnv*)arg;
|
||||
java_obj1 = (jobject)v1;
|
||||
java_obj2 = (jobject)v2;
|
||||
|
||||
if (java_obj1 == java_obj2)
|
||||
return 1;
|
||||
return (*jEnv)->IsSameObject(jEnv, java_obj1, java_obj2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a UTF8, null-terminated encoding of a Java string. The string must
|
||||
* be free'ed by the caller.
|
||||
*
|
||||
* If an error occurs, returns NULL and calls the JS error reporter.
|
||||
*/
|
||||
const char *
|
||||
jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr)
|
||||
{
|
||||
const char *str, *retval;
|
||||
|
||||
str = (*jEnv)->GetStringUTFChars(jEnv, jstr, 0);
|
||||
if (!str) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Can't get UTF8 characters from "
|
||||
"Java string");
|
||||
return NULL;
|
||||
}
|
||||
retval = JS_strdup(cx, str);
|
||||
(*jEnv)->ReleaseStringUTFChars(jEnv, jstr, str);
|
||||
return retval;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp)
|
||||
{
|
||||
const jschar *ucs2;
|
||||
JSString *jsstr;
|
||||
jsize ucs2_len;
|
||||
jsval val;
|
||||
|
||||
ucs2 = (*jEnv)->GetStringChars(jEnv, jstr, 0);
|
||||
if (!ucs2) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain Unicode characters"
|
||||
"from Java string");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
ucs2_len = (*jEnv)->GetStringLength(jEnv, jstr);
|
||||
jsstr = JS_InternUCStringN(cx, ucs2, ucs2_len);
|
||||
(*jEnv)->ReleaseStringChars(jEnv, jstr, ucs2);
|
||||
if (!jsstr)
|
||||
return JS_FALSE;
|
||||
|
||||
val = STRING_TO_JSVAL(jsstr);
|
||||
JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Not used ?
|
||||
const char *
|
||||
jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object)
|
||||
{
|
||||
jobject java_class;
|
||||
|
||||
java_class = (*jEnv)->GetObjectClass(jEnv, java_object);
|
||||
|
||||
if (!java_class) {
|
||||
PR_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return jsj_GetJavaClassName(cx, jEnv, java_class);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return, as a C string, the error message associated with a Java exception
|
||||
* that occurred as a result of a JNI call, preceded by the class name of
|
||||
* the exception. As a special case, if the class of the exception is
|
||||
* netscape.javascript.JSException, the exception class name is omitted.
|
||||
*
|
||||
* NULL is returned if no Java exception is pending. The caller is
|
||||
* responsible for free'ing the returned string. On exit, the Java exception
|
||||
* is *not* cleared.
|
||||
*/
|
||||
const char *
|
||||
jsj_GetJavaErrorMessage(JNIEnv *jEnv)
|
||||
{
|
||||
const char *java_error_msg;
|
||||
char *error_msg = NULL;
|
||||
jthrowable exception;
|
||||
jstring java_exception_jstring;
|
||||
|
||||
exception = (*jEnv)->ExceptionOccurred(jEnv);
|
||||
if (exception && jlThrowable_toString) {
|
||||
java_exception_jstring =
|
||||
(*jEnv)->CallObjectMethod(jEnv, exception, jlThrowable_toString);
|
||||
java_error_msg = (*jEnv)->GetStringUTFChars(jEnv, java_exception_jstring, NULL);
|
||||
error_msg = strdup((char*)java_error_msg);
|
||||
(*jEnv)->ReleaseStringUTFChars(jEnv, java_exception_jstring, java_error_msg);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* (*jEnv)->ExceptionDescribe(jEnv); */
|
||||
#endif
|
||||
}
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return, as a C string, the JVM stack trace associated with a Java
|
||||
* exception, as would be printed by java.lang.Throwable.printStackTrace().
|
||||
* The caller is responsible for free'ing the returned string.
|
||||
*
|
||||
* Returns NULL if an error occurs.
|
||||
*/
|
||||
static const char *
|
||||
get_java_stack_trace(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception)
|
||||
{
|
||||
const char *backtrace;
|
||||
jstring backtrace_jstr;
|
||||
|
||||
backtrace = NULL;
|
||||
if (java_exception && njJSUtil_getStackTrace) {
|
||||
backtrace_jstr = (*jEnv)->CallStaticObjectMethod(jEnv, njJSUtil,
|
||||
njJSUtil_getStackTrace,
|
||||
java_exception);
|
||||
if (!backtrace_jstr) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Unable to get exception stack trace");
|
||||
return NULL;
|
||||
}
|
||||
backtrace = jsj_DupJavaStringUTF(cx, jEnv, backtrace_jstr);
|
||||
}
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
/* Full Java backtrace when Java exceptions reported to JavaScript */
|
||||
#define REPORT_JAVA_EXCEPTION_STACK_TRACE
|
||||
|
||||
/*
|
||||
* This is a wrapper around JS_ReportError(), useful when an error condition
|
||||
* is the result of a JVM failure or exception condition. It appends the
|
||||
* message associated with the pending Java exception to the passed in
|
||||
* printf-style format string and arguments.
|
||||
*/
|
||||
static void
|
||||
vreport_java_error(JSContext *cx, JNIEnv *jEnv, const char *format, va_list ap)
|
||||
{
|
||||
char *error_msg, *js_error_msg;
|
||||
const char *java_stack_trace;
|
||||
const char *java_error_msg;
|
||||
jthrowable java_exception;
|
||||
|
||||
java_error_msg = NULL;
|
||||
java_exception = (*jEnv)->ExceptionOccurred(jEnv);
|
||||
if (java_exception && njJSException &&
|
||||
(*jEnv)->IsInstanceOf(jEnv, java_exception, njJSException)) {
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
jsj_ReportUncaughtJSException(cx, jEnv, java_exception);
|
||||
return;
|
||||
}
|
||||
|
||||
js_error_msg = PR_vsmprintf(format, ap);
|
||||
|
||||
if (!js_error_msg) {
|
||||
PR_ASSERT(0); /* Out-of-memory */
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef REPORT_JAVA_EXCEPTION_STACK_TRACE
|
||||
|
||||
java_stack_trace = get_java_stack_trace(cx, jEnv, java_exception);
|
||||
if (java_stack_trace) {
|
||||
error_msg = PR_smprintf("%s\n%s", js_error_msg, java_stack_trace);
|
||||
free((char*)java_stack_trace);
|
||||
if (!error_msg) {
|
||||
PR_ASSERT(0); /* Out-of-memory */
|
||||
return;
|
||||
}
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
java_error_msg = jsj_GetJavaErrorMessage(jEnv);
|
||||
if (java_error_msg) {
|
||||
error_msg = PR_smprintf("%s (%s)\n", js_error_msg, java_error_msg);
|
||||
free((char*)java_error_msg);
|
||||
free(js_error_msg);
|
||||
} else {
|
||||
error_msg = js_error_msg;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, error_msg);
|
||||
|
||||
/* Important: the Java exception must not be cleared until the reporter
|
||||
has been called, because the capture_js_error_reports_for_java(),
|
||||
called from JS_ReportError(), needs to read the exception from the JVM */
|
||||
(*jEnv)->ExceptionClear(jEnv);
|
||||
free(error_msg);
|
||||
}
|
||||
|
||||
void
|
||||
jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vreport_java_error(cx, env, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as jsj_ReportJavaError, except "internal error: " is prepended
|
||||
* to message.
|
||||
*/
|
||||
void
|
||||
jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
const char *format2;
|
||||
|
||||
va_start(ap, format);
|
||||
format2 = PR_smprintf("internal error: %s", format);
|
||||
if (format2) {
|
||||
vreport_java_error(cx, env, format2, ap);
|
||||
free((void*)format2);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Most LiveConnect errors are signaled by calling JS_ReportError(),
|
||||
* but in some circumstances, the target JSContext for such errors
|
||||
* is not determinable, e.g. during initialization. In such cases
|
||||
* any error messages are routed to this function.
|
||||
*/
|
||||
void
|
||||
jsj_LogError(const char *error_msg)
|
||||
{
|
||||
if (JSJ_callbacks && JSJ_callbacks->error_print)
|
||||
JSJ_callbacks->error_print(error_msg);
|
||||
else
|
||||
fputs(error_msg, stderr);
|
||||
}
|
||||
|
||||
jsize
|
||||
jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array)
|
||||
{
|
||||
jsize array_length = (*jEnv)->GetArrayLength(jEnv, java_array);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain array length");
|
||||
return -1;
|
||||
}
|
||||
return array_length;
|
||||
}
|
||||
|
||||
static JSJavaThreadState *the_java_jsj_env = NULL;
|
||||
|
||||
JSJavaThreadState *
|
||||
jsj_MapJSContextToJSJThread(JSContext *cx, JNIEnv **envp)
|
||||
{
|
||||
JSJavaThreadState *jsj_env;
|
||||
char *err_msg;
|
||||
|
||||
*envp = NULL;
|
||||
err_msg = NULL;
|
||||
|
||||
jsj_env = the_java_jsj_env;
|
||||
if (jsj_env == NULL)
|
||||
jsj_env = JSJ_callbacks->map_js_context_to_jsj_thread(cx, &err_msg);
|
||||
if (!jsj_env) {
|
||||
if (err_msg) {
|
||||
JS_ReportError(cx, err_msg);
|
||||
free(err_msg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (envp)
|
||||
*envp = jsj_env->jEnv;
|
||||
return jsj_env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since only one Java thread is allowed to enter JavaScript, this function is
|
||||
* used to enforce the use of that thread's state. The static global the_java_jsj_env
|
||||
* overrides using JSJ_callbacks->map_js_context_to_jsj_thread, which maps
|
||||
* native threads to JSJavaThreadStates. This isn't appropriate when Java calls
|
||||
* JavaScript, as there can be a many to one mapping from Java threads to native
|
||||
* threads.
|
||||
*/
|
||||
JSJavaThreadState *
|
||||
jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env)
|
||||
{
|
||||
JSJavaThreadState *old_jsj_env = the_java_jsj_env;
|
||||
the_java_jsj_env = java_jsj_env;
|
||||
return old_jsj_env;
|
||||
}
|
||||
264
mozilla/js/src/liveconnect/jsjava.h
Normal file
264
mozilla/js/src/liveconnect/jsjava.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* Publicly exported functions for JavaScript <==> Java communication.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _JSJAVA_H
|
||||
#define _JSJAVA_H
|
||||
|
||||
#ifndef prtypes_h___
|
||||
#include "prtypes.h"
|
||||
#endif
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
#include "jni.h" /* Java Native Interface */
|
||||
#include "jsapi.h" /* JavaScript engine API */
|
||||
|
||||
/*
|
||||
* A JSJavaVM structure is a wrapper around a JavaVM which incorporates
|
||||
* additional LiveConnect state.
|
||||
*/
|
||||
typedef struct JSJavaVM JSJavaVM;
|
||||
|
||||
/* LiveConnect and Java state, one per thread */
|
||||
typedef struct JSJavaThreadState JSJavaThreadState;
|
||||
|
||||
/*
|
||||
* An opaque type that represents the connection to the Java VM. In stand-alone
|
||||
* Java environments, this may be a JNI JavaVM object; in the browser environment
|
||||
* it is a reference to a JVM plugin. A set of callbacks in the JSJCallbacks
|
||||
* struct allow it to be manipulated.
|
||||
*/
|
||||
typedef struct SystemJavaVM SystemJavaVM;
|
||||
|
||||
/*
|
||||
* This callback table provides hooks to external functions that implement
|
||||
* functionality specific to the embedding. For example, these callbacks are
|
||||
* necessary in multi-threaded environments or to implement a security
|
||||
* policy.
|
||||
*/
|
||||
typedef struct JSJCallbacks {
|
||||
|
||||
/* This callback is invoked when there is no JavaScript execution
|
||||
environment (JSContext) associated with the current Java thread and
|
||||
a call is made from Java into JavaScript. (A JSContext is associated
|
||||
with a Java thread by calling the JSJ_SetJSContextForJavaThread()
|
||||
function.) This callback is only invoked when Java spontaneously calls
|
||||
into JavaScript, i.e. it is not called when JS calls into Java which
|
||||
calls back into JS.
|
||||
|
||||
This callback can be used to create a JSContext lazily, or obtain
|
||||
one from a pool of available JSContexts. The implementation of this
|
||||
callback can call JSJ_SetJSContextForJavaThread() to avoid any further
|
||||
callbacks of this type for this Java thread. */
|
||||
JSContext * (*map_jsj_thread_to_js_context)(JSJavaThreadState *jsj_env,
|
||||
JNIEnv *jEnv,
|
||||
char **errp);
|
||||
|
||||
/* This callback is invoked whenever a call is made into Java from
|
||||
JavaScript. It's responsible for mapping from a JavaScript execution
|
||||
environment (JSContext) to a Java thread. (A JavaContext can only
|
||||
be associated with one Java thread at a time.) */
|
||||
JSJavaThreadState * (*map_js_context_to_jsj_thread)(JSContext *cx,
|
||||
char **errp);
|
||||
|
||||
/* This callback implements netscape.javascript.JSObject.getWindow(),
|
||||
a method named for its behavior in the browser environment, where it
|
||||
returns the JS "Window" object corresponding to the HTML window that an
|
||||
applet is embedded within. More generally, it's a way for Java to get
|
||||
hold of a JS object that has not been explicitly passed to it. */
|
||||
JSObject * (*map_java_object_to_js_object)(JNIEnv *jEnv, void *pJavaObject,
|
||||
char **errp);
|
||||
|
||||
/* An interim callback function until the LiveConnect security story is
|
||||
straightened out. This function pointer can be set to NULL. */
|
||||
JSPrincipals * (*get_JSPrincipals_from_java_caller)(JNIEnv *jEnv, JSContext *pJSContext);
|
||||
|
||||
/* The following two callbacks sandwich any JS evaluation performed
|
||||
from Java. They may be used to implement concurrency constraints, e.g.
|
||||
by suspending the current thread until some condition is met. In the
|
||||
browser embedding, these are used to maintain the run-to-completion
|
||||
semantics of JavaScript. It is acceptable for either function pointer
|
||||
to be NULL. */
|
||||
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp);
|
||||
void (*exit_js)(JNIEnv *jEnv);
|
||||
|
||||
/* Most LiveConnect errors are signaled by calling JS_ReportError(), but in
|
||||
some circumstances, the target JSContext for such errors is not
|
||||
determinable, e.g. during initialization. In such cases any error
|
||||
messages are routed to this function. If the function pointer is set to
|
||||
NULL, error messages are sent to stderr. */
|
||||
void (*error_print)(const char *error_msg);
|
||||
|
||||
/* This enables liveconnect to ask the VM for a java wrapper so that VM gets a chance to
|
||||
store a mapping between a jsobject and java wrapper. So the unwrapping can be done on the
|
||||
VM side before calling nsILiveconnect apis. This saves on a round trip request. */
|
||||
jobject (*get_java_wrapper)(JNIEnv *jEnv, jint jsobject);
|
||||
|
||||
/* The following set of methods abstract over the JavaVM object. */
|
||||
PRBool (*create_java_vm)(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs);
|
||||
PRBool (*destroy_java_vm)(SystemJavaVM* jvm, JNIEnv* initialEnv);
|
||||
JNIEnv* (*attach_current_thread)(SystemJavaVM* jvm);
|
||||
PRBool (*detach_current_thread)(SystemJavaVM* jvm, JNIEnv* env);
|
||||
SystemJavaVM* (*get_java_vm)(JNIEnv* env);
|
||||
|
||||
/* Reserved for future use */
|
||||
void * reserved[10];
|
||||
} JSJCallbacks;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
/* A flag that denotes that a Java package has no sub-packages other than those
|
||||
explicitly pre-defined at the time of initialization. An access
|
||||
to a simple name within such a package, therefore, must either correspond to
|
||||
one of these explicitly pre-defined sub-packages or to a class within this
|
||||
package. It is reasonable for LiveConnect to signal an error if a simple
|
||||
name does not comply with these criteria. */
|
||||
#define PKG_SYSTEM 1
|
||||
|
||||
/* A flag that denotes that a Java package which might contain sub-packages
|
||||
that are not pre-defined at initialization time, because the sub-packages
|
||||
may not be the same in all installations. Therefore, an access to a simple
|
||||
name within such a a package which does not correspond to either a
|
||||
pre-defined sub-package or to a class, must be assummed to refer to an
|
||||
unknown sub-package. This behavior may cause bogus JavaPackage objects to be
|
||||
created if a package name is misspelled, e.g. sun.oi.net. */
|
||||
#define PKG_USER 2
|
||||
|
||||
/* A Java package defined at initialization time. */
|
||||
typedef struct JavaPackageDef {
|
||||
const char * name; /* e.g. "java.lang" */
|
||||
const char * path; /* e.g. "java/lang", or NULL for default */
|
||||
int flags; /* PKG_USER, PKG_SYSTEM, etc. */
|
||||
} JavaPackageDef;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The following two convenience functions present a complete, but simplified
|
||||
LiveConnect API which is designed to handle the special case of a single
|
||||
Java-VM, with single-threaded operation, and the use of only one JSContext.
|
||||
The full API is in the section below. */
|
||||
|
||||
/* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
reflection and by defining JavaPackage objects for the default Java packages
|
||||
as properties of global_obj. If java_vm is NULL, a new Java VM is
|
||||
created, using the provided classpath in addition to any default classpath.
|
||||
The classpath argument is ignored, however, if java_vm is non-NULL. */
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_SimpleInit(JSContext *cx, JSObject *global_obj,
|
||||
SystemJavaVM *java_vm, const char *classpath);
|
||||
|
||||
/* Free up all resources. Destroy the Java VM if it was created by LiveConnect */
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_SimpleShutdown();
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The "full" LiveConnect API, required when more than one thread, Java VM, or
|
||||
JSContext is involved. Initialization pseudocode might go roughly like
|
||||
this:
|
||||
|
||||
JSJ_Init() // Setup callbacks
|
||||
for each JavaVM {
|
||||
JSJ_ConnectToJavaVM(...)
|
||||
}
|
||||
for each JSContext {
|
||||
JSJ_InitJSContext(...)
|
||||
}
|
||||
for each JS evaluation {
|
||||
run JavaScript code in the JSContext;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Called once for all instances of LiveConnect to set up callbacks */
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_Init(JSJCallbacks *callbacks);
|
||||
|
||||
/* Called once per Java VM, this function initializes the classes, fields, and
|
||||
methods required for Java reflection. If java_vm is NULL, a new Java VM is
|
||||
created according to the create_java_vm callback in the JSJCallbacks,
|
||||
using the provided classpath in addition to any default initargs.
|
||||
The initargs argument is ignored, however, if java_vm is non-NULL. */
|
||||
PR_IMPLEMENT(JSJavaVM *)
|
||||
JSJ_ConnectToJavaVM(SystemJavaVM *java_vm, void* initargs);
|
||||
|
||||
/* Initialize the provided JSContext by setting up the JS classes necessary for
|
||||
reflection and by defining JavaPackage objects for the default Java packages
|
||||
as properties of global_obj. Additional packages may be pre-defined by
|
||||
setting the predefined_packages argument. (Pre-defining a Java package at
|
||||
initialization time is not necessary, but it will make package lookup faster
|
||||
and, more importantly, will avoid unnecessary network accesses if classes
|
||||
are being loaded over the network.) */
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_InitJSContext(JSContext *cx, JSObject *global_obj,
|
||||
JavaPackageDef *predefined_packages);
|
||||
|
||||
/* This function returns a structure that encapsulates the Java and JavaScript
|
||||
execution environment for the current native thread. It is intended to
|
||||
be called from the embedder's implementation of JSJCallback's
|
||||
map_js_context_to_jsj_thread() function. The thread_name argument is only
|
||||
used for debugging purposes and can be set to NULL. The Java JNI
|
||||
environment associated with this thread is returned through the java_envp
|
||||
argument if java_envp is non-NULL. */
|
||||
PR_IMPLEMENT(JSJavaThreadState *)
|
||||
JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *thread_name,
|
||||
JNIEnv **java_envp);
|
||||
|
||||
/* Destructor routine for per-thread JSJavaThreadState structure */
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env);
|
||||
|
||||
/* This function is used to specify a particular JSContext as *the* JavaScript
|
||||
execution environment to be used when LiveConnect is accessed from the given
|
||||
Java thread, i.e. when one of the methods of netscape.javascript.JSObject
|
||||
has been called. There can only be one such JS context for any given Java
|
||||
thread at a time. (To multiplex JSContexts among a single thread, this
|
||||
function could be called before Java is invoked on that thread.) The return
|
||||
value is the previous JSContext associated with the given Java thread.
|
||||
|
||||
If this function has not been called for a thread and a crossing is made
|
||||
into JavaScript from Java, the map_jsj_thread_to_js_context() callback will
|
||||
be invoked to determine the JSContext for the thread. The purpose of the
|
||||
function is to improve performance by avoiding the expense of the callback.
|
||||
*/
|
||||
PR_IMPLEMENT(JSContext *)
|
||||
JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env);
|
||||
|
||||
/* This routine severs the connection to a Java VM, freeing all related resources.
|
||||
It shouldn't be called until the global scope has been cleared in all related
|
||||
JSContexts (so that all LiveConnect objects are finalized) and a JavaScript
|
||||
GC is performed. Otherwise, accessed to free'ed memory could result. */
|
||||
PR_IMPLEMENT(void)
|
||||
JSJ_DisconnectFromJavaVM(JSJavaVM *);
|
||||
|
||||
/*
|
||||
* Reflect a Java object into a JS value. The source object, java_obj, must
|
||||
* be of type java.lang.Object or a subclass and may, therefore, be an array.
|
||||
*/
|
||||
PR_IMPLEMENT(JSBool)
|
||||
JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
#endif /* _JSJAVA_H */
|
||||
182
mozilla/js/src/liveconnect/makefile.win
Normal file
182
mozilla/js/src/liveconnect/makefile.win
Normal file
@@ -0,0 +1,182 @@
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
IGNORE_MANIFEST=1
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Makefile to build the Java reflections of JavaScript objects
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Specify the depth of the current directory relative to the
|
||||
#// root of NS
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DEPTH= ..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
!ifdef NSJVM
|
||||
DIRS = classes
|
||||
!endif
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DLLNAME=jsj$(MOZ_BITS)$(VERSION_NUMBER)
|
||||
PDBFILE=$(DLLNAME).pdb
|
||||
MAPFILE = $(DLLNAME).map
|
||||
RESFILE = jsj1640.res
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
MAKE_OBJ_TYPE = DLL
|
||||
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
DEFFILE = $(DLLNAME).def
|
||||
!endif
|
||||
|
||||
LLIBS=$(LIBNSPR) $(DIST)\lib\js$(MOZ_BITS)$(VERSION_NUMBER).lib \
|
||||
$(DIST)\lib\xpcom32.lib
|
||||
|
||||
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
|
||||
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define the files necessary to build the target (ie. OBJS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
OBJS= \
|
||||
.\$(OBJDIR)\jsj.obj \
|
||||
.\$(OBJDIR)\jsj_JSObject.obj \
|
||||
.\$(OBJDIR)\jsj_JavaArray.obj \
|
||||
.\$(OBJDIR)\jsj_JavaClass.obj \
|
||||
.\$(OBJDIR)\jsj_JavaMember.obj \
|
||||
.\$(OBJDIR)\jsj_JavaObject.obj \
|
||||
.\$(OBJDIR)\jsj_JavaPackage.obj \
|
||||
.\$(OBJDIR)\jsj_array.obj \
|
||||
.\$(OBJDIR)\jsj_class.obj \
|
||||
.\$(OBJDIR)\jsj_convert.obj \
|
||||
.\$(OBJDIR)\jsj_field.obj \
|
||||
.\$(OBJDIR)\jsj_hash.obj \
|
||||
.\$(OBJDIR)\jsj_method.obj \
|
||||
.\$(OBJDIR)\jsj_utils.obj \
|
||||
.\$(OBJDIR)\nsCLiveconnect.obj \
|
||||
.\$(OBJDIR)\nsCLiveconnectFactory.obj \
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
.\$(OBJDIR)\jsj_nodl.obj \
|
||||
!endif
|
||||
$(NULL)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// install headers
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
INSTALL_DIR=$(PUBLIC)\js
|
||||
INSTALL_FILE_LIST= \
|
||||
jsjava.h nsILiveconnect.h
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
|
||||
#// (these must be defined before the common makefiles are included)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifdef NSJVM
|
||||
JNI_GEN= \
|
||||
netscape.javascript.JSObject \
|
||||
netscape.javascript.JSException \
|
||||
$(NULL)
|
||||
|
||||
!endif
|
||||
|
||||
MODULE = java
|
||||
EXPORTS = \
|
||||
$(JNI_GEN_DIR)\netscape_javascript_JSObject.h \
|
||||
$(JNI_GEN_DIR)\netscape_javascript_JSException.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any local options for the make tools
|
||||
#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
LINCS=$(LINCS) -I$(JNI_GEN_DIR) \
|
||||
-I$(PUBLIC)\js \
|
||||
-I$(PUBLIC)\java \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
$(NULL)
|
||||
|
||||
|
||||
#!ifdef SERVER_BUILD
|
||||
#LLIBS=$(DIST)/lib/httpdlw.lib $(DIST)/lib/libsjboot.lib
|
||||
#!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Include the common makefile rules
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
export:: INSTALL_FILES
|
||||
|
||||
libs:: $(DLL)
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
|
||||
|
||||
####
|
||||
# this bit of extreme scariness came from the js/src makefile
|
||||
# reproduced here since that's where jsjava.c lives now...
|
||||
|
||||
!if ("$(MOZ_BITS)" == "16")
|
||||
#//
|
||||
#// Win16 Hoovers SO BAD!!!
|
||||
#//
|
||||
|
||||
!if !defined(MOZ_DEBUG)
|
||||
#//
|
||||
#// We must turn off codeview debug info so jni.c can build.
|
||||
#// Otherwise the linker gives errors about data in the $SYMBOLS
|
||||
#// segment being beyond a segment boundary.
|
||||
#//
|
||||
$(OBJDIR)\jsjava.obj: jsjava.c
|
||||
@$(CC) @<<$(CFGFILE)
|
||||
-c
|
||||
-Od
|
||||
$(CFLAGS)
|
||||
$(LCFLAGS)
|
||||
$(LINCS)
|
||||
$(LINCS_1)
|
||||
$(INCS)
|
||||
-Fd$(PDBFILE)
|
||||
-Fo.\$(OBJDIR)\
|
||||
$(*B).c
|
||||
<<KEEP
|
||||
!endif
|
||||
!endif
|
||||
111
mozilla/js/src/liveconnect/netscape_javascript_JSObject.h
Normal file
111
mozilla/js/src/liveconnect/netscape_javascript_JSObject.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright (C) 1998 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
#include <jni.h>
|
||||
/* Header for class netscape_javascript_JSObject */
|
||||
|
||||
#ifndef _Included_netscape_javascript_JSObject
|
||||
#define _Included_netscape_javascript_JSObject
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: initClass
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getMember
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getSlot
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot
|
||||
(JNIEnv *, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setMember
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember
|
||||
(JNIEnv *, jobject, jstring, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: setSlot
|
||||
* Signature: (ILjava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot
|
||||
(JNIEnv *, jobject, jint, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: removeMember
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: call
|
||||
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call
|
||||
(JNIEnv *, jobject, jstring, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: eval
|
||||
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval
|
||||
(JNIEnv *, jobject, jstring);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: toString
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: getWindow
|
||||
* Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: finalize
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: netscape_javascript_JSObject
|
||||
* Method: equals
|
||||
* Signature: (Ljava/lang/Object;)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_netscape_javascript_JSObject_equals
|
||||
(JNIEnv *, jobject, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
567
mozilla/js/src/liveconnect/nsCLiveconnect.cpp
Normal file
567
mozilla/js/src/liveconnect/nsCLiveconnect.cpp
Normal file
@@ -0,0 +1,567 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the implementation providing nsIFactory XP-COM interface.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "prtypes.h"
|
||||
#include "prprf.h"
|
||||
#include "prlog.h"
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
#ifdef XP_MAC
|
||||
#include "prosdep.h"
|
||||
#endif
|
||||
|
||||
#include "jsj_private.h"
|
||||
#include "jsjava.h"
|
||||
|
||||
#include "jscntxt.h" /* For js_ReportErrorAgain().
|
||||
TODO - get rid of private header */
|
||||
|
||||
#include "netscape_javascript_JSObject.h" /* javah-generated headers */
|
||||
|
||||
|
||||
/* A captured JavaScript error, created when JS_ReportError() is called while
|
||||
running JavaScript code that is itself called from Java. */
|
||||
struct CapturedJSError {
|
||||
char * message;
|
||||
JSErrorReport report; /* Line # of error, etc. */
|
||||
jthrowable java_exception; /* Java exception, error, or null */
|
||||
CapturedJSError * next; /* Next oldest captured JS error */
|
||||
};
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#include "nsCLiveconnect.h"
|
||||
|
||||
static NS_DEFINE_IID(kILiveconnectIID, NS_ILIVECONNECT_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports and AggregatedQueryInterface:
|
||||
|
||||
// Thes macro expands to the aggregated query interface scheme.
|
||||
|
||||
NS_IMPL_AGGREGATED(nsCLiveconnect);
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnect::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = GetInner();
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kILiveconnectIID)) {
|
||||
*aInstancePtr = this;
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsILiveconnect:
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member. If it is a basic data type it is converted to
|
||||
* a corresponding java type. If it is a NJSObject, then it is
|
||||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject *pjobj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null member name");
|
||||
member = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (!JS_GetProperty(cx, js_obj, name, &js_val))
|
||||
goto done;
|
||||
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &member, &dummy_bool);
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*pjobj = member;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject *pjobj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// =-= sudu: check to see if slot can be passed in as is.
|
||||
// Should it be converted to a jsint?
|
||||
if (!JS_GetElement(cx, js_obj, slot, &js_val))
|
||||
goto done;
|
||||
if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &member, &dummy_bool))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*pjobj = member;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::SetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject java_obj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null member name");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
|
||||
goto done;
|
||||
|
||||
JS_SetProperty(cx, js_obj, name, &js_val);
|
||||
|
||||
done:
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::SetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject java_obj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jsval js_val = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val))
|
||||
goto done;
|
||||
JS_SetElement(cx, js_obj, slot, &js_val);
|
||||
|
||||
done:
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* remove member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::RemoveMember(JNIEnv *jEnv, jsobject obj, const char *name)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jsval js_val = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null member name");
|
||||
goto done;
|
||||
}
|
||||
JS_DeleteProperty2(cx, js_obj, name, &js_val);
|
||||
|
||||
done:
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* call a method of Native JSObject.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a method.
|
||||
* @param jobjArr - Array of jobjects representing parameters of method being caled.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::Call(JNIEnv *jEnv, jsobject obj, const char *name, jobjectArray java_args, jobject *pjobj)
|
||||
{
|
||||
int i = 0;
|
||||
int argc = 0;
|
||||
int arg_num = 0;
|
||||
jsval *argv = 0;
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
jsval function_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
jobject result = NULL;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
result = NULL;
|
||||
if (!name) {
|
||||
JS_ReportError(cx, "illegal null JavaScript function name");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: What about security stuff ? Don't principals need to be set here ? */
|
||||
|
||||
/* Allocate space for JS arguments */
|
||||
if (java_args) {
|
||||
argc = jEnv->GetArrayLength(java_args);
|
||||
argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval));
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = 0;
|
||||
}
|
||||
|
||||
/* Convert arguments from Java to JS values */
|
||||
for (arg_num = 0; arg_num < argc; arg_num++) {
|
||||
jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num);
|
||||
|
||||
if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]))
|
||||
goto cleanup_argv;
|
||||
JS_AddRoot(cx, &argv[arg_num]);
|
||||
}
|
||||
|
||||
if (!JS_GetProperty(cx, js_obj, name, &function_val))
|
||||
goto cleanup_argv;
|
||||
|
||||
if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val))
|
||||
goto cleanup_argv;
|
||||
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &result, &dummy_bool);
|
||||
|
||||
cleanup_argv:
|
||||
if (argv) {
|
||||
for (i = 0; i < arg_num; i++)
|
||||
JS_RemoveRoot(cx, &argv[i]);
|
||||
JS_free(cx, argv);
|
||||
}
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*pjobj = result;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate a script with a Native JS Object representing scope.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
* @param pNSIPrincipaArray - Array of principals to be used to compare privileges.
|
||||
* @param numPrincipals - Number of principals being passed.
|
||||
* @param script - Script to be executed.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::Eval(JNIEnv *jEnv, jsobject obj, const char *script, jobject *pjobj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
nsresult err = NS_OK;
|
||||
jobject member = NULL;
|
||||
jsval js_val = NULL;
|
||||
jsval function_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
jobject result = NULL;
|
||||
const char *codebase = NULL;
|
||||
JSPrincipals *principals = NULL;
|
||||
JSBool eval_succeeded = PR_FALSE;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
|
||||
result = NULL;
|
||||
if (!script) {
|
||||
JS_ReportError(cx, "illegal null string eval argument");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* Set up security stuff */
|
||||
principals = NULL;
|
||||
if (JSJ_callbacks->get_JSPrincipals_from_java_caller)
|
||||
principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx);
|
||||
codebase = principals ? principals->codebase : NULL;
|
||||
|
||||
/* Have the JS engine evaluate the unicode string */
|
||||
eval_succeeded = JS_EvaluateScriptForPrincipals(cx, js_obj, principals,
|
||||
script, strlen(script),
|
||||
codebase, 0, &js_val);
|
||||
if (!eval_succeeded)
|
||||
goto done;
|
||||
|
||||
/* Convert result to a subclass of java.lang.Object */
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &result, &dummy_bool);
|
||||
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NULL;
|
||||
|
||||
*pjobj = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param pJavaObject - Either a jobject or a pointer to a plugin instance
|
||||
* representing the java object.
|
||||
* @param pjobj - return value. This is a native js object
|
||||
* representing the window object of a frame
|
||||
* in which a applet/bean resides.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject, jsobject *pobj)
|
||||
{
|
||||
char *err_msg = NULL;
|
||||
JSContext *cx = NULL;
|
||||
JSObject *js_obj = NULL;
|
||||
jsval js_val = NULL;
|
||||
int dummy_cost = 0;
|
||||
JSBool dummy_bool = PR_FALSE;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
jobject java_obj = NULL;
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env)
|
||||
return NULL;
|
||||
|
||||
err_msg = NULL;
|
||||
java_obj = NULL;
|
||||
js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, pJavaObject, &err_msg);
|
||||
if (!js_obj) {
|
||||
if (err_msg) {
|
||||
JS_ReportError(cx, err_msg);
|
||||
free(err_msg);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
#if 0
|
||||
js_val = OBJECT_TO_JSVAL(js_obj);
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &java_obj, &dummy_bool);
|
||||
#endif
|
||||
done:
|
||||
if (!jsj_exit_js(cx, jsj_env, &saved_state))
|
||||
return NULL;
|
||||
|
||||
//*pjobj = java_obj;
|
||||
*pobj = (jint)js_obj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, jsobject obj)
|
||||
{
|
||||
JSContext *cx = NULL;
|
||||
JavaToJSSavedState saved_state = {NULL,NULL};
|
||||
JSJavaThreadState *jsj_env = NULL;
|
||||
JSObject *js_obj = (JSObject *)obj;
|
||||
|
||||
if(jEnv == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
jsj_env = jsj_enter_js(jEnv, NULL, &cx, NULL, &saved_state);
|
||||
if (!jsj_env) /* Note: memory leak if we exit here */
|
||||
return NS_ERROR_FAILURE;
|
||||
#ifdef PRESERVE_JSOBJECT_IDENTITY
|
||||
jsj_remove_js_obj_reflection_from_hashtable(cx, js_obj);
|
||||
#endif /* PRESERVE_JSOBJECT_IDENTITY */
|
||||
jsj_exit_js(cx, jsj_env, &saved_state);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnect:
|
||||
|
||||
nsCLiveconnect::nsCLiveconnect(nsISupports *aOuter)
|
||||
{
|
||||
NS_INIT_AGGREGATED(aOuter);
|
||||
jsj_init_js_obj_reflections_table();
|
||||
}
|
||||
|
||||
nsCLiveconnect::~nsCLiveconnect()
|
||||
{
|
||||
}
|
||||
|
||||
166
mozilla/js/src/liveconnect/nsCLiveconnect.h
Normal file
166
mozilla/js/src/liveconnect/nsCLiveconnect.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains class definition implementing the public interface.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the class definition to implement nsILiveconnect XP-COM interface.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef nsCLiveconnect_h___
|
||||
#define nsCLiveconnect_h___
|
||||
|
||||
#include "nsILiveconnect.h"
|
||||
#include "nsAgg.h"
|
||||
|
||||
|
||||
/**
|
||||
* nsCLiveconnect implements nsILiveconnect interface for navigator.
|
||||
* This is used by a JVM to implement netscape.javascript.JSObject functionality.
|
||||
*/
|
||||
class nsCLiveconnect :public nsILiveconnect {
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports and AggregatedQueryInterface:
|
||||
|
||||
NS_DECL_AGGREGATED
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsILiveconnect:
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member. If it is a basic data type it is converted to
|
||||
* a corresponding java type. If it is a NJSObject, then it is
|
||||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetSlot(JNIEnv *jEnv, jsobject obj, int index, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject jobj);
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject jobj);
|
||||
|
||||
/**
|
||||
* remove member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
RemoveMember(JNIEnv *jEnv, jsobject obj, const char *name);
|
||||
|
||||
/**
|
||||
* call a method of Native JSObject.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a method.
|
||||
* @param jobjArr - Array of jobjects representing parameters of method being caled.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Call(JNIEnv *jEnv, jsobject obj, const char *name, jobjectArray jobjArr, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* Evaluate a script with a Native JS Object representing scope.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param pNSIPrincipaArray - Array of principals to be used to compare privileges.
|
||||
* @param numPrincipals - Number of principals being passed.
|
||||
* @param script - Script to be executed.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
//Eval(JNIEnv *jEnv, jsobject obj, nsIPrincipal **pNSIPrincipaArray, PRInt32 numPrincipals, const char *script, jobject *pjobj);
|
||||
Eval(JNIEnv *jEnv, jsobject obj, const char *script, jobject *pjobj);
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param pJavaObject - Either a jobject or a pointer to a plugin instance
|
||||
* representing the java object.
|
||||
* @param pjobj - return value. This is a native js object
|
||||
* representing the window object of a frame
|
||||
* in which a applet/bean resides.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetWindow(JNIEnv *jEnv, void *pJavaObject, jsobject *pobj);
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
FinalizeJSObject(JNIEnv *jEnv, jsobject obj);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnect:
|
||||
|
||||
nsCLiveconnect(nsISupports *aOuter);
|
||||
virtual ~nsCLiveconnect(void);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // nsCLiveconnect_h___
|
||||
168
mozilla/js/src/liveconnect/nsCLiveconnectFactory.cpp
Normal file
168
mozilla/js/src/liveconnect/nsCLiveconnectFactory.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the implementation providing nsILiveconnect XP-COM interface.
|
||||
*
|
||||
*/
|
||||
#include "prtypes.h"
|
||||
#include "nspr.h"
|
||||
#include "prmem.h"
|
||||
#include "prmon.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsCLiveconnect.h"
|
||||
#include "nsCLiveconnectFactory.h"
|
||||
#include "nsRepository.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
static NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
|
||||
static NS_DEFINE_IID(kILiveconnectIID, NS_ILIVECONNECT_IID);
|
||||
|
||||
nsIFactory *nsCLiveconnectFactory::m_pNSIFactory = NULL;
|
||||
nsCLiveconnect *nsCLiveconnectFactory::m_pNSCLiveconnect = NULL;
|
||||
|
||||
|
||||
|
||||
/*+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* NSGetFactory:
|
||||
* Provides entry point to liveconnect dll.
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
extern "C" NS_EXPORT nsresult
|
||||
NSGetFactory(const nsCID &aClass, nsIFactory **aFactory)
|
||||
{
|
||||
|
||||
if (!aClass.Equals(kCLiveconnectCID)) {
|
||||
return NS_ERROR_FACTORY_NOT_LOADED; // XXX right error?
|
||||
}
|
||||
nsCLiveconnectFactory* pCLiveConnectFactory = new nsCLiveconnectFactory();
|
||||
if (pCLiveConnectFactory == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
pCLiveConnectFactory->AddRef();
|
||||
*aFactory = pCLiveConnectFactory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT PRBool
|
||||
NSCanUnload(void)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnectFactory::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
PR_ASSERT(NULL != aInstancePtr);
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kIFactoryIID) ||
|
||||
aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*) this;
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsCLiveconnectFactory)
|
||||
NS_IMPL_RELEASE(nsCLiveconnectFactory)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsIFactory:
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnectFactory::CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
nsCLiveconnect *pNSCLiveconnect = NULL;
|
||||
*aResult = NULL;
|
||||
|
||||
if (aOuter && !aIID.Equals(kISupportsIID))
|
||||
return NS_NOINTERFACE; // XXX right error?
|
||||
if (m_pNSCLiveconnect == NULL)
|
||||
{
|
||||
m_pNSCLiveconnect = new nsCLiveconnect(aOuter);
|
||||
}
|
||||
if (m_pNSCLiveconnect == NULL)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (m_pNSCLiveconnect->QueryInterface(aIID,
|
||||
(void**)aResult) != NS_OK) {
|
||||
// then we're trying get a interface other than nsISupports and
|
||||
// nsICapsManager
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnectFactory::LockFactory(PRBool aLock)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnectFactory:
|
||||
|
||||
nsCLiveconnectFactory::nsCLiveconnectFactory(void)
|
||||
{
|
||||
if( m_pNSIFactory != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
nsresult err = NS_OK;
|
||||
NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
|
||||
err = this->QueryInterface(kIFactoryIID, (void**)&m_pNSIFactory);
|
||||
if ( (err == NS_OK) && (m_pNSIFactory != NULL) )
|
||||
{
|
||||
NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
|
||||
nsRepository::RegisterFactory(kCLiveconnectCID, m_pNSIFactory,
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
nsCLiveconnectFactory::~nsCLiveconnectFactory()
|
||||
{
|
||||
if(mRefCnt == 0)
|
||||
{
|
||||
NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
|
||||
nsRepository::UnregisterFactory(kCLiveconnectCID, (nsIFactory *)m_pNSIFactory);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
59
mozilla/js/src/liveconnect/nsCLiveconnectFactory.h
Normal file
59
mozilla/js/src/liveconnect/nsCLiveconnectFactory.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the class definition to implement nsIFactory XP-COM interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsCLiveconnectFactory_h___
|
||||
#define nsCLiveconnectFactory_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
|
||||
class nsCLiveconnectFactory : public nsIFactory {
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsISupports and AggregatedQueryInterface:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsIFactory:
|
||||
|
||||
NS_IMETHOD
|
||||
CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
NS_IMETHOD
|
||||
LockFactory(PRBool aLock);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnectFactory:
|
||||
|
||||
nsCLiveconnectFactory(void);
|
||||
virtual ~nsCLiveconnectFactory(void);
|
||||
|
||||
protected:
|
||||
static nsIFactory *m_pNSIFactory;
|
||||
static nsCLiveconnect *m_pNSCLiveconnect;
|
||||
};
|
||||
|
||||
#endif // nsCLiveconnectFactory_h___
|
||||
157
mozilla/js/src/liveconnect/nsILiveconnect.h
Normal file
157
mozilla/js/src/liveconnect/nsILiveconnect.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the Java-vendor-neutral implementation of LiveConnect
|
||||
*
|
||||
* It contains the public XP-COM based interface for java to javascript communication.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsILiveconnect_h___
|
||||
#define nsILiveconnect_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "jni.h"
|
||||
|
||||
|
||||
typedef jint jsobject;
|
||||
|
||||
class nsILiveconnect : public nsISupports {
|
||||
public:
|
||||
/**
|
||||
* get member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member. If it is a basic data type it is converted to
|
||||
* a corresponding java type. If it is a NJSObject, then it is
|
||||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* get member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param pjobj - return parameter as a java object representing
|
||||
* the member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetSlot(JNIEnv *jEnv, jsobject obj, int index, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetMember(JNIEnv *jEnv, jsobject obj, const char *name, jobject jobj) = 0;
|
||||
|
||||
/**
|
||||
* set member of a Native JSObject for a given index.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param index - Index of a member.
|
||||
* @param jobj - Value to set. If this is a basic data type, it is converted
|
||||
* using standard JNI calls but if it is a wrapper to a JSObject
|
||||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetSlot(JNIEnv *jEnv, jsobject obj, int slot, jobject jobj) = 0;
|
||||
|
||||
/**
|
||||
* remove member of a Native JSObject for a given name.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
RemoveMember(JNIEnv *jEnv, jsobject obj, const char *name) = 0;
|
||||
|
||||
/**
|
||||
* call a method of Native JSObject.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param name - Name of a method.
|
||||
* @param jobjArr - Array of jobjects representing parameters of method being caled.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Call(JNIEnv *jEnv, jsobject obj, const char *name, jobjectArray jobjArr, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* Evaluate a script with a Native JS Object representing scope.
|
||||
*
|
||||
* @param obj - A Native JS Object.
|
||||
* @param pNSIPrincipaArray - Array of principals to be used to compare privileges.
|
||||
* @param numPrincipals - Number of principals being passed.
|
||||
* @param script - Script to be executed.
|
||||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
//Eval(jsobject obj, nsIPrincipal **pNSIPrincipaArray, PRInt32 numPrincipals, const char *script, jobject *pjobj) = 0;
|
||||
Eval(JNIEnv *jEnv, jsobject obj, const char *script, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param pJavaObject - Either a jobject or a pointer to a plugin instance
|
||||
* representing the java object.
|
||||
* @param pjobj - return value. This is a native js object
|
||||
* representing the window object of a frame
|
||||
* in which a applet/bean resides.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetWindow(JNIEnv *jEnv, void *pJavaObject, jsobject *pobj) = 0;
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
*
|
||||
* @param jEnv - JNIEnv on which the call is being made.
|
||||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
FinalizeJSObject(JNIEnv *jEnv, jsobject obj) = 0;
|
||||
|
||||
};
|
||||
|
||||
#define NS_ILIVECONNECT_IID \
|
||||
{ /* 68190910-3318-11d2-97f0-00805f8a28d0 */ \
|
||||
0x68190910, \
|
||||
0x3318, \
|
||||
0x11d2, \
|
||||
{0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \
|
||||
};
|
||||
|
||||
#define NS_CLIVECONNECT_CID \
|
||||
{ /* b8f0cef0-3931-11d2-97f0-00805f8a28d0 */ \
|
||||
0xb8f0cef0, \
|
||||
0x3931, \
|
||||
0x11d2, \
|
||||
{0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \
|
||||
};
|
||||
|
||||
#endif // nsILiveconnect_h___
|
||||
@@ -1,5 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
</IfModule>
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_controller.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* This file is application-wide controller file. You can put all
|
||||
* application-wide controller-related methods here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* Add your application-wide methods in the class below, your controllers
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
*/
|
||||
|
||||
uses('Sanitize');
|
||||
|
||||
class AppController extends Controller {
|
||||
|
||||
/**
|
||||
* This function is intended to be used with url parameters when passing them to
|
||||
* a view. (This is useful when echoing values out in <input> tags, etc.
|
||||
* Note that the keys to the arrays are escaped as well.
|
||||
*
|
||||
* @param array dirty parameters
|
||||
* @return array cleaned values
|
||||
*/
|
||||
function decodeAndSanitize($params)
|
||||
{
|
||||
$clean = array();
|
||||
|
||||
foreach ($params as $var => $val) {
|
||||
$var = $this->Sanitize->html(urldecode($var));
|
||||
$val = $this->Sanitize->html(urldecode($val));
|
||||
|
||||
$clean[$var] = $val;
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_model.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Application model for Cake.
|
||||
*
|
||||
* This file is application-wide model file. You can put all
|
||||
* application-wide model-related methods here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Application model for Cake.
|
||||
*
|
||||
* Add your application-wide methods in the class below, your models
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
*/
|
||||
|
||||
uses('sanitize');
|
||||
|
||||
class AppModel extends Model {
|
||||
|
||||
/**
|
||||
* Will clean arrays for input into SQL.
|
||||
* Note that the array keys are getting cleaned here as well. If you're using strings
|
||||
* (with escapable characters in them) as keys to your array, be extra careful.
|
||||
*
|
||||
* @access public
|
||||
* @param array to be cleaned
|
||||
* @return array with sql escaped
|
||||
*/
|
||||
function cleanArrayForSql($array)
|
||||
{
|
||||
$sanitize = new Sanitize();
|
||||
$clean = array();
|
||||
|
||||
foreach ($array as $var => $val)
|
||||
{
|
||||
$var = $sanitize->sql($var);
|
||||
$val = $sanitize->sql($val);
|
||||
$clean[$var] = $val;
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,76 +0,0 @@
|
||||
;<?php die() ?>
|
||||
; SVN FILE: $Id: acl.ini.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $
|
||||
;/**
|
||||
; * Short description for file.
|
||||
; *
|
||||
; *
|
||||
; * PHP versions 4 and 5
|
||||
; *
|
||||
; * CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
; * Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
; * 1785 E. Sahara Avenue, Suite 490-204
|
||||
; * Las Vegas, Nevada 89104
|
||||
; *
|
||||
; * Licensed under The MIT License
|
||||
; * Redistributions of files must retain the above copyright notice.
|
||||
; *
|
||||
; * @filesource
|
||||
; * @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
; * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
; * @package cake
|
||||
; * @subpackage cake.app.config
|
||||
; * @since CakePHP v 0.10.0.1076
|
||||
; * @version $Revision: 1.1.1.1 $
|
||||
; * @modifiedby $LastChangedBy: phpnut $
|
||||
; * @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
; * @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
; */
|
||||
|
||||
; acl.ini.php - Cake ACL Configuration
|
||||
; ---------------------------------------------------------------------
|
||||
; Use this file to specify user permissions.
|
||||
; aco = access control object (something in your application)
|
||||
; aro = access request object (something requesting access)
|
||||
;
|
||||
; User records are added as follows:
|
||||
;
|
||||
; [uid]
|
||||
; groups = group1, group2, group3
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; Group records are added in a similar manner:
|
||||
;
|
||||
; [gid]
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; The allow, deny, and groups sections are all optional.
|
||||
; NOTE: groups names *cannot* ever be the same as usernames!
|
||||
;
|
||||
; ACL permissions are checked in the following order:
|
||||
; 1. Check for user denies (and DENY if specified)
|
||||
; 2. Check for user allows (and ALLOW if specified)
|
||||
; 3. Gather user's groups
|
||||
; 4. Check group denies (and DENY if specified)
|
||||
; 5. Check group allows (and ALLOW if specified)
|
||||
; 6. If no aro, aco, or group information is found, DENY
|
||||
;
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
;-------------------------------------
|
||||
;Users
|
||||
;-------------------------------------
|
||||
|
||||
[username-goes-here]
|
||||
groups = group1, group2
|
||||
deny = aco1, aco2
|
||||
allow = aco3, aco4
|
||||
|
||||
;-------------------------------------
|
||||
;Groups
|
||||
;-------------------------------------
|
||||
|
||||
[groupname-goes-here]
|
||||
deny = aco5, aco6
|
||||
allow = aco7, aco8
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: bootstrap.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.10.8.2117
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* This file is loaded automatically by the app/webroot/index.php file after the core bootstrap.php is loaded
|
||||
* This is an application wide file to load any function that is not used within a class define.
|
||||
* You can also use this to include or require any files in your application.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The settings below can be used to set additional paths to models, views and controllers.
|
||||
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
|
||||
*
|
||||
* $modelPaths = array('full path to models', 'second full path to models', 'etc...');
|
||||
* $viewPaths = array('this path to views', 'second full path to views', 'etc...');
|
||||
* $controllerPaths = array('this path to controllers', 'second full path to controllers', 'etc...');
|
||||
*
|
||||
*/
|
||||
|
||||
//EOF
|
||||
?>
|
||||
@@ -1,153 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: core.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* This is core configuration file.
|
||||
*
|
||||
* Use it to configure core behaviour ofCake.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* If you do not have mod rewrite on your system
|
||||
* or if you prefer to use CakePHP pretty urls.
|
||||
* uncomment the line below.
|
||||
* Note: If you do have mod rewrite but prefer the
|
||||
* CakePHP pretty urls, you also have to remove the
|
||||
* .htaccess files
|
||||
* release/.htaccess
|
||||
* release/app/.htaccess
|
||||
* release/app/webroot/.htaccess
|
||||
*/
|
||||
//define ('BASE_URL', env('SCRIPT_NAME'));
|
||||
|
||||
/**
|
||||
* Set debug level here:
|
||||
* - 0: production
|
||||
* - 1: development
|
||||
* - 2: full debug with sql
|
||||
* - 3: full debug with sql and dump of the current object
|
||||
*
|
||||
* In production, the "flash messages" redirect after a time interval.
|
||||
* With the other debug levels you get to click the "flash message" to continue.
|
||||
*
|
||||
*/
|
||||
define('DEBUG', 0);
|
||||
/**
|
||||
* Turn of caching checking wide.
|
||||
* You must still use the controller var cacheAction inside you controller class.
|
||||
* You can either set it controller wide, or in each controller method.
|
||||
* use var $cacheAction = true; or in the controller method $this->cacheAction = true;
|
||||
*/
|
||||
define ('CACHE_CHECK', false);
|
||||
/**
|
||||
* Error constant. Used for differentiating error logging and debugging.
|
||||
* Currently PHP supports LOG_DEBUG
|
||||
*/
|
||||
define ('LOG_ERROR', 2);
|
||||
/**
|
||||
* CakePHP includes 3 types of session saves
|
||||
* database or file. Set this to your preferred method.
|
||||
* If you want to use your own save handler place it in
|
||||
* app/config/name.php DO NOT USE file or database as the name.
|
||||
* and use just the name portion below.
|
||||
*
|
||||
* Setting this to cake will save files to /cakedistro/tmp directory
|
||||
* Setting it to php will use the php default save path
|
||||
* Setting it to database will use the database
|
||||
*
|
||||
*
|
||||
*/
|
||||
define('CAKE_SESSION_SAVE', 'php');
|
||||
/**
|
||||
* Set a random string of used in session.
|
||||
*
|
||||
*/
|
||||
define('CAKE_SESSION_STRING', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
|
||||
/**
|
||||
* Set the name of session cookie
|
||||
*
|
||||
*/
|
||||
define('CAKE_SESSION_COOKIE', 'CAKEPHP');
|
||||
|
||||
/**
|
||||
* Set level of Cake security.
|
||||
*
|
||||
*/
|
||||
define('CAKE_SECURITY', 'high');
|
||||
|
||||
/**
|
||||
* Set Cake Session time out.
|
||||
* If CAKE_SECURITY define is set
|
||||
* high: multiplied by 10
|
||||
* medium: is multiplied by 100
|
||||
* low is: multiplied by 300
|
||||
*
|
||||
* Number below is seconds.
|
||||
*/
|
||||
define('CAKE_SESSION_TIMEOUT', '120');
|
||||
|
||||
/**
|
||||
* Uncomment the define below to use cake built in admin routes.
|
||||
* You can set this value to anything you want.
|
||||
* All methods related to the admin route should be prefixed with the
|
||||
* name you set CAKE_ADMIN to.
|
||||
* For example: admin_index, admin_edit
|
||||
*/
|
||||
//define('CAKE_ADMIN', 'admin');
|
||||
|
||||
/**
|
||||
* The define below is used to turn cake built webservices
|
||||
* on or off. Default setting is off.
|
||||
*/
|
||||
define('WEBSERVICES', 'off');
|
||||
|
||||
/**
|
||||
* Compress output CSS (removing comments, whitespace, repeating tags etc.)
|
||||
* This requires a/var/cache directory to be writable by the web server (caching).
|
||||
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use Controller::cssTag().
|
||||
*/
|
||||
define('COMPRESS_CSS', false);
|
||||
|
||||
/**
|
||||
* If set to true, helpers would output data instead of returning it.
|
||||
*/
|
||||
define('AUTO_OUTPUT', false);
|
||||
|
||||
/**
|
||||
* If set to false, session would not automatically be started.
|
||||
*/
|
||||
define('AUTO_SESSION', true);
|
||||
|
||||
/**
|
||||
* Set the max size of file to use md5() .
|
||||
*/
|
||||
define('MAX_MD5SIZE', (5*1024)*1024 );
|
||||
|
||||
/**
|
||||
* To use Access Control Lists with Cake...
|
||||
*/
|
||||
define('ACL_CLASSNAME', 'DB_ACL');
|
||||
define('ACL_FILENAME', 'dbacl'.DS.'db_acl');
|
||||
|
||||
?>
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: database.php.default,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* This is core configuration file.
|
||||
*
|
||||
* Use it to configure core behaviour ofCake.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* In this file you set up your database connection details.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.config
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Database configuration class.
|
||||
* You can specify multiple configurations for production, development and testing.
|
||||
*
|
||||
* driver =>
|
||||
* mysql, postgres, sqlite, adodb-drivername, pear-drivername
|
||||
*
|
||||
* connect =>
|
||||
* MySQL set the connect to either mysql_pconnect of mysql_connect
|
||||
* PostgreSQL set the connect to either pg_pconnect of pg_connect
|
||||
* SQLite set the connect to sqlite_popen sqlite_open
|
||||
* ADOdb set the connect to one of these
|
||||
* (http://phplens.com/adodb/supported.databases.html) and
|
||||
* append it '|p' for persistent connection. (mssql|p for example, or just mssql for not persistent)
|
||||
*
|
||||
* host =>
|
||||
* the host you connect to the database
|
||||
* MySQL 'localhost' to add a port number use 'localhost:port#'
|
||||
* PostgreSQL 'localhost' to add a port number use 'localhost port=5432'
|
||||
*
|
||||
*/
|
||||
class DATABASE_CONFIG
|
||||
{
|
||||
var $default = array('driver' => 'mysql',
|
||||
'connect' => 'mysql_connect',
|
||||
'host' => 'localhost',
|
||||
'login' => 'user',
|
||||
'password' => 'password',
|
||||
'database' => 'project_name',
|
||||
'prefix' => '');
|
||||
|
||||
var $test = array('driver' => 'mysql',
|
||||
'connect' => 'mysql_connect',
|
||||
'host' => 'localhost',
|
||||
'login' => 'user',
|
||||
'password' => 'password',
|
||||
'database' => 'project_name-test',
|
||||
'prefix' => '');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: inflections.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Custom Inflected Words.
|
||||
*
|
||||
* This file is used to hold words that are not matched in the normail Inflector::pluralize() and
|
||||
* Inflector::singularize()
|
||||
*
|
||||
* PHP versions 4 and %
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 1.0.0.2312
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a key => value array of regex used to match words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $pluralRules = array('/(s)tatus$/i' => '\1\2tatuses', '/^(ox)$/i' => '\1\2en', '/([m|l])ouse$/i' => '\1ice');
|
||||
*/
|
||||
$pluralRules = array();
|
||||
/**
|
||||
* This is a key only array of plural words that should not be inflected.
|
||||
* Notice the last comma
|
||||
*
|
||||
* $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox');
|
||||
*/
|
||||
$uninflectedPlural = array();
|
||||
/**
|
||||
* This is a key => value array of plural irregular words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers')
|
||||
*/
|
||||
$irregularPlural = array();
|
||||
/**
|
||||
* This is a key => value array of regex used to match words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $singularRules = array('/(s)tatuses$/i' => '\1\2tatus', '/(matr)ices$/i' =>'\1ix','/(vert|ind)ices$/i')
|
||||
*/
|
||||
$singularRules = array();
|
||||
/**
|
||||
* This is a key only array of singular words that should not be inflected.
|
||||
* You should not have to change this value below if you do change it use same format
|
||||
* as the $uninflectedPlural above.
|
||||
*/
|
||||
$uninflectedSingular = $uninflectedPlural;
|
||||
/**
|
||||
* This is a key => value array of singular irregular words.
|
||||
* Most of the time this will be a reverse of the above $irregularPlural array
|
||||
* You should not have to change this value below if you do change it use same format
|
||||
*
|
||||
* $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother')
|
||||
*/
|
||||
$irregularSingular = array_flip($irregularPlural);
|
||||
?>
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: routes.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* In this file, you set up routes to your controllers and their actions.
|
||||
* Routes are very important mechanism that allows you to freely connect
|
||||
* different urls to chosen controllers and their actions (functions).
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Here, we are connecting '/' (base path) to controller called 'Pages',
|
||||
* its action called 'display', and we pass a param to select the view file
|
||||
* to use (in this case, /app/views/pages/home.thtml)...
|
||||
*/
|
||||
$Route->connect ('/', array('controller'=>'results', 'action'=>'', ''));
|
||||
|
||||
/**
|
||||
* ...and connect the rest of 'Pages' controller's urls.
|
||||
*/
|
||||
$Route->connect ('/pages/*', array('controller'=>'pages', 'action'=>'display'));
|
||||
|
||||
/**
|
||||
* Then we connect url '/test' to our test controller. This is helpfull in
|
||||
* developement.
|
||||
*/
|
||||
$Route->connect ('/tests', array('controller'=>'tests', 'action'=>'index'));
|
||||
|
||||
?>
|
||||
@@ -1,30 +0,0 @@
|
||||
CREATE TABLE `acos` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`model` varchar(255) NOT NULL default '',
|
||||
`object_id` int(11) default NULL,
|
||||
`alias` varchar(255) NOT NULL default '',
|
||||
`lft` int(11) default NULL,
|
||||
`rght` int(11) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `aros` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`model` varchar(255) NOT NULL default '',
|
||||
`user_id` int(11) default NULL,
|
||||
`alias` varchar(255) NOT NULL default '',
|
||||
`lft` int(11) default NULL,
|
||||
`rght` int(11) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `aros_acos` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`aro_id` int(11) default NULL,
|
||||
`aco_id` int(11) default NULL,
|
||||
`_create` int(1) NOT NULL default '0',
|
||||
`_read` int(1) NOT NULL default '0',
|
||||
`_update` int(1) NOT NULL default '0',
|
||||
`_delete` int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
@@ -1,11 +0,0 @@
|
||||
-- @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
-- @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
-- @since CakePHP v 0.10.8.1997
|
||||
-- @version $Revision: 1.1.1.1 $
|
||||
|
||||
CREATE TABLE cake_sessions (
|
||||
id varchar(255) NOT NULL default '',
|
||||
data text,
|
||||
expires int(11) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
class ApplicationsController extends AppController {
|
||||
|
||||
var $name = 'Applications';
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
class IntentionsController extends AppController {
|
||||
|
||||
var $name = 'Intentions';
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
class IssuesController extends AppController {
|
||||
|
||||
var $name = 'Issues';
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* Include the CSV library. It would be nice to make this OO sometime */
|
||||
vendor('csv/csv');
|
||||
|
||||
class ResultsController extends AppController {
|
||||
|
||||
var $name = 'Results';
|
||||
|
||||
/**
|
||||
* Model's this controller uses
|
||||
* @var array
|
||||
*/
|
||||
var $uses = array('Application','Result');
|
||||
|
||||
/**
|
||||
* Cake Helpers
|
||||
* @var array
|
||||
*/
|
||||
var $helpers = array('Html', 'Javascript', 'Export', 'Pagination','Time');
|
||||
|
||||
/**
|
||||
* Pagination helper variable array
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
var $pagination_parameters = array();
|
||||
|
||||
/**
|
||||
* Will hold a sanitize object
|
||||
* @var object
|
||||
*/
|
||||
var $Sanitize;
|
||||
|
||||
/**
|
||||
* Constructor - sets up the sanitizer and the pagination
|
||||
*/
|
||||
function ResultsController()
|
||||
{
|
||||
parent::AppController();
|
||||
|
||||
$this->Sanitize = new Sanitize();
|
||||
|
||||
// Pagination Stuff
|
||||
$this->pagination_parameters['show'] = empty($_GET['show'])? '10' : $this->Sanitize->paranoid($_GET['show']);
|
||||
$this->pagination_parameters['sortBy'] = empty($_GET['sort'])? 'created' : $this->Sanitize->paranoid($_GET['sort']);
|
||||
$this->pagination_parameters['direction'] = empty($_GET['direction'])? 'desc': $this->Sanitize->paranoid($_GET['direction']);
|
||||
$this->pagination_parameters['page'] = empty($_GET['page'])? '1': $this->Sanitize->paranoid($_GET['page']);
|
||||
$this->pagination_parameters['order'] = $this->modelClass.'.'.$this->pagination_parameters['sortBy'].' '.strtoupper($this->pagination_parameters['direction']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Front page will show the graph
|
||||
*/
|
||||
function index()
|
||||
{
|
||||
// Products dropdown
|
||||
$this->set('products', $this->Application->getApplications());
|
||||
|
||||
// Fill in all the data passed in $_GET
|
||||
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
|
||||
|
||||
// We'll need to include the graphing libraries
|
||||
$this->set('include_graph_libraries', true);
|
||||
|
||||
// Core data to show on page
|
||||
$this->set('descriptionAndTotalsData',$this->Result->getDescriptionAndTotalsData($this->params['url']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a table of user comments
|
||||
*/
|
||||
function comments()
|
||||
{
|
||||
// Products dropdown
|
||||
$this->set('products', $this->Application->getApplications());
|
||||
|
||||
// Fill in all the data passed in $_GET
|
||||
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
|
||||
|
||||
// Pagination settings
|
||||
$paging['style'] = 'html';
|
||||
$paging['link'] = "/results/comments/?product=".urlencode($this->params['url']['product'])."&start_date=".urlencode($this->params['url']['start_date'])."&end_date=".urlencode($this->params['url']['end_date'])."&show={$this->pagination_parameters['show']}&sort={$this->pagination_parameters['sortBy']}&direction={$this->pagination_parameters['direction']}&page=";
|
||||
$paging['count'] = $this->Result->getCommentCount($this->params['url']);
|
||||
$paging['page'] = $this->pagination_parameters['page'];
|
||||
$paging['limit'] = $this->pagination_parameters['show'];
|
||||
$paging['show'] = array('10','25','50');
|
||||
|
||||
// No point in showing them an error if they click on "show 50" but they are
|
||||
// already on the last page.
|
||||
if ($paging['count'] < ($this->pagination_parameters['page'] * ($this->pagination_parameters['show']/2))) {
|
||||
$this->pagination_parameters['page'] = $paging['page'] = 1;
|
||||
}
|
||||
|
||||
// Set pagination array
|
||||
$this->set('paging',$paging);
|
||||
|
||||
// Core data to show on page
|
||||
$this->set('commentsData',$this->Result->getComments($this->params['url'], $this->pagination_parameters));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a csv
|
||||
*/
|
||||
function csv()
|
||||
{
|
||||
// Get rid of the header/footer/etc.
|
||||
$this->layout = null;
|
||||
|
||||
// Our CSV library sends headers and everything. Keep the view empty!
|
||||
csv_send_csv($this->Result->getCsvExportData($this->params['url']));
|
||||
|
||||
// I'm not exiting here in case someone is going to use post callback stuff.
|
||||
// In development, that means extra lines get added to our CSVs, but in
|
||||
// production it should be clean.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: index.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app
|
||||
* @since CakePHP v 0.10.0.1076
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
require 'webroot'.DIRECTORY_SEPARATOR.'index.php';
|
||||
?>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
class Application extends AppModel {
|
||||
var $name = 'Application';
|
||||
|
||||
var $hasOne = array('Result');
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Intention' => array('className' => 'Intention'),
|
||||
'Issue' => array('className' => 'Issue')
|
||||
);
|
||||
|
||||
/**
|
||||
* This was added because running findAll() on this model does a left join on the
|
||||
* results table which takes around 10 seconds to grab all the data. All I want
|
||||
* is a list of the applications...
|
||||
*
|
||||
* @return array rows representing each application
|
||||
*/
|
||||
function getApplications()
|
||||
{
|
||||
return $this->query('SELECT * FROM `applications` ORDER BY `id`');
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
class Intention extends AppModel {
|
||||
var $name = 'Intention';
|
||||
|
||||
var $hasOne = array('Result');
|
||||
|
||||
var $hasAndBelongsToMany = array('Application' =>
|
||||
array('className' => 'Application')
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
class Issue extends AppModel {
|
||||
var $name = 'Issue';
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Application' => array('className' => 'Application'),
|
||||
'Result' => array('className' => 'Result')
|
||||
);
|
||||
}
|
||||
?>
|
||||
@@ -1,339 +0,0 @@
|
||||
<?php
|
||||
class Result extends AppModel {
|
||||
var $name = 'Result';
|
||||
|
||||
var $belongsTo = array('Application', 'Intention');
|
||||
|
||||
var $hasAndBelongsToMany = array('Issue' =>
|
||||
array('className' => 'Issue')
|
||||
);
|
||||
|
||||
/**
|
||||
* Count's all the comments, according to the parameters.
|
||||
* @param array URL parameters
|
||||
* @return Cake's findCount() value
|
||||
*/
|
||||
function getCommentCount($params)
|
||||
{
|
||||
// Clean parameters
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
// We only want to see rows with comments
|
||||
$_conditions = array("comments NOT LIKE ''");
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` >= '{$_date}'");
|
||||
}
|
||||
}
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` <= '{$_date}'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
/* Note that 'Application' is not the actual name of the table! You can
|
||||
* thank cake for that.*/
|
||||
array_push($_conditions, "`Application`.`name` LIKE '%{$_product}%'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '%{$_version}%'");
|
||||
} else {
|
||||
// defaults I guess?
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
// Do the actual query
|
||||
$comments = $this->findCount($_conditions);
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will retrieve all the comments within param's and pagination's parameters
|
||||
* @param array URL parameters
|
||||
* @param array pagination values from the controller
|
||||
* @param boolean if privacy is true phone numbers and email addresses will be
|
||||
* masked
|
||||
* @return cake result set
|
||||
*/
|
||||
function getComments($params, $pagination, $privacy=true)
|
||||
{
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
// We only want to see rows with comments
|
||||
$_conditions = array("comments NOT LIKE ''");
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` >= '{$_date}'");
|
||||
}
|
||||
}
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` <= '{$_date}'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
/* Note that 'Application' is not the actual name of the table! You can
|
||||
* thank cake for that.*/
|
||||
array_push($_conditions, "`Application`.`name` LIKE '%{$_product}%'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '%{$_version}%'");
|
||||
} else {
|
||||
// defaults I guess?
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
$comments = $this->findAll($_conditions, null, $pagination['order'], $pagination['show'], $pagination['page']);
|
||||
|
||||
if ($privacy) {
|
||||
// Pull out all the email addresses and phone numbers
|
||||
foreach ($comments as $var => $val) {
|
||||
|
||||
// Handle foo@bar.com
|
||||
$_email_regex = '/\ ?(.+)?@(.+)?\.(.+)?\ ?/';
|
||||
$comments[$var]['Result']['comments'] = preg_replace($_email_regex,'$1@****.$3',$comments[$var]['Result']['comments']);
|
||||
$comments[$var]['Result']['intention_text'] = preg_replace($_email_regex,'$1@****.$3',$comments[$var]['Result']['intention_text']);
|
||||
|
||||
// Handle xxx-xxx-xxxx
|
||||
$_phone_regex = '/([0-9]{3})[ .-]?[0-9]{4}/';
|
||||
$comments[$var]['Result']['comments'] = preg_replace($_phone_regex,'$1-****',$comments[$var]['Result']['comments']);
|
||||
$comments[$var]['Result']['intention_text'] = preg_replace($_phone_regex,'$1-****',$comments[$var]['Result']['intention_text']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function runs the query to get the export data for the CSV file.
|
||||
*
|
||||
* @param array URL parameters
|
||||
* @param boolean if privacy is true phone numbers and email addresses will be
|
||||
* masked
|
||||
* @return array two dimensional array that should be pretty easy to transform
|
||||
* into a CSV.
|
||||
*/
|
||||
function getCsvExportData($params, $privacy=true)
|
||||
{
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
// We have to use a left join here because there isn't always an intention
|
||||
$_query = "
|
||||
SELECT
|
||||
`results`.`id`,
|
||||
`results`.`created`,
|
||||
`results`.`intention_text` as `intention_other`,
|
||||
`results`.`comments`,
|
||||
`intentions`.`description` as `intention`
|
||||
FROM `results`
|
||||
LEFT JOIN `intentions` ON `results`.`intention_id`=`intentions`.`id`
|
||||
INNER JOIN `applications` ON `applications`.`id` = `results`.`application_id`
|
||||
WHERE
|
||||
1=1
|
||||
";
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query .= " AND `results`.`created` >= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query .= " AND `results`.`created` <= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
$_query .= " AND `applications`.`name` LIKE '{$_product}'";
|
||||
$_query .= " AND `applications`.`version` LIKE '{$_version}'";
|
||||
} else {
|
||||
// defaults I guess?
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
|
||||
$_query .= " ORDER BY `results`.`created` ASC";
|
||||
|
||||
$res = $this->query($_query);
|
||||
|
||||
// Since we're exporting to a CSV, we need to flatten the results into a 2
|
||||
// dimensional table array
|
||||
$newdata = array();
|
||||
|
||||
foreach ($res as $result) {
|
||||
|
||||
$newdata[] = array_merge($result['results'], $result['intentions']);
|
||||
}
|
||||
|
||||
if ($privacy) {
|
||||
// Pull out all the email addresses and phone numbers
|
||||
foreach ($newdata as $var => $val) {
|
||||
|
||||
// Handle foo@bar.com
|
||||
$_email_regex = '/\ ?(.+)?@(.+)?\.(.+)?\ ?/';
|
||||
$newdata[$var]['comments'] = preg_replace($_email_regex,'$1@****.$3',$newdata[$var]['comments']);
|
||||
$newdata[$var]['intention_other'] = preg_replace($_email_regex,'$1@****.$3',$newdata[$var]['intention_other']);
|
||||
|
||||
// Handle xxx-xxx-xxxx
|
||||
$_phone_regex = '/([0-9]{3})[ .-]?[0-9]{4}/';
|
||||
$newdata[$var]['comments'] = preg_replace($_phone_regex,'$1-****',$newdata[$var]['comments']);
|
||||
$newdata[$var]['intention_other'] = preg_replace($_phone_regex,'$1-****',$newdata[$var]['intention_other']);
|
||||
}
|
||||
}
|
||||
|
||||
// Our CSV library just prints out everything in order, so we have to put the
|
||||
// column labels on here ourselves
|
||||
$newdata = array_merge(array(array_keys($newdata[0])), $newdata);
|
||||
|
||||
return $newdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will retrieve the information used for graphing.
|
||||
* @param the url parameters (unescaped)
|
||||
* @return a result set
|
||||
*/
|
||||
function getDescriptionAndTotalsData($params)
|
||||
{
|
||||
// Clean parameters for inserting into SQL
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
/* It would be nice to drop something like this in the SELECT:
|
||||
*
|
||||
* CONCAT(COUNT(*)/(SELECT COUNT(*) FROM our_giant_query_all_over_again)*100,'%') AS `percentage`
|
||||
*/
|
||||
|
||||
$_query = "
|
||||
SELECT
|
||||
issues.description,
|
||||
COUNT( DISTINCT results.id ) AS total
|
||||
FROM
|
||||
issues
|
||||
LEFT JOIN
|
||||
issues_results ON issues_results.issue_id=issues.id
|
||||
LEFT JOIN results ON results.id=issues_results.result_id AND results.application_id=applications.id
|
||||
JOIN applications_issues ON applications_issues.issue_id=issues.id
|
||||
JOIN applications ON applications.id=applications_issues.application_id
|
||||
WHERE 1=1
|
||||
";
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query.= " AND `results`.`created` >= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query .= " AND `results`.`created` <= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
$_query .= " AND `applications`.`name` LIKE '{$_product}'";
|
||||
$_query .= " AND `applications`.`version` LIKE '{$_version}'";
|
||||
} else {
|
||||
// defaults I guess?
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
|
||||
$_query .= " GROUP BY `issues`.`description`
|
||||
ORDER BY `issues`.`description` DESC";
|
||||
|
||||
return $this->query($_query);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,188 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Functions that take a db result and export it to CSV.
|
||||
* Usage example:
|
||||
* <code>
|
||||
* if ($_GET['csv'])
|
||||
* {
|
||||
* $res=db_query("SELECT * FROM fic_courses");
|
||||
* csv_send_csv($res);
|
||||
* exit;
|
||||
* }
|
||||
* </code>
|
||||
* @package libs
|
||||
* @subpackage csv
|
||||
* @author Richard Faaberg <faabergr@onid.orst.edu>
|
||||
* @author Mike Morgan <mike.morgan@oregonstate.edu>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use a resource or two dimensional array, then send the CSV results to user.
|
||||
* @param mixed $res MySQL resource / result, or a two dimensional array
|
||||
* @param string $name name of the export file
|
||||
* @return bool true if file sent, false otherwise
|
||||
*/
|
||||
function csv_send_csv($res,$name=null)
|
||||
{
|
||||
// set name of the export file
|
||||
$filename=(is_null($name))?'export-'.date('Y-m-d').'.csv':$name.'.csv';
|
||||
// check for valid resource
|
||||
if ( is_resource($res) )
|
||||
{
|
||||
$csv=csv_export_to_csv($res);
|
||||
}
|
||||
elseif( is_array($res) && !empty($res) )
|
||||
{
|
||||
foreach ($res as $row)
|
||||
{
|
||||
if ( !is_array($row) )
|
||||
;
|
||||
else
|
||||
$csv[] = csv_array_to_csv($row)."\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_array($csv) )
|
||||
{
|
||||
// stream csv to user
|
||||
header("Content-type: application/x-csv");
|
||||
header('Content-disposition: inline; filename="'.$filename.'"');
|
||||
header('Cache-Control: private');
|
||||
header('Pragma: public');
|
||||
foreach ($csv as $row)
|
||||
{
|
||||
echo $row;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace quotes inside of a field with double quotes, which is something CSV requires.
|
||||
* @param string $string unquoted quotes
|
||||
* @return string $string quoted quotes
|
||||
*/
|
||||
function csv_fix_quotes($string)
|
||||
{
|
||||
return preg_replace('/"/','""',$string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace line breaks with commas trailed by a space.
|
||||
* @param string $string string containing line breaks
|
||||
* @param string string without line breaks
|
||||
*/
|
||||
function csv_fix_line_breaks($string)
|
||||
{
|
||||
return preg_replace('/(\n\r|\r)/','\n',$string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces instances of double quotes in a string with a single quote.
|
||||
* @param string $string the string to perform the replacement on
|
||||
* @return string the string with "" replaced by "
|
||||
*/
|
||||
function csv_unfix_quotes($string)
|
||||
{
|
||||
return preg_replace('/""/', '"', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place quotes outside of every field, which inherently solves space, line break issues.
|
||||
* @param string $string
|
||||
* @return string $string with quotes around it
|
||||
*/
|
||||
function csv_add_quotes($string)
|
||||
{
|
||||
return '"'.$string.'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes quotes from the beginning and the end of a string.
|
||||
* @param string $string the string to remove the quotes from
|
||||
* @return string the string, sans quotes at the beginning and end
|
||||
*/
|
||||
function csv_remove_quotes($string)
|
||||
{
|
||||
$pattern = "/^\"(.*)\"$/";
|
||||
$replacement = "$1";
|
||||
return preg_replace($pattern, $replacement, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array into a CSV string with quotes around each value.
|
||||
* @param array $array
|
||||
* @return string the values in $array surrounded by quotes and separated by commas
|
||||
*/
|
||||
function csv_array_to_csv($array)
|
||||
{
|
||||
$csv_arr = array();
|
||||
foreach ($array as $value)
|
||||
{
|
||||
$csv_arr[]=csv_add_quotes(csv_fix_quotes(csv_fix_line_breaks($value)));
|
||||
}
|
||||
$csv_string=implode(',',$csv_arr);
|
||||
|
||||
return $csv_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a CSV string into an array.
|
||||
* Please use sparingly - this creates temp files
|
||||
* @param string $string the CSV string
|
||||
* @return array the elements from the CSV string in an array
|
||||
*/
|
||||
function csv_csv_to_array($string)
|
||||
{
|
||||
$return = array();
|
||||
$length = strlen($string);
|
||||
|
||||
// create a temp file and write the string to it
|
||||
$tmpfname = tempnam('/tmp', 'csvlib');
|
||||
$fh = fopen($tmpfname, 'w');
|
||||
fwrite($fh, $string);
|
||||
fclose($fh);
|
||||
|
||||
// open the file for csv parsing
|
||||
$csvh = fopen($tmpfname, 'r');
|
||||
while (($arraydata = fgetcsv($csvh, $length, ',')) !== false)
|
||||
{
|
||||
$return = array_merge($return, $arraydata);
|
||||
}
|
||||
|
||||
fclose($csvh);
|
||||
unlink($tmpfname);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a CSV file into a two dimensional array
|
||||
* It returns all the rows in the file, so if the first row are headers, you'd need to take care of that in the returned array
|
||||
* @param string $filepath the path to the csv file
|
||||
* @param string $delimiter delimiter, default to ','
|
||||
* @param string $enclosure enclosure character, default to '"'
|
||||
* @return &array the two dimensional array with the csv file content, or an empty if an error occured
|
||||
*/
|
||||
function &csv_csv_file_to_array($filepath, $delimiter=',', $enclosure='"')
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if (!file_exists($filepath) || !is_readable($filepath))
|
||||
return $return;
|
||||
|
||||
$fh =& fopen($filepath, 'r');
|
||||
$size = filesize($filepath)+1;
|
||||
|
||||
while ($data =& fgetcsv($fh, $size, $delimiter, $enclosure))
|
||||
{
|
||||
$return[] = $data;
|
||||
}
|
||||
|
||||
fclose($fh);
|
||||
|
||||
return $return;
|
||||
}
|
||||
?>
|
||||
@@ -1,11 +0,0 @@
|
||||
<div id="t_footer">
|
||||
</div>
|
||||
|
||||
<!-- t_wrapper -->
|
||||
</div>
|
||||
|
||||
<!-- t_border -->
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Mozilla Uninstall Survey Data</title>
|
||||
<meta name="author" content="Mozilla Corporation" />
|
||||
<meta name="copyright" content="Mozilla Corporation" />
|
||||
<?php echo $html->charset('UTF-8'); ?>
|
||||
<?php echo $html->css('screen'); ?>
|
||||
<?php if (isset($include_graph_libraries) && $include_graph_libraries):
|
||||
echo $javascript->link('mochikit/MochiKit.js');
|
||||
echo $javascript->link('plotkit/Base.js');
|
||||
echo $javascript->link('plotkit/Layout.js');
|
||||
echo $javascript->link('plotkit/Canvas.js');
|
||||
echo $javascript->link('plotkit/SweetCanvas.js');
|
||||
endif; ?>
|
||||
</head>
|
||||
<body>
|
||||
<div id="t_border">
|
||||
<div id="t_wrapper">
|
||||
<a class="skipnav" href="#t_content">Skip Navigation Links</a>
|
||||
<div id="t_header">
|
||||
<div id="t_title">
|
||||
<h1>Mozilla Firefox Uninstall Survey Data</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<div id="t_nav">
|
||||
<ul>
|
||||
<li><?php echo $html->link('Results', '/results'); ?></li>
|
||||
<li><?php echo $html->link('Comments', '/results/comments'); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* When we're exporting data, we end up having to pass all the parameters
|
||||
* via $_GET. Since we're doing this a few times per page (each graph, and the
|
||||
* export hrefs) this helper should make that easier.
|
||||
*/
|
||||
class ExportHelper
|
||||
{
|
||||
/**
|
||||
* Method to collect the current $_GET parameters and build another string from
|
||||
* them.
|
||||
*
|
||||
* @param string cake URL that you want prepended to the result. eg: reports/graph/
|
||||
* @param array the array of GET variables to add. These need to be
|
||||
* pre-sanitized to print in html! This is designed to
|
||||
* be used from the calling controller like:
|
||||
* $params = $this->sanitize->html($url_parameters);
|
||||
* @param string string to put between url and arguments (probably either '?' or
|
||||
* '&')
|
||||
* @param array array of strings which will be ignored
|
||||
* @return string string with the url variables appeneded to it
|
||||
*/
|
||||
function buildUrlString($url, $params, $seperator='?', $ignore=array('url'))
|
||||
{
|
||||
$arguments = '';
|
||||
|
||||
foreach ($params as $var => $val) {
|
||||
if (!in_array($var, $ignore)) {
|
||||
$arguments .= empty($arguments) ? "{$var}={$val}" : "&{$var}={$val}";
|
||||
}
|
||||
}
|
||||
|
||||
return "{$url}{$seperator}{$arguments}";
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,196 +0,0 @@
|
||||
<?php
|
||||
class PaginationHelper {
|
||||
|
||||
var $helpers = array('Html','Ajax');
|
||||
var $_pageDetails = array();
|
||||
var $link = '';
|
||||
var $show = array();
|
||||
var $page;
|
||||
var $style;
|
||||
|
||||
/**
|
||||
* Sets the default pagination options.
|
||||
*
|
||||
* @param array $paging an array detailing the page options
|
||||
*/
|
||||
function setPaging($paging)
|
||||
{
|
||||
if(!empty($paging))
|
||||
{
|
||||
|
||||
$this->link = $paging['link'];
|
||||
$this->show = $paging['show'];
|
||||
$this->page = $paging['page'];
|
||||
$this->style = $paging['style'];
|
||||
|
||||
$pageCount = ceil($paging['count'] / $paging['limit'] );
|
||||
|
||||
$this->_pageDetails = array(
|
||||
'page'=>$paging['page'],
|
||||
'recordCount'=>$paging['count'],
|
||||
'pageCount' =>$pageCount,
|
||||
'nextPage'=> ($paging['page'] < $pageCount) ? $paging['page']+1 : '',
|
||||
'previousPage'=> ($paging['page']>1) ? $paging['page']-1 : '',
|
||||
'limit'=>$paging['limit']
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Displays limits for the query
|
||||
*
|
||||
* @param string $text - text to display before limits
|
||||
* @param string $separator - display a separate between limits
|
||||
*
|
||||
**/
|
||||
function show($text=null, $separator=null)
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['recordCount']) )
|
||||
{
|
||||
$t = '';
|
||||
if(is_array($this->show))
|
||||
{
|
||||
$t = $text.$separator;
|
||||
foreach($this->show as $value)
|
||||
{
|
||||
$link = preg_replace('/show=(.*?)&/','show='.$value.'&',$this->link);
|
||||
if($this->_pageDetails['limit'] == $value)
|
||||
{
|
||||
$t .= '<em>'.$value.'</em>'.$separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t .= $this->Ajax->linkToRemote($value, array("fallback"=>$this->action."#","url" => $link.$this->_pageDetails['page'],"update" => "ajax_update","method"=>"get")).$separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
$t .= $this->Html->link($value,$link.$this->_pageDetails['page']).$separator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
/**
|
||||
* Displays current result information
|
||||
*
|
||||
* @param string $text - text to preceeding the number of results
|
||||
*
|
||||
**/
|
||||
function result($text)
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['recordCount']) )
|
||||
{
|
||||
if($this->_pageDetails['recordCount'] > $this->_pageDetails['limit'])
|
||||
{
|
||||
$start_row = $this->_pageDetails['page'] > 1 ? (($this->_pageDetails['page']-1)*$this->_pageDetails['limit'])+1:'1';
|
||||
$end_row = ($this->_pageDetails['recordCount'] < ($start_row + $this->_pageDetails['limit']-1)) ? $this->_pageDetails['recordCount'] : ($start_row + $this->_pageDetails['limit']-1);
|
||||
$t = $text.$start_row.'-'.$end_row.' of '.$this->_pageDetails['recordCount'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $text.$this->_pageDetails['recordCount'];
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns a list of page numbers separated by $separator
|
||||
*
|
||||
* @param string $separator - defaults to null
|
||||
*
|
||||
**/
|
||||
function pageNumbers($separator=null)
|
||||
{
|
||||
if (empty($this->_pageDetails) || $this->_pageDetails['pageCount'] == 1) { return false; }
|
||||
$t = array();
|
||||
$text = '';
|
||||
$pc = 1;
|
||||
do
|
||||
{
|
||||
if($pc == $this->_pageDetails['page'])
|
||||
{
|
||||
$text = '<em>'.$pc.'</em>';
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$text = $this->Ajax->linkToRemote($pc, array("fallback"=>$this->action."#","url" =>$this->link.$pc,"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$text = $this->Html->link($pc,$this->link.$pc);
|
||||
}
|
||||
}
|
||||
|
||||
$t[] = $text;
|
||||
$pc++;
|
||||
}
|
||||
while ($pc<=$this->_pageDetails['pageCount']);
|
||||
|
||||
$t = implode($separator, $t);
|
||||
|
||||
return $t;
|
||||
}
|
||||
/**
|
||||
* Displays a link to the previous page, where the page doesn't exist then
|
||||
* display the $text
|
||||
*
|
||||
* @param string $text - text display: defaults to next
|
||||
*
|
||||
**/
|
||||
function prevPage($text='prev')
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['previousPage']) )
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['previousPage'],"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $this->Html->link($text,$this->link.$this->_pageDetails['previousPage']);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Displays a link to the next page, where the page doesn't exist then
|
||||
* display the $text
|
||||
*
|
||||
* @param string $text - text to display: defaults to next
|
||||
*
|
||||
**/
|
||||
function nextPage($text='next')
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if (!empty($this->_pageDetails['nextPage']))
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['nextPage'],"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $this->Html->link($text,$this->link.$this->_pageDetails['nextPage']);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php echo $this->renderElement( 'header' ); ?>
|
||||
<?php echo $this->renderElement( 'nav' ); ?>
|
||||
<div id="t_content_container">
|
||||
<div id="t_content">
|
||||
<?php echo $content_for_layout;?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo $this->renderElement( 'footer'); ?>
|
||||
@@ -1,51 +0,0 @@
|
||||
<h1><?php echo Inflector::humanize($this->name); ?></h1>
|
||||
|
||||
<div id="queryform">
|
||||
<?php echo $html->formTag('/results/comments/','get'); ?>
|
||||
<span>
|
||||
<label for="start_date">Start Date:</label>
|
||||
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
|
||||
<label for="end_date">End Date:</label>
|
||||
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
|
||||
</span>
|
||||
|
||||
<label for="product">Product:</label>
|
||||
<select name="product" id="product">
|
||||
<?php
|
||||
foreach ($products as $select) :
|
||||
$product = $select['applications']['name'].' '.$select['applications']['version'];
|
||||
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$product?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<input type="submit" name="submit" id="submit" value="Go" />
|
||||
</form>
|
||||
<br />
|
||||
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($commentsData)) : ?>
|
||||
|
||||
<table class="comments" summary="User submitted comments.">
|
||||
<tr><th>Date Recorded</th><th>Comment</th></tr>
|
||||
<?php foreach ($commentsData as $var => $val) : ?>
|
||||
<tr><td><?php echo $time->niceShort($val['Result']['created']); ?></td><td><?php echo nl2br(htmlspecialchars($val['Result']['comments'])); ?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if($pagination->setPaging($paging)):?>
|
||||
<ul id="page-numbers">
|
||||
<li><?php echo $pagination->show('Show ', ' '); ?></li>
|
||||
<li><?php echo $pagination->result('Results: '); ?></li>
|
||||
<li><?php echo $pagination->pageNumbers(' '); ?></li>
|
||||
</ul>
|
||||
<?php endif;?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,91 +0,0 @@
|
||||
<h1><?php echo Inflector::humanize($this->name); ?></h1>
|
||||
|
||||
<div id="queryform">
|
||||
<?php echo $html->formTag('/results/','get'); ?>
|
||||
<span>
|
||||
<label for="start_date">Start Date:</label>
|
||||
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
|
||||
<label for="end_date">End Date:</label>
|
||||
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
|
||||
</span>
|
||||
|
||||
<label for="product">Product:</label>
|
||||
<select name="product" id="product">
|
||||
<?php
|
||||
foreach ($products as $select) :
|
||||
$product = $select['applications']['name'].' '.$select['applications']['version'];
|
||||
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$product?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<input type="submit" name="submit" id="submit" value="Go" />
|
||||
</form>
|
||||
<br />
|
||||
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($descriptionAndTotalsData)) : ?>
|
||||
<?php
|
||||
/* Prepare data for graphing */
|
||||
$_dataset = '';
|
||||
$_count = 0;
|
||||
$_total = 0;
|
||||
/* We've got to do 2 loops here because I need the totals to calculate
|
||||
* percentages.
|
||||
*/
|
||||
foreach ($descriptionAndTotalsData as $var => $val) {
|
||||
$_total += $val[0]['total'];
|
||||
}
|
||||
foreach ($descriptionAndTotalsData as $var => $val) {
|
||||
// We're putting this in a js string, so escape the double quotes
|
||||
$_description = str_replace('"','\"',$val['issues']['description']);
|
||||
$_percentage = intval(($val[0]['total'] / $_total)*100);
|
||||
|
||||
$_dataset .= "[{$_count}, {$val[0]['total']}, \"{$_description} (n={$val[0]['total']}, {$_percentage}%)\"], ";
|
||||
$_count++;
|
||||
}
|
||||
$_dataset = "[{$_dataset}]";
|
||||
?>
|
||||
<div id="graphcontainer">
|
||||
<canvas id="graph" height="400" width="800">
|
||||
<table class="results" summary="Firefox Uninstallation results.">
|
||||
<tr><th>Reason for uninstalling</th><th>Total</th></tr>
|
||||
<?php foreach ($descriptionAndTotalsData as $var => $val) : ?>
|
||||
<tr><td><?=$val['issues']['description']?></td><td><?=$val[0]['total']?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</canvas>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var layout = new PlotKit.Layout("bar", {"barOrientation":"horizontal"});
|
||||
layout.addDataset("results", <?=$_dataset?>);
|
||||
layout.evaluate();
|
||||
|
||||
var canvas = MochiKit.DOM.getElement("graph");
|
||||
var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout,
|
||||
{
|
||||
"drawYAxis" : false,
|
||||
"drawXAxis" : false,
|
||||
"backgroundColor" : Color.fromHexString('#78c'),
|
||||
"strokeColor" : Color.fromHexString('#777'),
|
||||
"strokeWidth" : 1.0,
|
||||
"enableEvents" : false
|
||||
});
|
||||
|
||||
plotter.render();
|
||||
</script>
|
||||
|
||||
|
||||
<div id="exportbox">
|
||||
<a href="<?php echo $export->buildUrlString('results/comments/',$url_params); ?>">View Any Associated Comments»</a><br />
|
||||
<a href="<?php echo $export->buildUrlString('results/csv/',$url_params); ?>">Download this Data»</a>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,6 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
|
||||
</IfModule>
|
||||
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: css.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.webroot
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*/
|
||||
require(CONFIGS.'paths.php');
|
||||
require(CAKE.'basics.php');
|
||||
require(LIBS.'folder.php');
|
||||
require(LIBS.'file.php');
|
||||
require(LIBS.'legacy.php');
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $path
|
||||
* @param unknown_type $name
|
||||
* @return unknown
|
||||
*/
|
||||
function make_clean_css ($path, $name)
|
||||
{
|
||||
require(VENDORS.'csspp'.DS.'csspp.php');
|
||||
|
||||
$data = file_get_contents($path);
|
||||
$csspp = new csspp();
|
||||
$output = $csspp->compress($data);
|
||||
|
||||
$ratio = 100-(round(strlen($output)/strlen($data), 3)*100);
|
||||
$output = " /* file: $name, ratio: $ratio% */ " . $output;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $path
|
||||
* @param unknown_type $content
|
||||
* @return unknown
|
||||
*/
|
||||
function write_css_cache ($path, $content)
|
||||
{
|
||||
if (!is_dir(dirname($path)))
|
||||
mkdir(dirname($path));
|
||||
|
||||
$cache = new File($path);
|
||||
return $cache->write($content);
|
||||
}
|
||||
|
||||
if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs))
|
||||
die('Wrong file name.');
|
||||
|
||||
$filename = 'css/'.$regs[1];
|
||||
$filepath = CSS.$regs[1];
|
||||
$cachepath = CACHE.'css'.DS.str_replace(array('/','\\'), '-', $regs[1]);
|
||||
|
||||
if (!file_exists($filepath))
|
||||
die('Wrong file name.');
|
||||
|
||||
|
||||
if (file_exists($cachepath))
|
||||
{
|
||||
$templateModified = filemtime($filepath);
|
||||
$cacheModified = filemtime($cachepath);
|
||||
|
||||
if ($templateModified > $cacheModified)
|
||||
{
|
||||
$output = make_clean_css ($filepath, $filename);
|
||||
write_css_cache ($cachepath, $output);
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = file_get_contents($cachepath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = make_clean_css ($filepath, $filename);
|
||||
write_css_cache ($cachepath, $output);
|
||||
}
|
||||
|
||||
header("Date: ".date("D, j M Y G:i:s ", $templateModified).'GMT');
|
||||
header("Content-Type: text/css");
|
||||
header("Expires: ".gmdate("D, j M Y H:i:s", time()+DAY)." GMT");
|
||||
header("Cache-Control: cache");// HTTP/1.1
|
||||
header("Pragma: cache");// HTTP/1.0
|
||||
print $output;
|
||||
|
||||
?>
|
||||
@@ -1,195 +0,0 @@
|
||||
/* CSS Document */
|
||||
@import url("cake.forms.css");
|
||||
|
||||
* {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
body {
|
||||
font: 76% Verdana, Arial, Sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
img {
|
||||
border:0;
|
||||
}
|
||||
#wrapper {
|
||||
text-align:left;
|
||||
}
|
||||
#header {
|
||||
height: 101px;
|
||||
background: #0D5087 url(../img/cake.header_bg.png) repeat-x left top;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
#content {
|
||||
min-height:400px;
|
||||
background-color: #fff;
|
||||
padding:2em 4em;
|
||||
}
|
||||
#footer {
|
||||
text-align:center;
|
||||
padding:1em 0;
|
||||
font-size:smaller;
|
||||
border-top:1px solid #333;
|
||||
background-color: #063260;
|
||||
color:#fff;
|
||||
line-height:1.5;
|
||||
}
|
||||
#footer a {
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
padding-bottom:0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-family:"Trebuchet MS",Verdana,Arial,Sans-serif;
|
||||
}
|
||||
h1, a {
|
||||
color:#DB8101;
|
||||
}
|
||||
h1 em, a em {
|
||||
color:#008BCC;
|
||||
font-style: normal;
|
||||
}
|
||||
ul.colored a em
|
||||
h2 {
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color:#666;
|
||||
}
|
||||
a:hover, a:hover em {
|
||||
color:#A22424;
|
||||
text-decoration:none;
|
||||
}
|
||||
#content p, #content ul, #content ol {
|
||||
line-height:1.5;
|
||||
padding-bottom:1em;
|
||||
}
|
||||
ul, ol {
|
||||
margin-left:3em;
|
||||
}
|
||||
|
||||
/* tables */
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 1px solid #333;
|
||||
clear:both;
|
||||
margin: 0 0 2em 0;
|
||||
white-space: normal;
|
||||
}
|
||||
th {
|
||||
background-color: #ccc;
|
||||
border-top: 1px solid #fff;
|
||||
border-right: 1px solid #666;
|
||||
border-bottom: 1px solid #666;
|
||||
text-align: center;
|
||||
padding:3px;
|
||||
}
|
||||
table tr td {
|
||||
border-right: 1px solid #ccc;
|
||||
padding:4px 4px;
|
||||
vertical-align:top;
|
||||
text-align: center;
|
||||
}
|
||||
table tr.altRow td {
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
/* scaffold show */
|
||||
|
||||
|
||||
div.related {
|
||||
clear:both;
|
||||
display:block;
|
||||
}
|
||||
dl {
|
||||
line-height:2em;
|
||||
margin:1em;
|
||||
}
|
||||
dt {
|
||||
font-weight: bold;
|
||||
vertical-align:top;
|
||||
}
|
||||
dd {
|
||||
margin-left:10em;
|
||||
margin-top:-2em;
|
||||
vertical-align:top;
|
||||
}
|
||||
|
||||
/* scaffold buttons */
|
||||
|
||||
|
||||
.notice {
|
||||
color: #DB8101;
|
||||
background-color: #ddd;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
}
|
||||
.tip {
|
||||
color: #DB8101;
|
||||
background-color: #ddd;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
ul.actions {
|
||||
list-style: none;
|
||||
text-align:left;
|
||||
margin:2em 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul.actions li {
|
||||
margin-left:1em;
|
||||
list-style: none;
|
||||
display: inline;
|
||||
}
|
||||
ul.actions li a, ul.actions li input {
|
||||
padding: 2px 12px;
|
||||
color: #DB8101;
|
||||
background-color:#ccc;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
line-height: 24px;
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
text-decoration: none;
|
||||
}
|
||||
ul.actions li a:hover {
|
||||
color: #DB8101;
|
||||
background-color:#fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
td.listactions {
|
||||
width: 14em;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
td.listactions a {
|
||||
padding: 0px 8px;
|
||||
text-align:center;
|
||||
font-weight: bold;
|
||||
color: #DB8101;
|
||||
background-color:#ccc;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
white-space: nowrap;
|
||||
}
|
||||
td.listactions a:hover {
|
||||
color: #fff;
|
||||
background-color:#DB8101;
|
||||
}
|
||||
|
||||
/* index links */
|
||||
|
||||
ul.colored a {
|
||||
|
||||
}
|
||||
ul.colored a em {
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/* form.css */
|
||||
|
||||
form {
|
||||
margin: 0 4px;
|
||||
font-size: 120%;
|
||||
border-width: 0px 0px 0px 0px;
|
||||
border-style: solid;
|
||||
border-color: #DB8101;
|
||||
}
|
||||
|
||||
form fieldset {
|
||||
font-size: 100%;
|
||||
border-color: #000000;
|
||||
border-width: 1px 0px 0px 0px;
|
||||
border-style: solid none none none;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
form fieldset legend {
|
||||
font-size: 150%;
|
||||
font-weight: normal;
|
||||
color: #000;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
label u {
|
||||
font-style: normal;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
input, select, textarea {
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
form div {
|
||||
clear: left;
|
||||
display: block;
|
||||
margin: 5px 0px 0px 0px;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
form fieldset div.notes {
|
||||
float: right;
|
||||
width: 158px;
|
||||
height: auto;
|
||||
margin: 0px 0px 10px 10px;
|
||||
padding: 5px;
|
||||
border: 1px solid #666;
|
||||
background-color: #ffffe1;
|
||||
color: #666;
|
||||
font-size: 88%;
|
||||
}
|
||||
|
||||
form fieldset div.notes h4 {
|
||||
background-image: url(/images/icon_info.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: top left;
|
||||
padding: 3px 0px 3px 27px;
|
||||
border-width: 0px 0px 1px 0px;
|
||||
border-style: solid;
|
||||
border-color: #666;
|
||||
color: #666;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
form fieldset div.notes p {
|
||||
margin: 0em 0em 1.2em 0em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
form fieldset div.notes p.last {
|
||||
margin: 0em;
|
||||
}
|
||||
|
||||
form div fieldset {
|
||||
clear: none;
|
||||
border-width: 0px 1px 0px 1px;
|
||||
border-style: solid;
|
||||
border-color: #666;
|
||||
margin: 0px 0px 0px 142px;
|
||||
padding: 0px 5px 5px 5px;
|
||||
}
|
||||
|
||||
form div fieldset legend {
|
||||
font-size: 100%;
|
||||
padding: 0px 3px 0px 9px;
|
||||
}
|
||||
|
||||
form div.required fieldset legend {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form div label {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 200px;
|
||||
background-color: #f4f4f4;
|
||||
font-size: 16px;
|
||||
padding: 3px 5px;
|
||||
margin: 0px 0px 5px 0px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
form div.optional label, label.optional {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
form div.required label, label.required {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form div label.labelCheckbox, form div label.labelRadio {
|
||||
float: none;
|
||||
display: block;
|
||||
margin: 0px 0px 5px 142px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
form div fieldset label.labelCheckbox, form div fieldset label.labelRadio {
|
||||
margin: 0px 0px 5px 0px;
|
||||
}
|
||||
p.error {
|
||||
color: #DB8101;
|
||||
background-color: #DBA941;
|
||||
font-size: 14px;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
form div input, form div select, form div textarea {
|
||||
padding: 1px 3px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
form div input.inputFile {
|
||||
width: 211px;
|
||||
}
|
||||
|
||||
form div select.selectOne, form div select.selectMultiple {
|
||||
width: 211px;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
form div input.inputCheckbox, form div input.inputRadio, input.inputCheckbox, input.inputRadio {
|
||||
display: inline;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
background-color: transparent;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
form div.submit {
|
||||
padding: 0px 0px 0px 140px;
|
||||
clear:both;
|
||||
display:block;
|
||||
}
|
||||
|
||||
div.submit input {
|
||||
padding: 2px 12px;
|
||||
color: #DB8101;
|
||||
background-color:#ccc;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
text-decoration: none;
|
||||
width: auto;
|
||||
}
|
||||
div.submit input:hover {
|
||||
padding: 2px 12px;
|
||||
color: #fff;
|
||||
background-color:#DB8101;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
text-decoration: none;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
form div.submit div input.inputSubmit, form div.submit div input.inputButton {
|
||||
float: right;
|
||||
margin: 0px 0px 0px 5px;
|
||||
}
|
||||
|
||||
form div small {
|
||||
display: block;
|
||||
margin: 0px 0px 5px 142px;
|
||||
padding: 1px 3px;
|
||||
font-size: 88%;
|
||||
}
|
||||
|
||||
/* form.import.css */
|
||||
|
||||
form fieldset legend {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
form input, form select, form textarea {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
div.optional label:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
div.required label:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
form div label.labelCheckbox, form div label.labelRadio, label.labelCheckbox, label.labelRadio {
|
||||
display: block;
|
||||
width: 190px;
|
||||
padding: 4px 0px 0px 18px;
|
||||
text-indent: -18px;
|
||||
line-height: 120%;
|
||||
}
|
||||
|
||||
form div label.labelCheckbox input.inputCheckbox, form div label.labelRadio input.inputRadio, label.labelCheckbox input.inputCheckbox, label.labelRadio input.inputRadio {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form div fieldset input.inputText, form div fieldset input.inputPassword, form div fieldset input.inputFile, form div fieldset textarea.inputTextarea {
|
||||
width: 160px;
|
||||
margin: 0px 0px 0px 18px;
|
||||
}
|
||||
|
||||
form div label.compact {
|
||||
display: inline;
|
||||
width: auto;
|
||||
padding: 4px 10px 0px 0px;
|
||||
text-indent: 0px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form div.wide label {
|
||||
float: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
form div label.wide {
|
||||
width: 348px;
|
||||
}
|
||||
|
||||
form div.wide input.inputText, form div.wide input.inputPassword, form div.wide input.inputFile, form div.wide select, form div.wide textarea {
|
||||
width: 344px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form div.notes p, form div small {
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
form div.wide small {
|
||||
margin: 0px 0px 5px 0px;
|
||||
}
|
||||
|
||||
div.date select {
|
||||
width:auto;
|
||||
}
|
||||
|
||||
select.autoWidth {
|
||||
width:auto;
|
||||
}
|
||||
|
||||
option {
|
||||
padding-left:1em;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
form div,
|
||||
form div label.labelCheckbox, form div label.labelRadio,
|
||||
form div small,
|
||||
form div label.labelCheckbox, form div label.labelRadio, label.labelCheckbox, label.labelRadio {
|
||||
height: expression('1%');
|
||||
}
|
||||
form div fieldset input.inputText, form div fieldset input.inputPassword, form div fieldset input.inputFile, form div fieldset textarea.inputTextarea {
|
||||
margin: expression('0px 0px 0px -124px');
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/* Screen Stylesheet */
|
||||
|
||||
/* This is temporary while we use the scaffolding */
|
||||
@import url("cake.default.css");
|
||||
table { clear:none; }
|
||||
|
||||
/* CORE STYLES */
|
||||
|
||||
body{
|
||||
background-color:#788;
|
||||
}
|
||||
div#t_title{
|
||||
background-color:#ddd;
|
||||
height:50px;
|
||||
padding-left:8px;
|
||||
}
|
||||
div#t_title h1{
|
||||
font-size:1.7em;
|
||||
padding-top:10px;
|
||||
color:#677;
|
||||
}
|
||||
div#t_content_container{
|
||||
}
|
||||
div#t_content{
|
||||
padding: 20px 10px 100px 10px;
|
||||
margin-left:151px;
|
||||
background-image:url('../img/bg.jpg');
|
||||
background-position:bottom right;
|
||||
background-repeat:no-repeat;
|
||||
min-height:200px;
|
||||
}
|
||||
div#t_wrapper{
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
background-color:#fff;
|
||||
}
|
||||
|
||||
div#t_border{
|
||||
border-left:1px solid #111;
|
||||
border-right:1px solid #111;
|
||||
border-bottom:1px solid #111;
|
||||
margin:0px 30px 0px 30px;
|
||||
}
|
||||
|
||||
div#t_nav {
|
||||
padding:20px 0px 50px 0px;
|
||||
float:left;
|
||||
width:151px;
|
||||
}
|
||||
div#t_nav ul {
|
||||
list-style-type:none;
|
||||
padding:2px 0px 0px 0px;
|
||||
margin:0px;
|
||||
}
|
||||
div#t_nav ul li{
|
||||
padding:2px 0px 2px 0px;
|
||||
}
|
||||
div#t_nav ul li a{
|
||||
text-decoration:none;
|
||||
font-size:.8em;
|
||||
padding:6px 0px 6px 8px;
|
||||
margin:0px 0px 0px 0px;
|
||||
color:#566;
|
||||
border:none;
|
||||
}
|
||||
div#t_nav ul li a:hover{
|
||||
color:#f80;
|
||||
}
|
||||
div#t_nav h3 {
|
||||
padding:5px 0px 0px 5px;
|
||||
font-size:.9em;
|
||||
}
|
||||
div#t_footer {
|
||||
clear:both;
|
||||
border-top:1px solid #111;
|
||||
}
|
||||
|
||||
div#t_content h1 {
|
||||
margin-bottom:100px;
|
||||
font-size:1.6em;
|
||||
}
|
||||
|
||||
a.skipnav {
|
||||
position:absolute;
|
||||
visibility:hidden;
|
||||
}
|
||||
|
||||
div#queryform {
|
||||
margin: 5px 20px 5px 20px;
|
||||
padding-bottom:20px;
|
||||
width:700px;
|
||||
}
|
||||
div#queryform label {
|
||||
font-size:.8em;
|
||||
font-weight:bold;
|
||||
}
|
||||
div#queryform input[type="text"]{
|
||||
width:7em;
|
||||
}
|
||||
|
||||
div#exportbox {
|
||||
}
|
||||
|
||||
/* Classes for graph/table data. (Generally just padding) */
|
||||
.results {
|
||||
padding: 5px 5px 5px 5px;
|
||||
margin: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
div#notice {
|
||||
background-color:#ecc;
|
||||
border:1px dashed #daa;
|
||||
text-align:center;
|
||||
padding:6px 6px 6px 6px;
|
||||
margin:6px 20px 6px 20px;
|
||||
}
|
||||
|
||||
table.comments tr {
|
||||
}
|
||||
|
||||
table.comments tr td{
|
||||
text-align:left;
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
div.bar_chart_label {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
font-size: small;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.2 KiB |
@@ -1 +0,0 @@
|
||||
deny from all
|
||||
@@ -1,244 +0,0 @@
|
||||
2006-04-29 v1.3.1 (bug fix release)
|
||||
|
||||
- Fix sendXMLHttpRequest sendContent regression
|
||||
- Internet Explorer fix in MochiKit.Logging (printfire exception)
|
||||
- Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async
|
||||
|
||||
2006-04-26 v1.3 "warp zone"
|
||||
|
||||
- IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)
|
||||
- IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)
|
||||
- New MochiKit.Base.method as a convenience form of bind that takes the
|
||||
object before the method
|
||||
- New MochiKit.Base.flattenArguments for flattening a list of arguments to
|
||||
a single Array
|
||||
- Refactored MochiRegExp example to use MochiKit.Signal
|
||||
- New key_events example demonstrating use of MochiKit.Signal's key handling
|
||||
capabilities.
|
||||
- MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
|
||||
null is used and the string will be considered the first node. This
|
||||
allows for the more natural P("foo") rather than P(null, "foo").
|
||||
- MochiKit Interpreter example refactored to use MochiKit.Signal and now
|
||||
provides multi-line input and a help() function to get MochiKit function
|
||||
signature from the documentation.
|
||||
- Native Console Logging for the default MochiKit.Logging logger
|
||||
- New MochiKit.Async.DeferredList, gatherResults, maybeDeferred
|
||||
- New MochiKit.Signal example: draggable
|
||||
- Added sanity checking to Deferred to ensure that errors happen when chaining
|
||||
is used incorrectly
|
||||
- Opera sendXMLHttpRequest fix (sends empty string instead of null by default)
|
||||
- Fix a bug in MochiKit.Color that incorrectly generated hex colors for
|
||||
component values smaller than 16/255.
|
||||
- Fix a bug in MochiKit.Logging that prevented logs from being capped at a
|
||||
maximum size
|
||||
- MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
|
||||
Error, so that the errback chain is used instead of the callback chain.
|
||||
- MochiKit.DOM.appendChildNodes and associated functions now append iterables
|
||||
in the correct order.
|
||||
- New MochiKit-based SimpleTest test runner as a replacement for Test.Simple
|
||||
- MochiKit.Base.isNull no longer matches undefined
|
||||
- example doctypes changed to HTML4
|
||||
- isDateLike no longer throws error on null
|
||||
- New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt
|
||||
- updated elementDimensions to calculate width from offsetWidth instead
|
||||
of clientWidth
|
||||
- formContents now works with FORM tags that have a name attribute
|
||||
- Documentation now uses MochiKit to generate a function index
|
||||
|
||||
2006-01-26 v1.2 "the ocho"
|
||||
|
||||
- Fixed MochiKit.Color.Color.lighterColorWithLevel
|
||||
- Added new MochiKit.Base.findIdentical function to find the index of an
|
||||
element in an Array-like object. Uses === for identity comparison.
|
||||
- Added new MochiKit.Base.find function to find the index of an element in
|
||||
an Array-like object. Uses compare for rich comparison.
|
||||
- MochiKit.Base.bind will accept a string for func, which will be immediately
|
||||
looked up as self[func].
|
||||
- MochiKit.DOM.formContents no longer skips empty form elements for Zope
|
||||
compatibility
|
||||
- MochiKit.Iter.forEach will now catch StopIteration to break
|
||||
- New MochiKit.DOM.elementDimensions(element) for determining the width and
|
||||
height of an element in the document
|
||||
- MochiKit.DOM's initialization is now compatible with
|
||||
HTMLUnit + JWebUnit + Rhino
|
||||
- MochiKit.LoggingPane will now re-use a ``_MochiKit_LoggingPane`` DIV element
|
||||
currently in the document instead of always creating one.
|
||||
- MochiKit.Base now has operator.mul
|
||||
- MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
|
||||
a custom value attribute
|
||||
- Added new MochiKit.Color constructors fromComputedStyle and fromText
|
||||
- MochiKit.DOM.setNodeAttribute should work now
|
||||
- MochiKit.DOM now has a workaround for an IE bug when setting the style
|
||||
property to a string
|
||||
- MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
|
||||
name and for properties
|
||||
- MochiKit.DOM.scrapeText now walks the DOM tree in-order
|
||||
- MochiKit.LoggingPane now sanitizes the window name to work around IE bug
|
||||
- MochiKit.DOM now translates usemap to useMap to work around IE bug
|
||||
- MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks
|
||||
- Added new MochiKit.DOM documentation on element visibility
|
||||
- New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
|
||||
for determining the position of an element in the document
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG
|
||||
|
||||
2005-11-14 v1.1
|
||||
|
||||
- Fixed a bug in numberFormatter with large numbers
|
||||
- Massively overhauled documentation
|
||||
- Fast-path for primitives in MochiKit.Base.compare
|
||||
- New groupby and groupby_as_array in MochiKit.Iter
|
||||
- Added iterator factory adapter for objects that implement iterateNext()
|
||||
- Fixed isoTimestamp to handle timestamps with time zone correctly
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
|
||||
LEGEND, FIELDSET
|
||||
- New MochiKit.DOM formContents and enhancement to queryString to support it
|
||||
- Updated view_source example to use dp.SyntaxHighlighter 1.3.0
|
||||
- MochiKit.LoggingPane now uses named windows based on the URL so that
|
||||
a given URL will get the same LoggingPane window after a reload
|
||||
(at the same position, etc.)
|
||||
- MochiKit.DOM now has currentWindow() and currentDocument() context
|
||||
variables that are set with withWindow() and withDocument(). These
|
||||
context variables affect all MochiKit.DOM functionality (getElement,
|
||||
createDOM, etc.)
|
||||
- MochiKit.Base.items will now catch and ignore exceptions for properties
|
||||
that are enumerable but not accessible (e.g. permission denied)
|
||||
- MochiKit.Async.Deferred's addCallback/addErrback/addBoth
|
||||
now accept additional arguments that are used to create a partially
|
||||
applied function. This differs from Twisted in that the callback/errback
|
||||
result becomes the *last* argument, not the first when this feature
|
||||
is used.
|
||||
- MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
|
||||
arguments which are used to create a GET query string
|
||||
- Did some refactoring to reduce the footprint of MochiKit by a few
|
||||
kilobytes
|
||||
- escapeHTML to longer escapes ' (apos) and now uses
|
||||
String.replace instead of iterating over every char.
|
||||
- Added DeferredLock to Async
|
||||
- Renamed getElementsComputedStyle to computedStyle and moved
|
||||
it from MochiKit.Visual to MochiKit.DOM
|
||||
- Moved all color support out of MochiKit.Visual and into MochiKit.Color
|
||||
- Fixed range() to accept a negative step
|
||||
- New alias to MochiKit.swapDOM called removeElement
|
||||
- New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
|
||||
an attribute on a node without raising, roughly equivalent to:
|
||||
updateNodeAttributes(node, {attr: value})
|
||||
- New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
|
||||
a node's attribute or returns null without raising
|
||||
- Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
|
||||
directly (addLoadEvent did not leak, since it clears the handler)
|
||||
|
||||
2005-10-24 v1.0
|
||||
|
||||
- New interpreter example that shows usage of MochiKit.DOM to make
|
||||
an interactive JavaScript interpreter
|
||||
- New MochiKit.LoggingPane for use with the MochiKit.Logging
|
||||
debuggingBookmarklet, with logging_pane example to show its usage
|
||||
- New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
|
||||
in order to provide a live regular expression matching tool
|
||||
- Added advanced number formatting capabilities to MochiKit.Format:
|
||||
numberFormatter(pattern, placeholder="", locale="default") and
|
||||
formatLocale(locale="default")
|
||||
- Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
|
||||
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE
|
||||
- Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
|
||||
to MochiKit.Format
|
||||
- MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
|
||||
isoTimestamp(isoString) will convert them to Date objects, and
|
||||
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC
|
||||
- Fixed missing errback for sendXMLHttpRequest when the server does not
|
||||
respond
|
||||
- Fixed infinite recusion bug when using roundClass("DIV", ...)
|
||||
- Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
|
||||
from being cancelled properly
|
||||
- Workaround in MochiKit.Base bind (and partial) for functions that don't
|
||||
have an apply method, such as alert
|
||||
- Reliably return null from the string parsing/manipulation functions if
|
||||
the input can't be coerced to a string (s + "") or the input makes no sense;
|
||||
e.g. isoTimestamp(null) and isoTimestamp("") return null
|
||||
|
||||
2005-10-08 v0.90
|
||||
|
||||
- Fixed ISO compliance with toISODate
|
||||
- Added missing operator.sub
|
||||
- Placated Mozilla's strict warnings a bit
|
||||
- Added JSON serialization and unserialization support to MochiKit.Base:
|
||||
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
|
||||
API.
|
||||
- Fixed a bug in the script loader that failed in some scenarios when a script
|
||||
tag did not have a "src" attribute (thanks Ian!)
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
|
||||
P, FORM
|
||||
- Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
|
||||
and parseQueryString, when available.
|
||||
|
||||
2005-08-12 v0.80
|
||||
|
||||
- Source highlighting in all examples, moved to a view-source example
|
||||
- Added some experimental syntax highlighting for the Rounded Corners example,
|
||||
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib
|
||||
- Use an indirect binding for the logger conveniences, so that the global
|
||||
logger could be replaced by setting MochiKit.Logger.logger to something else
|
||||
(though an observer is probably a better choice).
|
||||
- Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
|
||||
which will be looked up with getElement
|
||||
- Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
|
||||
node.parentNode)
|
||||
- Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success
|
||||
- Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues
|
||||
- Possible workaround for Safari issue with swapDOM, where it would get
|
||||
confused because two elements were in the DOM at the same time with the
|
||||
same id
|
||||
- Added missing THEAD convenience function to MochiKit.DOM
|
||||
- Added lstrip, rstrip, strip to MochiKit.Format
|
||||
- Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
|
||||
MochiKit.DOM
|
||||
- MochiKit.Iter.iextend now has a fast-path for array-like objects
|
||||
- Added HSV color space support to MochiKit.Visual
|
||||
- Fixed a bug in the sortable_tables example, it now converts types
|
||||
correctly
|
||||
- Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
|
||||
scope
|
||||
|
||||
2005-08-04 v0.70
|
||||
|
||||
- New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
|
||||
a little TAL-ish DOM templating attribute language.
|
||||
- sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
|
||||
ignore requests with status == 0, which seems to happen for cached or local
|
||||
requests
|
||||
- Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.
|
||||
- Changed scrapeText API to return a string by default. This is API-breaking!
|
||||
It was dumb to have the default return value be the form you almost never
|
||||
want. Sorry.
|
||||
- Added special form to swapDOM(dest, src). If src is null, dest is removed
|
||||
(where previously you'd likely get a DOM exception).
|
||||
- Added three new functions to MochiKit.Base for dealing with URL query
|
||||
strings: urlEncode, queryString, parseQueryString
|
||||
- MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
|
||||
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
|
||||
new Function(v).
|
||||
- Another workaround for Internet "worst browser ever" Explorer's setAttribute
|
||||
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).
|
||||
- Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM
|
||||
- Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
|
||||
now!
|
||||
|
||||
2005-07-29 v0.60
|
||||
|
||||
- Beefed up the MochiKit.DOM test suite
|
||||
- Fixed return value for MochiKit.DOM.swapElementClass, could return
|
||||
false unexpectedly before
|
||||
- Added an optional "parent" argument to
|
||||
MochiKit.DOM.getElementsByTagAndClassName
|
||||
- Added a "packed" version in packed/MochiKit/MochiKit.js
|
||||
- Changed build script to rewrite the URLs in tests to account for the
|
||||
JSAN-required reorganization
|
||||
- MochiKit.Compat to potentially work around IE 5.5 issues
|
||||
(5.0 still not supported). Test.Simple doesn't seem to work there,
|
||||
though.
|
||||
- Several minor documentation corrections
|
||||
|
||||
2005-07-27 v0.50
|
||||
|
||||
- Initial Release
|
||||
@@ -1,69 +0,0 @@
|
||||
MochiKit is dual-licensed software. It is available under the terms of the
|
||||
MIT License, or the Academic Free License version 2.1. The full text of
|
||||
each license is included below.
|
||||
|
||||
MIT License
|
||||
===========
|
||||
|
||||
Copyright (c) 2005 Bob Ippolito. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
Academic Free License v. 2.1
|
||||
============================
|
||||
|
||||
Copyright (c) 2005 Bob Ippolito. All rights reserved.
|
||||
|
||||
This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
|
||||
|
||||
Licensed under the Academic Free License version 2.1
|
||||
|
||||
1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following:
|
||||
|
||||
a) to reproduce the Original Work in copies;
|
||||
|
||||
b) to prepare derivative works ("Derivative Works") based upon the Original Work;
|
||||
|
||||
c) to distribute copies of the Original Work and Derivative Works to the public;
|
||||
|
||||
d) to perform the Original Work publicly; and
|
||||
|
||||
e) to display the Original Work publicly.
|
||||
|
||||
2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works.
|
||||
|
||||
3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work.
|
||||
|
||||
4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license.
|
||||
|
||||
5) This section intentionally omitted.
|
||||
|
||||
6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
|
||||
|
||||
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer.
|
||||
|
||||
8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions.
|
||||
|
||||
10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
|
||||
|
||||
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License.
|
||||
|
||||
12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
|
||||
|
||||
13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
|
||||
|
||||
14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
|
||||
|
||||
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.
|
||||
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
Changes
|
||||
META.json
|
||||
MANIFEST This list of files
|
||||
LICENSE.txt
|
||||
doc/html/MochiKit/Async.html
|
||||
doc/html/MochiKit/Base.html
|
||||
doc/html/MochiKit/Color.html
|
||||
doc/html/MochiKit/DateTime.html
|
||||
doc/html/MochiKit/DOM.html
|
||||
doc/html/MochiKit/Format.html
|
||||
doc/html/MochiKit/index.html
|
||||
doc/html/MochiKit/Iter.html
|
||||
doc/html/MochiKit/Logging.html
|
||||
doc/html/MochiKit/LoggingPane.html
|
||||
doc/html/MochiKit/Signal.html
|
||||
doc/html/MochiKit/VersionHistory.html
|
||||
doc/html/MochiKit/Visual.html
|
||||
doc/js/toc.js
|
||||
doc/rst/MochiKit/Async.rst
|
||||
doc/rst/MochiKit/Base.rst
|
||||
doc/rst/MochiKit/Color.rst
|
||||
doc/rst/MochiKit/DateTime.rst
|
||||
doc/rst/MochiKit/DOM.rst
|
||||
doc/rst/MochiKit/Format.rst
|
||||
doc/rst/MochiKit/index.rst
|
||||
doc/rst/MochiKit/Iter.rst
|
||||
doc/rst/MochiKit/Logging.rst
|
||||
doc/rst/MochiKit/LoggingPane.rst
|
||||
doc/rst/MochiKit/Signal.rst
|
||||
doc/rst/MochiKit/VersionHistory.rst
|
||||
doc/rst/MochiKit/Visual.rst
|
||||
examples/ajax_tables/ajax_tables.css
|
||||
examples/ajax_tables/ajax_tables.js
|
||||
examples/ajax_tables/domains.json
|
||||
examples/ajax_tables/domains.xml
|
||||
examples/ajax_tables/index.html
|
||||
examples/color_wheel/color_wheel.css
|
||||
examples/color_wheel/color_wheel.js
|
||||
examples/color_wheel/index.html
|
||||
examples/draggable/draggable.css
|
||||
examples/draggable/draggable.js
|
||||
examples/draggable/index.html
|
||||
examples/interpreter/index.html
|
||||
examples/interpreter/interpreter.css
|
||||
examples/interpreter/interpreter.js
|
||||
examples/key_events/index.html
|
||||
examples/key_events/key_events.css
|
||||
examples/key_events/key_events.js
|
||||
examples/logging_pane/index.html
|
||||
examples/logging_pane/logging_pane.css
|
||||
examples/logging_pane/logging_pane.js
|
||||
examples/mochiregexp/index.html
|
||||
examples/mochiregexp/mochiregexp.css
|
||||
examples/mochiregexp/mochiregexp.js
|
||||
examples/rounded_corners/index.html
|
||||
examples/rounded_corners/rounded_corners.css
|
||||
examples/rounded_corners/rounded_corners.js
|
||||
examples/sortable_tables/index.html
|
||||
examples/sortable_tables/sortable_tables.css
|
||||
examples/sortable_tables/sortable_tables.js
|
||||
examples/view-source/view-source.css
|
||||
examples/view-source/view-source.html
|
||||
examples/view-source/view-source.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushPython.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushSql.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushVb.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushXml.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shCore.js
|
||||
examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css
|
||||
examples/view-source/lib/SyntaxHighlighter/Tests.html
|
||||
include/css/documentation.css
|
||||
include/css/general.css
|
||||
MochiKit/__package__.js
|
||||
MochiKit/Async.js
|
||||
MochiKit/Base.js
|
||||
MochiKit/Color.js
|
||||
MochiKit/DateTime.js
|
||||
MochiKit/DOM.js
|
||||
MochiKit/Format.js
|
||||
MochiKit/Iter.js
|
||||
MochiKit/Logging.js
|
||||
MochiKit/LoggingPane.js
|
||||
MochiKit/MochiKit.js
|
||||
MochiKit/MockDOM.js
|
||||
MochiKit/Signal.js
|
||||
MochiKit/Test.js
|
||||
MochiKit/Visual.js
|
||||
packed/MochiKit/__package__.js
|
||||
packed/MochiKit/MochiKit.js
|
||||
tests/index.html
|
||||
tests/test_Base.js
|
||||
tests/test_Color.js
|
||||
tests/test_DateTime.js
|
||||
tests/test_Format.js
|
||||
tests/test_Iter.js
|
||||
tests/test_Logging.js
|
||||
tests/test_MochiKit-Async.html
|
||||
tests/test_MochiKit-Base.html
|
||||
tests/test_MochiKit-Color.html
|
||||
tests/test_MochiKit-DateTime.html
|
||||
tests/test_MochiKit-DOM.html
|
||||
tests/test_MochiKit-Format.html
|
||||
tests/test_MochiKit-Iter.html
|
||||
tests/test_MochiKit-JSAN.html
|
||||
tests/test_MochiKit-Logging.html
|
||||
tests/test_MochiKit-MochiKit.html
|
||||
tests/test_MochiKit-Signal.html
|
||||
tests/test_Signal.js
|
||||
tests/SimpleTest/SimpleTest.js
|
||||
tests/SimpleTest/test.css
|
||||
tests/SimpleTest/TestRunner.js
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"recommends": {
|
||||
"JSAN": "0.10"
|
||||
},
|
||||
"name": "MochiKit",
|
||||
"license": "mit",
|
||||
"author": [
|
||||
"Bob Ippolito <bob@redivi.com>"
|
||||
],
|
||||
"abstract": "Python-inspired JavaScript kit",
|
||||
"generated_by": "MochiKit's build script",
|
||||
"build_requires": {
|
||||
"Test.Simple": "0.11"
|
||||
},
|
||||
"version": "1.3.1",
|
||||
"provides": {}
|
||||
}
|
||||
@@ -1,606 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Async - manage asynchronous tasks</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Async - manage asynchronous tasks</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
var url = "/src/b/bo/bob/MochiKit.Async/META.json";
|
||||
/*
|
||||
|
||||
META.json looks something like this:
|
||||
|
||||
{"name": "MochiKit", "version": "0.5"}
|
||||
|
||||
*/
|
||||
var d = loadJSONDoc(url);
|
||||
var gotMetadata = function (meta) {
|
||||
if (MochiKit.Async.VERSION == meta.version) {
|
||||
alert("You have the newest MochiKit.Async!");
|
||||
} else {
|
||||
alert("MochiKit.Async "
|
||||
+ meta.version
|
||||
+ " is available, upgrade!");
|
||||
}
|
||||
};
|
||||
var metadataFetchFailed = function (err) {
|
||||
alert("The metadata for MochiKit.Async could not be fetched :(");
|
||||
};
|
||||
d.addCallbacks(gotMetadata, metadataFetchFailed);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Async provides facilities to manage asynchronous
|
||||
(as in AJAX <a class="footnote-reference" href="#id7" id="id1" name="id1">[1]</a>) tasks. The model for asynchronous computation
|
||||
used in this module is heavily inspired by Twisted <a class="footnote-reference" href="#id8" id="id2" name="id2">[2]</a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="deferred" name="deferred">Deferred</a></h2>
|
||||
<p>The Deferred constructor encapsulates a single value that
|
||||
is not available yet. The most important example of this
|
||||
in the context of a web browser would be an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
|
||||
to a server. The importance of the Deferred is that it
|
||||
allows a consistent API to be exposed for all asynchronous
|
||||
computations that occur exactly once.</p>
|
||||
<p>The producer of the Deferred is responsible for doing all
|
||||
of the complicated work behind the scenes. This often
|
||||
means waiting for a timer to fire, or waiting for an event
|
||||
(e.g. <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> of <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>).
|
||||
It could also be coordinating several events (e.g.
|
||||
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> with a timeout, or several Deferreds
|
||||
(e.g. fetching a set of XML documents that should be
|
||||
processed at the same time).</p>
|
||||
<p>Since these sorts of tasks do not respond immediately, the
|
||||
producer of the Deferred does the following steps before
|
||||
returning to the consumer:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Create a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred();</a> object and keep a reference
|
||||
to it, because it will be needed later when the value is
|
||||
ready.</li>
|
||||
<li>Setup the conditions to create the value requested (e.g.
|
||||
create a new <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>, set its
|
||||
<tt class="docutils literal"><span class="pre">onreadystatechange</span></tt>).</li>
|
||||
<li>Return the <a class="mochiref reference" href="#fn-deferred">Deferred</a> object.</li>
|
||||
</ol>
|
||||
<p>Since the value is not yet ready, the consumer attaches
|
||||
a function to the Deferred that will be called when the
|
||||
value is ready. This is not unlike <tt class="docutils literal"><span class="pre">setTimeout</span></tt>, or
|
||||
other similar facilities you may already be familiar with.
|
||||
The consumer can also attach an "errback" to the
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a>, which is a callback for error handling.</p>
|
||||
<p>When the value is ready, the producer simply calls
|
||||
<tt class="docutils literal"><span class="pre">myDeferred.callback(theValue)</span></tt>. If an error occurred,
|
||||
it should call <tt class="docutils literal"><span class="pre">myDeferred.errback(theValue)</span></tt> instead.
|
||||
As soon as this happens, the callback that the consumer
|
||||
attached to the <a class="mochiref reference" href="#fn-deferred">Deferred</a> is called with <tt class="docutils literal"><span class="pre">theValue</span></tt>
|
||||
as the only argument.</p>
|
||||
<p>There are quite a few additional "advanced" features
|
||||
baked into <a class="mochiref reference" href="#fn-deferred">Deferred</a>, such as cancellation and
|
||||
callback chains, so take a look at the API
|
||||
reference if you would like to know more!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="errors" name="errors">Errors</a></h2>
|
||||
<p>
|
||||
<a name="fn-alreadycallederror"></a>
|
||||
<a class="mochidef reference" href="#fn-alreadycallederror">AlreadyCalledError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> if <tt class="docutils literal"><span class="pre">.callback</span></tt> or
|
||||
<tt class="docutils literal"><span class="pre">.errback</span></tt> are called more than once.</blockquote>
|
||||
<p>
|
||||
<a name="fn-browsercomplianceerror"></a>
|
||||
<a class="mochidef reference" href="#fn-browsercomplianceerror">BrowserComplianceError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown when the JavaScript runtime is not capable of performing
|
||||
the given function. Currently, this happens if the browser
|
||||
does not support <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-cancellederror"></a>
|
||||
<a class="mochidef reference" href="#fn-cancellederror">CancelledError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> when it is cancelled,
|
||||
unless a canceller is present and throws something else.</blockquote>
|
||||
<p>
|
||||
<a name="fn-genericerror"></a>
|
||||
<a class="mochidef reference" href="#fn-genericerror">GenericError</a>:</p>
|
||||
<blockquote>
|
||||
Results passed to <tt class="docutils literal"><span class="pre">.fail</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> of a <a class="mochiref reference" href="#fn-deferred">Deferred</a>
|
||||
are wrapped by this <tt class="docutils literal"><span class="pre">Error</span></tt> if <tt class="docutils literal"><span class="pre">!(result</span> <span class="pre">instanceof</span> <span class="pre">Error)</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-xmlhttprequesterror"></a>
|
||||
<a class="mochidef reference" href="#fn-xmlhttprequesterror">XMLHttpRequestError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown when an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> does not complete successfully
|
||||
for any reason. The <tt class="docutils literal"><span class="pre">req</span></tt> property of the error is the failed
|
||||
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object, and for convenience the <tt class="docutils literal"><span class="pre">number</span></tt>
|
||||
property corresponds to <tt class="docutils literal"><span class="pre">req.status</span></tt>.</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-deferred"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred">Deferred()</a>:</p>
|
||||
<blockquote>
|
||||
Encapsulates a sequence of callbacks in response to a value that
|
||||
may not yet be available. This is modeled after the Deferred class
|
||||
from Twisted <a class="footnote-reference" href="#id9" id="id3" name="id3">[3]</a>.</blockquote>
|
||||
<blockquote>
|
||||
<p>Why do we want this? JavaScript has no threads, and even if it did,
|
||||
threads are hard. Deferreds are a way of abstracting non-blocking
|
||||
events, such as the final response to an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</p>
|
||||
<p>The sequence of callbacks is internally represented as a list
|
||||
of 2-tuples containing the callback/errback pair. For example,
|
||||
the following call sequence:</p>
|
||||
<pre class="literal-block">
|
||||
var d = new Deferred();
|
||||
d.addCallback(myCallback);
|
||||
d.addErrback(myErrback);
|
||||
d.addBoth(myBoth);
|
||||
d.addCallbacks(myCallback, myErrback);
|
||||
</pre>
|
||||
<p>is translated into a <a class="mochiref reference" href="#fn-deferred">Deferred</a> with the following internal
|
||||
representation:</p>
|
||||
<pre class="literal-block">
|
||||
[
|
||||
[myCallback, null],
|
||||
[null, myErrback],
|
||||
[myBoth, myBoth],
|
||||
[myCallback, myErrback]
|
||||
]
|
||||
</pre>
|
||||
<p>The <a class="mochiref reference" href="#fn-deferred">Deferred</a> also keeps track of its current status (fired).
|
||||
Its status may be one of the following three values:</p>
|
||||
<blockquote>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="14%" />
|
||||
<col width="86%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th class="head">Value</th>
|
||||
<th class="head">Condition</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td>-1</td>
|
||||
<td>no value yet (initial condition)</td>
|
||||
</tr>
|
||||
<tr><td>0</td>
|
||||
<td>success</td>
|
||||
</tr>
|
||||
<tr><td>1</td>
|
||||
<td>error</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>A <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the error state if one of the following
|
||||
conditions are met:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>The result given to callback or errback is "<tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>"</li>
|
||||
<li>The callback or errback threw while executing. If the thrown object
|
||||
is not <tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>, it will be wrapped with
|
||||
<a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</li>
|
||||
</ol>
|
||||
<p>Otherwise, the <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the success state. The state
|
||||
of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> determines the next element in the callback
|
||||
sequence to run.</p>
|
||||
<p>When a callback or errback occurs with the example deferred chain, something
|
||||
equivalent to the following will happen (imagine that exceptions are caught
|
||||
and returned as-is):</p>
|
||||
<pre class="literal-block">
|
||||
// d.callback(result) or d.errback(result)
|
||||
if (!(result instanceof Error)) {
|
||||
result = myCallback(result);
|
||||
}
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
}
|
||||
result = myBoth(result);
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
} else {
|
||||
result = myCallback(result);
|
||||
}
|
||||
</pre>
|
||||
<p>The result is then stored away in case another step is added to the
|
||||
callback sequence. Since the <a class="mochiref reference" href="#fn-deferred">Deferred</a> already has a value
|
||||
available, any new callbacks added will be called immediately.</p>
|
||||
<p>There are two other "advanced" details about this implementation that are
|
||||
useful:</p>
|
||||
<p>Callbacks are allowed to return <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances,
|
||||
so you can build complicated sequences of events with (relative) ease.</p>
|
||||
<p>The creator of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> may specify a canceller. The
|
||||
canceller is a function that will be called if
|
||||
<a class="mochiref reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel</a> is called before the
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> fires. You can use this to allow an
|
||||
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to be cleanly cancelled, for example. Note that
|
||||
cancel will fire the <a class="mochiref reference" href="#fn-deferred">Deferred</a> with a
|
||||
<a class="mochiref reference" href="#fn-cancellederror">CancelledError</a> (unless your canceller throws or returns
|
||||
a different <tt class="docutils literal"><span class="pre">Error</span></tt>), so errbacks should be prepared to handle that
|
||||
<tt class="docutils literal"><span class="pre">Error</span></tt> gracefully for cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.addboth"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.addboth">Deferred.prototype.addBoth(func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add the same function as both a callback and an errback as the
|
||||
next element on the callback sequence. This is useful for code
|
||||
that you want to guarantee to run, e.g. a finalizer.</p>
|
||||
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
|
||||
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
|
||||
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the callback or
|
||||
errback will be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
|
||||
callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.addcallback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.addcallback">Deferred.prototype.addCallback(func[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add a single callback to the end of the callback sequence.</p>
|
||||
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
|
||||
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
|
||||
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the callback will
|
||||
be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
|
||||
callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.addcallbacks"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.addcallbacks">Deferred.prototype.addCallbacks(callback, errback)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add separate callback and errback to the end of the callback
|
||||
sequence. Either callback or errback may be <tt class="docutils literal"><span class="pre">null</span></tt>,
|
||||
but not both.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">callback</span></tt> or <tt class="docutils literal"><span class="pre">errback</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
|
||||
then it will be chained (its value or error will be passed to the
|
||||
next callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained,
|
||||
it can no longer accept new callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.adderrback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.adderrback">Deferred.prototype.addErrback(func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add a single errback to the end of the callback sequence.</p>
|
||||
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
|
||||
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
|
||||
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the errback will
|
||||
be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
|
||||
callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.callback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Begin the callback sequence with a non-<tt class="docutils literal"><span class="pre">Error</span></tt> result. Result
|
||||
may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should
|
||||
be called exactly once on a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.cancel"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Cancels a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has not yet received a value,
|
||||
or is waiting on another <a class="mochiref reference" href="#fn-deferred">Deferred</a> as its value.</p>
|
||||
<p>If a canceller is defined, the canceller is called.
|
||||
If the canceller did not return an <tt class="docutils literal"><span class="pre">Error</span></tt>, or there
|
||||
was no canceller, then the errback chain is started
|
||||
with <a class="mochiref reference" href="#fn-cancellederror">CancelledError</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.errback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Begin the callback sequence with an error result.
|
||||
Result may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
|
||||
but if <tt class="docutils literal"><span class="pre">!(result</span> <span class="pre">instanceof</span> <span class="pre">Error)</span></tt>, it will be wrapped
|
||||
with <a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</p>
|
||||
<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should
|
||||
be called exactly once on a
|
||||
<a name="fn-deferred"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlock"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlock">DeferredLock()</a>:</p>
|
||||
<blockquote>
|
||||
<p>A lock for asynchronous systems.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">locked</span></tt> property of a <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> will be <tt class="docutils literal"><span class="pre">true</span></tt> if
|
||||
it locked, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. Do not change this property.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlock.prototype.acquire"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlock.prototype.acquire">DeferredLock.prototype.acquire()</a>:</p>
|
||||
<blockquote>
|
||||
Attempt to acquire the lock. Returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that fires on
|
||||
lock acquisition with the <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> as the value.
|
||||
If the lock is locked, then the <a class="mochiref reference" href="#fn-deferred">Deferred</a> goes into a waiting
|
||||
list.</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlock.prototype.release"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlock.prototype.release">DeferredLock.prototype.release()</a>:</p>
|
||||
<blockquote>
|
||||
Release the lock. If there is a waiting list, then the first
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> in that waiting list will be called back.</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlist"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlist">DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Combine a list of <a class="mochiref reference" href="#fn-deferred">Deferred</a> into one. Track the callbacks and
|
||||
return a list of (success, result) tuples, 'success' being a boolean
|
||||
indicating whether result is a normal result or an error.</p>
|
||||
<p>Once created, you have access to all <a class="mochiref reference" href="#fn-deferred">Deferred</a> methods, like
|
||||
addCallback, addErrback, addBoth. The behaviour can be changed by the
|
||||
following options:</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">fireOnOneCallback</span></tt>:</dt>
|
||||
<dd>Flag for launching the callback once the first Deferred of the list
|
||||
has returned.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">fireOnOneErrback</span></tt>:</dt>
|
||||
<dd>Flag for calling the errback at the first error of a Deferred.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">consumeErrors</span></tt>:</dt>
|
||||
<dd>Flag indicating that any errors raised in the Deferreds should be
|
||||
consumed by the DeferredList.</dd>
|
||||
</dl>
|
||||
<p>Example:</p>
|
||||
<pre class="literal-block">
|
||||
// We need to fetch data from 2 different urls
|
||||
var d1 = loadJSONDoc(url1);
|
||||
var d2 = loadJSONDoc(url2);
|
||||
var l1 = new DeferredList([d1, d2], false, false, true);
|
||||
l1.addCallback(function (resultList) {
|
||||
MochiKit.Base.map(function (result) {
|
||||
if (result[0]) {
|
||||
alert("Data is here: " + result[1]);
|
||||
} else {
|
||||
alert("Got an error: " + result[1]);
|
||||
}
|
||||
}, resultList);
|
||||
});
|
||||
</pre>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-calllater"></a>
|
||||
<a class="mochidef reference" href="#fn-calllater">callLater(seconds, func[, args...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call <tt class="docutils literal"><span class="pre">func(args...)</span></tt> after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have elapsed.
|
||||
This is a convenience method for:</p>
|
||||
<pre class="literal-block">
|
||||
func = partial.apply(extend(null, arguments, 1));
|
||||
return wait(seconds).addCallback(function (res) { return func() });
|
||||
</pre>
|
||||
<p>Returns a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-dosimplexmlhttprequest"></a>
|
||||
<a class="mochidef reference" href="#fn-dosimplexmlhttprequest">doSimpleXMLHttpRequest(url[, queryArguments...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Perform a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> and wrap it with a
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> that may be cancelled.</p>
|
||||
<p>Note that currently, only <tt class="docutils literal"><span class="pre">200</span></tt> (OK) and <tt class="docutils literal"><span class="pre">304</span></tt>
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
|
||||
<dd>The URL to GET</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">queryArguments</span></tt>:</dt>
|
||||
<dd><p class="first">If this function is called with more than one argument, a <tt class="docutils literal"><span class="pre">"?"</span></tt>
|
||||
and the result of <a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a> with
|
||||
the rest of the arguments are appended to the URL.</p>
|
||||
<p>For example, this will do a GET request to the URL
|
||||
<tt class="docutils literal"><span class="pre">http://example.com?bar=baz</span></tt>:</p>
|
||||
<pre class="last literal-block">
|
||||
doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
|
||||
</pre>
|
||||
</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
|
||||
instance on success</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-evaljsonrequest"></a>
|
||||
<a class="mochidef reference" href="#fn-evaljsonrequest">evalJSONRequest(req)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Evaluate a JSON <a class="footnote-reference" href="#id10" id="id4" name="id4">[4]</a> <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
|
||||
<dd>The request whose <tt class="docutils literal"><span class="pre">.responseText</span></tt> property is to be evaluated</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A JavaScript object</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-fail"></a>
|
||||
<a class="mochidef reference" href="#fn-fail">fail([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had <tt class="docutils literal"><span class="pre">.errback(result)</span></tt>
|
||||
called.</p>
|
||||
<p>See <tt class="docutils literal"><span class="pre">succeed</span></tt> documentation for rationale.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
|
||||
<dd>The result to give to <a class="mochiref reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback(result)</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred()</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-gatherresults"></a>
|
||||
<a class="mochidef reference" href="#fn-gatherresults">gatherResults(deferreds)</a>:</p>
|
||||
<blockquote>
|
||||
A convenience function that returns a <a class="mochiref reference" href="#fn-deferredlist">DeferredList</a>
|
||||
from the given <tt class="docutils literal"><span class="pre">Array</span></tt> of <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances
|
||||
that will callback with an <tt class="docutils literal"><span class="pre">Array</span></tt> of just results when
|
||||
they're available, or errback on the first array.</blockquote>
|
||||
<p>
|
||||
<a name="fn-getxmlhttprequest"></a>
|
||||
<a class="mochidef reference" href="#fn-getxmlhttprequest">getXMLHttpRequest()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> compliant object for the current
|
||||
platform.</p>
|
||||
<p>In order of preference:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">XMLHttpRequest()</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP')</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Microsoft.XMLHTTP')</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP.4.0')</span></tt></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-maybedeferred"></a>
|
||||
<a class="mochidef reference" href="#fn-maybedeferred">maybeDeferred(func[, argument...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call a <tt class="docutils literal"><span class="pre">func</span></tt> with the given arguments and ensure the result is a
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">func</span></tt>:</dt>
|
||||
<dd>The function to call.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A new <a class="mochiref reference" href="#fn-deferred">Deferred</a> based on the call to <tt class="docutils literal"><span class="pre">func</span></tt>. If <tt class="docutils literal"><span class="pre">func</span></tt>
|
||||
does not naturally return a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, its result or error
|
||||
value will be wrapped by one.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-loadjsondoc"></a>
|
||||
<a class="mochidef reference" href="#fn-loadjsondoc">loadJSONDoc(url)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Do a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to a URL and get the response
|
||||
as a JSON <a class="footnote-reference" href="#id10" id="id5" name="id5">[4]</a> document.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
|
||||
<dd>The URL to GET</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the evaluated JSON <a class="footnote-reference" href="#id10" id="id6" name="id6">[4]</a>
|
||||
response upon successful <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-sendxmlhttprequest"></a>
|
||||
<a class="mochidef reference" href="#fn-sendxmlhttprequest">sendXMLHttpRequest(req[, sendContent])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Set an <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> handler on an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object
|
||||
and send it off. Will return a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will
|
||||
callback on success.</p>
|
||||
<p>Note that currently, only <tt class="docutils literal"><span class="pre">200</span></tt> (OK) and <tt class="docutils literal"><span class="pre">304</span></tt>
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
|
||||
<dd>An preconfigured <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object (open has been called).</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">sendContent</span></tt>:</dt>
|
||||
<dd>Optional string or DOM content to send over the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
|
||||
instance on success.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-succeed"></a>
|
||||
<a class="mochidef reference" href="#fn-succeed">succeed([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had <tt class="docutils literal"><span class="pre">.callback(result)</span></tt>
|
||||
called.</p>
|
||||
<p>This is useful when you're writing synchronous code to an asynchronous
|
||||
interface: i.e., some code is calling you expecting a <a class="mochiref reference" href="#fn-deferred">Deferred</a>
|
||||
result, but you don't actually need to do anything asynchronous. Just
|
||||
return <tt class="docutils literal"><span class="pre">succeed(theResult)</span></tt>.</p>
|
||||
<p>See <tt class="docutils literal"><span class="pre">fail</span></tt> for a version of this function that uses a failing
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> rather than a successful one.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
|
||||
<dd>The result to give to <a class="mochiref reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback(result)</a></dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-wait"></a>
|
||||
<a class="mochidef reference" href="#fn-wait">wait(seconds[, res])</a>:</p>
|
||||
<blockquote>
|
||||
Return a new cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will <tt class="docutils literal"><span class="pre">.callback(res)</span></tt>
|
||||
after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have elapsed.</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id7">[1]</a></td><td>AJAX, Asynchronous JavaScript and XML: <a class="reference" href="http://en.wikipedia.org/wiki/AJAX">http://en.wikipedia.org/wiki/AJAX</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id8" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id8">[2]</a></td><td>Twisted, an event-driven networking framework written in Python: <a class="reference" href="http://twistedmatrix.com/">http://twistedmatrix.com/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id9" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id3" name="id9">[3]</a></td><td>Twisted Deferred Reference: <a class="reference" href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html">http://twistedmatrix.com/projects/core/documentation/howto/defer.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id10" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id10">[4]</a></td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id5">2</a>, <a class="fn-backref" href="#id6">3</a>)</em> JSON, JavaScript Object Notation: <a class="reference" href="http://json.org/">http://json.org/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,509 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Color - color abstraction with CSS3 support</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Color - color abstraction with CSS3 support</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
// RGB color expressions are supported
|
||||
assert(
|
||||
objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
|
||||
);
|
||||
|
||||
// So is instantiating directly from HSL or RGB values.
|
||||
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
|
||||
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
|
||||
|
||||
// Or even SVG color keyword names, as per CSS3!
|
||||
assert( Color.fromString("aquamarine"), "#7fffd4" );
|
||||
|
||||
// NSColor-like colors built in
|
||||
assert( Color.whiteColor().toHexString() == "#ffffff" );
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Color is an abstraction for handling colors and strings that
|
||||
represent colors.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<p>MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha.
|
||||
It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG)
|
||||
color table.</p>
|
||||
<p>All of the functionality in this module is exposed through a Color constructor
|
||||
and its prototype, but a few of its internals are available for direct use at
|
||||
module level.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-color"></a>
|
||||
<a class="mochidef reference" href="#fn-color">Color()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Represents a color. Component values should be integers between <tt class="docutils literal"><span class="pre">0.0</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">1.0</span></tt>. You should use one of the <a class="mochiref reference" href="#fn-color">Color</a> factory
|
||||
functions such as <a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB</a>, <a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL</a>,
|
||||
etc. instead of constructing <a class="mochiref reference" href="#fn-color">Color</a> objects directly.</p>
|
||||
<p><a class="mochiref reference" href="#fn-color">Color</a> instances can be compared with
|
||||
<a class="mochiref reference" href="Base.html#fn-compare">MochiKit.Base.compare</a> (though ordering is on RGB, so is not
|
||||
particularly meaningful except for equality), and the default <tt class="docutils literal"><span class="pre">toString</span></tt>
|
||||
implementation returns <a class="mochiref reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>.</p>
|
||||
<p><a class="mochiref reference" href="#fn-color">Color</a> instances are immutable, and much of the architecture is
|
||||
inspired by AppKit's NSColor <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a></p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.frombackground"></a>
|
||||
<a class="mochidef reference" href="#fn-color.frombackground">Color.fromBackground(elem)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the background of the provided
|
||||
element. Equivalent to:</p>
|
||||
<pre class="literal-block">
|
||||
c = Color.fromComputedStyle(
|
||||
elem, "backgroundColor", "background-color") || Color.whiteColor();
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromcomputedstyle"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromcomputedstyle">Color.fromComputedStyle(elem, style, mozillaEquivalentCSS)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the result of
|
||||
<a class="mochiref reference" href="DOM.html#fn-computedstyle">MochiKit.DOM.computedStyle(elem, style, mozillaEquivalentCSS)</a>
|
||||
or <tt class="docutils literal"><span class="pre">null</span></tt> if not found.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhexstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhexstring">Color.fromHexString(hexString)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given hexadecimal color string.
|
||||
For example, <tt class="docutils literal"><span class="pre">"#FFFFFF"</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
|
||||
RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt> (white).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhsl"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhsl">Color.fromHSL(hue, saturation, lightness, alpha=1.0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>, <tt class="docutils literal"><span class="pre">saturation</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">lightness</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0.0</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhslstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhslstring">Color.fromHSLString(hslString)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal hsl color string.
|
||||
For example, <tt class="docutils literal"><span class="pre">"hsl(0,0%,100%)"</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
|
||||
HSL values <tt class="docutils literal"><span class="pre">[0/360,</span> <span class="pre">0/360,</span> <span class="pre">360/360]</span></tt> (white).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhsv"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhsv">Color.fromHSV(hue, saturation, value, alpha=1.0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>, <tt class="docutils literal"><span class="pre">saturation</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">value</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0.0</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-color.fromhsv">Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromname"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromname">Color.fromName(colorName)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object corresponding to the given
|
||||
SVG 1.0 color keyword name <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> as per the W3C CSS3
|
||||
Color Module <a class="footnote-reference" href="#id8" id="id3" name="id3">[3]</a>. <tt class="docutils literal"><span class="pre">"transparent"</span></tt> is also accepted
|
||||
as a color name, and will return <a class="mochiref reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromrgb"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromrgb">Color.fromRGB(red, green, blue, alpha=1.0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">red</span></tt>, <tt class="docutils literal"><span class="pre">green</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">blue</span></tt>, and <tt class="docutils literal"><span class="pre">alpha</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB({r: red, g: green, b: blue, a: alpha})</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromrgbstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromrgbstring">Color.fromRGBString(rgbString)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal rgb color string.
|
||||
For example, <tt class="docutils literal"><span class="pre">"rgb(255,255,255)"</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
|
||||
RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt> (white).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromtext"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromtext">Color.fromText(elem)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the text color of the provided
|
||||
element. Equivalent to:</p>
|
||||
<pre class="literal-block">
|
||||
c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromstring">Color.fromString(rgbOrHexString)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given RGB, HSL, hex, or name.
|
||||
Will return <tt class="docutils literal"><span class="pre">null</span></tt> if the string can not be parsed by any of these
|
||||
methods.</p>
|
||||
<p>See <a class="mochiref reference" href="#fn-color.fromhexstring">Color.fromHexString</a>, <a class="mochiref reference" href="#fn-color.fromrgbstring">Color.fromRGBString</a>,
|
||||
<a class="mochiref reference" href="#fn-color.fromhslstring">Color.fromHSLString</a> and <a class="mochiref reference" href="#fn-color.fromname">Color.fromName</a> more
|
||||
information.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.namedcolors"></a>
|
||||
<a class="mochidef reference" href="#fn-color.namedcolors">Color.namedColors()</a>:</p>
|
||||
<blockquote>
|
||||
Returns an object with properties for each SVG 1.0 color keyword
|
||||
name <a class="footnote-reference" href="#id7" id="id4" name="id4">[2]</a> supported by CSS3 <a class="footnote-reference" href="#id8" id="id5" name="id5">[3]</a>. Property names are the color keyword
|
||||
name in lowercase, and the value is a string suitable for
|
||||
<a class="mochiref reference" href="#fn-color.fromstring">Color.fromString()</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithalpha"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithalpha">Color.prototype.colorWithAlpha(alpha)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">alpha</span></tt> value.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithhue"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithhue">Color.prototype.colorWithHue(hue)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">hue</span></tt> value.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithsaturation"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithsaturation">Color.prototype.colorWithSaturation(saturation)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">saturation</span></tt> value (using the HSL color model).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithlightness"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithlightness">Color.prototype.colorWithLightness(lightness)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">lightness</span></tt> value.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.darkercolorwithlevel"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.darkercolorwithlevel">Color.prototype.darkerColorWithLevel(level)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but darker by the given
|
||||
<tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.lightercolorwithlevel"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.lightercolorwithlevel">Color.prototype.lighterColorWithLevel(level)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but lighter by the given
|
||||
<tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.blendedcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.blendedcolor">Color.prototype.blendedColor(other, fraction=0.5)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> whose RGBA component values are a weighted sum
|
||||
of this color and <tt class="docutils literal"><span class="pre">other</span></tt>. Each component of the returned color
|
||||
is the <tt class="docutils literal"><span class="pre">fraction</span></tt> of other's value plus <tt class="docutils literal"><span class="pre">1</span> <span class="pre">-</span> <span class="pre">fraction</span></tt> of this
|
||||
color's.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.islight"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.islight">Color.prototype.isLight()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is greater than
|
||||
<tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
|
||||
<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color components
|
||||
are not premultiplied).</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.isdark"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.isdark">Color.prototype.isDark()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is less than or
|
||||
equal to <tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
|
||||
<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color components
|
||||
are not premultiplied).</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.torgbstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.torgbstring">Color.prototype.toRGBString()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the decimal <tt class="docutils literal"><span class="pre">"rgb(red,</span> <span class="pre">green,</span> <span class="pre">blue)"</span></tt> string representation of this
|
||||
color.</p>
|
||||
<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
|
||||
<tt class="docutils literal"><span class="pre">"rgba(red,</span> <span class="pre">green,</span> <span class="pre">blue,</span> <span class="pre">alpha)"</span></tt> string representation will be used.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.tohslstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.tohslstring">Color.prototype.toHSLString()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the decimal <tt class="docutils literal"><span class="pre">"hsl(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness)"</span></tt>
|
||||
string representation of this color.</p>
|
||||
<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
|
||||
<tt class="docutils literal"><span class="pre">"hsla(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness,</span> <span class="pre">alpha)"</span></tt> string representation
|
||||
will be used.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.tohexstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the hexadecimal <tt class="docutils literal"><span class="pre">"#RRGGBB"</span></tt> string representation of this color.</p>
|
||||
<p>Note that the alpha component is completely ignored for hexadecimal
|
||||
string representations!</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
assert( Color.whiteColor().toHexString() == "#FFFFFF" );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.asrgb"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.asrgb">Color.prototype.asRGB()</a>:</p>
|
||||
<blockquote>
|
||||
Return the RGB (red, green, blue, alpha) components of this color as an
|
||||
object with <tt class="docutils literal"><span class="pre">r</span></tt>, <tt class="docutils literal"><span class="pre">g</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, and <tt class="docutils literal"><span class="pre">a</span></tt> properties that have
|
||||
values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.ashsl"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.ashsl">Color.prototype.asHSL()</a>:</p>
|
||||
<blockquote>
|
||||
Return the HSL (hue, saturation, lightness, alpha) components of this
|
||||
color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">l</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
|
||||
that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.ashsv"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.ashsv">Color.prototype.asHSV()</a>:</p>
|
||||
<blockquote>
|
||||
Return the HSV (hue, saturation, value, alpha) components of this
|
||||
color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">v</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
|
||||
that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.blackcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.blackcolor">Color.blackColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 0
|
||||
(#000000).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.bluecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.bluecolor">Color.blueColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 1
|
||||
(#0000ff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.browncolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.browncolor">Color.brownColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.6, 0.4, 0.2
|
||||
(#996633).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.cyancolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.cyancolor">Color.cyanColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 1
|
||||
(#00ffff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.darkgraycolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.darkgraycolor">Color.darkGrayColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1/3, 1/3, 1/3
|
||||
(#555555).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.graycolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.graycolor">Color.grayColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0.5, 0.5
|
||||
(#808080).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.greencolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.greencolor">Color.greenColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 0.
|
||||
(#00ff00).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.lightgraycolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.lightgraycolor">Color.lightGrayColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 2/3, 2/3, 2/3
|
||||
(#aaaaaa).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.magentacolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.magentacolor">Color.magentaColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 1
|
||||
(#ff00ff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.orangecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.orangecolor">Color.orangeColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0.5, 0
|
||||
(#ff8000).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.purplecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.purplecolor">Color.purpleColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0, 0.5
|
||||
(#800080).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.redcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.redcolor">Color.redColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 0
|
||||
(#ff0000).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.whitecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.whitecolor">Color.whiteColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 1
|
||||
(#ffffff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.yellowcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.yellowcolor">Color.yellowColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 0
|
||||
(#ffff00).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.transparentcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object that is completely transparent
|
||||
(has alpha component of 0).</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-clampcolorcomponent"></a>
|
||||
<a class="mochidef reference" href="#fn-clampcolorcomponent">clampColorComponent(num, scale)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns <tt class="docutils literal"><span class="pre">num</span> <span class="pre">*</span> <span class="pre">scale</span></tt> clamped between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">scale</span></tt>.</p>
|
||||
<p><a class="mochiref reference" href="#fn-clampcolorcomponent">clampColorComponent</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-hsltorgb"></a>
|
||||
<a class="mochidef reference" href="#fn-hsltorgb">hslToRGB(hue, saturation, lightness, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes RGB values from the provided HSL values. The return value is a
|
||||
mapping with <tt class="docutils literal"><span class="pre">"r"</span></tt>, <tt class="docutils literal"><span class="pre">"g"</span></tt>, <tt class="docutils literal"><span class="pre">"b"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-hsvtorgb"></a>
|
||||
<a class="mochidef reference" href="#fn-hsvtorgb">hsvToRGB(hue, saturation, value, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes RGB values from the provided HSV values. The return value is a
|
||||
mapping with <tt class="docutils literal"><span class="pre">"r"</span></tt>, <tt class="docutils literal"><span class="pre">"g"</span></tt>, <tt class="docutils literal"><span class="pre">"b"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB({h: hue, s: saturation, v: value, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-tocolorpart"></a>
|
||||
<a class="mochidef reference" href="#fn-tocolorpart">toColorPart(num)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert num to a zero padded hexadecimal digit for use in a hexadecimal
|
||||
color string. Num should be an integer between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">255</span></tt>.</p>
|
||||
<p><a class="mochiref reference" href="#fn-tocolorpart">toColorPart</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-rgbtohsl"></a>
|
||||
<a class="mochidef reference" href="#fn-rgbtohsl">rgbToHSL(red, green, blue, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes HSL values based on the provided RGB values. The return value is
|
||||
a mapping with <tt class="docutils literal"><span class="pre">"h"</span></tt>, <tt class="docutils literal"><span class="pre">"s"</span></tt>, <tt class="docutils literal"><span class="pre">"l"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL({r: red, g: green, b: blue, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-rgbtohsv"></a>
|
||||
<a class="mochidef reference" href="#fn-rgbtohsv">rgbToHSV(red, green, blue, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes HSV values based on the provided RGB values. The return value is
|
||||
a mapping with <tt class="docutils literal"><span class="pre">"h"</span></tt>, <tt class="docutils literal"><span class="pre">"s"</span></tt>, <tt class="docutils literal"><span class="pre">"v"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV({r: red, g: green, b: blue, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id7">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id8" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id8">[3]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id5">2</a>)</em> W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,798 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.DOM - painless DOM manipulation API</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.DOM - painless DOM manipulation API</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
// put that in your document.createElement and smoke it!
|
||||
swapDOM(oldTable, newTable);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>As you probably know, the DOM APIs are some of the most painful Java-inspired
|
||||
APIs you'll run across from a highly dynamic language. Don't worry about that
|
||||
though, because they provide a reasonable basis to build something that
|
||||
sucks a lot less.</p>
|
||||
<p>MochiKit.DOM takes much of its inspiration from Nevow's <a class="footnote-reference" href="#id5" id="id1" name="id1">[1]</a> stan <a class="footnote-reference" href="#id6" id="id2" name="id2">[2]</a>.
|
||||
This means you choose a tag, give it some attributes, then stuff it full
|
||||
of <em>whatever objects you want</em>. MochiKit.DOM isn't stupid, it knows that
|
||||
a string should be a text node, and that you want functions to be called,
|
||||
and that <tt class="docutils literal"><span class="pre">Array</span></tt>-like objects should be expanded, and stupid <tt class="docutils literal"><span class="pre">null</span></tt> values
|
||||
should be skipped.</p>
|
||||
<p>Hell, it will let you return strings from functions, and use iterators from
|
||||
<a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>. If that's not enough, just teach it new tricks with
|
||||
<a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>. If you have never used an API like this for
|
||||
creating DOM elements, you've been wasting your damn time. Get with it!</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="dom-coercion-rules" name="dom-coercion-rules">DOM Coercion Rules</a></h2>
|
||||
<p>In order of precedence, <a class="mochiref reference" href="#fn-createdom">createDOM</a> coerces given arguments to DOM
|
||||
nodes using the following rules:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Functions are called with a <tt class="docutils literal"><span class="pre">this</span></tt> of the parent
|
||||
node and their return value is subject to the
|
||||
following rules (even this one).</li>
|
||||
<li><tt class="docutils literal"><span class="pre">undefined</span></tt> and <tt class="docutils literal"><span class="pre">null</span></tt> are ignored.</li>
|
||||
<li>Iterables (see <a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>) are flattened
|
||||
(as if they were passed in-line as nodes) and each
|
||||
return value is subject to all of these rules.</li>
|
||||
<li>Values that look like DOM nodes (objects with a
|
||||
<tt class="docutils literal"><span class="pre">.nodeType</span> <span class="pre">></span> <span class="pre">0</span></tt>) are <tt class="docutils literal"><span class="pre">.appendChild</span></tt>'ed to the created
|
||||
DOM fragment.</li>
|
||||
<li>Strings are wrapped up with <tt class="docutils literal"><span class="pre">document.createTextNode</span></tt></li>
|
||||
<li>Objects that are not strings are run through the <tt class="docutils literal"><span class="pre">domConverters</span></tt>
|
||||
<a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a>
|
||||
(see <a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>).
|
||||
The value returned by the adapter is subject to these same rules (e.g.
|
||||
adapters are allowed to return a string, which will be coerced into a
|
||||
text node).</li>
|
||||
<li>If no adapter is available, <tt class="docutils literal"><span class="pre">.toString()</span></tt> is used to create a text node.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="creating-dom-element-trees" name="creating-dom-element-trees">Creating DOM Element Trees</a></h2>
|
||||
<p><a class="mochiref reference" href="#fn-createdom">createDOM</a> provides you with an excellent facility for creating DOM trees
|
||||
that is easy on the wrists. One of the best ways to understand how to use
|
||||
it is to take a look at an example:</p>
|
||||
<pre class="literal-block">
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
</pre>
|
||||
<p>This will create a table with the following visual layout (if it
|
||||
were inserted into the document DOM):</p>
|
||||
<blockquote>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="33%" />
|
||||
<col width="33%" />
|
||||
<col width="33%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th class="head">head1</th>
|
||||
<th class="head">head2</th>
|
||||
<th class="head">head3</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td>dataA1</td>
|
||||
<td>dataA2</td>
|
||||
<td>dataA3</td>
|
||||
</tr>
|
||||
<tr><td>dataB1</td>
|
||||
<td>dataB2</td>
|
||||
<td>dataB3</td>
|
||||
</tr>
|
||||
<tr><td>foot1</td>
|
||||
<td>foot2</td>
|
||||
<td>foot3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>Corresponding to the following HTML:</p>
|
||||
<pre class="literal-block">
|
||||
<table class="prettytable">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>head1</td>
|
||||
<td>head2</td>
|
||||
<td>head3</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>foot1</td>
|
||||
<td>foot2</td>
|
||||
<td>foot3</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>dataA1</td>
|
||||
<td>dataA2</td>
|
||||
<td>dataA3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dataB1</td>
|
||||
<td>dataB2</td>
|
||||
<td>dataB3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="dom-context" name="dom-context">DOM Context</a></h2>
|
||||
<p>In order to prevent having to pass a <tt class="docutils literal"><span class="pre">window</span></tt> and/or <tt class="docutils literal"><span class="pre">document</span></tt>
|
||||
variable to every MochiKit.DOM function (e.g. when working with a
|
||||
child window), MochiKit.DOM maintains a context variable for each
|
||||
of them. They are managed with the <a class="mochiref reference" href="#fn-withwindow">withWindow</a> and
|
||||
<a class="mochiref reference" href="#fn-withdocument">withDocument</a> functions, and can be acquired with
|
||||
<a class="mochiref reference" href="#fn-currentwindow">currentWindow()</a> and <a class="mochiref reference" href="#fn-currentdocument">currentDocument()</a></p>
|
||||
<p>For example, if you are creating DOM nodes in a child window, you
|
||||
could do something like this:</p>
|
||||
<pre class="literal-block">
|
||||
withWindow(child, function () {
|
||||
var doc = currentDocument();
|
||||
appendChildNodes(doc.body, H1(null, "This is in the child!"));
|
||||
});
|
||||
</pre>
|
||||
<p>Note that <a class="mochiref reference" href="#fn-withwindow">withWindow(win, ...)</a> also implies
|
||||
<a class="mochiref reference" href="#fn-withdocument">withDocument(win.document, ...)</a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="element-visibility" name="element-visibility">Element Visibility</a></h2>
|
||||
<p>The <a class="mochiref reference" href="#fn-hideelement">hideElement</a> and <a class="mochiref reference" href="#fn-showelement">showElement</a> functions are
|
||||
provided as a convenience, but only work for elements that are
|
||||
<tt class="docutils literal"><span class="pre">display:</span> <span class="pre">block</span></tt>. For a general solution to showing, hiding, and checking
|
||||
the explicit visibility of elements, we recommend using a solution that
|
||||
involves a little CSS. Here's an example:</p>
|
||||
<pre class="literal-block">
|
||||
<style type="text/css">
|
||||
.invisible { display: none; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function toggleVisible(elem) {
|
||||
toggleElementClass("invisible", elem);
|
||||
}
|
||||
|
||||
function makeVisible(elem) {
|
||||
removeElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function makeInvisible(elem) {
|
||||
addElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function isVisible(elem) {
|
||||
// you may also want to check for
|
||||
// getElement(elem).style.display == "none"
|
||||
return !hasElementClass(elem, "invisible");
|
||||
};
|
||||
</script>
|
||||
</pre>
|
||||
<p>MochiKit doesn't ship with such a solution, because there is no reliable and
|
||||
portable method for adding CSS rules on the fly with JavaScript.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-$"></a>
|
||||
<a class="mochidef reference" href="#fn-$">$(id[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
An alias for <a class="mochiref reference" href="#fn-getelement">getElement(id[, ...])</a></blockquote>
|
||||
<p>
|
||||
<a name="fn-addelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-addelementclass">addElementClass(element, className)</a>:</p>
|
||||
<blockquote>
|
||||
Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> has <tt class="docutils literal"><span class="pre">className</span></tt> set as part of its
|
||||
class attribute. This will not disturb other class names.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-addloadevent"></a>
|
||||
<a class="mochidef reference" href="#fn-addloadevent">addLoadEvent(func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Note that <a class="mochiref reference" href="#fn-addloadevent">addLoadEvent</a> can not be used in combination with
|
||||
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> if the <tt class="docutils literal"><span class="pre">onload</span></tt> event is connected.
|
||||
Once an event is connected with <a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs
|
||||
may be used for that same event.</p>
|
||||
<p>This will stack <tt class="docutils literal"><span class="pre">window.onload</span></tt> functions on top of each other.
|
||||
Each function added will be called after <tt class="docutils literal"><span class="pre">onload</span></tt> in the
|
||||
order that they were added.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-addtocallstack"></a>
|
||||
<a class="mochidef reference" href="#fn-addtocallstack">addToCallStack(target, path, func[, once])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Note that <a class="mochiref reference" href="#fn-addtocallstack">addToCallStack</a> is not compatible with
|
||||
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>. Once an event is connected with
|
||||
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs may be used for that same event.</p>
|
||||
<p>Set the property <tt class="docutils literal"><span class="pre">path</span></tt> of <tt class="docutils literal"><span class="pre">target</span></tt> to a function that calls the
|
||||
existing function at that property (if any), then calls <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">target[path]()</span></tt> returns exactly <tt class="docutils literal"><span class="pre">false</span></tt>, then <tt class="docutils literal"><span class="pre">func</span></tt> will
|
||||
not be called.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">once</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then <tt class="docutils literal"><span class="pre">target[path]</span></tt> is set to <tt class="docutils literal"><span class="pre">null</span></tt> after
|
||||
the function call stack has completed.</p>
|
||||
<p>If called several times for the same <tt class="docutils literal"><span class="pre">target[path]</span></tt>, it will create
|
||||
a stack of functions (instead of just a pair).</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-appendchildnodes"></a>
|
||||
<a class="mochidef reference" href="#fn-appendchildnodes">appendChildNodes(node[, childNode[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Append children to a DOM element using the <a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to add children to
|
||||
(if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
|
||||
will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
|
||||
<dd>All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-computedstyle"></a>
|
||||
<a class="mochidef reference" href="#fn-computedstyle">computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)</a>:</p>
|
||||
<blockquote>
|
||||
Looks up a CSS property for the given element. The element can be
|
||||
specified as either a string with the element's ID or the element
|
||||
object itself.</blockquote>
|
||||
<p>
|
||||
<a name="fn-createdom"></a>
|
||||
<a class="mochidef reference" href="#fn-createdom">createDOM(name[, attrs[, node[, ...]]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Create a DOM fragment in a really convenient manner, much like
|
||||
Nevow`s <a class="footnote-reference" href="#id5" id="id3" name="id3">[1]</a> stan <a class="footnote-reference" href="#id6" id="id4" name="id4">[2]</a>.</p>
|
||||
<p>Partially applied versions of this function for common tags are
|
||||
available as aliases:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">A</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">BUTTON</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">BR</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">CANVAS</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">DIV</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">FIELDSET</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">FORM</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">H1</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">H2</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">H3</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">HR</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">IMG</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">INPUT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">LABEL</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">LEGEND</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">LI</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">OL</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">OPTGROUP</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">OPTION</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">P</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">PRE</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">SELECT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">SPAN</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">STRONG</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TABLE</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TBODY</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TD</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TEXTAREA</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TFOOT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TH</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">THEAD</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TR</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">UL</span></tt></li>
|
||||
</ul>
|
||||
<p>See <a class="reference" href="#creating-dom-element-trees">Creating DOM Element Trees</a> for a comprehensive example.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
|
||||
<dd>The kind of fragment to create (e.g. 'span'), such as you would
|
||||
pass to <tt class="docutils literal"><span class="pre">document.createElement</span></tt>.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
|
||||
<dd><p class="first">An object whose properties will be used as the attributes
|
||||
(e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">'display:block'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
|
||||
attributes need to be set.</p>
|
||||
<p>See <a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a> for more information.</p>
|
||||
<p class="last">For convenience, if <tt class="docutils literal"><span class="pre">attrs</span></tt> is a string, <tt class="docutils literal"><span class="pre">null</span></tt> is used
|
||||
and the string will be considered the first <tt class="docutils literal"><span class="pre">node</span></tt>.</p>
|
||||
</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
|
||||
<dd>All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-createdomfunc"></a>
|
||||
<a class="mochidef reference" href="#fn-createdomfunc">createDOMFunc(tag[, attrs[, node[, ...]]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convenience function to create a partially applied createDOM
|
||||
function. You'd want to use this if you add additional convenience
|
||||
functions for creating tags, or if you find yourself creating
|
||||
a lot of tags with a bunch of the same attributes or contents.</p>
|
||||
<p>See <a class="mochiref reference" href="#fn-createdom">createDOM</a> for more detailed descriptions of the arguments.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">tag</span></tt>:</dt>
|
||||
<dd>The name of the tag</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
|
||||
<dd>Optionally specify the attributes to apply</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
|
||||
<dd>Optionally specify any children nodes it should have</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>function that takes additional arguments and calls
|
||||
<a class="mochiref reference" href="#fn-createdom">createDOM</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-currentdocument"></a>
|
||||
<a class="mochidef reference" href="#fn-currentdocument">currentDocument()</a>:</p>
|
||||
<blockquote>
|
||||
Return the current <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
|
||||
be the same as the global <tt class="docutils literal"><span class="pre">document</span></tt> unless <a class="mochiref reference" href="#fn-withdocument">withDocument</a> or
|
||||
<a class="mochiref reference" href="#fn-withwindow">withWindow</a> is currently executing.</blockquote>
|
||||
<p>
|
||||
<a name="fn-currentwindow"></a>
|
||||
<a class="mochidef reference" href="#fn-currentwindow">currentWindow()</a>:</p>
|
||||
<blockquote>
|
||||
Return the current <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
|
||||
be the same as the global <tt class="docutils literal"><span class="pre">window</span></tt> unless <a class="mochiref reference" href="#fn-withwindow">withWindow</a> is
|
||||
currently executing.</blockquote>
|
||||
<p>
|
||||
<a name="fn-elementdimensions"></a>
|
||||
<a class="mochidef reference" href="#fn-elementdimensions">elementDimensions(element)</a>:</p>
|
||||
<blockquote>
|
||||
Return the absolute pixel width and height of <tt class="docutils literal"><span class="pre">element</span></tt> as an object with
|
||||
<tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt> is not in the
|
||||
document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to be looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object with
|
||||
<tt class="docutils literal"><span class="pre">w</span></tt> and/or <tt class="docutils literal"><span class="pre">h</span></tt> properties.</blockquote>
|
||||
<p>
|
||||
<a name="fn-elementposition"></a>
|
||||
<a class="mochidef reference" href="#fn-elementposition">elementPosition(element[, relativeTo={x: 0, y: 0}])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the absolute pixel position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document as an
|
||||
object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt>
|
||||
is not in the document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to
|
||||
be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially
|
||||
as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">relativeTo</span></tt> is given, then its coordinates are subtracted from
|
||||
the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt>, e.g.:</p>
|
||||
<pre class="literal-block">
|
||||
var elemPos = elementPosition(elem);
|
||||
var anotherElemPos = elementPosition(anotherElem);
|
||||
var relPos = elementPosition(elem, anotherElem);
|
||||
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
|
||||
assert( relPos.y == (elemPos.y - anotherElemPos.y) );
|
||||
</pre>
|
||||
<p><tt class="docutils literal"><span class="pre">relativeTo</span></tt> may be specified as a string to be looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object
|
||||
with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-emithtml"></a>
|
||||
<a class="mochidef reference" href="#fn-emithtml">emitHTML(dom[, lst])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert a DOM tree to an <tt class="docutils literal"><span class="pre">Array</span></tt> of HTML string fragments</p>
|
||||
<p>You probably want to use <a class="mochiref reference" href="#fn-tohtml">toHTML</a> instead.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-escapehtml"></a>
|
||||
<a class="mochidef reference" href="#fn-escapehtml">escapeHTML(s)</a>:</p>
|
||||
<blockquote>
|
||||
Make a string safe for HTML, converting the usual suspects (lt,
|
||||
gt, quot, apos, amp)</blockquote>
|
||||
<p>
|
||||
<a name="fn-focusonload"></a>
|
||||
<a class="mochidef reference" href="#fn-focusonload">focusOnLoad(element)</a>:</p>
|
||||
<blockquote>
|
||||
Add an onload event to focus the given element</blockquote>
|
||||
<p>
|
||||
<a name="fn-formcontents"></a>
|
||||
<a class="mochidef reference" href="#fn-formcontents">formContents(elem)</a>:</p>
|
||||
<blockquote>
|
||||
Search the DOM tree, starting at <tt class="docutils literal"><span class="pre">elem</span></tt>, for any elements with a
|
||||
<tt class="docutils literal"><span class="pre">name</span></tt> and <tt class="docutils literal"><span class="pre">value</span></tt> attribute. Return a 2-element <tt class="docutils literal"><span class="pre">Array</span></tt> of
|
||||
<tt class="docutils literal"><span class="pre">names</span></tt> and <tt class="docutils literal"><span class="pre">values</span></tt> suitable for use with
|
||||
<a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-getelement"></a>
|
||||
<a class="mochidef reference" href="#fn-getelement">getElement(id[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>A small quick little function to encapsulate the <tt class="docutils literal"><span class="pre">getElementById</span></tt>
|
||||
method. It includes a check to ensure we can use that method.</p>
|
||||
<p>If the id isn't a string, it will be returned as-is.</p>
|
||||
<p>Also available as <a class="mochiref reference" href="#fn-$">$(...)</a> for convenience and compatibility with
|
||||
other JavaScript frameworks.</p>
|
||||
<p>If multiple arguments are given, an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-getelementsbytagandclassname"></a>
|
||||
<a class="mochidef reference" href="#fn-getelementsbytagandclassname">getElementsByTagAndClassName(tagName, className, parent=document)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns an array of elements in <tt class="docutils literal"><span class="pre">parent</span></tt> that match the tag name
|
||||
and class name provided. If <tt class="docutils literal"><span class="pre">parent</span></tt> is a string, it will be looked
|
||||
up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">tagName</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt> or <tt class="docutils literal"><span class="pre">"*"</span></tt>, all elements will be searched
|
||||
for the matching class.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">className</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, all elements matching the provided tag are
|
||||
returned.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-getnodeattribute"></a>
|
||||
<a class="mochidef reference" href="#fn-getnodeattribute">getNodeAttribute(node, attr)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Get the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return <tt class="docutils literal"><span class="pre">null</span></tt> on exception).</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
|
||||
<dd><p class="first">The name of the attribute</p>
|
||||
<p class="last">Note that it will do the right thing for IE, so don't do
|
||||
the <tt class="docutils literal"><span class="pre">class</span></tt> -> <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
|
||||
</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The attribute's value, or <tt class="docutils literal"><span class="pre">null</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-getviewportdimensions"></a>
|
||||
<a class="mochidef reference" href="#fn-getviewportdimensions">getViewportDimensions()</a>:</p>
|
||||
<blockquote>
|
||||
Return the pixel width and height of the viewport as an object with <tt class="docutils literal"><span class="pre">w</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">h</span></tt> properties. <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-haselementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-haselementclass">hasElementClass(element, className[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">className</span></tt> is found on the <tt class="docutils literal"><span class="pre">element</span></tt>.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-hideelement"></a>
|
||||
<a class="mochidef reference" href="#fn-hideelement">hideElement(element, ...)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
|
||||
<pre class="literal-block">
|
||||
partial(setDisplayForElement, "none")
|
||||
</pre>
|
||||
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-registerdomconverter"></a>
|
||||
<a class="mochidef reference" href="#fn-registerdomconverter">registerDOMConverter(name, check, wrap[, override])</a>:</p>
|
||||
<blockquote>
|
||||
Register an adapter to convert objects that match <tt class="docutils literal"><span class="pre">check(obj,</span> <span class="pre">ctx)</span></tt>
|
||||
to a DOM element, or something that can be converted to a DOM
|
||||
element (i.e. number, bool, string, function, iterable).</blockquote>
|
||||
<p>
|
||||
<a name="fn-removeelement"></a>
|
||||
<a class="mochidef reference" href="#fn-removeelement">removeElement(node)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Remove and return <tt class="docutils literal"><span class="pre">node</span></tt> from a DOM tree. This is technically
|
||||
just a convenience for <a class="mochiref reference" href="#fn-swapdom">swapDOM(node, null)</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>the DOM element (or string id of one) to be removed</dd>
|
||||
<dt><em>returns</em></dt>
|
||||
<dd>The removed element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-removeelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-removeelementclass">removeElementClass(element, className)</a>:</p>
|
||||
<blockquote>
|
||||
Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> does not have <tt class="docutils literal"><span class="pre">className</span></tt> set as part
|
||||
of its class attribute. This will not disturb other class names.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-replacechildnodes"></a>
|
||||
<a class="mochidef reference" href="#fn-replacechildnodes">replaceChildNodes(node[, childNode[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Remove all children from the given DOM element, then append any given
|
||||
childNodes to it (by calling <a class="mochiref reference" href="#fn-appendchildnodes">appendChildNodes</a>).</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to add children to
|
||||
(if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
|
||||
will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
|
||||
<dd>All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-scrapetext"></a>
|
||||
<a class="mochidef reference" href="#fn-scrapetext">scrapeText(node[, asArray=false])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Walk a DOM tree in-order and scrape all of the text out of it as a
|
||||
<tt class="docutils literal"><span class="pre">string</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">asArray</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned with
|
||||
each individual text node. These two are equivalent:</p>
|
||||
<pre class="literal-block">
|
||||
assert( scrapeText(node) == scrapeText(node, true).join("") );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setdisplayforelement"></a>
|
||||
<a class="mochidef reference" href="#fn-setdisplayforelement">setDisplayForElement(display, element[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Change the <tt class="docutils literal"><span class="pre">style.display</span></tt> for the given element(s). Usually
|
||||
used as the partial forms:</p>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="#fn-showelement">showElement(element, ...)</a></li>
|
||||
<li><a class="mochiref reference" href="#fn-hideelement">hideElement(element, ...)</a></li>
|
||||
</ul>
|
||||
<p>Elements are looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are acceptable.</p>
|
||||
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-setelementclass">setElementClass(element, className)</a>:</p>
|
||||
<blockquote>
|
||||
Set the entire class attribute of <tt class="docutils literal"><span class="pre">element</span></tt> to <tt class="docutils literal"><span class="pre">className</span></tt>.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-setelementdimensions"></a>
|
||||
<a class="mochidef reference" href="#fn-setelementdimensions">setElementDimensions(element, dimensions[, units='px'])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Sets the dimensions of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
|
||||
object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">dimensions</span></tt>:</dt>
|
||||
<dd>An object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
|
||||
<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setelementposition"></a>
|
||||
<a class="mochidef reference" href="#fn-setelementposition">setElementPosition(element, position[, units='px'])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Sets the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
|
||||
object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">position</span></tt>:</dt>
|
||||
<dd>An object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
|
||||
<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setnodeattribute"></a>
|
||||
<a class="mochidef reference" href="#fn-setnodeattribute">setNodeAttribute(node, attr, value)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Set the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return null on exception). If
|
||||
setting more than one attribute, you should use
|
||||
<a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
|
||||
<dd><p class="first">The name of the attribute</p>
|
||||
<p class="last">Note that it will do the right thing for IE, so don't do
|
||||
the <tt class="docutils literal"><span class="pre">class</span></tt> -> <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
|
||||
</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">value</span></tt>:</dt>
|
||||
<dd>The value of the attribute, may be an object to be merged
|
||||
(e.g. for setting style).</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element or <tt class="docutils literal"><span class="pre">null</span></tt> on failure</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setopacity"></a>
|
||||
<a class="mochidef reference" href="#fn-setopacity">setOpacity(element, opacity)</a>:</p>
|
||||
<blockquote>
|
||||
Sets <tt class="docutils literal"><span class="pre">opacity</span></tt> for <tt class="docutils literal"><span class="pre">element</span></tt>. Valid <tt class="docutils literal"><span class="pre">opacity</span></tt> values range from 0
|
||||
(invisible) to 1 (opaque). <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-showelement"></a>
|
||||
<a class="mochidef reference" href="#fn-showelement">showElement(element, ...)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
|
||||
<pre class="literal-block">
|
||||
partial(setDisplayForElement, "block")
|
||||
</pre>
|
||||
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-swapdom"></a>
|
||||
<a class="mochidef reference" href="#fn-swapdom">swapDOM(dest, src)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Replace <tt class="docutils literal"><span class="pre">dest</span></tt> in a DOM tree with <tt class="docutils literal"><span class="pre">src</span></tt>, returning <tt class="docutils literal"><span class="pre">src</span></tt>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">dest</span></tt>:</dt>
|
||||
<dd>a DOM element (or string id of one) to be replaced</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">src</span></tt>:</dt>
|
||||
<dd>the DOM element (or string id of one) to replace it with, or
|
||||
<tt class="docutils literal"><span class="pre">null</span></tt> if <tt class="docutils literal"><span class="pre">dest</span></tt> is to be removed (replaced with nothing).</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>a DOM element (<tt class="docutils literal"><span class="pre">src</span></tt>)</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-swapelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-swapelementclass">swapElementClass(element, fromClass, toClass)</a>:</p>
|
||||
<blockquote>
|
||||
If <tt class="docutils literal"><span class="pre">fromClass</span></tt> is set on <tt class="docutils literal"><span class="pre">element</span></tt>, replace it with <tt class="docutils literal"><span class="pre">toClass</span></tt>.
|
||||
This will not disturb other classes on that element.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-toggleelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-toggleelementclass">toggleElementClass(className[, element[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Toggle the presence of a given <tt class="docutils literal"><span class="pre">className</span></tt> in the class attribute
|
||||
of all given elements. All elements will be looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-tohtml"></a>
|
||||
<a class="mochidef reference" href="#fn-tohtml">toHTML(dom)</a>:</p>
|
||||
<blockquote>
|
||||
Convert a DOM tree to a HTML string using <a class="mochiref reference" href="#fn-emithtml">emitHTML</a></blockquote>
|
||||
<p>
|
||||
<a name="fn-updatenodeattributes"></a>
|
||||
<a class="mochidef reference" href="#fn-updatenodeattributes">updateNodeAttributes(node, attrs)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Update the attributes of a DOM element from a given object.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
|
||||
<dd><p class="first">An object whose properties will be used to set the attributes
|
||||
(e.g. <tt class="docutils literal"><span class="pre">{'class':</span> <span class="pre">'invisible'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
|
||||
attributes need to be set. If an object is given for the
|
||||
attribute value (e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">{'display':</span> <span class="pre">'block'}}</span></tt>)
|
||||
then <a class="mochiref reference" href="Base.html#fn-updatetree">MochiKit.Base.updatetree</a> will be used to set that
|
||||
attribute.</p>
|
||||
<p class="last">Note that it will do the right thing for IE, so don't do
|
||||
the <tt class="docutils literal"><span class="pre">class</span></tt> -> <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself, and it deals with
|
||||
setting "on..." event handlers correctly.</p>
|
||||
</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-withwindow"></a>
|
||||
<a class="mochidef reference" href="#fn-withwindow">withWindow(win, func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win</span></tt> and
|
||||
the <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win.document</span></tt>. When
|
||||
<tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a> will be
|
||||
restored to its previous state.</p>
|
||||
<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-withdocument"></a>
|
||||
<a class="mochidef reference" href="#fn-withdocument">withDocument(doc, func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">doc</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">doc</span></tt>.
|
||||
When <tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a>
|
||||
will be restored to its previous state.</p>
|
||||
<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id5" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id5">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> Nevow, a web application construction kit for Python: <a class="reference" href="http://nevow.com/">http://nevow.com/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id6">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> nevow.stan is a domain specific language for Python
|
||||
(read as "crazy getitem/call overloading abuse") that Donovan and I
|
||||
schemed up at PyCon 2003 at this super ninja Python/C++ programmer's
|
||||
(David Abrahams) hotel room. Donovan later inflicted this upon the
|
||||
masses in Nevow. Check out the Divmod project page for some
|
||||
examples: <a class="reference" href="http://nevow.com/Nevow2004Tutorial.html">http://nevow.com/Nevow2004Tutorial.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.DateTime - "what time is it anyway?"</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.DateTime - "what time is it anyway?"</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
stringDate = toISOTimestamp(new Date());
|
||||
dateObject = isoTimestamp(stringDate);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>Remote servers don't give you JavaScript Date objects, and they certainly
|
||||
don't want them from you, so you need to deal with string representations
|
||||
of dates and timestamps. MochiKit.Date does that.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<p>None.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-isodate"></a>
|
||||
<a class="mochidef reference" href="#fn-isodate">isoDate(str)</a>:</p>
|
||||
<blockquote>
|
||||
Convert an ISO 8601 date (YYYY-MM-DD) to a <tt class="docutils literal"><span class="pre">Date</span></tt> object.</blockquote>
|
||||
<p>
|
||||
<a name="fn-isotimestamp"></a>
|
||||
<a class="mochidef reference" href="#fn-isotimestamp">isoTimestamp(str)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert any ISO 8601 <a class="footnote-reference" href="#id3" id="id1" name="id1">[1]</a> timestamp (or something reasonably close to it)
|
||||
to a <tt class="docutils literal"><span class="pre">Date</span></tt> object. Will accept the "de facto" form:</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DD hh:mm:ss</blockquote>
|
||||
<p>or (the proper form):</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DDThh:mm:ssZ</blockquote>
|
||||
<p>If a time zone designator ("Z" or "[+-]HH:MM") is not present, then the
|
||||
local timezone is used.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-toisotime"></a>
|
||||
<a class="mochidef reference" href="#fn-toisotime">toISOTime(date)</a>:</p>
|
||||
<blockquote>
|
||||
Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to a string in the form of hh:mm:ss</blockquote>
|
||||
<p>
|
||||
<a name="fn-toisotimestamp"></a>
|
||||
<a class="mochidef reference" href="#fn-toisotimestamp">toISOTimestamp(date, realISO=false)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to something that's ALMOST but not quite an
|
||||
ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be:</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DDThh:mm:ssZ</blockquote>
|
||||
<p>However, we see junk in SQL and other places that looks like this:</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DD hh:mm:ss</blockquote>
|
||||
<p>So, this function returns the latter form, despite its name, unless
|
||||
you pass <tt class="docutils literal"><span class="pre">true</span></tt> for <tt class="docutils literal"><span class="pre">realISO</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-toisodate"></a>
|
||||
<a class="mochidef reference" href="#fn-toisodate">toISODate(date)</a>:</p>
|
||||
<blockquote>
|
||||
Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an ISO 8601 <a class="footnote-reference" href="#id3" id="id2" name="id2">[1]</a> date string (YYYY-MM-DD)</blockquote>
|
||||
<p>
|
||||
<a name="fn-americandate"></a>
|
||||
<a class="mochidef reference" href="#fn-americandate">americanDate(str)</a>:</p>
|
||||
<blockquote>
|
||||
Converts a MM/DD/YYYY date to a <tt class="docutils literal"><span class="pre">Date</span></tt> object</blockquote>
|
||||
<p>
|
||||
<a name="fn-topaddedamericandate"></a>
|
||||
<a class="mochidef reference" href="#fn-topaddedamericandate">toPaddedAmericanDate(date)</a>:</p>
|
||||
<blockquote>
|
||||
Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an MM/DD/YYYY date, e.g. 01/01/2001</blockquote>
|
||||
<p>
|
||||
<a name="fn-toamericandate"></a>
|
||||
<a class="mochidef reference" href="#fn-toamericandate">toAmericanDate(date)</a>:</p>
|
||||
<blockquote>
|
||||
Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an M/D/YYYY date, e.g. 1/1/2001</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id3" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id3">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>)</em> W3C profile of ISO 8601: <a class="reference" href="http://www.w3.org/TR/NOTE-datetime">http://www.w3.org/TR/NOTE-datetime</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,241 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Format - string formatting goes here</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Format - string formatting goes here</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
assert( truncToFixed(0.12345, 4) == "0.1234" );
|
||||
assert( roundToFixed(0.12345, 4) == "0.1235" );
|
||||
assert( twoDigitAverage(1, 0) == "0" );
|
||||
assert( twoDigitFloat(1.2345) == "1.23" );
|
||||
assert( twoDigitFloat(1) == "1" );
|
||||
assert( percentFormat(1.234567) == "123.46%" );
|
||||
assert( numberFormatter("###,###%")(125) == "12,500%" );
|
||||
assert( numberFormatter("##.000")(1.25) == "1.250" );
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>Formatting strings and stringifying numbers is boring, so a couple useful
|
||||
functions in that domain live here.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<p>None.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="formatting-numbers" name="formatting-numbers">Formatting Numbers</a></h2>
|
||||
<p>MochiKit provides an extensible number formatting facility, modeled loosely
|
||||
after the Number Format Pattern Syntax <a class="footnote-reference" href="#id2" id="id1" name="id1">[1]</a> from Java.
|
||||
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(pattern[, placeholder=""[, locale="default"])</a>
|
||||
returns a function that converts Number to string using the given information.
|
||||
<tt class="docutils literal"><span class="pre">pattern</span></tt> is a string consisting of the following symbols:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="85%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th class="head">Symbol</th>
|
||||
<th class="head">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td><tt class="docutils literal"><span class="pre">-</span></tt></td>
|
||||
<td>If given, used as the position of the minus sign
|
||||
for negative numbers. If not given, the position
|
||||
to the left of the first number placeholder is used.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">#</span></tt></td>
|
||||
<td>The placeholder for a number that does not imply zero
|
||||
padding.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">0</span></tt></td>
|
||||
<td>The placeholder for a number that implies zero padding.
|
||||
If it is used to the right of a decimal separator, it
|
||||
implies trailing zeros, otherwise leading zeros.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">,</span></tt></td>
|
||||
<td>The placeholder for a "thousands separator". May be used
|
||||
at most once, and it must be to the left of a decimal
|
||||
separator. Will be replaced by <tt class="docutils literal"><span class="pre">locale.separator</span></tt> in the
|
||||
result (the default is also <tt class="docutils literal"><span class="pre">,</span></tt>).</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">.</span></tt></td>
|
||||
<td>The decimal separator. The quantity of <tt class="docutils literal"><span class="pre">#</span></tt> or <tt class="docutils literal"><span class="pre">0</span></tt>
|
||||
after the decimal separator will determine the precision of
|
||||
the result. If no decimal separator is present, the
|
||||
fractional precision is <tt class="docutils literal"><span class="pre">0</span></tt> -- meaning that it will be
|
||||
rounded to the nearest integer.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">%</span></tt></td>
|
||||
<td>If present, the number will be multiplied by <tt class="docutils literal"><span class="pre">100</span></tt> and
|
||||
the <tt class="docutils literal"><span class="pre">%</span></tt> will be replaced by <tt class="docutils literal"><span class="pre">locale.percent</span></tt>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-formatlocale"></a>
|
||||
<a class="mochidef reference" href="#fn-formatlocale">formatLocale(locale="default")</a>:</p>
|
||||
<blockquote>
|
||||
Return a locale object for the given locale. <tt class="docutils literal"><span class="pre">locale</span></tt> may be either a
|
||||
string, which is looked up in the <tt class="docutils literal"><span class="pre">MochiKit.Format.LOCALE</span></tt> object, or
|
||||
a locale object. If no locale is given, <tt class="docutils literal"><span class="pre">LOCALE.default</span></tt> is used
|
||||
(equivalent to <tt class="docutils literal"><span class="pre">LOCALE.en_US</span></tt>).</blockquote>
|
||||
<p>
|
||||
<a name="fn-lstrip"></a>
|
||||
<a class="mochidef reference" href="#fn-lstrip">lstrip(str, chars="\s")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading whitespace stripped.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
|
||||
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-numberformatter"></a>
|
||||
<a class="mochidef reference" href="#fn-numberformatter">numberFormatter(pattern, placeholder="", locale="default")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a function <tt class="docutils literal"><span class="pre">formatNumber(aNumber)</span></tt> that formats numbers
|
||||
as a string according to the given pattern, placeholder and locale.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">pattern</span></tt> is a string that describes how the numbers should be formatted,
|
||||
for more information see <a class="reference" href="#formatting-numbers">Formatting Numbers</a>.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">locale</span></tt> is a string of a known locale (en_US, de_DE, fr_FR, default) or
|
||||
an object with the following fields:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="16%" />
|
||||
<col width="84%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td>separator</td>
|
||||
<td>The "thousands" separator for this locale (en_US is ",")</td>
|
||||
</tr>
|
||||
<tr><td>decimal</td>
|
||||
<td>The decimal separator for this locale (en_US is ".")</td>
|
||||
</tr>
|
||||
<tr><td>percent</td>
|
||||
<td>The percent symbol for this locale (en_US is "%")</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-percentformat"></a>
|
||||
<a class="mochidef reference" href="#fn-percentformat">percentFormat(someFloat)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf("%.2f%%",</span> <span class="pre">someFloat</span> <span class="pre">*</span> <span class="pre">100)</span></tt></p>
|
||||
<p>In new code, you probably want to use:
|
||||
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter("#.##%")(someFloat)</a> instead.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-roundtofixed"></a>
|
||||
<a class="mochidef reference" href="#fn-roundtofixed">roundToFixed(aNumber, precision)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, rounded to <tt class="docutils literal"><span class="pre">precision</span></tt>
|
||||
digits with trailing zeros. This is similar to
|
||||
<tt class="docutils literal"><span class="pre">Number.toFixed(aNumber,</span> <span class="pre">precision)</span></tt>, but this has implementation
|
||||
consistent rounding behavior (some versions of Safari round 0.5 down!)
|
||||
and also includes preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less than <tt class="docutils literal"><span class="pre">1</span></tt> (Safari,
|
||||
again).</p>
|
||||
<p>For example, <a class="mochiref reference" href="#fn-roundtofixed">roundToFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.14</span></tt> on every
|
||||
supported platform, where some return <tt class="docutils literal"><span class="pre">.13</span></tt> for <tt class="docutils literal"><span class="pre">(0.1357).toFixed(2)</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-rstrip"></a>
|
||||
<a class="mochidef reference" href="#fn-rstrip">rstrip(str, chars="\s")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with trailing whitespace stripped.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
|
||||
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-strip"></a>
|
||||
<a class="mochidef reference" href="#fn-strip">strip(str, chars="\s")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading and trailing whitespace
|
||||
stripped (equivalent to <a class="mochiref reference" href="#fn-lstrip">lstrip(rstrip(str, chars), chars)</a>).</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
|
||||
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-trunctofixed"></a>
|
||||
<a class="mochidef reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, truncated to <tt class="docutils literal"><span class="pre">precision</span></tt>
|
||||
digits with trailing zeros. This is similar to
|
||||
<tt class="docutils literal"><span class="pre">aNumber.toFixed(precision)</span></tt>, but this truncates rather than rounds and
|
||||
has implementation consistent behavior for numbers less than 1.
|
||||
Specifically, <a class="mochiref reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a> will always have a
|
||||
preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less than <tt class="docutils literal"><span class="pre">1</span></tt>.</p>
|
||||
<p>For example, <a class="mochiref reference" href="#fn-tofixed">toFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.13</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-twodigitaverage"></a>
|
||||
<a class="mochidef reference" href="#fn-twodigitaverage">twoDigitAverage(numerator, denominator)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Calculate an average from a numerator and a denominator and return
|
||||
it as a string with two digits of precision (e.g. "1.23").</p>
|
||||
<p>If the denominator is 0, "0" will be returned instead of <tt class="docutils literal"><span class="pre">NaN</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-twodigitfloat"></a>
|
||||
<a class="mochidef reference" href="#fn-twodigitfloat">twoDigitFloat(someFloat)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf("%.2f",</span> <span class="pre">someFloat)</span></tt></p>
|
||||
<p>In new code, you probably want to use
|
||||
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter("#.##")(someFloat)</a> instead.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id2" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id2">[1]</a></td><td>Java Number Format Pattern Syntax:
|
||||
<a class="reference" href="http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html">http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,372 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
theSum = sum(takewhile(
|
||||
partial(operator.gt, 10),
|
||||
imap(
|
||||
partial(operator.mul, 2),
|
||||
count()
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>All of the functional programming missing from <a class="mochiref reference" href="Base.html">MochiKit.Base</a> lives
|
||||
here. The functionality in this module is largely inspired by Python's iteration
|
||||
protocol <a class="footnote-reference" href="#id4" id="id1" name="id1">[1]</a>, and the itertools module <a class="footnote-reference" href="#id5" id="id2" name="id2">[2]</a>.</p>
|
||||
<p>MochiKit.Iter defines a standard way to iterate over anything, that you can
|
||||
extend with <a class="mochiref reference" href="#fn-registeriterator">registerIterator</a>, or by implementing the <tt class="docutils literal"><span class="pre">.iter()</span></tt>
|
||||
protocol. Iterators are lazy, so it can potentially be cheaper to build a
|
||||
filter chain of iterators than to build lots of intermediate arrays.
|
||||
Especially when the data set is very large, but the result is not.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="iteration-for-javascript" name="iteration-for-javascript">Iteration for JavaScript</a></h2>
|
||||
<p>The best overview right now is in my Iteration for JavaScript <a class="footnote-reference" href="#id6" id="id3" name="id3">[3]</a> blog entry.
|
||||
This information will migrate here eventually.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="errors" name="errors">Errors</a></h2>
|
||||
<p>
|
||||
<a name="fn-stopiteration"></a>
|
||||
<a class="mochidef reference" href="#fn-stopiteration">StopIteration</a>:</p>
|
||||
<blockquote>
|
||||
The singleton <a class="mochiref reference" href="Base.html#fn-namederror">MochiKit.Base.NamedError</a> that signifies the end
|
||||
of an iterator</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-applymap"></a>
|
||||
<a class="mochidef reference" href="#fn-applymap">applymap(fun, seq[, self])</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">applymap(fun,</span> <span class="pre">seq)</span></tt> --></dt>
|
||||
<dd>fun.apply(self, seq0), fun.apply(self, seq1), ...</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-chain"></a>
|
||||
<a class="mochidef reference" href="#fn-chain">chain(p, q[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">chain(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --> p0, p1, ... plast, q0, q1, ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-count"></a>
|
||||
<a class="mochidef reference" href="#fn-count">count(n=0)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">count(n=0)</span></tt> --> n, n + 1, n + 2, ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-cycle"></a>
|
||||
<a class="mochidef reference" href="#fn-cycle">cycle(p)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">cycle(p)</span></tt> --> p0, p1, ... plast, p0, p1, ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-dropwhile"></a>
|
||||
<a class="mochidef reference" href="#fn-dropwhile">dropwhile(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">dropwhile(pred,</span> <span class="pre">seq)</span></tt> --> seq[n], seq[n + 1], starting when</dt>
|
||||
<dd>pred(seq[n]) fails</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-every"></a>
|
||||
<a class="mochidef reference" href="#fn-every">every(iterable, func)</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for every item in
|
||||
<tt class="docutils literal"><span class="pre">iterable</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-exhaust"></a>
|
||||
<a class="mochidef reference" href="#fn-exhaust">exhaust(iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Exhausts an iterable without saving the results anywhere,
|
||||
like <a class="mochiref reference" href="#fn-list">list(iterable)</a> when you don't care what the output is.</blockquote>
|
||||
<p>
|
||||
<a name="fn-foreach"></a>
|
||||
<a class="mochidef reference" href="#fn-foreach">forEach(iterable, func[, self])</a>:</p>
|
||||
<blockquote>
|
||||
Call <tt class="docutils literal"><span class="pre">func</span></tt> for each item in <tt class="docutils literal"><span class="pre">iterable</span></tt>, and don't save the results.</blockquote>
|
||||
<p>
|
||||
<a name="fn-groupby"></a>
|
||||
<a class="mochidef reference" href="#fn-groupby">groupby(iterable[, keyfunc])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Make an iterator that returns consecutive keys and groups from the
|
||||
iterable. The key is a function computing a key value for each element.
|
||||
If not specified or is None, key defaults to an identity function and
|
||||
returns the element unchanged. Generally, the iterable needs to already be
|
||||
sorted on the same key function.</p>
|
||||
<p>The returned group is itself an iterator that shares the underlying
|
||||
iterable with <a class="mochiref reference" href="#fn-groupby">groupby()</a>. Because the source is shared, when the
|
||||
groupby object is advanced, the previous group is no longer visible.
|
||||
So, if that data is needed later, it should be stored as an array:</p>
|
||||
<pre class="literal-block">
|
||||
var groups = [];
|
||||
var uniquekeys = [];
|
||||
forEach(groupby(data, keyfunc), function (key_group) {
|
||||
groups.push(list(key_group[1]));
|
||||
uniquekeys.push(key_group[0]);
|
||||
});
|
||||
</pre>
|
||||
<p>As a convenience, <a class="mochiref reference" href="#fn-groupby_as_array">groupby_as_array()</a> is provided to suit the above
|
||||
use case.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-groupby_as_array"></a>
|
||||
<a class="mochidef reference" href="#fn-groupby_as_array">groupby_as_array(iterable[, keyfunc])</a>:</p>
|
||||
<blockquote>
|
||||
Perform the same task as <a class="mochiref reference" href="#fn-groupby">groupby()</a>, except return an array of
|
||||
arrays instead of an iterator of iterators.</blockquote>
|
||||
<p>
|
||||
<a name="fn-iextend"></a>
|
||||
<a class="mochidef reference" href="#fn-iextend">iextend(lst, iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Just like <a class="mochiref reference" href="#fn-list">list(iterable)</a>, except it pushes results on <tt class="docutils literal"><span class="pre">lst</span></tt>
|
||||
rather than creating a new one.</blockquote>
|
||||
<p>
|
||||
<a name="fn-ifilter"></a>
|
||||
<a class="mochidef reference" href="#fn-ifilter">ifilter(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">ifilter(pred,</span> <span class="pre">seq)</span></tt> --> elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt></blockquote>
|
||||
<p>
|
||||
<a name="fn-ifilterfalse"></a>
|
||||
<a class="mochidef reference" href="#fn-ifilterfalse">ifilterfalse(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">ifilterfalse(pred,</span> <span class="pre">seq)</span></tt> --> elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">false</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-imap"></a>
|
||||
<a class="mochidef reference" href="#fn-imap">imap(fun, p, q[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">imap(fun,</span> <span class="pre">p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --> fun(p0, q0, ...), fun(p1, q1, ...), ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-islice"></a>
|
||||
<a class="mochidef reference" href="#fn-islice">islice(seq, [start,] stop[, step])</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">islice(seq,</span> <span class="pre">[start,]</span> <span class="pre">stop[,</span> <span class="pre">step])</span></tt> --> elements from</dt>
|
||||
<dd>seq[start:stop:step] (in Python slice syntax)</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-iter"></a>
|
||||
<a class="mochidef reference" href="#fn-iter">iter(iterable[, sentinel])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert the given argument to an iterator (object implementing
|
||||
<tt class="docutils literal"><span class="pre">.next()</span></tt>).</p>
|
||||
<ol class="arabic simple">
|
||||
<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator (implements <tt class="docutils literal"><span class="pre">.next()</span></tt>), then it will
|
||||
be returned as-is.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator factory (implements <tt class="docutils literal"><span class="pre">.iter()</span></tt>), then
|
||||
the result of <tt class="docutils literal"><span class="pre">iterable.iter()</span></tt> will be returned.</li>
|
||||
<li>Otherwise, the iterator factory <a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a>
|
||||
is used to find a match.</li>
|
||||
<li>If no factory is found, it will throw <tt class="docutils literal"><span class="pre">TypeError</span></tt></li>
|
||||
</ol>
|
||||
<p>Built-in iterator factories are present for Array-like objects, and
|
||||
objects that implement the <tt class="docutils literal"><span class="pre">iterateNext</span></tt> protocol (e.g. the result of
|
||||
Mozilla's <tt class="docutils literal"><span class="pre">document.evaluate</span></tt>).</p>
|
||||
<p>When used directly, using an iterator should look like this:</p>
|
||||
<pre class="literal-block">
|
||||
var it = iter(iterable);
|
||||
try {
|
||||
while (var o = it.next()) {
|
||||
// use o
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
// pass
|
||||
}
|
||||
</pre>
|
||||
<p>This is ugly, so you should use the higher order functions to work
|
||||
with iterators whenever possible.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-izip"></a>
|
||||
<a class="mochidef reference" href="#fn-izip">izip(p, q[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">izip(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --> [p0, q0, ...], [p1, q1, ...], ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-list"></a>
|
||||
<a class="mochidef reference" href="#fn-list">list(iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Convert <tt class="docutils literal"><span class="pre">iterable</span></tt> to a new <tt class="docutils literal"><span class="pre">Array</span></tt></blockquote>
|
||||
<p>
|
||||
<a name="fn-next"></a>
|
||||
<a class="mochidef reference" href="#fn-next">next(iterator)</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">iterator.next()</span></tt></blockquote>
|
||||
<p>
|
||||
<a name="fn-range"></a>
|
||||
<a class="mochidef reference" href="#fn-range">range([start,] stop[, step])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return an iterator containing an arithmetic progression of integers.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">range(i,</span> <span class="pre">j)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([i, i + 1, i + 2, ..., j - 1])</a></p>
|
||||
<p><tt class="docutils literal"><span class="pre">start</span></tt> (!) defaults to <tt class="docutils literal"><span class="pre">0</span></tt>. When <tt class="docutils literal"><span class="pre">step</span></tt> is given, it specifies the
|
||||
increment (or decrement). The end point is omitted!</p>
|
||||
<p>For example, <tt class="docutils literal"><span class="pre">range(4)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([0, 1, 2, 3])</a>.
|
||||
This iterates over exactly the valid indexes for an array of 4 elements.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-reduce"></a>
|
||||
<a class="mochidef reference" href="#fn-reduce">reduce(fn, iterable[, initial])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Apply <tt class="docutils literal"><span class="pre">fn(a,</span> <span class="pre">b)</span></tt> cumulatively to the items of an
|
||||
iterable from left to right, so as to reduce the iterable
|
||||
to a single value.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
reduce(function (a, b) { return x + y; }, [1, 2, 3, 4, 5])
|
||||
</pre>
|
||||
<p>calculates:</p>
|
||||
<pre class="literal-block">
|
||||
((((1 + 2) + 3) + 4) + 5).
|
||||
</pre>
|
||||
<p>If initial is given, it is placed before the items of the sequence
|
||||
in the calculation, and serves as a default when the sequence is
|
||||
empty.</p>
|
||||
<p>Note that the above example could be written more clearly as:</p>
|
||||
<pre class="literal-block">
|
||||
reduce(operator.add, [1, 2, 3, 4, 5])
|
||||
</pre>
|
||||
<p>Or even simpler:</p>
|
||||
<pre class="literal-block">
|
||||
sum([1, 2, 3, 4, 5])
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-registeriteratorfactory"></a>
|
||||
<a class="mochidef reference" href="#fn-registeriteratorfactory">registerIteratorFactory(name, check, iterfactory[, override])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Register an iterator factory for use with the iter function.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">check</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">a</span></tt> can be
|
||||
converted into an iterator with <tt class="docutils literal"><span class="pre">iterfactory</span></tt>.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns an object with a
|
||||
<tt class="docutils literal"><span class="pre">.next()</span></tt> method that returns the next value in the sequence.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is guaranteed to only be called if <tt class="docutils literal"><span class="pre">check(a)</span></tt>
|
||||
returns a true value.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">override</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then it will be made the
|
||||
highest precedence iterator factory. Otherwise, the lowest.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-repeat"></a>
|
||||
<a class="mochidef reference" href="#fn-repeat">repeat(elem[, n])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">repeat(elem,</span> <span class="pre">[,n])</span></tt> --> elem, elem, elem, ... endlessly or up to n times</blockquote>
|
||||
<p>
|
||||
<a name="fn-reversed"></a>
|
||||
<a class="mochidef reference" href="#fn-reversed">reversed(iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Return a reversed array from iterable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-some"></a>
|
||||
<a class="mochidef reference" href="#fn-some">some(iterable, func)</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for at least one item in
|
||||
<tt class="docutils literal"><span class="pre">iterable</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-sorted"></a>
|
||||
<a class="mochidef reference" href="#fn-sorted">sorted(iterable[, cmp])</a>:</p>
|
||||
<blockquote>
|
||||
Return a sorted array from iterable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-sum"></a>
|
||||
<a class="mochidef reference" href="#fn-sum">sum(iterable, start=0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns the sum of a sequence of numbers plus the value
|
||||
of parameter <tt class="docutils literal"><span class="pre">start</span></tt> (with a default of 0). When the sequence is
|
||||
empty, returns start.</p>
|
||||
<p>Equivalent to:</p>
|
||||
<pre class="literal-block">
|
||||
reduce(operator.add, iterable, start);
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-takewhile"></a>
|
||||
<a class="mochidef reference" href="#fn-takewhile">takewhile(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">takewhile(pred,</span> <span class="pre">seq)</span></tt> --> seq[0], seq[1], ... until pred(seq[n]) fails</blockquote>
|
||||
<p>
|
||||
<a name="fn-tee"></a>
|
||||
<a class="mochidef reference" href="#fn-tee">tee(iterable, n=2)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">tee(it,</span> <span class="pre">n=2)</span></tt> --> [it1, it2, it3, ... itn] splits one iterator into n</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id4" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id4">[1]</a></td><td>The iteration protocol is described in
|
||||
PEP 234 - Iterators: <a class="reference" href="http://www.python.org/peps/pep-0234.html">http://www.python.org/peps/pep-0234.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id5" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id5">[2]</a></td><td>Python's itertools
|
||||
module: <a class="reference" href="http://docs.python.org/lib/module-itertools.html">http://docs.python.org/lib/module-itertools.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id3" name="id6">[3]</a></td><td>Iteration in JavaScript: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,310 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Logging - we're all tired of alert()</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Logging - we're all tired of alert()</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
log("INFO messages are so boring");
|
||||
logDebug("DEBUG messages are even worse");
|
||||
log("good thing I can pass", objects, "conveniently");
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Logging steals some ideas from Python's logging module <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a>, but
|
||||
completely forgot about the Java <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> inspiration. This is a KISS module for
|
||||
logging that provides enough flexibility to do just about anything via
|
||||
listeners, but without all the cruft.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="native-console-logging" name="native-console-logging">Native Console Logging</a></h2>
|
||||
<p>As of MochiKit 1.3, the default logger will log all messages to your browser's
|
||||
native console. This is currently supported in Safari, Opera 9, and Firefox
|
||||
when the <a class="reference" href="http://www.joehewitt.com/software/firebug/">FireBug</a> extension is installed.</p>
|
||||
<p>To disable this behavior:</p>
|
||||
<pre class="literal-block">
|
||||
MochiKit.Logging.logger.useNativeLogging = false;
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="bookmarklet-based-debugging" name="bookmarklet-based-debugging">Bookmarklet Based Debugging</a></h2>
|
||||
<p>JavaScript is at a serious disadvantage without a standard console for
|
||||
"print" statements. Everything else has one. The closest thing that
|
||||
you get in a browser environment is the <tt class="docutils literal"><span class="pre">alert</span></tt> function, which is
|
||||
absolutely evil.</p>
|
||||
<p>This leaves you with one reasonable solution: do your logging in the page
|
||||
somehow. The problem here is that you don't want to clutter the page with
|
||||
debugging tools. The solution to that problem is what we call BBD, or
|
||||
Bookmarklet Based Debugging <a class="footnote-reference" href="#id8" id="id4" name="id4">[3]</a>.</p>
|
||||
<p>Simply create a bookmarklet for <a class="reference" href="javascript:MochiKit.Logging.logger.debuggingBookmarklet()">javascript:MochiKit.Logging.logger.debuggingBookmarklet()</a>,
|
||||
and whack it whenever you want to see what's in the logger. Of course, this
|
||||
means you must drink the MochiKit.Logging kool-aid. It's tangy and sweet,
|
||||
don't worry.</p>
|
||||
<p>Currently this is an ugly <tt class="docutils literal"><span class="pre">alert</span></tt>, but we'll have something spiffy
|
||||
Real Soon Now, and when we do, you only have to upgrade MochiKit.Logging,
|
||||
not your bookmarklet!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-logmessage"></a>
|
||||
<a class="mochidef reference" href="#fn-logmessage">LogMessage(num, level, info)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Properties:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
|
||||
<dd>Identifier for the log message</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
|
||||
<dd>Level of the log message (<tt class="docutils literal"><span class="pre">"INFO"</span></tt>, <tt class="docutils literal"><span class="pre">"WARN"</span></tt>, <tt class="docutils literal"><span class="pre">"DEBUG"</span></tt>,
|
||||
etc.)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
|
||||
<dd>All other arguments passed to log function as an <tt class="docutils literal"><span class="pre">Array</span></tt></dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">timestamp</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">Date</span></tt> object timestamping the log message</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger"></a>
|
||||
<a class="mochidef reference" href="#fn-logger">Logger([maxSize])</a>:</p>
|
||||
<blockquote>
|
||||
<p>A basic logger object that has a buffer of recent messages
|
||||
plus a listener dispatch mechanism for "real-time" logging
|
||||
of important messages.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">maxSize</span></tt> is the maximum number of entries in the log.
|
||||
If <tt class="docutils literal"><span class="pre">maxSize</span> <span class="pre">>=</span> <span class="pre">0</span></tt>, then the log will not buffer more than that
|
||||
many messages. So if you don't like logging at all, be sure to
|
||||
pass <tt class="docutils literal"><span class="pre">0</span></tt>.</p>
|
||||
<p>There is a default logger available named "logger", and several
|
||||
of its methods are also global functions:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">logger.log</span></tt> -> <tt class="docutils literal"><span class="pre">log</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.debug</span></tt> -> <tt class="docutils literal"><span class="pre">logDebug</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.warning</span></tt> -> <tt class="docutils literal"><span class="pre">logWarning</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.error</span></tt> -> <tt class="docutils literal"><span class="pre">logError</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.fatal</span></tt> -> <tt class="docutils literal"><span class="pre">logFatal</span></tt></blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.addlistener"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener(ident, filter, listener)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add a listener for log messages.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">ident</span></tt> is a unique identifier that may be used to remove the listener
|
||||
later on.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">filter</span></tt> can be one of the following:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">null</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called for every log message
|
||||
received.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">string</span></tt>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-loglevelatleast">logLevelAtLeast(filter)</a> will be used as the function
|
||||
(see below).</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">function</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">filter(msg)</span></tt> will be called for every msg, if it returns
|
||||
true then <tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p><tt class="docutils literal"><span class="pre">listener</span></tt> is a function that takes one argument, a log message. A log
|
||||
message is an object (<a class="mochiref reference" href="#fn-logmessage">LogMessage</a> instance) that has at least these
|
||||
properties:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
|
||||
<dd>A counter that uniquely identifies a log message (per-logger)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
|
||||
<dd>A string or number representing the log level. If string, you
|
||||
may want to use <tt class="docutils literal"><span class="pre">LogLevel[level]</span></tt> for comparison.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
|
||||
<dd>An Array of objects passed as additional arguments to the <tt class="docutils literal"><span class="pre">log</span></tt>
|
||||
function.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.baselog"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.baselog">Logger.prototype.baseLog(level, message[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>The base functionality behind all of the log functions.
|
||||
The first argument is the log level as a string or number,
|
||||
and all other arguments are used as the info list.</p>
|
||||
<p>This function is available partially applied as:</p>
|
||||
<blockquote>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="61%" />
|
||||
<col width="39%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td>Logger.debug</td>
|
||||
<td>'DEBUG'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.log</td>
|
||||
<td>'INFO'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.error</td>
|
||||
<td>'ERROR'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.fatal</td>
|
||||
<td>'FATAL'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.warning</td>
|
||||
<td>'WARNING'</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>For the default logger, these are also available as global functions,
|
||||
see the <a class="mochiref reference" href="#fn-logger">Logger</a> constructor documentation for more info.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.clear"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.clear">Logger.prototype.clear()</a>:</p>
|
||||
<blockquote>
|
||||
Clear all messages from the message buffer.</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.debuggingbookmarklet"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.debuggingbookmarklet">Logger.prototype.debuggingBookmarklet()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Display the contents of the logger in a useful way for browsers.</p>
|
||||
<p>Currently, if <a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> is loaded, then a pop-up
|
||||
<a class="mochiref reference" href="LoggingPane.html#fn-loggingpane">MochiKit.LoggingPane.LoggingPane</a> will be used. Otherwise,
|
||||
it will be an alert with <a class="mochiref reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText()</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.dispatchlisteners"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.dispatchlisteners">Logger.prototype.dispatchListeners(msg)</a>:</p>
|
||||
<blockquote>
|
||||
Dispatch a log message to all listeners.</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.getmessages"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages(howMany)</a>:</p>
|
||||
<blockquote>
|
||||
Return a list of up to <tt class="docutils literal"><span class="pre">howMany</span></tt> messages from the message buffer.</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.getmessagetext"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText(howMany)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Get a string representing up to the last <tt class="docutils literal"><span class="pre">howMany</span></tt> messages in the
|
||||
message buffer. The default is <tt class="docutils literal"><span class="pre">30</span></tt>.</p>
|
||||
<p>The message looks like this:</p>
|
||||
<pre class="literal-block">
|
||||
LAST {messages.length} MESSAGES:
|
||||
[{msg.num}] {msg.level}: {m.info.join(' ')}
|
||||
[{msg.num}] {msg.level}: {m.info.join(' ')}
|
||||
...
|
||||
</pre>
|
||||
<p>If you want some other format, use
|
||||
<a class="mochiref reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages</a> and do it yourself.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.removelistener"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.removelistener">Logger.prototype.removeListener(ident)</a>:</p>
|
||||
<blockquote>
|
||||
Remove a listener using the ident given to <a class="mochiref reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener</a></blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-alertlistener"></a>
|
||||
<a class="mochidef reference" href="#fn-alertlistener">alertListener(msg)</a>:</p>
|
||||
<blockquote>
|
||||
Ultra-obnoxious <tt class="docutils literal"><span class="pre">alert(...)</span></tt> listener</blockquote>
|
||||
<p>
|
||||
<a name="fn-logdebug"></a>
|
||||
<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log an INFO message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-logdebug"></a>
|
||||
<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log a DEBUG message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-logerror"></a>
|
||||
<a class="mochidef reference" href="#fn-logerror">logError(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log an ERROR message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-logfatal"></a>
|
||||
<a class="mochidef reference" href="#fn-logfatal">logFatal(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log a FATAL message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-loglevelatleast"></a>
|
||||
<a class="mochidef reference" href="#fn-loglevelatleast">logLevelAtLeast(minLevel)</a>:</p>
|
||||
<blockquote>
|
||||
Return a function that will match log messages whose level
|
||||
is at least minLevel</blockquote>
|
||||
<p>
|
||||
<a name="fn-logwarning"></a>
|
||||
<a class="mochidef reference" href="#fn-logwarning">logWarning(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log a WARNING message to the default logger</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Python's logging module: <a class="reference" href="http://docs.python.org/lib/module-logging.html">http://docs.python.org/lib/module-logging.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id7">[2]</a></td><td>PEP 282, where they admit all of the Java influence: <a class="reference" href="http://www.python.org/peps/pep-0282.html">http://www.python.org/peps/pep-0282.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id8" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id4" name="id8">[3]</a></td><td>Original Bookmarklet Based Debugging blather: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/">http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,121 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
// open a pop-up window
|
||||
createLoggingPane()
|
||||
// use a div at the bottom of the document
|
||||
createLoggingPane(true);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Logging does not have any browser dependencies and is completely
|
||||
unobtrusive. MochiKit.LoggingPane is a browser-based colored viewing pane
|
||||
for your <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> output that can be used as a pop-up or
|
||||
inline.</p>
|
||||
<p>It also allows for regex and level filtering! MochiKit.LoggingPane is used
|
||||
as the default <a class="mochiref reference" href="Logging.html#fn-debuggingbookmarklet">MochiKit.Logging.debuggingBookmarklet()</a> if it is
|
||||
loaded.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-loggingpane"></a>
|
||||
<a class="mochidef reference" href="#fn-loggingpane">LoggingPane(inline=false, logger=MochiKit.Logging.logger)</a>:</p>
|
||||
<blockquote>
|
||||
<p>A listener for a <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> logger with an interactive
|
||||
DOM representation.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">inline</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> will be a <tt class="docutils literal"><span class="pre">DIV</span></tt>
|
||||
at the bottom of the document. Otherwise, it will be in a pop-up
|
||||
window with a name based on the calling page's URL. If there is an
|
||||
element in the document with an id of <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt>,
|
||||
it will be used instead of appending a new <tt class="docutils literal"><span class="pre">DIV</span></tt> to the body.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">logger</span></tt> is the reference to the <a class="mochiref reference" href="Logging.html#fn-logger">MochiKit.Logging.Logger</a> to
|
||||
listen to. If not specified, the global default logger is used.</p>
|
||||
<p>Properties:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">win</span></tt>:</dt>
|
||||
<dd>Reference to the pop-up window (<tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">inline</span></tt>)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">inline</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">true</span></tt> if the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> is inline</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">colorTable</span></tt>:</dt>
|
||||
<dd><p class="first">An object with property->value mappings for each log level
|
||||
and its color. May also be mutated on <tt class="docutils literal"><span class="pre">LoggingPane.prototype</span></tt>
|
||||
to affect all instances. For example:</p>
|
||||
<pre class="last literal-block">
|
||||
MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
|
||||
DEBUG: "green",
|
||||
INFO: "black",
|
||||
WARNING: "blue",
|
||||
ERROR: "red",
|
||||
FATAL: "darkred"
|
||||
};
|
||||
</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-loggingpane.prototype.closepane"></a>
|
||||
<a class="mochidef reference" href="#fn-loggingpane.prototype.closepane">LoggingPane.prototype.closePane()</a>:</p>
|
||||
<blockquote>
|
||||
Close the <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> (close the child window, or
|
||||
remove the <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> <tt class="docutils literal"><span class="pre">DIV</span></tt> from the document).</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-createloggingpane"></a>
|
||||
<a class="mochidef reference" href="#fn-createloggingpane">createLoggingPane(inline=false)</a>:</p>
|
||||
<blockquote>
|
||||
Create or return an existing <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> for this document
|
||||
with the given inline setting. This is preferred over using
|
||||
<a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> directly, as only one <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a>
|
||||
should be present in a given document.</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,331 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Signal - Simple universal event handling</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Signal - Simple universal event handling</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<p>Signal for DOM events:</p>
|
||||
<pre class="literal-block">
|
||||
// DOM events are also signals. Connect freely! The functions will be
|
||||
// called with the custom event as a parameter.
|
||||
|
||||
// calls myClicked.apply(getElement('myID'), event)
|
||||
connect('myID', 'onclick', myClicked);
|
||||
|
||||
// calls wasClicked.apply(myObject, event)
|
||||
connect('myID', 'onclick', myObject, wasClicked);
|
||||
|
||||
// calls myObject.wasClicked(event)
|
||||
connect('myID', 'onclick', myObject, 'wasClicked');
|
||||
|
||||
// the event is normalized, no more e = e || window.event!
|
||||
myObject.wasClicked = function(e) {
|
||||
var crossBrowserCoordinates = e.mouse().page;
|
||||
// e.mouse().page is a MochiKit.DOM.Coordinates object
|
||||
}
|
||||
</pre>
|
||||
<p>Signal for non-DOM events:</p>
|
||||
<pre class="literal-block">
|
||||
// otherObject.gotFlash() will be called when 'flash' signalled.
|
||||
connect(myObject, 'flash', otherObject, 'gotFlash');
|
||||
|
||||
// gotBang.apply(otherObject) will be called when 'bang' signalled.
|
||||
// You can access otherObject from within gotBang as 'this'.
|
||||
connect(myObject, 'bang', otherObject, gotBang);
|
||||
|
||||
// myFunc.apply(myObject) will be called when 'flash' signalled.
|
||||
// You can access myObject from within myFunc as 'this'.
|
||||
var ident = connect(myObject, 'flash', myFunc);
|
||||
|
||||
// You may disconnect with the return value from connect
|
||||
disconnect(ident);
|
||||
|
||||
// Signal can take parameters. These will be passed along to the connected
|
||||
// functions.
|
||||
signal(myObject, 'flash');
|
||||
signal(myObject, 'bang', 'BANG!');
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>Event handling was never so easy!</p>
|
||||
<p>This module takes care of all the hard work—figuring out which event
|
||||
model to use, trying to retrieve the event object, and handling your own
|
||||
internal events, as well as cleanup when the page is unloaded to clean up IE's
|
||||
nasty memory leakage.</p>
|
||||
<p>This event system is largely based on Qt's signal/slot system. Read more on
|
||||
how that is handled and also how it is used in model/view programming at:
|
||||
<a class="reference" href="http://doc.trolltech.com/">http://doc.trolltech.com/</a></p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="using-signal-for-dom-events" name="using-signal-for-dom-events">Using Signal for DOM Events</a></h2>
|
||||
<p>When using MochiKit.Signal, do not use the browser's native event API. That
|
||||
means, no <tt class="docutils literal"><span class="pre">onclick="blah"</span></tt>, no <tt class="docutils literal"><span class="pre">elem.addEventListener(...)</span></tt>, and certainly
|
||||
no <tt class="docutils literal"><span class="pre">elem.attachEvent(...)</span></tt>. This also means that
|
||||
<a class="mochiref reference" href="DOM.html#fn-addtocallstack">MochiKit.DOM.addToCallStack</a> and
|
||||
<a class="mochiref reference" href="DOM.html#fn-addloadevent">MochiKit.DOM.addLoadEvent</a> should not be used in combination with
|
||||
this module.</p>
|
||||
<p>Signals for DOM objects are named with the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix, e.g.:
|
||||
<tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>, etc.</p>
|
||||
<p>When the signal fires, your slot will be called with one parameter, the custom
|
||||
event object.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="custom-event-objects-for-dom-events" name="custom-event-objects-for-dom-events">Custom Event Objects for DOM events</a></h2>
|
||||
<p>Signals triggered by DOM events are called with a custom event object as a
|
||||
parameter. The custom event object presents a consistent view of the event
|
||||
across all supported platforms and browsers, and provides many conveniences
|
||||
not available even in a correct W3C implementation.</p>
|
||||
<p>See the <a class="reference" href="#dom-custom-event-object-reference">DOM Custom Event Object Reference</a> for a detailed API description
|
||||
of this object.</p>
|
||||
<p>If you find that you're accessing the native event for any reason, create a
|
||||
<a class="reference" href="http://trac.mochikit.com/newticket">new ticket</a> and we'll look into normalizing the behavior you're looking for.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="memory-usage" name="memory-usage">Memory Usage</a></h2>
|
||||
<p>Any object that has connected slots (via <a class="mochiref reference" href="#fn-connect">connect()</a>) is referenced
|
||||
by the Signal mechanism until it is disconnected via <a class="mochiref reference" href="#fn-disconnect">disconnect()</a>
|
||||
or <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>.</p>
|
||||
<p>Signal does not leak. It registers an <tt class="docutils literal"><span class="pre">'onunload'</span></tt> event that disconnects all
|
||||
objects on the page when the browser leaves the page. However, memory usage
|
||||
will grow during the page view for every connection made until it is
|
||||
disconnected. Even if the DOM object is removed from the document, it
|
||||
will still be referenced by Signal until it is explicitly disconnected.</p>
|
||||
<p>In order to conserve memory during the page view, <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>
|
||||
any DOM elements that are about to be removed from the document.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="using-signal-for-non-dom-objects" name="using-signal-for-non-dom-objects">Using Signal for non-DOM objects</a></h2>
|
||||
<p>Signals are triggered with the <a class="mochiref reference" href="#fn-signal">signal(src, 'signal', ...)</a>
|
||||
function. Additional parameters passed to this are passed onto the
|
||||
connected slots. Explicit signals are not required for DOM events.</p>
|
||||
<p>Slots that are connected to a signal are called in the following manner
|
||||
when that signal is signalled:</p>
|
||||
<ul class="simple">
|
||||
<li>If the slot was a single function, then it is called with <tt class="docutils literal"><span class="pre">this</span></tt> set
|
||||
to the object originating the signal with whatever parameters it was
|
||||
signalled with.</li>
|
||||
<li>If the slot was an object and a function, then it is called with
|
||||
<tt class="docutils literal"><span class="pre">this</span></tt> set to the object, and with whatever parameters it was
|
||||
signalled with.</li>
|
||||
<li>If the slot was an object and a string, then <tt class="docutils literal"><span class="pre">object[string]</span></tt> is
|
||||
called with the parameters to the signal.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="signal-api-reference" name="signal-api-reference">Signal API Reference</a></h2>
|
||||
<p>
|
||||
<a name="fn-connect"></a>
|
||||
<a class="mochidef reference" href="#fn-connect">connect(src, signal, dest[, func])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Connects a signal to a slot, and return a unique identifier that can be
|
||||
used to disconnect that signal.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">src</span></tt> is the object that has the signal. You may pass in a string, in
|
||||
which case, it is interpreted as an id for an HTML element.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">signal</span></tt> is a string that represents a signal name. If 'src' is an HTML
|
||||
Element, <tt class="docutils literal"><span class="pre">window</span></tt>, or the <tt class="docutils literal"><span class="pre">document</span></tt>, then it can be one of the
|
||||
'on-XYZ' events. You must include the 'on' prefix, and it must be all
|
||||
lower-case.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">dest</span></tt> and <tt class="docutils literal"><span class="pre">func</span></tt> describe the slot, or the action to take when the
|
||||
signal is triggered.</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a string, then
|
||||
<tt class="docutils literal"><span class="pre">dest[func].apply(dest,</span> <span class="pre">...)</span></tt> will be called when the signal
|
||||
is signalled.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a function, then
|
||||
<tt class="docutils literal"><span class="pre">func.apply(dest,</span> <span class="pre">...)</span></tt> will be called when the signal is
|
||||
signalled.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">func</span></tt> is undefined and <tt class="docutils literal"><span class="pre">dest</span></tt> is a function, then
|
||||
<tt class="docutils literal"><span class="pre">func.apply(src,</span> <span class="pre">...)</span></tt> will be called when the signal is
|
||||
signalled.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>No other combinations are allowed and will raise an exception.</p>
|
||||
<p>The return value can be passed to <a class="mochiref reference" href="#fn-disconnect">disconnect</a> to disconnect
|
||||
the signal.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-disconnect"></a>
|
||||
<a class="mochidef reference" href="#fn-disconnect">disconnect(ident)</a>:</p>
|
||||
<blockquote>
|
||||
To disconnect a signal, pass its ident returned by <a class="mochiref reference" href="#fn-connect">connect()</a>.
|
||||
This is similar to how the browser's <tt class="docutils literal"><span class="pre">setTimeout</span></tt> and <tt class="docutils literal"><span class="pre">clearTimeout</span></tt>
|
||||
works.</blockquote>
|
||||
<p>
|
||||
<a name="fn-disconnectall"></a>
|
||||
<a class="mochidef reference" href="#fn-disconnectall">disconnectAll(src[, signal, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p><tt class="docutils literal"><span class="pre">disconnectAll(src)</span></tt> removes all signals from src.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">disconnectAll(src,</span> <span class="pre">'onmousedown',</span> <span class="pre">'mySignal')</span></tt> will remove all
|
||||
<tt class="docutils literal"><span class="pre">'onmousedown'</span></tt> and <tt class="docutils literal"><span class="pre">'mySignal'</span></tt> signals from src.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-signal"></a>
|
||||
<a class="mochidef reference" href="#fn-signal">signal(src, signal, ...)</a>:</p>
|
||||
<blockquote>
|
||||
This will signal a signal, passing whatever additional parameters on to
|
||||
the connected slots. <tt class="docutils literal"><span class="pre">src</span></tt> and <tt class="docutils literal"><span class="pre">signal</span></tt> are the same as for
|
||||
<a class="mochiref reference" href="#fn-connect">connect()</a>.</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="dom-custom-event-object-reference" name="dom-custom-event-object-reference">DOM Custom Event Object Reference</a></h2>
|
||||
<p>
|
||||
<a name="fn-event"></a>
|
||||
<a class="mochidef reference" href="#fn-event">event()</a>:</p>
|
||||
<blockquote>
|
||||
The native event produced by the browser. You should not need to use this.</blockquote>
|
||||
<p>
|
||||
<a name="fn-src"></a>
|
||||
<a class="mochidef reference" href="#fn-src">src()</a>:</p>
|
||||
<blockquote>
|
||||
The element that this signal is connected to.</blockquote>
|
||||
<p>
|
||||
<a name="fn-type"></a>
|
||||
<a class="mochidef reference" href="#fn-type">type()</a>:</p>
|
||||
<blockquote>
|
||||
The event type (<tt class="docutils literal"><span class="pre">'click'</span></tt>, <tt class="docutils literal"><span class="pre">'mouseover'</span></tt>, <tt class="docutils literal"><span class="pre">'keypress'</span></tt>, etc.) as a
|
||||
string. Does not include the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix.</blockquote>
|
||||
<p>
|
||||
<a name="fn-target"></a>
|
||||
<a class="mochidef reference" href="#fn-target">target()</a>:</p>
|
||||
<blockquote>
|
||||
The element that triggered the event. This may be a child of
|
||||
<a class="mochiref reference" href="#fn-src">src()</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-modifier"></a>
|
||||
<a class="mochidef reference" href="#fn-modifier">modifier()</a>:</p>
|
||||
<blockquote>
|
||||
Returns <tt class="docutils literal"><span class="pre">{shift,</span> <span class="pre">ctrl,</span> <span class="pre">meta,</span> <span class="pre">alt,</span> <span class="pre">any}</span></tt>, where each property is <tt class="docutils literal"><span class="pre">true</span></tt>
|
||||
if its respective modifier key was pressed, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. <tt class="docutils literal"><span class="pre">any</span></tt>
|
||||
is <tt class="docutils literal"><span class="pre">true</span></tt> if any modifier is pressed, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise.</blockquote>
|
||||
<p>
|
||||
<a name="fn-stoppropagation"></a>
|
||||
<a class="mochidef reference" href="#fn-stoppropagation">stopPropagation()</a>:</p>
|
||||
<blockquote>
|
||||
Works like W3C's <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-preventdefault"></a>
|
||||
<a class="mochidef reference" href="#fn-preventdefault">preventDefault()</a>:</p>
|
||||
<blockquote>
|
||||
Works like W3C's <tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-stop"></a>
|
||||
<a class="mochidef reference" href="#fn-stop">stop()</a>:</p>
|
||||
<blockquote>
|
||||
Shortcut that calls <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt> and <tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-key"></a>
|
||||
<a class="mochidef reference" href="#fn-key">key()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns <tt class="docutils literal"><span class="pre">{code,</span> <span class="pre">string}</span></tt>.</p>
|
||||
<p>Use <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> handlers to detect control
|
||||
characters such as <tt class="docutils literal"><span class="pre">'KEY_F1'</span></tt>. Use the <tt class="docutils literal"><span class="pre">'onkeypressed'</span></tt> handler to
|
||||
detect "printable" characters, such as <tt class="docutils literal"><span class="pre">'é'</span></tt>.</p>
|
||||
<p>When a user presses F1, in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> this method
|
||||
returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">122,</span> <span class="pre">string:</span> <span class="pre">'KEY_F1'}</span></tt>. In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns
|
||||
<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">0,</span> <span class="pre">string:</span> <span class="pre">''}</span></tt>.</p>
|
||||
<p>If a user presses Shift+2 on a US keyboard, this method returns
|
||||
<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">50,</span> <span class="pre">string:</span> <span class="pre">'KEY_2'}</span></tt> in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>.
|
||||
In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">64,</span> <span class="pre">string:</span> <span class="pre">'@'}</span></tt>.</p>
|
||||
<p>See <tt class="docutils literal"><span class="pre">_specialKeys</span></tt> in the source code for a comprehensive list of
|
||||
control characters.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-mouse"></a>
|
||||
<a class="mochidef reference" href="#fn-mouse">mouse()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Properties for <tt class="docutils literal"><span class="pre">'onmouse*'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>, and
|
||||
<tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">page</span></tt> is a <a class="mochiref reference" href="DOM.html#fn-coordinates">MochiKit.DOM.Coordinates</a> object that
|
||||
represents the cursor position relative to the HTML document.
|
||||
Equivalent to <tt class="docutils literal"><span class="pre">pageX</span></tt> and <tt class="docutils literal"><span class="pre">pageY</span></tt> in Safari, Mozilla, and
|
||||
Opera.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">client</span></tt> is a <a class="mochiref reference" href="DOM.html#fn-coordinates">MochiKit.DOM.Coordinates</a> object that
|
||||
represents the cursor position relative to the visible portion of
|
||||
the HTML document. Equivalent to <tt class="docutils literal"><span class="pre">clientX</span></tt> and <tt class="docutils literal"><span class="pre">clientY</span></tt> on
|
||||
all browsers.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Properties for <tt class="docutils literal"><span class="pre">'onmouseup'</span></tt>, <tt class="docutils literal"><span class="pre">'onmousedown'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, and
|
||||
<tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">mouse().button</span></tt> returns <tt class="docutils literal"><span class="pre">{left,</span> <span class="pre">right,</span> <span class="pre">middle}</span></tt> where each
|
||||
property is <tt class="docutils literal"><span class="pre">true</span></tt> if the mouse button was pressed, <tt class="docutils literal"><span class="pre">false</span></tt>
|
||||
otherwise.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Known browser bugs:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><p class="first">Current versions of Safari won't signal <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt> when
|
||||
attached via <tt class="docutils literal"><span class="pre">connect()</span></tt> (<a class="reference" href="http://bugzilla.opendarwin.org/show_bug.cgi?id=7790">Safari Bug 7790</a>).</p>
|
||||
</li>
|
||||
<li><p class="first">Mac browsers don't report right-click consistently. Firefox
|
||||
signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().ctrl</span></tt> to true, Opera
|
||||
signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().meta</span></tt> to <tt class="docutils literal"><span class="pre">true</span></tt>, and
|
||||
Safari doesn't signal the slot at all (<a class="reference" href="http://bugzilla.opendarwin.org/show_bug.cgi?id=6595">Safari Bug 6595</a>).</p>
|
||||
<p>To find a right-click in Safari, Firefox, and IE, you can connect
|
||||
an element to <tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>. This doesn't work in Opera.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-relatedtarget"></a>
|
||||
<a class="mochidef reference" href="#fn-relatedtarget">relatedTarget()</a>:</p>
|
||||
<blockquote>
|
||||
Returns the document element that the mouse has moved to. This is
|
||||
generated for <tt class="docutils literal"><span class="pre">'onmouseover'</span></tt> and <tt class="docutils literal"><span class="pre">'onmouseout'</span></tt> events.</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Jonathan Gardner <<a class="reference" href="mailto:jgardner@jonathangardner.net">jgardner@jonathangardner.net</a>></li>
|
||||
<li>Beau Hartshorne <<a class="reference" href="mailto:beau@hartshornesoftware.com">beau@hartshornesoftware.com</a>></li>
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2006 Jonathan Gardner <<a class="reference" href="mailto:jgardner@jonathangardner.net">jgardner@jonathangardner.net</a>>, Beau
|
||||
Hartshorne <<a class="reference" href="mailto:beau@hartshornesoftware.com">beau@hartshornesoftware.com</a>>, and Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>.
|
||||
This program is dual-licensed free software; you can redistribute it and/or
|
||||
modify it under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,264 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title></title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<p>2006-04-29 v1.3.1 (bug fix release)</p>
|
||||
<ul class="simple">
|
||||
<li>Fix sendXMLHttpRequest sendContent regression</li>
|
||||
<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
|
||||
<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
|
||||
</ul>
|
||||
<p>2006-04-26 v1.3 "warp zone"</p>
|
||||
<ul class="simple">
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
|
||||
<li>New MochiKit.Base.method as a convenience form of bind that takes the
|
||||
object before the method</li>
|
||||
<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
|
||||
a single Array</li>
|
||||
<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
|
||||
<li>New key_events example demonstrating use of MochiKit.Signal's key handling
|
||||
capabilities.</li>
|
||||
<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
|
||||
null is used and the string will be considered the first node. This
|
||||
allows for the more natural P("foo") rather than P(null, "foo").</li>
|
||||
<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
|
||||
provides multi-line input and a help() function to get MochiKit function
|
||||
signature from the documentation.</li>
|
||||
<li>Native Console Logging for the default MochiKit.Logging logger</li>
|
||||
<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
|
||||
<li>New MochiKit.Signal example: draggable</li>
|
||||
<li>Added sanity checking to Deferred to ensure that errors happen when chaining
|
||||
is used incorrectly</li>
|
||||
<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
|
||||
<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
|
||||
component values smaller than 16/255.</li>
|
||||
<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
|
||||
maximum size</li>
|
||||
<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
|
||||
Error, so that the errback chain is used instead of the callback chain.</li>
|
||||
<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
|
||||
in the correct order.</li>
|
||||
<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
|
||||
<li>MochiKit.Base.isNull no longer matches undefined</li>
|
||||
<li>example doctypes changed to HTML4</li>
|
||||
<li>isDateLike no longer throws error on null</li>
|
||||
<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
|
||||
<li>updated elementDimensions to calculate width from offsetWidth instead
|
||||
of clientWidth</li>
|
||||
<li>formContents now works with FORM tags that have a name attribute</li>
|
||||
<li>Documentation now uses MochiKit to generate a function index</li>
|
||||
</ul>
|
||||
<p>2006-01-26 v1.2 "the ocho"</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
|
||||
<li>Added new MochiKit.Base.findIdentical function to find the index of an
|
||||
element in an Array-like object. Uses === for identity comparison.</li>
|
||||
<li>Added new MochiKit.Base.find function to find the index of an element in
|
||||
an Array-like object. Uses compare for rich comparison.</li>
|
||||
<li>MochiKit.Base.bind will accept a string for func, which will be immediately
|
||||
looked up as self[func].</li>
|
||||
<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
|
||||
compatibility</li>
|
||||
<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
|
||||
<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
|
||||
height of an element in the document</li>
|
||||
<li>MochiKit.DOM's initialization is now compatible with
|
||||
HTMLUnit + JWebUnit + Rhino</li>
|
||||
<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
|
||||
currently in the document instead of always creating one.</li>
|
||||
<li>MochiKit.Base now has operator.mul</li>
|
||||
<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
|
||||
a custom value attribute</li>
|
||||
<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
|
||||
<li>MochiKit.DOM.setNodeAttribute should work now</li>
|
||||
<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
|
||||
property to a string</li>
|
||||
<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
|
||||
name and for properties</li>
|
||||
<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
|
||||
<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
|
||||
<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
|
||||
<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
|
||||
<li>Added new MochiKit.DOM documentation on element visibility</li>
|
||||
<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
|
||||
for determining the position of an element in the document</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
|
||||
</ul>
|
||||
<p>2005-11-14 v1.1</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed a bug in numberFormatter with large numbers</li>
|
||||
<li>Massively overhauled documentation</li>
|
||||
<li>Fast-path for primitives in MochiKit.Base.compare</li>
|
||||
<li>New groupby and groupby_as_array in MochiKit.Iter</li>
|
||||
<li>Added iterator factory adapter for objects that implement iterateNext()</li>
|
||||
<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
|
||||
LEGEND, FIELDSET</li>
|
||||
<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
|
||||
<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
|
||||
<li>MochiKit.LoggingPane now uses named windows based on the URL so that
|
||||
a given URL will get the same LoggingPane window after a reload
|
||||
(at the same position, etc.)</li>
|
||||
<li>MochiKit.DOM now has currentWindow() and currentDocument() context
|
||||
variables that are set with withWindow() and withDocument(). These
|
||||
context variables affect all MochiKit.DOM functionality (getElement,
|
||||
createDOM, etc.)</li>
|
||||
<li>MochiKit.Base.items will now catch and ignore exceptions for properties
|
||||
that are enumerable but not accessible (e.g. permission denied)</li>
|
||||
<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
|
||||
now accept additional arguments that are used to create a partially
|
||||
applied function. This differs from Twisted in that the callback/errback
|
||||
result becomes the <em>last</em> argument, not the first when this feature
|
||||
is used.</li>
|
||||
<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
|
||||
arguments which are used to create a GET query string</li>
|
||||
<li>Did some refactoring to reduce the footprint of MochiKit by a few
|
||||
kilobytes</li>
|
||||
<li>escapeHTML to longer escapes ' (apos) and now uses
|
||||
String.replace instead of iterating over every char.</li>
|
||||
<li>Added DeferredLock to Async</li>
|
||||
<li>Renamed getElementsComputedStyle to computedStyle and moved
|
||||
it from MochiKit.Visual to MochiKit.DOM</li>
|
||||
<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
|
||||
<li>Fixed range() to accept a negative step</li>
|
||||
<li>New alias to MochiKit.swapDOM called removeElement</li>
|
||||
<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
|
||||
an attribute on a node without raising, roughly equivalent to:
|
||||
updateNodeAttributes(node, {attr: value})</li>
|
||||
<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
|
||||
a node's attribute or returns null without raising</li>
|
||||
<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
|
||||
directly (addLoadEvent did not leak, since it clears the handler)</li>
|
||||
</ul>
|
||||
<p>2005-10-24 v1.0</p>
|
||||
<ul class="simple">
|
||||
<li>New interpreter example that shows usage of MochiKit.DOM to make
|
||||
an interactive JavaScript interpreter</li>
|
||||
<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
|
||||
debuggingBookmarklet, with logging_pane example to show its usage</li>
|
||||
<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
|
||||
in order to provide a live regular expression matching tool</li>
|
||||
<li>Added advanced number formatting capabilities to MochiKit.Format:
|
||||
numberFormatter(pattern, placeholder="", locale="default") and
|
||||
formatLocale(locale="default")</li>
|
||||
<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
|
||||
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
|
||||
<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
|
||||
to MochiKit.Format</li>
|
||||
<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
|
||||
isoTimestamp(isoString) will convert them to Date objects, and
|
||||
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
|
||||
<li>Fixed missing errback for sendXMLHttpRequest when the server does not
|
||||
respond</li>
|
||||
<li>Fixed infinite recusion bug when using roundClass("DIV", ...)</li>
|
||||
<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
|
||||
from being cancelled properly</li>
|
||||
<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
|
||||
have an apply method, such as alert</li>
|
||||
<li>Reliably return null from the string parsing/manipulation functions if
|
||||
the input can't be coerced to a string (s + "") or the input makes no sense;
|
||||
e.g. isoTimestamp(null) and isoTimestamp("") return null</li>
|
||||
</ul>
|
||||
<p>2005-10-08 v0.90</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed ISO compliance with toISODate</li>
|
||||
<li>Added missing operator.sub</li>
|
||||
<li>Placated Mozilla's strict warnings a bit</li>
|
||||
<li>Added JSON serialization and unserialization support to MochiKit.Base:
|
||||
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
|
||||
API.</li>
|
||||
<li>Fixed a bug in the script loader that failed in some scenarios when a script
|
||||
tag did not have a "src" attribute (thanks Ian!)</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
|
||||
P, FORM</li>
|
||||
<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
|
||||
and parseQueryString, when available.</li>
|
||||
</ul>
|
||||
<p>2005-08-12 v0.80</p>
|
||||
<ul class="simple">
|
||||
<li>Source highlighting in all examples, moved to a view-source example</li>
|
||||
<li>Added some experimental syntax highlighting for the Rounded Corners example,
|
||||
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
|
||||
<li>Use an indirect binding for the logger conveniences, so that the global
|
||||
logger could be replaced by setting MochiKit.Logger.logger to something else
|
||||
(though an observer is probably a better choice).</li>
|
||||
<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
|
||||
which will be looked up with getElement</li>
|
||||
<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
|
||||
node.parentNode)</li>
|
||||
<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
|
||||
<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
|
||||
<li>Possible workaround for Safari issue with swapDOM, where it would get
|
||||
confused because two elements were in the DOM at the same time with the
|
||||
same id</li>
|
||||
<li>Added missing THEAD convenience function to MochiKit.DOM</li>
|
||||
<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
|
||||
<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
|
||||
MochiKit.DOM</li>
|
||||
<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
|
||||
<li>Added HSV color space support to MochiKit.Visual</li>
|
||||
<li>Fixed a bug in the sortable_tables example, it now converts types
|
||||
correctly</li>
|
||||
<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
|
||||
scope</li>
|
||||
</ul>
|
||||
<p>2005-08-04 v0.70</p>
|
||||
<ul class="simple">
|
||||
<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
|
||||
a little TAL-ish DOM templating attribute language.</li>
|
||||
<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
|
||||
ignore requests with status == 0, which seems to happen for cached or local
|
||||
requests</li>
|
||||
<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
|
||||
<li>Changed scrapeText API to return a string by default. This is API-breaking!
|
||||
It was dumb to have the default return value be the form you almost never
|
||||
want. Sorry.</li>
|
||||
<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
|
||||
(where previously you'd likely get a DOM exception).</li>
|
||||
<li>Added three new functions to MochiKit.Base for dealing with URL query
|
||||
strings: urlEncode, queryString, parseQueryString</li>
|
||||
<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
|
||||
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
|
||||
new Function(v).</li>
|
||||
<li>Another workaround for Internet "worst browser ever" Explorer's setAttribute
|
||||
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).</li>
|
||||
<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
|
||||
<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
|
||||
now!</li>
|
||||
</ul>
|
||||
<p>2005-07-29 v0.60</p>
|
||||
<ul class="simple">
|
||||
<li>Beefed up the MochiKit.DOM test suite</li>
|
||||
<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
|
||||
false unexpectedly before</li>
|
||||
<li>Added an optional "parent" argument to
|
||||
MochiKit.DOM.getElementsByTagAndClassName</li>
|
||||
<li>Added a "packed" version in packed/lib/MochiKit/MochiKit.js</li>
|
||||
<li>Changed build script to rewrite the URLs in tests to account for the
|
||||
JSAN-required reorganization</li>
|
||||
<li>MochiKit.Compat to potentially work around IE 5.5 issues
|
||||
(5.0 still not supported). Test.Simple doesn't seem to work there,
|
||||
though.</li>
|
||||
<li>Several minor documentation corrections</li>
|
||||
</ul>
|
||||
<p>2005-07-27 v0.50</p>
|
||||
<ul class="simple">
|
||||
<li>Initial Release</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,162 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Visual - visual effects</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Visual - visual effects</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
// round the corners of all h1 elements
|
||||
roundClass("h1", null);
|
||||
|
||||
// round the top left corner of the element with the id "title"
|
||||
roundElement("title", {corners: "tl"});
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Visual provides visual effects and support functions for visuals.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
|
||||
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
|
||||
<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<p>At this time, MochiKit.Visual provides one visual effect: rounded corners
|
||||
for your HTML elements. These rounded corners are created completely
|
||||
through CSS manipulations and require no external images or style sheets.
|
||||
This implementation was adapted from <a class="reference" href="http://www.openrico.org">Rico</a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-roundclass"></a>
|
||||
<a class="mochidef reference" href="#fn-roundclass">roundClass(tagName[, className[, options]])</a>:</p>
|
||||
<blockquote>
|
||||
Rounds all of the elements that match the <tt class="docutils literal"><span class="pre">tagName</span></tt> and <tt class="docutils literal"><span class="pre">className</span></tt>
|
||||
specifiers, using the options provided. <tt class="docutils literal"><span class="pre">tagName</span></tt> or <tt class="docutils literal"><span class="pre">className</span></tt> can
|
||||
be <tt class="docutils literal"><span class="pre">null</span></tt> to match all tags or classes. For more information about
|
||||
the options, see the <a class="mochiref reference" href="#fn-roundelement">roundElement</a> function.</blockquote>
|
||||
<p>
|
||||
<a name="fn-roundelement"></a>
|
||||
<a class="mochidef reference" href="#fn-roundelement">roundElement(element[, options])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Immediately round the corners of the specified element.
|
||||
The element can be given as either a string
|
||||
with the element ID, or as an element object.</p>
|
||||
<p>The options mapping has the following defaults:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="35%" />
|
||||
<col width="65%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td>corners</td>
|
||||
<td><tt class="docutils literal"><span class="pre">"all"</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>color</td>
|
||||
<td><tt class="docutils literal"><span class="pre">"fromElement"</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>bgColor</td>
|
||||
<td><tt class="docutils literal"><span class="pre">"fromParent"</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>blend</td>
|
||||
<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>border</td>
|
||||
<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>compact</td>
|
||||
<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>corners:</p>
|
||||
<blockquote>
|
||||
<p>specifies which corners of the element should be rounded.
|
||||
Choices are:</p>
|
||||
<ul class="simple">
|
||||
<li>all</li>
|
||||
<li>top</li>
|
||||
<li>bottom</li>
|
||||
<li>tl (top left)</li>
|
||||
<li>bl (bottom left)</li>
|
||||
<li>tr (top right)</li>
|
||||
<li>br (bottom right)</li>
|
||||
</ul>
|
||||
<dl class="docutils">
|
||||
<dt>Example:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">"tl</span> <span class="pre">br"</span></tt>: top-left and bottom-right corners are rounded</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<dl class="docutils">
|
||||
<dt>blend:</dt>
|
||||
<dd>specifies whether the color and background color should be blended
|
||||
together to produce the border color.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id1" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id1">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id2" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id2">[2]</a></td><td>SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id3" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id3">[3]</a></td><td>W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Kevin Dangoor <<a class="reference" href="mailto:dangoor@gmail.com">dangoor@gmail.com</a>></li>
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
<li>Originally adapted from Rico <<a class="reference" href="http://openrico.org/">http://openrico.org/</a>> (though little remains)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
<p>Portions adapted from <a class="reference" href="http://www.openrico.org">Rico</a> are available under the terms of the
|
||||
<a class="reference" href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,319 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit Documentation Index</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="distribution" name="distribution">Distribution</a></h1>
|
||||
<p>MochiKit - makes JavaScript suck a bit less</p>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Async.html">MochiKit.Async</a> - manage asynchronous tasks</li>
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a> - functional programming and useful comparisons</li>
|
||||
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a> - painless DOM manipulation API</li>
|
||||
<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a> - color abstraction with CSS3 support</li>
|
||||
<li><a class="mochiref reference" href="DateTime.html">MochiKit.DateTime</a> - "what time is it anyway?"</li>
|
||||
<li><a class="mochiref reference" href="Format.html">MochiKit.Format</a> - string formatting goes here</li>
|
||||
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a> - itertools for JavaScript; iteration made HARD,
|
||||
and then easy</li>
|
||||
<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> - we're all tired of <tt class="docutils literal"><span class="pre">alert()</span></tt></li>
|
||||
<li><a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> - interactive <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a>
|
||||
pane</li>
|
||||
<li><a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> - simple universal event handling</li>
|
||||
<li><a class="mochiref reference" href="Visual.html">MochiKit.Visual</a> - visual effects</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="notes" name="notes">Notes</a></h1>
|
||||
<p>To turn on MochiKit's compatibility mode, do this before loading MochiKit:</p>
|
||||
<pre class="literal-block">
|
||||
<script type="text/javascript">MochiKit = {__compat__: true};</script>
|
||||
</pre>
|
||||
<p>When compatibility mode is on, you must use fully qualified names for all
|
||||
MochiKit functions (e.g. <tt class="docutils literal"><span class="pre">MochiKit.Base.map(...)</span></tt>).</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="screencasts" name="screencasts">Screencasts</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="http://mochikit.com/screencasts/MochiKit_Intro-1">MochiKit 1.1 Intro</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="http://groups.google.com/group/mochikit">Google Groups: MochiKit</a>: The official mailing list for discussions
|
||||
related to development of and with MochiKit</li>
|
||||
<li><a class="reference" href="http://mochikit.com/">mochikit.com</a>: MochiKit's home on the web</li>
|
||||
<li><a class="reference" href="http://bob.pythonmac.org/">from __future__ import *</a>: Bob Ippolito's blog</li>
|
||||
<li><a class="reference" href="http://openjsan.org/doc/b/bo/bob/lib/MochiKit/">MochiKit on JSAN</a>: the JSAN distribution page for MochiKit</li>
|
||||
<li><a class="reference" href="http://del.icio.us/tag/mochikit">MochiKit tag on del.icio.us</a>: Recent bookmarks related to MochiKit</li>
|
||||
<li><a class="reference" href="http://technorati.com/tag/mochikit">MochiKit tag on Technorati</a>: Recent blog entries related to MochiKit</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="version-history" name="version-history">Version History</a></h1>
|
||||
<p>2006-04-29 v1.3.1 (bug fix release)</p>
|
||||
<ul class="simple">
|
||||
<li>Fix sendXMLHttpRequest sendContent regression</li>
|
||||
<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
|
||||
<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
|
||||
</ul>
|
||||
<p>2006-04-26 v1.3 "warp zone"</p>
|
||||
<ul class="simple">
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
|
||||
<li>New MochiKit.Base.method as a convenience form of bind that takes the
|
||||
object before the method</li>
|
||||
<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
|
||||
a single Array</li>
|
||||
<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
|
||||
<li>New key_events example demonstrating use of MochiKit.Signal's key handling
|
||||
capabilities.</li>
|
||||
<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
|
||||
null is used and the string will be considered the first node. This
|
||||
allows for the more natural P("foo") rather than P(null, "foo").</li>
|
||||
<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
|
||||
provides multi-line input and a help() function to get MochiKit function
|
||||
signature from the documentation.</li>
|
||||
<li>Native Console Logging for the default MochiKit.Logging logger</li>
|
||||
<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
|
||||
<li>New MochiKit.Signal example: draggable</li>
|
||||
<li>Added sanity checking to Deferred to ensure that errors happen when chaining
|
||||
is used incorrectly</li>
|
||||
<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
|
||||
<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
|
||||
component values smaller than 16/255.</li>
|
||||
<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
|
||||
maximum size</li>
|
||||
<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
|
||||
Error, so that the errback chain is used instead of the callback chain.</li>
|
||||
<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
|
||||
in the correct order.</li>
|
||||
<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
|
||||
<li>MochiKit.Base.isNull no longer matches undefined</li>
|
||||
<li>example doctypes changed to HTML4</li>
|
||||
<li>isDateLike no longer throws error on null</li>
|
||||
<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
|
||||
<li>updated elementDimensions to calculate width from offsetWidth instead
|
||||
of clientWidth</li>
|
||||
<li>formContents now works with FORM tags that have a name attribute</li>
|
||||
<li>Documentation now uses MochiKit to generate a function index</li>
|
||||
</ul>
|
||||
<p>2006-01-26 v1.2 "the ocho"</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
|
||||
<li>Added new MochiKit.Base.findIdentical function to find the index of an
|
||||
element in an Array-like object. Uses === for identity comparison.</li>
|
||||
<li>Added new MochiKit.Base.find function to find the index of an element in
|
||||
an Array-like object. Uses compare for rich comparison.</li>
|
||||
<li>MochiKit.Base.bind will accept a string for func, which will be immediately
|
||||
looked up as self[func].</li>
|
||||
<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
|
||||
compatibility</li>
|
||||
<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
|
||||
<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
|
||||
height of an element in the document</li>
|
||||
<li>MochiKit.DOM's initialization is now compatible with
|
||||
HTMLUnit + JWebUnit + Rhino</li>
|
||||
<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
|
||||
currently in the document instead of always creating one.</li>
|
||||
<li>MochiKit.Base now has operator.mul</li>
|
||||
<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
|
||||
a custom value attribute</li>
|
||||
<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
|
||||
<li>MochiKit.DOM.setNodeAttribute should work now</li>
|
||||
<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
|
||||
property to a string</li>
|
||||
<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
|
||||
name and for properties</li>
|
||||
<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
|
||||
<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
|
||||
<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
|
||||
<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
|
||||
<li>Added new MochiKit.DOM documentation on element visibility</li>
|
||||
<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
|
||||
for determining the position of an element in the document</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
|
||||
</ul>
|
||||
<p>2005-11-14 v1.1</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed a bug in numberFormatter with large numbers</li>
|
||||
<li>Massively overhauled documentation</li>
|
||||
<li>Fast-path for primitives in MochiKit.Base.compare</li>
|
||||
<li>New groupby and groupby_as_array in MochiKit.Iter</li>
|
||||
<li>Added iterator factory adapter for objects that implement iterateNext()</li>
|
||||
<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
|
||||
LEGEND, FIELDSET</li>
|
||||
<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
|
||||
<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
|
||||
<li>MochiKit.LoggingPane now uses named windows based on the URL so that
|
||||
a given URL will get the same LoggingPane window after a reload
|
||||
(at the same position, etc.)</li>
|
||||
<li>MochiKit.DOM now has currentWindow() and currentDocument() context
|
||||
variables that are set with withWindow() and withDocument(). These
|
||||
context variables affect all MochiKit.DOM functionality (getElement,
|
||||
createDOM, etc.)</li>
|
||||
<li>MochiKit.Base.items will now catch and ignore exceptions for properties
|
||||
that are enumerable but not accessible (e.g. permission denied)</li>
|
||||
<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
|
||||
now accept additional arguments that are used to create a partially
|
||||
applied function. This differs from Twisted in that the callback/errback
|
||||
result becomes the <em>last</em> argument, not the first when this feature
|
||||
is used.</li>
|
||||
<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
|
||||
arguments which are used to create a GET query string</li>
|
||||
<li>Did some refactoring to reduce the footprint of MochiKit by a few
|
||||
kilobytes</li>
|
||||
<li>escapeHTML to longer escapes ' (apos) and now uses
|
||||
String.replace instead of iterating over every char.</li>
|
||||
<li>Added DeferredLock to Async</li>
|
||||
<li>Renamed getElementsComputedStyle to computedStyle and moved
|
||||
it from MochiKit.Visual to MochiKit.DOM</li>
|
||||
<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
|
||||
<li>Fixed range() to accept a negative step</li>
|
||||
<li>New alias to MochiKit.swapDOM called removeElement</li>
|
||||
<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
|
||||
an attribute on a node without raising, roughly equivalent to:
|
||||
updateNodeAttributes(node, {attr: value})</li>
|
||||
<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
|
||||
a node's attribute or returns null without raising</li>
|
||||
<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
|
||||
directly (addLoadEvent did not leak, since it clears the handler)</li>
|
||||
</ul>
|
||||
<p>2005-10-24 v1.0</p>
|
||||
<ul class="simple">
|
||||
<li>New interpreter example that shows usage of MochiKit.DOM to make
|
||||
an interactive JavaScript interpreter</li>
|
||||
<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
|
||||
debuggingBookmarklet, with logging_pane example to show its usage</li>
|
||||
<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
|
||||
in order to provide a live regular expression matching tool</li>
|
||||
<li>Added advanced number formatting capabilities to MochiKit.Format:
|
||||
numberFormatter(pattern, placeholder="", locale="default") and
|
||||
formatLocale(locale="default")</li>
|
||||
<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
|
||||
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
|
||||
<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
|
||||
to MochiKit.Format</li>
|
||||
<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
|
||||
isoTimestamp(isoString) will convert them to Date objects, and
|
||||
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
|
||||
<li>Fixed missing errback for sendXMLHttpRequest when the server does not
|
||||
respond</li>
|
||||
<li>Fixed infinite recusion bug when using roundClass("DIV", ...)</li>
|
||||
<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
|
||||
from being cancelled properly</li>
|
||||
<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
|
||||
have an apply method, such as alert</li>
|
||||
<li>Reliably return null from the string parsing/manipulation functions if
|
||||
the input can't be coerced to a string (s + "") or the input makes no sense;
|
||||
e.g. isoTimestamp(null) and isoTimestamp("") return null</li>
|
||||
</ul>
|
||||
<p>2005-10-08 v0.90</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed ISO compliance with toISODate</li>
|
||||
<li>Added missing operator.sub</li>
|
||||
<li>Placated Mozilla's strict warnings a bit</li>
|
||||
<li>Added JSON serialization and unserialization support to MochiKit.Base:
|
||||
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
|
||||
API.</li>
|
||||
<li>Fixed a bug in the script loader that failed in some scenarios when a script
|
||||
tag did not have a "src" attribute (thanks Ian!)</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
|
||||
P, FORM</li>
|
||||
<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
|
||||
and parseQueryString, when available.</li>
|
||||
</ul>
|
||||
<p>2005-08-12 v0.80</p>
|
||||
<ul class="simple">
|
||||
<li>Source highlighting in all examples, moved to a view-source example</li>
|
||||
<li>Added some experimental syntax highlighting for the Rounded Corners example,
|
||||
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
|
||||
<li>Use an indirect binding for the logger conveniences, so that the global
|
||||
logger could be replaced by setting MochiKit.Logger.logger to something else
|
||||
(though an observer is probably a better choice).</li>
|
||||
<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
|
||||
which will be looked up with getElement</li>
|
||||
<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
|
||||
node.parentNode)</li>
|
||||
<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
|
||||
<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
|
||||
<li>Possible workaround for Safari issue with swapDOM, where it would get
|
||||
confused because two elements were in the DOM at the same time with the
|
||||
same id</li>
|
||||
<li>Added missing THEAD convenience function to MochiKit.DOM</li>
|
||||
<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
|
||||
<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
|
||||
MochiKit.DOM</li>
|
||||
<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
|
||||
<li>Added HSV color space support to MochiKit.Visual</li>
|
||||
<li>Fixed a bug in the sortable_tables example, it now converts types
|
||||
correctly</li>
|
||||
<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
|
||||
scope</li>
|
||||
</ul>
|
||||
<p>2005-08-04 v0.70</p>
|
||||
<ul class="simple">
|
||||
<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
|
||||
a little TAL-ish DOM templating attribute language.</li>
|
||||
<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
|
||||
ignore requests with status == 0, which seems to happen for cached or local
|
||||
requests</li>
|
||||
<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
|
||||
<li>Changed scrapeText API to return a string by default. This is API-breaking!
|
||||
It was dumb to have the default return value be the form you almost never
|
||||
want. Sorry.</li>
|
||||
<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
|
||||
(where previously you'd likely get a DOM exception).</li>
|
||||
<li>Added three new functions to MochiKit.Base for dealing with URL query
|
||||
strings: urlEncode, queryString, parseQueryString</li>
|
||||
<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
|
||||
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
|
||||
new Function(v).</li>
|
||||
<li>Another workaround for Internet "worst browser ever" Explorer's setAttribute
|
||||
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).</li>
|
||||
<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
|
||||
<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
|
||||
now!</li>
|
||||
</ul>
|
||||
<p>2005-07-29 v0.60</p>
|
||||
<ul class="simple">
|
||||
<li>Beefed up the MochiKit.DOM test suite</li>
|
||||
<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
|
||||
false unexpectedly before</li>
|
||||
<li>Added an optional "parent" argument to
|
||||
MochiKit.DOM.getElementsByTagAndClassName</li>
|
||||
<li>Added a "packed" version in packed/lib/MochiKit/MochiKit.js</li>
|
||||
<li>Changed build script to rewrite the URLs in tests to account for the
|
||||
JSAN-required reorganization</li>
|
||||
<li>MochiKit.Compat to potentially work around IE 5.5 issues
|
||||
(5.0 still not supported). Test.Simple doesn't seem to work there,
|
||||
though.</li>
|
||||
<li>Several minor documentation corrections</li>
|
||||
</ul>
|
||||
<p>2005-07-27 v0.50</p>
|
||||
<ul class="simple">
|
||||
<li>Initial Release</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,89 +0,0 @@
|
||||
function function_ref(fn) {
|
||||
return A({"href": fn[1], "class": "mochiref reference"}, fn[0], BR());
|
||||
};
|
||||
|
||||
function toggle_docs() {
|
||||
toggleElementClass("invisible", "show_index", "function_index");
|
||||
return false;
|
||||
};
|
||||
|
||||
function create_toc() {
|
||||
if (getElement("distribution")) {
|
||||
return global_index();
|
||||
}
|
||||
if (getElement("api-reference")) {
|
||||
return module_index();
|
||||
}
|
||||
};
|
||||
|
||||
function doXHTMLRequest(url) {
|
||||
var req = getXMLHttpRequest();
|
||||
if (req.overrideMimeType) {
|
||||
req.overrideMimeType("text/xml");
|
||||
}
|
||||
req.open("GET", url, true);
|
||||
return sendXMLHttpRequest(req).addCallback(function (res) {
|
||||
return res.responseXML.documentElement;
|
||||
});
|
||||
};
|
||||
|
||||
function load_request(href, div, doc) {
|
||||
var functions = withDocument(doc, spider_doc);
|
||||
forEach(functions, function (func) {
|
||||
// fix anchors
|
||||
if (func[1].charAt(0) == "#") {
|
||||
func[1] = href + func[1];
|
||||
}
|
||||
});
|
||||
var showLink = A({"class": "force-pointer"}, "[+]");
|
||||
var hideLink = A({"class": "force-pointer"}, "[\u2013]");
|
||||
var functionIndex = DIV({"id": "function_index", "class": "invisible"},
|
||||
hideLink,
|
||||
P(null, map(function_ref, functions))
|
||||
);
|
||||
var toggleFunc = function (e) {
|
||||
toggleElementClass("invisible", showLink, functionIndex);
|
||||
};
|
||||
connect(showLink, "onclick", toggleFunc);
|
||||
connect(hideLink, "onclick", toggleFunc);
|
||||
replaceChildNodes(div,
|
||||
showLink,
|
||||
functionIndex
|
||||
);
|
||||
};
|
||||
|
||||
function global_index() {
|
||||
var distList = getElementsByTagAndClassName("ul")[0];
|
||||
var bullets = getElementsByTagAndClassName("li", null, distList);
|
||||
for (var i = 0; i < bullets.length; i++) {
|
||||
var tag = bullets[i];
|
||||
var firstLink = getElementsByTagAndClassName("a", "mochiref", tag)[0];
|
||||
var href = getNodeAttribute(firstLink, "href");
|
||||
var div = DIV(null, "[\u2026]");
|
||||
appendChildNodes(tag, BR(), div);
|
||||
var d = doXHTMLRequest(href).addCallback(load_request, href, div);
|
||||
}
|
||||
};
|
||||
|
||||
function spider_doc() {
|
||||
return map(
|
||||
function (tag) {
|
||||
return [scrapeText(tag), getNodeAttribute(tag, "href")];
|
||||
},
|
||||
getElementsByTagAndClassName("a", "mochidef")
|
||||
);
|
||||
};
|
||||
|
||||
function module_index() {
|
||||
var sections = getElementsByTagAndClassName("div", "section");
|
||||
var ptr = sections[1];
|
||||
var ref = DIV({"class": "section"},
|
||||
H1(null, "Function Index"),
|
||||
A({"id": "show_index", "href": "#", "onclick": toggle_docs}, "[show]"),
|
||||
DIV({"id": "function_index", "class": "invisible"},
|
||||
A({"href":"#", "onclick": toggle_docs}, "[hide]"),
|
||||
P(null, map(function_ref, spider_doc()))));
|
||||
ptr.parentNode.insertBefore(ref, ptr);
|
||||
};
|
||||
|
||||
addLoadEvent(create_toc);
|
||||
@@ -1,573 +0,0 @@
|
||||
.. title:: MochiKit.Async - manage asynchronous tasks
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.Async - manage asynchronous tasks
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
var url = "/src/b/bo/bob/MochiKit.Async/META.json";
|
||||
/*
|
||||
|
||||
META.json looks something like this:
|
||||
|
||||
{"name": "MochiKit", "version": "0.5"}
|
||||
|
||||
*/
|
||||
var d = loadJSONDoc(url);
|
||||
var gotMetadata = function (meta) {
|
||||
if (MochiKit.Async.VERSION == meta.version) {
|
||||
alert("You have the newest MochiKit.Async!");
|
||||
} else {
|
||||
alert("MochiKit.Async "
|
||||
+ meta.version
|
||||
+ " is available, upgrade!");
|
||||
}
|
||||
};
|
||||
var metadataFetchFailed = function (err) {
|
||||
alert("The metadata for MochiKit.Async could not be fetched :(");
|
||||
};
|
||||
d.addCallbacks(gotMetadata, metadataFetchFailed);
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
MochiKit.Async provides facilities to manage asynchronous
|
||||
(as in AJAX [1]_) tasks. The model for asynchronous computation
|
||||
used in this module is heavily inspired by Twisted [2]_.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
- :mochiref:`MochiKit.Base`
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Deferred
|
||||
--------
|
||||
|
||||
The Deferred constructor encapsulates a single value that
|
||||
is not available yet. The most important example of this
|
||||
in the context of a web browser would be an ``XMLHttpRequest``
|
||||
to a server. The importance of the Deferred is that it
|
||||
allows a consistent API to be exposed for all asynchronous
|
||||
computations that occur exactly once.
|
||||
|
||||
The producer of the Deferred is responsible for doing all
|
||||
of the complicated work behind the scenes. This often
|
||||
means waiting for a timer to fire, or waiting for an event
|
||||
(e.g. ``onreadystatechange`` of ``XMLHttpRequest``).
|
||||
It could also be coordinating several events (e.g.
|
||||
``XMLHttpRequest`` with a timeout, or several Deferreds
|
||||
(e.g. fetching a set of XML documents that should be
|
||||
processed at the same time).
|
||||
|
||||
Since these sorts of tasks do not respond immediately, the
|
||||
producer of the Deferred does the following steps before
|
||||
returning to the consumer:
|
||||
|
||||
1. Create a ``new`` :mochiref:`Deferred();` object and keep a reference
|
||||
to it, because it will be needed later when the value is
|
||||
ready.
|
||||
2. Setup the conditions to create the value requested (e.g.
|
||||
create a new ``XMLHttpRequest``, set its
|
||||
``onreadystatechange``).
|
||||
3. Return the :mochiref:`Deferred` object.
|
||||
|
||||
Since the value is not yet ready, the consumer attaches
|
||||
a function to the Deferred that will be called when the
|
||||
value is ready. This is not unlike ``setTimeout``, or
|
||||
other similar facilities you may already be familiar with.
|
||||
The consumer can also attach an "errback" to the
|
||||
:mochiref:`Deferred`, which is a callback for error handling.
|
||||
|
||||
When the value is ready, the producer simply calls
|
||||
``myDeferred.callback(theValue)``. If an error occurred,
|
||||
it should call ``myDeferred.errback(theValue)`` instead.
|
||||
As soon as this happens, the callback that the consumer
|
||||
attached to the :mochiref:`Deferred` is called with ``theValue``
|
||||
as the only argument.
|
||||
|
||||
There are quite a few additional "advanced" features
|
||||
baked into :mochiref:`Deferred`, such as cancellation and
|
||||
callback chains, so take a look at the API
|
||||
reference if you would like to know more!
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
:mochidef:`AlreadyCalledError`:
|
||||
|
||||
Thrown by a :mochiref:`Deferred` if ``.callback`` or
|
||||
``.errback`` are called more than once.
|
||||
|
||||
|
||||
:mochidef:`BrowserComplianceError`:
|
||||
|
||||
Thrown when the JavaScript runtime is not capable of performing
|
||||
the given function. Currently, this happens if the browser
|
||||
does not support ``XMLHttpRequest``.
|
||||
|
||||
|
||||
:mochidef:`CancelledError`:
|
||||
|
||||
Thrown by a :mochiref:`Deferred` when it is cancelled,
|
||||
unless a canceller is present and throws something else.
|
||||
|
||||
|
||||
:mochidef:`GenericError`:
|
||||
|
||||
Results passed to ``.fail`` or ``.errback`` of a :mochiref:`Deferred`
|
||||
are wrapped by this ``Error`` if ``!(result instanceof Error)``.
|
||||
|
||||
|
||||
:mochidef:`XMLHttpRequestError`:
|
||||
|
||||
Thrown when an ``XMLHttpRequest`` does not complete successfully
|
||||
for any reason. The ``req`` property of the error is the failed
|
||||
``XMLHttpRequest`` object, and for convenience the ``number``
|
||||
property corresponds to ``req.status``.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
:mochidef:`Deferred()`:
|
||||
|
||||
Encapsulates a sequence of callbacks in response to a value that
|
||||
may not yet be available. This is modeled after the Deferred class
|
||||
from Twisted [3]_.
|
||||
|
||||
.. _`Twisted`: http://twistedmatrix.com/
|
||||
|
||||
Why do we want this? JavaScript has no threads, and even if it did,
|
||||
threads are hard. Deferreds are a way of abstracting non-blocking
|
||||
events, such as the final response to an ``XMLHttpRequest``.
|
||||
|
||||
The sequence of callbacks is internally represented as a list
|
||||
of 2-tuples containing the callback/errback pair. For example,
|
||||
the following call sequence::
|
||||
|
||||
var d = new Deferred();
|
||||
d.addCallback(myCallback);
|
||||
d.addErrback(myErrback);
|
||||
d.addBoth(myBoth);
|
||||
d.addCallbacks(myCallback, myErrback);
|
||||
|
||||
is translated into a :mochiref:`Deferred` with the following internal
|
||||
representation::
|
||||
|
||||
[
|
||||
[myCallback, null],
|
||||
[null, myErrback],
|
||||
[myBoth, myBoth],
|
||||
[myCallback, myErrback]
|
||||
]
|
||||
|
||||
The :mochiref:`Deferred` also keeps track of its current status (fired).
|
||||
Its status may be one of the following three values:
|
||||
|
||||
|
||||
===== ================================
|
||||
Value Condition
|
||||
===== ================================
|
||||
-1 no value yet (initial condition)
|
||||
0 success
|
||||
1 error
|
||||
===== ================================
|
||||
|
||||
A :mochiref:`Deferred` will be in the error state if one of the following
|
||||
conditions are met:
|
||||
|
||||
1. The result given to callback or errback is "``instanceof Error``"
|
||||
2. The callback or errback threw while executing. If the thrown object
|
||||
is not ``instanceof Error``, it will be wrapped with
|
||||
:mochiref:`GenericError`.
|
||||
|
||||
Otherwise, the :mochiref:`Deferred` will be in the success state. The state
|
||||
of the :mochiref:`Deferred` determines the next element in the callback
|
||||
sequence to run.
|
||||
|
||||
When a callback or errback occurs with the example deferred chain, something
|
||||
equivalent to the following will happen (imagine that exceptions are caught
|
||||
and returned as-is)::
|
||||
|
||||
// d.callback(result) or d.errback(result)
|
||||
if (!(result instanceof Error)) {
|
||||
result = myCallback(result);
|
||||
}
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
}
|
||||
result = myBoth(result);
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
} else {
|
||||
result = myCallback(result);
|
||||
}
|
||||
|
||||
The result is then stored away in case another step is added to the
|
||||
callback sequence. Since the :mochiref:`Deferred` already has a value
|
||||
available, any new callbacks added will be called immediately.
|
||||
|
||||
There are two other "advanced" details about this implementation that are
|
||||
useful:
|
||||
|
||||
Callbacks are allowed to return :mochiref:`Deferred` instances,
|
||||
so you can build complicated sequences of events with (relative) ease.
|
||||
|
||||
The creator of the :mochiref:`Deferred` may specify a canceller. The
|
||||
canceller is a function that will be called if
|
||||
:mochiref:`Deferred.prototype.cancel` is called before the
|
||||
:mochiref:`Deferred` fires. You can use this to allow an
|
||||
``XMLHttpRequest`` to be cleanly cancelled, for example. Note that
|
||||
cancel will fire the :mochiref:`Deferred` with a
|
||||
:mochiref:`CancelledError` (unless your canceller throws or returns
|
||||
a different ``Error``), so errbacks should be prepared to handle that
|
||||
``Error`` gracefully for cancellable :mochiref:`Deferred` instances.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.addBoth(func)`:
|
||||
|
||||
Add the same function as both a callback and an errback as the
|
||||
next element on the callback sequence. This is useful for code
|
||||
that you want to guarantee to run, e.g. a finalizer.
|
||||
|
||||
If additional arguments are given, then ``func`` will be replaced
|
||||
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
|
||||
differs from `Twisted`_, because the result of the callback or
|
||||
errback will be the *last* argument passed to ``func``.
|
||||
|
||||
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned ``Deferred`` is chained, it can no longer accept new
|
||||
callbacks.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.addCallback(func[, ...])`:
|
||||
|
||||
Add a single callback to the end of the callback sequence.
|
||||
|
||||
If additional arguments are given, then ``func`` will be replaced
|
||||
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
|
||||
differs from `Twisted`_, because the result of the callback will
|
||||
be the *last* argument passed to ``func``.
|
||||
|
||||
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned ``Deferred`` is chained, it can no longer accept new
|
||||
callbacks.
|
||||
|
||||
:mochidef:`Deferred.prototype.addCallbacks(callback, errback)`:
|
||||
|
||||
Add separate callback and errback to the end of the callback
|
||||
sequence. Either callback or errback may be ``null``,
|
||||
but not both.
|
||||
|
||||
If ``callback`` or ``errback`` returns a :mochiref:`Deferred`,
|
||||
then it will be chained (its value or error will be passed to the
|
||||
next callback). Note that once the returned ``Deferred`` is chained,
|
||||
it can no longer accept new callbacks.
|
||||
|
||||
:mochidef:`Deferred.prototype.addErrback(func)`:
|
||||
|
||||
Add a single errback to the end of the callback sequence.
|
||||
|
||||
If additional arguments are given, then ``func`` will be replaced
|
||||
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
|
||||
differs from `Twisted`_, because the result of the errback will
|
||||
be the *last* argument passed to ``func``.
|
||||
|
||||
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned ``Deferred`` is chained, it can no longer accept new
|
||||
callbacks.
|
||||
|
||||
:mochidef:`Deferred.prototype.callback([result])`:
|
||||
|
||||
Begin the callback sequence with a non-``Error`` result. Result
|
||||
may be any value except for a :mochiref:`Deferred`.
|
||||
|
||||
Either ``.callback`` or ``.errback`` should
|
||||
be called exactly once on a :mochiref:`Deferred`.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.cancel()`:
|
||||
|
||||
Cancels a :mochiref:`Deferred` that has not yet received a value,
|
||||
or is waiting on another :mochiref:`Deferred` as its value.
|
||||
|
||||
If a canceller is defined, the canceller is called.
|
||||
If the canceller did not return an ``Error``, or there
|
||||
was no canceller, then the errback chain is started
|
||||
with :mochiref:`CancelledError`.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.errback([result])`:
|
||||
|
||||
Begin the callback sequence with an error result.
|
||||
Result may be any value except for a :mochiref:`Deferred`,
|
||||
but if ``!(result instanceof Error)``, it will be wrapped
|
||||
with :mochiref:`GenericError`.
|
||||
|
||||
Either ``.callback`` or ``.errback`` should
|
||||
be called exactly once on a :mochidef:`Deferred`.
|
||||
|
||||
|
||||
:mochidef:`DeferredLock()`:
|
||||
|
||||
A lock for asynchronous systems.
|
||||
|
||||
The ``locked`` property of a :mochiref:`DeferredLock` will be ``true`` if
|
||||
it locked, ``false`` otherwise. Do not change this property.
|
||||
|
||||
|
||||
:mochidef:`DeferredLock.prototype.acquire()`:
|
||||
|
||||
Attempt to acquire the lock. Returns a :mochiref:`Deferred` that fires on
|
||||
lock acquisition with the :mochiref:`DeferredLock` as the value.
|
||||
If the lock is locked, then the :mochiref:`Deferred` goes into a waiting
|
||||
list.
|
||||
|
||||
|
||||
:mochidef:`DeferredLock.prototype.release()`:
|
||||
|
||||
Release the lock. If there is a waiting list, then the first
|
||||
:mochiref:`Deferred` in that waiting list will be called back.
|
||||
|
||||
|
||||
:mochidef:`DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])`:
|
||||
|
||||
Combine a list of :mochiref:`Deferred` into one. Track the callbacks and
|
||||
return a list of (success, result) tuples, 'success' being a boolean
|
||||
indicating whether result is a normal result or an error.
|
||||
|
||||
Once created, you have access to all :mochiref:`Deferred` methods, like
|
||||
addCallback, addErrback, addBoth. The behaviour can be changed by the
|
||||
following options:
|
||||
|
||||
``fireOnOneCallback``:
|
||||
Flag for launching the callback once the first Deferred of the list
|
||||
has returned.
|
||||
|
||||
``fireOnOneErrback``:
|
||||
Flag for calling the errback at the first error of a Deferred.
|
||||
|
||||
``consumeErrors``:
|
||||
Flag indicating that any errors raised in the Deferreds should be
|
||||
consumed by the DeferredList.
|
||||
|
||||
Example::
|
||||
|
||||
// We need to fetch data from 2 different urls
|
||||
var d1 = loadJSONDoc(url1);
|
||||
var d2 = loadJSONDoc(url2);
|
||||
var l1 = new DeferredList([d1, d2], false, false, true);
|
||||
l1.addCallback(function (resultList) {
|
||||
MochiKit.Base.map(function (result) {
|
||||
if (result[0]) {
|
||||
alert("Data is here: " + result[1]);
|
||||
} else {
|
||||
alert("Got an error: " + result[1]);
|
||||
}
|
||||
}, resultList);
|
||||
});
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`callLater(seconds, func[, args...])`:
|
||||
|
||||
Call ``func(args...)`` after at least ``seconds`` seconds have elapsed.
|
||||
This is a convenience method for::
|
||||
|
||||
func = partial.apply(extend(null, arguments, 1));
|
||||
return wait(seconds).addCallback(function (res) { return func() });
|
||||
|
||||
Returns a cancellable :mochiref:`Deferred`.
|
||||
|
||||
|
||||
:mochidef:`doSimpleXMLHttpRequest(url[, queryArguments...])`:
|
||||
|
||||
Perform a simple ``XMLHttpRequest`` and wrap it with a
|
||||
:mochiref:`Deferred` that may be cancelled.
|
||||
|
||||
Note that currently, only ``200`` (OK) and ``304``
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an ``XMLHttpRequestError``.
|
||||
|
||||
``url``:
|
||||
The URL to GET
|
||||
|
||||
``queryArguments``:
|
||||
If this function is called with more than one argument, a ``"?"``
|
||||
and the result of :mochiref:`MochiKit.Base.queryString` with
|
||||
the rest of the arguments are appended to the URL.
|
||||
|
||||
For example, this will do a GET request to the URL
|
||||
``http://example.com?bar=baz``::
|
||||
|
||||
doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
|
||||
|
||||
*returns*:
|
||||
:mochiref:`Deferred` that will callback with the ``XMLHttpRequest``
|
||||
instance on success
|
||||
|
||||
|
||||
:mochidef:`evalJSONRequest(req)`:
|
||||
|
||||
Evaluate a JSON [4]_ ``XMLHttpRequest``
|
||||
|
||||
``req``:
|
||||
The request whose ``.responseText`` property is to be evaluated
|
||||
|
||||
*returns*:
|
||||
A JavaScript object
|
||||
|
||||
|
||||
:mochidef:`fail([result])`:
|
||||
|
||||
Return a :mochiref:`Deferred` that has already had ``.errback(result)``
|
||||
called.
|
||||
|
||||
See ``succeed`` documentation for rationale.
|
||||
|
||||
``result``:
|
||||
The result to give to :mochiref:`Deferred.prototype.errback(result)`.
|
||||
|
||||
*returns*:
|
||||
A ``new`` :mochiref:`Deferred()`
|
||||
|
||||
|
||||
:mochidef:`gatherResults(deferreds)`:
|
||||
|
||||
A convenience function that returns a :mochiref:`DeferredList`
|
||||
from the given ``Array`` of :mochiref:`Deferred` instances
|
||||
that will callback with an ``Array`` of just results when
|
||||
they're available, or errback on the first array.
|
||||
|
||||
|
||||
:mochidef:`getXMLHttpRequest()`:
|
||||
|
||||
Return an ``XMLHttpRequest`` compliant object for the current
|
||||
platform.
|
||||
|
||||
In order of preference:
|
||||
|
||||
- ``new XMLHttpRequest()``
|
||||
- ``new ActiveXObject('Msxml2.XMLHTTP')``
|
||||
- ``new ActiveXObject('Microsoft.XMLHTTP')``
|
||||
- ``new ActiveXObject('Msxml2.XMLHTTP.4.0')``
|
||||
|
||||
|
||||
:mochidef:`maybeDeferred(func[, argument...])`:
|
||||
|
||||
Call a ``func`` with the given arguments and ensure the result is a
|
||||
:mochiref:`Deferred`.
|
||||
|
||||
``func``:
|
||||
The function to call.
|
||||
|
||||
*returns*:
|
||||
A new :mochiref:`Deferred` based on the call to ``func``. If ``func``
|
||||
does not naturally return a :mochiref:`Deferred`, its result or error
|
||||
value will be wrapped by one.
|
||||
|
||||
|
||||
:mochidef:`loadJSONDoc(url)`:
|
||||
|
||||
Do a simple ``XMLHttpRequest`` to a URL and get the response
|
||||
as a JSON [4]_ document.
|
||||
|
||||
``url``:
|
||||
The URL to GET
|
||||
|
||||
*returns*:
|
||||
:mochiref:`Deferred` that will callback with the evaluated JSON [4]_
|
||||
response upon successful ``XMLHttpRequest``
|
||||
|
||||
|
||||
:mochidef:`sendXMLHttpRequest(req[, sendContent])`:
|
||||
|
||||
Set an ``onreadystatechange`` handler on an ``XMLHttpRequest`` object
|
||||
and send it off. Will return a cancellable :mochiref:`Deferred` that will
|
||||
callback on success.
|
||||
|
||||
Note that currently, only ``200`` (OK) and ``304``
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an ``XMLHttpRequestError``.
|
||||
|
||||
``req``:
|
||||
An preconfigured ``XMLHttpRequest`` object (open has been called).
|
||||
|
||||
``sendContent``:
|
||||
Optional string or DOM content to send over the ``XMLHttpRequest``.
|
||||
|
||||
*returns*:
|
||||
:mochiref:`Deferred` that will callback with the ``XMLHttpRequest``
|
||||
instance on success.
|
||||
|
||||
|
||||
:mochidef:`succeed([result])`:
|
||||
|
||||
Return a :mochiref:`Deferred` that has already had ``.callback(result)``
|
||||
called.
|
||||
|
||||
This is useful when you're writing synchronous code to an asynchronous
|
||||
interface: i.e., some code is calling you expecting a :mochiref:`Deferred`
|
||||
result, but you don't actually need to do anything asynchronous. Just
|
||||
return ``succeed(theResult)``.
|
||||
|
||||
See ``fail`` for a version of this function that uses a failing
|
||||
:mochiref:`Deferred` rather than a successful one.
|
||||
|
||||
``result``:
|
||||
The result to give to :mochiref:`Deferred.prototype.callback(result)`
|
||||
|
||||
*returns*:
|
||||
a ``new`` :mochiref:`Deferred`
|
||||
|
||||
|
||||
:mochidef:`wait(seconds[, res])`:
|
||||
|
||||
Return a new cancellable :mochiref:`Deferred` that will ``.callback(res)``
|
||||
after at least ``seconds`` seconds have elapsed.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX
|
||||
.. [2] Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/
|
||||
.. [3] Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
|
||||
.. [4] JSON, JavaScript Object Notation: http://json.org/
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,481 +0,0 @@
|
||||
.. title:: MochiKit.Color - color abstraction with CSS3 support
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.Color - color abstraction with CSS3 support
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
// RGB color expressions are supported
|
||||
assert(
|
||||
objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
|
||||
);
|
||||
|
||||
// So is instantiating directly from HSL or RGB values.
|
||||
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
|
||||
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
|
||||
|
||||
// Or even SVG color keyword names, as per CSS3!
|
||||
assert( Color.fromString("aquamarine"), "#7fffd4" );
|
||||
|
||||
// NSColor-like colors built in
|
||||
assert( Color.whiteColor().toHexString() == "#ffffff" );
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
MochiKit.Color is an abstraction for handling colors and strings that
|
||||
represent colors.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
- :mochiref:`MochiKit.Base`
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha.
|
||||
It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG)
|
||||
color table.
|
||||
|
||||
All of the functionality in this module is exposed through a Color constructor
|
||||
and its prototype, but a few of its internals are available for direct use at
|
||||
module level.
|
||||
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
:mochidef:`Color()`:
|
||||
|
||||
Represents a color. Component values should be integers between ``0.0``
|
||||
and ``1.0``. You should use one of the :mochiref:`Color` factory
|
||||
functions such as :mochiref:`Color.fromRGB`, :mochiref:`Color.fromHSL`,
|
||||
etc. instead of constructing :mochiref:`Color` objects directly.
|
||||
|
||||
:mochiref:`Color` instances can be compared with
|
||||
:mochiref:`MochiKit.Base.compare` (though ordering is on RGB, so is not
|
||||
particularly meaningful except for equality), and the default ``toString``
|
||||
implementation returns :mochiref:`Color.prototype.toHexString()`.
|
||||
|
||||
:mochiref:`Color` instances are immutable, and much of the architecture is
|
||||
inspired by AppKit's NSColor [1]_
|
||||
|
||||
|
||||
:mochidef:`Color.fromBackground(elem)`:
|
||||
|
||||
Returns a :mochiref:`Color` object based on the background of the provided
|
||||
element. Equivalent to::
|
||||
|
||||
c = Color.fromComputedStyle(
|
||||
elem, "backgroundColor", "background-color") || Color.whiteColor();
|
||||
|
||||
|
||||
:mochidef:`Color.fromComputedStyle(elem, style, mozillaEquivalentCSS)`:
|
||||
|
||||
Returns a :mochiref:`Color` object based on the result of
|
||||
:mochiref:`MochiKit.DOM.computedStyle(elem, style, mozillaEquivalentCSS)`
|
||||
or ``null`` if not found.
|
||||
|
||||
|
||||
:mochidef:`Color.fromHexString(hexString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given hexadecimal color string.
|
||||
For example, ``"#FFFFFF"`` would return a :mochiref:`Color` with
|
||||
RGB values ``[255/255, 255/255, 255/255]`` (white).
|
||||
|
||||
|
||||
:mochidef:`Color.fromHSL(hue, saturation, lightness, alpha=1.0)`:
|
||||
|
||||
Return a :mochiref:`Color` object from the given ``hue``, ``saturation``,
|
||||
``lightness`` values. Values should be numbers between ``0.0`` and
|
||||
``1.0``.
|
||||
|
||||
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})`
|
||||
|
||||
|
||||
:mochidef:`Color.fromHSLString(hslString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given decimal hsl color string.
|
||||
For example, ``"hsl(0,0%,100%)"`` would return a :mochiref:`Color` with
|
||||
HSL values ``[0/360, 0/360, 360/360]`` (white).
|
||||
|
||||
|
||||
:mochidef:`Color.fromHSV(hue, saturation, value, alpha=1.0)`:
|
||||
|
||||
Return a :mochiref:`Color` object from the given ``hue``, ``saturation``,
|
||||
``value`` values. Values should be numbers between ``0.0`` and
|
||||
``1.0``.
|
||||
|
||||
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})`
|
||||
|
||||
|
||||
:mochidef:`Color.fromName(colorName)`:
|
||||
|
||||
Returns a :mochiref:`Color` object corresponding to the given
|
||||
SVG 1.0 color keyword name [2]_ as per the W3C CSS3
|
||||
Color Module [3]_. ``"transparent"`` is also accepted
|
||||
as a color name, and will return :mochiref:`Color.transparentColor()`.
|
||||
|
||||
|
||||
:mochidef:`Color.fromRGB(red, green, blue, alpha=1.0)`:
|
||||
|
||||
Return a :mochiref:`Color` object from the given ``red``, ``green``,
|
||||
``blue``, and ``alpha`` values. Values should be numbers between ``0``
|
||||
and ``1.0``.
|
||||
|
||||
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`Color.fromRGB({r: red, g: green, b: blue, a: alpha})`
|
||||
|
||||
|
||||
:mochidef:`Color.fromRGBString(rgbString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given decimal rgb color string.
|
||||
For example, ``"rgb(255,255,255)"`` would return a :mochiref:`Color` with
|
||||
RGB values ``[255/255, 255/255, 255/255]`` (white).
|
||||
|
||||
|
||||
:mochidef:`Color.fromText(elem)`:
|
||||
|
||||
Returns a :mochiref:`Color` object based on the text color of the provided
|
||||
element. Equivalent to::
|
||||
|
||||
c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
|
||||
|
||||
|
||||
:mochidef:`Color.fromString(rgbOrHexString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given RGB, HSL, hex, or name.
|
||||
Will return ``null`` if the string can not be parsed by any of these
|
||||
methods.
|
||||
|
||||
See :mochiref:`Color.fromHexString`, :mochiref:`Color.fromRGBString`,
|
||||
:mochiref:`Color.fromHSLString` and :mochiref:`Color.fromName` more
|
||||
information.
|
||||
|
||||
|
||||
:mochidef:`Color.namedColors()`:
|
||||
|
||||
Returns an object with properties for each SVG 1.0 color keyword
|
||||
name [2]_ supported by CSS3 [3]_. Property names are the color keyword
|
||||
name in lowercase, and the value is a string suitable for
|
||||
:mochiref:`Color.fromString()`.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithAlpha(alpha)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``alpha`` value.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithHue(hue)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``hue`` value.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithSaturation(saturation)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``saturation`` value (using the HSL color model).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithLightness(lightness)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``lightness`` value.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.darkerColorWithLevel(level)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but darker by the given
|
||||
``level`` (between ``0`` and ``1.0``).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.lighterColorWithLevel(level)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but lighter by the given
|
||||
``level`` (between ``0`` and ``1.0``).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.blendedColor(other, fraction=0.5)`:
|
||||
|
||||
Return a new :mochiref:`Color` whose RGBA component values are a weighted sum
|
||||
of this color and ``other``. Each component of the returned color
|
||||
is the ``fraction`` of other's value plus ``1 - fraction`` of this
|
||||
color's.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.isLight()`:
|
||||
|
||||
Return ``true`` if the lightness value of this color is greater than
|
||||
``0.5``.
|
||||
|
||||
Note that ``alpha`` is ignored for this calculation (color components
|
||||
are not premultiplied).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.isDark()`:
|
||||
|
||||
Return ``true`` if the lightness value of this color is less than or
|
||||
equal to ``0.5``.
|
||||
|
||||
Note that ``alpha`` is ignored for this calculation (color components
|
||||
are not premultiplied).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.toRGBString()`:
|
||||
|
||||
Return the decimal ``"rgb(red, green, blue)"`` string representation of this
|
||||
color.
|
||||
|
||||
If the alpha component is not ``1.0`` (fully opaque), the
|
||||
``"rgba(red, green, blue, alpha)"`` string representation will be used.
|
||||
|
||||
For example::
|
||||
|
||||
assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.toHSLString()`:
|
||||
|
||||
Return the decimal ``"hsl(hue, saturation, lightness)"``
|
||||
string representation of this color.
|
||||
|
||||
If the alpha component is not ``1.0`` (fully opaque), the
|
||||
``"hsla(hue, saturation, lightness, alpha)"`` string representation
|
||||
will be used.
|
||||
|
||||
For example::
|
||||
|
||||
assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.toHexString()`:
|
||||
|
||||
Return the hexadecimal ``"#RRGGBB"`` string representation of this color.
|
||||
|
||||
Note that the alpha component is completely ignored for hexadecimal
|
||||
string representations!
|
||||
|
||||
For example::
|
||||
|
||||
assert( Color.whiteColor().toHexString() == "#FFFFFF" );
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.asRGB()`:
|
||||
|
||||
Return the RGB (red, green, blue, alpha) components of this color as an
|
||||
object with ``r``, ``g``, ``b``, and ``a`` properties that have
|
||||
values between ``0.0`` and ``1.0``.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.asHSL()`:
|
||||
|
||||
Return the HSL (hue, saturation, lightness, alpha) components of this
|
||||
color as an object with ``h``, ``s``, ``l`` and ``a`` properties
|
||||
that have values between ``0.0`` and ``1.0``.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.asHSV()`:
|
||||
|
||||
Return the HSV (hue, saturation, value, alpha) components of this
|
||||
color as an object with ``h``, ``s``, ``v`` and ``a`` properties
|
||||
that have values between ``0.0`` and ``1.0``.
|
||||
|
||||
|
||||
:mochidef:`Color.blackColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 0, 0
|
||||
(#000000).
|
||||
|
||||
|
||||
:mochidef:`Color.blueColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 0, 1
|
||||
(#0000ff).
|
||||
|
||||
|
||||
:mochidef:`Color.brownColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0.6, 0.4, 0.2
|
||||
(#996633).
|
||||
|
||||
|
||||
:mochidef:`Color.cyanColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 1, 1
|
||||
(#00ffff).
|
||||
|
||||
|
||||
:mochidef:`Color.darkGrayColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1/3, 1/3, 1/3
|
||||
(#555555).
|
||||
|
||||
|
||||
:mochidef:`Color.grayColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0.5, 0.5, 0.5
|
||||
(#808080).
|
||||
|
||||
|
||||
:mochidef:`Color.greenColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 1, 0.
|
||||
(#00ff00).
|
||||
|
||||
|
||||
:mochidef:`Color.lightGrayColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 2/3, 2/3, 2/3
|
||||
(#aaaaaa).
|
||||
|
||||
|
||||
:mochidef:`Color.magentaColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 0, 1
|
||||
(#ff00ff).
|
||||
|
||||
|
||||
:mochidef:`Color.orangeColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 0.5, 0
|
||||
(#ff8000).
|
||||
|
||||
|
||||
:mochidef:`Color.purpleColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0.5, 0, 0.5
|
||||
(#800080).
|
||||
|
||||
|
||||
:mochidef:`Color.redColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 0, 0
|
||||
(#ff0000).
|
||||
|
||||
|
||||
:mochidef:`Color.whiteColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 1, 1
|
||||
(#ffffff).
|
||||
|
||||
|
||||
:mochidef:`Color.yellowColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 1, 0
|
||||
(#ffff00).
|
||||
|
||||
|
||||
:mochidef:`Color.transparentColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object that is completely transparent
|
||||
(has alpha component of 0).
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`clampColorComponent(num, scale)`:
|
||||
|
||||
Returns ``num * scale`` clamped between ``0`` and ``scale``.
|
||||
|
||||
:mochiref:`clampColorComponent` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`hslToRGB(hue, saturation, lightness, alpha)`:
|
||||
|
||||
Computes RGB values from the provided HSL values. The return value is a
|
||||
mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})`.
|
||||
|
||||
:mochiref:`hslToRGB` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`hsvToRGB(hue, saturation, value, alpha)`:
|
||||
|
||||
Computes RGB values from the provided HSV values. The return value is a
|
||||
mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`hsvToRGB({h: hue, s: saturation, v: value, a: alpha})`.
|
||||
|
||||
:mochiref:`hsvToRGB` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`toColorPart(num)`:
|
||||
|
||||
Convert num to a zero padded hexadecimal digit for use in a hexadecimal
|
||||
color string. Num should be an integer between ``0`` and ``255``.
|
||||
|
||||
:mochiref:`toColorPart` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`rgbToHSL(red, green, blue, alpha)`:
|
||||
|
||||
Computes HSL values based on the provided RGB values. The return value is
|
||||
a mapping with ``"h"``, ``"s"``, ``"l"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`rgbToHSL({r: red, g: green, b: blue, a: alpha})`.
|
||||
|
||||
:mochiref:`rgbToHSL` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`rgbToHSV(red, green, blue, alpha)`:
|
||||
|
||||
Computes HSV values based on the provided RGB values. The return value is
|
||||
a mapping with ``"h"``, ``"s"``, ``"v"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`rgbToHSV({r: red, g: green, b: blue, a: alpha})`.
|
||||
|
||||
:mochiref:`rgbToHSV` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] Application Kit Reference - NSColor: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html
|
||||
.. [2] SVG 1.0 color keywords: http://www.w3.org/TR/SVG/types.html#ColorKeywords
|
||||
.. [3] W3C CSS3 Color Module: http://www.w3.org/TR/css3-color/#svg-color
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
@@ -1,782 +0,0 @@
|
||||
.. title:: MochiKit.DOM - painless DOM manipulation API
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.DOM - painless DOM manipulation API
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
// put that in your document.createElement and smoke it!
|
||||
swapDOM(oldTable, newTable);
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
As you probably know, the DOM APIs are some of the most painful Java-inspired
|
||||
APIs you'll run across from a highly dynamic language. Don't worry about that
|
||||
though, because they provide a reasonable basis to build something that
|
||||
sucks a lot less.
|
||||
|
||||
MochiKit.DOM takes much of its inspiration from Nevow's [1]_ stan [2]_.
|
||||
This means you choose a tag, give it some attributes, then stuff it full
|
||||
of *whatever objects you want*. MochiKit.DOM isn't stupid, it knows that
|
||||
a string should be a text node, and that you want functions to be called,
|
||||
and that ``Array``-like objects should be expanded, and stupid ``null`` values
|
||||
should be skipped.
|
||||
|
||||
Hell, it will let you return strings from functions, and use iterators from
|
||||
:mochiref:`MochiKit.Iter`. If that's not enough, just teach it new tricks with
|
||||
:mochiref:`registerDOMConverter`. If you have never used an API like this for
|
||||
creating DOM elements, you've been wasting your damn time. Get with it!
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
- :mochiref:`MochiKit.Base`
|
||||
- :mochiref:`MochiKit.Iter`
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
DOM Coercion Rules
|
||||
------------------
|
||||
|
||||
In order of precedence, :mochiref:`createDOM` coerces given arguments to DOM
|
||||
nodes using the following rules:
|
||||
|
||||
1. Functions are called with a ``this`` of the parent
|
||||
node and their return value is subject to the
|
||||
following rules (even this one).
|
||||
2. ``undefined`` and ``null`` are ignored.
|
||||
3. Iterables (see :mochiref:`MochiKit.Iter`) are flattened
|
||||
(as if they were passed in-line as nodes) and each
|
||||
return value is subject to all of these rules.
|
||||
4. Values that look like DOM nodes (objects with a
|
||||
``.nodeType > 0``) are ``.appendChild``'ed to the created
|
||||
DOM fragment.
|
||||
5. Strings are wrapped up with ``document.createTextNode``
|
||||
6. Objects that are not strings are run through the ``domConverters``
|
||||
:mochiref:`MochiKit.Base.AdapterRegistry`
|
||||
(see :mochiref:`registerDOMConverter`).
|
||||
The value returned by the adapter is subject to these same rules (e.g.
|
||||
adapters are allowed to return a string, which will be coerced into a
|
||||
text node).
|
||||
7. If no adapter is available, ``.toString()`` is used to create a text node.
|
||||
|
||||
|
||||
Creating DOM Element Trees
|
||||
--------------------------
|
||||
|
||||
:mochiref:`createDOM` provides you with an excellent facility for creating DOM trees
|
||||
that is easy on the wrists. One of the best ways to understand how to use
|
||||
it is to take a look at an example::
|
||||
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
|
||||
|
||||
This will create a table with the following visual layout (if it
|
||||
were inserted into the document DOM):
|
||||
|
||||
+--------+--------+--------+
|
||||
| head1 | head2 | head3 |
|
||||
+========+========+========+
|
||||
| dataA1 | dataA2 | dataA3 |
|
||||
+--------+--------+--------+
|
||||
| dataB1 | dataB2 | dataB3 |
|
||||
+--------+--------+--------+
|
||||
| foot1 | foot2 | foot3 |
|
||||
+--------+--------+--------+
|
||||
|
||||
Corresponding to the following HTML::
|
||||
|
||||
<table class="prettytable">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>head1</td>
|
||||
<td>head2</td>
|
||||
<td>head3</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>foot1</td>
|
||||
<td>foot2</td>
|
||||
<td>foot3</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>dataA1</td>
|
||||
<td>dataA2</td>
|
||||
<td>dataA3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dataB1</td>
|
||||
<td>dataB2</td>
|
||||
<td>dataB3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
DOM Context
|
||||
-----------
|
||||
|
||||
In order to prevent having to pass a ``window`` and/or ``document``
|
||||
variable to every MochiKit.DOM function (e.g. when working with a
|
||||
child window), MochiKit.DOM maintains a context variable for each
|
||||
of them. They are managed with the :mochiref:`withWindow` and
|
||||
:mochiref:`withDocument` functions, and can be acquired with
|
||||
:mochiref:`currentWindow()` and :mochiref:`currentDocument()`
|
||||
|
||||
For example, if you are creating DOM nodes in a child window, you
|
||||
could do something like this::
|
||||
|
||||
withWindow(child, function () {
|
||||
var doc = currentDocument();
|
||||
appendChildNodes(doc.body, H1(null, "This is in the child!"));
|
||||
});
|
||||
|
||||
Note that :mochiref:`withWindow(win, ...)` also implies
|
||||
:mochiref:`withDocument(win.document, ...)`.
|
||||
|
||||
|
||||
Element Visibility
|
||||
------------------
|
||||
|
||||
The :mochiref:`hideElement` and :mochiref:`showElement` functions are
|
||||
provided as a convenience, but only work for elements that are
|
||||
``display: block``. For a general solution to showing, hiding, and checking
|
||||
the explicit visibility of elements, we recommend using a solution that
|
||||
involves a little CSS. Here's an example::
|
||||
|
||||
<style type="text/css">
|
||||
.invisible { display: none; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function toggleVisible(elem) {
|
||||
toggleElementClass("invisible", elem);
|
||||
}
|
||||
|
||||
function makeVisible(elem) {
|
||||
removeElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function makeInvisible(elem) {
|
||||
addElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function isVisible(elem) {
|
||||
// you may also want to check for
|
||||
// getElement(elem).style.display == "none"
|
||||
return !hasElementClass(elem, "invisible");
|
||||
};
|
||||
</script>
|
||||
|
||||
MochiKit doesn't ship with such a solution, because there is no reliable and
|
||||
portable method for adding CSS rules on the fly with JavaScript.
|
||||
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`$(id[, ...])`:
|
||||
|
||||
An alias for :mochiref:`getElement(id[, ...])`
|
||||
|
||||
|
||||
:mochidef:`addElementClass(element, className)`:
|
||||
|
||||
Ensure that the given ``element`` has ``className`` set as part of its
|
||||
class attribute. This will not disturb other class names.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`addLoadEvent(func)`:
|
||||
|
||||
Note that :mochiref:`addLoadEvent` can not be used in combination with
|
||||
:mochiref:`MochiKit.Signal` if the ``onload`` event is connected.
|
||||
Once an event is connected with :mochiref:`MochiKit.Signal`, no other APIs
|
||||
may be used for that same event.
|
||||
|
||||
This will stack ``window.onload`` functions on top of each other.
|
||||
Each function added will be called after ``onload`` in the
|
||||
order that they were added.
|
||||
|
||||
|
||||
:mochidef:`addToCallStack(target, path, func[, once])`:
|
||||
|
||||
Note that :mochiref:`addToCallStack` is not compatible with
|
||||
:mochiref:`MochiKit.Signal`. Once an event is connected with
|
||||
:mochiref:`MochiKit.Signal`, no other APIs may be used for that same event.
|
||||
|
||||
Set the property ``path`` of ``target`` to a function that calls the
|
||||
existing function at that property (if any), then calls ``func``.
|
||||
|
||||
If ``target[path]()`` returns exactly ``false``, then ``func`` will
|
||||
not be called.
|
||||
|
||||
If ``once`` is ``true``, then ``target[path]`` is set to ``null`` after
|
||||
the function call stack has completed.
|
||||
|
||||
If called several times for the same ``target[path]``, it will create
|
||||
a stack of functions (instead of just a pair).
|
||||
|
||||
|
||||
:mochidef:`appendChildNodes(node[, childNode[, ...]])`:
|
||||
|
||||
Append children to a DOM element using the `DOM Coercion Rules`_.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to add children to
|
||||
(if a string is given, :mochiref:`getElement(node)`
|
||||
will be used to locate the node)
|
||||
|
||||
``childNode``...:
|
||||
All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
`DOM Coercion Rules`_.
|
||||
|
||||
*returns*:
|
||||
The given DOM element
|
||||
|
||||
|
||||
:mochidef:`computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)`:
|
||||
|
||||
Looks up a CSS property for the given element. The element can be
|
||||
specified as either a string with the element's ID or the element
|
||||
object itself.
|
||||
|
||||
|
||||
:mochidef:`createDOM(name[, attrs[, node[, ...]]])`:
|
||||
|
||||
Create a DOM fragment in a really convenient manner, much like
|
||||
Nevow`s [1]_ stan [2]_.
|
||||
|
||||
Partially applied versions of this function for common tags are
|
||||
available as aliases:
|
||||
|
||||
- ``A``
|
||||
- ``BUTTON``
|
||||
- ``BR``
|
||||
- ``CANVAS``
|
||||
- ``DIV``
|
||||
- ``FIELDSET``
|
||||
- ``FORM``
|
||||
- ``H1``
|
||||
- ``H2``
|
||||
- ``H3``
|
||||
- ``HR``
|
||||
- ``IMG``
|
||||
- ``INPUT``
|
||||
- ``LABEL``
|
||||
- ``LEGEND``
|
||||
- ``LI``
|
||||
- ``OL``
|
||||
- ``OPTGROUP``
|
||||
- ``OPTION``
|
||||
- ``P``
|
||||
- ``PRE``
|
||||
- ``SELECT``
|
||||
- ``SPAN``
|
||||
- ``STRONG``
|
||||
- ``TABLE``
|
||||
- ``TBODY``
|
||||
- ``TD``
|
||||
- ``TEXTAREA``
|
||||
- ``TFOOT``
|
||||
- ``TH``
|
||||
- ``THEAD``
|
||||
- ``TR``
|
||||
- ``TT``
|
||||
- ``UL``
|
||||
|
||||
See `Creating DOM Element Trees`_ for a comprehensive example.
|
||||
|
||||
``name``:
|
||||
The kind of fragment to create (e.g. 'span'), such as you would
|
||||
pass to ``document.createElement``.
|
||||
|
||||
``attrs``:
|
||||
An object whose properties will be used as the attributes
|
||||
(e.g. ``{'style': 'display:block'}``), or ``null`` if no
|
||||
attributes need to be set.
|
||||
|
||||
See :mochiref:`updateNodeAttributes` for more information.
|
||||
|
||||
For convenience, if ``attrs`` is a string, ``null`` is used
|
||||
and the string will be considered the first ``node``.
|
||||
|
||||
``node``...:
|
||||
All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
`DOM Coercion Rules`_.
|
||||
|
||||
*returns*:
|
||||
A DOM element
|
||||
|
||||
|
||||
:mochidef:`createDOMFunc(tag[, attrs[, node[, ...]]])`:
|
||||
|
||||
Convenience function to create a partially applied createDOM
|
||||
function. You'd want to use this if you add additional convenience
|
||||
functions for creating tags, or if you find yourself creating
|
||||
a lot of tags with a bunch of the same attributes or contents.
|
||||
|
||||
See :mochiref:`createDOM` for more detailed descriptions of the arguments.
|
||||
|
||||
``tag``:
|
||||
The name of the tag
|
||||
|
||||
``attrs``:
|
||||
Optionally specify the attributes to apply
|
||||
|
||||
``node``...:
|
||||
Optionally specify any children nodes it should have
|
||||
|
||||
*returns*:
|
||||
function that takes additional arguments and calls
|
||||
:mochiref:`createDOM`
|
||||
|
||||
|
||||
:mochidef:`currentDocument()`:
|
||||
|
||||
Return the current ``document`` `DOM Context`_. This will always
|
||||
be the same as the global ``document`` unless :mochiref:`withDocument` or
|
||||
:mochiref:`withWindow` is currently executing.
|
||||
|
||||
|
||||
:mochidef:`currentWindow()`:
|
||||
|
||||
Return the current ``window`` `DOM Context`_. This will always
|
||||
be the same as the global ``window`` unless :mochiref:`withWindow` is
|
||||
currently executing.
|
||||
|
||||
|
||||
:mochidef:`elementDimensions(element)`:
|
||||
|
||||
Return the absolute pixel width and height of ``element`` as an object with
|
||||
``w`` and ``h`` properties, or ``undefined`` if ``element`` is not in the
|
||||
document. ``element`` may be specified as a string to be looked up with
|
||||
:mochiref:`getElement`, a DOM element, or trivially as an object with
|
||||
``w`` and/or ``h`` properties.
|
||||
|
||||
|
||||
:mochidef:`elementPosition(element[, relativeTo={x: 0, y: 0}])`:
|
||||
|
||||
Return the absolute pixel position of ``element`` in the document as an
|
||||
object with ``x`` and ``y`` properties, or ``undefined`` if ``element``
|
||||
is not in the document. ``element`` may be specified as a string to
|
||||
be looked up with :mochiref:`getElement`, a DOM element, or trivially
|
||||
as an object with ``x`` and/or ``y`` properties.
|
||||
|
||||
If ``relativeTo`` is given, then its coordinates are subtracted from
|
||||
the absolute position of ``element``, e.g.::
|
||||
|
||||
var elemPos = elementPosition(elem);
|
||||
var anotherElemPos = elementPosition(anotherElem);
|
||||
var relPos = elementPosition(elem, anotherElem);
|
||||
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
|
||||
assert( relPos.y == (elemPos.y - anotherElemPos.y) );
|
||||
|
||||
``relativeTo`` may be specified as a string to be looked up with
|
||||
:mochiref:`getElement`, a DOM element, or trivially as an object
|
||||
with ``x`` and/or ``y`` properties.
|
||||
|
||||
|
||||
:mochidef:`emitHTML(dom[, lst])`:
|
||||
|
||||
Convert a DOM tree to an ``Array`` of HTML string fragments
|
||||
|
||||
You probably want to use :mochiref:`toHTML` instead.
|
||||
|
||||
|
||||
:mochidef:`escapeHTML(s)`:
|
||||
|
||||
Make a string safe for HTML, converting the usual suspects (lt,
|
||||
gt, quot, apos, amp)
|
||||
|
||||
|
||||
:mochidef:`focusOnLoad(element)`:
|
||||
|
||||
Add an onload event to focus the given element
|
||||
|
||||
|
||||
:mochidef:`formContents(elem)`:
|
||||
|
||||
Search the DOM tree, starting at ``elem``, for any elements with a
|
||||
``name`` and ``value`` attribute. Return a 2-element ``Array`` of
|
||||
``names`` and ``values`` suitable for use with
|
||||
:mochiref:`MochiKit.Base.queryString`.
|
||||
|
||||
|
||||
:mochidef:`getElement(id[, ...])`:
|
||||
|
||||
A small quick little function to encapsulate the ``getElementById``
|
||||
method. It includes a check to ensure we can use that method.
|
||||
|
||||
If the id isn't a string, it will be returned as-is.
|
||||
|
||||
Also available as :mochiref:`$(...)` for convenience and compatibility with
|
||||
other JavaScript frameworks.
|
||||
|
||||
If multiple arguments are given, an ``Array`` will be returned.
|
||||
|
||||
|
||||
:mochidef:`getElementsByTagAndClassName(tagName, className, parent=document)`:
|
||||
|
||||
Returns an array of elements in ``parent`` that match the tag name
|
||||
and class name provided. If ``parent`` is a string, it will be looked
|
||||
up with :mochiref:`getElement`.
|
||||
|
||||
If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
|
||||
for the matching class.
|
||||
|
||||
If ``className`` is ``null``, all elements matching the provided tag are
|
||||
returned.
|
||||
|
||||
|
||||
:mochidef:`getNodeAttribute(node, attr)`:
|
||||
|
||||
Get the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return ``null`` on exception).
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``attr``:
|
||||
The name of the attribute
|
||||
|
||||
Note that it will do the right thing for IE, so don't do
|
||||
the ``class`` -> ``className`` hack yourself.
|
||||
|
||||
*returns*:
|
||||
The attribute's value, or ``null``
|
||||
|
||||
|
||||
:mochidef:`getViewportDimensions()`:
|
||||
|
||||
Return the pixel width and height of the viewport as an object with ``w``
|
||||
and ``h`` properties. ``element`` is looked up with
|
||||
:mochiref:`getElement`, so string identifiers are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`hasElementClass(element, className[, ...])`:
|
||||
|
||||
Return ``true`` if ``className`` is found on the ``element``.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`hideElement(element, ...)`:
|
||||
|
||||
Partial form of :mochiref:`setDisplayForElement`, specifically::
|
||||
|
||||
partial(setDisplayForElement, "none")
|
||||
|
||||
For information about the caveats of using a ``style.display`` based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
`Element Visibility`_.
|
||||
|
||||
|
||||
:mochidef:`registerDOMConverter(name, check, wrap[, override])`:
|
||||
|
||||
Register an adapter to convert objects that match ``check(obj, ctx)``
|
||||
to a DOM element, or something that can be converted to a DOM
|
||||
element (i.e. number, bool, string, function, iterable).
|
||||
|
||||
|
||||
:mochidef:`removeElement(node)`:
|
||||
|
||||
Remove and return ``node`` from a DOM tree. This is technically
|
||||
just a convenience for :mochiref:`swapDOM(node, null)`.
|
||||
|
||||
``node``:
|
||||
the DOM element (or string id of one) to be removed
|
||||
|
||||
*returns*
|
||||
The removed element
|
||||
|
||||
|
||||
:mochidef:`removeElementClass(element, className)`:
|
||||
|
||||
Ensure that the given ``element`` does not have ``className`` set as part
|
||||
of its class attribute. This will not disturb other class names.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`replaceChildNodes(node[, childNode[, ...]])`:
|
||||
|
||||
Remove all children from the given DOM element, then append any given
|
||||
childNodes to it (by calling :mochiref:`appendChildNodes`).
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to add children to
|
||||
(if a string is given, :mochiref:`getElement(node)`
|
||||
will be used to locate the node)
|
||||
|
||||
``childNode``...:
|
||||
All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
`DOM Coercion Rules`_.
|
||||
|
||||
*returns*:
|
||||
The given DOM element
|
||||
|
||||
|
||||
:mochidef:`scrapeText(node[, asArray=false])`:
|
||||
|
||||
Walk a DOM tree in-order and scrape all of the text out of it as a
|
||||
``string``.
|
||||
|
||||
If ``asArray`` is ``true``, then an ``Array`` will be returned with
|
||||
each individual text node. These two are equivalent::
|
||||
|
||||
assert( scrapeText(node) == scrapeText(node, true).join("") );
|
||||
|
||||
|
||||
:mochidef:`setDisplayForElement(display, element[, ...])`:
|
||||
|
||||
Change the ``style.display`` for the given element(s). Usually
|
||||
used as the partial forms:
|
||||
|
||||
- :mochiref:`showElement(element, ...)`
|
||||
- :mochiref:`hideElement(element, ...)`
|
||||
|
||||
Elements are looked up with :mochiref:`getElement`, so string identifiers
|
||||
are acceptable.
|
||||
|
||||
For information about the caveats of using a ``style.display`` based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
`Element Visibility`_.
|
||||
|
||||
|
||||
:mochidef:`setElementClass(element, className)`:
|
||||
|
||||
Set the entire class attribute of ``element`` to ``className``.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`setElementDimensions(element, dimensions[, units='px'])`:
|
||||
|
||||
Sets the dimensions of ``element`` in the document from an
|
||||
object with ``w`` and ``h`` properties.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``dimensions``:
|
||||
An object with ``w`` and ``h`` properties
|
||||
|
||||
``units``:
|
||||
Optionally set the units to use, default is ``px``
|
||||
|
||||
|
||||
:mochidef:`setElementPosition(element, position[, units='px'])`:
|
||||
|
||||
Sets the absolute position of ``element`` in the document from an
|
||||
object with ``x`` and ``y`` properties.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``position``:
|
||||
An object with ``x`` and ``y`` properties
|
||||
|
||||
``units``:
|
||||
Optionally set the units to use, default is ``px``
|
||||
|
||||
|
||||
:mochidef:`setNodeAttribute(node, attr, value)`:
|
||||
|
||||
Set the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return null on exception). If
|
||||
setting more than one attribute, you should use
|
||||
:mochiref:`updateNodeAttributes`.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``attr``:
|
||||
The name of the attribute
|
||||
|
||||
Note that it will do the right thing for IE, so don't do
|
||||
the ``class`` -> ``className`` hack yourself.
|
||||
|
||||
``value``:
|
||||
The value of the attribute, may be an object to be merged
|
||||
(e.g. for setting style).
|
||||
|
||||
*returns*:
|
||||
The given DOM element or ``null`` on failure
|
||||
|
||||
|
||||
:mochidef:`setOpacity(element, opacity)`:
|
||||
|
||||
Sets ``opacity`` for ``element``. Valid ``opacity`` values range from 0
|
||||
(invisible) to 1 (opaque). ``element`` is looked up with
|
||||
:mochiref:`getElement`, so string identifiers are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`showElement(element, ...)`:
|
||||
|
||||
Partial form of :mochiref:`setDisplayForElement`, specifically::
|
||||
|
||||
partial(setDisplayForElement, "block")
|
||||
|
||||
For information about the caveats of using a ``style.display`` based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
`Element Visibility`_.
|
||||
|
||||
|
||||
:mochidef:`swapDOM(dest, src)`:
|
||||
|
||||
Replace ``dest`` in a DOM tree with ``src``, returning ``src``.
|
||||
|
||||
``dest``:
|
||||
a DOM element (or string id of one) to be replaced
|
||||
|
||||
``src``:
|
||||
the DOM element (or string id of one) to replace it with, or
|
||||
``null`` if ``dest`` is to be removed (replaced with nothing).
|
||||
|
||||
*returns*:
|
||||
a DOM element (``src``)
|
||||
|
||||
|
||||
:mochidef:`swapElementClass(element, fromClass, toClass)`:
|
||||
|
||||
If ``fromClass`` is set on ``element``, replace it with ``toClass``.
|
||||
This will not disturb other classes on that element.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`toggleElementClass(className[, element[, ...]])`:
|
||||
|
||||
Toggle the presence of a given ``className`` in the class attribute
|
||||
of all given elements. All elements will be looked up with
|
||||
:mochiref:`getElement`, so string identifiers are acceptable.
|
||||
|
||||
|
||||
:mochidef:`toHTML(dom)`:
|
||||
|
||||
Convert a DOM tree to a HTML string using :mochiref:`emitHTML`
|
||||
|
||||
|
||||
:mochidef:`updateNodeAttributes(node, attrs)`:
|
||||
|
||||
Update the attributes of a DOM element from a given object.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``attrs``:
|
||||
An object whose properties will be used to set the attributes
|
||||
(e.g. ``{'class': 'invisible'}``), or ``null`` if no
|
||||
attributes need to be set. If an object is given for the
|
||||
attribute value (e.g. ``{'style': {'display': 'block'}}``)
|
||||
then :mochiref:`MochiKit.Base.updatetree` will be used to set that
|
||||
attribute.
|
||||
|
||||
Note that it will do the right thing for IE, so don't do
|
||||
the ``class`` -> ``className`` hack yourself, and it deals with
|
||||
setting "on..." event handlers correctly.
|
||||
|
||||
*returns*:
|
||||
The given DOM element
|
||||
|
||||
|
||||
:mochidef:`withWindow(win, func)`:
|
||||
|
||||
Call ``func`` with the ``window`` `DOM Context`_ set to ``win`` and
|
||||
the ``document`` `DOM Context`_ set to ``win.document``. When
|
||||
``func()`` returns or throws an error, the `DOM Context`_ will be
|
||||
restored to its previous state.
|
||||
|
||||
The return value of ``func()`` is returned by this function.
|
||||
|
||||
|
||||
:mochidef:`withDocument(doc, func)`:
|
||||
|
||||
Call ``func`` with the ``doc`` `DOM Context`_ set to ``doc``.
|
||||
When ``func()`` returns or throws an error, the `DOM Context`_
|
||||
will be restored to its previous state.
|
||||
|
||||
The return value of ``func()`` is returned by this function.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] Nevow, a web application construction kit for Python: http://nevow.com/
|
||||
.. [2] nevow.stan is a domain specific language for Python
|
||||
(read as "crazy getitem/call overloading abuse") that Donovan and I
|
||||
schemed up at PyCon 2003 at this super ninja Python/C++ programmer's
|
||||
(David Abrahams) hotel room. Donovan later inflicted this upon the
|
||||
masses in Nevow. Check out the Divmod project page for some
|
||||
examples: http://nevow.com/Nevow2004Tutorial.html
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user