Skip to content

Commit 38017d7

Browse files
author
Pavel Malyshev
committed
Support of GET-forms
1 parent 043e68c commit 38017d7

File tree

3 files changed

+239
-0
lines changed

3 files changed

+239
-0
lines changed

examples/form/index.html

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Basic</title>
5+
<script src="/page.js"></script>
6+
<base href="/form/" >
7+
</head>
8+
<body>
9+
<h1>GET form</h1>
10+
<p></p>
11+
<form class="form" method="get" action="/">
12+
<p>
13+
<label>Text (should):</label>
14+
<input name="text">
15+
</p>
16+
<p>
17+
<label>Textarea (should):</label>
18+
<textarea name="textarea"></textarea>
19+
</p>
20+
<p>
21+
<label>Radio (should selected):</label>
22+
<input type="radio" name="radio" value="1"> 1
23+
<input type="radio" name="radio" value="2"> 2
24+
</p>
25+
<p>
26+
<label>Checkbox (should selected):</label>
27+
<input name="checkbox1" type="checkbox"> checkbox1
28+
<input name="checkbox2" type="checkbox"> checkbox2
29+
</p>
30+
<p>
31+
<label>Hidden (should but it's strange):</label>
32+
<input name="hidden" type="hidden">
33+
</p>
34+
<p>
35+
<label>File (should with path to file):</label>
36+
<input name="file" type="file">
37+
</p>
38+
<p>
39+
<label>Unnamed (shouldn't without name):</label>
40+
<input class="unnamed">
41+
<button type="button">find</button>
42+
</p>
43+
<p>
44+
<label>Disabled (shouldn't because disabled):</label>
45+
<input name="disabled" disabled>
46+
</p>
47+
<p>
48+
<label>Submit Buttons (should with its name/value):</label>
49+
<button name="button" value="find">find</button>
50+
<input name="button" type="submit" value="search">
51+
</p>
52+
<p>
53+
<label>Regular Buttons (shouldn't):</label>
54+
<button type="button" name="button" value="find">find</button>
55+
<input name="button" type="button" value="search">
56+
</p>
57+
<p>
58+
<label>Submit to Action Button (should with different action):</label>
59+
<button formaction="/another" name="button" value="find">find</button>
60+
</p>
61+
62+
</form>
63+
64+
<script>
65+
66+
page.base('/form');
67+
68+
page('/', index);
69+
70+
page('/:action', action);
71+
72+
page.start({
73+
submit: true
74+
});
75+
76+
function index(ctx) {
77+
document.querySelector('p')
78+
.textContent = 'searching index for ' + ctx.querystring;
79+
}
80+
81+
function action(ctx) {
82+
document.querySelector('p')
83+
.textContent = 'another action ' + (ctx.params.action || '');
84+
}
85+
</script>
86+
</body>
87+
</html>

index.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@
183183
* - `click` bind to click events [true]
184184
* - `popstate` bind to popstate [true]
185185
* - `dispatch` perform initial dispatch [true]
186+
* - `submit` bind to submit events (GET-forms only) [true]
186187
*
187188
* @param {Object} options
188189
* @api public
@@ -199,6 +200,9 @@
199200
if (false !== options.click && hasDocument) {
200201
pageWindow.document.addEventListener(clickEvent, onclick, false);
201202
}
203+
if (false !== options.submit && hasDocument) {
204+
pageWindow.document.addEventListener('submit', onsubmit, false);
205+
}
202206
hashbang = !!options.hashbang;
203207
if(hashbang && hasWindow && !hasHistory) {
204208
pageWindow.addEventListener('hashchange', onpopstate, false);
@@ -233,6 +237,7 @@
233237
page.len = 0;
234238
running = false;
235239
hasDocument && pageWindow.document.removeEventListener(clickEvent, onclick, false);
240+
hasDocument && pageWindow.document.removeEventListener('submit', onsubmit, false);
236241
hasWindow && pageWindow.removeEventListener('popstate', onpopstate, false);
237242
hasWindow && pageWindow.removeEventListener('hashchange', onpopstate, false);
238243
};
@@ -683,6 +688,77 @@
683688
page.show(orig);
684689
}
685690

691+
/**
692+
* Handle "submit" events.
693+
*/
694+
695+
function onsubmit(e) {
696+
if (e.defaultPrevented) return;
697+
698+
var form = e.target,
699+
btnSubmit = checkButtonElement(document.activeElement) && document.activeElement;
700+
701+
var action = form.hasAttribute('action') && form.getAttribute('action'),
702+
method = form.hasAttribute('method') && form.getAttribute('method'),
703+
target = form.hasAttribute('target') && form.getAttribute('target');
704+
705+
if (btnSubmit) {
706+
if (btnSubmit.hasAttribute('formaction')) action = btnSubmit.getAttribute('formaction');
707+
if (btnSubmit.hasAttribute('formmethod')) method = btnSubmit.getAttribute('formmethod');
708+
if (btnSubmit.hasAttribute('formtarget')) target = btnSubmit.getAttribute('formtarget');
709+
}
710+
711+
// Ignore if tag has
712+
// 1. method and not method="get"
713+
// 2. target and not target="_self"
714+
if (method && method.toLowerCase() !== 'get') return;
715+
if (target && target.toLowerCase() !== '_self') return;
716+
717+
var a = document.createElement('a');
718+
a.href = action;
719+
720+
var pathname = a.pathname,
721+
hash = a.hash || '',
722+
search = [];
723+
724+
var elements = form.elements,
725+
len = elements.length;
726+
727+
for (var i = 0; i < len; i++) {
728+
if ( ! elements[i].name || elements[i].disabled) continue;
729+
if (['checkbox', 'radio'].indexOf(elements[i].type) >= 0 && !elements[i].checked) {
730+
continue;
731+
}
732+
if (checkButtonElement(elements[i]) && elements[i] !== btnSubmit) {
733+
continue;
734+
}
735+
search.push(elements[i].name + '=' + elements[i].value);
736+
}
737+
738+
var path = (pathname + '?' + search.join('&') + hash);
739+
path = path[0] !== '/' ? '/' + path : path;
740+
741+
// strip leading "/[drive letter]:" on NW.js on Windows
742+
if (hasProcess && path.match(/^\/[a-zA-Z]:\//)) {
743+
path = path.replace(/^\/[a-zA-Z]:\//, '/');
744+
}
745+
746+
var pageBase = getBase();
747+
748+
if (path.indexOf(pageBase) === 0) {
749+
path = path.substr(base.length);
750+
}
751+
752+
if (hashbang) path = path.replace('#!', '');
753+
754+
e.preventDefault();
755+
page.show(path);
756+
}
757+
758+
function checkButtonElement(el) {
759+
return (el.type && ['button', 'submit', 'image'].indexOf(el.type) >= 0) || el.tagName === 'button';
760+
}
761+
686762
/**
687763
* Event button.
688764
*/

page.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
583583
* - `click` bind to click events [true]
584584
* - `popstate` bind to popstate [true]
585585
* - `dispatch` perform initial dispatch [true]
586+
* - `submit` bind to submit events (GET-forms only) [true]
586587
*
587588
* @param {Object} options
588589
* @api public
@@ -599,6 +600,9 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
599600
if (false !== options.click && hasDocument) {
600601
pageWindow.document.addEventListener(clickEvent, onclick, false);
601602
}
603+
if (false !== options.submit && hasDocument) {
604+
pageWindow.document.addEventListener('submit', onsubmit, false);
605+
}
602606
hashbang = !!options.hashbang;
603607
if(hashbang && hasWindow && !hasHistory) {
604608
pageWindow.addEventListener('hashchange', onpopstate, false);
@@ -633,6 +637,7 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
633637
page.len = 0;
634638
running = false;
635639
hasDocument && pageWindow.document.removeEventListener(clickEvent, onclick, false);
640+
hasDocument && pageWindow.document.removeEventListener('submit', onsubmit, false);
636641
hasWindow && pageWindow.removeEventListener('popstate', onpopstate, false);
637642
hasWindow && pageWindow.removeEventListener('hashchange', onpopstate, false);
638643
};
@@ -1083,6 +1088,77 @@ pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
10831088
page.show(orig);
10841089
}
10851090

1091+
/**
1092+
* Handle "submit" events.
1093+
*/
1094+
1095+
function onsubmit(e) {
1096+
if (e.defaultPrevented) return;
1097+
1098+
var form = e.target,
1099+
btnSubmit = checkButtonElement(document.activeElement) && document.activeElement;
1100+
1101+
var action = form.hasAttribute('action') && form.getAttribute('action'),
1102+
method = form.hasAttribute('method') && form.getAttribute('method'),
1103+
target = form.hasAttribute('target') && form.getAttribute('target');
1104+
1105+
if (btnSubmit) {
1106+
if (btnSubmit.hasAttribute('formaction')) action = btnSubmit.getAttribute('formaction');
1107+
if (btnSubmit.hasAttribute('formmethod')) method = btnSubmit.getAttribute('formmethod');
1108+
if (btnSubmit.hasAttribute('formtarget')) target = btnSubmit.getAttribute('formtarget');
1109+
}
1110+
1111+
// Ignore if tag has
1112+
// 1. method and not method="get"
1113+
// 2. target and not target="_self"
1114+
if (method && method.toLowerCase() !== 'get') return;
1115+
if (target && target.toLowerCase() !== '_self') return;
1116+
1117+
var a = document.createElement('a');
1118+
a.href = action;
1119+
1120+
var pathname = a.pathname,
1121+
hash = a.hash || '',
1122+
search = [];
1123+
1124+
var elements = form.elements,
1125+
len = elements.length;
1126+
1127+
for (var i = 0; i < len; i++) {
1128+
if ( ! elements[i].name || elements[i].disabled) continue;
1129+
if (['checkbox', 'radio'].indexOf(elements[i].type) >= 0 && !elements[i].checked) {
1130+
continue;
1131+
}
1132+
if (checkButtonElement(elements[i]) && elements[i] !== btnSubmit) {
1133+
continue;
1134+
}
1135+
search.push(elements[i].name + '=' + elements[i].value);
1136+
}
1137+
1138+
var path = (pathname + '?' + search.join('&') + hash);
1139+
path = path[0] !== '/' ? '/' + path : path;
1140+
1141+
// strip leading "/[drive letter]:" on NW.js on Windows
1142+
if (hasProcess && path.match(/^\/[a-zA-Z]:\//)) {
1143+
path = path.replace(/^\/[a-zA-Z]:\//, '/');
1144+
}
1145+
1146+
var pageBase = getBase();
1147+
1148+
if (path.indexOf(pageBase) === 0) {
1149+
path = path.substr(base.length);
1150+
}
1151+
1152+
if (hashbang) path = path.replace('#!', '');
1153+
1154+
e.preventDefault();
1155+
page.show(path);
1156+
}
1157+
1158+
function checkButtonElement(el) {
1159+
return (el.type && ['button', 'submit', 'image'].indexOf(el.type) >= 0) || el.tagName === 'button';
1160+
}
1161+
10861162
/**
10871163
* Event button.
10881164
*/

0 commit comments

Comments
 (0)