My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Wednesday, November 29, 2006

W3 Validator, DOM, byteson and PHP

I've uploaded a new byteson example page, based on a single and simple request to a PHP page that uses W3 Validator service, calling a SOAP result, parse them to convert it into an associative array and finally send it with JSON to byteson.

Here is the PHP code

<?php
// byteson filter
if(isset($_POST['byteson'])) {

// http://www.phpclasses.org/browse/package/3512.html
require 'FastJSON.class.php';

// http://www.devpro.it/code/143.html
require 'W3validator.function.php';

// remove magic quotes if th it's present
// magic_quotes is a problem for JSON strings
if(get_magic_quotes_gpc())
$_POST['byteson'] = stripslashes($_POST['byteson']);

// get the output
$output = FastJSON::encode(W3validator(FastJSON::decode($_POST['byteson'])));

// force new content to download
header('Content-Type: text/plain; charset=utf-8');
header('Content-Length: '.strlen($output));
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');

// exit writing JSON object for byteson
exit($output);
}
?>

This code is above the xHTML output and You can view them by yourself, viewing the example page.

This php page uses two other files, my FastJSON class and my last function on devpro, called W3validator (what a fantasy ...).

The JavaScript code is this one

// new browsers filter
if(document.getElementsByTagName)
onload = function(){ // (C) Andrea Giammarchi

// assing tabindex and accesskey
function accesstab(input){
input.accesskey = input.tabindex = ++accesskey;
++tabindex;
};

// assign generic link properties
function addLinkProperties(a){
tab(a);
a.href = "#";
a.onclick = function(){
var ul = this.parentNode.getElementsByTagName("ul").item(0);
ul.style.display = !!ul.style.display ? "" : "none";
return false;
};
return a;
};

// append one or more elements into another
// then return the "parent" element
function append(parent, elements){
if(elements.constructor !== Array)
elements = [elements];
for(var i = 0; i < elements.length; i++)
parent.appendChild(elements[i]);
return parent;
};

// create a list if there are errors or warnings
function createList(message, obj){
for(var a, span, i = 0, key = "", list = [], tmp = []; i < obj.length; i++) {
for(key in obj[i]) {
span = node("span");
span.innerHTML = obj[i][key];
tmp.push(append(
node("li"), [
append(node("strong"), text(key)),
span
]
));
};
a = addLinkProperties(append(node("a"), text(message.concat(i + 1))));
list.push(append(node("li"),[a, append(node("ul"), tmp)]));
tmp = [];
};
return append(node("ul"), list);
};

// perform the request using byteson
function doRequest(oldtab){

// just call the server side page
// sending input string and adding just
// one listener ( because I'm sure, this application will works "perfectly" :P )
byteson.request("w3validator.php", inputuri.value, {

// onload event
load:function(obj, xhr){
var a, key = "";

// remove the loading text
resultlist.removeChild(resultlist.firstChild);

// create a list with every key value ...
for(key in obj) {

// but not with Arrays (errors or warnings)
if(obj[key].constructor !== Array) {
append(
resultlist,
append(
node("li"), [
append(node("strong"), text(key)),
append(node("span"), text(obj[key]))
]
)
);
};
};

// create last list with each error or each warning
for(key in obj) {
if(obj[key].constructor === Array && obj[key].length > 0) {
a = addLinkProperties(append(node("a"), text(key)));
append(
resultlist,
append(
node("li"), [
a,
createList(key.replace(/list/, ' #'), obj[key])
]
)
);
a.onclick();
};
};

// enable the form
inputuri.disabled = senduri.disabled = false;

// set old tabindex for next request
// (correct tab navigation ready)
tabindex = oldtab;
}
});
};

// create and return an element of specified type
function node(type){return document.createElement(type)};

// add tabindex property using global scpe tabindex integer value
function tab(node){node.tabindex = ++tabindex};

// create and return a text node with specified content
function text(value){return document.createTextNode(value)};

// internal global scope variables
var accesskey = 0, // accesskey (WCAG ready ?)
tabindex = 0, // tabindex (tab navigation ready)
output = document.getElementById("request"), // div container
form = node("form"), // used form
inputlabel = node("label"), // label for input text
inputuri = node("input"), // input text
sendlabel = node("label"), // label for send button
senduri = node("input"), // send button
resultlist = node("ul"); // result unordered list

// assign accesskey, tabindex and other parameters for each input (in this case text and btn)
accesstab(inputuri);
inputuri.type = "text";
inputuri.id = inputlabel["for"] = "userinput";
// keyboard event listener (RETURN to perform the request)
inputuri.onkeyup = function(evt){
if(!evt)
evt = window.event;
if(!evt.wich)
evt.wich = evt.keyCode;
if(evt.wich === 13 && this.value.replace(/^\s*|\s*$/, '').length > 4)
senduri.onclick();
};

accesstab(senduri);
senduri.type = "button";
senduri.id = sendlabel["for"] = "sendinput";
senduri.value = "verify";
// request function
senduri.onclick = function(){
var newresult = node("ul");

// disable the form
inputuri.disabled = senduri.disabled = true;

// blur this button
senduri.blur();

// remove precedent unordered list element and replace
// replace them with a simple "loading response" message
// inside a new unordered list element
resultlist.parentNode.replaceChild(newresult, resultlist);

// assign new ul element to global scope var (to change them on load)
resultlist = newresult;
append(resultlist, append(node("li"), text("loading response")));

// perform the request with byteson
doRequest(tabindex);
return false;
};

// form should be disabled, by default
// (the form doesn't degrade in this example)
form.onsubmit = function(){return false};

// create the output only for the first time
output.replaceChild(
append(
form, // the form
append(
node("fieldset"), [ // top fieldset
append(
node("legend"), // and its legend
text("W3 Validator") // with its content
),
append(
inputlabel, // label for text input
text("write a valid url address") // and its content
),
inputuri, // input text
append(
sendlabel, // label for button
text("verify W3 validator result") // and its content
),
senduri // send button
]
)
), output.firstChild);

// create result fieldset to show informations
// append this fieldset after the precedent output
append(
output,
append(
node("fieldset"), [ // bottom fieldset
append(
node("legend"), // and its legend
text("W3 Response") // with its content
),
resultlist // and its unordered list
] // to show the result
)
);
}; // that's all


The last file is the external stylesheet used in this page.

This basic example can explain better than every post, how W3validator PHP function works and how much is simple to implement byteson inside other JS code.

Have fun with W3 validation ;-)

1 comment:

Anonymous said...

bellissimo questo... me l'ero perso complimenti