summaryrefslogtreecommitdiff
path: root/javascript/jsapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'javascript/jsapi.c')
-rw-r--r--javascript/jsapi.c164
1 files changed, 143 insertions, 21 deletions
diff --git a/javascript/jsapi.c b/javascript/jsapi.c
index bec565316..ef34371d1 100644
--- a/javascript/jsapi.c
+++ b/javascript/jsapi.c
@@ -32,14 +32,16 @@ void js_initialise(void)
/* Create a JS runtime. */
#if JS_VERSION >= 180
- JS_SetCStringsAreUTF8(); /* we prefer our runtime to be utf-8 */
+ JS_SetCStringsAreUTF8(); /* we prefer our runtime to be utf-8 */
#endif
rt = JS_NewRuntime(8L * 1024L * 1024L);
JSLOG("New runtime handle %p", rt);
- /* register script content handler */
- javascript_init();
+ if (rt != NULL) {
+ /* register script content handler */
+ javascript_init();
+ }
}
void js_finalise(void)
@@ -97,7 +99,7 @@ void js_destroycontext(jscontext *ctx)
*
* This performs the following actions
* 1. constructs a new global object by initialising a window class
- * 2. Instantiate the global a window object
+ * 2. Instantiate the global a window object
*/
jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
{
@@ -116,7 +118,7 @@ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
}
window = jsapi_new_Window(cx, window_proto, NULL, win_priv, doc_priv);
-
+
return (jsobject *)window;
}
@@ -139,9 +141,9 @@ bool js_exec(jscontext *ctx, const char *txt, size_t txtlen)
return false;
}
- if (JS_EvaluateScript(cx,
- JS_GetGlobalObject(cx),
- txt, txtlen,
+ if (JS_EvaluateScript(cx,
+ JS_GetGlobalObject(cx),
+ txt, txtlen,
"<head>", 0, &rval) == JS_TRUE) {
return true;
@@ -153,7 +155,7 @@ bool js_exec(jscontext *ctx, const char *txt, size_t txtlen)
dom_exception _dom_event_create(dom_document *doc, dom_event **evt);
#define dom_event_create(d, e) _dom_event_create((dom_document *)(d), (dom_event **) (e))
-bool js_fire_event(jscontext *ctx, const char *type, void *target)
+bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node *target)
{
JSContext *cx = (JSContext *)ctx;
dom_node *node = target;
@@ -165,18 +167,23 @@ bool js_fire_event(jscontext *ctx, const char *type, void *target)
dom_event *event;
dom_string *type_dom;
+ if (cx == NULL) {
+ return false;
+ }
+
if (node == NULL) {
- /* deliver to window */
- if (cx == NULL) {
- return false;
- }
+ /* deliver manufactured event to window */
+ JSLOG("Dispatching event %s at window", type);
- exc = dom_string_create((unsigned char*)type, strlen(type), &type_dom);
+ /* create and initialise and event object */
+ exc = dom_string_create((unsigned char*)type,
+ strlen(type),
+ &type_dom);
if (exc != DOM_NO_ERR) {
return false;
}
- exc = dom_event_create(-1, &event);
+ exc = dom_event_create(doc, &event);
if (exc != DOM_NO_ERR) {
return false;
}
@@ -192,18 +199,133 @@ bool js_fire_event(jscontext *ctx, const char *type, void *target)
return false;
}
+ /* dispatch event at the window object */
argv[0] = OBJECT_TO_JSVAL(jsevent);
- ret = JS_CallFunctionName(cx,
- JS_GetGlobalObject(cx),
- "dispatchEvent",
- 1,
- argv,
+ ret = JS_CallFunctionName(cx,
+ JS_GetGlobalObject(cx),
+ "dispatchEvent",
+ 1,
+ argv,
&rval);
- }
+ } else {
+ JSLOG("Dispatching event %s at %p", type, node);
+
+ /* create and initialise and event object */
+ exc = dom_string_create((unsigned char*)type,
+ strlen(type),
+ &type_dom);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ exc = dom_event_create(doc, &event);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ exc = dom_event_init(event, type_dom, true, true);
+ dom_string_unref(type_dom);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ dom_event_target_dispatch_event(node, event, &ret);
+
+ }
if (ret == JS_TRUE) {
return true;
}
return false;
}
+
+struct js_dom_event_private {
+ JSContext *cx; /* javascript context */
+ jsval funcval; /* javascript function to call */
+ struct dom_node *node; /* dom node event listening on */
+ dom_string *type; /* event type */
+ dom_event_listener *listener; /* the listener containing this */
+};
+
+static void
+js_dom_event_listener(struct dom_event *event, void *pw)
+{
+ struct js_dom_event_private *private = pw;
+ jsval event_argv[1];
+ jsval event_rval;
+ JSObject *jsevent;
+
+ JSLOG("WOOT dom event with %p", private);
+
+ if (!JSVAL_IS_VOID(private->funcval)) {
+ jsevent = jsapi_new_Event(private->cx, NULL, NULL, event);
+ if (jsevent != NULL) {
+
+ /* dispatch event at the window object */
+ event_argv[0] = OBJECT_TO_JSVAL(jsevent);
+
+ JS_CallFunctionValue(private->cx,
+ NULL,
+ private->funcval,
+ 1,
+ event_argv,
+ &event_rval);
+ }
+ }
+}
+
+/* add a listener to a dom node
+ *
+ * 1. Create a dom_event_listener From a handle_event function pointer
+ * and a private word In a document context
+ *
+ * 2. Register for your events on a target (dom nodes are targets)
+ * dom_event_target_add_event_listener(node, evt_name, listener,
+ * capture_or_not)
+ *
+ */
+
+bool
+js_dom_event_add_listener(jscontext *ctx,
+ struct dom_document *document,
+ struct dom_node *node,
+ struct dom_string *event_type_dom,
+ void *js_funcval)
+{
+ JSContext *cx = (JSContext *)ctx;
+ dom_exception exc;
+ struct js_dom_event_private *private;
+
+ private = malloc(sizeof(struct js_dom_event_private));
+ if (private == NULL) {
+ return false;
+ }
+
+ exc = dom_event_listener_create(document,
+ js_dom_event_listener,
+ private,
+ &private->listener);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ private->cx = cx;
+ private->funcval = *(jsval *)js_funcval;
+ private->node = node;
+ private->type = event_type_dom;
+
+ JSLOG("adding %p to listener", private);
+
+ JSAPI_ADD_VALUE_ROOT(cx, &private->funcval);
+ exc = dom_event_target_add_event_listener(private->node,
+ private->type,
+ private->listener,
+ true);
+ if (exc != DOM_NO_ERR) {
+ JSLOG("failed to add listener");
+ JSAPI_REMOVE_VALUE_ROOT(cx, &private->funcval);
+ }
+
+ return true;
+}