Please login or register.

Login with username, password and session length
Advanced search  

News:

You need/want an older version of sNews ? Download an older/unsupported version here.

Author Topic: [Tutorial] Javascript  (Read 2452 times)

nukpana

  • Hero Member
  • *****
  • Karma: 71
  • Posts: 663
[Tutorial] Javascript
« on: January 02, 2010, 03:28:07 PM »

Before I start, I know some are wondering what happened to the the Custom Template Part 2B, well all I can say is, it's in the works.... now then...

This tutorial is about Javascript applied (or how I have been applying it) to this CMS.

One of the things I have been doing is reducing the amount of inline Javascript in the core.  This helps keeping the core smaller (not by much...) and the outputted HTML cleaner as well. It follows the concepts of Unobtrusive Javascript - http://en.wikipedia.org/wiki/Unobtrusive_Javascript

Let's take a simple core function.

I will assume you know the basics but I will note a few things:
a. Javascript code should always be placed at the bottom of the page (before the closing body tag)
  - Based on that, Javascript shouldn't be placed inline in any HTML. 
     - ( We don't do this with CSS, why do we do it with Javascript? )
b. The basics like creating a var and getting elements.

Most of the time the basic uses will be like so:

Code: [Select]
if (document.getElementById("something")) {
var blah = document.getElementById("something");
blah.onEVENT_such_as_onclick = function();
}
What this is saying is if our ID exists, then when the event is done, do a function.
We see an example of this here: http://snewscms.com/forum/index.php?topic=8275.0

Ok, let's look at the pages function in snews.php

Code: (HTML) [Select]
<ul id="topmenu">
<li><a class="current" href="http://localhost/snews.17/">Home</a></li>
<li><a href="http://localhost/snews.17/archive/">Archive</a></li>
<li><a href="http://localhost/snews.17/contact/">Contact</a></li>
<li><a href="http://localhost/snews.17/sitemap/">Site Map</a></li>
</ul>

Code: (PHP) [Select]
// DISPLAY PAGES
function pages() {
global $categorySEF,$_No3;
$qwr = !_ADMIN ? ' AND visible=\'YES\'' : '';
$class = empty($categorySEF) ? ' class="current"' : '';
echo '<li><a'.$class.' href="'._SITE.'">'.l('home').'</a></li>';
$class = ($categorySEF == 'archive') ? ' class="current"' : '';
echo '<li><a'.$class.' href="'._SITE.'archive/">'.l('archive').'</a></li>';
$query = "SELECT id, seftitle, title FROM "._PRE.'articles'." WHERE position = 3 $qwr ORDER BY artorder ASC, id";
$result = mysql_query($query);
$num = mysql_num_rows($result);
while ($r = mysql_fetch_array($result)) {
$title = $r['title'];
$class = ($categorySEF == $r['seftitle'])? ' class="current"' : '';
if ($r['id'] != s('display_page')) {
echo '<li><a'.$class.' href="'._SITE.$r['seftitle'].'/">'.$title.'</a></li>';
}
}
$class = ($categorySEF == 'contact') ? ' class="current"': '';
echo '<li><a'.$class.' href="'._SITE.'contact/">'.l('contact').'</a></li>';
$class = ($categorySEF == 'sitemap') ? ' class="current"': '';
echo '<li><a'.$class.' href="'._SITE.'sitemap/">'.l('sitemap').'</a></li>';
if ($num) $_No3 = true;
}

At first glance, we can see some code is being used for adding a class element to the current page.  5 lines to be exact and oddly enough, there is not a CSS style to with this style - oops!  Can't we break this down more??

Code: (PHP) [Select]
// DISPLAY PAGES
function pages() {
global $categorySEF,$_No3;
$qwr = !_ADMIN ? ' AND visible=\'YES\'' : '';
echo '<li><a href="'._SITE.'">'.l('home').'</a></li>';
echo '<li><a href="'._SITE.'archive/">'.l('archive').'</a></li>';
$query = "SELECT id, seftitle, title FROM "._PRE.'articles'." WHERE position = 3 $qwr ORDER BY artorder ASC, id";
$result = mysql_query($query);
$num = mysql_num_rows($result);
while ($r = mysql_fetch_array($result)) {
$title = $r['title'];
if ($r['id'] != s('display_page')) {
echo '<li><a href="'._SITE.$r['seftitle'].'/">'.$title.'</a></li>';
}
}
echo '<li><a href="'._SITE.'contact/">'.l('contact').'</a></li>';
echo '<li><a href="'._SITE.'sitemap/">'.l('sitemap').'</a></li>';
if ($num) $_No3 = true;
}

Good, the function is a little bit leaner and some unneeded code is now out of the core. So how are we to get that class back?

Code: [Select]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
body { width: 750px; margin: 0 auto; }
li { list-style: none; display: inline; }
#header h1 { float: left; }
#topNav { float: right; margin-top: 30px; }
#topNav li a{ padding-right: 10px; }
.current { color: black; text-decoration: none; }
</style>
</head>
<body>
<div id="header">
<h1>siteName</h1>
<ul id="topmenu">
<li><a href="http://localhost/snews.17/">Home</a></li>
<li><a href="http://localhost/snews.17/archive/">Archive</a></li>
<li><a href="http://localhost/snews.17/contact/">Contact</a></li>
<li><a href="http://localhost/snews.17/sitemap/">Site Map</a></li>
</ul>
</div>
<script type="text/javascript">
var link = document.getElementsByTagName("a");
for ( var i=0; i<link.length; i++ ) {
if ( link[i].href == window.location ) {
link[i].setAttribute("class", "current");
}
}

</script>
</body>
</html>

Ok what is going on??

Code: [Select]
var link = document.getElementsByTagName("a");First, we are getting an array of all a links,

Code: [Select]
for ( var i=0; i<link.length; i++ ) {then cycle through them.

Code: [Select]
if ( link[i].href == window.location ) {If one of the links is equal to the current url...

Code: [Select]
link[i].setAttribute("class", "current");then add a class attribute to the a element.

If you haven't noticed, this is applied to all links in the document. So we could remove more code from the core like so:

Code: (function categories) [Select]
$class = $category_title == $categorySEF ? ' class="current"' : '';
or
Code: (function subcategories) [Select]
$class = $subSEF == $subcatSEF ? ' class="current"' : '';
Logged

nukpana

  • Hero Member
  • *****
  • Karma: 71
  • Posts: 663
Re: [Tutorial] Javascript
« Reply #1 on: January 02, 2010, 07:05:15 PM »

AJAX.

A quick word about AJAX.  99% of what will be used by users here is not AJAX.  The X is XML and most of the responses are text/HTML and JSON.

So how do we do it (in it's basic form)?

Well we need the basic Request functions:
Code: (Javascript) [Select]
// Base AJAX functions

// Get the new Request object
function XHR() {
var xhr = false;
xhr = window.ActiveXObject
? new ActiveXObject("Microsoft.XMLHTTP")
: new XMLHttpRequest();
return xhr;
}

// Build the request and get the reply back
// snd is the parameters, with GET this is null, with POST, it is the sent parameters
// type is either GET or POST
function request( url, snd, callback, type ) {
var http = XHR();
if (http) {
http.onreadystatechange = callback;
};
http.open(type, url, true);
if (type == "POST") {
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", snd.length);
http.setRequestHeader("Connection", "close");
}
http.send(snd);
}

NOTE - If you are a jQuery user you will note the request function is similar to jQuery's ajax functions.

Now let's make a page to do the request.  First we will do a GET request:
Code: (name the page test.php) [Select]
<?php

function showRes() {
if (isset($_GET['res'])) {
echo ' You clicked me!!';
die();
}
}
showRes();

?>

<a href="#" id="something">Click Me</a>
<div id="result"></div>

<script>
window.onload = function() {
showResult();
}

// Base AJAX functions
function XHR() {
var xhr = false;
xhr = window.ActiveXObject
? new ActiveXObject("Microsoft.XMLHTTP")
: new XMLHttpRequest();
return xhr;
}

function request( url, snd, callback, type ) {
var http = XHR();
if (http) {
http.onreadystatechange = callback;
};
http.open(type, url, true);
if (type == "POST") {
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", snd.length);
http.setRequestHeader("Connection", "close");
}
http.send(snd);
}

function showResult() {
var blh = document.getElementById("something");
blh.onclick = function() {
request(
"test.php?res=something",
null,
function() {
var res = document.getElementById("result");
res.innerHTML = this.responseText;
},
'GET'
);
}
}
</script>

Our showResult function is no different from the first posted code in this thread. We get an variable by calling it's ID, then we add a function to the event, here being onclick.

The response function is calling it's parameters:
url - test.php?res=something
snd = null as this is a GET request
callback is our function to do when we get the reponse back
type is GET

PHP then gets the GET variable and sends back the request and calls die() to only send what we need.

A AJAX POST looks like this:
Code: [Select]
<?php

function showUserName() {
if (isset($_POST['name'])) {
echo ' Your name is '.$_POST['name'];
die(); 
}
}
showUserName();

?>

<form method="post" action="#">
<label for="userName">Your Name is</label>
<input id="userName" name="userName" type="text" />
<input type="submit" name="formSubmit" value="Submit" />
</form>
<div id="formResult"></div

<script>
window.onload = function() {
showName();
}

// Base AJAX functions
function XHR() {
var xhr = false;
xhr = window.ActiveXObject
? new ActiveXObject("Microsoft.XMLHTTP")
: new XMLHttpRequest();
return xhr;
}

function request( url, snd, callback, type ) {
var http = XHR();
if (http) {
http.onreadystatechange = callback;
};
http.open(type, url, true);
if (type == "POST") {
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", snd.length);
http.setRequestHeader("Connection", "close");
}
http.send(snd);
}

function showName() {
var frm = document.forms[0];
frm.onsubmit = function() {
request(
"test.php",
"name=" + encodeURIComponent(frm.userName.value),
function() {
var res = document.getElementById("formResult");
res.innerHTML = this.responseText;
},
'POST'
);
return false;
}
}

</script>


Not that much different than the first example.  This time we are using a form (what else for POST?).  What is different is the snd parameter has the form values now and we are returning false so the AJAX response is coming through where we want.
« Last Edit: January 03, 2010, 01:44:31 AM by nukpana »
Logged