Showing posts with label html. Show all posts
Showing posts with label html. Show all posts

Printer-Friendly Page With CSS

Monday, July 7, 2008

Ok, so you want to create a printer-friendly page without having to create another web page for that purpose. Here's how.

First, create a separate stylesheet with the rules for the page to be printed. Usually, this css is named print.css, so maybe you should name your it print.css too :D.

Second, link the stylesheet to the page and set the media property to print.
<link rel="stylesheet" type="text/css" href="base.css" media="screen" /> <link rel="stylesheet" type="text/css" href="print.css" media="print" />

You see, the default value for the media attribute is all, so if you don't specify the attribute the browser will apply the CSS rules to all media. There are actually ten media types:

Media Type Description
all Suitable for all devices
braille For Braille tactile feedback devices
embossed For paged Braille printers
handheld For handheld devices
print For paged material, documents viewed on-screen in print preview mode
projection For projected presentation, i.e projectors
screen Primarily for color computers screens
speech For speech synthesizers
tty For media using fixed-pitch character grid i.e teletypes, terminals, or devices with limited display capabilities
tv For television-type devices


If you want to define the stylesheet for several media, separate the media values with comma, like this
<link rel="stylesheet" type="text/css" href="dual.css" media="print, projection" />

And beside using link method, you can also use import, like the following line @import URI(dual.css) print,projection; And stil there's way to define stylesheet and media types, it's by using the @media, which enables writing css rules that can be set for different media, all in one stylesheet
<style type="text/css">
@media print{
 #container {
  font-size: 10pt;
  background: #FFFFFF;
  color: #000000 
 }
}

@media screen{
 #container {
  font-size: .8em;
  background: #0000FF;
  color: #FFFFFF 
 } 
}
</style>


Hope this helps.

Getting XML Data from Server Using AJX

Friday, June 27, 2008

Previously, we use AJAX to receive data from server using the responseText property, it's quite usefull but what if you want to get a complicated data like a bunch of names, addresses, numbers, and many more information in a single request? Sure, you can format your responseText, but why bother if you can use the responseXML property?

Accessing the responseXML will get you a response of HTTP request as XML DOM objects, and this only happen if the XML returned by the server is a valid XML, otherwise you get null.

Here's how we do it.

First, an example of XML file generated by PHP, you can generate more complex with database-driven data, but here's I just a simple plain XML.

<?php
header('Content-type: text/xml');
?>
<students>
 <student year="1999">
  <name>John Smith</name>
  <ssn>23132452</ssn>
 </student>
 <student year="2000">
  <name>Jane Smith</name>
  <ssn>23132453</ssn>
 </student>
</students>
and the javscript code to extract data from XML file.
function getXMLHttp() {
var XMLHttp = null;
if (window.XMLHttpRequest) {
  try {
    XMLHttp = new XMLHttpRequest();
  } catch (e) { }
} else if (window.ActiveXObject) {
  try {
    XMLHttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      XMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) { }
  }
}
return XMLHttp;
}

var XMLHttp = getXMLHttp();
XMLHttp.open("GET", "getstudents.php");
XMLHttp.onreadystatechange = function(){
if (XMLHttp.readyState == 4) {
  var xml = XMLHttp.responseXML;
  var student = xml.getElementsByTagName("student")[0];
  var year= student.getAttribute("year");
 var name, ssn;
 for (var i=0; i<student.childNodes.length; i++) {
    if (student.childNodes[i].nodeName == "name") {
      name = student.childNodes[i].firstChild.nodeValue;
    } else if (student.childNodes[i].nodeName == "ssn") {
      ssn= student.childNodes[i].firstChild.nodeValue;
    }
  }
  window.alert(name + " / " + ssn + " / " + year);
}
};
XMLHttp.send(null);
Screenie of the result


I'll write about using documentElement and JSON to do the same thing, but in an easier way, later. For now, I hope the code above suffices.

Dynamically Generate HTML Element Using Strings and Arrays

Thursday, June 26, 2008

Eventhough DOM is maybe the most powerfull technique to manipulate a page's content, sometimes we can get performance benefits by not using it and use core javascript objects instead. In the following example I'll use strings and arrays to generate a table. I'll show both way for comparison. Remember, minimizing your code's use of OM objects can always increase your page's performance. Here's an example of a DOM scripting technique:

function createTable(numRows, numCols) {
    var idRow = 0, idCol = 0;
    var oTable = document.createElement("TABLE");
    var oTBody = document.createElement("TBODY");
    var oTRow = null;
    var oTCol = null;

    for (idRow; idRow < numRows; idRow++) {
        oTRow = document.createElement("TR");
        oTRow.style.border="solid 1px blue";
        for (idCol = 0; idCol < numCols; idCol++) {
            oTCol = document.createElement("TD");
            oTCol.innerText = "("+idRow + ", " + idCol+")";
            oTRow.appendChild(oTCol);
        };
        oTBody.appendChild(oTRow);
    };
    oTable.appendChild(oTBody);
    document.body.appendChild(oTable);
};
Call the script on your page using onload="createTable(5, 5)" for example. And here's an example using the strings and arrays:
function createTable(numRows, numCols) {
    var idRow = 0, idCol = 0;
    var buffer = new Array();
    var bufferCount = 0;
    buffer[bufferCount++] = "<table><tbody>";

    for (idRow; idRow < numRows; idRow++) {
        buffer[bufferCount++] = "<tr>";
        for (idCol = 0; idCol < numCols; idCol++) {
            buffer[bufferCount++] = "<td>";
            buffer[bufferCount++] = "("+idRow;
            buffer[bufferCount++] = ", ";
            buffer[bufferCount++] = idCol+")";
            buffer[bufferCount++] = "</td>";
        };

        buffer[bufferCount++] = "</tr>";
    };

    buffer[bufferCount++] = "</tbody></table>";
    document.body.innerHTML += buffer.join("");
};
The outputs of both code is the same, but the second is faster than the first. It proves that manipulating page dynamically is faster using core javascript code than using the DOM API. In the second method, we used buffer array to store the HTML strings. This method avoids using more CPU cycles to concatenate new element separately like in the first method. In short, the second method is faster because it changes the element in one complete string while the first method does it per element. Hope this helps.

Loading JavaScript Files Dynamically

Wednesday, June 25, 2008

So, you want to load the javascript code on runtime, for example, you want a spesific javascript to be loaded depending on some user input. How to do that? You can always use the document.write to add a new <script> element to the page. But it's not recommended and it's not working with some browsers. The better approach is to use DOM. First, create a <script> element, set the attributes, then add this element to page's DOM. Here's the example code. Remember to put the element inside the <head> section.

<script language="JavaScript" type="text/javascript">
  var myjs = document.createElement("script");
  myjs.setAttribute("type", "text/javascript");
  myjs.setAttribute("language", "JavaScript");
  myjs.setAttribute("src", "myscript.js");
  document.getElementsByTagName("head")[0].appendChild(myjs);
</script>
In that example, the script will load external javascript file named myscript.js, all you have to do is define the trigger of the script. Javascript and DOM are maybe the most powerfull way to manipulate your pages. That's how I see it. But we will discuss about this opinion later. Hope this helps,

Creating Simple Auto-Complete Field with AJAX

Wednesday, June 18, 2008

I noticed the ajax auto-complete field for the first time when I type a keyword in google suggest, the field automagically giving me suggestion by displaying options to what word i might looked for beneath the text field, and now you can find this auto-complete variation very popular on search page. Here's a screenshot that I only typed "open" and google suggest me of what word may related to it and the amount of result accordingly. Here's a screenie.

What I will show you here is a simple quick way to do it. I will write a simple script that would auto-complete a word that user inputted with the stored words on database and returns the first match. Here's a complete list of the code

<head>
<script language="javascript">
function getXMLHttp() {
var XMLHttp = null;
if (window.XMLXMLHttpRequestuest) {
try {
XMLHttp = new XMLXMLHttpRequestuest();
}  catch (e) { }
}  else if (window.ActiveXObject) {
  try {
   XMLHttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
  XMLHttp = new ActiveXObject(
    "Microsoft.XMLHTTP");
  } catch (e) { }
 }
}
return XMLHttp;
}

function autocomplete (from, ev) {
   if (( ev.keyCode >= 48 && ev.keyCode <= 57 ) ||  ( ev.keyCode >= 65 && ev.keyCode <= 90 )) {        
var XMLHttpRequest = getXMLHttp();        
XMLHttpRequest.open
("GET", "suggest.php?word="+document.getElementsByName("txtWord")[0].value, true);               
XMLHttpRequest.onreadystatechange = function (  ) {            
if (XMLHttpRequest.readyState == 4) {                
var suggestion = XMLHttpRequest.responseText;                
var txtWord = document.getElementById ('txtWord');                 
if ((suggestion) && (txtWord.value == original_text)) {                    
//Gecko and Opera                    
if (document.getSelection) {                        
var initial_len = txtWord.value.length;                         
txtWord.value += suggestion;                         
txtWord.selectionStart = initial_len;                        
txtWord.selectionEnd = txtWord.value.length;                     }                    
//IE <= 6                    
else if (document.selection) {                        
var sel = document.selection.createRange (  );                        
sel.text = suggestion;                                   
sel.move ("character", -suggestion.length);                        
sel.findText (suggestion);                         sel.select (   );                    
}                
}
}        
}        
XMLHttpRequest.send (null);    
}
}
</script> </head> <body> <input style="position: absolute" type="text" name="txtWord" 
id="txtWord" onKeyup="autocomplete(this, event)" /> </body> 


At the server side, you have to create a php (or whatever server-side programming language) file that find the first match of text inputted by user and simply prints that value. The code in javascript will get that value via XMLHttpRequest.responseText and send it to input field. The remaining script in that javascript is meant to graft the end of the word we get from the responseText onto the beginning of the word, and select it.

The screenshot above shows that the code auto-completes my input from "au" to "automatic" and select the "tomatic" word. It's different presentation since google puts the options into a drop-down menu but I hope it gives a clue of how we get the completion words back.

Hope that helps.

Aborting XMLHttpRequest on Timeout

Tuesday, June 17, 2008

When your application is using ajax, there are possibilities that you made many HTTP request at a time, especially if you have a page with multiple ajax components or what they call mashup. And that might be a problem. You have to know whether your request has been done or not.

The simplest way to do it is by defining a timeout period for the request, if a request takes longer time than the period defined, then you have to abort the request, and rolling back the condition to before the request is sent(if any).

The method used here is abort(), XMLHttp.abort(). The following code will show you how to abort the request if it has not been fully executed after 7 seconds. The file sleep.php here is only a dummy file which took 10 seconds to execute, therefore the request will be aborted for sure.

Here's the code for the sleep.php file

<?php
sleep(10);
echo "this text only appeared after 10 seconds";
?>

And here's the html file with a code to abort the request if it took longer than 7 seconds

<script language="JavaScript" type="text/javascript">
function getXMLHttp() {
 var XMLHttp = null;
 if (window.XMLHttpRequest) {
   try {
     XMLHttp = new XMLHttpRequest();
   } catch (e) { }
 } else if (window.ActiveXObject) {
   try {
     XMLHttp = new ActiveXObject("Msxml2.XMLHTTP");
   } catch (e) {
     try {
       XMLHttp = new ActiveXObject(
         "Microsoft.XMLHTTP");
     } catch (e) { }
   }
 }
 return XMLHttp;
}

var XMLHttp = getXMLHttp();
XMLHttp.open("GET", "sleep.php");
XMLHttp.onreadystatechange = function() {
 if (XMLHttp.readyState == 4) {
   window.alert("Returned data: " +
                XMLHttp.responseText);
 }
}
XMLHttp.send(null);
window.setTimeout("timeout();", 7000);

function timeout() {
 if (XMLHttp.readyState != 4 &&
     XMLHttp.readyState != 0) {
   XMLHttp.onreadystatechange = function() { };
   XMLHttp.abort();
   window.alert("Request aborted");
 }
}
</script>
Wait until 7 seconds and a javascript alert will tell you that request is aborted.

Hope this helps.

Accessing CSS Styles Using JavaScript

Monday, June 16, 2008

Almost any css properties can be set by javascript using the name of the css property as the Javascript property. The problem is, some characters like the dash("-") are not allowed within a JavaScript property. And we all know that CSS has many properties that contain dash in them, like font-family and border-right. Therefore, Javascript uses a lowerCamelCase syntax, which means that every component starts with an uppercase letter, but not the very first one. So font-family in CSS can be set using fontFamily property in Javascript.

There are 2 common ways to access CSS on the page: 1. using event handlers of HTML attributes and submitting a reference to the current element as parameter, like onClick="handler(this)". 2. accessing the element directly using document.getElementById("elementName")

Here's an example of the first approach:

<script language="javascript">
function useVerdana(elementName){
elementName.style.fontFamily="verdana";
}
</script>
<p id="myelement" onClick="useVerdana(this)">This is the element content</p>


And here's an example of the second approach, doing exactly the same thing:
<script language="javascript">
function useVerdana(){
var elementName=document.getElementById("myelement");
elementName.style.fontFamily="verdana";
}
</script>
<p id="myelement" onClick="useVerdana()">This is the element content</p>


And remember, there's NO DASH in javascript property!. That's actually the moral of this story.

Hope this helps,

Detecting Browser Type

Saturday, June 14, 2008

Since some css/don't run the same way on every browser, sometimes you have to detect what browser type is your visitor using, then decide what to do to your visitor accordingly.

The navigator JavaScript object provides browser informations, the most useful, but also sometimes not-easy to parse, is its userAgent property, which contains the complete browser identification string that is also sent in the HTTP User-Agent header with each request.

If you just want to determine the browser type, the window.alert(navigator.appName) will suffice, however the value returned is not always correct so you still have to look to the navigator.userAgent like this:<> br /

<script language="JavaScript" type="text/javascript">
var uA = navigator.userAgent;
var browserType = "unknown";
if (uA.indexOf("Opera") > -1) {
 browserType = "Opera";
} else if (uA.indexOf("Safari") > -1) {
 browserType = "Safari";
} else if (uA.indexOf("Konqueror") > -1) {
 browserType = "Konqueror";
} else if (uA.indexOf("Gecko") > -1) {
 browserType = "Mozilla";
} else if (uA.indexOf("MSIE") > -1) {
 browserType = "Internet Explorer";
}
window.alert(browserType);
</script>

As you can see, opera is checked first since the browser can identify itself as another browser. The point here is, with some effort to userAgent you can extend the script to detect more than just the name of the browser type, you can even get the version or the derivatives(with example as mozilla: k-meleon, firefox, ephipany, camino, etc).

More references can be found in http://www.webreference.com/tools/browser/javascript.html and http://gemal.dk/browserspy/basic.html

Hope this helps.

Debugging CSS and Browser Issues

Friday, June 13, 2008

Perhaps, the best tool I can recommend to debug CSS is firefox's Firebug and Web Developer Add-Onns. But sometimes they're just not enough, so I will give you a quick step by step manual of how to debuggin your css code and browser issues.

First, validate your HTML code. Go to http://validator.w3.org/ and simply correct every errors you may find. just copy paste the error to google and with some efforts you'll get the solution how to fix them.

Second, validate your CSS. Go to http://jigsaw.w3.org/css-validator/ and do the same thing as you do with your HTML code.

Third, simplify your CSS. Add new rule at the end of your stylesheet, using global selector and set properties for all elements, like this:

*{
margin: 0;
padding: 0;
}

Then, give border to every block-element so it become like this:
*{
margin: 0;
padding: 0;
border: solid 1px #000000
}

Comment out any css rule you suspect causing the errors, do it one-by-one until the problem recurs, and finally:

Find and research any similar problem through google. You may found some css bugs are well mentioned at expert-exchange. and http://www.positioniseverything.net/.

Hope that helps.

Fieldset and legend on IE6 and Firefox

Wednesday, June 4, 2008

Take a look at this simple css and html code, here's the css code:

fieldset{
background-color: #c0c0c0;
}
and here's the HTML part:
<fieldset>
<legend>Legend</legend>
<label for="something">something</label>
<input name="something" type="text">
</fieldset>
On firefox, it will be viewed like this:
fieldset standard in firefox
While on IE6, it will be viewed like this:
fieldset standard in IE6
And that's quite irritating. I don't know about other browser like safari and opera, but so far, here's a a quick code to solve the problem. You only need to change the css code.
fieldset {
display: block;
background-color: #c0c0c0;
position: relative;
}

legend {
padding: 0;
position: relative;
/* this works for IE6, to move up the legend */
top: -0.7em;
}

/* Hide this rule from IE */
legend {
/* on Gecko based browser we move the legend up with this */
margin-bottom: .3em;
}
The result is like this in Firefox:

And in IE6:

Finally, the background color in IE6 is not exceeded the top border, you can adjust the position of the content by adjusting the number yourself, I'm sure everybody is quite familiar with that.

SetAttribute on IE6 and firefox

Thursday, May 29, 2008

Say, you want to create an element using javascript with code like

<div class="myClass" onClick="myFunction()">inner HTML</div>
Now, the way to do it in firefox is by simply using javascript setAttribute like this:
<script language="javaScript">
element = document.createElement("div");
 element.appendChild(document.createTextNode("inner HTML"));
 element.setAttribute("class", myClass");
 element.setAttribute("onClick", "myFunction()");
</script>

But on Internet Explorer, that code won't work. It's broken. The class part should be written className on IE, so instead of >element.setAttribute("class", myClass"); it should be >element.setAttribute("className", myClass");, and what if you have many element attributes that you don't know whether they're applied the same way on IE and firefox ? like >style, id, name, on{Change, MouseOver, etc} ?

So far, here's the quick solution to do it, it's only a try catch block actually :
>
<script language="javaScript">
try {
   element = document.createElement("<div class=\"myClass\" onclick=\"myFunction()\">");
   element.appendChild(document.createTextNode("inner HTML"));
 } catch (e) {
   element = document.createElement("div");
 element.appendChild(document.createTextNode("inner HTML"));
 element.setAttribute("class", myClass");
 element.setAttribute("onClick", "myFunction()");
 }
</script>


Quite quick, eh ?