Dokumentace
Transkript
České vysoké učení technické v Praze Fakulta elektrotechnická Semestrální práce z předmětu Návrh uživatelského rozhraní Remote Flash Usability testing Autor: Lukáš Skřivánek Email: [email protected] Datum: 28.5.2006 Remote Flash Usability testing Lukáš Skřivánek Zadání Navrhněte systém, který zaznamená interakci člověka (stisky kláves, pohyb kurzoru myši, klikání myši, dragování objektů, atd.) s flash animací. Tento systém poté umožní zpětné přehrání těchto interakcí. Vámi navržený systém by měl obsahovat tlačítka na pozastavení, zastavení a převinutí zaznamenaných akcí. Návrh řešení Celý systém lze rozdělit na dvě oddělitelné části – část určená pro záznam (recorder) a část určená pro pozdější přehrání zaznamenaných akcí (player). Recorder Recoder lze realizovat dvěma způsoby, buď jako flash animaci, která do sebe vloží zaznamenávanou flash animaci nebo jako samostatný soubor *.as obsahující pouze zdrojový text ActionScriptu, který se přilinkuje k testované flash animaci. Událostní model funguje tak, že existují odesílatelé událostí (dispatcher), ke kterým se mohou zaregistrovat posluchači (listener) obsahující funkce (metody) obsluhující danou událost. Odesílatele i posluchače událostí lze v ActionScriptu 2.0 vytvořit, nám však k záznamu událostí stačí vytvořit jen posluchače obsluhujícího události myši a klávesnice a zaregistrovat ho u globálního odesílatele událostí “Mouse”, v případě myši, a “Key”, v případě klávesnice. Tito odesílatelé přímo odrážejí reakce uživatele. V rozumných programovacích jazycích získá metoda posluchače jako parametr objekt reprezentující událost nesoucí veškeré informace o dané události. Potom stačí tento objekt serializovat a uložit pro pozdější načtení playerem. Bohužel v ActionScriptu 2.0 se tento parametr nepředává a je třeba informace o události získávat z globálních proměnných (např. _xmouse, _ymouse) nebo z globálního odesílatele událostí (např. Key.getAscii(), Key.getCode()), avšak po posbírání informací již nic nebrání uložení události. Player Úkolem playeru je načíst a deserializovat nebo jinak zrekonstruovat recorderem uložený objekt události a ve správný čas ho pomocí odesílatele, u kterého jsou zaregistrováni všichni posluchači přehrávané flash animace, předat těmto posluchačům. Na to flash animace zareaguje stejně jako by byla akce právě vyvolána uživatelem. Toto je jediné správné řešení problému. Bohužel v ActionScriptu 2.0 je znemožněno hned ze dvou důvodů. Prvním důvodem je výše zmíněné předávání objektu události posluchači jako parametru. Tím, že se informace o události musí číst z globálních proměnných je třeba je při vyslání naší události nastavit na příslušné hodnoty, avšak ne všechny lze změnit. Druhým vážnějším důvodem je nemožnost vyslání události pomocí globálních odesílatelů “Mouse” a “Key”, ke kterým jsou zaregistrováni všichni posluchači přehrávané flash animace. Věřím, že v některé z příštích verzí ActionScriptu již toto možné bude a že 1 Remote Flash Usability testing Lukáš Skřivánek samotné odeslání nastaví příslušné globální proměnné, čímž odpadne i prvně zmíněný problém, nebo dokonce začne používat předávání objektu události jako parametru posluchači. Paradoxem této situace je, že lze vytvořit jakýsi objekt události i vlastního odesílatele události, který již námi vytvořenou událost odeslat umí. Bohužel u našeho odesílatele nejsou zaregistrováni posluchači přehrávané flash animace. Ideální by tedy bylo, kdyby šlo přesměrovat registrace posluchačů z globálních odesílatelů “Key” a “Mouse” na našeho odesílatele a tím dokonce zastínit interakci uživatele v době přehrávání flash animace, což ovšem samožřejmě nejde. Další řešení již není zcela ideální, ale pokud by bylo možné získat z odesílatele veškeré posluchače, které jsou u něho zaregistrováni, bylo by možné volat obslužné funkce (metody) “ručně”. Ovšem ani toto odesílatelé událostí v ActionScriptu 2.0 neumožňují. Implementace Recorder Při implementaci recorderu jsme sáhli po variantě samostatného souboru obsahujícího zdrojový text ActionScriptu *.as, který se bude linkovat s flash animací, ve které chceme odchytávat interakce uživatele. Pro ukládání dat jsme zvolili cestu přes PHP skript, přestože současná verze produktu Macromedia Flash 8.0 umí ukládat do souboru pomocí JavaScriptu, protože chceme ukládat interakce do databáze MySQL. Pro komunikaci s PHP skriptem používáme XML verze 1.0. Na začátku pomocí PHP skriptu získáme z databáze číslo nového uživatele a toto číslo v databázi rezervujeme s událostí start, dále vytvoříme dva posluchače obsluhující události onKeyDown, onKeyUp, onMouseDown, onMouseUp a onMouseMove. V obsluze těchto událostí se tvoří XML soubor, který obsahuje číslo uživatele, url flash animace, čas události, číslo snímku, na kterém došlo k události, druh události a další informace o události. Čas události se měří od první interakce uživatele (první událost je v čase 0). Události jsou odesílány v průběhu záznamu po předem daném množství událostí. Záznam končí zavřením flash animace, ale v tuto chvíli je potřeba odeslat poslední zaznamenané události. O nedokonalosti událostního modelu v ActionScriptu 2.0 již bylo v tomto dokumentu řečeno mnohé a proto čtenáře jistě nepřekvapí, že neobsahuje událost ukončení přehrávače flash animace. Tímto faktem vstupuje do hry JavaScript, mimochodem jazyk podobný ActionScriptu, a omezení zaznamenávání interakcí uživatele pouze s flash animací umístěné v HTML stránce. JavaScript totiž umožňuje nejen zachytit událost ukončení setrvání HTML stránky v prohlížeči, ale dokonce volat zpřístupněné funkce ActionScriptu v přehrávané flash animaci. Pro snazší pochopení provázání jednotlivých programovacích jazyků a toků dat slouží následující obrázek: 2 Remote Flash Usability testing Lukáš Skřivánek Ve chvíli uzavření prohlížeče, načtení jiné stránky či obnovení stránky je JavaScriptem odchycena událost onUnload a JavaScript volá funkci ActionScriptu onClose(). Tato funkce přidá poslední událost end s časovým razítkem a odešle poslední události skriptu PHP. PHP skript obsluhuje požadavky ActionScriptu tak, že buď načte z databáze číslo posledního uživate, to zvýší a předá zpět flash animaci, nebo přijme XML soubor, ten přečte a pomocí SQL uloží data v něm obsažená do databáze. Než začneme databázi jako uložiště událostí využívat je třeba v ní vytvořit tabulku. Naše tabulka obsahuje atributy: ID, UrlSwf, UserID, Frame, Time, Kind, MouseX, MouseY, Ascii, KeyCode. Player Z důvodů uvedených v části o návrhu řešení není v současné době možné implementovat player podle prvotní vize v ActionScriptu 2.0. Možným řešením je buď vyčkat příchodu vyšších verzí ActionScriptu nebo jiných technologií spojených s Macromedia Flashem nebo sáhnout po jiných nastrojích jakými může být například Win32 API, jenž bude posílat události přímo přehrávači flash animace. Instalace Recorder Pro správnou funkci recorderu je nutné mít: 1. zdrojový soubor recorderu (recorder.as - příloha č. 1) 2. zdrojový soubor testované flash animace (*.fla) 3. html stránku, která bude obsahovat flash animaci (recorder.html - příloha č. 3) 4. PHP skript pro ukládání událostí (save.php - příloha č. 2) 5. schéma tabulky (sql.txt - příloha č. 4) 6. funkční webový server s podporou PHP skriptů 7. databázový server MySQL 3 Remote Flash Usability testing Lukáš Skřivánek 1. Ve zdrojovém souboru recorderu (recorder.as) je třeba modifikovat cestu k PHP skriptu určenému k ukládání událostí: _global.php_name = "http://www.server.cz/save.php"; a volitelně je možné změnit po kolika událostech má docházet k odesílání: _global.send_count = 50; 2. Zdrojový soubor testované flash animace je třeba modifikovat tak, že na první snímek animace vložíme akci: #include "recorder.as" Na konci toho řádku nesmí být středník. Tato akce způsobí přilinkování souboru recorder.as k flash animaci. Pokud se soubor recorder.as nachází v jiném adresáři nebo je přejmenován, je třeba změnit cestu a název vkládaného souboru. Pak již stačí jen spuštěním animaci znovu přeložit. 3. V html stránce je třeba modifikovat cestu k flash animaci a to hned na dvou místech: <param name="movie" value="animace.swf"> a <embed src="animace.swf" .... Pokud budete vytvářet stránku svoji, upozorňuji, že je nezbytně nutné, aby obsahovala <param name="allowScriptAccess" value="always" /> v tagu objekt flash animace a AllowScriptAccess="always" v tagu embeded. Bez tohoto by nefungovala komunikace mezi JavaScriptem a ActionScriptem. V mnohých zdrojích se dočtete, že hodnota always je u atributu AllowScriptAccess automatická bez uvedení, ale není to pravda. 4. V PHP skriptu je třeba správně nastavit adresu k MySQL serveru: $SQL_Server="mysql.server.cz"; uživatelské jméno v MySQL: $SQL_Login="user name"; heslo: $SQL_Password="password"; databázi: $SQL_Databaze="databaze"; 4 Remote Flash Usability testing Lukáš Skřivánek a název tabulky, kterou vytvoříme za chvíli: $SQL_Table="recorder"; 5. Podle tohoto schématu je třeba vytvořit tabulku v databázi. Pokud chcete zvolit jiný název tabulky nezapomeňte správně nastavit v PHP skriptu proměnnou $SQL_Table (část 4.). Jiné zásahy do schématu se provádět nemusí. Body 6 a 7 přesahují rámec tohoto textu a nejsou ani cílem, stačí mít funkční webový server s podporou PHP skriptů. Do jeho adresáře s publikovanými html a php stránkami přikopírovat soubory: • nově přeloženou flash animaci (*.swf) • html stránku, která bude obsahovat flash animaci (recorder.html) • PHP skript pro ukládání událostí (save.php) Zároveň Vám musí fungovat MySQL server a musíte mít správně nastavené veškeré výše zmíněné proměnné (cesty, jména, hesla ...) a vytvořenou tabulku (bod 5.). Pak již stačí zadat do prohlížeče adresu: http://adresaVasehoWebovehoServeru/cesta/recorder.html. Měla by se Vám zobrazit html stránka obsahující vaši flash animaci. Při první interakci s touto animací se začnou veškeré interakce zaznamenávat (včetně té první) a záznam skončí až při uzavření okna prohlížeče, načtení jiné stránky nebo obnovení stránky(v tom případě může začít záznam znovu pod novým uživatelem). Závěr Ač celý dokument vyznívá proti produktu Macromedia Flash a ActionScriptu, je třeba říci, že se jedná o velmi kvalitní kreslící a prezentační nástroj, ve kterém lze dokonce tvořit aplikace a hry, je uživatelsky přívětivý, intuitivní a velmi dobře se v něm pracuje. ActionScript samotný je jazyk, který prochází vývojem a tím se stává stále mocnějším nástrojem. Podle mého názoru jeho událostní model není zatím zcela vyzrálý, avšak je třeba si uvědomit, že na podobné účely není určený ani navržený a pro běžné aplikace je plně dostačující. Celá práce byla realizována v Macromedia Flashi 8.0 Trial version a je pravděpodobné, že v nižších verzích nebude korektně fungovat zvláště zpřístupnění funkcí z ActionScriptu pro JavaScript. (ExternalInterface.addCallback("onClose", null, onClose);) Zdroje http://www.macromedia.com http://www.adobe.com/cfusion/tdrc/index.cfm?product=flashpro&loc=en_us – Trial version 5 Remote Flash Usability testing Lukáš Skřivánek http://www.brajeshwar.com/reference/as2/ http://livedocs.macromedia.com/flash/mx2004/ http://www.adobe.com/support/flash/action_scripts/actionscript_dictionary/ http://www.kirupa.com/developer/oop2/AS2OOPindex.htm http://www.actionscript.org/tutorials.shtml http://flash.jakpsatweb.cz/ 6 Remote Flash Usability testing Lukáš Skřivánek Příloha č. 1 - recorder.as import flash.external.*; // option variable _global.php_name = "http://www.server.cz/save.php"; _global.send_count = 50; // do not change _global.capture_count = 0; _global.t0 = 0; _global.user = 0; // create XML _global.EventXML = new XML(); _global.EventXML.contentType = "text/xml"; _global.EventXML.xmlDecl = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"; _global.EventXML.appendChild( EventXML.createElement("swfEvents") ); _global.UserXML = new XML(); _global.NothingXML = new XML(); //read user ID randomize = Math.random()*Math.random(); _global.UserXML.load(_global.php_name+"?id="+randomize); _global.UserXML.onLoad = userOnLoad; function userOnLoad(success:Boolean) { if (success) { if (_global.UserXML.firstChild.nextSibling.nodeName == "user") { _global.user = _global.UserXML.firstChild.nextSibling.firstChild.nodeValue; _level0.vypis=_global.user; } else { fatal_error("RECORDER: Connection failed! (2)"); } } else { fatal_error("RECORDER: Connection failed! (1)"); } } //print error function fatal_error(mess:String){ _level0.createEmptyMovieClip("error", _level0.getNextHighestDepth()); _level0.error.createTextField("mess", 1, 0, 0, 200, 20); _level0.error.mess.background=true; _level0.error.mess.backgroundColor = 0xFF0000; _level0.error.mess.text = mess; } //end capture function onClose() { time=getTimer(); if(_global.t0==0){ _global.t0=time; } _global.EventXML.lastChild.appendChild( EventXML.createElement("end") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createTextNode(time-_global.t0) ); ESend(); } ExternalInterface.addCallback("onClose", null, onClose); //save events function ESend() { //set user and url _global.EventXML.firstChild.insertBefore(EventXML.createElement("user"), _global.EventXML.firstChild.firstChild); _global.EventXML.firstChild.firstChild.appendChild( EventXML.createTextNode(_global.user) ); _global.EventXML.firstChild.insertBefore(EventXML.createElement("url"), _global.EventXML.firstChild.firstChild); _global.EventXML.firstChild.firstChild.appendChild( EventXML.createTextNode(_level0._url) ); //send XML randomize = Math.random()*Math.random(); _global.EventXML.sendAndLoad(_global.php_name+"?id="+randomize,_global.NothingXML); 7 Remote Flash Usability testing Lukáš Skřivánek //create new XML _global.capture_count = 0; _global.EventXML = new XML(); _global.EventXML.contentType = "text/xml"; _global.EventXML.xmlDecl = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"; _global.EventXML.appendChild( EventXML.createElement("swfEvents") ); } //save events function EventsSend() { _global.capture_count++; if((_global.capture_count > _global.send_count)&&(_global.user!=0)){ ESend(); } } //create mouseListener var mouseListener:Object = new Object(); mouseListener.onMouseDown = function() { time=getTimer(); if(_global.t0==0){ _global.t0=time; } _global.EventXML.lastChild.appendChild( EventXML.createElement("event") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("time") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(time_global.t0) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("frame") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(_level0._currentframe) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("kind") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode("onMouseDown") ); _global.mouse_x = _xmouse; _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("mouse_x") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(mouse_x) ); _global.mouse_y = _ymouse; _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("mouse_y") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(mouse_y) ); EventsSend(); }; mouseListener.onMouseUp = function() { time=getTimer(); if(_global.t0==0){ _global.t0=time; } _global.EventXML.lastChild.appendChild( EventXML.createElement("event") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("time") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(time_global.t0) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("frame") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(_level0._currentframe) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("kind") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode("onMouseUp") ); _global.mouse_x = _xmouse; _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("mouse_x") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(mouse_x) ); _global.mouse_y = _ymouse; _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("mouse_y") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(mouse_y) ); EventsSend(); }; mouseListener.onMouseMove = function() { time=getTimer(); if(_global.t0==0){ _global.t0=time; } _global.EventXML.lastChild.appendChild( EventXML.createElement("event") ); 8 Remote Flash Usability testing Lukáš Skřivánek _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("time") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(time_global.t0) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("frame") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(_level0._currentframe) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("kind") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode("onMouseMove") ); _global.mouse_x = _xmouse; _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("mouse_x") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(mouse_x) ); _global.mouse_y = _ymouse; _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("mouse_y") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(mouse_y) ); EventsSend(); }; Mouse.addListener(mouseListener); //create keyListener var keyListener:Object = new Object(); keyListener.onKeyDown = function() { time=getTimer(); if(_global.t0==0){ _global.t0=time; } _global.EventXML.lastChild.appendChild( EventXML.createElement("event") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("time") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(time_global.t0) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("frame") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(_level0._currentframe) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("kind") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode("onKeyDown") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("ascii") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(Key.getAscii()) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("code") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(Key.getCode()) ); EventsSend(); }; keyListener.onKeyUp = function() { time=getTimer(); if(_global.t0==0){ _global.t0=time; } _global.EventXML.lastChild.appendChild( EventXML.createElement("event") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("time") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(time_global.t0) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("frame") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(_level0._currentframe) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("kind") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode("onKeyUp") ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("ascii") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(Key.getAscii()) ); _global.EventXML.lastChild.lastChild.appendChild( EventXML.createElement("code") ); _global.EventXML.lastChild.lastChild.lastChild.appendChild( EventXML.createTextNode(Key.getCode()) ); EventsSend(); }; Key.addListener(keyListener); 9 Remote Flash Usability testing Lukáš Skřivánek Příloha č. 2 – save.php <?php //option variable - SQL $SQL_Server="mysql.server.cz"; $SQL_Login="user name"; $SQL_Password="password"; $SQL_Databaze="databaze"; $SQL_Table="recorder"; //do not change //connect database $Spojeni = mysql_connect($SQL_Server, $SQL_Login, $SQL_Password); if ($Spojeni) { $DB = mysql_select_db($SQL_Databaze, $Spojeni); if ($DB) { mysql_query("SET CHARACTER SET utf8"); if(IsSet($HTTP_RAW_POST_DATA)){ //save XML $dom = domxml_open_mem($HTTP_RAW_POST_DATA); $root = $dom->document_element(); $url="unknown"; $user=0; // zero is ban $frame=0; $time=0; //parse XML function parse_node($node) { global $SQL_Table, $url, $user, $frame, $time; if ($node->has_child_nodes()) { foreach($node->child_nodes() as $n) { if ($n->node_name()=='url'){ foreach($n->child_nodes() as $text) { $url=$text->node_value(); } } if ($n->node_name()=='user'){ foreach($n->child_nodes() as $text) { $user=$text->node_value(); } } if ($n->node_name()=='end'){ foreach($n->child_nodes() as $text) { $endtime=$text->node_value(); } if($user!=0){ $UP = mysql_query("INSERT INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind) VALUES('$url',$user, 0, $endtime, 'end')"); } } if ($n->node_name()=='event'){ foreach($n->child_nodes() as $text) { if ($text->node_name()=='time'){ foreach($text->child_nodes() as $value) { $time=$value->node_value(); } } if ($text->node_name()=='frame'){ foreach($text->child_nodes() as $value) { $frame=$value->node_value(); } } if ($text->node_name()=='kind'){ foreach($text->child_nodes() as $value) { $kind=$value->node_value(); } } if ($text->node_name()=='mouse_x'){ foreach($text->child_nodes() as $value) { $mouse_x=$value->node_value(); } 10 Remote Flash Usability testing Lukáš Skřivánek } if ($text->node_name()=='mouse_y'){ foreach($text->child_nodes() as $value) { $mouse_y=$value->node_value(); } } if ($text->node_name()=='ascii'){ foreach($text->child_nodes() as $value) { $ascii=$value->node_value(); } } if ($text->node_name()=='code'){ foreach($text->child_nodes() as $value) { $code=$value->node_value(); } } } if (($kind=="onKeyUp")||($kind=="onKeyDown")){ if($user!=0){ $UP = mysql_query("INSERT INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind,Ascii,KeyCode) VALUES('$url',$user, $frame, $time, '$kind', $ascii, $code)"); $kind=""; $ascii=0; $code=0; } }else{ if($user!=0){ $UP = mysql_query("INSERT INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind,MouseX,MouseY) VALUES('$url',$user, $frame, $time, '$kind', $mouse_x, $mouse_y)"); $kind=""; $mouse_x=0; $mouse_y=0; } } } } } } parse_node($root); $dom->free(); }else{ //read and send user ID $result = mysql_query("SELECT COALESCE( MAX( UserID ) , 0 ) AS MAXUSER FROM $SQL_Table"); $row = mysql_fetch_array($result); $maxid = $row['MAXUSER']; $maxid++; $UP = mysql_query("INSERT INTO $SQL_Table (UrlSwf,UserID,Frame,Time,Kind) VALUES('unknown',$maxid, 0, 0, 'start')"); header("Content-type: text/xml"); echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; echo "<user>"; echo $maxid; echo "</user>"; } } } @mysql_close ($Spojeni); ?> 11 Remote Flash Usability testing Lukáš Skřivánek Příloha č. 3 – recorder.html <html> <head> <title>NUR - FLASH - Recorder</title> <script type="text/javascript"> /* <![CDATA[ */ function onClose(){ window.document.myFlash.onClose(); } /* ]]> */ </script> </head> <body onUnload="onClose();alert('Recording was finished!');return true;"> <p> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swf lash.cab#version=8,0,0,0" width="550" height="400" id="myFlash"> <param name="movie" value="animace.swf"> <param name="allowScriptAccess" value="always" /> <param name="quality" value="high"> <embed src="animace.swf" quality="high" width="550" height="400" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Pr od_Version=ShockwaveFlash" name="myFlash" swLiveConnect="true" AllowScriptAccess="always"> </embed> </object> </p> </body> </html> 12 Remote Flash Usability testing Lukáš Skřivánek Příloha č. 4 – sql.txt CREATE TABLE `recorder` ( `ID` INT NOT NULL AUTO_INCREMENT, `UrlSwf` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL , `UserID` INT NOT NULL, `Frame` INT NOT NULL, `Time` INT UNSIGNED NOT NULL, `Kind` VARCHAR( 20 ) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL, `MouseX` MEDIUMINT, `MouseY` MEDIUMINT, `Ascii` TINYINT UNSIGNED, `KeyCode` SMALLINT, PRIMARY KEY ( `ID` ) ); 13
Podobné dokumenty
ActionScript
animace a jejich interpretaci. Předdefinovaný XML Socket objekt umožňuje vytvářet plynulé
spojení se serverem k propouštění XML dat pro aplikace v reálném čase.
Vyuºití JavaScriptových knihoven - ExtBrain
V jádře jQuery jsou zakomponovány funkce pro správu událostí (event handling). Pokud
je daná událost na elementu vyvolána, je spuštěna akce, která se k dané události váže.
Základem připojování udál...
Postřehová hra Zadání projektu 1 Moje cíle
5 – pokud je výbuch (datový typ boolean) true, metoda g2d nastaví
na „Objektu“, čtvereci patřičnou barvou.
6 – pokud je výbuch (datový typ boolean, na začátku je nastaven jako false)
true, metoda g...
Aliens atack - Gymnázium Arabská
parametr souřadnice y. Další třída byla catcher, která zastupuje plosinu. Catcher má
parametr souřadnice x. Dalším postupem bylo nahrání těchto dvou obrázků do canvasu.
Hlavní myšlenka kódu je vytv...
Appendix to ces news 2012: Longest words
As result we have a corpus containing only well-formed sentences in the language under consideration. The
sentences are in random order; hence, sharing the corpus does not violate copyright law bec...
Univerzita Palackého v Olomouci - Katedra geoinformatiky
animace se snímky přehrávají stanovenou rychlostí. Vloţené objekty mohou
obsahovat vlastní časovou osu, která funguje nezávisle na hlavní, při ovládání
objektu je třeba její snímky adresovat přes j...
Porovnani projektu Wikidata a DBpedia jako zdroju
volby ve Francii, obce v Německu, atp.). Důsledkem bylo, že data extrahovaná z anglické verze Wikipedie, kterých byla většina, měla jako subjekt URI obsahující název
článku v angličtině, a data ext...
Jak na Google Tag Manager
zvolíme název účtu, jak ukazuje obrázek níže. Z důvodu přehlednosti je dobré používat
unikátní název. V případě, že má firma/vlastník vícero webových stránek, vytváříme jeden
účet, ve kterém bude p...