1 /* The SpiderMonkey window object implementation. */
13 #include "ecmascript/spidermonkey/util.h"
15 #include "bfu/dialog.h"
16 #include "cache/cache.h"
17 #include "cookies/cookies.h"
18 #include "dialogs/menu.h"
19 #include "dialogs/status.h"
20 #include "document/html/frames.h"
21 #include "document/document.h"
22 #include "document/forms.h"
23 #include "document/view.h"
24 #include "ecmascript/ecmascript.h"
25 #include "ecmascript/spidermonkey/form.h"
26 #include "intl/gettext/libintl.h"
27 #include "main/select.h"
28 #include "osdep/newwin.h"
29 #include "osdep/sysname.h"
30 #include "protocol/http/http.h"
31 #include "protocol/uri.h"
32 #include "session/history.h"
33 #include "session/location.h"
34 #include "session/session.h"
35 #include "session/task.h"
36 #include "terminal/tab.h"
37 #include "terminal/terminal.h"
38 #include "util/conv.h"
39 #include "util/memory.h"
40 #include "util/string.h"
41 #include "viewer/text/draw.h"
42 #include "viewer/text/form.h"
43 #include "viewer/text/link.h"
44 #include "viewer/text/vs.h"
47 /* Accordingly to the JS specs, each input type should own object. That'd be a
48 * huge PITA though, however DOM comes to the rescue and defines just a single
49 * HTMLInputElement. The difference could be spotted only by some clever tricky
50 * JS code, but I hope it doesn't matter anywhere. --pasky */
52 static JSBool
input_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
);
53 static JSBool
input_set_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
);
55 static const JSClass input_class
= {
56 "input", /* here, we unleash ourselves */
58 JS_PropertyStub
, JS_PropertyStub
,
59 input_get_property
, input_set_property
,
60 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
67 JSP_INPUT_DEFAULT_CHECKED
,
68 JSP_INPUT_DEFAULT_VALUE
,
81 /* XXX: Some of those are marked readonly just because we can't change them
82 * safely now. Changing default* values would affect all open instances of the
83 * document, leading to a potential security risk. Changing size and type would
84 * require re-rendering the document (TODO), tabindex would require renumbering
85 * of all links and whatnot. --pasky */
86 static const JSPropertySpec input_props
[] = {
87 { "accessKey", JSP_INPUT_ACCESSKEY
, JSPROP_ENUMERATE
},
88 { "alt", JSP_INPUT_ALT
, JSPROP_ENUMERATE
},
89 { "checked", JSP_INPUT_CHECKED
, JSPROP_ENUMERATE
},
90 { "defaultChecked",JSP_INPUT_DEFAULT_CHECKED
,JSPROP_ENUMERATE
},
91 { "defaultValue",JSP_INPUT_DEFAULT_VALUE
,JSPROP_ENUMERATE
},
92 { "disabled", JSP_INPUT_DISABLED
, JSPROP_ENUMERATE
},
93 { "form", JSP_INPUT_FORM
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
94 { "maxLength", JSP_INPUT_MAX_LENGTH
, JSPROP_ENUMERATE
},
95 { "name", JSP_INPUT_NAME
, JSPROP_ENUMERATE
},
96 { "readonly", JSP_INPUT_READONLY
, JSPROP_ENUMERATE
},
97 { "size", JSP_INPUT_SIZE
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
98 { "src", JSP_INPUT_SRC
, JSPROP_ENUMERATE
},
99 { "tabindex", JSP_INPUT_TABINDEX
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
100 { "type", JSP_INPUT_TYPE
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
101 { "value", JSP_INPUT_VALUE
, JSPROP_ENUMERATE
},
105 static JSBool
input_blur(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
106 static JSBool
input_click(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
107 static JSBool
input_focus(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
108 static JSBool
input_select(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
110 static const JSFunctionSpec input_funcs
[] = {
111 { "blur", input_blur
, 0 },
112 { "click", input_click
, 0 },
113 { "focus", input_focus
, 0 },
114 { "select", input_select
, 0 },
119 input_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
121 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
122 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
123 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
124 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
125 struct document_view
*doc_view
= vs
->doc_view
;
126 struct document
*document
= doc_view
->document
;
127 struct form_state
*fs
= JS_GetPrivate(ctx
, obj
);
128 struct form_control
*fc
= find_form_control(document
, fs
);
130 struct link
*link
= NULL
;
133 assert(fc
->form
&& fs
);
135 if (!JSVAL_IS_INT(id
))
138 linknum
= get_form_control_link(document
, fc
);
139 /* Hiddens have no link. */
140 if (linknum
>= 0) link
= &document
->links
[linknum
];
142 undef_to_jsval(ctx
, vp
);
144 switch (JSVAL_TO_INT(id
)) {
145 case JSP_INPUT_ACCESSKEY
:
147 struct string keystr
;
151 init_string(&keystr
);
152 add_accesskey_to_string(&keystr
, link
->accesskey
);
153 string_to_jsval(ctx
, vp
, keystr
.source
);
154 done_string(&keystr
);
158 string_to_jsval(ctx
, vp
, fc
->alt
);
160 case JSP_INPUT_CHECKED
:
161 boolean_to_jsval(ctx
, vp
, fs
->state
);
163 case JSP_INPUT_DEFAULT_CHECKED
:
164 boolean_to_jsval(ctx
, vp
, fc
->default_state
);
166 case JSP_INPUT_DEFAULT_VALUE
:
167 string_to_jsval(ctx
, vp
, fc
->default_value
);
169 case JSP_INPUT_DISABLED
:
170 /* FIXME: <input readonly disabled> --pasky */
171 boolean_to_jsval(ctx
, vp
, fc
->mode
== FORM_MODE_DISABLED
);
174 object_to_jsval(ctx
, vp
, parent_form
);
176 case JSP_INPUT_MAX_LENGTH
:
177 int_to_jsval(ctx
, vp
, fc
->maxlength
);
180 string_to_jsval(ctx
, vp
, fc
->name
);
182 case JSP_INPUT_READONLY
:
183 /* FIXME: <input readonly disabled> --pasky */
184 boolean_to_jsval(ctx
, vp
, fc
->mode
== FORM_MODE_READONLY
);
187 int_to_jsval(ctx
, vp
, fc
->size
);
190 if (link
&& link
->where_img
)
191 string_to_jsval(ctx
, vp
, link
->where_img
);
193 case JSP_INPUT_TABINDEX
:
195 /* FIXME: This is WRONG. --pasky */
196 int_to_jsval(ctx
, vp
, link
->number
);
200 unsigned char *s
= NULL
;
203 case FC_TEXT
: s
= "text"; break;
204 case FC_PASSWORD
: s
= "password"; break;
205 case FC_FILE
: s
= "file"; break;
206 case FC_CHECKBOX
: s
= "checkbox"; break;
207 case FC_RADIO
: s
= "radio"; break;
208 case FC_SUBMIT
: s
= "submit"; break;
209 case FC_IMAGE
: s
= "image"; break;
210 case FC_RESET
: s
= "reset"; break;
211 case FC_BUTTON
: s
= "button"; break;
212 case FC_HIDDEN
: s
= "hidden"; break;
213 default: INTERNAL("input_get_property() upon a non-input item."); break;
215 string_to_jsval(ctx
, vp
, s
);
218 case JSP_INPUT_VALUE
:
219 string_to_jsval(ctx
, vp
, fs
->value
);
223 INTERNAL("Invalid ID %d in input_get_property().", JSVAL_TO_INT(id
));
231 input_set_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
233 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
234 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
235 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
236 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
237 struct document_view
*doc_view
= vs
->doc_view
;
238 struct document
*document
= doc_view
->document
;
239 struct form_state
*fs
= JS_GetPrivate(ctx
, obj
);
240 struct form_control
*fc
= find_form_control(document
, fs
);
242 struct link
*link
= NULL
;
245 assert(fc
->form
&& fs
);
247 if (!JSVAL_IS_INT(id
))
250 linknum
= get_form_control_link(document
, fc
);
251 /* Hiddens have no link. */
252 if (linknum
>= 0) link
= &document
->links
[linknum
];
254 switch (JSVAL_TO_INT(id
)) {
255 case JSP_INPUT_ACCESSKEY
:
257 link
->accesskey
= accesskey_string_to_unicode(jsval_to_string(ctx
, vp
));
260 mem_free_set(&fc
->alt
, stracpy(jsval_to_string(ctx
, vp
)));
262 case JSP_INPUT_CHECKED
:
263 if (fc
->type
!= FC_CHECKBOX
&& fc
->type
!= FC_RADIO
)
265 fs
->state
= jsval_to_boolean(ctx
, vp
);
267 case JSP_INPUT_DISABLED
:
268 /* FIXME: <input readonly disabled> --pasky */
269 fc
->mode
= (jsval_to_boolean(ctx
, vp
) ? FORM_MODE_DISABLED
270 : fc
->mode
== FORM_MODE_READONLY
? FORM_MODE_READONLY
273 case JSP_INPUT_MAX_LENGTH
:
274 fc
->maxlength
= atol(jsval_to_string(ctx
, vp
));
277 mem_free_set(&fc
->name
, stracpy(jsval_to_string(ctx
, vp
)));
279 case JSP_INPUT_READONLY
:
280 /* FIXME: <input readonly disabled> --pasky */
281 fc
->mode
= (jsval_to_boolean(ctx
, vp
) ? FORM_MODE_READONLY
282 : fc
->mode
== FORM_MODE_DISABLED
? FORM_MODE_DISABLED
287 mem_free_set(&link
->where_img
, stracpy(jsval_to_string(ctx
, vp
)));
290 case JSP_INPUT_VALUE
:
291 if (fc
->type
== FC_FILE
)
292 break; /* A huge security risk otherwise. */
293 mem_free_set(&fs
->value
, stracpy(jsval_to_string(ctx
, vp
)));
294 if (fc
->type
== FC_TEXT
|| fc
->type
== FC_PASSWORD
)
295 fs
->state
= strlen(fs
->value
);
299 INTERNAL("Invalid ID %d in input_set_property().", JSVAL_TO_INT(id
));
307 input_blur(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
309 /* We are a text-mode browser and there *always* has to be something
310 * selected. So we do nothing for now. (That was easy.) */
315 input_click(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
317 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
318 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
319 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
320 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
321 struct document_view
*doc_view
= vs
->doc_view
;
322 struct document
*document
= doc_view
->document
;
323 struct session
*ses
= doc_view
->session
;
324 struct form_state
*fs
= JS_GetPrivate(ctx
, obj
);
325 struct form_control
*fc
;
329 fc
= find_form_control(document
, fs
);
332 linknum
= get_form_control_link(document
, fc
);
333 /* Hiddens have no link. */
337 /* Restore old current_link afterwards? */
338 jump_to_link_number(ses
, doc_view
, linknum
);
339 if (enter(ses
, doc_view
, 0) == FRAME_EVENT_REFRESH
)
340 refresh_view(ses
, doc_view
, 0);
342 print_screen_status(ses
);
344 boolean_to_jsval(ctx
, rval
, 0);
349 input_focus(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
351 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
352 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
353 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
354 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
355 struct document_view
*doc_view
= vs
->doc_view
;
356 struct document
*document
= doc_view
->document
;
357 struct session
*ses
= doc_view
->session
;
358 struct form_state
*fs
= JS_GetPrivate(ctx
, obj
);
359 struct form_control
*fc
;
363 fc
= find_form_control(document
, fs
);
366 linknum
= get_form_control_link(document
, fc
);
367 /* Hiddens have no link. */
371 jump_to_link_number(ses
, doc_view
, linknum
);
373 boolean_to_jsval(ctx
, rval
, 0);
378 input_select(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
380 /* We support no text selecting yet. So we do nothing for now.
381 * (That was easy, too.) */
386 get_input_object(JSContext
*ctx
, JSObject
*jsform
, struct form_state
*fs
)
388 if (!fs
->ecmascript_obj
) {
389 /* jsform ('form') is input's parent */
390 /* FIXME: That is NOT correct since the real containing element
391 * should be its parent, but gimme DOM first. --pasky */
392 JSObject
*jsinput
= JS_NewObject(ctx
, (JSClass
*) &input_class
, NULL
, jsform
);
394 JS_DefineProperties(ctx
, jsinput
, (JSPropertySpec
*) input_props
);
395 JS_DefineFunctions(ctx
, jsinput
, (JSFunctionSpec
*) input_funcs
);
396 JS_SetPrivate(ctx
, jsinput
, fs
);
397 fs
->ecmascript_obj
= jsinput
;
399 return fs
->ecmascript_obj
;
404 get_form_control_object(JSContext
*ctx
, JSObject
*jsform
, enum form_type type
, struct form_state
*fs
)
417 return get_input_object(ctx
, jsform
, fs
);
425 INTERNAL("Weird fc->type %d", type
);
432 static JSBool
form_elements_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
);
434 static const JSClass form_elements_class
= {
437 JS_PropertyStub
, JS_PropertyStub
,
438 form_elements_get_property
, JS_PropertyStub
,
439 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
442 static JSBool
form_elements_item(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
443 static JSBool
form_elements_namedItem(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
445 static const JSFunctionSpec form_elements_funcs
[] = {
446 { "item", form_elements_item
, 1 },
447 { "namedItem", form_elements_namedItem
, 1 },
451 /* INTs from 0 up are equivalent to item(INT), so we have to stuff length out
453 enum form_elements_prop
{ JSP_FORM_ELEMENTS_LENGTH
= -1 };
454 static const JSPropertySpec form_elements_props
[] = {
455 { "length", JSP_FORM_ELEMENTS_LENGTH
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
460 form_elements_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
462 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
463 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
464 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
465 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
466 struct document_view
*doc_view
= vs
->doc_view
;
467 struct document
*document
= doc_view
->document
;
468 struct form_view
*form_view
= JS_GetPrivate(ctx
, parent_form
);
469 struct form
*form
= find_form_by_form_view(document
, form_view
);
471 if (JSVAL_IS_STRING(id
)) {
472 form_elements_namedItem(ctx
, obj
, 1, &id
, vp
);
476 if (!JSVAL_IS_INT(id
))
479 undef_to_jsval(ctx
, vp
);
481 switch (JSVAL_TO_INT(id
)) {
482 case JSP_FORM_ELEMENTS_LENGTH
:
483 int_to_jsval(ctx
, vp
, list_size(&form
->items
));
487 form_elements_item(ctx
, obj
, 1, &id
, vp
);
495 form_elements_item(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
497 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
498 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
499 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
500 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
501 struct document_view
*doc_view
= vs
->doc_view
;
502 struct document
*document
= doc_view
->document
;
503 struct form_view
*form_view
= JS_GetPrivate(ctx
, parent_form
);
504 struct form
*form
= find_form_by_form_view(document
, form_view
);
505 struct form_control
*fc
;
512 index
= atol(jsval_to_string(ctx
, &argv
[0]));
514 undef_to_jsval(ctx
, rval
);
516 foreach (fc
, form
->items
) {
518 if (counter
== index
) {
519 JSObject
*fcobj
= get_form_control_object(ctx
, parent_form
, fc
->type
, find_form_state(doc_view
, fc
));
522 object_to_jsval(ctx
, rval
, fcobj
);
532 form_elements_namedItem(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
534 JSObject
*parent_form
= JS_GetParent(ctx
, obj
);
535 JSObject
*parent_doc
= JS_GetParent(ctx
, parent_form
);
536 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
537 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
538 struct document_view
*doc_view
= vs
->doc_view
;
539 struct document
*document
= doc_view
->document
;
540 struct form_view
*form_view
= JS_GetPrivate(ctx
, parent_form
);
541 struct form
*form
= find_form_by_form_view(document
, form_view
);
542 struct form_control
*fc
;
543 unsigned char *string
;
548 string
= jsval_to_string(ctx
, &argv
[0]);
552 undef_to_jsval(ctx
, rval
);
554 foreach (fc
, form
->items
) {
555 if (fc
->name
&& !strcasecmp(string
, fc
->name
)) {
556 JSObject
*fcobj
= get_form_control_object(ctx
, parent_form
, fc
->type
, find_form_state(doc_view
, fc
));
559 object_to_jsval(ctx
, rval
, fcobj
);
570 static JSBool
form_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
);
571 static JSBool
form_set_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
);
573 static const JSClass form_class
= {
576 JS_PropertyStub
, JS_PropertyStub
,
577 form_get_property
, form_set_property
,
578 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
591 static const JSPropertySpec form_props
[] = {
592 { "action", JSP_FORM_ACTION
, JSPROP_ENUMERATE
},
593 { "elements", JSP_FORM_ELEMENTS
, JSPROP_ENUMERATE
},
594 { "encoding", JSP_FORM_ENCODING
, JSPROP_ENUMERATE
},
595 { "length", JSP_FORM_LENGTH
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
596 { "method", JSP_FORM_METHOD
, JSPROP_ENUMERATE
},
597 { "name", JSP_FORM_NAME
, JSPROP_ENUMERATE
},
598 { "target", JSP_FORM_TARGET
, JSPROP_ENUMERATE
},
602 static JSBool
form_reset(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
603 static JSBool
form_submit(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
605 static const JSFunctionSpec form_funcs
[] = {
606 { "reset", form_reset
, 0 },
607 { "submit", form_submit
, 0 },
612 form_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
614 /* DBG("doc %p %s\n", parent_doc, JS_GetStringBytes(JS_ValueToString(ctx, OBJECT_TO_JSVAL(parent_doc)))); */
615 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
616 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
617 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
618 struct document_view
*doc_view
= vs
->doc_view
;
619 struct form_view
*fv
= JS_GetPrivate(ctx
, obj
);
620 struct form
*form
= find_form_by_form_view(doc_view
->document
, fv
);
624 if (JSVAL_IS_STRING(id
)) {
625 struct form_control
*fc
;
626 unsigned char *string
;
628 string
= jsval_to_string(ctx
, &id
);
629 foreach (fc
, form
->items
) {
630 JSObject
*fcobj
= NULL
;
632 if (!fc
->name
|| strcasecmp(string
, fc
->name
))
635 fcobj
= get_form_control_object(ctx
, obj
, fc
->type
, find_form_state(doc_view
, fc
));
637 object_to_jsval(ctx
, vp
, fcobj
);
639 undef_to_jsval(ctx
, vp
);
646 if (!JSVAL_IS_INT(id
))
649 undef_to_jsval(ctx
, vp
);
651 switch (JSVAL_TO_INT(id
)) {
652 case JSP_FORM_ACTION
:
653 string_to_jsval(ctx
, vp
, form
->action
);
656 case JSP_FORM_ELEMENTS
:
658 /* jsform ('form') is form_elements' parent; who knows is that's correct */
659 JSObject
*jsform_elems
= JS_NewObject(ctx
, (JSClass
*) &form_elements_class
, NULL
, obj
);
661 JS_DefineProperties(ctx
, jsform_elems
, (JSPropertySpec
*) form_elements_props
);
662 JS_DefineFunctions(ctx
, jsform_elems
, (JSFunctionSpec
*) form_elements_funcs
);
663 object_to_jsval(ctx
, vp
, jsform_elems
);
664 /* SM will cache this property value for us so we create this
665 * just once per form. */
669 case JSP_FORM_ENCODING
:
670 switch (form
->method
) {
671 case FORM_METHOD_GET
:
672 case FORM_METHOD_POST
:
673 string_to_jsval(ctx
, vp
, "application/x-www-form-urlencoded");
675 case FORM_METHOD_POST_MP
:
676 string_to_jsval(ctx
, vp
, "multipart/form-data");
678 case FORM_METHOD_POST_TEXT_PLAIN
:
679 string_to_jsval(ctx
, vp
, "text/plain");
684 case JSP_FORM_LENGTH
:
685 int_to_jsval(ctx
, vp
, list_size(&form
->items
));
688 case JSP_FORM_METHOD
:
689 switch (form
->method
) {
690 case FORM_METHOD_GET
:
691 string_to_jsval(ctx
, vp
, "GET");
694 case FORM_METHOD_POST
:
695 case FORM_METHOD_POST_MP
:
696 case FORM_METHOD_POST_TEXT_PLAIN
:
697 string_to_jsval(ctx
, vp
, "POST");
703 string_to_jsval(ctx
, vp
, form
->name
);
706 case JSP_FORM_TARGET
:
707 string_to_jsval(ctx
, vp
, form
->target
);
711 INTERNAL("Invalid ID %d in form_get_property().", JSVAL_TO_INT(id
));
719 form_set_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
721 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
722 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
723 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
724 struct document_view
*doc_view
= vs
->doc_view
;
725 struct form_view
*fv
= JS_GetPrivate(ctx
, obj
);
726 struct form
*form
= find_form_by_form_view(doc_view
->document
, fv
);
727 unsigned char *string
;
731 if (!JSVAL_IS_INT(id
))
734 switch (JSVAL_TO_INT(id
)) {
735 case JSP_FORM_ACTION
:
736 mem_free_set(&form
->action
, stracpy(jsval_to_string(ctx
, vp
)));
739 case JSP_FORM_ENCODING
:
740 string
= jsval_to_string(ctx
, vp
);
741 if (!strcasecmp(string
, "application/x-www-form-urlencoded")) {
742 form
->method
= form
->method
== FORM_METHOD_GET
? FORM_METHOD_GET
744 } else if (!strcasecmp(string
, "multipart/form-data")) {
745 form
->method
= FORM_METHOD_POST_MP
;
746 } else if (!strcasecmp(string
, "text/plain")) {
747 form
->method
= FORM_METHOD_POST_TEXT_PLAIN
;
751 case JSP_FORM_METHOD
:
752 string
= jsval_to_string(ctx
, vp
);
753 if (!strcasecmp(string
, "GET")) {
754 form
->method
= FORM_METHOD_GET
;
755 } else if (!strcasecmp(string
, "POST")) {
756 form
->method
= FORM_METHOD_POST
;
761 mem_free_set(&form
->name
, stracpy(jsval_to_string(ctx
, vp
)));
764 case JSP_FORM_TARGET
:
765 mem_free_set(&form
->target
, stracpy(jsval_to_string(ctx
, vp
)));
769 INTERNAL("Invalid ID %d in form_set_property().", JSVAL_TO_INT(id
));
777 form_reset(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
779 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
780 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
781 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
782 struct document_view
*doc_view
= vs
->doc_view
;
783 struct form_view
*fv
= JS_GetPrivate(ctx
, obj
);
784 struct form
*form
= find_form_by_form_view(doc_view
->document
, fv
);
788 do_reset_form(doc_view
, form
);
789 draw_forms(doc_view
->session
->tab
->term
, doc_view
);
791 boolean_to_jsval(ctx
, rval
, 0);
797 form_submit(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
799 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
800 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
801 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
802 struct document_view
*doc_view
= vs
->doc_view
;
803 struct session
*ses
= doc_view
->session
;
804 struct form_view
*fv
= JS_GetPrivate(ctx
, obj
);
805 struct form
*form
= find_form_by_form_view(doc_view
->document
, fv
);
808 submit_given_form(ses
, doc_view
, form
, 0);
810 boolean_to_jsval(ctx
, rval
, 0);
816 get_form_object(JSContext
*ctx
, JSObject
*jsdoc
, struct form_view
*fv
)
818 if (!fv
->ecmascript_obj
) {
819 /* jsdoc ('document') is fv's parent */
820 /* FIXME: That is NOT correct since the real containing element
821 * should be its parent, but gimme DOM first. --pasky */
822 JSObject
*jsform
= JS_NewObject(ctx
, (JSClass
*) &form_class
, NULL
, jsdoc
);
824 JS_DefineProperties(ctx
, jsform
, (JSPropertySpec
*) form_props
);
825 JS_DefineFunctions(ctx
, jsform
, (JSFunctionSpec
*) form_funcs
);
826 JS_SetPrivate(ctx
, jsform
, fv
);
827 fv
->ecmascript_obj
= jsform
;
829 return fv
->ecmascript_obj
;
833 static JSBool
forms_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
);
835 const JSClass forms_class
= {
838 JS_PropertyStub
, JS_PropertyStub
,
839 forms_get_property
, JS_PropertyStub
,
840 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
843 static JSBool
forms_item(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
844 static JSBool
forms_namedItem(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
);
846 const JSFunctionSpec forms_funcs
[] = {
847 { "item", forms_item
, 1 },
848 { "namedItem", forms_namedItem
, 1 },
852 /* INTs from 0 up are equivalent to item(INT), so we have to stuff length out
854 enum forms_prop
{ JSP_FORMS_LENGTH
= -1 };
855 const JSPropertySpec forms_props
[] = {
856 { "length", JSP_FORMS_LENGTH
, JSPROP_ENUMERATE
| JSPROP_READONLY
},
861 forms_get_property(JSContext
*ctx
, JSObject
*obj
, jsval id
, jsval
*vp
)
863 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
864 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
865 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
866 struct document_view
*doc_view
= vs
->doc_view
;
867 struct document
*document
= doc_view
->document
;
869 if (JSVAL_IS_STRING(id
)) {
870 forms_namedItem(ctx
, obj
, 1, &id
, vp
);
874 if (!JSVAL_IS_INT(id
))
877 switch (JSVAL_TO_INT(id
)) {
878 case JSP_FORMS_LENGTH
:
879 int_to_jsval(ctx
, vp
, list_size(&document
->forms
));
883 forms_item(ctx
, obj
, 1, &id
, vp
);
891 forms_item(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
893 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
894 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
895 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
896 struct form_view
*fv
;
903 index
= atol(jsval_to_string(ctx
, &argv
[0]));
905 undef_to_jsval(ctx
, rval
);
907 foreach (fv
, vs
->forms
) {
909 if (counter
== index
) {
910 object_to_jsval(ctx
, rval
, get_form_object(ctx
, parent_doc
, fv
));
919 forms_namedItem(JSContext
*ctx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
921 JSObject
*parent_doc
= JS_GetParent(ctx
, obj
);
922 JSObject
*parent_win
= JS_GetParent(ctx
, parent_doc
);
923 struct view_state
*vs
= JS_GetPrivate(ctx
, parent_win
);
924 struct document_view
*doc_view
= vs
->doc_view
;
925 struct document
*document
= doc_view
->document
;
927 unsigned char *string
;
932 undef_to_jsval(ctx
, rval
);
934 string
= jsval_to_string(ctx
, &argv
[0]);
938 foreach (form
, document
->forms
) {
939 if (form
->name
&& !strcasecmp(string
, form
->name
)) {
940 object_to_jsval(ctx
, rval
, get_form_object(ctx
, parent_doc
,
941 find_form_view(doc_view
, form
)));