Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added version 0.6

  • Loading branch information...
commit fd9f99cc0bc3e6c3de4e9eb672603472143be778 1 parent 16f7f48
@tmpvar authored
Showing with 11,156 additions and 0 deletions.
  1. +30 −0 LICENSE.txt
  2. +1 −0  USAGE.txt
  3. +3 −0  VERSION.txt
  4. +54 −0 front/config/config-blerby-core.xml
  5. +54 −0 front/config/config-phpunit.xml
  6. +57 −0 front/config/config-simpletest.xml
  7. +57 −0 front/config/config.xml
  8. BIN  front/www/Images/arrow_refresh.gif
  9. BIN  front/www/Images/blerbytestrunner.gif
  10. BIN  front/www/Images/error.gif
  11. BIN  front/www/Images/loading.gif
  12. BIN  front/www/Images/pass.gif
  13. BIN  front/www/Images/treeview/file-old.gif
  14. BIN  front/www/Images/treeview/file.gif
  15. BIN  front/www/Images/treeview/folder-closed.gif
  16. BIN  front/www/Images/treeview/folder.gif
  17. BIN  front/www/Images/treeview/treeview-default-line.gif
  18. +801 −0 front/www/Script/jquery.btr.js
  19. +150 −0 front/www/Script/jquery.highlightFade.js
  20. +3,549 −0 front/www/Script/jquery.js
  21. +75 −0 front/www/Script/jquery.timer.js
  22. +251 −0 front/www/Script/jquery.treeview.js
  23. +256 −0 front/www/Script/md5.js
  24. +195 −0 front/www/Style/main.css
  25. +116 −0 front/www/detect.php
  26. +142 −0 front/www/index.php
  27. +92 −0 front/www/runner.php
  28. +259 −0 front/www/sandbox.php
  29. +159 −0 library/Blerby/TestRunner/Config.php
  30. +106 −0 library/Blerby/TestRunner/Connector.php
  31. +182 −0 library/Blerby/TestRunner/Connector/Dependency.php
  32. +156 −0 library/Blerby/TestRunner/Connector/OneToOne.php
  33. +125 −0 library/Blerby/TestRunner/Filter.php
  34. +99 −0 library/Blerby/TestRunner/Filter/Directory.php
  35. +104 −0 library/Blerby/TestRunner/Filter/Extension.php
  36. +98 −0 library/Blerby/TestRunner/Filter/File.php
  37. +220 −0 library/Blerby/TestRunner/Init.php
  38. +142 −0 library/Blerby/TestRunner/Reporter.php
  39. +91 −0 library/Blerby/TestRunner/Reporter/JSON.php
  40. +108 −0 library/Blerby/TestRunner/Result.php
  41. +222 −0 library/Blerby/TestRunner/Runner.php
  42. +234 −0 library/Blerby/TestRunner/Runner/PHPUnit.php
  43. +238 −0 library/Blerby/TestRunner/Runner/SimpleTest.php
  44. +247 −0 library/Blerby/TestRunner/Runner/SimpleTest/Reporter.php
  45. +275 −0 library/Blerby/TestRunner/Scanner.php
  46. +206 −0 library/Blerby/TestRunner/Scanner/File.php
  47. +158 −0 library/Blerby/TestRunner/Scanner/File/ModTime.php
  48. +112 −0 library/Blerby/TestRunner/Scanner/Manual.php
  49. +83 −0 library/Blerby/TestRunner/ServiceLocator.php
  50. +85 −0 library/Blerby/TestRunner/Status.php
  51. +49 −0 library/Blerby/TestRunner/Util.php
  52. +107 −0 sample/PHPUnit/BowlingGame.php
  53. +112 −0 sample/PHPUnit/BowlingGameSpec.php
  54. +110 −0 sample/PHPUnit/BowlingGameTest.php
  55. +77 −0 sample/SimpleTest/adapter_test.php
  56. +10 −0 sample/SimpleTest/bad_test_suite.php
  57. +51 −0 sample/SimpleTest/collector_test.php
  58. +40 −0 sample/SimpleTest/command_line_test.php
  59. +97 −0 sample/SimpleTest/compatibility_test.php
  60. +88 −0 sample/SimpleTest/dumper_test.php
  61. +300 −0 sample/SimpleTest/errors_test.php
  62. +245 −0 sample/SimpleTest/expectation_test.php
  63. 0  README → sample/SimpleTest/support/collector/collectable.1
  64. 0  sample/SimpleTest/support/collector/collectable.2
  65. +3 −0  sample/SimpleTest/support/empty_test_file.php
  66. +1 −0  sample/SimpleTest/support/latin1_sample
  67. +15 −0 sample/SimpleTest/support/spl_examples.php
  68. +1 −0  sample/SimpleTest/support/supplementary_upload_sample.txt
  69. +7 −0 sample/SimpleTest/support/test1.php
  70. +1 −0  sample/SimpleTest/support/upload_sample.txt
  71. +8 −0 sample/SimpleTest/test_with_parse_error.php
  72. +55 −0 sample/SimpleTest/unit_tester_test.php
  73. +187 −0 sample/SimpleTest/xml_test.php
View
30 LICENSE.txt
@@ -0,0 +1,30 @@
+Software License Agreement (BSD License)
+
+Copyright (c) 2006, Sproutware
+All rights reserved.
+
+Redistribution and use of this software 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.
+
+* Neither the name of Sproutware nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Sproutware.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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.
View
1  USAGE.txt
@@ -0,0 +1 @@
+please see: http://blerby.com/projects/testrunner/ for documentation
View
3  VERSION.txt
@@ -0,0 +1,3 @@
+Version 0.6
+
+Please see http://www.blerby.com/project/testrunner/changelog for release details.
View
54 front/config/config-blerby-core.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<config>
+ <includePaths>
+ <path>/var/www/localhost/htdocs/Blerby/library/</path>
+ </includePaths>
+ <dependencyCache>
+ <file>/var/www/localhost/htdocs/btest/front/cache/resolvedDependency.cache</file>
+ </dependencyCache>
+ <scanners>
+ <filters>
+ <filter>
+ <type>Extension</type>
+ <options>
+ <extensions>.php,.php5,.inc</extensions>
+ </options>
+ </filter>
+ </filters>
+ <scanner>
+ <type>File_ModTime</type>
+ <options>
+ <name>test</name>
+ <path>/var/www/localhost/htdocs/Blerby/test/library</path>
+ <cache>
+ <path>/var/www/localhost/htdocs/btest/front/cache</path>
+ </cache>
+ </options>
+ <connectors>
+ <connector>
+ <type>Dependency</type>
+ <options>
+ <pathToCode>/var/www/localhost/htdocs/Blerby/library/Blerby/</pathToCode>
+ </options>
+ </connector>
+ </connectors>
+ </scanner>
+ </scanners>
+ <runner>
+ <type>PHPUnit</type>
+ <options>
+ <suite>
+ <path>/usr/share/php5/PHPUnit</path>
+ <includes>
+ <file>Framework.php</file>
+ </includes>
+ </suite>
+ </options>
+ <reporters>
+ <reporter>
+ <type>JSON</type>
+ <options></options>
+ </reporter>
+ </reporters>
+ </runner>
+</config>
View
54 front/config/config-phpunit.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<config>
+ <includePaths>
+ <path>../sample/PHPUnit/</path>
+ </includePaths>
+ <dependencyCache>
+ <file>../cache/resolvedDependency.cache</file>
+ </dependencyCache>
+ <scanners>
+ <filters>
+ <filter>
+ <type>Extension</type>
+ <options>
+ <extensions>Test.php</extensions>
+ </options>
+ </filter>
+ </filters>
+ <scanner>
+ <type>File_ModTime</type>
+ <options>
+ <name>test</name>
+ <path>../sample/PHPUnit/</path>
+ <cache>
+ <path>../cache</path>
+ </cache>
+ </options>
+ <connectors>
+ <connector>
+ <type>Dependency</type>
+ <options>
+ <pathToCode>../sample/PHPUnit/</pathToCode>
+ </options>
+ </connector>
+ </connectors>
+ </scanner>
+ </scanners>
+ <runner>
+ <type>PHPUnit</type>
+ <options>
+ <suite>
+ <path></path>
+ <includes>
+ <file>PHPUnit/Framework.php</file>
+ </includes>
+ </suite>
+ </options>
+ <reporters>
+ <reporter>
+ <type>JSON</type>
+ <options></options>
+ </reporter>
+ </reporters>
+ </runner>
+</config>
View
57 front/config/config-simpletest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<config>
+ <includePaths>
+ <path>../sample/SimpleTest/</path>
+ </includePaths>
+ <dependencyCache>
+ <file>../cache/resolvedDependency.cache</file>
+ </dependencyCache>
+ <scanners>
+ <filters>
+ <filter>
+ <type>Extension</type>
+ <options>
+ <extensions>_test.php</extensions>
+ </options>
+ </filter>
+ </filters>
+ <scanner>
+ <type>File_ModTime</type>
+ <options>
+ <name>test</name>
+ <path>../sample/SimpleTest/</path>
+ <cache>
+ <path>../cache</path>
+ </cache>
+ </options>
+ <connectors>
+ <connector>
+ <type>Dependency</type>
+ <options>
+ <pathToCode>../sample/SimpleTest/</pathToCode>
+ </options>
+ </connector>
+ </connectors>
+ </scanner>
+ </scanners>
+ <runner>
+ <type>SimpleTest</type>
+ <options>
+ <suite>
+ <path>simpletest</path>
+ <includes>
+ <file>simpletest/simpletest.php</file>
+ <file>simpletest/test_case.php</file>
+ <file>simpletest/autorun.php</file>
+ <file>simpletest/unit_tester.php</file>
+ </includes>
+ </suite>
+ </options>
+ <reporters>
+ <reporter>
+ <type>JSON</type>
+ <options></options>
+ </reporter>
+ </reporters>
+ </runner>
+</config>
View
57 front/config/config.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<config>
+ <includePaths>
+ <path>../sample/SimpleTest/</path>
+ </includePaths>
+ <dependencyCache>
+ <file>../cache/resolvedDependency.cache</file>
+ </dependencyCache>
+ <scanners>
+ <filters>
+ <filter>
+ <type>Extension</type>
+ <options>
+ <extensions>_test.php</extensions>
+ </options>
+ </filter>
+ </filters>
+ <scanner>
+ <type>File_ModTime</type>
+ <options>
+ <name>test</name>
+ <path>../sample/SimpleTest/</path>
+ <cache>
+ <path>../cache</path>
+ </cache>
+ </options>
+ <connectors>
+ <connector>
+ <type>Dependency</type>
+ <options>
+ <pathToCode>../sample/SimpleTest/</pathToCode>
+ </options>
+ </connector>
+ </connectors>
+ </scanner>
+ </scanners>
+ <runner>
+ <type>SimpleTest</type>
+ <options>
+ <suite>
+ <path>simpletest</path>
+ <includes>
+ <file>simpletest/simpletest.php</file>
+ <file>simpletest/test_case.php</file>
+ <file>simpletest/autorun.php</file>
+ <file>simpletest/unit_tester.php</file>
+ </includes>
+ </suite>
+ </options>
+ <reporters>
+ <reporter>
+ <type>JSON</type>
+ <options></options>
+ </reporter>
+ </reporters>
+ </runner>
+</config>
View
BIN  front/www/Images/arrow_refresh.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/blerbytestrunner.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/error.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/loading.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/pass.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/treeview/file-old.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/treeview/file.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/treeview/folder-closed.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/treeview/folder.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  front/www/Images/treeview/treeview-default-line.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
801 front/www/Script/jquery.btr.js
@@ -0,0 +1,801 @@
+/*
+ * Blerby TestRunner
+ *
+ * Manages display/events/ajax for running tests
+ *
+ * Note: this is only a partial jQuery extension (mostly for looks)
+ *
+ * @author Elijah Insua <tmpvar@gmail.com>
+ * @link http://www.blerby.com/project/testrunner/
+ * @version #0.6#
+ */
+
+jQuery.btr = function(settings)
+{
+ // ** Currently running a test **
+ this.isRunning = false;
+ this.pendingRun = false;
+
+ // ** Results **
+ this.totalPasses = 0;
+ this.totalFailure = 0;
+ this.totalError = 0;
+ this.totalTests = 0;
+ this.totalSkipped = 0;
+
+ // ** Test Results **
+ this.oTests = new Object();
+
+ // ** Default Settings **
+ this.settings = jQuery.extend(
+ {
+ detectTimeout : 2000,
+ runnerTimeout : 1000,
+ displayTotalPassed : "#totalPassed",
+ displayTotalFailed : "#totalFailed",
+ displayTotalError : "#totalError",
+ displayTotalTests : "#totalTests",
+ displayTotalSkipped : "#totalSkipped",
+ displayPercentSuccess : "#percentSuccess",
+ filesToRun : 5
+ }, settings
+ );
+
+ // ** Pending test storage **
+ this.aPendingTests = new Array();
+
+ // ** Add a test to the pending queue if not already included **
+ this.queueTest = function(file)
+ {
+ // ** Search existing
+ var fileExitsInQueue = false;
+ for (i in this.aPendingTests)
+ {
+ if (this.aPendingTests[i] == file) {
+ fileExitsInQueue = true;
+ }
+ }
+
+ // ** File doesnt exist, so add it **
+ if (!fileExitsInQueue && file != undefined) {
+ this.aPendingTests.push(file);
+ }
+ }
+
+ // ** Update all status texts **
+ this.status = function(text)
+ {
+
+
+ text = (jQuery(text).text()) ? jQuery(text).text() : text
+
+ document.title = "BTR: " + text;
+ jQuery("#currentFileDisplay").html(text);
+ }
+
+ // ** Reset BTR's front/backend caches **
+ this.reset = function()
+ {
+ // ** Clear the serverside cache **
+ // TODO: implement cache clearing
+ var _self = this;
+ this.status("Clearing caches...");
+ jQuery.ajax({type:"GET",url:btrUrlPath + "sandbox.php",data:{action:'reset'},dataType:"json",
+ complete:
+ function(xhr, status)
+ {
+ if (status == 'success') {
+ _self.status("<b style='color:green'>Caches Cleared<b>");
+ } else {
+ _self.status("<b style='color:red'>There was a problem clearing the caches</b>");
+ }
+ }
+ });
+
+ // ** Clear the pending tests **
+ delete this.aPendingTests;
+ this.aPendingTests = new Array();
+
+ // ** Clear existing test results **
+ delete this.oTests;
+ this.oTests = new Object();
+
+ // ** Reset Display **
+ this.calculateStatistics();
+ }
+
+ // ** Start the execution **
+ this.start = function()
+ {
+ // ** Prepare a variable for the nested closures below **
+ var _self = this;
+
+ // ** Clean the caches **
+ this.reset();
+
+ // ** Create detection event **
+ jQuery(this).bind("doDetect",
+ function (e, name, value)
+ {
+ if (!_self.isRunning && _self.aPendingTests.length < 1) {
+ _self.status("Detecting...");
+ }
+
+ $.getJSON(btrUrlPath + "sandbox.php", {action:'detect'},
+ function(data)
+ {
+ if (jQuery(data.aChanges).length > 0) {
+ for(k in data.aChanges)
+ {
+ _self.queueTest(data.aChanges[k]['file']);
+ };
+ }
+
+ // ** Manage file deletions **
+ if (jQuery(data.aDeletions).length > 0) {
+ for(k in data.aDeletions)
+ {
+ // ** Attempt to locate a pending test with the same filename **
+ for (i in _self.aPendingTests)
+ {
+ // ** If found, delete from pending tests **
+ if (_self.aPendingTests[i] == data.aDeletions[k]['file']) {
+ delete _self.aPendingTests[i];
+ }
+ }
+ };
+ }
+ }
+ );
+ }
+ )
+
+ // ** Create runner event **
+ jQuery(this).bind("doRunner",
+ function (e, name, value)
+ {
+ // ** Only run if we have tests in queue and not running **
+ if (jQuery(_self.aPendingTests).length > 0 &&
+ !_self.isRunning)
+ {
+ var a = 1;
+
+ // ** Setup params for ajax request below **
+ var params = new Object();
+ params.action = "run";
+ params.aFiles = "";
+
+ // ** Wait until we are done to run again **
+ _self.isRunning = true;
+
+
+ var fileCount = 0;
+ // ** Include X tests, not overrunning the boundries of aPendingTests **
+ while (a <= _self.settings.filesToRun && jQuery(_self.aPendingTests).length )
+ {
+ // ** Separate with semi-colons **
+ if (a > 1) {
+ params.aFiles = params.aFiles + ";";
+ }
+
+ // ** Add filename to string **
+ var tmpFile = _self.aPendingTests.shift();
+ params.aFiles = params.aFiles + tmpFile;
+ a++;
+ fileCount++;
+
+ // ** Notify the display of tests that are being run **
+ var tmpHash = this.getHashByFilename(tmpFile);
+ if (tmpHash != false) {
+ jQuery("#" + tmpHash + " .icon").attr("src","Images/loading.gif");
+ }
+
+ }
+
+ // ** Ensure that the calculated file string is not empty **
+ if (params.aFiles != "") {
+
+ // ** Update display -> this is actually kind of annoying? **
+ _self.status("Running " + fileCount + " of " + (jQuery(_self.aPendingTests).length + fileCount) + " queued files.");
+
+ // ** Run calculated tests **
+ jQuery.getJSON(btrUrlPath + "sandbox.php", params,
+ function(data)
+ {
+ // ** Convert results into html boxes and such **
+ _self.processRunnerResults(data);
+ }
+ );
+ }
+ }
+
+ // ** Set the runner to run at a regular interval **
+ setTimeout(
+ function()
+ {
+ jQuery(_self).trigger("doRunner");
+ }, this.settings.runnerTimeout
+ );
+
+ }
+ );
+
+ // ** If automatic scanning is allowed **
+ if (this.settings.detectTimeout > 0) {
+
+ // ** Kick off a detection process **
+ jQuery(this).trigger("doDetect");
+
+ // ** Set the detector to run at a regular interval **
+ setInterval(
+ function()
+ {
+ jQuery(_self).trigger("doDetect");
+ }, this.settings.detectTimeout
+ );
+
+ // ** Set the runner to run at a regular interval **
+ setTimeout(
+ function()
+ {
+ jQuery(_self).trigger("doRunner");
+ }, this.settings.runnerTimeout
+ );
+ }
+ };
+
+ // ** Get a failing file's has by its filename **
+ this.getHashByFilename = function(filename)
+ {
+ for (i in this.oTests)
+ {
+ if (this.oTests[i]['file'] == filename) {
+ return this.oTests[i]['hash'];
+ }
+ }
+ return false;
+ }
+
+ // ** Post processing of results **
+ this.processRunnerResults = function(data)
+ {
+ // ** Add file results to our oTests **
+ for (k in data)
+ {
+ // ** Ensure we have a valid result before we add it **
+ if (data[k] != undefined && data[k]['hash']) {
+
+ this.addFileResult(data[k]['hash'],data);
+ }
+ }
+
+ this.calculateStatistics();
+ }
+
+ // ** Update the html statistics **
+ this.calculateStatistics = function()
+ {
+ // ** Reset counts **
+ this.totalPasses = 0;
+ this.totalFailure = 0;
+ this.totalError = 0;
+ this.totalTests = 0;
+ this.totalSkipped = 0;
+
+ // ** Calculate results **
+ for(k in this.oTests)
+ {
+ var currentTest = this.oTests[k];
+ this.totalPasses += currentTest.countPasses();
+ this.totalFailure += Number(currentTest.totalFailure);
+ this.totalError += Number(currentTest.totalError);
+ this.totalTests += Number(currentTest.totalTests);
+ this.totalSkipped += Number(currentTest.totalSkipped);
+ }
+
+ // ** Calculate percentage of success **
+ var p = null;
+ p = (this.totalPasses && this.totalTests) ?
+ (this.totalPasses / this.totalTests) * 100 :
+ 0;
+
+ // ** Force percentage to be atleast 0% **
+ p = (p<0) ? 0 : p;
+
+ // ** Display percentage **
+ jQuery(this.settings.displayPercentSuccess).text(Math.round(p));
+
+ // ** Subtract skipped from passes **
+ this.totalPasses = Number(this.totalPasses) - Number(this.totalSkipped);
+
+ // ** Ensure total passes never goes negative **
+ if (this.totalPasses < 0) {
+ this.totalPasses = 0;
+ }
+
+ // ** Update the summary amounts **
+ jQuery(this.settings.displayTotalPassed).text(this.totalPasses);
+ jQuery(this.settings.displayTotalFailed).text(this.totalFailure);
+ jQuery(this.settings.displayTotalError).text(this.totalError);
+ jQuery(this.settings.displayTotalTests).text(this.totalTests);
+ jQuery(this.settings.displayTotalSkipped).text(this.totalSkipped);
+
+ this.isRunning = false;
+ }
+
+ // ** Add a file result box if appropriate **
+ this.addFileResult = function(hash, jsonObj)
+ {
+ // ** Create a new file entry **
+ if (this.oTests[hash] == undefined) {
+ this.oTests[hash] = new jQuery.btr.file(hash, this);
+ }
+
+ // ** Ensure that file entry exists **
+ if (this.oTests[hash] != undefined) {
+
+ // ** Setup the test file **
+ var testFile = this.oTests[hash];
+
+ var id = 0;
+
+ testFile.processResults(hash,jsonObj[hash]);
+ return;
+ if (jQuery(jsonObj[hash]['results']).length > 0)
+ {
+ for (result in jsonObj[hash]['results'])
+ {
+ if (result.action != undefined &&
+ result.action != "delete")
+ {
+ // ** Single files can have multiple results, dont overwrite the old **
+ id++;
+
+ // ** Process the incomming results **
+ testFile.processResults(id,jsonObj[hash]);
+ }
+ }
+ }
+ }
+ }
+}
+
+// ** Blerby Test Runner File Object **
+jQuery.btr.file = function(hash, runner)
+{
+ this.hash = hash;
+ this.runner = runner;
+ this.file = "";
+ this.oResults = new Object();
+
+ this.hasRun = true;
+
+ this.totalTests = 0;
+ this.totalPasses = 0;
+ this.totalSkipped = 0;
+ this.totalFailure = 0;
+ this.totalError = 0;
+ this.totalInvalid = 0;
+
+ this.box = null;
+
+ // ** Kill off fixed result boxen **
+ this.cleanResults = function(o, jsonObj)
+ {
+ // loop through and kill off the results
+ // add results to the box
+
+ var a = 0;
+ var resultContainer = jQuery(o).children();
+ for (a=0; a<resultContainer.length; a++)
+ {
+ var found = false;
+ for(k in jsonObj.results)
+ {
+ if (jsonObj.hash + "_" + jsonObj.results[k]['line'] == resultContainer[a]['id']) {
+ found = true;
+ }
+ }
+
+ // delete expired results
+ if (!found) {
+ this.deleteResult(resultContainer[a]);
+ delete this.oResults[resultContainer[a]['id']]
+ }
+ }
+ }
+
+ // ** Remove a file result box **
+ this.deleteResult = function(jqueryObj)
+ {
+ jQuery(jqueryObj).highlightFade({color:'#ffffc8',speed:200})
+ jQuery(jqueryObj).fadeOut(200,
+ function ()
+ {
+ jQuery(this).remove();
+ }
+ );
+ delete this.oResults[jqueryObj.id];
+ }
+
+ this.processResults = function(hash, jsonObj)
+ {
+ // ** Track incomming results from the server **
+ this.totalTests = Number(jsonObj.info.count);
+ this.totalFailure = Number(jsonObj.info.failureCount);
+ this.totalError = Number(jsonObj.info.errorCount);
+ this.totalSkipped = Number(jsonObj.info.skippedCount);
+
+ // ** Track what file this is **
+ this.file = jsonObj.info.file;
+
+ // ** Track whether or not we found failures **
+ var found = false
+
+ // ** We have results, which means there was a problem **
+ if (jQuery(jsonObj.results).length > 0) {
+
+ for(k in jsonObj.results)
+ {
+ if (jQuery(jsonObj.results[k]).length > 0 &&
+ jsonObj.results[k]['status'] != 'pass')
+ {
+ // ** Add a result **
+ this.oResults[this.hash + "_" + jsonObj.results[k]['line']] = new jQuery.btr.file.result(this.hash + "_" + jsonObj.results[k]['line'], jsonObj.results[k]);
+
+ // ** add to end of re-test queue **
+ this.runner.queueTest(jsonObj.results[k]['file']);
+
+ // ** Found a failure in this result set **
+ found = true;
+ }
+
+ var resultContainer = jQuery("#" + this.hash).find(".resultContainer");
+ this.cleanResults(resultContainer,jsonObj);
+
+ }
+ }
+
+ // ** We found some sort of problem earlier **
+ if (found == true && jQuery(this.oResults).length > 0) {
+ jQuery("#" + this.hash + " .icon").attr("src","Images/error.gif");
+ // add file box if non-existant
+ var boxResult = jQuery("#" + this.hash);
+ if (!boxResult.length) {
+ boxResult = jQuery("#fileTemplate").clone();
+ jQuery(boxResult).attr("id",this.hash);
+
+ jQuery("#fileContainer").append(boxResult);
+ jQuery(boxResult).find(".title").html(jsonObj['info']['file']);
+ jQuery(boxResult).fadeIn(200,
+ function()
+ {
+ jQuery(this).highlightFade({color:'#ffffc8',speed:200})
+ }
+ );
+ }
+
+
+ // add results to the box
+ resultContainer = jQuery(boxResult).find(".resultContainer");
+ for(k in this.oResults)
+ {
+ // add box
+ if (this.oResults[k]['status'] != 'pass') {
+ this.oResults[k].addBox(resultContainer);
+ }
+ }
+
+ // ** No problems, procede with removing the error box **
+ } else {
+ this.removeBox();
+ }
+ };
+
+ // ** Remove results **
+ this.remove = function()
+ {
+ delete this.oResults;
+
+ // ** Remain consistent for future failures **
+ this.oResults = new Object();
+ };
+
+ // ** Remove file box **
+ this.removeBox = function()
+ {
+ delete this.runner.aPendingTests[this.hash];
+ this.remove();
+
+ // ** Remove html box if it exists **
+ if (jQuery("#" + this.hash + " .icon").length > 0) {
+ jQuery("#" + this.hash + " .icon").attr("src","Images/pass.gif");
+ jQuery("#" + this.hash).highlightFade({color:'#ffffc8', complete:
+ function()
+ {
+ // ** dodges issue where runner timout is less than 700 **
+ jQuery("#" + this.hash + " .icon").removeClass("icon");
+
+ // ** Fadeout and remove **
+ jQuery(this).fadeOut(700,
+ function()
+ {
+ jQuery(this).remove();
+ }
+ );
+ }
+ });
+ }
+ }
+
+ // ** Count the number of passes in this file **
+ this.countPasses = function()
+ {
+ // ** Get the total from the total tests **
+ var ret = this.totalTests - (this.totalFailure + this.totalError);
+ return Number(ret);
+ };
+}
+
+// ** File result helper **
+jQuery.btr.file.result = function(hash,jsonObj)
+{
+ this.status = jsonObj.status;
+ this.line = jsonObj.line;
+ this.message = jsonObj.message;
+ this.count = jsonObj.count;
+ this.file = jsonObj.file;
+ this.hash = hash;
+ this.jsonObj = jsonObj;
+
+ // ** Add a result box **
+ this.addBox = function(o)
+ {
+ // ** Display Failure **
+ var boxResult = jQuery(o).find("#" + this.hash);
+ if (!boxResult.length) {
+ boxResult = jQuery("#resultTemplate").clone();
+ jQuery(boxResult).attr("id",this.hash);
+
+ jQuery(o).append(boxResult)
+ jQuery(boxResult).fadeIn(200,
+ function()
+ {
+ jQuery(this).highlightFade({color:'#ffffc8',speed:200})
+ }
+ );
+ }
+ var actualFile = "\nFile: " + this.jsonObj.file + "<br />";
+ var myLine = (this.line != undefined) ? "Line: " + this.line : '';
+ jQuery(boxResult).find(".line").html(actualFile + myLine);
+
+ jQuery(boxResult).find(".message").html(this.message);
+ }
+
+ // ** Remove a result box **
+ this.removeBox = function()
+ {
+ var boxResult = jQuery(o).find("#" + this.hash);
+ $(boxResult).remove();
+ }
+}
+
+// ** BTR Test menu builder/helper **
+jQuery.btr.menu = function(settings)
+{
+ var params = {action:'available'}
+
+ this.oStructure = new Object();
+
+ // ** Default Settings **
+ this.settings = jQuery.extend(
+ {
+ id : "testMenu",
+ runnerName: 'BTR',
+ runner: null
+ }, settings
+ );
+
+ var _self = this;
+
+ jQuery.getJSON(btrUrlPath + "sandbox.php", params,
+ function(data)
+ {
+
+
+ var menu = _self.createMenu(_self.settings.id, data);
+
+ jQuery('*').bind('click',_self.handleClick);
+
+ jQuery("#" + _self.settings.id).html(menu);
+
+
+ jQuery("#" + _self.settings.id).treeview({
+ collapsed: true,
+ animated: "fast",
+ prerendered: false,
+ persist: "location",
+ unique:false
+ });
+
+ jQuery("div.popup").show('fast');
+ jQuery("#" + _self.settings.id).find("a").remove('click').click(
+ function (event)
+ {
+ jQuery.btr.queueTests(this,_self.settings.runner);
+ event.stopPropagation()
+ window.location = jQuery(this).attr('href');
+ return false;
+ }
+ );
+
+
+ }
+ );
+
+ // ** Handle click events, for hiding the popup **
+ this.handleClick = function(e,v,a)
+ {
+ var tmpNode = this;
+ var found = false;
+
+ // ** Calculate whether the click happened inside of the popup **
+ if (tmpNode.tagName != "HTML" && tmpNode.tagName != "BODY") {
+ while ((tmpNode = jQuery(tmpNode).parent())) {
+
+ if (jQuery(tmpNode).hasClass('popup')) {
+ found = true;
+ break;
+ } else if (tmpNode[0]['tagName'] == "BODY") {
+ break;
+ }
+ }
+ }
+
+ if (found == false) {
+ _self.destroyMenu(_self);
+
+ // ** Do not propigate click if we know its inside of the popup **
+ } else {
+ e.stopPropagation();
+ return false;
+ }
+
+ }
+
+ // ** Remove the menu, unbind popup hiding events **
+ this.destroyMenu = function(source)
+ {
+ jQuery(".popup").hide().find("ul").html("");
+ jQuery('*').unbind('click',source.handleClick);
+ }
+
+ // ** Convert a json object into a better structure **
+ this.jsonToStructure = function(o, path, full, partial)
+ {
+ if (!path) { return o; }
+
+ if (o[path] == undefined) {
+ o[path] = new Object();
+
+ o[path]['type'] = 'dir';
+ if (path.indexOf('.') > -1) {
+ o[path]['type'] = 'file';
+ o[path]['full'] = full;
+ }
+
+ o[path]['partial'] = partial;
+ o[path]['name'] = path;
+ }
+
+ return o[path];
+ }
+
+ // ** Convert an object structure into html recursively **
+ this.structureToHtml = function(o)
+ {
+ var ret = "";
+
+ // ** List folders first **
+ for (elem in o)
+ {
+ // ** Skip over unsed params **
+ if (elem == 'type' || elem == 'name' || elem == 'partial') { continue; }
+
+ // ** Create link for queuing tests **
+
+ // ** If directory go recurse **
+ if (o[elem]['type'] == 'dir') {
+ ret += "<li><span class='folder'><a id='path:" + o[elem]['partial'] + "' href='#path:" + o[elem]['partial'] + "'>" + elem + "</a></span>";
+
+ ret += "<ul class='expandable'>";
+ ret += this.structureToHtml(o[elem]);
+ ret += "</ul></li>";
+ }
+ }
+
+ // ** Add Files **
+ for (elem in o)
+ {
+ // ** Skip over unsed params **
+ if (elem == 'type' || elem == 'name' || elem == 'partial') { continue; }
+
+ // ** File **
+ if (o[elem]['type'] != 'dir') {
+ ret += "<li><span class='file'><a id='path:" + o[elem]['partial'] + "' href='#path:" + o[elem]['partial'] + "' rel='" + o[elem]['full'] + "'>" + elem + "</a></span></li>";
+ }
+ }
+ return ret;
+ }
+
+ // ** Create the btr menu from a json object **
+ this.createMenu = function(id, jsonObj)
+ {
+ // ** Create base link + ability to run all tests **
+ var menu = "<li><span class='folder'><a id='path:/'href='#path:/' onmousedown='jQuery.btr.queueTests(this,";
+ menu += this.settings.runnerName + ")'>Available Tests</a></span><ul>";
+
+ for (i in jsonObj)
+ {
+ // ** Shorten the dir to a readable format (long paths especially) **
+ var currentFile = jsonObj[i];
+ for (clean in aCleanPaths)
+ {
+ currentFile = currentFile.replace(aCleanPaths[clean],'');
+ }
+
+ // ** Remove prepended slash if exists **
+ currentFile = currentFile.replace(/^\//,"");
+
+ // ** Split the directory **
+ var aCurrent = currentFile.split("/");
+
+ // ** Create a nested object structure **
+ var oCurrent = this.oStructure;
+ var rebuilt = "";
+ var first = true;
+ for (path in aCurrent)
+ {
+ if (first) {
+ first = false;
+ } else {
+ rebuilt += "/";
+ }
+
+ rebuilt += aCurrent[path];
+
+ oCurrent = this.jsonToStructure(oCurrent,aCurrent[path], jsonObj[i], rebuilt);
+ }
+ }
+
+ // ** Convert nested objects into nested ul/li list **
+ menu += this.structureToHtml(this.oStructure);
+
+
+ menu += "</ul></li><li><hr /><a class='reset' href='javascript:void(0);' onmousedown='" + this.settings.runnerName + ".reset()'> Reset Caches</a></li></ul>";
+ menu += "<li><hr /><a href='http://www.blerby.com/project/testrunner/' target='_blank'>BTR Homepage</a></li></ul>";
+ return menu;
+ }
+}
+
+// ** Queue tests into BTR using the dom as a guide**
+jQuery.btr.queueTests = function(e, ourBTR)
+{
+
+ var aAnchor = jQuery(e).parent().parent().find("a");
+
+ aAnchor.each(
+ function (k,tmpAnchor)
+ {
+ ourBTR.pendingRun = (k+1>=aAnchor.length) ? true : false;
+
+ // ** Locate the rel attr **
+ var rel = jQuery(tmpAnchor).attr('rel');
+
+ // ** Ensure that we only add files to the test queue **
+ if (rel != "" && rel.indexOf('.') > -1) {
+ ourBTR.queueTest(rel);
+ }
+ }
+ );
+}
View
150 front/www/Script/jquery.highlightFade.js
@@ -0,0 +1,150 @@
+/**
+ * jQuery Plugin highlightFade (jquery.offput.ca/highlightFade)
+ * (c) 2006 Blair Mitchelmore (offput.ca) blair@offput.ca
+ */
+/**
+ * This is version 0.7 of my highlightFade plugin. It follows the yellow fade technique of Web 2.0 fame
+ * but expands it to allow any starting colour and allows you to specify the end colour as well.
+ *
+ * For the moment, I'm done with this plug-in. Unless I come upon a really cool feature it should have
+ * this plug-in will only receive updates to ensure future compatibility with jQuery.
+ *
+ * As of now (Aug. 16, 2006) the plugin has been written with the 1.0.1 release of jQuery (rev 249) which
+ * is available from http://jquery.com/src/jquery-1.0.1.js
+ *
+ * A note regarding rgb() syntax: I noticed that most browsers implement rgb syntax as either an integer
+ * (0-255) or percentage (0-100%) value for each field, that is, rgb(i/p,i/p,i/p); however, the W3C
+ * standard clearly defines it as "either three integer values or three percentage values" [http://www.w3.org/TR/CSS21/syndata.html]
+ * which I choose to follow despite the error redundancy of the typical behaviour browsers employ.
+ *
+ * Changelog:
+ *
+ * 0.7:
+ * - Added the awesome custom attribute support written by George Adamson (slightly modified)
+ * - Removed bgColor plugin dependency seeing as attr is customizable now...
+ * 0.6:
+ * - Abstracted getBGColor into its own plugin with optional test and data retrieval functions
+ * - Converted all $ references to jQuery references as John's code seems to be shifting away
+ * from that and I don't want to have to update this for a long time.
+ * 0.5:
+ * - Added simple argument syntax for only specifying start colour of event
+ * - Removed old style argument syntax
+ * - Added 'interval', 'final, and 'end' properties
+ * - Renamed 'color' property to 'start'
+ * - Added second argument to $.highlightFade.getBGColor to bypass the e.highlighting check
+ * 0.4:
+ * - Added rgb(%,%,%) color syntax
+ * 0.3:
+ * - Fixed bug when event was called while parent was also running event corrupting the
+ * the background colour of the child
+ * 0.2:
+ * - Fixed bug where an unspecified onComplete function made the page throw continuous errors
+ * - Fixed bug where multiple events on the same element would speed each subsequent event
+ * 0.1:
+ * - Initial Release
+ *
+ * @author Blair Mitchelmore (blair@offput.ca)
+ * @version 0.5
+ */
+jQuery.fn.highlightFade = function(settings) {
+ var o = (settings && settings.constructor == String) ? {start: settings} : settings || {};
+ var d = jQuery.highlightFade.defaults;
+ var i = o['interval'] || d['interval'];
+ var a = o['attr'] || d['attr'];
+ var ts = {
+ 'linear': function(s,e,t,c) { return parseInt(s+(c/t)*(e-s)); },
+ 'sinusoidal': function(s,e,t,c) { return parseInt(s+Math.sin(((c/t)*90)*(Math.PI/180))*(e-s)); },
+ 'exponential': function(s,e,t,c) { return parseInt(s+(Math.pow(c/t,2))*(e-s)); }
+ };
+ var t = (o['iterator'] && o['iterator'].constructor == Function) ? o['iterator'] : ts[o['iterator']] || ts[d['iterator']] || ts['linear'];
+ if (d['iterator'] && d['iterator'].constructor == Function) t = d['iterator'];
+ return this.each(function() {
+ if (!this.highlighting) this.highlighting = {};
+ var e = (this.highlighting[a]) ? this.highlighting[a].end : jQuery.highlightFade.getBaseValue(this,a) || [255,255,255];
+ var c = jQuery.highlightFade.getRGB(o['start'] || o['colour'] || o['color'] || d['start'] || [255,255,128]);
+ var s = jQuery.speed(o['speed'] || d['speed']);
+ var r = o['final'] || (this.highlighting[a] && this.highlighting[a].orig) ? this.highlighting[a].orig : jQuery.curCSS(this,a);
+ if (o['end'] || d['end']) r = jQuery.highlightFade.asRGBString(e = jQuery.highlightFade.getRGB(o['end'] || d['end']));
+ if (typeof o['final'] != 'undefined') r = o['final'];
+ if (this.highlighting[a] && this.highlighting[a].timer) window.clearInterval(this.highlighting[a].timer);
+ this.highlighting[a] = { steps: ((s.duration) / i), interval: i, currentStep: 0, start: c, end: e, orig: r, attr: a };
+ jQuery.highlightFade(this,a,o['complete'],t);
+ });
+};
+
+jQuery.highlightFade = function(e,a,o,t) {
+ e.highlighting[a].timer = window.setInterval(function() {
+ var newR = t(e.highlighting[a].start[0],e.highlighting[a].end[0],e.highlighting[a].steps,e.highlighting[a].currentStep);
+ var newG = t(e.highlighting[a].start[1],e.highlighting[a].end[1],e.highlighting[a].steps,e.highlighting[a].currentStep);
+ var newB = t(e.highlighting[a].start[2],e.highlighting[a].end[2],e.highlighting[a].steps,e.highlighting[a].currentStep);
+ jQuery(e).css(a,jQuery.highlightFade.asRGBString([newR,newG,newB]));
+ if (e.highlighting[a].currentStep++ >= e.highlighting[a].steps) {
+ jQuery(e).css(a,e.highlighting[a].orig || '');
+ window.clearInterval(e.highlighting[a].timer);
+ e.highlighting[a] = null;
+ if (o && o.constructor == Function) o.call(e);
+ }
+ },e.highlighting[a].interval);
+};
+
+jQuery.highlightFade.defaults = {
+ start: [255,255,128],
+ interval: 50,
+ speed: 400,
+ attr: 'backgroundColor'
+};
+
+jQuery.highlightFade.getRGB = function(c,d) {
+ var result;
+ if (c && c.constructor == Array && c.length == 3) return c;
+ if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))
+ return [parseInt(result[1]),parseInt(result[2]),parseInt(result[3])];
+ else if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))
+ return [parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55];
+ else if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))
+ return [parseInt("0x" + result[1]),parseInt("0x" + result[2]),parseInt("0x" + result[3])];
+ else if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))
+ return [parseInt("0x"+ result[1] + result[1]),parseInt("0x" + result[2] + result[2]),parseInt("0x" + result[3] + result[3])];
+ else
+ return jQuery.highlightFade.checkColorName(c) || d || null;
+};
+
+jQuery.highlightFade.asRGBString = function(a) {
+ return "rgb(" + a.join(",") + ")";
+};
+
+jQuery.highlightFade.getBaseValue = function(e,a,b) {
+ var s, t;
+ b = b || false;
+ t = a = a || jQuery.highlightFade.defaults['attr'];
+ do {
+ s = jQuery(e).css(t || 'backgroundColor');
+ if ((s != '' && s != 'transparent') || (e.tagName.toLowerCase() == "body") || (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end)) break;
+ t = false;
+ } while (e = e.parentNode);
+ if (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end) s = e.highlighting[a].end;
+ if (s == undefined || s == '' || s == 'transparent') s = [255,255,255];
+ return jQuery.highlightFade.getRGB(s);
+};
+
+jQuery.highlightFade.checkColorName = function(c) {
+ if (!c) return null;
+ switch(c.replace(/^\s*|\s*$/g,'').toLowerCase()) {
+ case 'aqua': return [0,255,255];
+ case 'black': return [0,0,0];
+ case 'blue': return [0,0,255];
+ case 'fuchsia': return [255,0,255];
+ case 'gray': return [128,128,128];
+ case 'green': return [0,128,0];
+ case 'lime': return [0,255,0];
+ case 'maroon': return [128,0,0];
+ case 'navy': return [0,0,128];
+ case 'olive': return [128,128,0];
+ case 'purple': return [128,0,128];
+ case 'red': return [255,0,0];
+ case 'silver': return [192,192,192];
+ case 'teal': return [0,128,128];
+ case 'white': return [255,255,255];
+ case 'yellow': return [255,255,0];
+ }
+};
View
3,549 front/www/Script/jquery.js
3,549 additions, 0 deletions not shown
View
75 front/www/Script/jquery.timer.js
@@ -0,0 +1,75 @@
+/*
+ *
+ * jQuery Timer plugin v0.1
+ * Matt Schmidt [http://www.mattptr.net]
+ *
+ * Licensed under the BSD License:
+ * http://mattptr.net/license/license.txt
+ *
+ */
+
+ jQuery.timer = function (interval, callback)
+ {
+ /**
+ *
+ * timer() provides a cleaner way to handle intervals
+ *
+ * @usage
+ * $.timer(interval, callback);
+ *
+ *
+ * @example
+ * $.timer(1000, function (timer) {
+ * alert("hello");
+ * timer.stop();
+ * });
+ * @desc Show an alert box after 1 second and stop
+ *
+ * @example
+ * var second = false;
+ * $.timer(1000, function (timer) {
+ * if (!second) {
+ * alert('First time!');
+ * second = true;
+ * timer.reset(3000);
+ * }
+ * else {
+ * alert('Second time');
+ * timer.stop();
+ * }
+ * });
+ * @desc Show an alert box after 1 second and show another after 3 seconds
+ *
+ *
+ */
+
+ this.interval = interval || 100;
+
+ if (!callback)
+ return false;
+
+ _timer = function (interval, callback) {
+ this.stop = function () {
+ clearInterval(self.id);
+ };
+
+ this.internalCallback = function () {
+ callback(self);
+ };
+
+ this.reset = function (val) {
+ if (self.id)
+ clearInterval(self.id);
+
+ val = val || 100;
+ this.id = setInterval(this.internalCallback, val);
+ };
+
+ this.interval = interval;
+ this.id = setInterval(this.internalCallback, this.interval);
+
+ var self = this;
+ };
+
+ return new _timer(interval, callback);
+ };
View
251 front/www/Script/jquery.treeview.js
@@ -0,0 +1,251 @@
+/*
+ * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
+ * http://docs.jquery.com/Plugins/Treeview
+ *
+ * Copyright (c) 2007 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+
+ $.extend($.fn, {
+ swapClass: function(c1, c2) {
+ var c1Elements = this.filter('.' + c1);
+ this.filter('.' + c2).removeClass(c2).addClass(c1);
+ c1Elements.removeClass(c1).addClass(c2);
+ return this;
+ },
+ replaceClass: function(c1, c2) {
+ return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
+ },
+ hoverClass: function(className) {
+ className = className || "hover";
+ return this.hover(function() {
+ $(this).addClass(className);
+ }, function() {
+ $(this).removeClass(className);
+ });
+ },
+ heightToggle: function(animated, callback) {
+ animated ?
+ this.animate({ height: "toggle" }, animated, callback) :
+ this.each(function(){
+ jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+ if(callback)
+ callback.apply(this, arguments);
+ });
+ },
+ heightHide: function(animated, callback) {
+ if (animated) {
+ this.animate({ height: "hide" }, animated, callback);
+ } else {
+ this.hide();
+ if (callback)
+ this.each(callback);
+ }
+ },
+ prepareBranches: function(settings) {
+ if (!settings.prerendered) {
+ // mark last tree items
+ this.filter(":last-child:not(ul)").addClass(CLASSES.last);
+ // collapse whole tree, or only those marked as closed, anyway except those marked as open
+ this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
+ }
+ // return all items with sublists
+ return this.filter(":has(>ul)");
+ },
+ applyClasses: function(settings, toggler) {
+ this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
+ toggler.apply($(this).next());
+ }).add( $("a", this) ).hoverClass();
+
+ if (!settings.prerendered) {
+ // handle closed ones first
+ this.filter(":has(>ul:hidden)")
+ .addClass(CLASSES.expandable)
+ .replaceClass(CLASSES.last, CLASSES.lastExpandable);
+
+ // handle open ones
+ this.not(":has(>ul:hidden)")
+ .addClass(CLASSES.collapsable)
+ .replaceClass(CLASSES.last, CLASSES.lastCollapsable);
+
+ // create hitarea
+ this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
+ var classes = "";
+ $.each($(this).parent().attr("class").split(" "), function() {
+ classes += this + "-hitarea ";
+ });
+ $(this).addClass( classes );
+ });
+ }
+
+ // apply event to hitarea
+ this.find("div." + CLASSES.hitarea).click( toggler );
+ },
+ treeview: function(settings) {
+
+ settings = $.extend({
+ cookieId: "treeview"
+ }, settings);
+
+ if (settings.add) {
+ return this.trigger("add", [settings.add]);
+ }
+
+ if ( settings.toggle ) {
+ var callback = settings.toggle;
+ settings.toggle = function() {
+ return callback.apply($(this).parent()[0], arguments);
+ };
+ }
+
+ // factory for treecontroller
+ function treeController(tree, control) {
+ // factory for click handlers
+ function handler(filter) {
+ return function() {
+ // reuse toggle event handler, applying the elements to toggle
+ // start searching for all hitareas
+ toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
+ // for plain toggle, no filter is provided, otherwise we need to check the parent element
+ return filter ? $(this).parent("." + filter).length : true;
+ }) );
+ return false;
+ };
+ }
+ // click on first element to collapse tree
+ $("a:eq(0)", control).click( handler(CLASSES.collapsable) );
+ // click on second to expand tree
+ $("a:eq(1)", control).click( handler(CLASSES.expandable) );
+ // click on third to toggle tree
+ $("a:eq(2)", control).click( handler() );
+ }
+
+ // handle toggle event
+ function toggler() {
+ $(this)
+ .parent()
+ // swap classes for hitarea
+ .find(">.hitarea")
+ .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+ .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+ .end()
+ // swap classes for parent li
+ .swapClass( CLASSES.collapsable, CLASSES.expandable )
+ .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+ // find child lists
+ .find( ">ul" )
+ // toggle them
+ .heightToggle( settings.animated, settings.toggle );
+ if ( settings.unique ) {
+ $(this).parent()
+ .siblings()
+ // swap classes for hitarea
+ .find(">.hitarea")
+ .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
+ .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
+ .end()
+ .replaceClass( CLASSES.collapsable, CLASSES.expandable )
+ .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
+ .find( ">ul" )
+ .heightHide( settings.animated, settings.toggle );
+ }
+ }
+
+ function serialize() {
+ function binary(arg) {
+ return arg ? 1 : 0;
+ }
+ var data = [];
+ branches.each(function(i, e) {
+ data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
+ });
+ $.cookie(settings.cookieId, data.join("") );
+ }
+
+ function deserialize() {
+ var stored = $.cookie(settings.cookieId);
+ if ( stored ) {
+ var data = stored.split("");
+ branches.each(function(i, e) {
+ $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
+ });
+ }
+ }
+
+ // add treeview class to activate styles
+ this.addClass("treeview");
+
+ // prepare branches and find all tree items with child lists
+ var branches = this.find("li").prepareBranches(settings);
+
+ switch(settings.persist) {
+ case "cookie":
+ var toggleCallback = settings.toggle;
+ settings.toggle = function() {
+ serialize();
+ if (toggleCallback) {
+ toggleCallback.apply(this, arguments);
+ }
+ };
+ deserialize();
+ break;
+ case "location":
+ var current = this.find("a").filter(function() { return this.href.toLowerCase() == location.href.toLowerCase(); });
+ if ( current.length ) {
+ current.addClass("selected").parents("ul, li").add( current.next() ).show();
+ }
+ break;
+ }
+
+ branches.applyClasses(settings, toggler);
+
+ // if control option is set, create the treecontroller and show it
+ if ( settings.control ) {
+ treeController(this, settings.control);
+ $(settings.control).show();
+ }
+
+ return this.bind("add", function(event, branches) {
+ $(branches).prev()
+ .removeClass(CLASSES.last)
+ .removeClass(CLASSES.lastCollapsable)
+ .removeClass(CLASSES.lastExpandable)
+ .find(">.hitarea")
+ .removeClass(CLASSES.lastCollapsableHitarea)
+ .removeClass(CLASSES.lastExpandableHitarea);
+ $(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
+ });
+ }
+ });
+
+ // classes used by the plugin
+ // need to be styled via external stylesheet, see first example
+ var CLASSES = $.fn.treeview.classes = {
+ open: "open",
+ closed: "closed",
+ expandable: "expandable",
+ expandableHitarea: "expandable-hitarea",
+ lastExpandableHitarea: "lastExpandable-hitarea",
+ collapsable: "collapsable",
+ collapsableHitarea: "collapsable-hitarea",
+ lastCollapsableHitarea: "lastCollapsable-hitarea",
+ lastCollapsable: "lastCollapsable",
+ lastExpandable: "lastExpandable",
+ last: "last",
+ hitarea: "hitarea"
+ };
+
+ // provide backwards compability
+ $.fn.Treeview = $.fn.treeview;
+
+})(jQuery);
View
256 front/www/Script/md5.js
@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+ return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << ((len) % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+
+ a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+ d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+ c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
+ b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+ a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+ d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
+ c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+ b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+ a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
+ d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+ c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+ b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+ a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
+ d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+ c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+ b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
+
+ a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+ d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+ c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
+ b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+ a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+ d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
+ c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+ b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+ a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
+ d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+ c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+ b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
+ a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+ d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+ c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
+ b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+ a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+ d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+ c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
+ b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+ a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+ d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
+ c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+ b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+ a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
+ d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+ c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+ b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
+ a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+ d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+ c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
+ b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+ a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+ d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
+ c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+ b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+ a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
+ d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+ c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+ b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+ a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
+ d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+ c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+ b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
+ a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+ d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+ c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
+ b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ }
+ return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+ var bkey = str2binl(key);
+ if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+ var ipad = Array(16), opad = Array(16);
+ for(var i = 0; i < 16; i++)
+ {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+ return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+ return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+ }
+ }
+ return str;
+}
View
195 front/www/Style/main.css
@@ -0,0 +1,195 @@
+body {
+ font-family: verdana;
+ font-size:11px;
+ padding:0px;
+ margin:0px;
+}
+.box {
+ background:#fafafa;
+ border:1px solid #DDD;
+ margin:0px;
+ padding:0px;
+}
+#controls {
+ border-bottom:2px solid #DDD;
+ background:#f0f0f0;
+ height:28px;
+}
+#controls img {
+ float:left;
+ margin-right:60px;
+}
+#controls div {
+ font-weight:bold;
+ display:inline;
+ font-size:14px;
+ text-align:left;
+ vertical-align:baseline;
+ line-height:28px;
+ padding-right:30px;
+ width:120px;
+}
+
+#controls div span {
+ font-size:18px;
+}
+
+.ulHidden li {
+ display:none;
+}
+
+#currentFileDisplay {
+ width:700px;
+ margin-left:100px;
+ color:#b0b0b0;
+ text-align:right;
+ font-size:14px;
+ overflow:none;
+}
+
+div.popup {
+ display:none;
+ top:28px;
+ left:0px;
+ position:absolute;
+ z-index:1000;
+ padding:5px;
+ background:#f0f0f0;
+ vertical-align:middle;
+ border:2px solid #DDD;
+ border-right:2px solid #DDD;
+ border-left:none;
+}
+
+.popup ul, .popup li {
+ margin:0px;
+ padding:0px;
+ list-style:none;
+}
+
+.popup li {
+ list-style:none;
+}
+pre.message {
+ font-family:verdana;
+ padding-left:5px;
+ margin:0;
+ font-weight:bold;
+ font-size:14px;
+
+}
+
+h1.results {
+ font-size:14px;
+}
+
+.line {
+ padding:5px;
+ font-size:14px
+}
+
+.result {
+ margin:10px 10px;
+ padding:5px 0px;
+
+}
+.result img.icon {
+ height:48px;
+ width:47px;
+}
+.errorIcon {
+ background-position:10px;
+ padding: 0px 10px 0px 80px;
+}
+.result .leftBox {
+ float:left;
+ width:50px;
+ margin-top:5px;
+ margin-left:10px;
+}
+.result .rightBox {
+ margin-right:15px;
+ margin-left:80px;
+}
+.result .titleLine {
+ border-bottom:1px solid #CCC;
+ padding-bottom:2px;
+ margin:3px 0px 10px 0px;
+ font-size:14px;
+ color:#999;
+}
+.result .titleLine .line {
+ font-size:14px;
+ font-weight:bold;
+}
+
+a, a:visited {
+ font-family:verdana;
+ color:#2B5FA9;
+ text-decoration:none;
+ margin:0;
+ padding:0;
+ border:0px;
+}
+img {
+ border:0px;
+ margin:0px;
+ padding:0px;
+}
+
+.filetree li { padding: 0px 5px 0px 5px; font-size:16px; }
+.filetree span.folder, .filetree span.file { padding: 1px 0 1px 22px; }
+.filetree span.folder { background: url(Images/treeview/folder.gif) 0 0 no-repeat; }
+.filetree li.expandable span.folder { background: url(Images/treeview/folder-closed.gif) 0 0 no-repeat; }
+.filetree span.file { background: url(Images/treeview/file.gif) 0 0 no-repeat; }
+
+.treeview, .treeview ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+
+
+
+
+.treeview .hitarea {
+ background: url(Images/treeview/treeview-default.gif) -64px -25px no-repeat;
+ height: 16px;
+ width: 16px;
+ margin-left: -16px;
+ float: left;
+ cursor: pointer;
+}
+/* fix for IE6 */
+* html .hitarea {
+ display: inline;
+ float:none;
+}
+
+.treeview li a {
+ color:#000;
+}
+
+.treeview li li {
+ margin: 0;
+ padding: 3px 0pt 3px 16px;
+}
+
+.treeview a.selected {
+ background-color: #eee;
+}
+
+
+
+.treeview .hover, .popup a:hover { color: red; cursor: pointer; }
+
+
+.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
+
+.treeview .expandable-hitarea { background-position: -80px -3px; }
+
+.treeview li.last { background-position: 0 -1766px }
+.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(Images/treeview/treeview-default.gif); }
+.treeview li.lastCollapsable { background-position: 0 -111px }
+.treeview li.lastExpandable { background-position: -32px -67px }
+.treeview li a:hover { cursor: pointer; }
View
116 front/www/detect.php
@@ -0,0 +1,116 @@
+<?php
+ /*******************************************\
+
+ Blerby Components (c) 2008 Sproutware
+
+ ##LICENSE##
+
+ Author: Elijah Insua (Feb 9, 2008)
+ Filename: detect.php
+ Package: package_declaration
+
+ \*******************************************/
+
+/**
+ * @license ##LICENSE_URL##
+ * @author Elijah Insua
+ * @package
+ * @subpackage
+ * @version #0.6#
+ */
+
+/**
+ *
+ * @author Elijah Insua
+ * @version #0.6#
+ * @package Blerby
+ */
+$start = microtime(false);
+
+error_reporting(E_ALL | E_STRICT | E_WARNING);
+
+// ** Process Config **
+require_once "Blerby/TestRunner/Init.php";
+Blerby_TestRunner_Init::start();
+
+define('BTR_FRONT_PATH',realpath(dirname(__FILE__) . "/../"));
+
+// ** Setup The Config **
+Blerby_TestRunner_Init::set("config",new Blerby_TestRunner_Config(BTR_FRONT_PATH . "/config/config.xml"));
+Blerby_TestRunner_Init::setupIncludePaths();
+
+// ** Changes Store **
+$aChanges = array();
+
+// ** Deletion Store **
+$aDeletions = array();
+
+// ** Locate the global filters if available **
+$globalFilters = Blerby_TestRunner_Init::get("config")->get("scanners/filters");
+
+// ** Create Scanners **
+foreach (Blerby_TestRunner_Init::get("config")->get("scanners")->children() as $s)
+{
+
+ // ** Only configure scanners in the scanners section **
+ if ($s->getName() != 'scanner') {
+ continue;
+ }
+
+ // *** Get scanner configuration ***
+ $scannerConf = new Blerby_TestRunner_Config($s);
+
+ // *** Default to File scanner ***
+ $scannerType = $scannerConf->get("type","File");
+
+ // *** Instantiate Scanner ***
+ $scannerType = 'Blerby_TestRunner_Scanner_' . $scannerType;
+ $scanner = Blerby_TestRunner_ServiceLocator::get($scannerType,$scannerConf);
+
+ // ** Load global scanner filters if available **
+ if ($globalFilters->children()) {
+ $scanner->loadFilters($globalFilters);
+ }
+
+ // *** Scan for Changes ***
+ $scanner->scan($scannerConf->get("options/path"));
+
+ // *** Merge found changes ***
+ $aChanges = array_merge($aChanges,$scanner->getChanges());
+
+ // *** Merge found deletions ***
+ $aDeletions = array_merge($aDeletions,$scanner->getDeletions());
+
+}
+
+
+// ** Prepare Changes **
+$hashTable = array();
+
+$ourPath = Blerby_TestRunner_Util::cleanPath(realpath(dirname(__FILE__) . "/../"));
+
+foreach ($aChanges as $k=>$i)
+{
+ // ** Ensure we are not detecting files in btr's front **
+ if ($i && $ourPath && strpos($i,$ourPath) === false) {
+ $hashTable[md5($k)] = array("file"=>$i,
+ "hash"=>md5($k));
+ }
+}
+$send = array();
+$send['aChanges'] = $hashTable;
+
+// ** Prepare Deletions **
+$hashTable = array();
+foreach ($aDeletions as $k=>$i)
+{
+ $hashTable[md5($k)] = array("file"=>$i,
+ "hash"=>md5($k));
+}
+
+$send['aDeletions'] = $hashTable;
+$end = microtime(false);
+$send['debug']['executionTime'] = $end-$start;
+
+
+return $send;
View
142 front/www/index.php
@@ -0,0 +1,142 @@
+<?php $btrUrlPath = $_SERVER['REQUEST_URI']; ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <script type="text/javasrcipt">
+ var BTR = null;
+ </script>
+ <script type="text/javascript" src="<?php echo $btrUrlPath; ?>Script/jquery.js"></script>
+ <script type="text/javascript" src="<?php echo $btrUrlPath; ?>Script/jquery.timer.js"></script>
+ <script type="text/javascript" src="<?php echo $btrUrlPath; ?>Script/jquery.treeview.js"></script>
+ <script type="text/javascript" src="<?php echo $btrUrlPath; ?>Script/jquery.btr.js"></script>
+ <script type="text/javascript" src="<?php echo $btrUrlPath; ?>Script/jquery.highlightFade.js"></script>
+
+ <style type="text/css" media="screen">
+ @import url("<?php echo $btrUrlPath; ?>Style/main.css");
+
+