Location: PHPKode > projects > OpenWolf Guidelines Validator > openWolf 0.9.9/wai/rules.php
<?php

/*************************************************

openWolf - an HTML accessibility guidelines validator
Author: Geoff Munn (hide@address.com)
Version: 0.9.9

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

You may contact the author of openWolf by e-mail at: hide@address.com

The latest version of openWolf can be obtained from:
http://openwolf.sourceforge.net/

*************************************************/

//GLOBAL TODO LIST:
/*
Check that all user checks are actually appropriately labeled... some could be warnings for instance.
Remove all examples of getAllElements.  The lookup tables are much faster
Rejig the basic interface so that rules that apply to both priority 1 & 2 can still be checked
Fix up all the dictionaries to not use byref arrays
*/

define('PRIORITY_MUST', 'Must');
define('PRIORITY_SHOULD', 'Should');
define('PRIORITY_MAY', 'May');

define('RESULT_PASS', 0);
define('RESULT_WARNING', 1);
define('RESULT_FAIL', 2);
define('RESULT_USER', 3);

define('USER_CHECK', 'The site administrator needs to confirm this.');

define('INSTANCE_LIMIT', 3);
define('MAX_CHILDREN_SHOWN', 3);

function rules($parse, $colours, $options){

	$wai=Array();
	
	$level1=$options['priority1'];
	$level2=$options['priority2'];
	$level3=$options['priority3'];
	
	//we need to check the rules in guideline order, NOT priority order:
	//Guideline 1:
	if($level1)
		$wai['WAI_1_1_1']=wai_1_1_1($parse);
	if($level1)
		$wai['WAI_1_1_2']=wai_1_1_2($parse);
	if($level1)
		$wai['WAI_1_1_3']=wai_1_1_3($parse);
	if($level1)
		$wai['WAI_1_1_4']=wai_1_1_4($parse);
	if($level3)
		$wai['WAI_3_1_5']=wai_3_1_5($parse);
		
	//Guideline 2:
	if($level1)
		$wai['WAI_1_2_1']=wai_1_2_1($parse, $colours);
	//THIS NEEDS TO BE FIXED TO SWITCH BETWEEN PRIORITY TYPES:
	if($level2 || $level3)
		$wai['WAI_2_2_2']=wai_2_2_2($parse, $colours);
	
	//Guideline 3:
	if($level2)
		$wai['WAI_2_3_1']=wai_2_3_1($parse);
	if($level2)
		$wai['WAI_2_3_2']=wai_2_3_2($parse);
	if($level2)
		$wai['WAI_2_3_3']=wai_2_3_3($parse);
	if($level2)
		$wai['WAI_2_3_4']=wai_2_3_4($parse);
	if($level2)
		$wai['WAI_2_3_5']=wai_2_3_5($parse);
	if($level2)
		$wai['WAI_2_3_6']=wai_2_3_6($parse);
	if($level2)
		$wai['WAI_2_3_7']=wai_2_3_7($parse);
		
	//Guideline 4
	if($level1)
		$wai['WAI_1_4_1']=wai_1_4_1($parse);
	if($level3)
		$wai['WAI_3_4_2']=wai_3_4_2($parse);
	if($level3)
		$wai['WAI_3_4_3']=wai_3_4_3($parse);
		
	//Guideline 5
	if($level1)
		$wai['WAI_1_5_1']=wai_1_5_1($parse);
	if($level1)
		$wai['WAI_1_5_2']=wai_1_5_2($parse);
	if($level2)
		$wai['WAI_2_5_3']=wai_2_5_3($parse);
	if($level2)
		$wai['WAI_2_5_4']=wai_2_5_4($parse);
	if($level3)
		$wai['WAI_3_5_5']=wai_3_5_5($parse);
	if($level3)
		$wai['WAI_3_5_6']=wai_3_5_6($parse);
		
	//Guideline 6
	if($level1)
		$wai['WAI_1_6_1']=wai_1_6_1($parse);
	if($level1)
		$wai['WAI_1_6_2']=wai_1_6_2($parse);
	if($level1) 
		$wai['WAI_1_6_3']=wai_1_6_3($parse);
	if($level2)
		$wai['WAI_2_6_4']=wai_2_6_4($parse);
	if($level2)
		$wai['WAI_2_6_5']=wai_2_6_5($parse);
		
	//Guideline 7
	if($level1)
		$wai['WAI_1_7_1']=wai_1_7_1($parse);
	if($level2)
		$wai['WAI_2_7_2']=wai_2_7_2($parse);
	if($level2)
		$wai['WAI_2_7_3']=wai_2_7_3($parse);
	if($level2)
		$wai['WAI_2_7_4']=wai_2_7_4($parse);
	if($level2)
		$wai['WAI_2_7_5']=wai_2_7_5($parse);
		
	//Guideline 8
	//THIS NEEDS TO BE FIXED TO SWITCH BETWEEN PRIORITY TYPES:
	if($level1 || $level2)
		$wai['WAI_2_8_1']=wai_2_8_1($parse);
	
	//Guideline 9
	if($level1)
		$wai['WAI_1_9_1']=wai_1_9_1($parse);
	if($level2)
		$wai['WAI_2_9_2']=wai_2_9_2($parse);
	if($level2)
		$wai['WAI_2_9_3']=wai_2_9_3($parse);
	if($level3)
		$wai['WAI_3_9_4']=wai_3_9_4($parse);
	if($level3)
		$wai['WAI_3_9_5']=wai_3_9_5($parse);
	
	//Guideline 10
	if($level2)
		$wai['WAI_2_10_1']=wai_2_10_1($parse);
	if($level2)
		$wai['WAI_2_10_2']=wai_2_10_2($parse);
	if($level3)
		$wai['WAI_3_10_3']=wai_3_10_3($parse);
	if($level3)
		$wai['WAI_3_10_4']=wai_3_10_4($parse);
	if($level3)
		$wai['WAI_3_10_5']=wai_3_10_5($parse);
	
	//Guideline 11
	if($level2)
		$wai['WAI_2_11_1']=wai_2_11_1($parse);
	if($level2)
		$wai['WAI_2_11_2']=wai_2_11_2($parse);
	if($level3)
		$wai['WAI_3_11_3']=wai_3_11_3();
	if($level1)
		$wai['WAI_1_11_4']=wai_1_11_4($wai);
	
	//Guideline 12
	if($level1)
		$wai['WAI_1_12_1']=wai_1_12_1($parse);
	if($level2)
		$wai['WAI_2_12_2']=wai_2_12_2($parse);
	if($level2)
		$wai['WAI_2_12_3']=wai_2_12_3();
	if($level2)
		$wai['WAI_2_12_4']=wai_2_12_4($parse);
		
	//Guideline 13
	if($level2)
		$wai['WAI_2_13_1']=wai_2_13_1($parse);
	if($level2)
		$wai['WAI_2_13_2']=wai_2_13_2($parse);
	if($level2)
		$wai['WAI_2_13_3']=wai_2_13_3();
	if($level2)
		$wai['WAI_2_13_4']=wai_2_13_4();
	if($level3)
		$wai['WAI_3_13_5']=wai_3_13_5();
	if($level3)
		$wai['WAI_3_13_6']=wai_3_13_6();
	if($level3)
		$wai['WAI_3_13_7']=wai_3_13_7($parse);
	if($level3)
		$wai['WAI_3_13_8']=wai_3_13_8();
	if($level3)
		$wai['WAI_3_13_9']=wai_3_13_9();
	if($level3)
		$wai['WAI_3_13_10']=wai_3_13_10($parse);
		
	//Guideline 14
	if($level1)
		$wai['WAI_1_14_1']=wai_1_14_1($parse);
	if($level3)
		$wai['WAI_3_14_2']=wai_3_14_2();
	if($level3)
		$wai['WAI_3_14_3']=wai_3_14_3($parse);
	
	return $wai;
}

function WAI_1_1_1($parse){
	//Provide a text equivalent for every non-text element (for example alt, longdesc or in element content). This includes: images, graphical representations of text (including symbols),
	//image map regions, animations (for example, animated GIFs), applets and programmatic options, ASCII art, frames, scripts, images used as list bullets, spacers, graphical buttons, 
	//sounds (played with or without user interaction), standalone audio files, audio tracks of video, and video.
	
	//Priority:		Must

	//Techniques:	

	//TODO: check that the longdesc is a valid URI and that it is HTML
	//TODO:	The file size check on alt text will not detect anything in shorthand, ie 10KB
	//TODO:	Should the long alt text check apply for applets and objects?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Provide a text equivalent for every non-text element (e.g., via &quot;alt&quot;, &quot;longdesc&quot;, or in element content). This includes: images, graphical representations of text (including symbols), image map regions, animations (e.g., animated GIFs), applets and programmatic objects, ascii art, frames, scripts, images used as list bullets, spacers, graphical buttons, sounds (played with or without user interaction), stand-alone audio files, audio tracks of video, and video.';
	$results['header']='g1';
		
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('img');
	
	//Put all of the images into an array so we can identify decorative images
	$images=Array();
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$src=$parse->src($this_element);
		
		if(!isset($images[$src]))
			$images[$src]=false;
		else
			$images[$src]=true;
		
	}
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
		
		$alt=trim($parse->getAttribute($this_element, 'alt', true));
		$specified=$parse->specified($this_element, 'alt');
		if(!$specified){
			$result_key='This image is missing an \'alt\' attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
		if($alt=='' && $specified && $images[$src]==false){
			//check to see if the height and width attributes are both less than 10 pixels
			$width=$parse->getAttribute($this_element, 'width');
			$height=$parse->getAttribute($this_element, 'height');
			if($width>10 || $height>10 || $width=='' || $height==''){
				$result_key='The \'alt\' attribute value is empty.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$results['instances'][$result_key]['info'][]='If this image is not purely decorative, then you could put a short description of the image in an alt attribute, for example, alt=&quot;Company logo&quot;<br>If it is decorative, then an empty alt attribute should be fine.';
				$hasFailed=true;
			}
		}
		if(substr($alt, -5)=='bytes'){
			$result_key='The \'alt\' attribute value seems to be a file size (it ends with \'bytes\').';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
		}
		if(substr($alt,-3)=='jpg' || substr($alt,-3)=='gif' || substr($alt, -4)=='jpeg' || substr($alt, -3)=='png' || substr($alt, -3)=='bmp'){
			$result_key='The \'alt\' attribute value ends with an image file suffix.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
		if(strlen($alt)>150){
			$result_key='The \'alt\' attribute value is longer than 150 characters. Perhaps a description file could be created.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('input');
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$type=$parse->getAttribute($this_element, 'type');
		if($type=='image'){
			$alt=trim($parse->getAttribute($this_element, 'alt', true));
			$specified=$parse->specified($this_element, 'alt');
			if(!$specified){
				$result_key='This form image is missing an \'alt\' attribute.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
			if($alt==''  && $specified){
				$result_key='The \'alt\' attribute value is empty.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$hasFailed=true;
			}
			if(substr($alt, -5)=='bytes'){
				$result_key='The \'alt\' attribute value seems to be a file size (it ends with \'bytes\').';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$hasFailed=true;
			}
			if(substr($alt,-3)=='jpg' || substr($alt,-3)=='gif' || substr($alt, -4)=='jpeg' || substr($alt, -3)=='png' || substr($alt, -3)=='bmp'){
				$result_key='The \'alt\' attribute value ends with an image file suffix.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$hasFailed=true;
			}
		}		
	}
	
	$temp=$parse->getElementsByTagname('applet');
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$type=$parse->getAttribute($this_element, 'type');
		$text=trim($parse->innerText($this_element));
		
		if(!$parse->specified($this_element, 'alt') && $text==''){
			$result_key='This applet is missing a text equivalent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
		
		$alt=trim($parse->getAttribute($this_element, 'alt', true));
		$specified=$parse->specified($this_element, 'alt');
		if(!$specified){
			$result_key='The \'alt\' attribute value is not specified.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
		if(trim($alt)=='' && $specified){
			$result_key='The \'alt\' attribute value is empty.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
		if(substr($alt, -5)=='bytes'){
			$result_key='The \'alt\' attribute value seems to be a file size (it ends with \'bytes\').';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
		if(substr($alt,-6)=='.class' || substr($alt,-5)=='.java' || substr($alt, -4)=='.jar' || substr($alt, -4)=='.zip'){
			$result_key='The \'alt\' attribute value ends with a java file suffix.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('object');
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$type=$parse->getAttribute($this_element, 'type', true);
		$mime=substr($type, 0, 6);
		
		if($mime=='image/'){
			//does this object element contain at least one word of text or an image element:
			$innerText=$parse->innerText($this_element);
			$imgs=$parse->all_descendants($this_element, 'img');
			if(strlen(trim($innerText))==0 && count($imgs)==0){
				$result_key='This object element is missing an alternative representation.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
		if($mime=='audio/' || $mime=='video/'){
			$result_key='Audio and video files require a text equivalent. Is there an associated text equivalent for this audio or video file?';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='data';
			$hasFailed=true;
		}	
	}
	
	$temp=$parse->getElementsByTagname('a');
	$sound_files=load_sound_extensions();
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$href=$parse->href($this_element);
		$href2=$parse->getAttribute($this_element, 'href');
		$extension=strtolower(get_extension($href));
		if(array_key_exists($extension, $sound_files)){
			$result_key='Audio files require a text equivalent. Is there an associated text equivalent for this audio file: ' . $href2 . '?';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='href';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('frame');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		//TODO: check that the longdesc is a valid URI and that it is HTML
		$longdesc=trim($parse->getAttribute($this_element, 'longdesc'));
		if($longdesc==''){
			$result_key='This frame is missing a longdesc attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}	
	}
	$temp=$parse->getElementsByTagname('frameset');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$frames=$parse->all_descendants($this_element, 'frame');
		if(count($frames)>2){
			for($i=0;$i<count($frames);$i++){
				$longdesc=trim($parse->getAttribute($this_element, 'longdesc'));
				if($longdesc==''){
					$result_key='Is the relationship between the frames clear for the user?';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_WARNING;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;					
				}
			}
		}
	}
	
	$temp=$parse->getElementsByTagname('iframe');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$longdesc=trim($parse->getAttribute($this_element, 'longdesc'));
		//TODO: check that the longdesc is a valid URI and that it is HTML
		if($longdesc==''){
			$result_key='This iframe is missing a longdesc attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}	
	}
	
	//NOTE: perhaps this should use the specifed approach instead? And also check for empty alt text
	$temp=$parse->getElementsByTagname('area');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$alt=$parse->getAttribute($this_element, 'alt');
		//Todo: put in suspicious placeholder text
		if(trim($alt)==''){
			$result_key='This image map area is missing an \'alt\' text attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('script');
	$bodys=$parse->getElementsByTagname('body');
	$all=$parse->getAllElements();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		if($this_element>$bodys[0]){
			//is the next element a <noscript> element?
			//checking for a closing tag will stop the {else} bit from working (false positives are generated)
			if($all[$this_element+2]['tagname']!='noscript'){
				$result_key='This script element is missing a <code>noscript</code> alternative.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			} else {
				$innerHTML=$parse->innerHTML($this_element+2);
				if(trim($innerHTML)==''){
					$result_key='This noscript element does not contain accessible HTML.';
					$results['instances'][$result_key]['indices'][]=$this_element+2;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}				
			}
		}	
	}
	
	if(!$hasFailed){
		$result_key='A text equivalent was provided for every non-text element.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_1_2($parse){
	//Provide redundant text links for each active region of server-side image maps except where the regions cannot be defined with an available geometric shape.
	
	//Priority:		Must
	
	//Techniques:	Find any <img> elements with ismap=true
	
	//Comments:		Server side image maps don't reveal their destinations, so I can't check to see if there are redundant links present
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Provide redundant text links for each active region of a server-side image map.';
	$results['header']='g1';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('img');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			//NOTE: can ismap='false' be valid?  I don't think so...
			if($parse->specified($this_element, 'ismap')==true){
				$result_key='All server-side image maps should have associated text links in the document.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		} 
		if(!$hasFailed){
			$result_key='No server-side image maps were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No server-side image maps were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_1_3($parse){
	//Until user agents can automatically read aloud the text equivalent of a visual track, provide an auditory description of the important information of the visual track of a multimedia presentation.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#auditory-descriptions
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Until user agents can automatically read aloud the text equivalent of a visual track, provide an auditory description of the important information of the visual track of a multimedia presentation.';
	$results['header']='g1';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('object');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$type=$parse->getAttribute($this_element, 'type', true);
		if(substr($type, 0, 5)=='video'){
			$result_key='All multimedia presentations should have an associated audio description.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No multimedia presentations were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_1_4($parse){
	//For any time-based multimedia presentation (e.g., a movie or animation), synchronize equivalent alternatives (e.g., captions or auditory descriptions of the visual track) with the presentation.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#av-in-dynamic-objects
	
	//Note:			Is the object element enough?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='For any time-based multimedia presentation (e.g., a movie or animation), synchronize equivalent alternatives (e.g., captions or auditory descriptions of the visual track) with the presentation.';
	$results['header']='g1';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('object');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$type=$parse->getAttribute($this_element, 'type');
		if(strtolower(substr($type, 0, 5))=='video'){
			$result_key='All multimedia presentations should have synchronized equivalents.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No multimedia presentations were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_2_1($parse, $colours){
	//Ensure that all information conveyed with color is also available without color, for example from context or markup.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#color-convey
	
	//Note:			This does not check for inline styles
	//				This should try to match an element to the colour
	//TODO:			This should confirm that the colour that has been mentioned actually appears somewhere in the page
	
	//NOTE:			We are not checking for background colours, or anything else; just font colours
	
	//TODO:			The colour 'pink' comes back as 'light red'
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Ensure that all information conveyed with color is also available without color, for example from context or markup.';
	$results['header']='g2';
	
	$hasFailed=false;
		
	$colour_list=Array();
	
	$temp=$parse->getElementsByTagname('font');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$colour=$parse->getAttribute($this_element, 'color');
		if($colour!=''){
			$colour_details=$colours->get_colour_details($colour);
			$colour_list[]=$colour_details['colour'];
		}
	}
	
	//check each element for styles:
	
	$all_colour_styles=$parse->getStylesByProperty('color');
	foreach($all_colour_styles as $this_style){
		
		if(time()>$timeout)
			break;
				
		$colour_details=$colours->get_colour_details($this_style['value']);
		if(!in_array($colour_details['colour'], $colour_list))
			$colour_list[]=$colour_details['colour'];
		
	}
	//so now we have all the colours:
	$innerText=strtolower($parse->bodyInnerText());
	$all_words=str_word_count($innerText, 1);
	foreach($colour_list as $this_colour){
		
		if(time()>$timeout)
			break;
				
		if(in_array(strtolower($this_colour), $all_words)){
			$result_key="The colour '<span class=\"quote\">" . $this_colour . "</span>' is referred to in the text of the page.";
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='Font colour was not relied upon to impart meaning.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_4_1($parse){
	//Clearly identify changes in the natural language of a document's text and any text equivalents, for example captions.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#language
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']="Clearly identify changes in the natural language of a document's text and any <a href=\"#text-equivalent\">text equivalents</a> (e.g., captions).<br>For example, in HTML use the &quot;lang&quot; attribute. In XML, use &quot;xml:lang&quot;.";
	$results['header']='g4';
		
	$text=$parse->bodyInnerText();
	if(str_word_count($text)>2){
		$result_key='Any words or phrases in a document that are not in the primary language of the document should be identified.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	} else {
		$result_key='No need for language identification was found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_5_1($parse){
	//For data tables, identify row and column headers.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#table-headers
	
	//NOTE:			We are ignoring the AXIS attribute
	//				Please review
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='For data tables, identify row and column headers.';
	$results['header']='g5';
	
	$hasFailed=false;
	$found=false;
	$foundHeaders=false;
	$foundRows=false;
	
	$temp=$parse->getElementsByTagname('table');
	if(count($temp)){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			//check each td and th element and check for the presence of either 'scope' or 'headers' attributes
			if(is_data_table($parse, $this_element)){
				//this is a data table
				$found=true;
				$foundRows=false;
				$foundHeaders=false;
				$descendants=$parse->all_descendants($this_element);
				foreach($descendants as $this_descendant){
					
					if(time()>$timeout)
						break;
						
					$tagname=$parse->tagname($this_descendant);
					if($tagname=='td' || $tagname=='th'){
						$scope=$parse->getAttribute($this_descendant, 'scope');
						$headers=$parse->getAttribute($this_descendant, 'headers');
						if($scope!='' || $headers!=''){
							
							if($tagname=='th')
								$foundHeaders=true;
							else
								$foundRows=true;
							
						}
					}
				}
				
				if($foundHeaders==false && $foundRows==false){
					$result_key='This table is missing headers.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				} else {
					
					if(!$foundHeaders){
						$result_key='This table has column headers but may require row headers.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					}
					if(!$foundRows){
						$result_key='This table has row headers but may require column headers.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					}
					//if($foundHeaders && $foundRows){
					//	$result_key='This table has identified the rows and columns.';;
					//	$results['instances'][$result_key]['indices'][]=$this_element;
					//	$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					//	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					//	$results['instances'][$result_key]['highlight_attribute'][]='';
					//	$hasFailed=false;
					//}
				}
			}
		}
		//This doesn not necessaryily make sense... but anyhoo:
		if(!$hasFailed){
			if($found){
				$result_key='All data tables included row or column headers.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No data tables were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No tables were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_5_2($parse){
	//For data tables that have two or more logical levels of row or column headers, use markup to associate data cells and header cells.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#table-structure
	
	//NOTE:			We are ignoring the AXIS attribute
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='For data tables that have two or more logical levels of row or column headers, use markup to associate data cells and header cells.';
	$results['header']='g5';
	
	$hasFailed=true;
	$found=false;
	$foundHeaders=false;
	$foundRows=false;
	
	$temp=$parse->getElementsByTagname('table');
	if(count($temp)){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$row_count=0;
			$col_count=0;
			$max_cols=0;
			//check each td and th element and check for the presence of either 'scope' or 'headers' attributes
			if(is_data_table($parse, $this_element)){
				//this is a data table
				$found=true;
				$foundRows=false;
				$foundHeaders=false;
				$descendants=$parse->all_descendants($this_element);
				foreach($descendants as $this_descendant){
					
					if(time()>$timeout)
						break;
				
					$tagname=$parse->tagname($this_descendant);
					if($tagname=='td' || $tagname=='th'){
						$col_count++;
						$scope=$parse->getAttribute($this_descendant, 'scope');
						$headers=$parse->getAttribute($this_descendant, 'headers');
						if($scope!='' || $headers!=''){
							
							if($tagname=='th')
								$foundHeaders=true;
							else
								$foundRows=true;
							
						}
					}
					if($tagname=='tr'){
						
						if($col_count>$max_cols)
							$max_cols=$col_count;	
						
						$row_count++;
					}
				}
				if($row_count>1 || $max_cols>1){
					if($foundHeaders==false && $foundRows==false){
						$result_key='This table is missing headers.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					} else {
						if(!$foundHeaders){
							$result_key='This table has column headers but may require row headers.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$hasFailed=true;
						}
						if(!$foundRows){
							$result_key='Table has row headers but may require column headers.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$hasFailed=true;
						}
						//if($foundHeaders && $foundRows){
						//	$result_key='This table has identified the rows and columns.';
						//	$results['instances'][$result_key]['indices'][]=$this_element;
						//	$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						//	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						//	$results['instances'][$result_key]['highlight_attribute'][]='';
						//	$hasFailed=true;
						//}
					}
				} else {
					$result_key='No data tables require rows or columns to be identified.';
					$results['instances'][$result_key]['indices'][]=-1;
					$results['instances'][$result_key]['type'][]=RESULT_PASS;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=false;
				}
			}
		}
		if($hasFailed){
			if($found){
				$result_key='All data tables included row or column headers.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No data tables were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No tables were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_6_1($parse){
	//Organise documents so they may be read without stylesheets.  For example, when an HTML document is rendered without associated style sheets, it must still be possible to read the document.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#style-sheet-guidelines
	
	//TODO:			Are the text/css checks too restrictive?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Organize documents so they may be read without style sheets. For example, when an HTML document is rendered without associated style sheets, it must still be possible to read the document.';
	$results['header']='g6';
	
	$found=false;
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('link');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$rel=$parse->getAttribute($this_element, 'rel', true);
		$type=$parse->getAttribute($this_element, 'type', true);
		$media=$parse->getAttribute($this_element, 'media', true);
		//NOTE: This does not check to see if there is an href attribute or that it is valid
		
		if(($rel=='stylesheet' || $rel=='alternate' || $rel=='') && $type=='text/css' && ($media=='' || $media=='all' || $media=='screen')){
			$result_key='Please ensure that this document can be read without style sheets.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$found=true;
			$hasFailed=true;
			break;
		}
	}
	
	if(!$found){
		$temp=$parse->getElementsByTagname('style');
		$found=false;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$type=$parse->getAttribute($this_element, 'type', true);
			$media=$parse->getAttribute($this_element, 'media', true);
			if($type=='text/css' && ($media=='' || $media=='all' || $media=='screen')){
				$found=true;
				break;
			}
		}
		//check that at least one of these has text/css as a type
		if($found){
			$result_key='Please ensure that this document can be read without style sheets.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
			$found=true;
		}
	}
	
	if(!$found){
		//$temp=$parse->getAllElements();
		$temp=$parse->getElementsByAttribute('style');
		if(sizeof($temp)>0){
			$result_key='Please ensure that this document can be read without style sheets.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
		/*foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($this_element['is_closing']==false && $this_element['tagname']!='!'){
				$has_style=$parse->specified($this_element['elementIndex'], 'style');
				if($has_style){
					$result_key='Please ensure that this document can be read without style sheets.';
					$results['instances'][$result_key]['indices'][]=-1;
					$results['instances'][$result_key]['type'][]=RESULT_WARNING;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					$found=true;
					break;
				}
			}
		}*/
	}
	if(!$hasFailed){
		$result_key='No style sheets were used.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_6_2($parse){
	//Ensure that equivalents for dynamic content are updated when the dynamic content changes.
	
	//Priority:		must
	
	//Techniques:	http://www.w3.org/TR/AERT#frame-has-html-src
	
	//Note:			Is the list of common extensions sufficient?
	//				For the purpose of this, we are assuming that 'valid' means a supported file type
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Ensure that equivalents for dynamic content are updated when the dynamic content changes.';
	$results['header']='g6';
	
	$hasFailed=false;
	$found=false;
	
	$extensions=load_common_extensions();
	
	$temp=$parse->getElementsByTagname('frame');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$src=$parse->src($this_element);
			$this_extension=get_extension($src);
			if($this_extension!=''){
				if(!isset($extensions[$this_extension])){
					$result_key='This frame does not contain a valid markup file.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='src';
					$hasFailed=true;
				}
			}
		}
	}
	
	$temp=$parse->getElementsByTagname('iframe');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$src=$parse->src($this_element);
			$this_extension=get_extension($src);
			if($this_extension!=''){
				if(!isset($extensions[$this_extension])){
					$result_key='This iframe does not contain a valid markup file.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='src';
					$hasFailed=true;
				}
			}
		}
	}
	
	if(!$hasFailed){
		if($found){
			$result_key='All frames contained valid markup files.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;	
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		} else {
			$result_key='All frames contained valid markup files.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	return $results;
}

function WAI_1_6_3($parse){
	//Ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.  If this is not possible, provide equivalent information on an alternative accessible page.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#scripts
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported. If this is not possible, provide equivalent information on an alternative accessible page.';
	$results['header']='g6';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('script');
	if(count($temp)>0){
		$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;
	}
	if(!$hasFailed){
		$temp=$parse->getElementsByTagname('object');
		if(count($temp)>0){
			$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$temp=$parse->getElementsByTagname('applet');
		if(count($temp)>0){
			$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$temp=$parse->getElementsByTagname('embed');
		if(count($temp)>0){
			$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$result_key='No scripts, applets or other programmatic objects were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;	
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_7_1($parse){
	//Until user agents allow users to control flickering, avoid causing the screen to flicker.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#avoid-flicker
	
	//TODO:			Fix this to only include animated gifs
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> allow users to control flickering, avoid causing the screen to flicker.";
	$results['header']='g7';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('script');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$result_key='Display flicker is distracting and may be dangerous to some users. Please ensure this element does not cause the display to flicker.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('object');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$result_key='Display flicker is distracting and may be dangerous to some users. Please ensure this element does not cause the display to flicker.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('embed');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$result_key='Display flicker is distracting and may be dangerous to some users. Please ensure this element does not cause the display to flicker.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('applet');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$result_key='Display flicker is distracting and may be dangerous to some users. Please ensure this element does not cause the display to flicker.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('img');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$extension=get_extension($parse->src($this_element));
		
		if($extension=='gif'){
			$result_key='Display flicker is distracting and may be dangerous to some users. Please ensure this element does not cause the display to flicker.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No sources of flickering were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_9_1($parse){
	//Provide redundant text links for each active region of server-side image maps except where the regions cannot be defined with an available geometric shape.
	
	//Priority:		Must
	
	//Techniques:	Find any <img> elements with ismap=true
	
	//Note:			We cannot actually check for server-side image map links, so we just raise a warning...
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Provide client-side image maps instead of server-side image maps except where the regions cannot be defined with an available geometric shape.';
	$results['header']='g9';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('img');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'ismap')==true){
				$result_key='Use client-side image maps instead of server-side maps.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		} 
		if(!$hasFailed){
			$result_key='No server-side image maps were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No images were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_11_4($wai){
	//If, after best efforts, you cannot create an accessible page, provide a link to an alternative page that uses W3C technologies, is accessible, has equivalent information (or functionality), and is updated as often as the inaccessible (original) page.
	
	//Priority:		Must
	
	//Techniques:	Mark as a user check
	
	//NOTES:		This only raises a warning on 'fail' types, not 'warnings' or anything else
	//				This checks for fails across all the priorities, not just prority 1
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']="If, <a href=\"#alt-page-note\">after best efforts</a>, you cannot create an <a href=\"#accessible\">accessible</a> page, provide a link to an alternative page that uses W3C technologies, is accessible, has <a href=\"#equivalent\">equivalent</a> information (or functionality), and is updated as often as the inaccessible (original) page.";
	$results['header']='g11';
	
	$hasFailed=false;
		
	//check all the WAI priority 1 checkpoints and if there are fails on any of them, mark this rule as having failed
	foreach($wai as $this_wai){
		
		if(time()>$timeout)
				break;
				
		if(isset($this_wai['type'])){
			//go through all the types:
			for($i=0; $i<count($this_wai['type']); $i++){
				if($this_wai['type'][$i]=='fail'){
					$hasFailed=true;
					break;
				}
			}
		}
	}
	if($hasFailed){
		$result_key='This document does not conform to the WCAG guidelines. If you are unable to make the necessary repairs to this document then please create another equivalent page that is accessible and link to it from this document.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	} else {
		$result_key='No alternative page link necessary.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_12_1($parse){
	//Title each frame to facilitate frame identification and navigation.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#frame-names
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Title each frame to facilitate frame identification and navigation.';
	$results['header']='g12';
	
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('frame');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$found=true;
		$src=$parse->getAttribute($this_element, 'src');
		
		if($parse->specified($this_element, 'title')){
			$title=$parse->getAttribute($this_element, 'title');
			if(trim($title)==''){
				$result_key='This frame is missing a title attribute value (it is empty).';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='title';
				$hasFailed=true;
			}
		} else {
			$result_key='This frame is missing a title attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('iframe');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$found=true;
		$src=$parse->getAttribute($this_element, 'src');
		
		if($parse->specified($this_element, 'title')){
			$title=$parse->getAttribute($this_element, 'title');
			if($title=='' || $title==' '){
				$result_key='This iframe is missing a title attribute value (it is empty).';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='title';
				$hasFailed=true;
			}
		} else {
			$result_key='This iframe is missing a title attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if($found){
		if(!$hasFailed){
			$result_key='All frame elements contained title attributes.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No frames were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_1_14_1($parse){
	//Sentences use plain and inclusive language, free from jargon.  This applies to web specific content.
	//The wording considers the audience for which the content is intended
	
	//Priority: 	Should
	
	//Techniques:	We are going to get all the <p> tags only, and check the inner text value for their score
	//				There are some Flesch functions for this purpose.
	
	//Notes:		Nested <p> elements will essentially be checked twice
	
	//TODO:			Maybe just highlight the text, and not include the surrounding <p> tags?
	//TODO:			Consider moving the score into the ['info'] field?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MUST;
	$results['rule_text']='Use the clearest and simplest language appropriate for a site\'s content.';
	$results['header']='g14';
	
	$hasFailed=false;
	$temp=$parse->getElementsByTagName('p');
	
	foreach($temp as $this_element){

		if(time()>$timeout)
			break;
				
		$innerText_orig=$parse->innerText($this_element);
		$word_count=str_word_count($innerText_orig);

		$innerText=trim(clean_text($innerText_orig));
		
		if($innerText!='' && $word_count>10){
			$flesch_score = calculate_flesch($innerText);
			
			if($flesch_score<0)
				$flesch_score=0;
						
			if($flesch_score<50 && $flesch_score>0){
				$result_key='This paragraph has a Flesch reading ease score of ' . $flesch_score . ' and may be too difficult for some people.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_TEXT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
			if($flesch_score>70){
				$result_key='This paragraph has a Flesch reading ease score of ' . $flesch_score . ' and may be too simple for it\'s audience.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_TEXT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}
	
	if(!$hasFailed){
		$result_key='All paragraphs have a Flesch reading ease score of between 50 and 70.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}	
	
	return $results;
}

function WAI_2_2_2($parse, $colours){
	//Ensure that foreground and background color combinations provide sufficient contrast when viewed by someone having color deficits or when viewed on a black and white screen.
	
	//Priority:		Should for images, may for text
	
	//Techniques: 	http://www.w3.org/TR/AERT#color-contrast
	
	//NOTE:			How do we highlight stylesheet colors?
	
	//TODO:			Perhaps we should include a visual example of the text colour on the background colour
	//				to demonstrate the colour contrast
	
	//TODO:			How do form <input> elements and so forth interact with this?
	//TODO:			Check this rule against the suggested technique
	//TODO:			This is priority 2 for images, priority 3 for text
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Ensure that foreground and background color combinations provide sufficient contrast when viewed by someone having color deficits or when viewed on a black and white screen.';
	$results['header']='g2';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('body');
	
	if(count($temp)>0){
		$body_source_index=$temp[0];
		$all_elements=$parse->getAllElements();
		$length=$all_elements[$body_source_index]['closingIndex'];
		
		$default_background='white';
		$default_text='black';
		
		$void_tagnames=Array();
		$void_tagnames[]='script';
		$void_tagnames[]='style';
		$void_tagnames[]='object';
		$void_tagnames[]='embed';
		$void_tagnames[]='noscript';
		$void_tagnames[]='select';
		$void_tagnames[]='option';
		$void_tagnames[]='textarea';
		
		for($i=$body_source_index; $i<$length; $i++){
			
			if(time()>$timeout)
				break;
							
			$tagname=$all_elements[$i]['tagname'];
			
			if(!$all_elements[$i]['is_closing'] && $tagname!='!' && !$all_elements[$i]['is_self_closing'] && !in_array($tagname, $void_tagnames)){
				//get the innertext value:
				$text=$parse->text($i, true);
				if($text!=''){
					//get the background and text colours for this element:
					//we store them in the _orig variables because for comparison purposes we need to convert
					//them to hex values and we want to use their original values for display purposes
					
					$text_orig='';
					$background_orig='';
					
					//Get the background colour details:
					$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'background-color');
										
					if(isset($temp['value']))
						$background_orig=$temp['value'];
					
					//Get the text colour details:
					$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'color');
					
					if(isset($temp['value']))
						$text_orig=$temp['value'];
					
						
					//If no background or text colours have been specified, then use the default colours (usually white and black respectively).
					if($background_orig=='')
						$background_orig=$default_background;
					
					if($text_orig=='')
						$text_orig=$default_text;
								
					//The returned results may be in a different format after being standardised for the contrast test
					//That is why the _orig variables were created for reporting purposes
					$background_colour=$colours->get_colour_details($background_orig, false);
					$text_colour=$colours->get_colour_details($text_orig, false);
					
					if(!$colours->does_contrast($background_colour, $text_colour)){
						//Is this element actually visible?
						$hidden=false;
						$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'display');
						
						if(@$temp['value']=='none')
							$hidden=true;
							
						if(!$hidden){
							$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'visibility');
							
							if(@$temp['value']=='hidden' || @$temp['value']=='collapse')
								$hidden=true;
								
						}
						
						if(!$hidden){
							$result_key='The text colour does not contrast well with the background colour.';
							$results['instances'][$result_key]['indices'][]=$all_elements[$i]['elementIndex'];
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_TEXT_NOT_CHILDREN;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$results['instances'][$result_key]['info'][]='The text colour \'' . $text_orig . '\' does not contrast well with the background colour \'' . $background_orig . '\'.';
							$hasFailed=true;
						}
					}
				
				}
			}
		}
		
		if(!$hasFailed){
			$result_key='All text colours contrasted well with the background colours.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;			
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		
	}
	
	return $results;
}

function WAI_2_3_1($parse){
	//When an appropriate markup language exists, use markup rather than images to convey information.

	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#text-markup
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='When an appropriate markup language exists, use markup rather than images to convey information.';
	$results['header']='g3';
	
	$found=false;
	
	$temp=$parse->getElementsByTagname('pre');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='When an appropriate markup language exists, use markup rather than images to convey information. For example, use MathML to mark up mathematical equations, and <a href=\"#style-sheet\">style sheets</a> to format text and control layout. Also, avoid using images to represent text -- use text and style sheets instead. Refer also to <a href=\"#gl-new-technologies\">guideline 6</a> and <a href=\"#gl-use-w3c\">guideline 11</a>.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;	
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	$temp=$parse->getElementsByTagname('img');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='When an appropriate markup language exists, use markup rather than images to convey information. For example, use MathML to mark up mathematical equations, and style sheets to format text and control layout.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';	
		}
	}
	
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='When an appropriate markup language exists, use markup rather than images to convey information. For example, use MathML to mark up mathematical equations, and style sheets to format text and control layout.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='When an appropriate markup language exists, use markup rather than images to convey information. For example, use MathML to mark up mathematical equations, and style sheets to format text and control layout.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	if(!$found){
		$result_key='All content appears to use appropriate markup.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_3_2($parse){
	//Create documents that validate to published formal grammars.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#document
	
	//TODO:			Actually validate the document, and fix the occasional doctype which can't be properly identified
	//				in the is_doctype_valid function
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Create documents that validate to published formal grammars.';
	$results['header']='g3';
	
	$docType=$parse->docType();
	
	if($docType!=''){
		$bits=getDocType($docType['docType']);
		if(!is_doctype_valid($bits)){
			$result_key='The document type must conform to the HTML specification and the list of public text identifiers.';
			$results['instances'][$result_key]['indices'][]=$docType['elementIndex'];
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='';
		} else {
			//ok so the doctype is fine, does it validate?
			$w3=new w3;
			$w3->is_xml=true;
			$w3->validate_page($parse->currentPage);
			$status=$w3->validStatus();
			
			$errors=$w3->getErrorCount();
			
			if(strtolower($status)=='valid'){
				$result_key='This HTML is valid.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='';
			} else {
				$result_key='This HTML is not valid.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='There are ' . $errors . ' problems in this page.';
			}
		}
	} else {
		$result_key='The document must contain a <code>!doctype ...</code> declaration.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_3_3($parse){
	//Use style sheets to control layout and presentation.

	//Priority:		Should
	
	//Techniques:	Use CR_6_3_4_b
	
	//NOTE:			Should a border on a table raise a warning?  How about images?
	//				How do we handle instances where a display attribute is used, but a stylesheet equivilent is also used?
	
	//TODO:			Perhaps check the stylesheets to see if this element has this display attribute specified?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Use style sheets to control layout and presentation.';
	$results['header']='g3';
	
	$hasFailed=false;
	
	$attributes=Array();
	
	$visuals=load_display_attributes();
	
	//Go through each tag and check it's attributes for visual appearance-based attributes
	$temp=$parse->getAllElements();
	for($i=0; $i<count($temp); $i++){
		
		if(time()>$timeout)
			break;
		
		//for some reason, the count() value may actually be higher than the number of elements, so
		//we need to use the isset() function (www.nytimes.com)
		if(isset($temp[$i]) && ($temp[$i]['is_closing']==false && ($temp[$i]['tagname']!='!'))){
			$attributes=$parse->getAttributes($i);
			foreach($attributes as $this_attribute){
				
				if(time()>$timeout)
					break;
			
				if(isset($visuals[$this_attribute['name']])){
					$result_key='Visual display attributes were found in the HTML.';
					$results['instances'][$result_key]['indices'][]=$i;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
					$results['instances'][$result_key]['highlight_attribute'][]=$this_attribute['name'];
					$results['instances'][$result_key]['info'][]='This visual display attribute (\'' . $this_attribute['name'] . '\') should be specified in a stylesheet.';
					
					$hasFailed=true;
				}
			}
		}
	}
	if(!$hasFailed){
		$result_key='No visual display attributes found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='';
	}
	
	return $results;
}

function WAI_2_3_4($parse){
	//Use relative rather than absolute units in markup language attribute values and style sheet property values.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#relative-units.
	
	//				Check font-size, margin-left, margin-right, margin-top, margin-bottom, padding-left, padding-right,
	//				padding-top, padding-bottom, border-left-width, border-right-width, border-top-width, border-bottom-width,
	//				word-spacing, letter-spacing, text-indent, background-position, background-position-x, background-position-y, outline-width, marker-offset, border-spacing, top, left, bottom, right, width, height, min-width, min-height, max-width, max-height, line-height, vertical-align, clip, 
	
	//Exception: "width" and "height" attributes of IMG, OBJECT, and APPLET elements.
	
	//TODO:			Include html tags and their measurements in this check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="Use relative rather than absolute units in markup language attribute values and style sheet property values.<br>For example, in CSS, use 'em' or percentage lengths rather than 'pt' or 'cm', which are absolute units. If absolute units are used, validate that the rendered content is usable (refer to the <a href=\"#validation\">section on validation</a>).";
	$results['header']='g3';
	
	$hasFailed=false;
	
	//We can use our new handy-dandy property lookup for the stylesheets
	$properties[]='font-size';
	//$properties[]='margin-top';
	//$properties[]='margin-right';
	//$properties[]='margin-bottom';
	//$properties[]='margin-left';
	//$properties[]='padding-top';
	//$properties[]='padding-right';
	//$properties[]='padding-bottom';
	//$properties[]='padding-left';
	//$properties[]='border-top-width';
	//$properties[]='border-right-width';
	//$properties[]='border-bottom-width';
	//$properties[]='border-left-width';
	$properties[]='word-spacing';
	$properties[]='letter-spacing';
	$properties[]='text-indent';
	$properties[]='background-position';
	$properties[]='background-position-x';
	$properties[]='background-position-y';
	$properties[]='outline-width';
	$properties[]='marker-offset';
	$properties[]='border-spacing';
	//$properties[]='top';
	//$properties[]='left';
	//$properties[]='bottom';
	//$properties[]='right';
	$properties[]='width';
	$properties[]='height';
	$properties[]='min-width';
	$properties[]='min-height';
	$properties[]='max-width';
	$properties[]='max-height';
	$properties[]='line-height';
	$properties[]='vertical-align';
	$properties[]='clip'; 	
	
	foreach($properties as $this_property){

		$values=$parse->getStylesByProperty($this_property, 'screen');

		foreach($values as $this_value){

			if(time()>$timeout)
				break;
			
			if(!is_unit_relative($this_value['value'])){
				
				if(is_array($this_value['value']))
					$value_string=join($this_value['value'], ' ');
				else $value_string=$this_value['value'];
				
				if($this_value['inline']){
					$result_key='This element uses absolute units of measure rather than relative units of measure.';
					$results['instances'][$result_key]['indices'][]=$this_value['selector'];
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
					$results['instances'][$result_key]['highlight_attribute'][]='style';
					$results['instances'][$result_key]['rule'][]='';
					$results['instances'][$result_key]['selector_group'][]='';
					$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				} else {
					$result_key='This style uses absolute units of measure rather than relative units of measure.';
					$results['instances'][$result_key]['indices'][]=-2;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_CSS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$results['instances'][$result_key]['stylesheet'][]=$this_value['stylesheet'];
					$results['instances'][$result_key]['rule'][]=$this_value['rule'];
					$results['instances'][$result_key]['selector_group'][]=$this_value['selector_group'];
					$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				}
				$hasFailed=true;
			}
		}
	}
	
	//Check the HTML elements
	$temp=$parse->getElementsByTagname('frameset');
	foreach($temp as $this_element){
		$rows=$parse->getAttribute($this_element, 'rows', true);
		$bits=explode(',', $rows);
		foreach($bits as $this_bit){
			if($this_bit!='*' && !is_relative($this_bit)){
				$result_key='This frameset row attribute uses absolute units of measure rather than relative units of measure.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='rows';
				$results['instances'][$result_key]['stylesheet'][]=-1;
				$results['instances'][$result_key]['rule'][]=-1;
				$results['instances'][$result_key]['selector_group'][]=-1;
				//$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				$hasFailed=true;
			}
		}
		
		$cols=$parse->getAttribute($this_element, 'cols', true);
		$bits=explode(',', $cols);
		foreach($bits as $this_bit){
			if($this_bit!='*' && !is_relative($this_bit)){
				$result_key='This frameset col attribute uses absolute units of measure rather than relative units of measure.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='cols';
				$results['instances'][$result_key]['stylesheet'][]=-1;
				$results['instances'][$result_key]['rule'][]=-1;
				$results['instances'][$result_key]['selector_group'][]=-1;
				//$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				$hasFailed=true;
			}
		}
	}
	
	$table_tags[]='table';
	$table_tags[]='tr';
	$table_tags[]='th';
	$table_tags[]='td';

	$attributes[]='bottompadding';
	$attributes[]='cellspacing';
	$attributes[]='cellpadding';
	$attributes[]='height';
	$attributes[]='hspace';
	$attributes[]='leftpadding';
	$attributes[]='rightpadding';
	$attributes[]='toppadding';
	$attributes[]='vspace';
	$attributes[]='width';
	
	foreach($table_tags as $this_table_tag){
		$temp=$parse->getElementsByTagname($this_table_tag);
		foreach($temp as $this_element){
			foreach($attributes as $this_attribute){
				$value=$parse->getAttribute($this_element, $this_attribute, true);
				if(!is_relative($value)){
					$result_key='This ' . $this_table_tag . ' ' . $this_attribute . ' attribute uses absolute units of measure rather than relative units of measure.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]=$this_attribute;
					$results['instances'][$result_key]['stylesheet'][]=-1;
					$results['instances'][$result_key]['rule'][]=-1;
					$results['instances'][$result_key]['selector_group'][]=-1;
					$hasFailed=true;
				}	
			}		
		}
	}
	
	$temp=$parse->getElementsByTagname('font');
	foreach($temp as $this_element){
		$value=$parse->getAttribute($this_element, 'size');
		if(!is_relative($value)){
			$result_key='This font size attribute uses absolute units of measure rather than relative units of measure.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='size';
			$results['instances'][$result_key]['stylesheet'][]=-1;
			$results['instances'][$result_key]['rule'][]=-1;
			$results['instances'][$result_key]['selector_group'][]=-1;
			$hasFailed=true;
		}
		
		$value=$parse->getAttribute($this_element, 'point-size');
		if(!is_relative($value)){
			$result_key='This font point-size attribute uses absolute units of measure rather than relative units of measure.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='point-size';
			$results['instances'][$result_key]['stylesheet'][]=-1;
			$results['instances'][$result_key]['rule'][]=-1;
			$results['instances'][$result_key]['selector_group'][]=-1;
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No absolute unit measurements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='All measurements used relative units.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}	
	
	return $results;
}

function WAI_2_3_5($parse){
	//Use header elements, H1, H2... H6, to convey document structure and use them according to specification.

	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#logical-heading
	
	//TODO:			Not highlight elements as possibly being good for headers if they contain links
	//TODO:			If a page has no <Hx> elements at all, should this be a pass (currently the situation) or a warning?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Use header elements to convey document structure and use them according to specification.';
	$results['header']='g3';
	
	$hasFailed=false;
	$found=false;
	
	$headers['h1']['next']='h2';
	$headers['h1']['others']=Array('h3', 'h4', 'h5', 'h6');
	$headers['h2']['next']='h3';
	$headers['h2']['others']=Array('h4', 'h5', 'h6');
	$headers['h3']['next']='h4';
	$headers['h3']['others']=Array('h5', 'h6');
	$headers['h4']['next']='h5';
	$headers['h4']['others']=Array('h6');
	//$headers['h5']['next']='h6';
	//$headers['h5']['others']=Array();
	//Get all the <h1> elements and check that the next header element is an <h2>
	foreach($headers as $key => $this_header){
		$temp=$parse->getElementsByTagname($key);
		foreach($temp as $this_element){
			$found=true;
			$next=$parse->getNextElement($this_element);
			while($next){
				$tagname=$parse->tagname($next);
				
				if($tagname!=$key && $tagname!=$this_header['next'] && (in_array($tagname, $this_header['others']))){
					$result_key='Header levels must not increase by more than one level per heading. Do not use headings to create font effects; use style sheets to change font styles.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$results['instances'][$result_key]['info'][]='The next header element is:<br><code>' . htmlspecialchars($parse->outerHTML($next)) . '</code>';
					
					$hasFailed=true;
				}
				
				if($tagname=='h1' || $tagname=='h2' || $tagname=='h3' || $tagname=='h4' || $tagname=='h5' || $tagname=='h6'){
					break;
				}
				$next=$parse->getNextElement($next);
			}
			
			//verify that header is not used for formatting:
			//get the inner text of this element:
			$innerText=strip_spaces($parse->innerText($this_element), true);
									
			if(str_word_count($innerText)>20){
				$result_key='Header elements (<code>h1</code> - <code>h6</code>) should be used to define headers and should not be used for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='This header could be converted to either a paragraph or blockquote.';
				$hasFailed=true;
			}
		}
	}
	
	//now check <p> elements for formatting:
	$temp=$parse->getElementsByTagname('p');
	foreach($temp as $this_element){
		$found=true;
		$p_text_orig=$parse->innerText($this_element);
		$p_text=trim(strip_spaces($p_text_orig, true));
		
		if($p_text!='' && str_word_count($p_text)<10){
			$all_descendants=$parse->all_descendants($this_element);
			
			if(sizeof($all_descendants)==0)
				$all_descendants[]=$this_element;
			
			$descendant_count=count($all_descendants);
			$descendant_found=false;
			for($i=0; $i<$descendant_count; $i++){
				
				$tag_name=$parse->tagname($all_descendants[$i]);
				if($tag_name=='b' || $tag_name=='strong' || $tag_name=='u' || $tag_name=='em' || $tag_name=='u'){
					$text=strip_spaces($parse->innerText($all_descendants[$i]), true);
					if($text==$p_text){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
				}
				//check the styles:
				$text=strip_spaces($parse->innerText($all_descendants[$i]), true);
				if($text==$p_text){
					$applied=$parse->getStyleValue($all_descendants[$i], 'font-weight', 'screen');
					if(strtolower($applied['value'])=='bold' || strtolower($applied['value'])=='bolder' || $applied['value']=='700' || $applied['value']=='800' || $applied['value']=='900'){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
					
					$applied=$parse->getStyleValue($all_descendants[$i], 'font-style', 'screen');
					if(strtolower($applied['value'])=='italic'){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
				
					$applied=$parse->getStyleValue($all_descendants[$i], 'text-decoration', 'screen');
					if(strtolower($applied['value'])=='underline'){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
					
					if($descendant_found)
						break;
				}
			}
		}
	}
	if($found){
		if(!$hasFailed){
			$result_key='All heading elements were used in the correct fashion.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		
	} else {
		$result_key='No heading elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_3_6($parse){
	//Mark up lists and list items properly.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#list-structure

	//TODO: 		use array_merge to combine all the different element types into one array, saves on duplication
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Mark up lists and list items properly.';
	$results['header']='g3';
	
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('ol');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){

			if(time()>$timeout)
				break;
			
			$descendants=$parse->all_descendants($this_element, 'li');
			if(count($descendants)==0){
				$result_key='List items should not be used for formatting text. Use style sheets or tables for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
			if(count($descendants)==1){
				$result_key='List items should not be used for formatting text. Use style sheets or tables for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
	}
	
	$temp=$parse->getElementsByTagname('ul');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$descendants=$parse->all_descendants($this_element, 'li');
			if(count($descendants)==0){
				$result_key='List items should not be used for formatting text. Use style sheets or tables for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
			if(count($descendants)==1){
				$result_key='List items should not be used for formatting text. Use style sheets or tables for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
	}
	
	$temp=$parse->getElementsByTagname('dl');
	if(count($temp)>0){
		$found=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$descendants=$parse->all_descendants($this_element, 'li');
			if(count($descendants)==0){
				$result_key='List items should not be used for formatting text. Use style sheets or tables for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
			if(count($descendants)==1){
				$result_key='List items should not be used for formatting text. Use style sheets or tables for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
	}
	
	if(!$hasFailed){
		if($found){
			$result_key='All lists were used correctly.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		} else {
			$result_key='No lists were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	return $results;
}

function WAI_2_3_7($parse){
	//Mark up quotations.  Do not use quotation markup for formatting effects such as identation.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#quotes
	
	//TODO:			Are there any other methods of encoding a quote mark?
	//				Unicode perhaps?
	//TODO:			Differentiate between not finding incorrect quotations styles and not finding any quotation styles at all?
	//TODO:			Fix this to not highlight blockquotes that have no text because they're nested...
		
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Mark up quotations. Do not use quotation markup for formatting effects such as indentation.';
	$results['header']='g3';
	
	$hasFailed=false;
	
	//check paragraphs for quote marks
	$temp=$parse->getElementsByTagname('p');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$text=trim(strip_spaces($parse->innerText($this_element)));
		
		if(substr($text,0,1)=='"' || substr($text,0,1)=='\'' || strtolower(substr($text,0,6))=='&quot;' || strtolower(substr($text,0,6))=='&apos;'){
			if(substr($text,-1)=='"' || substr($text,-1)=='\'' || strtolower(substr($text,-6))=='&quot;' || strtolower(substr($text, -6))=='&apos;'){
				//this has quotes at the start and end
				$result_key='The following text may need to be marked using <code>q</code> or <code>blockquote</code>: [' . $text . '].';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}
	
	//check for correctly used q tags
	$temp=$parse->getElementsByTagname('q');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		//q elements need to have at least one word before or after it
		$parent=$parse->parentElement($this_element);
		$parent_text=$parse->innerText($parent);
		$text=$parse->innerText($this_element);
		$quote_count=str_word_count($text);
		$parent_text_count=str_word_count($parent_text);
		if($parent_text_count>=$quote_count || $quote_count>=10){
			$result_key='This text should be marked as <code>blockquote</code> not <code>q</code>: [' . $text . '].';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	//check for correctly used blockquote tags
	$temp=$parse->getElementsByTagname('blockquote');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$text=$parse->innerText($this_element);
		//blockquotes should be longer than 10 words
		
		$quote_count=str_word_count($text);
		if($quote_count<10){
			$result_key='This text should be marked as <code>q</code> not <code>blockquote</code>: [' . $text . '].';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	//check for nested blockquotes:
	$temp=$parse->getElementsByTagname('blockquote');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$descendants=$parse->all_descendants($this_element, 'blockquote');
		if(count($descendants)>0){
			$result_key='<code>blockquote</code> elements should be used to define quotes and should not be used for formatting text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No incorrect use of quotations were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_5_3($parse){
	//Verify that layout tables make sense when linearized.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#avoid-table-for-layout
	
	//Note:			This is a user check, should a linerised version be provided?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="Do not use tables for layout unless the table makes sense when linearized. Otherwise, if the table does not make sense, provide an alternative equivalent (which may be a <a href=\"#linearized-table\">linearized version</a>).";
	$results['header']='g5';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('table');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			if(!is_data_table($parse, $this_element)){
				$result_key='Tables used for layout should make sense when linearized.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		if(!$hasFailed){
			$result_key='No layout tables were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No tables were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_5_4($parse){
	//Tables used for layout should not use table headings to create formatting effects.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#table-layout
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='If a table is used for layout, do not use any structural markup for the purpose of visual formatting.';
	$results['header']='g5';
	
	$hasFailed=false;
	$found=false;
	$temp=$parse->getElementsByTagname('table');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			if(!is_data_table($parse, $this_element)){
				$found=true;
				//check for any <th> elements
				$descendants=$parse->all_descendants($this_element, 'th');
				if(count($descendants)>0){
					$result_key='Tables used for layout should not use table headings to create formatting effects.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}	
			}
		}
		if(!$hasFailed){
			if($found){
				$result_key='No layout tables used <code>th</code> elements.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No layout tables were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No tables were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_6_4($parse){
	//For scripts and applets, ensure that event handlers are input device independant.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#keyboard-operable
	
	//NOTE:			The script check does not make a reference to the type attribute
	//				The message refers only to scripts and applet elements
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='For scripts and applets, ensure that event handlers are input device-independent.';
	$results['header']='g6';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('script');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	$temp=$parse->getElementsByTagname('embed');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	if(!$hasFailed){
		$result_key='No scripts or applets were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_6_5($parse){
	//Ensure that dynamic content is accessible or provide an alternative presentation or page.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#fallback-page
	
	//TODO:			Investigate how nested framesets are handled by the all_descendants search for noframes elements
	
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Ensure that dynamic content is accessible or provide an alternative presentation or page.';
	$results['header']='g6';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('frameset');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$descendants=$parse->all_descendants($this_element, 'noframes');
			if(count($descendants)==0){
				$result_key='No <code>noframes</code> element was found within this frameset.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			} else {
				//There could be many noframes, but usually only one...
				foreach($descendants as $this_element2){
					
					if(time()>$timeout)
						break;
						
					$innerText=strtolower($parse->innerText($this_element2));
					if(str_word_count($innerText)>1){
						//are there any links?
						$descendants2=$parse->all_descendants($this_element2, 'a');
						if(count($descendants2)==0){
							$result_key='This <code>noframes</code> element does not appear to contain navigation links.';
							$results['instances'][$result_key]['indices'][]=$this_element2;
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$hasFailed=true;
						}
						//check each word
						$words=str_word_count($innerText,1);
						for($i=0;$i<count($words);$i++){

							if(time()>$timeout)
								break;
								
							if($words[$i]=='upgrade' || $words[$i]=='missing' || ($words[$i]=='full' && @$words[$i+1]=='advantage') || ($words[$i]=='supports' && @$words[$i+1]=='frames')){
								$result_key='Does your page work if frames are not loaded?';
								$results['instances'][$result_key]['indices'][]=$this_element;
								$results['instances'][$result_key]['type'][]=RESULT_WARNING;
								$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
								$results['instances'][$result_key]['highlight_attribute'][]='';
								$hasFailed=true;
							}
						}
					} else {
						$result_key='The <code>noframes</code> element must contain some text.';
						$results['instances'][$result_key]['indices'][]=$this_element2;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					}
					
				}
			}
			
			if(!$hasFailed){
				$result_key='All framesets contain alternative text.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No framesets were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_7_2($parse){
	//Until user agents allow users to control blinking, avoid causing content to blink.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#style-text
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> allow users to control blinking, avoid causing content to blink (i.e., change presentation at a regular rate, such as turning on and off).";
	$results['header']='g7';
	
	$temp=$parse->getElementsByTagname('blink');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='The <code>blink</code> element is not defined in any W3C HTML specification and should not be used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			//$results['repair'][]="<p>Try replacing the BLINK element with one of the following:</p><ul><li>STRONG</li><li>EM</li><li>SPAN style=\"text-decoration: blink\"</li><li>H1</li><li>H2</li><li>H3</li><li>H4</li><li>H5</li><li>H6</li></ul>";
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='If you really need to use blinking text, use the stylesheet property &quot;text-decoration: blink&quot;';
		}
	} else {
		$result_key='No <code>blink</code> elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_7_3($parse){
	//Until user agents allow users to freeze moving content, avoid movement in pages.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#video-information
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> allow users to freeze moving content, avoid movement in pages.";
	$results['header']='g7';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('marquee');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='The <code>marquee</code> element is not defined in any W3C HTML specification and should not be used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			//$results['repair'][]="<p>Try replacing the MARQUEE element with one of the following:</p><ul><li>STRONG</li><li>EM</li><li>SPAN style=\"text-decoration: blink\"</li><li>H1</li><li>H2</li><li>H3</li><li>H4</li><li>H5</li><li>H6</li></ul>";
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Moving text is generally considered to be an annoyance.  You could use the stylesheet property &quot;text-decoration: blink&quot;.';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='Please confirm that this <code>object</code> element does not contain any moving text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	$temp=$parse->getElementsByTagname('embed');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='Please confirm that this <code>embed</code> element does not contain any moving text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='Please confirm that this <code>applet</code> element does not contain any moving text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No potentially moving items were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_7_4($parse){
	//Until user agents provide the ability to stop the refresh, do not create periodically auto-refreshing pages.

	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#no-periodic-refresh
	
	//NOTE:			Snoopy MUST be configured to ignore redirects for this to work.
	//				This only addresses integer refreshes.  URL redirects are handled in 2_7_5
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> provide the ability to stop the refresh, do not create periodically auto-refreshing pages.";
	$results['header']='g7';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('meta');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$httpequiv=$parse->getAttribute($this_element, 'http-equiv', true);
		if($httpequiv=='refresh'){
			$content=$parse->getAttribute($this_element, 'content');
			$bits=explode(';', $content);
			if(is_numeric($bits[0]) && $bits[0]>0){
				$result_key='This page uses auto-refresh which can make the page difficult to read for some people.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='content';
				$hasFailed=true;
			}
		}
	}
	
	if(!$hasFailed){
		$result_key='No auto-refreshes were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_7_5($parse){
	//Until user agents provide the ability to stop auto-direct, do not use markup to redirect pages automatically.  Instead, configure the server to perform redirects.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#auto-page-refresh
	
	//NOTE:			Snoopy MUST be configured to ignore redirects for this to work.
	//				Do we want to allow a check initially, and then to optionally follow the redirect?  It could be handy
	//				for url redirects that the user isn't aware of.
	//				We are ignoring integers here because we are really only interesting URL redirects.  Refreshes are
	//				handled in 2_7_4
	
	//Note: 		This doesn't actually check to see if the so-called URL is valid
	//NOTE:			This will also trigger 2_7_4, is this desirable?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> provide the ability to stop auto-redirect, do not use markup to redirect pages automatically. Instead, configure the server to perform redirects.";
	$results['header']='g7';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('meta');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$refresh=$parse->getAttribute($this_element, 'http-equiv', true);
			if($refresh=='refresh'){
				$content=$parse->getAttribute($this_element, 'content');
				$bits=explode(';', $content);
				if($content!='' && is_numeric($content[0]) && sizeof($bits)>1){
					$result_key='This page uses auto-redirect which can make the page difficult to read for some people.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='content';
					$hasFailed=true;
				}
			}
		}
		
		if(!$hasFailed){
			$result_key='No auto-redirect elements found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No auto-redirect elements found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_8_1($parse){
	//Make programmatic elements such as scripts and applets directly accessible or compatible with assistive technologies.
	
	//Priority:		Should
	
	//Techniques:	No link?
	
	//TODO:			This is Priority 1 if functionality is important and not presented elsewhere, otherwise Priority 2.
	
	//NOTE:			The script check does not care what the 'type' or 'language' attribute is
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Make programmatic elements such as scripts and applets directly accessible or compatible with assistive technologies.';
	$results['header']='g8';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('embed');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('script');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	if(!$hasFailed){
		$result_key='No programmatic elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_9_2($parse){
	//Ensure that any element that has its own interface can be operated in a device-independant manner.
	
	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#keyboard-operable
	
	//TODO:			Perhaps check the mime type of the object elements because images could be displayed within <object> elements.
	
	//NOTE:			<script> elements not included
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Ensure that any element that has its own interface can be operated in a device-independent manner.';
	$results['header']='g9';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('object');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$result_key='Please ensure this programmatic object can be operated in a device independent manner.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;	
	}
	
	$temp=$parse->getElementsByTagname('embed');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$result_key='Please ensure this programmatic object can be operated in a device independent manner.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;	
	}
	
	$temp=$parse->getElementsByTagname('applet');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$result_key='Please ensure this programmatic object can be operated in a device independent manner.';
		$results['instances'][$result_key]['indices'][]=$this_element;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;	
	}
	
	if(!$hasFailed){
		$result_key='No programmatic objects were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_9_3($parse){
	//For scripts, specify logical event handlers, rather than device-dependant event handlers.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#device-independent-events
	
	//NOTE:			This does not check for assigned event handlers though javascript code
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='For scripts, specify logical event handlers rather than device-dependent event handlers.';
	$results['header']='g9';
	
	$hasFailed=false;
	
	//onMouseDown()
	//onMouseUp()
	//onClick()
	//onMouseOver()
	//onMouseOut()
	//onMouseMove()
	
	$onMouseDown=$parse->getElementsByAttribute('onmousedown');
	$onMouseUp=$parse->getElementsByAttribute('onmouseup');
	$onClick=$parse->getElementsByAttribute('onclick');
	$onMouseOver=$parse->getElementsByAttribute('onmouseover');
	$onMouseOut=$parse->getElementsByAttribute('onmouseout');
	$onMouseMove=$parse->getElementsByAttribute('onmousemove');
	
	if($onMouseDown){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseDown as $this_element){
			
			if(time()>$timeout)
				break;
				
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmousedown';
			$results['instances'][$result_key]['info'][]='Try using onKeyDown as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseUp){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseUp as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmouseup';
			$results['instances'][$result_key]['info'][]='Try using onKeyUp as a replacement.';
		}
		$hasFailed=true;
	}
	if($onClick){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onClick as $this_element){

			if(time()>$timeout)
				break;
				
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onclick';
			$results['instances'][$result_key]['info'][]='Try using onKeyPress as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseOver){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseOver as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmouseover';
			$results['instances'][$result_key]['info'][]='Try using onFocus as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseOut){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseOut as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmouseout';
			$results['instances'][$result_key]['info'][]='Try using onBlur as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseMove){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseMove as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmousemove';
			//No suggested replacement here
		}
		$hasFailed=true;
	}
	
	if(!$hasFailed){
		$result_key='No device-dependant event handlers were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_10_1($parse){
	//Until user agents allow users to turn off spawned windows, do not cause pop-ups or other windows to appear and do not change the current window without informing the user.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#no-new-windows
	
	//NOTE:		Does not check for javascript popups
		
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> allow users to turn off spawned windows, do not cause pop-ups or other windows to appear and do not change the current window without informing the user.";
	$results['header']='g10';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('a');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$target=$parse->getAttribute($this_element, 'target', true);
			if($target=='_new' || $target=='_blank'){
				$result_key='This anchor element will open a new window that can disorient some users.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='target';
				$hasFailed=true;
			}
		}
		if(!$hasFailed){
			$result_key='No anchors spawn new windows.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No anchors were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';	
	}
		
	return $results;
}

function WAI_2_10_2($parse){
	//Every descriptive label is tagged as LABEL and associated with the name of the field.
	
	//Priority:		Must
	
	//Techniques:	Get every <input> element.  If it is not hidden or a cancel or submit button, then check for a label.
	//				This is done by getting the ID attribute (if any), and checking for a <label> with the 'for' attribute with this ID or if this returns nothing,
	//				move up the parent list until we find an enclosing <label> element.
	//				This label must be either the immediatley preceeding element, or the next one after the label.
	
	//NOTE:			Form fields that aren't contained within proper block parent tags may detect text for other form fields

	//NOTE:			This does not actually require a form input field to be contained within a <form> element
	
	//TODO:			What does this function actually do?  I am confused...
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> support explicit associations between labels and form controls, for all form controls with implicitly associated labels, ensure that the label is properly positioned.";
	$results['header']='g10';
	
	$hasFailed=false;
	
	$blocks=load_block_elements(false);
	//Div tags frequently prevent this rule from identifying associated text, so we are going to ignore them here
	unset($blocks['div']);
	
	$temp=Array();
	$temp=array_merge($temp, $parse->getElementsByTagName('input'));
	$temp=array_merge($temp, $parse->getElementsByTagName('select'));
	$temp=array_merge($temp, $parse->getElementsByTagName('textarea'));
	
	if(count($temp)>0){
		$allLabels=$parse->getElementsByTagName('label');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$input_good=true;
			$has_label=false;
			
			$type=$parse->getAttribute($this_element, 'type', true);
			
			//we are not checking hidden elements, as well as submit and cancel buttons
			if($type!='hidden' && $type!='submit' && $type!='reset' && $type!='image'){
				//Does this element have an id?
				$id=$parse->getAttribute($this_element, 'id', true);
				//if so, is there a label with this id as a 'for' attribute value?
				if($id!=''){
					//we need to get any label with the 'for' attribute matching this id attribute
					foreach($allLabels as $this_label){
						
						if(time()>$timeout)
							break;
							
						$for=$parse->getAttribute($this_label, 'for', true);
						if($for==$id){
							$has_label=true;
							//ok, so it matches
							if($this_label<$this_element){
								for($i=$this_element-1; $i>$this_label; $i--){
									if(tagType($parse->tagName($i))==PARSE_BLOCK_ELEMENT){
										$input_good=false;
										break;
									}
								}
							} else {
								for($i=$this_element+1; $i<$this_label; $i++){
									if(tagType($parse->tagName($i))==PARSE_BLOCK_ELEMENT){
										$input_good=false;
										break;
									}
								}
							}
							//ok, so now we know if the input element is any good, even if it has the same for/id combo
							//we shall assume that there is only one id/for combo to check for, and we can exit here
							break;	
						}
					}
					
					if(!$input_good){
						$result_key='This form field has a <code>label</code> element which is not immediately adjacent to the input field. ';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_WARNING;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]="<p>The label html is:<br><code>" . htmlspecialchars($parse->outerHTML($this_label)) . "</code></p>";
						$hasFailed=true;						
					}
					
				}		
			}
		}
		
		if(!$hasFailed){
			$result_key='All labels were correctly positioned';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No form input elements were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_11_1($parse){
	//Use W3C technologies when they are available and appropriate for a task and use the latest versions when supported.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#latest-w3c-specs
	
	//NOTE:			embed elements containing .swf files will be identified twice
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Use W3C technologies when they are available and appropriate for a task and use the latest versions when supported.';
	$results['header']='g11';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('img');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$extension=get_extension($parse->src($this_element));
		if($extension=='gif' || $extension=='jpg' || $extension=='jpeg'){
			$result_key='Non-W3C technology used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='src';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('a');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$extension=get_extension($parse->href($this_element));
		if($extension=='pdf'){
			$result_key='Non-W3C technology used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='href';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('embed');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$extension=get_extension($parse->src($this_element));
		if($extension=='swf'){
			
			//check to see if a parent is an object element
			$parent=$parse->parentElement($this_element);
			$object_found=false;
			while($parent>=0){
				if($parse->tagname($parent)=='object'){
					$type=$parse->getAttribute($parent, 'type', true);
					if($type=='application/x-shockwave-flash'){
						$object_found=true;
						break;
					}
				}
				
				$parent=$parse->parentElement($parent);
			}
			
			if(!$object_found){
				$result_key='Non-W3C technology used.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='src';
				$hasFailed=true;
			}
		}
	}
	
	$temp=$parse->getElementsByTagname('object');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$type=$parse->getAttribute($this_element, 'type', true);
		if($type=='application/x-shockwave-flash'){
			$data=$parse->getAttribute($this_element, 'data');
			$result_key='Non-W3C technology used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='data';
			$hasFailed=true;
		}
	}
	
	$proprietary=Array();
	load_proprietary_elements($proprietary);

	foreach($proprietary as $this_proprietary){
		
		if(time()>$timeout)
			break;
			
		$temp=$parse->getElementsByTagname($this_proprietary);
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
					
				if($this_proprietary=='input'){
					$type=$parse->getAttribute($this_element, 'type', true);
					if($type=='readonly'){
						$result_key='The proprietary element ' . $this_proprietary . ' was found.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
						$results['instances'][$result_key]['highlight_attribute'][]='type';
						$hasFailed=true;
					}
				} else {
					$result_key='The proprietary element ' . $this_proprietary . ' was found.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
			}
		}
	}
	
	if(!$hasFailed){
		$result_key='No non-W3C technologies were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_11_2($parse){
	//Avoid deprecated features of W3C technologies.

	//Priority:		Should
	
	//Techniques:	Use CR_6_3_3_d
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Avoid deprecated features of W3C technologies.';
	$results['header']='g11';
	
	$hasFailed=false;
	$deprecated=Array();
	$deprecated=load_deprecated_elements();

	foreach($deprecated as $this_deprecated){
		
		if(time()>$timeout)
			break;
			
		$temp=$parse->getElementsByTagname($this_deprecated['element']);
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='This HTML element <code>' . $this_deprecated['element'] . '</code> is now deprecated and should not be used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Use this element instead: <code>' . $this_deprecated['replacement'] . '</code>.';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No deprecated elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_12_2($parse){
	//Describe the purpose of frames and how frames relate to each other if it is not obvious by frame titles alone.

	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#frame-longdesc
	
	//NOTE:			If frames are found, raise as a user check
	//				Iframes are not included... should they?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Describe the purpose of frames and how frames relate to each other if it is not obvious by frame titles alone.';
	$results['header']='g12';
	
	$temp=$parse->getElementsByTagName('frameset');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='Please check that the purpose of this frameset is clear.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No frames were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_12_3(){
	//Divide large blocks of information into more manageable groups where natural and appropriate.
	
	//Priority:		Should
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Divide large blocks of information into more manageable groups where natural and appropriate.';
	$results['header']='g12';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_2_12_4($parse){
	//Associate labels explicitly with their controls.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#associate-labels
	
	//Methods:		We are ignoring submit, reset and hidden inputs, as well as buttons and images (often used as buttons)
		
	//NOTE:			This does not take into account the presence of accompanying text
	
	//TODO:			This does not include <textarea> or <select> elements
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Associate labels explicitly with their controls.';
	$results['header']='g12';
	
	$hasFailed=false;
	
	$blocks=load_block_elements(false);
	//Div tags frequently prevent this rule from identifying associated text, so we are going to ignore them here
	unset($blocks['div']);
	
	$temp=$parse->getElementsByTagname('input');

	if(count($temp)>0){
		$allLabels=$parse->getElementsByTagname('label');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$found=false;
			$type=$parse->getAttribute($this_element, 'type', true);
			
			//we are not checking hidden elements, as well as submit and cancel buttons
			if($type!='hidden' && $type!='submit' && $type!='reset' && $type!='button' && $type!='image'){
				//Does this element have an id?
				$id=$parse->getAttribute($this_element, 'id', true);
				//if so, is there a label with this id as a 'for' attribute value?
				if($id!=''){
					foreach($allLabels as $this_label){
						
						if(time()>$timeout)
							break;
			
						$for=$parse->getAttribute($this_label, 'for', true);
						if($for==$id){
							$found=true;
							break;
						}
					}
				}
				if(!$found){
					//Is this element's parent element a label?
					$parent=$parse->parentElement($this_element);
					$tagname=$parse->tagname($parent);
					if($tagname!='label'){
						//move up the list until a block element is found
						if(!isset($blocks[$tagname])){
							while(!isset($blocks[$tagname])){
								
								if(time()>$timeout)
									break;
								
								$parent=$parse->parentElement($parent);
								$tagname=$parse->tagname($parent);
								
								if($tagname=='label'){
									$found=true;
									break;
								}
								
								if($parent==0)
									break;
								
							}
						} 
						
					} else $found=true;
										
					if(!$found){
						$innerText_orig=$parse->innerText($parent);
						$innerText=trim(strip_spaces($innerText_orig));
						if($innerText!=''){
							$result_key='This input field appears to have text associated with it which is not in a label.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$results['instances'][$result_key]['info'][]="<p>The text is <span class=\"quote\">" . $innerText_orig . "</span></p>";
							$hasFailed=true;
						}
					}
				}
			}
		
		}
		if(!$hasFailed){
			$result_key='No input fields had unassociated text';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No form elements were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_13_1($parse){
	//Clearly identify the target of each link.
	
	//Priority:	Should
	
	//Techniques: http://www.w3.org/TR/AERT#meaningful-links
	
	//TODO:			We need to include the other destination for highlighting purposes
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Clearly identify the target of each link.';
	$results['header']='g13';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('a');
	$used=Array();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$text=$parse->innerText($this_element);
		$title=$parse->getAttribute($this_element, 'title');
		$link=$parse->href($this_element);
		
		$text2=strtolower(trim(strip_spaces($text)));
				
		if($text2!='' && $link!='' && isset($used[$text2]['text']) && @$used[$text2]['link']!=$link){
			$result_key="This link text ('<span class=\"quote\">" . $text . "'</span>) has already been used for a different destination.";
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
			
		} else {
		
			switch(TRUE){
				case($text2=='click here'):
					$result_key="This link text may not be meaningful when read on its own: <span class=\"quote\">" . $text . "</span>";
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
				case($text2=='more'):
					$result_key="This link text may not be meaningful when read on its own:  <span class=\"quote\">" . $text . "</span>";
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
				case($text2=='follow this'):
					$result_key="This link text may not be meaningful when read on its own:  <span class=\"quote\">" . $text . "</span>";
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
				case(strlen($text2)>60):
					$result_key='This link text is quite long and should be shortened.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
			}
			$used[$text2]['text']=$text2;
			$used[$text2]['link']=$link;
		}
	}
	if(!$hasFailed){
		$result_key='All links clearly identified their targets.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_13_2($parse){
	//Provide metadata to add semantic information to pages and sites.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#use-metadata
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Provide metadata to add semantic information to pages and sites.';
	$results['header']='g13';
	
	$hasFailed=true;
	
	$temp=$parse->getElementsByTagname('meta');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$httpequiv=$parse->getAttribute($this_element, 'http-equiv', true);
		if($httpequiv!='refresh' && $httpequiv!='' && $httpequiv!='content-type')
			$hasFailed=false;
	}
	
	$temp=$parse->getElementsByTagname('address');
	if(count($temp)>0)
		$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('title');
	if(count($temp)>0)
		$hasFailed=false;
		
	$temp=$parse->getElementsByTagname('link');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$rel=$parse->getAttribute($this_element, 'rel', true);
		$type=$parse->getAttribute($this_element, 'type', true);
		if(($rel!='stylesheet' || $rel!='alternate') && $type!='text/css')
			$hasFailed=false;
	}
	
	if($hasFailed){
		$result_key='This document does not contain any meta information.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='Meta information can be provided throught:<br><ul><li>title of the page (required for frames, see checkpoint 12.1),</li><li>type of content,</li><li>descriptions of the content of the page,</li><li>conformance claims,</li><li>author information,</li><li>next page in a series (e.g., LINK rel="next").</li></ul>';
	} else {
		$result_key='This document contains meta information.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_2_13_3(){
	//Provide information about the general layout of a site.
	
	//Priority:		May
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Provide information about the general layout of a site (e.g., a site map or table of contents).';
	$results['header']='g13';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	return $results;
}

function WAI_2_13_4(){
	//Use navigation mechanisms in a consistent manner.
	
	//Priority:		Should
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_SHOULD;
	$results['rule_text']='Use navigation mechanisms in a consistent manner.';
	$results['header']='g13';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_1_5($parse){
	//Until user agents render text equivalents for client-side image map links, provide redundant text links for each active region of a client-side image map.
	
	//Priority:		Should
	
	//Techniques:	Get all the <area> elements and get all the <a> elements, via getElementsByTagname.  Check that each <area> link has an <a> equivalent.
	
	//NOTE:			Perhaps the imagemap should receive the element index, because the areas cannot be highlighted
	//				Should we check that the links are actually have text inside them?  This will pick up '#' links
	//				which might be a problem
		
	//TODO:			What do we do about links such as '#'?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Until user agents render text equivalents for client-side image map links, provide redundant text links for each active region of a client-side image map.';
	$results['header']='g1';
		
	$hasFailed=false;
	$temp=$parse->getElementsByTagname('map');
	if(count($temp)>0){
		$all_links=$parse->getElementsByTagname('a');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$temp2=$parse->all_descendants($this_element, 'area');
			
			foreach($temp2 as $this_area){
				
				if(time()>$timeout)
					break;
			
				if($parse->specified($this_area, 'href')){
					$area_href=$parse->href($this_area);
					$link_found=false;
					foreach($all_links as $this_anchor){
						
						if(time()>$timeout)
							break;
							
						$link_href=$parse->href($this_anchor);
						if($link_href==$area_href){
							$link_found=true;
							break;
						}	
					}
					if(!$link_found){
						$result_key='Client-side image maps should have associated text links.';
						$results['instances'][$result_key]['indices'][]=$this_area;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='href';
						$hasFailed=true;
					}
				}
			}
		}
		if(!$hasFailed){
			$result_key='All image maps had text alternatives.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		//no image maps, no problem!
		$result_key='No image maps found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_4_2($parse){
	//Specify the expansion of each abbreviation or acronym in a document where it first occurs.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#expand-abbr
	
	//NOTE:			No attempt to get the first instance of an acronym is made.  Perhaps the str_word_count function can be used for this
	//				Also, perhaps we could trim trailing letters, like URLs to get URL.  And convert other characters such as dashes to spaces to increase the haul
	//				Is it not possible to highlight the acronym?
	//				This will detect words inside comments (bad) and hex values inside <style> elements contained within
	//				the body element (annoying)
	//TODO:			style elements seem to be picked up in the innerHTML function (www.stuff.co.nz)
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Specify the expansion of each abbreviation or acronym in a document where it first occurs.';
	$results['header']='g4';
	
	$found=false;
	
	$temp=$parse->getElementsByTagname('body');
	
	if(count($temp)>0){
		$innerText=strip_spaces($parse->innerText($temp[0]));
				
		$words=str_word_count($innerText, 1);
		
		$acronyms=Array();
		
		//get each word and see if it's in all caps
		foreach($words as $this_word){
			
			if(time()>$timeout)
				break;
				
			if(strlen($this_word)>2){
				if($this_word==strtoupper($this_word)){
					//we need to check that this word has at least one letter in it, otherwise 'words' such as '----' will be picked up:
					for($i=0;$i<strlen($this_word);$i++){
						
						if(time()>$timeout)
							break;
			
						$ord=ord(strtoupper(substr($this_word, $i,1)));
						if($ord>64 && $ord<91){
							//this word is probably an acronym
							$acronyms[$this_word]=$this_word;
							break;		
						}
					}						
				}	
			}
		}	
		
		//now check to see if any of the words have an acronym attribute associated with it
		if(count($acronyms)>0)
			$found=true;
				
		$all_acronyms=$parse->getElementsByTagname('acronym');
		foreach($all_acronyms as $this_acronym){
			
			if(time()>$timeout)
				break;
			
			$innerText=trim($parse->innerText($this_acronym));
			//assumes that the whole innerText is the complete acronym:
			if(isset($acronyms[$innerText]))  
				unset($acronyms[$innerText]);
			
		}
		
		//The following acronyms do not have expanded definitions:
		if(count($acronyms)>0){
			foreach($acronyms as $key=>$this_acronym){
				
				if(time()>$timeout)
					break;
			
				$result_key="A potential acronym/abbreviation has been discovered: <span class=\"quote\">" . $key . "</span>.";
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
			
		} else {
			if($found){
				$result_key='All acronyms have been defined.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;			
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No acronyms were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No acronyms were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_4_3($parse){
	//Identify the primary natural language of a document.

	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#identify-lang
	
	//Methods:		As per http://www.w3.org/TR/NOTE-html-lan, we are checking the meta tags for a language value
	
	//TODO:			We are not testing for XML lang attributes (see the rule text for an example)
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']="Identify the primary natural language of a document. For example, in HTML set the &quot;lang&quot; attribute on the HTML element. In XML, use &quot;xml:lang&quot;. Server operators should configure servers to take advantage of HTTP content negotiation mechanisms ([<a href=\"#ref-RFC2068\">RFC2068</a>], section 14.13) so that clients can automatically retrieve documents of the preferred language.";
	$results['header']='g4';
	
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('html');
	//only check the first instance:
	$lang_codes=Array();
	$lang_codes=language_codes();
	
	if(count($temp)>0){
		$lang=$parse->getAttribute($temp[0], 'lang', true);
		//check that it is a valid two-letter code:
		if($lang!=''){
			$bits=explode('-',$lang);
			if($bits[0]!='i' && $bits[0]!='x'){
				$found=true;
				//if(strlen($lang)!=2 || !array_key_exists($lang, $lang_codes)){
				if(!array_key_exists($bits[0], $lang_codes)){
					$result_key='The primary language of this document does not appear to be valid.';
					$results['instances'][$result_key]['indices'][]=$temp[0];
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
					$results['instances'][$result_key]['highlight_attribute'][]='lang';
					$hasFailed=true;
				}				
			}
		}
	}
	if(!$found){
		$temp=$parse->getElementsByTagName('meta');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$http_equiv=$parse->getAttribute($this_element, 'http-equiv', true);
			$content=$parse->getAttribute($this_element, 'content', true);
			if(strtolower($http_equiv)=='content-language'){
				$bits=explode('-',$content);
				if($bits[0]!='i' && $bits[0]!='x'){
					//if(strlen($content)!=2 || !array_key_exists($content, $lang_codes)){
					if(!array_key_exists($bits[0], $lang_codes)){
						$result_key='The primary language of this document does not appear to be valid.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
						$results['instances'][$result_key]['highlight_attribute'][]='content';
						$hasFailed=true;
					}
					$found=true;
				}
			}
		}
	}
	
	if(!$found){	
		$result_key='The primary language of this document has not been set.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$hasFailed=true;
	} else {
		if(!$hasFailed){
			$result_key='This document contains a primary language value.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	return $results;
}

function WAI_3_5_5($parse){
	//Provide summaries for tables.

	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#table-summaries
	
	//NOTE:			I have decided that this only applies to data tables
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Provide summaries for tables.';
	$results['header']='g5';
	
	$hasFailed=false;
	$found=false;
	$temp=$parse->getElementsByTagname('table');

	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			if(is_data_table($parse, $this_element)){
				$found=true;
				$summary=$parse->getAttribute($this_element, 'summary');
				if(trim($summary=='')){
					$result_key='This table is missing a summary.  In the summary, describe the purpose of the table (either layout or data). For example \'This table charts the number of cups of coffee consumed by each senator, the type of coffee (decaf or regular), and whether taken with sugar.\'';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
				$captions=$parse->all_descendants($this_element, 'caption');
				if(count($captions)==0){
					$result_key='This table does not have a caption: A table caption describes the nature of the table in one to three sentences. For example, \'Cups of coffee consumed by each senator.\'';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
			}
		}
		if(!$hasFailed && $found){
			$result_key='All tables contained summaries';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		if(!$hasFailed && !$found){
			$result_key='No data tables were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No tables were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_5_6($parse){
	//Provide abbreviations for header labels.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#abbreviate-labels
	
	//TODO:			This does not check for any of the invalid types of abbreviations (none specified by w3 page)
	//NOTE:			This does not tie header results to the table it belongs to
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Provide abbreviations for header labels.';
	$results['header']='g5';
	
	$hasFailed=false;
	$required=false;
	
	$temp=$parse->getElementsByTagname('th');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$text=trim(strip_spaces($parse->innerText($this_element)));
			if(strlen($text)>15){
				$required=true;
				$abbr=$parse->getAttribute($this_element, 'abbr');
				if(trim($abbr=='')){
					$result_key='This table header is missing an abbreviation.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
			}
		}
		
		if(!$hasFailed  && !$required){
			$result_key='No table headers required abbreviations.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		if(!$hasFailed && $required){
			$result_key='All necessary table headers contained abbreviations.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No table headers were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_9_4($parse){
	//Create a logical tab order through links, form controls and objects.

	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#forms-keyboard
	//				If there is a tab index on any of these elements, then a warning is raised if any element of the same type does not carry a tabindex.
	//				Forms get a warning if no elements have a tabindex
	//				warnings are only raised for links without tabindexes if a tabindex is already present on another link
	
	//				http://unfortunatelypaul.com/2005/03/16/tabindex/
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Create a logical tab order through links, form controls, and objects.';
	$results['header']='g9';
	
	$hasFailed=false;
	$required=false;
	
	//get all the links:
	$temp=$parse->getElementsByTagname('a');
	if(count($temp)>0){
		$required=false;
		$links=Array();
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$tab_index=$parse->getAttribute($this_element, 'tabindex');
			if($tab_index==''){
				//this link has no tab index.. store it in the array incase we find a tab index later
				$links[]=$this_element;
			} else {
				if($tab_index<0 || !is_numeric($tab_index)){
					$result_key='This link has an invalid tab order value.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
					$hasFailed=true;
				} else
					$required=true;
				
			}
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This link is missing a tab order. A tab order makes links easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}
	//get all the links:
	//we want to restrict this to a per-map basis
	
	$temp=$parse->getElementsByTagname('map');
	foreach($temp as $this_map){
		
		if(time()>$timeout)
			break;
			
		$all_areas=$parse->all_descendants($this_map, 'area');
		$links=Array();
		$required=false;
		foreach($all_areas as $this_area){
			
			if(time()>$timeout)
				break;
				
			$tab_index=$parse->getAttribute($this_area, 'tabindex');
			if($tab_index==''){
				//this link has no tab index.. store it in the array incase we find a tab index later
				$links[]=$this_area;
			} else {
				if($tab_index<0 || !is_numeric($tab_index)){
					$result_key='This area link has an invalid tab order value.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
					$hasFailed=true;
				} else
					$required=true;
				
			}
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This area link is missing a tab order. A tab order makes links easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
	}
	
	$all_forms=$parse->getElementsByTagname('form');
	foreach($all_forms as $this_form){
		
		if(time()>$timeout)
			break;
				
		//The problem here is that we need to check all the different input types in this form for any instances of tabindex attributes
		$required=false;
		$links=Array();
		//get all the form controls:
		$temp=$parse->all_descendants($this_form, 'input');
		if(count($temp)>0){
			foreach($temp as $this_element){

				if(time()>$timeout)
					break;
				
				$type=$parse->getAttribute($this_element, 'hidden', true);
				if($type!='hidden'){
					$tab_index=$parse->getAttribute($this_element, 'tabindex');
					if($tab_index==''){	
						//this link has no tab index, store it in the array incase we find a tab index later
						$links[]['indice']=$this_element;
						$links[count($links)-1]['type']='form';
					} else {
						if($tab_index<0 || !is_numeric($tab_index)){
							$result_key='This form control has an invalid tab order value.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
							$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
							$hasFailed=true;
						} else
							$required=true;
						
					}
				}
			}
		}
		
		//get all the button controls:
		$temp=$parse->all_descendants($this_form, 'button');
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
					
				$tab_index=$parse->getAttribute($this_element, 'tabindex');
				if($tab_index==''){	
					//this link has no tab index.. store it in the array incase we find a tab index later
					$links[]['indice']=$this_element;
					$links[count($links)-1]['type']='button';
				} else {
					if($tab_index<0 || !is_numeric($tab_index)){
						$result_key='This button control has an invalid tab order value.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
						$hasFailed=true;
					} else
						$required=true;
					
				}
			
			}
		}
		//get all the select controls:
		$temp=$parse->all_descendants($this_form, 'select');
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
				
				$tab_index=$parse->getAttribute($this_element, 'tabindex');
				if($tab_index==''){	
					//this link has no tab index.. store it in the array incase we find a tab index later
					$links[]['indice']=$this_element;
					$links[count($links)-1]['type']='select';
				} else {
					if($tab_index<0 || !is_numeric($tab_index)){
						$result_key='This select control has an invalid tab order value.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
						$hasFailed=true;
					} else
						$required=true;
					
				}
			
			}
		}
		//get all the textarea controls:
		$temp=$parse->all_descendants($this_form, 'textarea');
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
				
				$tab_index=$parse->getAttribute($this_element, 'tabindex');
				if($tab_index==''){	
					//this link has no tab index.. store it in the array incase we find a tab index later
					$links[]['indice']=$this_element;
					$links[count($links)-1]['type']='textarea';
				} else {
					if($tab_index<0 || !is_numeric($tab_index)){
						$result_key='This textarea control has an invalid tab order value.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
						$hasFailed=true;
					} else
						$required=true;
					
				}
			
			}
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This ' . $this_link['type'] . ' control is missing a tab order. A tab order makes form controls easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link['indice'];
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}
	
	//get all the objects:
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		$required=false;
		$links=Array();
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$tab_index=$parse->getAttribute($this_element, 'tabindex');
			if($tab_index==''){
				//this link has no tab index.. store it in the array incase we find a tab index later
				$links[]=$this_element;
			} else {
				if($tab_index<0 || !is_numeric($tab_index)){
					$result_key='This form control has an invalid tab order value.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
					$hasFailed=true;
				} else
					$required=true;
				
			}		
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This object control is missing a tab order. A tab order makes form controls easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}

	if(!$hasFailed && $required){
		$result_key='All required elements had tab orders.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	if(!$hasFailed && !$required){
		$result_key='No elements required tab orders.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_9_5($parse){
	//Provide keyboard shortcuts to important links, form controls, and groups of form controls.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#keyboard-shortcuts
	
	//Notes:		INPUT elements of type 'hidden' are ignored here
	//				Should this check be aware of the form in which the elements are contained?
	//				Basically a form could have text fields with no accesskeys, but a single form field elsewhere
	//				with an accesskey would mean that form inputs were passed
	
	//NOTE:			Why is <SELECT> not in this list?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Provide keyboard shortcuts to important links (including those in client-side image maps), form controls, and groups of form controls.';
	$results['header']='g9';
	
	$hasFailed=false;
	$found=false;
	$required=false;
	
	$temp=$parse->getElementsByTagname('a');
	if(count($temp)){
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>a</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	$temp=$parse->getElementsByTagname('area');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>area</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	$temp=$parse->getElementsByTagname('button');
	if(count($temp)){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>button</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	$temp=$parse->getElementsByTagname('input');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->getAttribute($this_element, 'type')!='hidden'){
				if($parse->specified($this_element, 'accesskey')){
					$found=true;
					break;
				}
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>input</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	$temp=$parse->getElementsByTagname('label');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>label</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	$temp=$parse->getElementsByTagname('LEGEND');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>legend</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	$temp=$parse->getElementsByTagname('textarea');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found && $required){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>textarea</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	if(!$hasFailed && $required){
		$result_key='Access keys were found on all of the required element types.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;	
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	if(!$required){
		$result_key='No elements required keyboard shortcuts.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;	
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_10_3($parse){
	//Until user agents (including assistive technologies) render side-by-side text correctly, provide a linear text alternative (on the current page or some other) for all tables that lay out text in parallel, word-wrapped columns.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#linear-tables
	
	//Methods:		Raise a warning for all non-data tables that are found.
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> (including assistive technologies) render side-by-side text correctly, provide a linear text alternative (on the current page or some other) for all tables that lay out text in parallel, word-wrapped columns.";
	$results['header']='g10';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('table');
	if(count($temp)){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if(is_data_table($parse, $this_element)){
				$result_key='Please consult the definition of linearised table. This checkpoint benefits people with user agents (such as some screen readers) that are unable to handle blocks of text presented side-by-side; the checkpoint should not discourage content developers from using tables to represent tabular information.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
		if(!$hasFailed){
			$result_key='No layout tables were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No tables were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_10_4($parse){
	//Until user agents handle empty controls correctly, include default, place-holding characters in edit boxes and text areas.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#place-holders
	
	//Note:			&nbsp; counts as valid text for textareas
	//				Also, how do <optgroup> elements affect option requirements?
	
	//TODO:			Fix the message to differentiate between textfields, radio buttons and checkboxes
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']="<a href=\"/#until-user-agents\">Until user agents</a> handle empty controls correctly, include default, place-holding characters in edit boxes and text areas.";
	$results['header']='g10';
	
	$hasFailed=false;
	
	//check that all inputs of type 'text', 'checkbox' or 'radio' have a default value
	//NOTE: I've removed checkbox and radio buttons from this since 'value' is the wrong attribute to check and
	//the default state might be 'off'
	
	$temp=$parse->getElementsByTagname('input');
	$found=false;
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$found=true;
		$type=$parse->getAttribute($this_element, 'type', true);
		//if($type=='text' || $type=='checkbox' || $type=='radio'){
		if($type=='text'){
			$value=trim(strip_spaces($parse->getAttribute($this_element, 'value')));
			if($value==''){
				$result_key='This form control is missing placeholder text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['highlight_limit'][]=-1;
				$hasFailed=true;
			}
		}
	}
	//check that all textareas have some text
	$temp=$parse->getElementsByTagname('textarea');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$found=true;
		$text=trim(strip_spaces($parse->innerText($this_element)));
		if($text==''){
			$result_key='This textarea is missing placeholder text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['highlight_limit'][]=-1;
			$hasFailed=true;
		}
	}
	
	//check that all select lists have a selected option
	$temp=$parse->getElementsByTagname('select');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$found=true;
		$selected_found=false;
		//Do we want to just specify <option> elements, or get everything (there could be <optgroup> tags...
		$options=$parse->all_descendants($this_element);
		foreach($options as $this_option){
			
			if(time()>$timeout)
				break;
				
			$is_selected=$parse->specified($this_option, 'selected');
			if($is_selected){
				$selected_found=true;
				break;
			}
		}
		if(!$selected_found){
			$result_key='At least one option must be selected within this group.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['highlight_limit'][]=MAX_CHILDREN_SHOWN;
			$hasFailed=true;
		}
	}
	
	if(!$found){
		$result_key='No form controls were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	} else {
		if(!$hasFailed){
			$result_key='Default values were specified for all form controls.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	return $results;
}

function WAI_3_10_5($parse){
	//Until user agents (including assistive technologies) render adjacent links distinctly, include non-link, printable characters (surrounded by spaces) between adjacent links.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#divide-links
	
	//Methods:		If two <a> tags are found in sequential order, then this is raised as an error.
	//				&nbsp; instances are ignored in this check
	
	//NOTE:			What do we do about internal anchors?
	//TODO:			Perhaps check to see if the elements have been redefined as block/inline elements?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']="<a href=\"#until-user-agents\">Until user agents</a> (including assistive technologies) render adjacent links distinctly, include non-link, printable characters (surrounded by spaces) between adjacent links.";
	$results['header']='g10';
	
	$hasFailed=false;
	
	//get all the anchor tags, and check to see if the next tag is another anchor tag... if so, it has failed.
	$temp=$parse->getElementsByTagname('a');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			if(time()>$timeout)
				break;
				
			$innerText=strip_spaces($parse->innerText($this_element), true);
			if($innerText!='' && $parse->specified($this_element, 'href')){
				//okay, so this link has text, let's see if the very next element is also a link
				//get the closing index
				$closing_index=$parse->allElements[$this_element]['closingIndex'];
				
				//ok, so get the next element after this closing element
				//if it is a block element (opening or closing), then exit
				$not_link=true;
				$link_found=false;
				$next=$closing_index;
				
				do {
					$next=$parse->getNextElement($next, 'forward', true);
					
					if(!$next)
						break;
					
					$tagname=$parse->tagname($next);
					if(tagType($tagname)==PARSE_BLOCK_ELEMENT && !$parse->isOrphan($next))
						break;
						
					if($tagname=='a' && !$parse->isClosing($next)){
						$innerText=strip_spaces($parse->innerText($next), true);
						if($innerText!='' && $parse->specified($next, 'href')){
							$link_found=true;
							break;
						}
					}
					
				} while($not_link);
					
				if($link_found){
					$text=strip_spaces($parse->text($closing_index), true);
					if($text==''){
						$result_key="This link does not have a separating character between it and the next link.";
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]="The two adjacent links are:<br><span class=\"quote\">" . htmlspecialchars($parse->outerHTML($this_element)) . "</span><br>and<br><span class=\"quote\">" . htmlspecialchars($parse->outerHTML($next)) . "</span>.";
						$hasFailed=true;
					}
				}
			}
		}
		
		if(!$hasFailed){
			$result_key='No text links were found adjacent to one another.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No anchor tags were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_11_3(){
	//Provide information so that users may receive documents according to their preferences.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#content-preferences
	
	//Note:			This is a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Provide information so that users may receive documents according to their preferences (e.g., language, content type, etc.).';
	$results['header']='g11';
	
	$result_key='Provide information so that users may receive documents according to their preferences.';
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_13_5(){
	//Provide navigation bars to highlight and give access to the navigation mechanism.
	
	//Priority:		May
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Provide navigation bars to highlight and give access to the navigation mechanism.';
	$results['header']='g13';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_13_6(){
	//Group related links, identify the group (for user agents), and, until user agents do so, provide a way to bypass the group.
	
	//Priority:		May
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']="Group related links, identify the group (for <a href=\"#until-user-agents\">user agents</a>), and, until user agents do so, provide a way to bypass the group.";
	$results['header']='g13';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_13_7($parse){
	//If search functions are provided, enable different types of searches for different skill levels and preferences.

	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#searches
	
	//Methods:		If a form contains the word 'search' in any part of the innerText value, this is assumed to be a 
	//				search form.  A warning is then raised.
	//				This checks for an input type="text".  If such a field exists and the word 'search' is present,
	//				then it fails.
	
	//NOTE:			Should the word 'search' extend to the value attribute of the input fields?
	//				Should a search form have a valid button or submit button to be included?
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='If search functions are provided, enable different types of searches for different skill levels and preferences.';
	$results['header']='g13';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('form');
	if(count($temp)>0){
		foreach($temp as $this_element){

			if(time()>$timeout)
				break;
				
			$innerHTML=strtolower($parse->innerHTML($this_element, true));
			if(strpos($innerHTML, 'search')!==false){
				$all_inputs=$parse->all_descendants($this_element, 'input');
				$found_text=false;
				
				foreach($all_inputs as $this_input){

					if(time()>$timeout)
						break;
						
					$type=$parse->getAttribute($this_input, 'type');
					if($type=='text'){
						$found_text=true;
						break;
					}
					
				}
				
				if($found_text){
					$result_key='When providing search functionality, content developers should offer search mechanisms that satisfy varying skill levels and preferences. Most search facilities require the user to enter keywords for search terms. Users with spelling disabilities and users unfamiliar with the language of your site will have a difficult time finding what they need if the search requires perfect spelling. Search engines might include a spell checker, offer &quot;best guess&quot; alternatives, query-by-example searches, similarity searches, etc.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_WARNING;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
			}
		}
	
		if(!$hasFailed){
			$result_key='No search forms were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No forms were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_13_8(){
	//Place distinguishing information at the beginning of headings, paragraphs, lists, etc.
	
	//Priority:		May
	
	//Techniques:	Raise as a user check
	
	//Notes:		The WAI page provides no hints on this rule
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Place distinguishing information at the beginning of headings, paragraphs, lists, etc.';
	$results['header']='g13';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_13_9(){
	//Provide information about document collections.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#bundled-version
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Provide information about document collections (i.e., documents comprising multiple pages.).';
	$results['header']='g13';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_13_10($parse){
	//Provide a means to skip over multi-line ASCII art.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#skip-over-ascii
	
	//Methods:		The elements <pre> and <xmp> are checked for.  Any instances are raised as warnings.
	
	//Notes:		This does not check to see if this element is visible or not.
	//				This does not check for either a link or actual ASCII art
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;;
	$results['rule_text']='Provide a means to skip over multi-line ASCII art.';
	$results['header']='g13';
	
	$found=false;
	
	$temp=$parse->getElementsByTagname('pre');
	if(count($temp)>0){
		$found=true;	
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='A link must be provided to skip over ASCII art.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	$temp=$parse->getElementsByTagname('xmp');
	if(count($temp)>0){
		$found=true;	
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='A link must be provided to skip over ASCII art.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	if(!$found){
		$result_key='No instances of multiline ASCII art were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function WAI_3_14_2(){
	//Supplement text with graphic or auditory presentations where they will facilitate comprehension of the page.
	
	//Priority:		May
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Supplement text with graphic or auditory presentations where they will facilitate comprehension of the page.';
	$results['header']='g14';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	return $results;
}

function WAI_3_14_3($parse){
	//Create a style of presentation that is consistent across pages.
	
	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#navigation
	
	//Methods:		If a <style> or <link> element is found, then stylesheets have been used.  Both tags MUST have
	//				type='text/css' included.
	
	//Note:			No attempt to check for the same stylesheets across different pages is made... should it?
	//				No check is made to see if these required elements actually have any content
	
	//In this, we are going to require that the rel attribute is either 'stylesheet' or not specified, so that this
	//stylesheet is inferred as being the preferred stylesheet.  'Alternate stylesheet' stylesheets do not fit this
	//requirement
	
	//NOTE:			According to how this has been implemented, it is possible for a <link> element with no REL or MEDIA
	//				attribute to be valid...
	
	$timeout=get_timeout();
	
	$results=Array();
	$results['priority']=PRIORITY_MAY;
	$results['rule_text']='Create a style of presentation that is consistent across pages.';
	$results['header']='g14';
	
	$found=false;
	
	$temp=$parse->getElementsByTagname('link');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$rel=$parse->getAttribute($this_element, 'rel', true);
		$type=$parse->getAttribute($this_element, 'type', true);
		$media=$parse->getAttribute($this_element, 'media', true);
		
		if($type=='text/css' && ($rel=='stylesheet' || $rel=='') && ($media=='' || $media=='screen' || $media=='all'))
			$found=true;	
		
	}
	
	$temp=$parse->getElementsByTagname('style');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$type=$parse->getAttribute($this_element, 'type', true);
		$media=$parse->getAttribute($this_element, 'media', true);
		
		if($type=='text/css' && ($media=='' || $media=='screen' || $media=='all'))
			$found=true;	
		
	}
	
	if($found){
		$result_key='Style sheets have been used for presentation purposes.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	} else {
		$result_key='Consistent page layout and recognisable graphics benefit all users. In particular, they help people with cognitive disabilities or who have difficulty reading.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	return $results;
}

function get_timeout(){
	return time() + LOOP_LENGTH;
}

?>
Return current item: OpenWolf Guidelines Validator