|
40 | 40 | *
|
41 | 41 | * @type string
|
42 | 42 | **/
|
43 |
| - Mobilebone.VERSION = '1.1.8'; |
| 43 | + Mobilebone.VERSION = '1.2.0'; |
44 | 44 |
|
45 | 45 | /**
|
46 | 46 | * Whether catch attribute of href from element with tag 'a'
|
|
53 | 53 | **/
|
54 | 54 | Mobilebone.captureLink = true;
|
55 | 55 |
|
| 56 | + /** |
| 57 | + * Whether catch events of 'submit' from <form> element |
| 58 | + * If the value set to false, <form> is a normal form except data-ajax="true" |
| 59 | + * If the value set to true, <form> will submit as a ajax request, |
| 60 | + and the return value will be used to create a new page and transition into meanwhile. |
| 61 | + However, if data-ajax="false", <form> won't submit as a ajax. |
| 62 | + * |
| 63 | + * @type boolean |
| 64 | + **/ |
| 65 | + Mobilebone.captureForm = true; |
| 66 | + |
56 | 67 | /**
|
57 | 68 | * The root of transition-callback
|
58 | 69 | * Default value is 'root', you can consider as window-object.
|
|
150 | 161 |
|
151 | 162 | // rules as follow:
|
152 | 163 | // data-* > data-params > options > defaults
|
153 |
| - ["title", "root", "form"].forEach(function(key) { |
154 |
| - |
| 164 | + ["title", "root", "form"].forEach(function(key) { |
155 | 165 | _params[key] = element.getAttribute("data-" + key) || _dataparams[key] || options[key] || defaults[key];
|
156 | 166 | });
|
157 | 167 |
|
|
182 | 192 | }
|
183 | 193 | });
|
184 | 194 |
|
185 |
| - |
186 | 195 | return _params;
|
187 | 196 | };
|
188 | 197 |
|
|
243 | 252 | } else if (typeof onpagefirstinto == "function") {
|
244 | 253 | onpagefirstinto(pageInto, pageOut, options.response);
|
245 | 254 | }
|
| 255 | + // capture form submit |
| 256 | + slice.call(pageInto.querySelectorAll("form")).forEach(function(form) { |
| 257 | + Mobilebone.submit(form); |
| 258 | + }); |
246 | 259 | }
|
247 | 260 |
|
248 | 261 | // do callback when animation start/end
|
|
253 | 266 | });
|
254 | 267 | if (!store[pageid]) {
|
255 | 268 | var animateEventName = isWebkit? webkitkey: animationkey;
|
| 269 | + // if it's the out element, hide it when 'animationend' |
256 | 270 | index && pageInto.addEventListener(animateEventName, function() {
|
257 | 271 | if (this.classList.contains("in") == false) {
|
258 | 272 | this.style.display = "none";
|
259 | 273 | }
|
260 | 274 | });
|
261 |
| - |
| 275 | + // bind animation events |
262 | 276 | if (typeof animition == "string" && params_in.root[animition]) {
|
263 | 277 | pageInto.addEventListener(animateEventName, function() {
|
264 | 278 | params_in.root[animition](this, this.classList.contains("in")? "into": "out");
|
|
312 | 326 | var href = "", formdata = "", clean_url = "";
|
313 | 327 | if (trigger) {
|
314 | 328 | if (trigger.nodeType == 1) {
|
| 329 | + // form element |
| 330 | + if (trigger.action) return trigger.getAttribute("action"); |
| 331 | + // a element |
315 | 332 | href = trigger.getAttribute("href");
|
316 | 333 | formdata = trigger.getAttribute("data-formdata") || trigger.getAttribute("data-data");
|
317 | 334 | } else if (trigger.url) {
|
|
386 | 403 | if (element_or_options) {
|
387 | 404 | if (element_or_options.nodeType == 1) {
|
388 | 405 | // legal elements
|
389 |
| - if (element_or_options.href) { |
| 406 | + if (element_or_options.href || element_or_options.action) { |
390 | 407 | page_title = element_or_options.getAttribute("data-title") || options.title;
|
391 | 408 | }
|
392 | 409 | response = options.response;
|
|
425 | 442 | create = null;
|
426 | 443 |
|
427 | 444 | // do transition
|
428 |
| - this.transition(create_page, current_page, { |
| 445 | + var optionsTransition = { |
429 | 446 | response: response || dom_or_html,
|
430 | 447 | id: this.getCleanUrl(element_or_options) || create_page.id || ("unique" + Date.now())
|
431 |
| - }); |
| 448 | + }; |
| 449 | + // 'if' statement below added on v2.0.0 |
| 450 | + if (typeof options == "object") { |
| 451 | + if (typeof options.history != "undefined") { |
| 452 | + optionsTransition.history = options.history; |
| 453 | + } |
| 454 | + if (typeof options.remove != "undefined") { |
| 455 | + optionsTransition.remove = options.remove; |
| 456 | + } |
| 457 | + } |
| 458 | + this.transition(create_page, current_page, optionsTransition); |
432 | 459 | };
|
433 | 460 |
|
434 | 461 | /**
|
|
458 | 485 | * For ajax request to get HTML or JSON.
|
459 | 486 |
|
460 | 487 | * @params trigger_or_options - Necessary
|
461 |
| - 1. dom-object. or~ |
| 488 | + 1. dom-object:<a>|<form>. |
462 | 489 | 2. object.
|
463 | 490 | * @returns undefined
|
464 | 491 | * @example Mobilebone.ajax(document.querySelector("a"));
|
|
474 | 501 | // default params
|
475 | 502 | var defaults = {
|
476 | 503 | url: "",
|
| 504 | + type: "", |
477 | 505 | dataType: "",
|
478 | 506 | data: {},
|
479 | 507 | timeout: 10000,
|
|
485 | 513 | complete: function() {}
|
486 | 514 | };
|
487 | 515 |
|
488 |
| - var params = {}, ele_mask = null; |
| 516 | + var params = {}, ele_mask = null, formData = null; |
489 | 517 |
|
490 | 518 | // if 'trigger_or_options' is a element, we should turn it to options-object
|
491 | 519 | var params_from_trigger = {}, attr_mask;
|
|
503 | 531 | }
|
504 | 532 | }
|
505 | 533 | }
|
506 |
| - |
507 |
| - // the ajax url is special, we need special treatment |
| 534 | + |
508 | 535 | params.url = this.getCleanUrl(trigger_or_options, params.url);
|
509 | 536 |
|
| 537 | + var tagName = trigger_or_options.tagName.toLowerCase(); |
| 538 | + if (tagName == "form") { |
| 539 | + params.type = trigger_or_options.method; |
| 540 | + |
| 541 | + formData = new FormData(trigger_or_options); |
| 542 | + } |
| 543 | + |
510 | 544 | // get mask element
|
511 | 545 | attr_mask = trigger_or_options.getAttribute("data-mask");
|
512 | 546 | if (attr_mask == "true" || attr_mask == "") {
|
|
547 | 581 |
|
548 | 582 | // ajax request
|
549 | 583 | var xhr = new XMLHttpRequest();
|
550 |
| - xhr.open("GET", params.url + (/\?/.test(params.url)? "&" : "?") + "r=" + Date.now(), params.async, params.username, params.password); |
| 584 | + xhr.open(params.type || "GET", params.url + (/\?/.test(params.url)? "&" : "?") + "r=" + Date.now(), params.async, params.username, params.password); |
551 | 585 | xhr.timeout = params.timeout;
|
552 | 586 |
|
553 | 587 | xhr.onload = function() {
|
|
565 | 599 | params.error.call(params, xhr, xhr.status);
|
566 | 600 | }
|
567 | 601 | } else if (params.dataType == "unknown") {
|
| 602 | + // ajax send by url |
| 603 | + // no history hush |
| 604 | + // no element remove |
| 605 | + params.history = false; |
| 606 | + params.remove = false; |
568 | 607 | try {
|
569 | 608 | // as json
|
570 | 609 | response = JSON.parse(xhr.response);
|
|
606 | 645 | ele_mask.style.visibility = "hidden";
|
607 | 646 | };
|
608 | 647 |
|
609 |
| - xhr.send(null); |
| 648 | + xhr.send(formData); |
| 649 | + }; |
| 650 | + |
| 651 | + /** |
| 652 | + * capture form submit events to a ajax request. |
| 653 | + |
| 654 | + * @params form: formElement. - Necessary |
| 655 | + * @example Mobilebone.form(document.querySelector("form")); |
| 656 | + * |
| 657 | + **/ |
| 658 | + Mobilebone.submit = function(form) { |
| 659 | + if (!form || typeof form.action != "string") return; |
| 660 | + var ajax = form.getAttribute("data-ajax"); |
| 661 | + if (ajax == "false" || (this.captureForm == false && ajax != "true")) return; |
| 662 | + |
| 663 | + form.addEventListener("submit", function(event) { |
| 664 | + Mobilebone.ajax(this); |
| 665 | + event.preventDefault(); |
| 666 | + }); |
610 | 667 | };
|
611 | 668 |
|
612 | 669 |
|
|
710 | 767 | });
|
711 | 768 | }
|
712 | 769 | }
|
| 770 | + |
713 | 771 | // change flag-var for avoiding repeat init
|
714 | 772 | hasInited = true;
|
715 | 773 | };
|
|
819 | 877 | popup();
|
820 | 878 | return element;
|
821 | 879 | };
|
| 880 | + |
822 | 881 | /**
|
823 | 882 | * private method: convert query string to key-value object
|
824 | 883 | **/
|
|
849 | 908 | **/
|
850 | 909 | window.addEventListener("popstate", function() {
|
851 | 910 | var hash = location.hash.replace("#&", "").replace("#", "");
|
| 911 | + if (hash == "") return; |
852 | 912 |
|
853 | 913 | var page_in = store[hash];
|
854 | 914 |
|
855 | 915 | if (!page_in) {
|
856 | 916 | if(isSimple.test(hash) == false) {
|
| 917 | + // as a url |
| 918 | + Mobilebone.ajax({ |
| 919 | + url: hash, |
| 920 | + dataType: "unknown" |
| 921 | + }); |
857 | 922 | return;
|
858 | 923 | }
|
859 | 924 | page_in = document.querySelector("#" + hash)
|
|
862 | 927 | var page_out = document.querySelector(".in." + Mobilebone.classPage);
|
863 | 928 |
|
864 | 929 | if ((page_in && page_in == page_out) || Mobilebone.pushStateEnabled == false) return;
|
865 |
| - |
866 | 930 |
|
867 | 931 | // hash ↔ id
|
868 | 932 | if (page_in) {
|
|
0 commit comments