make events work on elements

This commit is contained in:
Vincent Sanders 2012-12-04 18:01:11 +00:00
parent 878fe3e68c
commit 897acff532
5 changed files with 400 additions and 29 deletions

View File

@ -26,6 +26,10 @@
typedef struct jscontext jscontext;
typedef struct jsobject jsobject;
struct dom_document;
struct dom_node;
struct dom_string;
/** Initialise javascript interpreter */
void js_initialise(void);
@ -51,10 +55,16 @@ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv);
/* execute some javascript in a context */
bool js_exec(jscontext *ctx, const char *txt, size_t txtlen);
struct dom_document;
struct dom_node;
/* fire an event at a dom node */
bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target);
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);
#endif /* _NETSURF_JAVASCRIPT_JS_H_ */

View File

@ -32,7 +32,7 @@ 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);
@ -97,7 +97,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 +116,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 +139,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;
@ -174,8 +174,8 @@ bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node
JSLOG("Dispatching event %s at window", type);
/* create and initialise and event object */
exc = dom_string_create((unsigned char*)type,
strlen(type),
exc = dom_string_create((unsigned char*)type,
strlen(type),
&type_dom);
if (exc != DOM_NO_ERR) {
return false;
@ -200,18 +200,18 @@ bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node
/* 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),
exc = dom_string_create((unsigned char*)type,
strlen(type),
&type_dom);
if (exc != DOM_NO_ERR) {
return false;
@ -237,3 +237,93 @@ bool js_fire_event(jscontext *ctx, const char *type, dom_document *doc, dom_node
}
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);
JS_AddValueRoot(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");
JS_RemoveValueRoot(cx, &private->funcval);
}
return true;
}

View File

@ -23,7 +23,9 @@ preamble %{
#include "utils/config.h"
#include "utils/log.h"
#include "utils/corestrings.h"
#include "javascript/js.h"
#include "javascript/jsapi.h"
#include "javascript/jsapi/binding.h"
@ -218,24 +220,248 @@ getter childElementCount %{
%}
getter EventHandler %{
JSLOG("propname[%d]=\"%s\"",
JSLOG("propname[%d].name=\"%s\"",
tinyid,
jsclass_properties[tinyid].name);
%}
setter EventHandler %{
JSLOG("propname[%d]=\"%s\"",
tinyid,
dom_string *event_type_dom;
JSLOG("propname[%d].name=\"%s\"",
tinyid,
jsclass_properties[tinyid].name);
/*
1. Create a dom_event_listener From a handle_event function pointer
and a private word In a document context
switch (tinyid) {
case JSAPI_PROP_TINYID_onabort:
event_type_dom = corestring_dom_abort;
break;
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)
case JSAPI_PROP_TINYID_onblur:
event_type_dom = corestring_dom_blur;
break;
*/
case JSAPI_PROP_TINYID_oncancel:
event_type_dom = corestring_dom_cancel;
break;
case JSAPI_PROP_TINYID_oncanplay:
event_type_dom = corestring_dom_canplay;
break;
case JSAPI_PROP_TINYID_oncanplaythrough:
event_type_dom = corestring_dom_canplaythrough;
break;
case JSAPI_PROP_TINYID_onchange:
event_type_dom = corestring_dom_change;
break;
case JSAPI_PROP_TINYID_onclick:
event_type_dom = corestring_dom_click;
break;
case JSAPI_PROP_TINYID_onclose:
event_type_dom = corestring_dom_close;
break;
case JSAPI_PROP_TINYID_oncontextmenu:
event_type_dom = corestring_dom_contextmenu;
break;
case JSAPI_PROP_TINYID_oncuechange:
event_type_dom = corestring_dom_cuechange;
break;
case JSAPI_PROP_TINYID_ondblclick:
event_type_dom = corestring_dom_dblclick;
break;
case JSAPI_PROP_TINYID_ondrag:
event_type_dom = corestring_dom_drag;
break;
case JSAPI_PROP_TINYID_ondragend:
event_type_dom = corestring_dom_dragend;
break;
case JSAPI_PROP_TINYID_ondragenter:
event_type_dom = corestring_dom_dragenter;
break;
case JSAPI_PROP_TINYID_ondragleave:
event_type_dom = corestring_dom_dragleave;
break;
case JSAPI_PROP_TINYID_ondragover:
event_type_dom = corestring_dom_dragover;
break;
case JSAPI_PROP_TINYID_ondragstart:
event_type_dom = corestring_dom_dragstart;
break;
case JSAPI_PROP_TINYID_ondrop:
event_type_dom = corestring_dom_drop;
break;
case JSAPI_PROP_TINYID_ondurationchange:
event_type_dom = corestring_dom_durationchange;
break;
case JSAPI_PROP_TINYID_onemptied:
event_type_dom = corestring_dom_emptied;
break;
case JSAPI_PROP_TINYID_onended:
event_type_dom = corestring_dom_ended;
break;
case JSAPI_PROP_TINYID_onerror:
event_type_dom = corestring_dom_error;
break;
case JSAPI_PROP_TINYID_onfocus:
event_type_dom = corestring_dom_focus;
break;
case JSAPI_PROP_TINYID_oninput:
event_type_dom = corestring_dom_input;
break;
case JSAPI_PROP_TINYID_oninvalid:
event_type_dom = corestring_dom_invalid;
break;
case JSAPI_PROP_TINYID_onkeydown:
event_type_dom = corestring_dom_keydown;
break;
case JSAPI_PROP_TINYID_onkeypress:
event_type_dom = corestring_dom_keypress;
break;
case JSAPI_PROP_TINYID_onkeyup:
event_type_dom = corestring_dom_keyup;
break;
case JSAPI_PROP_TINYID_onload:
event_type_dom = corestring_dom_load;
break;
case JSAPI_PROP_TINYID_onloadeddata:
event_type_dom = corestring_dom_loadeddata;
break;
case JSAPI_PROP_TINYID_onloadedmetadata:
event_type_dom = corestring_dom_loadedmetadata;
break;
case JSAPI_PROP_TINYID_onloadstart:
event_type_dom = corestring_dom_loadstart;
break;
case JSAPI_PROP_TINYID_onmousedown:
event_type_dom = corestring_dom_mousedown;
break;
case JSAPI_PROP_TINYID_onmousemove:
event_type_dom = corestring_dom_mousemove;
break;
case JSAPI_PROP_TINYID_onmouseout:
event_type_dom = corestring_dom_mouseout;
break;
case JSAPI_PROP_TINYID_onmouseover:
event_type_dom = corestring_dom_mouseover;
break;
case JSAPI_PROP_TINYID_onmouseup:
event_type_dom = corestring_dom_mouseup;
break;
case JSAPI_PROP_TINYID_onmousewheel:
event_type_dom = corestring_dom_mousewheel;
break;
case JSAPI_PROP_TINYID_onpause:
event_type_dom = corestring_dom_pause;
break;
case JSAPI_PROP_TINYID_onplay:
event_type_dom = corestring_dom_play;
break;
case JSAPI_PROP_TINYID_onplaying:
event_type_dom = corestring_dom_playing;
break;
case JSAPI_PROP_TINYID_onprogress:
event_type_dom = corestring_dom_progress;
break;
case JSAPI_PROP_TINYID_onratechange:
event_type_dom = corestring_dom_ratechange;
break;
case JSAPI_PROP_TINYID_onreset:
event_type_dom = corestring_dom_reset;
break;
case JSAPI_PROP_TINYID_onscroll:
event_type_dom = corestring_dom_scroll;
break;
case JSAPI_PROP_TINYID_onseeked:
event_type_dom = corestring_dom_seeked;
break;
case JSAPI_PROP_TINYID_onseeking:
event_type_dom = corestring_dom_seeking;
break;
case JSAPI_PROP_TINYID_onselect:
event_type_dom = corestring_dom_select;
break;
case JSAPI_PROP_TINYID_onshow:
event_type_dom = corestring_dom_show;
break;
case JSAPI_PROP_TINYID_onstalled:
event_type_dom = corestring_dom_stalled;
break;
case JSAPI_PROP_TINYID_onsubmit:
event_type_dom = corestring_dom_submit;
break;
case JSAPI_PROP_TINYID_onsuspend:
event_type_dom = corestring_dom_suspend;
break;
case JSAPI_PROP_TINYID_ontimeupdate:
event_type_dom = corestring_dom_timeupdate;
break;
case JSAPI_PROP_TINYID_onvolumechange:
event_type_dom = corestring_dom_volumechange;
break;
case JSAPI_PROP_TINYID_onwaiting:
event_type_dom = corestring_dom_waiting;
break;
default:
JSLOG("called with unknown tinyid");
return JS_TRUE;
}
js_dom_event_add_listener((struct jscontext *)cx,
private->htmlc->document,
(dom_node *)private->node,
event_type_dom,
vp);
%}

View File

@ -0,0 +1,30 @@
<html>
<head>
<title>alert onclick example</title>
<script type="text/javascript">
function causealert()
{
var txt = document.getElementById("p1").textContent;
alert(txt);
}
</script>
</head>
<body>
<div style="border: 1px solid red">
<p id="p1">First line of paragraph.<br /></p>
</div><br />
<button id="button1" >add another textNode.</button>
<script>
var button = document.getElementById("button1");
button.onclick = causealert;
</script>
</body>
</html>

View File

@ -5,12 +5,15 @@
</head>
<body>
<h1>JavaScript Tests</h1>
<h2>Window</h2>
<ul>
<li><a href="window.lately.html">location</a></li>
<li><a href="window-enumerate.html">enumerate</a></li>
</ul>
<h2>Document write</h2>
<ul>
<li><a href="inline-doc-write-simple.html">Simple document write</a></li>
@ -22,7 +25,9 @@
<li><a href="inline-innerhtml.html">Inline script innerHtml test</a></li>
</ul>
<h2>DOM tests</h2>
<h3>Reference method tests</h3>
<ul>
<li><a href="dom-element-firstElementChild.html">firstElementChild</a></li>
@ -31,24 +36,34 @@
<li><a href="dom-element-childElementCount.html">childElementCount</a></li>
<li><a href="doc-dom2.html">getElementById</a></li>
<li><a href="dom-getElementsByTagName.html">getElementsByTagName</a></li>
</ul>
<h3>Enumeration tests</h3>
<ul>
<li><a href="dom-node-enumerate.html">Node element interface</a></li>
<li><a href="dom-body-enumerate.html">Body element interface</a></li>
<li><a href="dom-document-enumerate.html">Document interface</a></li>
</ul>
<h3>Document element specific</h3>
<ul>
<li><a href="dom-doc-cookie.html">Cookie dispaly (only from server)</a></li>
<li><a href="dom-doc-location.html">location</a></li>
</ul>
<h2>Dom events</h2>
<ul>
<li><a href="event-onload.html">window.onload</a></li>
<li><a href="event-onclick.html">button.onclick</a></li>
</ul>
<h2>Assorted</h2>
<ul>
<li><a href="assorted-log-doc-write.html">console.log and document.write</a></li>
<li><a href="wikipedia-lcm.html">Example from wikipedia</a></li>
</ul>
</body>
</html>