diff options
Diffstat (limited to 'misc/openlayers/tests/auto-tests.html')
-rw-r--r-- | misc/openlayers/tests/auto-tests.html | 2447 |
1 files changed, 2447 insertions, 0 deletions
diff --git a/misc/openlayers/tests/auto-tests.html b/misc/openlayers/tests/auto-tests.html new file mode 100644 index 0000000..f467e41 --- /dev/null +++ b/misc/openlayers/tests/auto-tests.html @@ -0,0 +1,2447 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html><head> +<meta http-equiv="refresh" content="1200" /> +<title> Run the testsuite</title> +<noscript>Javascript is disabled in your browser. This page cannot be displayed correctly without Javascript. Sorry. <br/> If you want to view this page, please change your browser settings so that Javascript is enabled.</noscript> +<!-- +Test.AnotherWay version 0.5 + +Copyright (c) 2005 Artem Khodush, http://straytree.org + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--> +<style type="text/css"> +* { padding: 0; margin: 0; } +html { height: 99%; } +body { height: 98%; font: normal normal 10pt sans-serif } +#col1 { float: left; width: 27em; margin: 0 0 0 1em; overflow: visible; } +#col2 { position: relative; height: 98%; margin: 0 0.5em 0 28em; } +#col1_header { margin-top: 0.5em; } +#scroller { height: 400px; overflow: auto;} +#testtable { margin: 0 0 2em 0; width: 97%; } +#run_buttons { margin-bottom: 4em; } + +#right_header { padding-top: 0.8em; } +#results_count { float: left; } +.active_tab { float: right; padding: 0 1em 0.2em 1em; background: #0af; border: 1px solid #048; border-bottom: none; cursor: pointer; cursor: hand; + position: relative; top: -0.2em; } +.inactive_tab { float: right; padding: 0 1em 0 1em; background: #9bb; color: #444; border: 1px solid #9bb; border-bottom: none; cursor: pointer; cursor: hand; } +.inactive_mouseover_tab { float: right; padding: 0 1em 0 1em; background: #9bb; color: #062; border: 1px solid #062; border-bottom: none; cursor: pointer; cursor: hand; } + +#right_frame { overflow: auto; position: relative; top: -0.2em; clear: right; height: 95%; border: 1px solid #048; } + +#debug { display: none; } +#debug p { margin: 2px 0 0 5em; text-indent: -4.8em; } + +#error { display: none; color: #c22; } + +#results p { margin: 0 0 2px 0; } +/* cursor indicating that detailed results may be expanded/contracted */ +#results p.badtest { cursor: text; } +#results p.ok, #results p.fail { cursor: pointer; cursor: hand; } + +/* colored squares in the results window at the left of test page names */ +#results p.ok .bullet { background: #6d6; } +#results p.fail .bullet { background: #d46; } +#results p.badtest .bullet { background: #ea3; } +#results p.loading .bullet { background: #48f; } +#results p.running .bullet { background: #26e; } +#results p.waiting .bullet { background: #04d; } +/* highlight in the results line */ +#results p .warning { background: #ffc; } + +/* layout of the detailed results */ +.result_detail { padding-left: 3em; } +.result_exception_detail { padding-left: 4em; } +.result_exception_stack_detail { padding-left: 5em; } +.result_micro_detail { padding-left: 6em; } +/* colouring in the detailed results */ +.result_detail .fail, .result_exception_detail .fail, .result_micro_detail .fail { background: #ffd8d8; } + +/* "start recording" controls*/ +#record_div { margin-top: 3em; } +#record_div p { margin-bottom: 0.5em; } +#record_select { width: 88%; } +#record_input { width: 53%; } +</style> +<script type="text/javascript"> +<!-- + +function report_results() { + req = false; + // branch for native XMLHttpRequest object + if(window.XMLHttpRequest && !(window.ActiveXObject)) { + try { + req = new XMLHttpRequest(); + } catch(e) { + req = false; + } + // branch for IE/Windows ActiveX version + } else if(window.ActiveXObject) { + try { + req = new ActiveXObject("Msxml2.XMLHTTP"); + } catch(e) { + try { + req = new ActiveXObject("Microsoft.XMLHTTP"); + } catch(e) { + req = false; + } + } + } + req.open("POST", "/test/results.cgi"); + req.setRequestHeader("Content-Type", 'application/x-www-form-urlencoded'); + var results = document.getElementById('total').innerHTML; + var test_text = ""; + if (results.match("fail")) { + test_text = document.getElementById("results").innerHTML; + } + req.send("results="+escape(results)+"&test_text="+escape(test_text)); +} + +if( typeof( Test )=="undefined" ) { + Test={}; +} +Test.AnotherWay={}; + +Test.AnotherWay._g_test_iframe=null; // frame where to load test pages +Test.AnotherWay._g_test_frame_no_clear=false; // true - leave last page displayed after tests end +Test.AnotherWay._g_test_page_urls=[]; // array of: { url: url, convention: "anotherway" or "jsan" } +Test.AnotherWay._g_test_object_for_jsan=null; // test object for filling by tests that adhere to jsan Test.Simple calling convention +Test.AnotherWay._g_pages_to_run=null; // list of pages to run automatically after loading +Test.AnotherWay._g_run_on_main_load=false; // special handling for run_pages_to_run when it might be called before onload or before list of test pages is known. +Test.AnotherWay._g_run_on_list_load=false; +Test.AnotherWay._g_main_loaded=false; + +Test.AnotherWay._run_pages_to_run=function( called_from_outside ) +{ + if( !Test.AnotherWay._g_main_loaded ) { + Test.AnotherWay._g_run_on_main_load=true; + }else { + var a_pages=Test.AnotherWay._g_pages_to_run; + if( a_pages=="all" ) { + for( var i=0; i<Test.AnotherWay._g_test_page_urls.length; ++i ) { + Test.AnotherWay._run_test_page( "test"+i ); + } + }else if( a_pages!=null ) { + for( var run_i=0; run_i<a_pages.length; ++run_i ) { + var run_page=a_pages[run_i]; + var found=false; + for( var all_i=0; all_i<Test.AnotherWay._g_test_page_urls.length; ++all_i ) { + if( run_page==Test.AnotherWay._g_test_page_urls[all_i].url ) { + Test.AnotherWay._run_test_page( "test"+all_i, called_from_outside ); + found=true; + break; + } + } + if( !found ) { + Test.AnotherWay._show_error( "page specified to run is not found in the page list: "+run_page ); + break; + } + } + } + } +} + +Test.AnotherWay._add_test_page_url=function( test_url, convention ) +{ + var table=document.getElementById( "testtable" ); + var record_select=document.getElementById( "record_select" ); + var index=Test.AnotherWay._g_test_page_urls.length; + + // trim spaces. + if( test_url.match( "^(\\s*)(.*\\S)(\\s*)$" ) ) { + test_url=RegExp.$2; + } + + Test.AnotherWay._g_test_page_urls[index]={ url: test_url, convention: convention }; + var row=table.insertRow( -1 ); + + var cell; + var cell_child; + cell=row.insertCell( -1 ); + cell_child=document.createElement( "input" ); + cell_child.type="checkbox"; + cell_child.id="checkbox"+index; + cell_child.checked='checked'; + cell_child.defaultChecked='checked'; + cell.appendChild( cell_child ); + + cell=row.insertCell( -1 ); + cell.setAttribute( "width", "75%" ); + cell.appendChild( document.createTextNode( test_url ) ); + + cell=row.insertCell( -1 ); + cell_child=document.createElement( "input" ); + cell_child.type="button"; + cell_child.id="test"+index; + cell_child.value=" run "; + cell_child.onclick=Test.AnotherWay._run_one_onclick; + cell.appendChild( cell_child ); + + cell=row.insertCell( -1 ); + cell.setAttribute( "width", "8em" ); + cell_child=document.createElement( "span" ); + cell.appendChild( cell_child ); + + var option=document.createElement( "option" ); + option.appendChild( document.createTextNode( test_url ) ); + record_select.appendChild( option ); +} +Test.AnotherWay._show_error=function( msg ) +{ + var error_div=document.getElementById( "error" ); + error_div.innerHTML=""; + error_div.appendChild( document.createTextNode( msg ) ); + error_div.style.display="block"; +} + +// read urls from the list in the html file inside the list_iframe +// fill on-screen list with urls and "run" buttons, and fill the g_test_page_urls object. +Test.AnotherWay._list_iframe_onload=function() +{ + if( window.frames.list_iframe!=null && window.frames.list_iframe.location!="" && window.frames.list_iframe.location!="about:blank" ) { + var list_doc=window.frames.list_iframe.document; + var list=list_doc.getElementById( "testlist" ); + if( list!=null ) { + for( var i=0; i<list.childNodes.length; ++i ) { + var item=list.childNodes[i]; + if( item.nodeName=="LI" || item.nodeName=="li" ) { + var convention="anotherway"; + if( Test.AnotherWay._get_css_class( item )=="jsan" ) { + convention="jsan"; + } + Test.AnotherWay._add_test_page_url( item.innerHTML, convention ); + } + } + if( Test.AnotherWay._g_run_on_list_load ) { + Test.AnotherWay._g_run_on_list_load=false; + Test.AnotherWay._run_pages_to_run(); + } + }else { + Test.AnotherWay._show_error( "no list with id 'testlist' in a list file "+window.frames.list_iframe.location ); + } + } +} + +Test.AnotherWay._map_checkboxes=function( f ) +{ + var table=document.getElementById( "testtable" ); + var checks=table.getElementsByTagName( "INPUT" ); + for( var i=0; i<checks.length; ++i ) { + if( checks[i].type=="checkbox" && checks[i].id.match( /^checkbox(\d+)$/ ) ) { + f( checks[i], RegExp.$1 ); + } + } +} +Test.AnotherWay._run_all_onclick=function() +{ + Test.AnotherWay._map_checkboxes( function( c, id ) { Test.AnotherWay._run_test_page( "test"+id ); } ); +} +Test.AnotherWay._run_selected_onclick=function() +{ + Test.AnotherWay._map_checkboxes( function( c, id ) { if( c.checked ) Test.AnotherWay._run_test_page( "test"+id ); } ); +} +Test.AnotherWay._unselect_all_onclick=function() +{ + Test.AnotherWay._map_checkboxes( function( c, id ) { c.checked=false; } ); +} +Test.AnotherWay._run_one_onclick=function() +{ + Test.AnotherWay._run_test_page( this.id ); +} + +// construct an object that will gather results of running one test function +Test.AnotherWay._test_object_t=function( fun_name ) +{ + this.name=fun_name; // name of the test function + this.n_plan=null; // planned number of assertions + this.n_ok=0; // # of ok assertions + this.n_fail=0; // # of failed assertions + this.exception=""; // if the function throwed an exception, it's its message + this.exception_stack=[]; // strings: function call stack from the exception + this.assertions=[]; // assertion results: array of { ok: 1 or 0, name: string } + this.wait_result_milliseconds=0; // how long to wait before collecting results from the test + this.second_wait_msg=null; // <p> status message (in addition to the page wait_msg) + this.delay_actions=[]; // array of actions to be perfomed after the test function returns + // action : { acton_kind: "call" | "window" | "replay" + // when "call": { call_fn call_delay_milliseconds } call_fn takes nothing + // when "window" : { wnd_url wnd_wnd wnd_fn wnd_timeout_milliseconds wnd_dont_close } wnd_fn takes wnd + // wnen "replay" : { replay_wnd replay_events replay_event_i replay_checkpoints } checkpoint_fn takes this, wnd + // } + this.delay_action_i=null; // index of delay action currently being performed + this.delay_prev_timer_time=0; // for counting time while performing delay_actions + this.delay_current_milliseconds_left=0; // time left before the next action, runs down + this.delay_total_milliseconds_left=0; // for indication: total estimated time for all actions, runs up and down +} + +Test.AnotherWay._test_object_t.prototype.ok=function( cond, name ) +{ + if( cond ) { + ++this.n_ok; + cond=1; + }else { + ++this.n_fail; + cond=0; + } + this.assertions.push( { ok: cond, name: name } ); +} +Test.AnotherWay._test_object_t.prototype.fail=function( name ) +{ + this.ok( false, name ); +} +Test.AnotherWay._test_object_t.prototype.plan=function( n ) +{ + this.n_plan=n; +} +Test.AnotherWay._test_object_t.prototype.wait_result=function( seconds ) +{ + this.wait_result_milliseconds=1000*seconds; +} +Test.AnotherWay._eq_fail_msg=function( path, what, expected, got ) +{ + return "eq: "+path+" "+what+" differ: got "+got+", but expected "+expected; +} +Test.AnotherWay._array_eq=function( expected, got, path, msg ) +{ + if( expected.length!=got.length ) { + msg.msg=Test.AnotherWay._eq_fail_msg( path, "array length", expected.length, got.length ); + return false; + } + for( var i=0; i<expected.length; ++i ) { + if( !Test.AnotherWay._thing_eq( expected[i], got[i], path+"["+i+"]", msg ) ) { + return false; + } + } + return true; +} +Test.AnotherWay._object_eq=function( expected, got, path, msg ) +{ + var v; + for( v in expected ) { + if( ! (v in got) ) { + msg.msg=Test.AnotherWay._eq_fail_msg( path+"."+v, "properties", expected[v], "undefined" ); + return false; + } + if( !Test.AnotherWay._thing_eq( expected[v], got[v], path+"."+v, msg ) ) { + return false; + } + } + for( v in got ) { + if( ! (v in expected) ) { + msg.msg=Test.AnotherWay._eq_fail_msg( path+"."+v, "properties", "undefined", got[v] ); + return false; + } + } + return true; +} +Test.AnotherWay._constructor_name=function( x ) +{ + if( x==null ) { + return ""; + } + var s="unknown"; + try { + s=typeof( x.constructor ); + if( s!="unknown" ) { + s=x.constructor.toString(); + } + }catch( e ) { + s="unknown"; + } + if( s=="unknown" ) { + // hackish attempt to guess a type + var is_array=true; + var index=0; + for( i in x ) { + if( i!=index ) { + is_array=false; + } + ++index; + } + return is_array ? "Array" : "Object"; // for empty arrays/objects, this will be wrong half the time + }else if( s.match( /^\s*function\s+(\w+)\s*\(/ ) ) { + return RegExp.$1; + }else { + var c = ''; + switch(typeof x) { + case 'string': + c = 'String'; + break; + case 'object': + c = 'Object'; + break; + default: + c = ''; + } + return c; } +} +Test.AnotherWay._is_array=function( x ) +{ + return Test.AnotherWay._constructor_name( x )=="Array"; +} +Test.AnotherWay._is_value_type=function( x ) +{ + cn=Test.AnotherWay._constructor_name( x ); + return cn=="Number" || cn=="String" || cn=="Boolean" || cn=="Date"; +} +Test.AnotherWay._thing_eq=function( expected, got, path, msg ) +{ + if( expected==null && got==null ) { + return true; + }else if( (expected==null && got!=null) || (expected!=null && got==null) ) { + msg.msg=Test.AnotherWay._eq_fail_msg( path, "values", expected, got ); + return false; + }else { + var expected_cn=Test.AnotherWay._constructor_name( expected ); + var got_cn=Test.AnotherWay._constructor_name( got ); + if( expected_cn!=got_cn ) { + msg.msg=Test.AnotherWay._eq_fail_msg( path, "types", expected_cn, got_cn ); + return false; + }else { + if( Test.AnotherWay._is_array( expected ) ) { + return Test.AnotherWay._array_eq( expected, got, path, msg ); + }else if( Test.AnotherWay._is_value_type( expected ) ) { + if( expected!=got ) { + msg.msg=Test.AnotherWay._eq_fail_msg( path, "values", expected, got ); + return false; + }else { + return true; + } + }else { // just a plain object + return Test.AnotherWay._object_eq( expected, got, path, msg ); + } + } + } +} +Test.AnotherWay._test_object_t.prototype.eq=function( got, expected, name ) +{ + var msg={}; + if( Test.AnotherWay._thing_eq( expected, got, "", msg ) ) { + this.ok( 1, name ); + }else { + this.fail( name+". "+msg.msg ); + } +} +Test.AnotherWay._test_object_t.prototype.like=function( got, expected, name ) +{ + if( got.match( expected )!=null ) { + this.ok( 1, name ); + }else { + this.fail( name+": got "+got+", but expected it to match: "+expected ); + } +} +Test.AnotherWay._g_html_eq_span=null; +Test.AnotherWay._html_eq_string_to_node=function( string_or_node, what, msg ) +{ + if( string_or_node.nodeType!=null ) { + string_or_node=Test.AnotherWay._html_eq_node_to_string( string_or_node ); // double trip - to make properties assigned in scripts available as html node attributes + } + if( Test.AnotherWay._g_html_eq_span==null ) { + Test.AnotherWay._g_html_eq_span=document.createElement( "span" ); + } + Test.AnotherWay._g_html_eq_span.innerHTML=string_or_node; + if( Test.AnotherWay._g_html_eq_span.childNodes.length!=1 ) { + msg.msg="bad "+what+" html string given (should contain exactly one outermost element): "+string_or_node; + } + return Test.AnotherWay._g_html_eq_span.childNodes[0].cloneNode( true ); +} +Test.AnotherWay._html_eq_node_to_string=function( node ) { + if( Test.AnotherWay._g_html_eq_span==null ) { + Test.AnotherWay._g_html_eq_span=document.createElement( "span" ); + } + Test.AnotherWay._g_html_eq_span.innerHTML=""; + if( node.outerHTML!=null ) { + Test.AnotherWay._g_html_eq_span.innerHTML=node.outerHTML; + }else { + var clone = node.cloneNode(true); + var node = Test.AnotherWay._g_html_eq_span; + if(node.ownerDocument && node.ownerDocument.importNode) { + if(node.ownerDocument != clone.ownerDocument) { + clone = node.ownerDocument.importNode(clone, true); + } + } + node.appendChild(clone); + } + return Test.AnotherWay._g_html_eq_span.innerHTML; +} +Test.AnotherWay._html_eq_path_msg=function( path ) +{ + var msg=""; + for( var i=0; i<path.length; ++i ) { + msg+=" [node "+path[i].node; + if( path[i].id!=null && path[i].id!="" ) { + msg+=" id "+path[i].id; + }else if( path[i].index!=null ) { + msg+=" at index "+path[i].index; + } + msg+="] " + } + return msg; +} +Test.AnotherWay._html_eq_fail_msg=function( path, what, expected, got ) +{ + return Test.AnotherWay._html_eq_path_msg( path )+": "+what+" differ: got "+got+", but expected "+expected; +} +Test.AnotherWay._html_eq_remove_blank=function( text ) +{ + if( text==null ) { + return ""; + }else if( text.match( "^(\\s*)(.*\\S)(\\s*)$" ) ) { + return RegExp.$2; + }else if( text.match( "\s*" ) ) { + return ""; + } + return text; +} +Test.AnotherWay._html_eq_remove_blank_nodes=function( node ) +{ + var to_remove=[]; + for( var child=node.firstChild; child!=null; child=child.nextSibling ) { + if( child.nodeType==3 ) { + var value=Test.AnotherWay._html_eq_remove_blank( child.nodeValue ); + if( value=="" ) { + to_remove.push( child ); + }else { + child.nodeValue=value; + } + } + } + for( var i=0; i<to_remove.length; ++i ) { + node.removeChild( to_remove[i] ); + } +} +Test.AnotherWay._html_node_type_text=function( node_type ) +{ + if( node_type==1 ) { + return "1 (html element)"; + }else if( node_type==3 ) { + return "3 (text)"; + }else { + return node_type; + } +} +Test.AnotherWay._html_eq_node=function( expected, got, path, msg, expected_loc_base, got_loc_base ) +{ + if( expected.nodeType!=got.nodeType ) { + msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "node types", Test.AnotherWay._html_node_type_text( expected.nodeType ), Test.AnotherWay._html_node_type_text( got.nodeType ) ); + return false; + }else if( expected.nodeType==3 ) { + if( expected.nodeValue!=got.nodeValue ) { + msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "text", expected.nodeValue, got.nodeValue ); + return false; + } + }else if( expected.nodeType==1 ) { + if( expected.nodeName!=got.nodeName ) { + msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "node names", expected.nodeName, got.nodeName ); + return false; + } + // compare attributes + var expected_attrs={}; + var got_attrs={}; + var i; + var a; + for( i=0; i<expected.attributes.length; ++i ) { + a=expected.attributes[i]; + if( a.specified ) { + expected_attrs[a.name]=1; + } + } + for( i=0; i<got.attributes.length; ++i ) { + a=got.attributes[i]; + if( a.specified ) { + got_attrs[a.name]=1; + } + } + for( a in expected_attrs ) { + if( ! (a in got_attrs) ) { + msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": attribute sets differ: expected attribute "+a+" is missing"; + return false; + } + } + for( a in got_attrs ) { + if( ! (a in expected_attrs) ) { + msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": attribute sets differ: got extra attribute "+a; + return false; + } + } + for( a in expected_attrs ) { + var expected_value=expected.getAttribute( a ); + var got_value=got.getAttribute( a ); + if( typeof( expected_value )=="string" && typeof( got_value )=="string" ) { + expected_value=Test.AnotherWay._html_eq_remove_blank( expected_value ); + got_value=Test.AnotherWay._html_eq_remove_blank( got_value ); + var ok=expected_value==got_value; + if( !ok && (a=="href" || a=="HREF" ) ) { // try relative hrefs + var expected_relative_value=expected_value; + if( expected_loc_base!=null && expected_value.substring( 0, expected_loc_base.length )==expected_loc_base ) { + expected_relative_value=expected_value.substring( expected_loc_base.length ); + } + var got_relative_value=got_value; + if( got_loc_base!=null && got_value.substring( 0, got_loc_base.length )==got_loc_base ) { + got_relative_value=got_value.substring( got_loc_base.length ); + } + ok=expected_relative_value==got_relative_value; + } + if( !ok ) { + msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "attribute "+a+" values", expected_value, got_value ); + return false; + } + }else if( typeof( expected_value )=="function" && typeof( got_value )=="function" ) { + expected_value=expected_value.toString(); + got_value=got_value.toString(); + if( expected_value!=got_value ) { + msg.msg=Test.AnotherWay._html_eq_fail_msg( path, "attribute "+a+" values", expected_value, got_value ); + return false; + } + }else { + var value_msg={}; + if( !Test.AnotherWay._thing_eq( expected_value, got_value, "", value_msg ) ) { + msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": attribute "+a+" values differ: "+value_msg.msg; + return false; + } + } + } + // compare child nodes + Test.AnotherWay._html_eq_remove_blank_nodes( expected ); + Test.AnotherWay._html_eq_remove_blank_nodes( got ); + var expected_length=expected.childNodes.length; + var got_length=got.childNodes.length; + if( expected_length<got_length ) { + msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": got "+(got_length-expected_length)+" extra child nodes"; + return false; + }else if( expected_length>got_length ) { + msg.msg=Test.AnotherWay._html_eq_path_msg( path )+": expected "+(expected_length-got_length)+" more child nodes"; + return false; + }else { + for( i=0; i<expected_length; ++i ) { + var expected_node=expected.childNodes[i]; + path.push( { node: expected_node.nodeName, id: expected_node.id, index: i } ); + var eq=Test.AnotherWay._html_eq_node( expected_node, got.childNodes[i], path, msg, expected_loc_base, got_loc_base ); + path.pop(); + if( !eq ) { + return false; + } + } + } + } + return true; +} +Test.AnotherWay._html_eq_get_loc_base=function( node ) +{ + var loc_base=document.location; + if( node.ownerDocument!=null ) { + loc_base=node.ownerDocument.location; + } + if( loc_base!=null ) { + loc_base=loc_base.href; + var slash_pos=loc_base.lastIndexOf( "/" ); + if( slash_pos!=-1 ) { + loc_base=loc_base.substring( 0, slash_pos+1 ); + } + } + return loc_base; +} +Test.AnotherWay._test_object_t.prototype.html_eq=function( got, expected, name ) +{ + var msg={}; + var expected_node=Test.AnotherWay._html_eq_string_to_node( expected, "expected", msg ); + if( msg.msg!=null ) { + this.fail( name+" html_eq: "+msg.msg ); + }else { + var got_node=Test.AnotherWay._html_eq_string_to_node( got, "got", msg ); + if( msg.msg!=null ) { + this.fail( name+" html_eq: "+msg.msg ); + }else { + var expected_loc_base=Test.AnotherWay._html_eq_get_loc_base( expected ); + var got_loc_base=Test.AnotherWay._html_eq_get_loc_base( got ); + if( Test.AnotherWay._html_eq_node( expected_node, got_node, [], msg, expected_loc_base, got_loc_base ) ) { + this.ok( 1, name ); + }else { + var msg=name+" html_eq "+msg.msg; + var expected_str=Test.AnotherWay._html_eq_node_to_string( expected_node ); + var got_str=Test.AnotherWay._html_eq_node_to_string( got_node ); + msg+=".\n got html: "+got_str; + msg+=".\n expected html: "+expected_str; + this.fail( msg ); + } + } + } +} +Test.AnotherWay._debug_pane_print=function( msg ) +{ + var d=new Date(); + var p=document.createElement( "p" ); + p.appendChild( document.createTextNode( d.toLocaleTimeString()+" "+msg ) ); + var debug_pane=document.getElementById( "debug" ); + debug_pane.appendChild( p ); + var debug_tab=document.getElementById( "debug_tab" ); + var results_tab=document.getElementById( "results_tab" ); + debug_tab.style.visibility="visible"; + results_tab.style.visibility="visible"; +} +Test.AnotherWay._test_object_t.prototype.debug_print=function( msg ) +{ + Test.AnotherWay._debug_pane_print( this.name+": "+msg ); +} +Test.AnotherWay._test_object_t.prototype.delay_call=function() +{ + var timeout_ms=200; + for( var i=0; i<arguments.length; ++i ) { + if( typeof( arguments[i] )!="function" ) { + timeout_ms=3000*arguments[i]; + }else { + var action={ action_kind: "call", call_delay_milliseconds: timeout_ms, call_fn: arguments[i] }; + this.delay_total_milliseconds_left+=Test.AnotherWay._action_estimate_milliseconds( action ); + this.delay_actions.push( action ); + } + } +} +Test.AnotherWay._test_object_t.prototype.open_window=function( url, fn, timeout_seconds ) +{ + if( timeout_seconds==null ) { + timeout_seconds=4; + } + var no_close=document.getElementById( "dont_close_test_windows" ); + var action={ action_kind: "window", wnd_url: url.toString(), wnd_wnd: null, wnd_fn: fn, wnd_timeout_milliseconds: timeout_seconds*1000, wnd_no_close: no_close.checked }; + this.delay_total_milliseconds_left+=Test.AnotherWay._action_estimate_milliseconds( action ); + this.delay_actions.push( action ); +} +Test.AnotherWay._test_object_t.prototype.replay_events=function( wnd, events ) +{ + if( Test.AnotherWay._g_no_record_msg!=null ) { + this.fail( "replay_events: "+Test.AnotherWay._g_no_record_msg ); + }else { + var action={ action_kind: "replay", replay_wnd: wnd, replay_events: events.events, replay_event_i: null, replay_checkpoints: events.checkpoints }; + this.delay_total_milliseconds_left+=Test.AnotherWay._action_estimate_milliseconds( action ); + this.delay_actions.push( action ); + } +} +Test.AnotherWay._action_estimate_milliseconds=function( action ) +{ + var ms=0; + if( action.action_kind=="call" ) { + ms=action.call_delay_milliseconds; + }else if( action.action_kind=="window" ) { + ms=0; + }else if( action.action_kind=="replay" ) { + ms=0; + for( var i=0; i<action.replay_events.length; ++i ) { + ms+=action.replay_events[i]["time"]-0; + } + } + return ms; +} + +Test.AnotherWay._g_timeout_granularity=200; +Test.AnotherWay._g_tests_queue=[]; // vector of { url: string, test_objects : array of test_object_t, test_object_i: int, wait_msg: <p> object, loading_timeout_milliseconds: int, timeout_id: id } + +// load one html page, schedule further processing +Test.AnotherWay._run_test_page=function( id, called_from_outside ) +{ + if( id.match( /^test(\d+)/ ) ) { + id=RegExp.$1; + Test.AnotherWay._g_tests_queue.push( { + url: Test.AnotherWay._g_test_page_urls[id].url, + convention: Test.AnotherWay._g_test_page_urls[id].convention, + test_objects: [] + } ); + if( Test.AnotherWay._g_tests_queue.length==1 ) { + if( !called_from_outside ) { + // Crap. Be careful stepping around. + // For Mozilla and Opera, when this file is included into the frameset page that is in another directory (and _g_outside_path_correction!=null) + // but the test pages are started from within it (by "run" buttons), then: + // depending on whether the page is the first one loaded into the test frame or not, + // the base url for relative test pages differs. + // Crap, like I said. + Test.AnotherWay._g_tests_queue[0].suppress_outside_path_correction=true; + } + Test.AnotherWay._start_loading_page(); + } + } +} +Test.AnotherWay._load_next_page=function() +{ + Test.AnotherWay._g_tests_queue.splice( 0, 1 ); + if( Test.AnotherWay._g_tests_queue.length>0 ) { + Test.AnotherWay._start_loading_page(); + }else { + if( !Test.AnotherWay._g_test_frame_no_clear ) { + Test.AnotherWay._g_test_iframe.location.replace( "about:blank" ); + } + report_results(); + } +} +Test.AnotherWay._g_opera_path_correction=null; // ugly wart to support opera +Test.AnotherWay._g_outside_path_correction=null; // ugly wart to accomodate Opera and Mozilla, where relative url relates to the directory where the page that calls this function is located +Test.AnotherWay._set_iframe_location=function( iframe, loc, outside_path_correction ) +{ + // allow to load only locations with the same origin + var proto_end=loc.indexOf( "://" ); + if( proto_end!=-1 ) { // otherwise, it's safe to assume (for Opera, Mozilla and IE ) that loc will be treated as relative + var main_loc=window.location.href; + var host_end=loc.substring( proto_end+3 ).indexOf( "/" ); + var ok=false; + if( host_end!=-1 ) { + var loc_origin=loc.substring( 0, proto_end+3+host_end+1 ); + if( main_loc.length>=loc_origin.length && main_loc.substring( 0, loc_origin.length )==loc_origin ) { + ok=true; + } + } + if( !ok ) { + return { msg: "test pages may have only urls with the same origin as "+main_loc }; + } + } + // opera cannot handle urls relative to file:// without assistance + if( window.opera!=null && window.location.protocol=="file:" && loc.indexOf( ":" )==-1 ) { + var base=window.location.href; + var q_pos=base.indexOf( "?" ); + if( q_pos!=-1 ) { + base=base.substring( 0, q_pos ); + } + var slash_pos=base.lastIndexOf( "/" ); + if( slash_pos!=-1 ) { + base=base.substring( 0, slash_pos+1 ); + Test.AnotherWay._g_opera_path_correction=base; + loc=base+loc; + } + } + // if this function is called from another page, and if that page is in another directory, correction is needed + if( outside_path_correction!=null ) { + var pos=loc.indexOf( outside_path_correction ); + if( pos==0 ) { + loc=loc.substring( outside_path_correction.length+1 ); + } + } + if( iframe.location!=null ) { + iframe.location.replace( loc ); + }else { + iframe.src=loc; + } + return {}; +} +Test.AnotherWay._start_loading_page=function() +{ + var test_page=Test.AnotherWay._g_tests_queue[0]; + test_page.loading_timeout_milliseconds=20000; + test_page.timeout_id=setTimeout( Test.AnotherWay._loading_timeout, Test.AnotherWay._g_timeout_granularity ); + test_page.wait_msg=Test.AnotherWay._print_counter_result( test_page.url, "loading...", test_page.loading_timeout_milliseconds, "loading" ); + if( test_page.convention=="jsan" ) { + // the tests in that page will run when it's loading, so the test object must be ready + Test.AnotherWay._g_test_object_for_jsan=new Test.AnotherWay._test_object_t( test_page.url ); + } + var outside_path_correction=null; + if( Test.AnotherWay._g_outside_path_correction!=null && !test_page.suppress_outside_path_correction ) { + outside_path_correction=Test.AnotherWay._g_outside_path_correction; + } + var result=Test.AnotherWay._set_iframe_location( Test.AnotherWay._g_test_iframe, test_page.url, outside_path_correction ); + if( result.msg!=null ) { + Test.AnotherWay._unprint_result( test_page.wait_msg ); + Test.AnotherWay._print_result( test_page.url, result.msg, "badtest", null ); + Test.AnotherWay._load_next_page(); + } +} + +Test.AnotherWay._loading_timeout=function() +{ + var test_page=Test.AnotherWay._g_tests_queue[0]; + test_page.loading_timeout_milliseconds-=Test.AnotherWay._g_timeout_granularity; + if( test_page.loading_timeout_milliseconds>0 ) { + Test.AnotherWay._update_msg_counter( test_page.wait_msg, (test_page.loading_timeout_milliseconds/1000).toFixed() ); + test_page.timeout_id=setTimeout( Test.AnotherWay._loading_timeout, Test.AnotherWay._g_timeout_granularity ); + }else { + Test.AnotherWay._unprint_result( test_page.wait_msg ); + Test.AnotherWay._print_result( test_page.url, "Unable to load test page. Timeout expired", "badtest", null ); + Test.AnotherWay._load_next_page(); + } +} + +Test.AnotherWay._strip_query_and_hash=function( s ) +{ + var i=s.lastIndexOf( "#" ); + if( i!=-1 ) { + s=s.substring( 0, i ); + } + i=s.lastIndexOf( "?" ); + if( i!=-1 ) { + s=s.substring( 0, i ); + } + return s; +} +Test.AnotherWay._is_url_loaded=function( url, wnd ) +{ + var loaded=false; + if( wnd!=null && wnd.location!=null ) { + // after some popup blocker interference, location may behave strange.. + var location_s=""; + location_s+=wnd.location; + if( location_s!="" ) { + var pathname=wnd.location.pathname; + var expected_url=url; + var i=expected_url.lastIndexOf( "#" ); + if( i!=-1 ) { + expected_url=expected_url.substring( 0, i ); + } + i=expected_url.lastIndexOf( "?" ); + if( i!=-1 ) { + expected_url=expected_url.substring( 0, i ); + } + i=expected_url.lastIndexOf( "/" ); + if( i!=-1 && i!=expected_url.length-1 ) { + expected_url=expected_url.substring( i+1 ); + } + i=pathname.indexOf( expected_url ) + if( wnd.location.href==url || (i!=-1 && i==pathname.length-expected_url.length) ) { + if( /*window.opera==null*/wnd.document.readyState==null || wnd.document.readyState=="complete" ) { // for opera (and IE?), getElementById does not work until.. + loaded=true; + } + } + } + } + return loaded; +} +// find and run all test functions in the g_cur_page html page. +Test.AnotherWay._test_page_onload=function() +{ + if( Test.AnotherWay._g_tests_queue.length==0 ) { + return; + } + var test_page=Test.AnotherWay._g_tests_queue[0]; + if( !Test.AnotherWay._is_url_loaded( test_page.url, Test.AnotherWay._g_test_iframe ) ) { + return; + } + clearTimeout( test_page.timeout_id ); + Test.AnotherWay._unprint_result( test_page.wait_msg ); + + if( test_page.convention=="anotherway" ) { + // get test function names (those beginning with "test") + if( typeof( Test.AnotherWay._g_test_iframe.document.scripts )!='undefined' ) { // IE + for( var i=0; i<Test.AnotherWay._g_test_iframe.document.scripts.length; ++i ) { + var script_text=Test.AnotherWay._g_test_iframe.document.scripts[i].text; + var fun_sig="function test"; + var fun_start=script_text.indexOf( fun_sig ); + + while( fun_start!=-1 ) { + script_text=script_text.substring( fun_start, script_text.length ); + var fun_end=script_text.indexOf( '(' ); + var fun_name=script_text.substring( "function ".length, fun_end ); + var whitespace = fun_name.indexOf( ' ' ); + if (whitespace >= 0) + fun_name = fun_name.substring( 0, whitespace ); + test_page.test_objects.push( new Test.AnotherWay._test_object_t( fun_name ) ); + script_text=script_text.substring( fun_end, script_text.length ); + fun_start=script_text.indexOf( fun_sig ); + } + } + }else { // otherwise (not IE) it ought to work like this + for( var i in Test.AnotherWay._g_test_iframe) { + // Hack to prevent failure in FF3.0b1 + if (i == "innerWidth" || i == "innerHeight") { continue; } + if( typeof( Test.AnotherWay._g_test_iframe[i] )=='function' ) { + if( i.substring( 0, 4 )=="test" ) { + test_page.test_objects.push( new Test.AnotherWay._test_object_t( i ) ); + } + } + } + } + }else if( test_page.convention=="jsan" ) { + // the test object is already filled with results + test_page.test_objects.push( Test.AnotherWay._g_test_object_for_jsan ); + } + + if( test_page.test_objects.length==0 ) { + Test.AnotherWay._print_result( test_page.url, "No test functions defined in the page", "badtest", null ); + Test.AnotherWay._load_next_page(); + return; + } + + test_page.wait_msg=Test.AnotherWay._print_result( test_page.url, "running tests..<span class=\"counter\">"+test_page.test_objects.length+"</span>", "running", null ); + + test_page.test_object_i=0; + Test.AnotherWay._run_more_tests(); +} + +Test.AnotherWay._handle_exception=function( o, e, title ) +{ + var s=title+": "+typeof( e )+": "; + if( e.message!=null ) { + s+=e.message; + }else if( e.description!=null ) { + s+=e.description; + }else { + s+=e.toString(); + } +// if( e.location!=null ) { // XXX figure out how to display exception location if it's present (like in mozilla) +// s+=" location: "+e.location.toString(); +// } + o.exception=s; + s=[]; + if( e.stack ) { + var lines=e.stack.split( "\n" ); + for( var i=0; i<lines.length; ++i ) { + // format of the line: func_name(args)@file_name:line_no + if( lines[i].match( /(\w*)\(([^\)]*)\)@(.*):([^:]*)$/ ) ) { + var func_name=RegExp.$1; + if( func_name.length==0 ) { + func_name="<anonymous>"; + } + s.push( "in "+func_name+"( "+RegExp.$2+") at "+RegExp.$3+" line "+RegExp.$4+"\n" ); + } + } + } + o.exception_stack=s; +} + +Test.AnotherWay._run_more_tests=function() +{ + var test_page=Test.AnotherWay._g_tests_queue[0]; + while( test_page.test_object_i<test_page.test_objects.length ) { + Test.AnotherWay._update_msg_counter( test_page.wait_msg, (1+test_page.test_object_i)+"/"+test_page.test_objects.length ); + var o=test_page.test_objects[test_page.test_object_i]; + if( test_page.convention=="anotherway" ) { + try { + Test.AnotherWay._g_test_iframe[o.name]( o ); + }catch( e ) { + Test.AnotherWay._handle_exception( o, e, "" ); + } + } // for "jsan" convention, test has run already + if( o.delay_actions.length>0 || o.wait_result_milliseconds>0 ) { + o.delay_total_milliseconds_left+=o.wait_result_milliseconds; + Test.AnotherWay._delay_actions_timeout(); + return; + } + ++test_page.test_object_i; + } + Test.AnotherWay._unprint_result( test_page.wait_msg ); + Test.AnotherWay._print_result( test_page.url, null, null, test_page.test_objects ); + Test.AnotherWay._load_next_page(); +} + +Test.AnotherWay._delay_actions_timeout=function() +{ + var test_page=Test.AnotherWay._g_tests_queue[0]; + var test_object=test_page.test_objects[test_page.test_object_i]; + var finished=true; + if( test_object.delay_action_i==null ) { + // set up to start first action + test_object.delay_action_i=-1; + }else { + // perform current action + var milliseconds_passed=(new Date()).getTime()-test_object.delay_prev_timer_time; + test_object.delay_current_milliseconds_left-=milliseconds_passed; + test_object.delay_total_milliseconds_left-=milliseconds_passed; + finished=Test.AnotherWay._delay_continue_action( test_object, milliseconds_passed ); + } + while( finished && test_object.delay_action_i<test_object.delay_actions.length ) { + ++test_object.delay_action_i; // start next action + finished=Test.AnotherWay._delay_start_action( test_object ); + } + if( test_object.delay_action_i<=test_object.delay_actions.length ) { // any more actions left ? + test_object.delay_prev_timer_time=(new Date()).getTime(); + var next_timeout=Test.AnotherWay._g_timeout_granularity; + if( test_object.delay_current_milliseconds_left<next_timeout ) { + next_timeout=test_object.delay_current_milliseconds_left; + } + if( test_object.second_wait_msg!=null ) { + Test.AnotherWay._update_msg_counter( test_object.second_wait_msg, (test_object.delay_total_milliseconds_left/1000).toFixed() ); + } + setTimeout( Test.AnotherWay._delay_actions_timeout, next_timeout ); + }else { // no more actions left. run the next test. + if( test_object.second_wait_msg!=null ) { + Test.AnotherWay._unprint_result( test_object.second_wait_msg ); + test_object.second_wait_msg=null; + } + ++test_page.test_object_i; + Test.AnotherWay._run_more_tests(); + } +} +Test.AnotherWay._delay_start_action=function( test_object ) +{ + var finished=false; + var wait_msg=""; + if( test_object.delay_action_i==test_object.delay_actions.length ) { + if( test_object.wait_result_milliseconds>0 ) { + test_object.delay_current_milliseconds_left=test_object.wait_result_milliseconds; // wait for result + wait_msg="waiting for results.."; + }else { + ++test_object.delay_action_i; // dont wait for result + } + }else { + var action=test_object.delay_actions[test_object.delay_action_i]; + if( action.action_kind=="call" ) { + test_object.delay_current_milliseconds_left=action.call_delay_milliseconds; + wait_msg="performing delayed calls.."; + }else if( action.action_kind=="window" ) { + if( Test.AnotherWay._g_opera_path_correction!=null && action.wnd_url.indexOf( ":" )==-1 ) { + action.wnd_url=Test.AnotherWay._g_opera_path_correction+action.wnd_url; + } + action.wnd_wnd=window.open( action.wnd_url, "_blank" ); + if( action.wnd_wnd==null ) { + finished=true; + test_object.fail( "unable to open window for "+action.wnd_url ); + }else { + test_object.delay_current_milliseconds_left=action.wnd_timeout_milliseconds; + wait_msg="opening window.."; + } + }else if( action.action_kind=="replay" ) { + if( action.replay_events.length==0 ) { + finished=true; + }else { + action.replay_event_i=0; + test_object.delay_current_milliseconds_left=action.replay_events[0]["time"]; + wait_msg="replaying events.."; + } + } + } + if( test_object.second_wait_msg!=null ) { + Test.AnotherWay._unprint_result( test_object.second_wait_msg ); + } + if( wait_msg!="" ) { + var test_page=Test.AnotherWay._g_tests_queue[0]; + test_object.second_wait_msg=Test.AnotherWay._print_counter_result( test_page.url, wait_msg, test_object.delay_total_milliseconds_left, "waiting" ); + }else { + test_object.second_wait_msg=null; + } + return finished; +} +Test.AnotherWay._delay_continue_action=function( test_object, milliseconds_passed ) +{ + var finished=test_object.delay_current_milliseconds_left<=0; + if( test_object.delay_action_i==test_object.delay_actions.length ) { // action is "waiting for results" + if( test_object.n_plan!=null && test_object.n_plan==test_object.n_ok+test_object.n_fail ) { + finished=true; // if all assertions results are recorded, don't wait any more + } + if( finished ) { + ++test_object.delay_action_i; // move on to the next test + } + }else { + var action=test_object.delay_actions[test_object.delay_action_i]; + if( action.action_kind=="call" ) { + if( finished ) { + try { + action.call_fn(); + }catch( e ) { + Test.AnotherWay._handle_exception( test_object, e, "in delay_call" ); + } + } + }else if( action.action_kind=="window" ) { + test_object.delay_total_milliseconds_left+=milliseconds_passed; // for "window", the countdown is suspended since it's unknown how long it will take + if( Test.AnotherWay._is_url_loaded( action.wnd_url, action.wnd_wnd ) ) { + try { + action.wnd_fn( action.wnd_wnd ); + }catch( e ) { + Test.AnotherWay._handle_exception( test_object, e, "in open_window function call" ); + } + finished=true; + }else if( finished ) { + test_object.fail( "unable to open window for url '"+action.wnd_url+"'. timeout expired" ); + } + }else if( action.action_kind=="replay" ) { + if( finished ) { +// try { + Test.AnotherWay._delay_replay_event( test_object, action.replay_wnd, action.replay_events[action.replay_event_i], action.replay_checkpoints ); +// }catch( e ) { // disabled, until I know how to gel location info from an exception +// Test.AnotherWay._handle_exception( test_object, e, "while replaying event" ); +// } + ++action.replay_event_i; + finished=action.replay_event_i==action.replay_events.length; + if( !finished ) { + test_object.delay_current_milliseconds_left=action.replay_events[action.replay_event_i]["time"]; + } + } + } + } + return finished; +} +Test.AnotherWay._delay_replay_event=function( test_object, wnd, event, checkpoints ) +{ + if( event.type=="_checkpoint" ) { + var checkpoint_n=event.which; + var prev_n_fail=test_object.n_fail; + checkpoints[checkpoint_n]( test_object, wnd ); + var flash_color= prev_n_fail==test_object.n_fail ? "#2f2" : "#f22" ; + Test.AnotherWay._record_flash_border( flash_color ); + }else if( event.type=="click" || event.type=="mouseover" || event.type=="mouseout" || event.type=="mousemove" || event.type=="mousedown" || event.type=="mouseup" ) { + var target=Test.AnotherWay._record_node_path_to_node( event["target"], wnd.document ); + if( target!=null ) { + Test.AnotherWay._record_control_update_highlight( target, "ball", event ); + var e=wnd.document.createEvent( "MouseEvents" ); + var related_target=Test.AnotherWay._record_node_path_to_node( event["relatedTarget"], wnd.document ); + e.initMouseEvent( + event["type"], + event["cancelable"], + event["bubbles"], + wnd.document.defaultView, + event["detail"], + event["screenX"], + event["screenY"], + event["clientX"], + event["clientY"], + event["ctrlKey"], + event["altKey"], + event["shiftKey"], + event["metaKey"], + event["button"], + Test.AnotherWay._record_node_path_to_node( event["relatedTarget"], wnd.document ) + ); + // Firefox 1.0.6 somehow loses relatedTarget somewhere on the way. Pass through our own, for those who choose to care. + e.passThroughRelatedTarget=related_target; + target.dispatchEvent( e ); + } + }else if( event.type=="keyup" || event.type=="keydown" || event.type=="keypress" ) { + var e=wnd.document.createEvent( "KeyboardEvents" ); // forget it. Apparently it's not supported neither by mozilla nor by opera. + e.initKeyboardEvent( + event["type"], + event["cancelable"], + event["bubbles"], + wnd.document.defaultView, + event["which"], + event["which"], + event["ctrlKey"], + event["altKey"], + event["shiftKey"], + event["metaKey"], + false + ); + wnd.document.dispatchEvent( e ); + } +} + +Test.AnotherWay._print_counter_result=function( url, msg, milliseconds, style ) +{ + return Test.AnotherWay._print_result( url, msg+"<span class=\"counter\">"+(milliseconds/1000).toFixed()+"</span>", style, null ); +} + +Test.AnotherWay._g_result_count=0; // for assigning unique ids to result paragraphs + +// number of pages tested +Test.AnotherWay._g_ok_pages=0; +Test.AnotherWay._g_fail_pages=0; + +Test.AnotherWay._print_result=function( url, msg, style, test_objects ) +{ + var results=document.getElementById( "results" ); + var r=results.appendChild( document.createElement( "p" ) ); + r.id="result"+Test.AnotherWay._g_result_count; + ++Test.AnotherWay._g_result_count; + r.onclick=Test.AnotherWay._toggle_detail; + var text="<span class=\"bullet\"> </span> "; + if( url!="" ) { + text+=url+": "; + } + if( msg!=null ) { + text+=msg; + } + if( test_objects!=null ) { + // compose summary and detail texts + var total_ok=0; + var total_detail_ok=0; + var total_fail=0; + var total_detail_fail=0; + var no_plan=0; + + var detail=results.appendChild( document.createElement( "div" ) ); + + if( r.id.match( /^result(\d+)$/ ) ) { + detail.id="result_detail"+RegExp.$1; + } + + for( var i=0; i<test_objects.length; ++i ) { + var o=test_objects[i]; + var p; + var p_text; + p=document.createElement( "P" ); + Test.AnotherWay._set_css_class( p, "result_detail" ); + p_text=o.name; + if( o.n_fail>0 || o.exception || (o.n_plan!=null && o.n_plan!=o.n_ok+o.n_fail) || (o.n_plan==null && o.n_ok==0 && o.n_fail==0)) { + ++total_fail; + p_text+=" <span class=\"fail\">"; + if( o.n_plan!=null && o.n_plan!=o.n_ok+o.n_fail) { + p_text+="planned "+o.n_plan+" assertions but got "+(o.n_ok+o.n_fail)+"; "; + } + if(o.n_plan==null && o.n_ok==0 && o.n_fail==0) { + p_text+="test did not output anything"; + }else { + p_text+=" fail "+o.n_fail; + } + p_text+="</span>"; + }else { + ++total_ok; + } + p_text+=" ok "+o.n_ok; + if( o.n_plan==null ) { + no_plan=1; + p_text+=" <span class=\"warning\">no plan</span>"; + } + p.innerHTML=p_text; + detail.appendChild( p ); + if( o.exception ) { + p=document.createElement( "P" ); + Test.AnotherWay._set_css_class( p, "result_exception_detail" ); + p.innerHTML="<span class=\"fail\">exception:</span> "+o.exception; + detail.appendChild( p ); + p=document.createElement( "P" ); + Test.AnotherWay._set_css_class( p, "result_exception_stack_detail" ); + p.innerHTML=o.exception_stack.join( "<br/>" ); + detail.appendChild( p ); + } + for( var ii=0; ii<o.assertions.length; ++ii ) { + var oo=o.assertions[ii]; + var status=oo.ok ? "ok" : "<span class=\"fail\">fail</span>"; + p=document.createElement( "P" ); + Test.AnotherWay._set_css_class( p, "result_micro_detail" ); + p.innerHTML=status; + p.appendChild( document.createTextNode( " "+oo.name ) ); + detail.appendChild( p ); + } + total_detail_ok+=o.n_ok; + total_detail_fail+=o.n_fail; + } + if( total_fail || total_detail_fail ) { + text+=" fail "+total_fail; + } + text+=" ok "+total_ok+" (detailed:"; + if( total_fail || total_detail_fail ) { + text+=" fail "+total_detail_fail; + } + text+=" ok "+total_detail_ok+")"; + if( no_plan ) { + text+=" <span class=\"warning\">no plan</span>"; + } + style= total_fail==0 ? "ok" : "fail"; + detail.style.display= style=="fail" ? "block" : "none"; + detail.style.cursor="text"; + } + if( style!=null ) { + Test.AnotherWay._set_css_class( r, style ); + if( style=="ok" ) { + ++Test.AnotherWay._g_ok_pages; + }else if( style=="fail" || style=="badtest" ) { + ++Test.AnotherWay._g_fail_pages; + } + var pages_total=""; + if( Test.AnotherWay._g_fail_pages>0 ) { + pages_total+=" fail "+Test.AnotherWay._g_fail_pages; + } + pages_total+=" ok "+Test.AnotherWay._g_ok_pages; + Test.AnotherWay._update_results_total( pages_total ); + } + r.innerHTML=text; + if( results.scrollHeight!=null && results.scrollTop!=null && results.offsetHeight!=null ) { + results.scrollTop=results.scrollHeight-results.offsetHeight; + } + // when test_objects is not null, the results are final - good time to clean up + if( test_objects!=null ) { + for( var i=0; i<test_objects.length; ++i ) { + var actions=test_objects[i].delay_actions; + for( var action_i=0; action_i<actions.length; ++action_i ) { + var action=actions[action_i]; + if( action.action_kind=="window" && action.wnd_wnd!=null && !action.wnd_no_close ) { + action.wnd_wnd.close(); + action.wnd_wnd=null; + } + } + } + } + return r; +} +Test.AnotherWay._unprint_result=function( child ) +{ + var results=document.getElementById( "results" ); + results.removeChild( child ); +} +Test.AnotherWay._toggle_detail=function() +{ + if( this.id.match( /^result(\d+)$/ ) ) { + var detail=document.getElementById( "result_detail"+RegExp.$1 ); + if( detail!=null ) { + if( detail.style.display=="none" ) { + detail.style.display="block"; + }else if( detail.style.display=="block" ) { + detail.style.display="none"; + } + } + } +} +Test.AnotherWay._update_msg_counter=function( msg, text ) +{ + for( var i=0; i<msg.childNodes.length; ++i ) { + var item=msg.childNodes[i]; + if( item.nodeName=="SPAN" && Test.AnotherWay._get_css_class( item )=="counter" ) { + item.innerHTML=text; + } + } +} +Test.AnotherWay._update_results_total=function( msg ) +{ + var total=document.getElementById( "total" ); + if( total ) { + total.innerHTML=msg; + } +} +Test.AnotherWay._results_clear_onclick=function() +{ + var results=document.getElementById( "results" ); + results.innerHTML=""; + Test.AnotherWay._update_results_total( "" ); + Test.AnotherWay._g_ok_pages=0; + Test.AnotherWay._g_fail_pages=0; + var debug=document.getElementById( "debug" ); + debug.innerHTML=""; +} + +Test.AnotherWay._get_css_class=function( o ) +{ + var c=o.getAttribute( "className" ); + if( c==null || c=="" ) { + c=o.getAttribute( "class" ); + } + return c; +} +Test.AnotherWay._set_css_class=function( o, css_class ) +{ + o.setAttribute( "className", css_class ); + o.setAttribute( "class", css_class ); +} + +Test.AnotherWay._tab_onclick=function() +{ + var tab=this; + var tabs=[ document.getElementById( "debug_tab" ), document.getElementById( "results_tab" ) ]; + var panes=[ document.getElementById( "debug" ), document.getElementById( "results" ) ]; + for( var i=0; i<tabs.length; ++i ) { + if( tab==tabs[i] ) { + Test.AnotherWay._set_css_class( tabs[i], "active_tab" ); + panes[i].style.display="block"; + }else { + Test.AnotherWay._set_css_class( tabs[i], "inactive_tab" ); + panes[i].style.display="none"; + } + } +} +Test.AnotherWay._tab_mouseover=function() +{ + if( Test.AnotherWay._get_css_class( this )=="inactive_tab" ) { + Test.AnotherWay._set_css_class( this, "inactive_mouseover_tab" ); + } +} +Test.AnotherWay._tab_mouseout=function() +{ + if( Test.AnotherWay._get_css_class( this )=="inactive_mouseover_tab" ) { + Test.AnotherWay._set_css_class( this, "inactive_tab" ); + } +} + +// recording mouse input +Test.AnotherWay._record_check_onfocus=function() +{ + var o=this; + var check_select=o.type!="text"; + var div=document.getElementById( "record_div" ); + var inputs=div.getElementsByTagName( "input" ); + for( var i=0; i<inputs.length; ++i ) { + var input=inputs[i]; + if( input.type=="radio" ) { + if( input.value=="select" ) { + input.checked=check_select; + }else if( input.value=="input" ) { + input.checked=!check_select; + } + } + } +} + +Test.AnotherWay._g_no_record_msg=null; // not null - recording is unavailable +Test.AnotherWay._g_record_timeout_cnt=0; // opening window for a page for recording +Test.AnotherWay._g_record_url=null; +Test.AnotherWay._g_record_wnd=null; +Test.AnotherWay._g_record_random_id=null; // added to element ids of record_control div so that they do not clash with ids already in the page for which input is recorded +Test.AnotherWay._g_record_keydown=null; // recording control - which key is down +Test.AnotherWay._g_record_ctrl_keydown=false; +Test.AnotherWay._g_record_shift_keydown=false; +Test.AnotherWay._g_record_control_visible=true; // recording control ui state +Test.AnotherWay._g_record_started; +Test.AnotherWay._g_record_paused; +Test.AnotherWay._g_record_include_mousemove=false; +Test.AnotherWay._g_record_start_time; // for time references +Test.AnotherWay._g_record_pause_start_time; +Test.AnotherWay._g_record_update_time_interval; // showing time in the control ui +Test.AnotherWay._g_record_waiting_for_results=false; // waiting for results window to open +Test.AnotherWay._g_record_events; // recorded events +Test.AnotherWay._g_record_under_cursor; // track element under cursor +Test.AnotherWay._g_record_checkpoint_count; // for checkpoint numbering +Test.AnotherWay._g_record_mouse_over_record_control; // for avoiding record control highlight on mouseover +Test.AnotherWay._g_record_highlighted_element={ element: null, x: null, y: null }; + +Test.AnotherWay._record_control_get_element=function( id ) +{ + if( Test.AnotherWay._g_record_wnd!=null && Test.AnotherWay._g_record_wnd.document!=null ) { + return Test.AnotherWay._g_record_wnd.document.getElementById( id+Test.AnotherWay._g_record_random_id ); + }else { + return null; + } +} +Test.AnotherWay._record_start_onclick=function() // "record" button on the run_tests.html: open a window for a page for which input is recorded +{ + if( Test.AnotherWay._g_no_record_msg!=null ) { + alert( Test.AnotherWay._g_no_record_msg ); + return; + } + if( Test.AnotherWay._g_record_timeout_cnt>0 + || (Test.AnotherWay._g_record_wnd!=null && (Test.AnotherWay._g_record_wnd.closed!=null && !Test.AnotherWay._g_record_wnd.closed)) ) { // in opera, closed is null. + alert( "there is already window opened for recording input for a page "+Test.AnotherWay._g_record_url ); + return; + } + var div=document.getElementById( "record_div" ); + var inputs=div.getElementsByTagName( "input" ); + var url=null; + for( var i=0; i<inputs.length; ++i ) { + var input=inputs[i]; + if( input.type=="radio" ) { + if( input.value=="select" && input.checked ) { + var index=document.getElementById( "record_select" ).selectedIndex; + if( index>0 ) { + url=Test.AnotherWay._g_test_page_urls[index-1].url; + } + }else if( input.value=="input" && input.checked ) { + url=document.getElementById( "record_input" ).value; + } + } + } + if( url!=null ) { + Test.AnotherWay._g_record_url=url; + Test.AnotherWay._g_record_wnd=window.open( url, "_blank" ); + if( Test.AnotherWay._g_record_wnd==null ) { + alert( "unable to open new window for a page: "+url ); + }else { + Test.AnotherWay._g_record_timeout_cnt=50; + setTimeout( Test.AnotherWay._record_window_timeout, 100 ); + } + } +} +Test.AnotherWay._record_window_timeout=function() +{ + if( Test.AnotherWay._is_url_loaded( Test.AnotherWay._g_record_url, Test.AnotherWay._g_record_wnd ) ) { + Test.AnotherWay._record_window_setup( Test.AnotherWay._g_record_wnd ); + }else { + if( --Test.AnotherWay._g_record_timeout_cnt>0 ) { + setTimeout( Test.AnotherWay._record_window_timeout, 100 ); + }else { + alert( "timeout expired while opening new window for a page: "+Test.AnotherWay._g_record_url ); + Test.AnotherWay._g_record_wnd=null; + Test.AnotherWay._g_record_url=null; + Test.AnotherWay._g_record_timeout_cnt=0; + } + } +} +Test.AnotherWay._record_control_randomize_id=function( e, r ) +{ + if( e.id!="" ) { + e.id=e.id+r; + } + for( var c=e.firstChild; c!=null; c=c.nextSibling ) { + Test.AnotherWay._record_control_randomize_id( c, r ); + } +} +Test.AnotherWay._record_window_setup=function( wnd ) // insert recording control into the page for which input is recorded +{ + Test.AnotherWay._g_record_timeout_cnt=0; + var this_div=document.getElementById( "record_control" ); + var record_control=wnd.document.importNode( this_div, true ); + Test.AnotherWay._g_record_random_id=(1000*Math.random()).toFixed(); + Test.AnotherWay._record_control_randomize_id( record_control, Test.AnotherWay._g_record_random_id ); + Test.AnotherWay._g_record_control_visible=true; + Test.AnotherWay._g_record_started=false; + Test.AnotherWay._g_record_paused=false; + Test.AnotherWay._g_record_checkpoint_count=0; + Test.AnotherWay._g_record_mouse_over_record_control=false; + var doc=wnd.document; + doc.body.appendChild( record_control ); + // opera sans-serif font is different + if( window.opera ) { + cursor_over_indicator=Test.AnotherWay._record_control_get_element( "record_cursor_over" ); + cursor_over_indicator.style.width="18em"; + cursor_over_indicator.style.height="2em"; + cursor_over_indicator.style.fontSize="7pt"; + } + doc.addEventListener( "keydown", Test.AnotherWay._record_control_keydown, true ); + doc.addEventListener( "keyup", Test.AnotherWay._record_control_keyup, true ); +// doc.addEventListener( "keypress", Test.AnotherWay._record_event, true ); // replaying is not supported by any known browser + + doc.body.addEventListener( "mousemove", Test.AnotherWay._record_on_mousemove, true ); + doc.body.addEventListener( "click", Test.AnotherWay._record_event, true ); + doc.body.addEventListener( "mouseover", Test.AnotherWay._record_event, true ); + doc.body.addEventListener( "mouseout", Test.AnotherWay._record_event, true ); + doc.body.addEventListener( "mousedown", Test.AnotherWay._record_event, true ); + doc.body.addEventListener( "mouseup", Test.AnotherWay._record_event, true ); +} +Test.AnotherWay._record_control_key_disabled=function( k ) +{ + if( k=="c" ) { + return !Test.AnotherWay._g_record_started; + }else if( k=="p" ) { + return !Test.AnotherWay._g_record_started; + }else if( k=="s" ) { + return Test.AnotherWay._g_record_waiting_for_results; + }else { + return false; + } +} + +Test.AnotherWay._record_control_update_ui=function() +{ + var keydown_color="#fff"; + var disabled_color="#aaa"; + var button_color="#adf"; + var active_color="#fdf"; + + var display={}; + display[false]="none"; + display[true]="inline"; + + var s_button=Test.AnotherWay._record_control_get_element( "record_s" ); + var record_on=Test.AnotherWay._record_control_get_element( "record_on" ); + var record_off=Test.AnotherWay._record_control_get_element( "record_off" ); + + s_button.style.backgroundColor= Test.AnotherWay._record_control_key_disabled( "s" ) ? disabled_color + : Test.AnotherWay._g_record_keydown=="s" ? keydown_color : Test.AnotherWay._g_record_started ? active_color : button_color; + record_on.style.display=display[!Test.AnotherWay._g_record_started]; + record_off.style.display=display[Test.AnotherWay._g_record_started]; + + var h_button=Test.AnotherWay._record_control_get_element( "record_h" ); + h_button.style.backgroundColor= Test.AnotherWay._g_record_keydown=="h" ? keydown_color : button_color; + + var p_button=Test.AnotherWay._record_control_get_element( "record_p" ); + var record_pause_on=Test.AnotherWay._record_control_get_element( "record_pause_on" ); + var record_pause_off=Test.AnotherWay._record_control_get_element( "record_pause_off" ); + p_button.style.backgroundColor= Test.AnotherWay._record_control_key_disabled( "p" ) ? disabled_color + : Test.AnotherWay._g_record_keydown=="p" ? keydown_color : Test.AnotherWay._g_record_paused ? active_color : button_color; + record_pause_on.style.display=display[!Test.AnotherWay._g_record_paused]; + record_pause_off.style.display=display[Test.AnotherWay._g_record_paused]; + + var m_button=Test.AnotherWay._record_control_get_element( "record_m" ); + var record_include_mousemove=Test.AnotherWay._record_control_get_element( "record_include_mousemove" ); + var record_omit_mousemove=Test.AnotherWay._record_control_get_element( "record_omit_mousemove" ); + m_button.style.backgroundColor= Test.AnotherWay._g_record_keydown=="m" ? keydown_color : Test.AnotherWay._g_record_include_mousemove ? active_color : button_color; + record_include_mousemove.style.display=display[!Test.AnotherWay._g_record_include_mousemove]; + record_omit_mousemove.style.display=display[Test.AnotherWay._g_record_include_mousemove]; + + var c_button=Test.AnotherWay._record_control_get_element( "record_c" ); + c_button.style.backgroundColor= Test.AnotherWay._record_control_key_disabled( "c" ) ? disabled_color + : Test.AnotherWay._g_record_keydown=="c" ? keydown_color : button_color; + + var record_indicator=Test.AnotherWay._record_control_get_element( "record_indicator" ); + record_indicator.style.display=display[Test.AnotherWay._g_record_started]; + + var pause_indicator=Test.AnotherWay._record_control_get_element( "record_pause_indicator" ); + pause_indicator.style.display=display[Test.AnotherWay._g_record_paused]; + + var record_control=Test.AnotherWay._record_control_get_element( "record_control" ); + record_control.style.display= Test.AnotherWay._g_record_control_visible ? "block" : "none"; + + var shift_button=Test.AnotherWay._record_control_get_element( "record_shift_key" ); + shift_button.style.backgroundColor= Test.AnotherWay._g_record_shift_keydown ? keydown_color : button_color; + + var ctrl_button=Test.AnotherWay._record_control_get_element( "record_ctrl_key" ); + ctrl_button.style.backgroundColor= Test.AnotherWay._g_record_ctrl_keydown ? keydown_color : button_color; +} +Test.AnotherWay._record_format_time=function( t ) +{ + t=new Date( t ); + var m=t.getMinutes(); + var s=t.getSeconds(); + var str= m==0 ? "" : m+"m "; + str+=s+"s."; + return str; +} +Test.AnotherWay._record_control_update_time=function() +{ + var time_display=Test.AnotherWay._record_control_get_element( "record_time" ); + if( time_display!=null ) { + time_display.innerHTML=Test.AnotherWay._record_format_time( (new Date()).getTime()-Test.AnotherWay._g_record_start_time ); + } +} +Test.AnotherWay._record_control_update_highlight=function( elem, style, event ) +{ + if( elem==null ) { + Test.AnotherWay._record_highlight_border( null ); + }else { + var pos=Test.AnotherWay._get_page_coords( elem ); + if( style=="ball" || elem!=Test.AnotherWay._g_record_highlighted_element.element || pos.x!=Test.AnotherWay._g_record_highlighted_element.x || pos.y!=Test.AnotherWay._g_record_highlighted_element.y ) { + Test.AnotherWay._g_record_highlighted_element={ element: elem, x: pos.x, y: pos.y }; + Test.AnotherWay._record_highlight_border( elem, style, event ); + } + } +} +Test.AnotherWay._record_decode_key=function( event ) +{ + var k=null; + if( event==null ) { + k=Test.AnotherWay._g_record_wnd.event.keyCode; + }else { + k=event.which; + } + if( k==83 ) { + return "s"; + }else if( k==72 ) { + return "h"; + }else if( k==73 ) { + return "i"; + }else if( k==80 ) { + return "p"; + }else if( k==67 ) { + return "c"; + }else if( k==77 ) { + return "m"; + }else if( k==16 ) { + return "shift"; + }else if( k==17 ) { + return "ctrl"; + }else if( k==18 ) { + return "alt"; + }else if( k==19 ) { + return "pause"; + }else if( k==123 ) { + return "f12"; + } + return ""; +} +Test.AnotherWay._record_control_keydown=function( event ) +{ + var handled=false; + var k=Test.AnotherWay._record_decode_key( event ); + if( k=="shift" ) { + Test.AnotherWay._g_record_shift_keydown=true; + }else if( k=="ctrl" ) { + Test.AnotherWay._g_record_ctrl_keydown=true; + }else if( k!="" && (Test.AnotherWay._g_record_keydown==null || Test.AnotherWay._g_record_keydown==k) ) { + if( Test.AnotherWay._g_record_ctrl_keydown && Test.AnotherWay._g_record_shift_keydown && !Test.AnotherWay._record_control_key_disabled( k ) ) { + Test.AnotherWay._g_record_keydown=k; + handled=true; + } + }else { + Test.AnotherWay._g_record_keydown=""; + } + Test.AnotherWay._record_control_update_ui(); + if( !handled ) { +// Test.AnotherWay._record_event( event ); // replaying is not supported in any known browser + } + return; +} +Test.AnotherWay._record_control_keyup=function( event ) +{ + var handled=false; + var k=Test.AnotherWay._record_decode_key( event ); + if( k=="shift" ) { + Test.AnotherWay._g_record_shift_keydown=false; + }else if( k=="ctrl" ) { + Test.AnotherWay._g_record_ctrl_keydown=false; + }else if( k!="" && k==Test.AnotherWay._g_record_keydown && Test.AnotherWay._g_record_ctrl_keydown && Test.AnotherWay._g_record_shift_keydown ) { + if( k=="s" ) { + Test.AnotherWay._g_record_started=!Test.AnotherWay._g_record_started; + if( Test.AnotherWay._g_record_started ) { + Test.AnotherWay._g_record_events=[]; + Test.AnotherWay._g_record_start_time=(new Date()).getTime(); + Test.AnotherWay._record_control_update_time(); + Test.AnotherWay._g_record_update_time_interval=window.setInterval( Test.AnotherWay._record_control_update_time, 200 ); + }else { + Test.AnotherWay._record_control_update_highlight( null ); + if( !Test.AnotherWay._g_record_paused ) { + window.clearInterval( Test.AnotherWay._g_record_update_time_interval ); + } + Test.AnotherWay._g_record_waiting_for_results=true; + // open a new window for self, pass a parameter to dump recorded events as javascript code there + // (the easiest way to obtain a document from the same origin, so it's writable, is to open this same page again) + Test.AnotherWay._g_record_paused=false; + var loc=window.location; + loc=loc.protocol+"//"+loc.host+loc.pathname+"?recording_results="+Test.AnotherWay._g_record_random_id; + if( window.open( loc, "_blank" )==null ) { + alert( "unable to open new window for results" ); + } + } + handled=true; + }else if( k=="h" ) { + Test.AnotherWay._g_record_control_visible=!Test.AnotherWay._g_record_control_visible; + handled=true; + }else if( k=="p" ) { + Test.AnotherWay._g_record_paused=!Test.AnotherWay._g_record_paused; + if( Test.AnotherWay._g_record_paused ) { + Test.AnotherWay._g_record_pause_start_time=(new Date()).getTime(); + if( Test.AnotherWay._g_record_started ) { + window.clearInterval( Test.AnotherWay._g_record_update_time_interval ); + } + Test.AnotherWay._record_control_update_highlight( null ); + }else { + var pause_duration=(new Date()).getTime()-Test.AnotherWay._g_record_pause_start_time; + Test.AnotherWay._g_record_start_time+=pause_duration; + Test.AnotherWay._g_record_update_time_interval=window.setInterval( Test.AnotherWay._record_control_update_time, 200 ); + } + handled=true; + }else if( k=="m" ) { + Test.AnotherWay._g_record_include_mousemove=!Test.AnotherWay._g_record_include_mousemove; + handled=true; + }else if( k=="c" ) { + var o=Test.AnotherWay._record_checkpoint(); + Test.AnotherWay._record_display_checkpoint( o ); + Test.AnotherWay._record_flash_border( "#24d" ); + handled=true; + } + } + Test.AnotherWay._g_record_keydown=null; + Test.AnotherWay._record_control_update_ui(); + if( !handled ) { +// Test.AnotherWay._record_event( event ); // replaying is not supported in any known browser + } + return; +} +Test.AnotherWay._record_html_node_path=function( node ) +{ + if( node==null ) { + return null; + } + var path=[]; + while( true ) { + if( node.id!=null && node.id!="" ) { + path.unshift( "#"+node.id+" "+node.nodeName ); + break; + }else { + var parent_node=node.parentNode; + if( parent_node==null ) { + return []; // no BODY up the path - this node is screwed (browsers differ in what's above the body), discard + }else { + var i=0; + var found=false; + for( var child=parent_node.firstChild; child!=null; child=child.nextSibling ) { + if( child==node ) { + found=true; + break; + } + if( child.nodeType==1 ) { // count only HTML element nodes + ++i; + } + } + if( !found ) { + i=-1; + } + path.unshift( i+" "+node.nodeName ); + if( parent_node.nodeName=="BODY" || parent_node.nodeName=="body" ) { + break; + } + node=parent_node; + } + } + } + return path; +} +Test.AnotherWay._record_node_path_to_string=function( path ) +{ + var s=""; + if( path!=null ) { + for( var i=0; i<path.length; ++i ) { + s+= i==0 ? "" : ", "; + var elem=path[i].split( " " ); + if( elem[0].charAt( 0 )=="#" ) { + s+=elem[1]+" "+elem[0]; + }else { + s+=elem[1]+" ["+elem[0]+"]"; + } + } + } + return s; +} +Test.AnotherWay._record_node_path_to_node=function( path_str, doc ) +{ + if( path_str==null ) { + return null; + } + var path=path_str.split( "," ); + var node=doc.body; + for( var i=0; i<path.length; ++i ) { + var node_i=path[i].split( " " )[0]; + if( node_i.charAt( 0 )=="#" ) { + node=doc.getElementById( node_i.substring( 1 ) ); + }else { + if( node_i<0 || node_i>=node.childNodes.length ) { + node=null; + }else { + node=node.firstChild; + while( node!=null ) { + if( node.nodeType==1 ) { // count only HTML element nodes + if( node_i==0 ) { + break; + } + --node_i; + } + node=node.nextSibling; + } + } + } + if( node==null ) { + return null; + } + } + return node; +} +Test.AnotherWay._record_control_contains_id=function( s ) +{ + return s.match( /^#record_[\w_]+/ ) && s.match( Test.AnotherWay._g_record_random_id ); +} +Test.AnotherWay._record_checkpoint=function() +{ + var o={ type: "_checkpoint", time: (new Date()).getTime()-Test.AnotherWay._g_record_start_time, which: Test.AnotherWay._g_record_checkpoint_count++, + target: Test.AnotherWay._record_html_node_path( Test.AnotherWay._g_record_under_cursor ) }; + Test.AnotherWay._g_record_events.push( o ); + return o; +} +Test.AnotherWay._record_event=function( event ) +{ + var unneeded=["rangeOffset","eventPhase","timeStamp","isTrusted","popupWindowFeatures","rangeOffset"]; + if( Test.AnotherWay._g_record_started && !Test.AnotherWay._g_record_paused ) { + var o={}; + for( var n in event ) { + var needed=!n.match( /^[A-Z0-9_]+$/ ); + if( needed ) { + for( var ui=0; ui<unneeded.length; ++ui ) { + if( unneeded[ui]==n ) { + needed=false; + break; + } + } + if( needed ) { + var value=event[n]; + if( typeof( value )!="object" && typeof( value )!="function" ) { + o[n]=value; + }else if( n=="target" || n=="relatedTarget" ) { + o[n]=Test.AnotherWay._record_html_node_path( value ); + } + } + } + } + o["time"]=(new Date()).getTime()-Test.AnotherWay._g_record_start_time; + var over_record_control= o["target"]!=null && o["target"][0]!=null && Test.AnotherWay._record_control_contains_id( o["target"][0] ); + if( !over_record_control ) { + Test.AnotherWay._g_record_events.push( o ); + } + } + return true; +} +Test.AnotherWay._record_on_mousemove=function( event ) +{ + var path=Test.AnotherWay._record_html_node_path( event.target ); + var new_mouse_over_record_control= path!=null && path[0]!=null && Test.AnotherWay._record_control_contains_id( path[0] ); + if( new_mouse_over_record_control!=Test.AnotherWay._g_record_mouse_over_record_control ) { + Test.AnotherWay._g_record_mouse_over_record_control=new_mouse_over_record_control; + Test.AnotherWay._record_control_update_ui(); + } + if( event.target!=null && event.target!=Test.AnotherWay._g_record_under_cursor ) { + Test.AnotherWay._g_record_under_cursor=event.target; + var s=""; + if( path==null || path[0]==null || !Test.AnotherWay._record_control_contains_id( path[0] ) ) { + s=Test.AnotherWay._record_node_path_to_string( path ); + } + if( s=="" ) { + s=" "; + } + var cursor_over_indicator=Test.AnotherWay._record_control_get_element( "record_cursor_over" ); + cursor_over_indicator.innerHTML=s; + } + + var highlight_element=null; + if( !Test.AnotherWay._g_record_mouse_over_record_control && Test.AnotherWay._g_record_started && !Test.AnotherWay._g_record_paused ) { + highlight_element=event.target; + } + // highlight border disabled on recording - it causes page to scroll, issuing spurious mouseover/mouseout event + //Test.AnotherWay._record_control_update_highlight( highlight_element, "border" ); + + if( Test.AnotherWay._g_record_include_mousemove ) { + Test.AnotherWay._record_event( event ); + } + return true; +} +Test.AnotherWay._record_display_checkpoint=function( o ) +{ + var checkpoints_div=Test.AnotherWay._record_control_get_element( "record_checkpoints" ); + var p=checkpoints_div.appendChild( checkpoints_div.ownerDocument.createElement( "div" ) ); + p.style.marginTop="3px"; + p.style.font="normal normal 8pt sans-serif"; + p.style.color="#000"; + p.style.textAligh="left"; + p.style.position="relative"; + p.style.width="100%"; + var checkpoint_text=""; + checkpoint_text+="#"+(o.which+1); + checkpoint_text+=" "+Test.AnotherWay._record_format_time( o.time ); + if( o.target!=null ) { + checkpoint_text+=Test.AnotherWay._record_node_path_to_string( o.target ); + } + p.appendChild( p.ownerDocument.createTextNode( checkpoint_text ) ); +} +Test.AnotherWay._record_save_results=function( doc ) +{ + // strange, but DOM-style append does not work here in opera 8. + var append=function( s ) { doc.write( "<div>"+s+"</div>" ); }; + append( "/* paste this data into your javascript and pass it as an argument to replay_events method */" ); + append( "{ checkpoints: [" ); + var first_checkpoint=true; + for( var i=0; i<Test.AnotherWay._g_record_events.length; ++i ) { + var o=Test.AnotherWay._g_record_events[i]; + if( o.type=="_checkpoint" ) { + var str= first_checkpoint ? "" : "}, "; + str+="function( tst, wnd ) { // #"+o.which+" time "+Test.AnotherWay._record_format_time( o.time )+" cursor was over "+Test.AnotherWay._record_node_path_to_string( o.target ); + append( str ); + first_checkpoint=false; + } + } + if( !first_checkpoint ) { + append( "}" ); + } + append( "], events: [ " ); + var prev_time=0; + for( var i=0; i<Test.AnotherWay._g_record_events.length; ++i ) { + var o=Test.AnotherWay._g_record_events[i]; + var s=""; + s+= "{"; + var n_first=true; + for( var n in o ) { + if( n=="time" ) { // convert to relative time + var cur_time=o[n]-0; + o[n]=cur_time-prev_time; + prev_time=cur_time; + } + s+=n_first ? n : ", "+n; + s+=":"; + if( o[n]==null ) { + s+="null"; + }else { + s+="\""+o[n]+"\""; + } + n_first=false; + } + s+= i==Test.AnotherWay._g_record_events.length-1 ? "}" : "},"; + append( s ); + } + append( "] }" ); + append( ";" ); +} + +Test.AnotherWay._g_record_border; // border highlighting element under cursor +Test.AnotherWay._g_record_border_flashes=[]; // array of { color: color, timeout: milliseconds } +Test.AnotherWay._g_record_border_flashing=false; +Test.AnotherWay._g_record_border_normal_color="#d4b"; +Test.AnotherWay._record_flash_border_timeout=function() +{ + var color=Test.AnotherWay._g_record_border_normal_color; + var timeout=null; + if( Test.AnotherWay._g_record_border_flashes.length!=0 ) { + color=Test.AnotherWay._g_record_border_flashes[0].color; + timeout=Test.AnotherWay._g_record_border_flashes[0].timeout; + Test.AnotherWay._g_record_border_flashes.splice( 0, 1 ); + } + if( Test.AnotherWay._g_record_border!=null ) { + for( var i=0; i<Test.AnotherWay._g_record_border.length; ++i ) { + Test.AnotherWay._g_record_border[i].style.backgroundColor=color; + } + } + if( timeout!=null ) { + setTimeout( Test.AnotherWay._record_flash_border_timeout, timeout ); + }else { + Test.AnotherWay._g_record_border_flashing=false; + } +} +Test.AnotherWay._get_page_coords=function( elm ) +{ + var point = { x: 0, y: 0 }; + while( elm ) { + point.x+=elm.offsetLeft; + point.y+=elm.offsetTop; + elm=elm.offsetParent; + } + return point; +} +Test.AnotherWay._set_page_coords=function( elm, x, y ) +{ + var parent_coords={ x: 0, y: 0 }; + if( elm.offsetParent ) { + parent_coords=Test.AnotherWay._get_page_coords( elm.offsetParent ); + } + var new_x=x-parent_coords.x; + if( new_x<0 ) { + new_x=0; + } + elm.style.left=new_x+'px'; + var new_y=y-parent_coords.y; + if( new_y<0 ) { + new_y=0; + } + elm.style.top=new_y+'px'; +} +Test.AnotherWay._record_setup_highlight_positions=function( element, style, coords, positions ) +{ + if( style=="border" ) { + var width=element.clientWidth; + var height=element.clientHeight; + var step=0; + var thickness=2; + var fudge_expand=4; + positions.push( { x: coords.x-step-thickness, y: coords.y-step-thickness, width: width+2*step+2*thickness+fudge_expand, height: thickness } ); + positions.push( { x: coords.x+width+step+fudge_expand, y: coords.y-step-thickness, width: thickness, height: height+2*step+2*thickness+fudge_expand } ); + positions.push( { x:positions[0].x, y:positions[0].y, width:positions[0].width, height:positions[0].height } ); + positions.push( { x:positions[1].x, y:positions[1].y, width:positions[1].width, height:positions[1].height } ); + positions[2].y+=height+thickness+2*step+fudge_expand; + positions[3].x-=width+thickness+2*step+fudge_expand; + }else if( style=="ball" ) { + positions.push( { x: coords.x+2, y: coords.y, width: 2, height: 6 } ); + positions.push( { x: coords.x, y: coords.y+2, width: 6, height: 2 } ); + positions.push( { x: coords.x+1, y: coords.y+1, width: 4, height: 4 } ); + } +} +Test.AnotherWay._record_highlight_border=function( element, style, event ) // null - hide border +{ + if( element!=null ) { + if( Test.AnotherWay._g_record_border==null || Test.AnotherWay._g_record_border[0].ownerDocument!=element.ownerDocument ) { + Test.AnotherWay._g_record_border=[]; + var n= style=="border" ? 4 : style=="ball" ? 3 : 0; + for( var i=0; i<4; ++i ) { + var b=element.ownerDocument.createElement( "div" ); + b.style.position="absolute"; + b.style.zIndex="1"; + b.style.backgroundColor=Test.AnotherWay._g_record_border_normal_color; + element.ownerDocument.body.appendChild( b ); + Test.AnotherWay._g_record_border.push( b ); + } + } + var coords=null; + if( style=="border" ) { + coords=Test.AnotherWay._get_page_coords( element ); + }else if( style=="ball" ) { + if( event!=null ) { + if( event.pageX!=null && event.pageY!=null ) { + coords={ x: event.pageX-0, y: event.pageY-0 }; + }else if( event.clientX!=null && event.clientY!=null ) { + var doc=element.ownerDocument; + if( doc!=null ) { + coords={ x: (event.clientX-0)+doc.body.scrollLeft, y: (event.clientY-0)+doc.body.scrollTop }; + } + } + } + } + if( coords!=null && element.clientWidth!=null && element.clientHeight!=null ) { + var positions=[]; + Test.AnotherWay._record_setup_highlight_positions( element, style, coords, positions ); + for( var i=0; i<positions.length; ++i ) { + var b=Test.AnotherWay._g_record_border[i]; + var p=positions[i]; + Test.AnotherWay._set_page_coords( b, p.x, p.y ); + b.style.width=p.width+"px"; + b.style.height=p.height+"px"; + b.style.display="block"; + } + } + }else { + if( Test.AnotherWay._g_record_border!=null ) { + for( var i=0; i<Test.AnotherWay._g_record_border.length; ++i ) { + Test.AnotherWay._g_record_border[i].style.display="none"; + } + } + } +} +Test.AnotherWay._record_flash_border=function( color ) +{ + if( Test.AnotherWay._g_record_border_flashing ) { //already + Test.AnotherWay._g_record_border_flashes.push( { color: Test.AnotherWay._g_record_border_normal_color, timeout:300 } ); + Test.AnotherWay._g_record_border_flashes.push( { color: color, timeout:600 } ); + }else { + Test.AnotherWay._g_record_border_flashing=true; + Test.AnotherWay._g_record_border_flashes.push( { color: color, timeout:600 } ); + Test.AnotherWay._record_flash_border_timeout(); + } +} +Test.AnotherWay._record_prepare_doc_for_results=function() +{ + document.open(); + document.write( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">" ); + document.write( "<html><head><title> Input recording results</title>" ); + document.write( "<style type=\"text/css\">" ); + document.write( "body { font: normal normal smaller sans-serif; }" ); + document.write( "div { margin-top: 3px; }" ); + document.write( "</style></head><body>" ); + // opera and mozilla disagree over who the opener is. + if( typeof( window.opener.Test )!="undefined" && typeof( window.opener.Test.AnotherWay )!="undefined" ) { + window.opener.Test.AnotherWay._record_save_results( document ); + window.opener.Test.AnotherWay._g_record_waiting_for_results=false; + window.opener.Test.AnotherWay._record_control_update_ui(); + }else if( typeof( window.opener.opener.Test )!="undefined" && typeof( window.opener.opener.Test.AnotherWay )!="undefined" ) { + window.opener.opener.Test.AnotherWay._record_save_results( document ); + window.opener.opener.Test.AnotherWay._g_record_waiting_for_results=false; + window.opener.opener.Test.AnotherWay._record_control_update_ui(); + } + document.write( "</body>" ); + document.close(); +} + +// global initialization +onload=function() +{ + if( window.opera ) { + var good_opera=typeof( window.opera.version )=="function"; + good_opera=good_opera && window.opera.version().match( /^\s*(\d+)/ ); + good_opera=good_opera && RegExp.$1>=8; + } + var span=document.createElement( "SPAN" ); + span.innerHTML="<!--[if IE]><br /><![endif]-"+"->"; + var is_ie=span.getElementsByTagName( "BR" ).length>0; + + Test.AnotherWay._g_test_iframe=window.frames.test_iframe; + + var query_str=window.location.search; + if( query_str.charAt( 0 )=="?" ) { + query_str=query_str.substring( 1 ); + } + var testlist_page="list-tests.html"; + var auto_run=false; + if( query_str!="" ) { + var params=[query_str]; + if( query_str.indexOf( ";" )!=-1 ) { + params=query_str.split( ";" ); + }else if( query_str.indexOf( "&" )!=-1 ) { + params=query_str.split( "&" ); + } + for( var param_i=0; param_i<params.length; ++param_i ) { + var param=params[param_i].split( "=" ); + if( param[0]=="recording_results" ) { + if( window.opener!=null ) { + // we were told to show recording results - replace everything in the document with the results + Test.AnotherWay._record_prepare_doc_for_results(); + return; + } + }else if( param[0]=="testpage" ) { + Test.AnotherWay._add_test_page_url( decodeURIComponent( param[1] ), "anotherway" ); + }else if( param[0]=="jsantestpage" ) { + Test.AnotherWay._add_test_page_url( decodeURIComponent( param[1] ), "jsan" ); + }else if( param[0]=="testlist" ) { + testlist_page=decodeURIComponent( param[1] ); + }else if( param[0]=="testframe" ) { + if( window.opera && !good_opera ) { + Test.AnotherWay._show_error( "testframe parameter does not work in versions of Opera prior to 8.0. Sorry (pathches are welcome)." ); + // Opera 7 barfs on attempt to access frame.frameElement. + // if someone knows a way to assign onload handler to that iframe in Opera 7 + // without disrupting code that works in other browsers, patches are welcome. + }else { + var frame_path=param[1].split( "." ); + var frame=top; + for( var frame_path_i=0; frame_path_i<frame_path.length; ++frame_path_i ) { + frame=frame[frame_path[frame_path_i]]; + } + if( frame==null ) { + Test.AnotherWay._show_error( "unable to find frame specified for loading test pages: "+param[1] ); + }else { + if( frame.frameElement!=null ) { // for the following assignement to onload to work, frameElement is required + frame=frame.frameElement; + } + Test.AnotherWay._g_test_iframe=frame; + } + } + }else if( param[0]=="testframe_no_clear" ) { + Test.AnotherWay._g_test_frame_no_clear=true; + }else if( param[0]=="windows" ) { + if (param[1] == "none") { + } + }else if( param[0]=="run" ) { + auto_run=true; + if( param[1]=="all" ) { + Test.AnotherWay._g_pages_to_run="all"; + }else { + if( Test.AnotherWay._g_pages_to_run==null || Test.AnotherWay._g_pages_to_run=="all" ) { + Test.AnotherWay._g_pages_to_run=[]; + } + var pages=param[1].split( "," ); + for( var i=0; i<pages.length; ++i ) { + Test.AnotherWay._g_pages_to_run.push( pages[i] ); + } + } + } + } + } + if( Test.AnotherWay._g_test_page_urls.length==0 ) { // if no individual pages were given on the command line, load the list + var result=Test.AnotherWay._set_iframe_location( window.frames["list_iframe"], testlist_page ); + if( result.msg!=null ) { + Test.AnotherWay._show_error( result.msg ); + } + Test.AnotherWay._g_run_on_list_load=auto_run; + }else { + Test.AnotherWay._g_run_on_main_load=auto_run; + } + + var f=Test.AnotherWay._g_test_iframe; + try { + if( f.attachEvent!=null ) { + f.attachEvent( "onload", Test.AnotherWay._test_page_onload ); + }else { + f.onload=Test.AnotherWay._test_page_onload; + } + if( Test.AnotherWay._g_test_iframe.nodeType!=null && Test.AnotherWay._g_test_iframe.contentWindow!=null ) { // it's iframe element, not the iframe. we need iframe. + Test.AnotherWay._g_test_iframe=Test.AnotherWay._g_test_iframe.contentWindow; + } + }catch(e) { + // ignore stupid opera error if the frame has onload handler assigned in the inline html + } + var handlers={ + "run_all": { "onclick": Test.AnotherWay._run_all_onclick }, + "run_selected": { "onclick": Test.AnotherWay._run_selected_onclick }, + "unselect_all": { "onclick": Test.AnotherWay._unselect_all_onclick }, + "record_select": { "onfocus": Test.AnotherWay._record_check_onfocus }, + "record_input": { "onfocus": Test.AnotherWay._record_check_onfocus }, + "record_start": { "onclick": Test.AnotherWay._record_start_onclick }, + "clear_btn": { "onclick": Test.AnotherWay._results_clear_onclick }, + "results_tab": { "onclick": Test.AnotherWay._tab_onclick, "onmouseover": Test.AnotherWay._tab_mouseover, "onmouseout": Test.AnotherWay._tab_mouseout }, + "debug_tab": { "onclick": Test.AnotherWay._tab_onclick, "onmouseover": Test.AnotherWay._tab_mouseover, "onmouseout": Test.AnotherWay._tab_mouseout } + }; + for( var hs in handlers ) { + var o=document.getElementById( hs ); + if( o!=null ) { + for( var h in handlers[hs] ) { + o[h]=handlers[hs][h]; + } + }else { + Test.AnotherWay._show_error( "unable to set "+h+" handler: id "+hs+" not found" ); + } + } + + if( window.opera && !good_opera ) { + Test.AnotherWay._g_no_record_msg="Input events recording and replaying is not available in opera versions prior to 8.0."; + } + if( is_ie ) { + Test.AnotherWay._g_no_record_msg="Input events recording and replaying is not available in internet explorer."; + } + if( Test.AnotherWay._g_no_record_msg!=null ) { + var no_record_p=document.getElementById( "record_not_supported" ); + no_record_p.style.display="block"; + no_record_p.appendChild( document.createTextNode( Test.AnotherWay._g_no_record_msg ) ); + } + + Test.AnotherWay._g_main_loaded=true; + if( Test.AnotherWay._g_run_on_main_load ) { + Test.AnotherWay._g_run_on_main_load=false; + Test.AnotherWay._run_pages_to_run(); + } +} +Test.AnotherWay._test_object_t.prototype.open_window=null; +// --> +</script> +<script type="text/javascript" src="xml_eq.js"></script> +<script type="text/javascript" src="geom_eq.js"></script> +</head><body> + +<div id="col1"> +<div id="col1_header">Test pages:</div> +<div id="scroller"> +<table id="testtable"> +</table> +</div> +<div id="run_buttons"> +<input type="button" value=" clear " id="clear_btn" /> +<input type="button" value=" run all " id="run_all" /> +<input type="button" value=" run selected " id="run_selected" /> +<input type="button" value=" unselect all " id="unselect_all" /> +</div> +<input type="checkbox" id="dont_close_test_windows" /> do not close windows opened by tests +<div id="error"></div> +<div id="record_div"> +<p id="record_not_supported" style="display:none"></p> +<p>Record mouse input for the page:</p> +<p><input type="radio" name="record_choose" value="select" checked="checked" /> <select id="record_select"><option selected="selected">-- select a page: --</option></select></p> +<p><input type="radio" name="record_choose" value="input" /> or enter page url: <input type="text" id="record_input" /></p> +<p><input type="button" value=" record " id="record_start" /></p> +</div> +</div> + +<div id="col2"> +<div id="right_header"> +<span id="results_count">Results: <span id="total"></span></span> +<span id="results_tab" class="active_tab" style="visibility:hidden">Results</span> +<span id="debug_tab" class="inactive_tab" style="visibility:hidden">Debug</span> +</div> +<div id="right_frame"> +<div id="results"></div> +<div id="debug"></div> +</div> +</div> + +<span style="display:none"> +<iframe name="list_iframe" onload="Test.AnotherWay._list_iframe_onload();"></iframe> +<iframe name="test_iframe" onload="Test.AnotherWay._test_page_onload();"></iframe> + +<!-- record_control div is to be imported into other documents, so all its styles are inline --> +-<div id="record_control" style="position:absolute;bottom:0;left:0;margin:0;padding:0.5em;width:22em;height:22em;border:1px solid;background:#ffd;font: normal normal 8pt sans-serif; color:#000; text-align: left"> + +<p style="margin:0 0 0 0; padding:0"> + +<span style="display:none;font-weight:bold;color:#408" id="record_indicator"> +recording. <span style="font-weight:normal">time: <span id="record_time"></span></span><span id="record_pause_indicator"> paused</span> +</span> +</p> + +<div id="record_cursor_over" style="margin:0;padding:2px;width:14em;height:1.1em;overflow:hidden;float:right;border:1px solid #777;background:#fff;font: normal normal 8pt sans-serif;position:relative;top:3px;color:#000;text-align:left;"> </div> +<p style="margin:2px 0 0 0; padding:0"> +cursor is over +</p> + +<p style="margin:8px 0 0 0; padding:0;"> + keyboard control: press + <span id="record_ctrl_key" style="border:1px solid #226;background:#adf;padding:0 0.5em">ctrl</span> - + <span id="record_shift_key" style="border:1px solid #226;background:#adf;padding:0 0.5em">shift</span> - +</p> + +<p style="margin:4px 0 0 0; padding:0"> +<span id="record_s" style="border:1px solid #226;background:#adf;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">s</span> +<span id="record_on">to <b>start</b> recording</span> +<span id="record_off" style="display:none">to <b>stop</b> recording</span> +</p> + +<p style="margin:4px 0 0 0; padding:0"> +<span id="record_h" style="border:1px solid #226;background:#adf;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">h</span> +<span>to <b>hide/show</b> this window</span> +</p> + +<p style="margin:4px 0 0 0; padding:0"> +<span id="record_m" style="border:1px solid #226;background:#adf;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">m</span> +<span id="record_include_mousemove">to <b> record</b> mousemove</span> +<span id="record_omit_mousemove" style="display:none">to <b>omit</b> mousemove</span> +</p> + +<p style="margin:4px 0 0 0; padding:0"> +<span id="record_p" style="border:1px solid #226;background:#aaa;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">p</span> +<span id="record_pause_on">to <b> pause</b> recording</span> +<span id="record_pause_off" style="display:none">to <b>continue</b> recording</span> +</p> + +<p style="margin:4px 0 0 0; padding:0"> +<span id="record_c" style="border:1px solid #226;background:#aaa;width:1.2em;float:left;font-weight:bold;text-align:center;margin-right:0.5em">c</span> +<span>to add checkpoint</span> +</p> + +<p style="margin:6px 0 0 0; padding:0"> +checkpoints: +</p> +<div id="record_checkpoints" style="position:relative;width:100%;height:6em;overflow:auto;font: normal normal 8pt sans-serif; color:#000; text-align: left"> +</div> +</div> + +</span> +</body></html> |