diff options
Diffstat (limited to 'includes/js/dojox/analytics')
-rw-r--r-- | includes/js/dojox/analytics/README | 134 | ||||
-rw-r--r-- | includes/js/dojox/analytics/_base.js | 127 | ||||
-rw-r--r-- | includes/js/dojox/analytics/logger/JSON.php | 724 | ||||
-rw-r--r-- | includes/js/dojox/analytics/logger/dojoxAnalytics.php | 31 | ||||
-rw-r--r-- | includes/js/dojox/analytics/plugins/consoleMessages.js | 24 | ||||
-rw-r--r-- | includes/js/dojox/analytics/plugins/dojo.js | 22 | ||||
-rw-r--r-- | includes/js/dojox/analytics/plugins/idle.js | 34 | ||||
-rw-r--r-- | includes/js/dojox/analytics/plugins/mouseClick.js | 49 | ||||
-rw-r--r-- | includes/js/dojox/analytics/plugins/mouseOver.js | 90 | ||||
-rw-r--r-- | includes/js/dojox/analytics/plugins/window.js | 34 | ||||
-rw-r--r-- | includes/js/dojox/analytics/profiles/analytics.profile.js | 21 | ||||
-rw-r--r-- | includes/js/dojox/analytics/profiles/analyticsInBase.profile.js | 22 | ||||
-rw-r--r-- | includes/js/dojox/analytics/tests/test_analytics.html | 93 |
13 files changed, 1405 insertions, 0 deletions
diff --git a/includes/js/dojox/analytics/README b/includes/js/dojox/analytics/README new file mode 100644 index 0000000..c41cc19 --- /dev/null +++ b/includes/js/dojox/analytics/README @@ -0,0 +1,134 @@ +------------------------------------------------------------------------------- +dojox.analytics +------------------------------------------------------------------------------- +Version 1.0 +Release date: 12/17/2007 +------------------------------------------------------------------------------- +Project state: beta +------------------------------------------------------------------------------- +Project authors + Dustin Machi +------------------------------------------------------------------------------- +Project description + analytics and client monitoring system. Including the base analytics +system and any number of plugins enables logging of different system data +back to the server. Plugins included at this time: + + dojo - reports dojo startup collected information + window - reports available window information to the server + mouseOver - allows periodic sampling of mouseOver + mouseClick - reports any mouse clicks to the server + idle - reports idle/activity + consoleMessages - reports console.* messages to the server + + +------------------------------------------------------------------------------- +Dependencies: + +Dojo Core (package loader). +------------------------------------------------------------------------------- +Documentation + +Usage: + +The primary intended usage will be to create a custom build layer that includes +the particular plugins you need for your project. However in practice you +can use the system as such: + + <script type="text/javascript" src="../../../dojo/dojo.js" + djConfig="parseOnLoad: true, isDebug: false, usePlainJson: true, sendMethod: 'script', sendInterval: 5000"></script> + + <script language="JavaScript" type="text/javascript"> + // include the analytics system + dojo.require("dojox.analytics"); + + //tracks mouse clicks on the page + dojo.require("dojox.analytics.plugins.mouseClick"); + + // this plugin returns the informatin dojo collects when it launches + dojo.require("dojox.analytics.plugins.dojo"); + + // this plugin return the information the window has when it launches + // and it also ties to a few events such as window.option + dojo.require("dojox.analytics.plugins.window"); + + // this plugin tracks console. message, It logs console.error, warn, and + // info messages to the tracker. It also defines console.rlog() which + // can be used to log only to the server. Note that if isDebug() is disabled + // you will still see the console messages on the sever, but not in the actual + // browser console. + dojo.require("dojox.analytics.plugins.consoleMessages"); + + // tracks where a mouse is on a page an what it is over, periodically sampling + // and storing this data + dojo.require("dojox.analytics.plugins.mouseOver"); + + //tracks when the user has gone idle + dojo.require("dojox.analytics.plugins.idle"); + + </script> + +When done using a build, none of the dojo.require() statement will be requires +would already be in the build. + +Most of the plugins and the base itself have a number of configurable params +that are passed in via the djConfig variable set. This approach is taken so that +the parameters can be easily provided in the case of a build or for a custom +dojo.js build with analytics built in. Examples for different build profiles +are in the profiles directory. + +Available Configuration Parameters: + + Base Configs + sendInterval - Normal send interval. Default 5000 + sendMethod - "script" || "xhrPost" + inTransitRetry - Delay before retrying an a send if it was in transit + or if there is still data to be sent after a post. + Default 1000 + analyticsUrl - url to send logging data to. defaults to the test php + file for now + maxRequestSize - Maximum size of GET style requests. Capped at 2000 for + IE, and 4000 otherwise + + consoleMessages Config: + + consoleLogFuncs - functions from the console object that you will log to + the server. If the console object doesn't exist + or a particuarl method doesn't exist it will be + created as a remote logging only method. This provides + a quick and convient way to automatically define + a remote logging funciton that includes the functions + name in the log. The 'rlog' in the default paramerters + is an example of this. Defaults to ["error", "warn", "info", "rlog"] + + idle Config: + + idleTime - Number of ms to be idle before being reported to the server as idle + + mouseOver config: + targetProps - the properties whose values will be reported for each target from + a mouse over sample. defaults to ["id","className","localName","href", "spellcheck", "lang", "textContent", "value" ] + + sampleDelay - the delay in ms between mouseover samples. Defaults to 2500 + + window config: + windowConnects - methods on the window objec that will be attached to + have its data passed to the server when called. + + +Note that the basic usage of this system simply serializes json with toJson() when passed +to the analytics addData() method. If data is passed that has circular references +it will die. Take care not to do that or be surprised when it doens't work +in those cases. + + +------------------------------------------------------------------------------- +Installation instructions + +Grab the following from the Dojo SVN Repository: +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/analytics + +Install into the following directory structure: +/dojox/analytics/ + +...which should be at the same level as your Dojo checkout. diff --git a/includes/js/dojox/analytics/_base.js b/includes/js/dojox/analytics/_base.js new file mode 100644 index 0000000..8d6bd66 --- /dev/null +++ b/includes/js/dojox/analytics/_base.js @@ -0,0 +1,127 @@ +if(!dojo._hasResource["dojox.analytics._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics._base"] = true; +dojo.provide("dojox.analytics._base"); + +dojox.analytics = function(){ + //where we store data until we're ready to send it off. + + //the data queue; + this._data = [] ; + + //id of messages for this session/page + this._id=1; + + //some default values + this.sendInterval=dojo.config["sendInterval"] || 5000; + this.inTransitRetry=dojo.config["inTransitRetry"] || 200; + this.dataUrl=dojo.config["analyticsUrl"] || dojo.moduleUrl("dojox.analytics.logger", "dojoxAnalytics.php"); + this.sendMethod = dojo.config["sendMethod"] || "xhrPost"; + if (dojo.isIE){ + this.maxRequestSize = 2000; + }else{ + this.maxRequestSize = dojo.config["maxRequestSize"] || 4000; + } + + //while we can go ahead and being logging as soon as this constructor is completed + //we're not going to schedule pushing data to the server until after the page + //has completed loading + dojo.addOnLoad(this, "schedulePusher"); + dojo.addOnUnload(this, "pushData", true); +}; + +dojo.extend(dojox.analytics, { + schedulePusher: function(interval){ + // summary: + // schedule the data pushing routines to happen in interval ms + setTimeout(dojo.hitch(this, "checkData"), interval||this.sendInterval); + }, + + addData: function(dataType, data){ + // summary: + // add data to the queue. Will be pusshed to the server on the next + // data push + + if (arguments.length>2){ + var d = []; + for(var i=1;i<arguments.length;i++){ + d.push(arguments[i]); + } + data = d; + } + + this._data.push({plugin: dataType, data: data}); + }, + + checkData: function(){ + // summary + if (this._inTransit){ + this.schedulePusher(this.inTransitRetry); + return; + } + + if (this.pushData()){return} + this.schedulePusher(); + }, + + pushData: function(){ + // summary + // pushes data to the server if any exists. If a push is done, return + // the deferred after hooking up completion callbacks. If there is no data + // to be pushed, return false; + if (this._data.length>0){ + //clear the queue + this._inTransit=this._data; + this._data=[]; + var def; + switch(this.sendMethod){ + case "script": + def = dojo.io.script.get({url: this.getQueryPacket(), preventCache: 1, callbackParamName: "callback"}); + break; + case "xhrPost": + default: + console.info("post send: ", this._inTransit); + def = dojo.xhrPost({url:this.dataUrl, content: {id: this._id++, data: dojo.toJson(this._inTransit)}}); + break; + } + def.addCallback(this, "onPushComplete"); + return def; + } + return false; + }, + + getQueryPacket: function(){ + while(true){ + var content = {id: this._id++, data: dojo.toJson(this._inTransit)}; + + //FIXME would like a much better way to get the query down to lenght + var query = this.dataUrl + '?' + dojo.objectToQuery(content); + if (query.length>this.maxRequestSize){ + this._data.unshift(this._inTransit.pop()); + this._split=1; + }else{ + //console.log("script send: ", this._inTransit, " Remaining in queue: ", this._data.length); + return query; + } + } + }, + + onPushComplete: function(results){ + // summary + // if our data push was successfully, remove the _inTransit data and schedule the next + // parser run. + if (this._inTransit){ + delete this._inTransit; + } + + if (this._data.length>0){ + this.schedulePusher(this.inTransitRetry); + } else { + this.schedulePusher(); + } + } +}); + +//create the analytics singleton +dojox.analytics = new dojox.analytics(); + +} diff --git a/includes/js/dojox/analytics/logger/JSON.php b/includes/js/dojox/analytics/logger/JSON.php new file mode 100644 index 0000000..4a21ce7 --- /dev/null +++ b/includes/js/dojox/analytics/logger/JSON.php @@ -0,0 +1,724 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ + +/** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * @category + * @package Services_JSON + * @author Michal Migurski <mike-json@teczno.com> + * @author Matt Knapp <mdknapp[at]gmail[dot]com> + * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> + * @copyright 2005 Michal Migurski + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_SLICE', 1); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_STR', 2); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_ARR', 4); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_OBJ', 8); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_CMT', 16); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_LOOSE_TYPE', 10); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_STRICT_TYPE', 11); + +/** + * Converts to and from JSON format. + * + * Brief example of use: + * + * <code> + * // create a new instance of Services_JSON + * $json = new Services_JSON(); + * + * // convert a complexe value to JSON notation, and send it to the browser + * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); + * $output = $json->encode($value); + * + * print($output); + * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] + * + * // accept incoming POST data, assumed to be in JSON notation + * $input = file_get_contents('php://input', 1000000); + * $value = $json->decode($input); + * </code> + */ +class Services_JSON +{ + /** + * constructs a new JSON instance + * + * @param int $use object behavior: when encoding or decoding, + * be loose or strict about object/array usage + * + * possible values: + * - SERVICES_JSON_STRICT_TYPE: strict typing, default. + * "{...}" syntax creates objects in decode(). + * - SERVICES_JSON_LOOSE_TYPE: loose typing. + * "{...}" syntax creates associative arrays in decode(). + */ + function Services_JSON($use = SERVICES_JSON_STRICT_TYPE) + { + $this->use = $use; + } + + /** + * convert a string from one UTF-16 char to one UTF-8 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf16 UTF-16 character + * @return string UTF-8 character + * @access private + */ + function utf162utf8($utf16) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) + return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); + + $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); + + switch(true) { + case ((0x7F & $bytes) == $bytes): + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x7F & $bytes); + + case (0x07FF & $bytes) == $bytes: + // return a 2-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xC0 | (($bytes >> 6) & 0x1F)) + . chr(0x80 | ($bytes & 0x3F)); + + case (0xFFFF & $bytes) == $bytes: + // return a 3-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xE0 | (($bytes >> 12) & 0x0F)) + . chr(0x80 | (($bytes >> 6) & 0x3F)) + . chr(0x80 | ($bytes & 0x3F)); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + function utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $ut8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return string JSON string representation of input var + * @access public + */ + function encode($var) + { + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + return '{' . + join(',', array_map(array($this, 'name_value'), + array_keys($var), + array_values($var))) + . '}'; + } + + // treat it like a regular array + return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']'; + + case 'object': + $vars = get_object_vars($var); + return '{' . + join(',', array_map(array($this, 'name_value'), + array_keys($vars), + array_values($vars))) + . '}'; + + default: + return ''; + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + function name_value($name, $value) + { + return $this->encode(strval($name)) . ':' . $this->encode($value); + } + + /** + * reduce a string by removing leading and trailing comments and whitespace + * + * @param $str string string value to strip of comments and whitespace + * + * @return string string value stripped of comments and whitespace + * @access private + */ + function reduce_string($str) + { + $str = preg_replace(array( + + // eliminate single line comments in '// ...' form + '#^\s*//(.+)$#m', + + // eliminate multi-line comments in '/* ... */' form, at start of string + '#^\s*/\*(.+)\*/#Us', + + // eliminate multi-line comments in '/* ... */' form, at end of string + '#/\*(.+)\*/\s*$#Us' + + ), '', $str); + + // eliminate extraneous space + return trim($str); + } + + /** + * decodes a JSON string into appropriate variable + * + * @param string $str JSON-formatted string + * + * @return mixed number, boolean, string, array, or object + * corresponding to given JSON input string. + * See argument 1 to Services_JSON() above for object-output behavior. + * Note that decode() always returns strings + * in ASCII or UTF-8 format! + * @access public + */ + function decode($str) + { + $str = $this->reduce_string($str); + + switch (strtolower($str)) { + case 'true': + return true; + + case 'false': + return false; + + case 'null': + return null; + + default: + if (is_numeric($str)) { + // Lookie-loo, it's a number + + // This would work on its own, but I'm trying to be + // good about returning integers where appropriate: + // return (float)$str; + + // Return float or int, as appropriate + return ((float)$str == (integer)$str) + ? (integer)$str + : (float)$str; + + } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { + // STRINGS RETURNED IN UTF-8 FORMAT + $delim = substr($str, 0, 1); + $chrs = substr($str, 1, -1); + $utf8 = ''; + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c < $strlen_chrs; ++$c) { + + $substr_chrs_c_2 = substr($chrs, $c, 2); + $ord_chrs_c = ord($chrs{$c}); + + switch (true) { + case $substr_chrs_c_2 == '\b': + $utf8 .= chr(0x08); + ++$c; + break; + case $substr_chrs_c_2 == '\t': + $utf8 .= chr(0x09); + ++$c; + break; + case $substr_chrs_c_2 == '\n': + $utf8 .= chr(0x0A); + ++$c; + break; + case $substr_chrs_c_2 == '\f': + $utf8 .= chr(0x0C); + ++$c; + break; + case $substr_chrs_c_2 == '\r': + $utf8 .= chr(0x0D); + ++$c; + break; + + case $substr_chrs_c_2 == '\\"': + case $substr_chrs_c_2 == '\\\'': + case $substr_chrs_c_2 == '\\\\': + case $substr_chrs_c_2 == '\\/': + if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || + ($delim == "'" && $substr_chrs_c_2 != '\\"')) { + $utf8 .= $chrs{++$c}; + } + break; + + case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): + // single, escaped unicode character + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) + . chr(hexdec(substr($chrs, ($c + 4), 2))); + $utf8 .= $this->utf162utf8($utf16); + $c += 5; + break; + + case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): + $utf8 .= $chrs{$c}; + break; + + case ($ord_chrs_c & 0xE0) == 0xC0: + // characters U-00000080 - U-000007FF, mask 110XXXXX + //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 2); + ++$c; + break; + + case ($ord_chrs_c & 0xF0) == 0xE0: + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 3); + $c += 2; + break; + + case ($ord_chrs_c & 0xF8) == 0xF0: + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 4); + $c += 3; + break; + + case ($ord_chrs_c & 0xFC) == 0xF8: + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 5); + $c += 4; + break; + + case ($ord_chrs_c & 0xFE) == 0xFC: + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 6); + $c += 5; + break; + + } + + } + + return $utf8; + + } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { + // array, or object notation + + if ($str{0} == '[') { + $stk = array(SERVICES_JSON_IN_ARR); + $arr = array(); + } else { + if ($this->use == SERVICES_JSON_LOOSE_TYPE) { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = array(); + } else { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = new stdClass(); + } + } + + array_push($stk, array('what' => SERVICES_JSON_SLICE, + 'where' => 0, + 'delim' => false)); + + $chrs = substr($str, 1, -1); + $chrs = $this->reduce_string($chrs); + + if ($chrs == '') { + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } else { + return $obj; + + } + } + + //print("\nparsing {$chrs}\n"); + + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c <= $strlen_chrs; ++$c) { + + $top = end($stk); + $substr_chrs_c_2 = substr($chrs, $c, 2); + + if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { + // found a comma that is not inside a string, array, etc., + // OR we've reached the end of the character list + $slice = substr($chrs, $top['where'], ($c - $top['where'])); + array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); + //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + // we are in an array, so just push an element onto the stack + array_push($arr, $this->decode($slice)); + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + // we are in an object, so figure + // out the property name and set an + // element in an associative array, + // for now + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // "name":value pair + $key = $this->decode($parts[1]); + $val = $this->decode($parts[2]); + + if ($this->use == SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // name:value pair, where name is unquoted + $key = $parts[1]; + $val = $this->decode($parts[2]); + + if ($this->use == SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } + + } + + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { + // found a quote, and we are not inside a string + array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); + //print("Found start of string at {$c}\n"); + + } elseif (($chrs{$c} == $top['delim']) && + ($top['what'] == SERVICES_JSON_IN_STR) && + (($chrs{$c - 1} != '\\') || + ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) { + // found a quote, we're in a string, and it's not escaped + array_pop($stk); + //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '[') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-bracket, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); + //print("Found start of array at {$c}\n"); + + } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { + // found a right-bracket, and we're in an array + array_pop($stk); + //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '{') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-brace, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); + //print("Found start of object at {$c}\n"); + + } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { + // found a right-brace, and we're in an object + array_pop($stk); + //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($substr_chrs_c_2 == '/*') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a comment start, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); + $c++; + //print("Found start of comment at {$c}\n"); + + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { + // found a comment end, and we're in one now + array_pop($stk); + $c++; + + for ($i = $top['where']; $i <= $c; ++$i) + $chrs = substr_replace($chrs, ' ', $i, 1); + + //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } + + } + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + return $obj; + + } + + } + } + } + +} + +?>
\ No newline at end of file diff --git a/includes/js/dojox/analytics/logger/dojoxAnalytics.php b/includes/js/dojox/analytics/logger/dojoxAnalytics.php new file mode 100644 index 0000000..0f7f849 --- /dev/null +++ b/includes/js/dojox/analytics/logger/dojoxAnalytics.php @@ -0,0 +1,31 @@ +<?php + require_once("./JSON.php"); + + $filename = "./logs/analytics.log"; + $json = new Services_JSON; + + $id = $_REQUEST["id"]; + $items = $json->decode($_REQUEST["data"]); + + if (!$handle = fopen($filename, 'a+')) { + print '{error: "server error"}'; + exit; + } + + foreach($items as $i=>$item){ + $item->_analyticsId = $id; + $item->_analyticsTimeStamp = time(); + $log = $json->encode($item) . "\n"; + fwrite($handle, $log); + } + + fclose($handle); + + $response = "{'eventsRecieved': '" . sizeof($items) . "', 'id': '" . $id . "'}"; + if ($_REQUEST["callback"]){ + print $_REQUEST["callback"] . "(" . $response . ");"; + }else{ + print $response; + } + +?> diff --git a/includes/js/dojox/analytics/plugins/consoleMessages.js b/includes/js/dojox/analytics/plugins/consoleMessages.js new file mode 100644 index 0000000..6b8e0f0 --- /dev/null +++ b/includes/js/dojox/analytics/plugins/consoleMessages.js @@ -0,0 +1,24 @@ +if(!dojo._hasResource["dojox.analytics.plugins.consoleMessages"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics.plugins.consoleMessages"] = true; +dojo.provide("dojox.analytics.plugins.consoleMessages"); + +dojox.analytics.plugins.consoleMessages = new (function(){ + // summary: + // plugin to have analyitcs return the base info dojo collects + this.addData = dojo.hitch(dojox.analytics, "addData", "consoleMessages"); + + var lvls = dojo.config["consoleLogFuncs"] || ["error", "warn", "info", "rlog"]; + if(!console){ + console={}; + } + + for(var i=0; i<lvls.length;i++){ + if (console[lvls[i]]){ + dojo.connect(console, lvls[i], dojo.hitch(this, "addData", lvls[i])); + }else{ + console[lvls[i]] = dojo.hitch(this, "addData", lvls[i]); + } + } +})(); + +} diff --git a/includes/js/dojox/analytics/plugins/dojo.js b/includes/js/dojox/analytics/plugins/dojo.js new file mode 100644 index 0000000..5ecd2ba --- /dev/null +++ b/includes/js/dojox/analytics/plugins/dojo.js @@ -0,0 +1,22 @@ +if(!dojo._hasResource["dojox.analytics.plugins.dojo"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics.plugins.dojo"] = true; +dojo.provide("dojox.analytics.plugins.dojo"); + +dojox.analytics.plugins.dojo = new (function(){ + // summary: + // plugin to have analyitcs return the base info dojo collects + this.addData = dojo.hitch(dojox.analytics, "addData", "dojo"); + dojo.addOnLoad(dojo.hitch(this, function(){ + var data = {}; + for(var i in dojo){ + if ((i=="version") || ((!dojo.isObject(dojo[i]))&&(i[0]!="_"))){ + data[i]=dojo[i]; + } + } + + if (dojo.config){data.djConfig=dojo.config} + this.addData(data); + })); +})(); + +} diff --git a/includes/js/dojox/analytics/plugins/idle.js b/includes/js/dojox/analytics/plugins/idle.js new file mode 100644 index 0000000..d1e71b7 --- /dev/null +++ b/includes/js/dojox/analytics/plugins/idle.js @@ -0,0 +1,34 @@ +if(!dojo._hasResource["dojox.analytics.plugins.idle"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics.plugins.idle"] = true; +dojo.provide("dojox.analytics.plugins.idle"); + +// window startup data +dojox.analytics.plugins.idle = new (function(){ + this.addData = dojo.hitch(dojox.analytics, "addData", "idle"); + this.idleTime=dojo.config["idleTime"] || 60000; + this.idle=true; + + this.setIdle = function(){ + this.addData("isIdle"); + this.idle=true; + + } + + dojo.addOnLoad(dojo.hitch(this, function(){ + var idleResets=["onmousemove","onkeydown","onclick","onscroll"]; + for (var i=0;i<idleResets.length;i++){ + dojo.connect(dojo.doc,idleResets[i],this, function(e){ + if (this.idle){ + this.idle=false; + this.addData("isActive"); + this.idleTimer=setTimeout(dojo.hitch(this,"setIdle"), this.idleTime); + }else{ + clearTimeout(this.idleTimer); + this.idleTimer=setTimeout(dojo.hitch(this,"setIdle"), this.idleTime); + } + }); + } + })); +})(); + +} diff --git a/includes/js/dojox/analytics/plugins/mouseClick.js b/includes/js/dojox/analytics/plugins/mouseClick.js new file mode 100644 index 0000000..c527383 --- /dev/null +++ b/includes/js/dojox/analytics/plugins/mouseClick.js @@ -0,0 +1,49 @@ +if(!dojo._hasResource["dojox.analytics.plugins.mouseClick"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics.plugins.mouseClick"] = true; +dojo.provide("dojox.analytics.plugins.mouseClick"); + +// window startup data +dojox.analytics.plugins.mouseClick = new (function(){ + this.addData = dojo.hitch(dojox.analytics, "addData", "mouseClick"); + + this.onClick=function(e){ + this.addData(this.trimEvent(e)); + } + dojo.connect(dojo.doc, "onclick", this, "onClick"); + + this.trimEvent=function(e){ + var t = {}; + for (var i in e){ + switch(i){ + case "target": + case "originalTarget": + case "explicitOriginalTarget": + var props=["id","className","nodeName", "localName","href", "spellcheck", "lang"]; + t[i]={}; + for(var j=0;j<props.length;j++){ + if(e[i][props[j]]){ + if (props[j]=="text" || props[j]=="textContent"){ + if ((e[i]["localName"]!="HTML")&&(e[i]["localName"]!="BODY")){ + t[i][props[j]]=e[i][props[j]].substr(0,50); + } + }else{ + t[i][props[j]]=e[i][props[j]]; + } + } + } + break; + case "clientX": + case "clientY": + case "pageX": + case "pageY": + case "screenX": + case "screenY": + t[i]=e[i]; + break; + } + } + return t; + } +})(); + +} diff --git a/includes/js/dojox/analytics/plugins/mouseOver.js b/includes/js/dojox/analytics/plugins/mouseOver.js new file mode 100644 index 0000000..beaf25c --- /dev/null +++ b/includes/js/dojox/analytics/plugins/mouseOver.js @@ -0,0 +1,90 @@ +if(!dojo._hasResource["dojox.analytics.plugins.mouseOver"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics.plugins.mouseOver"] = true; +dojo.provide("dojox.analytics.plugins.mouseOver"); + +dojox.analytics.plugins.mouseOver = new (function(){ + this.watchMouse = dojo.config["watchMouseOver"] || true; + this.mouseSampleDelay = dojo.config["sampleDelay"] || 2500; + this.addData = dojo.hitch(dojox.analytics, "addData", "mouseOver"); + this.targetProps = dojo.config["targetProps"] || ["id","className","localName","href", "spellcheck", "lang", "textContent", "value" ]; + + this.toggleWatchMouse=function(){ + if (this._watchingMouse){ + dojo.disconnect(this._watchingMouse); + delete this._watchingMouse; + return; + } + dojo.connect(dojo.doc, "onmousemove", this, "sampleMouse"); + } + + if (this.watchMouse){ + dojo.connect(dojo.doc, "onmouseover", this, "toggleWatchMouse"); + dojo.connect(dojo.doc, "onmouseout", this, "toggleWatchMouse"); + } + + this.sampleMouse=function(e){ + if (!this._rateLimited){ + this.addData("sample",this.trimMouseEvent(e)); + this._rateLimited=true; + setTimeout(dojo.hitch(this, function(){ + if (this._rateLimited){ + //this.addData("sample", this.trimMouseEvent(this._lastMouseEvent)); + this.trimMouseEvent(this._lastMouseEvent); + delete this._lastMouseEvent; + delete this._rateLimited; + } + }), this.mouseSampleDelay); + } + this._lastMouseEvent = e; + return e; + } + + this.trimMouseEvent=function(e){ + var t = {}; + for (var i in e){ + switch(i){ + //case "currentTarget": + case "target": + //case "originalTarget": + //case "explicitOriginalTarget": + var props=this.targetProps; + t[i]={}; + //console.log(e, i, e[i]); + for(var j=0;j<props.length;j++){ + if(dojo.isObject(e[i]) && props[j] in e[i]){ + + if (props[j]=="text" || props[j]=="textContent"){ + if (e[i]["localName"] && (e[i]["localName"]!="HTML")&&(e[i]["localName"]!="BODY")){ + t[i][props[j]]=e[i][props[j]].substr(0,50); + } + }else{ + t[i][props[j]]=e[i][props[j]]; + } + } + } + break; + //case "clientX": + //case "clientY": + //case "pageX": + //case "pageY": + //case "screenX": + //case "screenY": + case "x": + case "y": + if (e[i]) { + //console.log("Attempting: " + i); + var val = e[i]; + //console.log("val: " + val); console.log(i + "e of i: " + val); + t[i]=val + ''; + } + break; + default: + //console.log("Skipping: ", i); + break; + } + } + return t; + } +})(); + +} diff --git a/includes/js/dojox/analytics/plugins/window.js b/includes/js/dojox/analytics/plugins/window.js new file mode 100644 index 0000000..1eb86bb --- /dev/null +++ b/includes/js/dojox/analytics/plugins/window.js @@ -0,0 +1,34 @@ +if(!dojo._hasResource["dojox.analytics.plugins.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.analytics.plugins.window"] = true; +dojo.provide("dojox.analytics.plugins.window"); + +// window startup data +dojox.analytics.plugins.window = new (function(){ + this.addData = dojo.hitch(dojox.analytics, "addData", "window"); + this.windowConnects = dojo.config["windowConnects"] || ["open", "onerror"]; + + for(var i=0; i<this.windowConnects.length;i++){ + dojo.connect(window, this.windowConnects[i], dojo.hitch(this, "addData", this.windowConnects[i])); + } + + dojo.addOnLoad(dojo.hitch(this, function(){ + var data = {}; + for(var i in window){ + if (dojo.isObject(window[i])){ + switch(i){ + case "location": + case "console": + data[i]=window[i]; + break; + default: + break; + } + }else{ + data[i]=window[i]; + } + } + this.addData(data); + })); +})(); + +} diff --git a/includes/js/dojox/analytics/profiles/analytics.profile.js b/includes/js/dojox/analytics/profiles/analytics.profile.js new file mode 100644 index 0000000..a484da2 --- /dev/null +++ b/includes/js/dojox/analytics/profiles/analytics.profile.js @@ -0,0 +1,21 @@ +dependencies = { + layers: [ + { + name: "../dojox/analytics.js", + dependencies: [ + "dojox.analytics", + "dojox.analytics.plugins.dojo", + "dojox.analytics.plugins.window", + "dojox.analytics.plugins.consoleMessages", + "dojox.analytics.plugins.mouseOver", + "dojox.analytics.plugins.mouseClick", + "dojox.analytics.plugins.idle" + ] + } + ], + + prefixes: [ + [ "dojox", "../dojox" ], + [ "dijit", "../dijit" ] + ] +} diff --git a/includes/js/dojox/analytics/profiles/analyticsInBase.profile.js b/includes/js/dojox/analytics/profiles/analyticsInBase.profile.js new file mode 100644 index 0000000..22dbbd3 --- /dev/null +++ b/includes/js/dojox/analytics/profiles/analyticsInBase.profile.js @@ -0,0 +1,22 @@ +dependencies = { + layers: [ + { + //name: "../dojox/analytics.js", + name: "dojo.js", + dependencies: [ + "dojox.analytics", + "dojox.analytics.plugins.dojo", + "dojox.analytics.plugins.window", + "dojox.analytics.plugins.consoleMessages", + "dojox.analytics.plugins.mouseOver", + "dojox.analytics.plugins.mouseClick", + "dojox.analytics.plugins.idle" + ] + } + ], + + prefixes: [ + [ "dojox", "../dojox" ], + [ "dijit", "../dijit" ] + ] +} diff --git a/includes/js/dojox/analytics/tests/test_analytics.html b/includes/js/dojox/analytics/tests/test_analytics.html new file mode 100644 index 0000000..9fb8757 --- /dev/null +++ b/includes/js/dojox/analytics/tests/test_analytics.html @@ -0,0 +1,93 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> + <title>Dojox Analytics Test</title> + + <script type="text/javascript" src="../../../dojo/dojo.js" + djConfig="parseOnLoad: true, isDebug: true, usePlainJson: true, sendMethod: 'script', sendInterval: 5000, analyticsUrl: 'http://dojotoolkit.org/~dmachi/dojo-1.0/dojox/analytics/logger/dojoxAnalytics.php'"></script> + <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script> + + <script language="JavaScript" type="text/javascript"> + // include the analytics system + dojo.require("dojox.analytics"); + + // this plugin returns the informatin dojo collects when it launches + dojo.require("dojox.analytics.plugins.dojo"); + + // this plugin return the information the window has when it launches + // and it also ties to a few events such as window.option + dojo.require("dojox.analytics.plugins.window"); + + // this plugin tracks console. message, It logs console.error, warn, and + // info messages to the tracker. It also defines console.rlog() which + // can be used to log only to the server. Note that if isDebug() is disabled + // you will still see the console messages on the sever, but not in the actual + // browser console. + dojo.require("dojox.analytics.plugins.consoleMessages"); + + // tracks where a mouse is on a page an what it is over, periodically sampling + // and storing this data + dojo.require("dojox.analytics.plugins.mouseOver"); + + //tracks mouse clicks on the page + dojo.require("dojox.analytics.plugins.mouseClick"); + + //tracks when the user has gone idle + dojo.require("dojox.analytics.plugins.idle"); + + dojo.require("dijit.TitlePane"); + dojo.require("dojo.parser"); + dojo.require("dojo.io.script"); + + // widgets used inside subpage loaded via href= + dojo.require("dijit.form.Button"); + dojo.require("dijit.form.ComboBox"); + + dojo.addOnLoad(function(){console.info("Page Loaded Sample Message");}); + </script> + + <style type="text/css"> + @import "../../../dojo/resources/dojo.css"; + @import "../../../dijit/tests/css/dijitTests.css"; + </style> +</head> +<body> + <table> + <tr> + <td colspan=3> + <h1 class="testTitle">Dijit TitlePane Test</h1> + </td> + </tr> + <tr> + <td width="20%"></td> + <td> + <div dojoType="dijit.TitlePane" title="digg" style="width: 300px;"> + Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque + iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing + orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus + pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum... + Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque + nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. + + <a href="http://cometdaily.com">cometdaily.com</a> + </div> + + <div dojoType="dijit.TitlePane" title="Article 1" style="width: 300px;"> + Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque + iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing + orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus + pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum... + Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque + nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. + + <a href="http://dojotoolkit.org">dojotoolkit.org</a> + </div> + </td> + <td width="20%"></td> + </tr> + </table> +</body> +</html> |