diff options
Diffstat (limited to 'javascript/jsapi.c')
-rw-r--r-- | javascript/jsapi.c | 164 |
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; +} |