Näytetään tekstit, joissa on tunniste jquery. Näytä kaikki tekstit
Näytetään tekstit, joissa on tunniste jquery. Näytä kaikki tekstit

lauantai 10. elokuuta 2013

Javascript: How to send just one form element by Ajax with XMLHttpRequest 2

Because of HTML5, we have new XMLHttpRequest level 2 API and FormData-object which let us to create a custom POST data.  In this post I am not going to explain all details about new Ajax possibilities, that is done in article "New Tricks in XMLHttpRequest2".

In article written by Eric Bidelman, is explained in nice way how to create a FormData-object from particular form-element. So we can turn any form into a FormData-object by giving a form-element from DOM to FormData constructor.

var myform=document.getElementByTagName('form')[0]
var formdata=new FormData(myform);

This will create an formdata variable which can be send to server by Ajax.

What Eric does not tell in article, is that FormData object can be feeded only with Form element, and in object itself it is not possible to choose which form controls will be included and which should be left behind. This is how it different from jQuery's $.serialize or $.serializeArray, which does not care if form controls actually are inside a form element or not.

In real life, it is sometimes needed to send to the server only particular section of form or an individual form control. Lets assume we have an lonely textinput which we would like to send to an server.
<input type="text" name="address" id="myinput">

As now, it is not possible to create a FormData object, because the input is not inside a form.
However, following functions will make it happen:

function createFormData(elem) {
var dataform=document.createElement('form');
dataform.appendChild(elem.cloneNode(1));
return new FormData(dataform);
 }


With the function it is possible to create an FormData object from single input:

var inputelement=document.getElementById('myinput')
var formdata=createFormData(inputelement)


Finally we can send the input to a server:

var xhr = new XMLHttpRequest();
xhr.open('POST', 'mywebpage', true);
xhr.onload = function(e) { ... };
xhr.send(formdata);

torstai 8. elokuuta 2013

Javascript: window.prompt on IE10 metro

Today some of my customers complained that they cannot fill form in one website. After investigating I soon realized that problem was lack of support for window.prompt method in IE 10 Metro mode.

I like to use window.prompt, because it is native and standard way to ask user input. It gives away the UI design to browsers, so designer does not need to care how it will be shown on different devices.

In IE 10 Metro, window.prompt is defined and the method does exist. However, user will never see prompt box and value of prompt is always undefined.

To correct the functionality in IE 10 Metro mode, I created a polyfill for it. The webpage that I used in this particular case is using jQuery Mobile framework, so I used popups from jQM it as part of the solution. I also had to alter behavior of window.prompt a little bit. Because it is impossibe to create a polyfill which will halt execution of script while waiting user input, I had to implement a callback which will be executed when user has given the input.

The code for fixing window.prompt on IE10 metro mode (Requires: jQuery Mobile 1.3)

window.cacheprompt=window.prompt;
window.prompt=function(msg,defaultvalue,callback) {
var r=window.cacheprompt(msg,defaultvalue);
if(typeof(callback)=='undefined')
return r;
if(typeof(r)=='undefined' && typeof(callback)=='function') {
var form=$.mobile.activePage[0].appendChild(document.createElement('form'));
var label=form.appendChild(document.createElement('label'));
label.appendChild(document.createTextNode(msg));
var textinput=document.createElement('input');
textinput.type='text';
label.appendChild(textinput).value=defaultvalue;
var btn=form.appendChild(document.createElement('input'));
btn.type='button';
btn.value='ok';
btn.onclick=function() {
callback(textinput.value);
$(form).popup('close');
}
$(form).popup({theme:'a'}).popup('open');
}
else if(typeof(callback)=='function')
return callback(r);
 }

The polyfill will override native window.prompt method, but wont affect behavior of it unless browser is not capable of showing the prompt window. The Polyfill adds third parameter to prompt method, a callback which will be executed when user has gave the input.

window.prompt('Your name', 'Peter Pan', function(name) {
    alert('Your name is '+name);
 })

On IE10 Metro UI it will be shown as in picture: