--- /dev/null
+/* @override http://localhost/mark_story/site/debug_kit/css/debug_toolbar.css */
+#debug-kit-toolbar {
+ position: fixed;
+ top: 0px;
+ right:0px;
+ width: 100%;
+ height: 1%;
+ overflow: visible;
+ z-index:10000;
+ font-family: helvetica, arial, sans-serif;
+ font-size: 12px;
+ direction: ltr;
+}
+#debug-kit-toolbar img {
+ border:0;
+ outline:0;
+}
+
+/* panel tabs */
+#debug-kit-toolbar #panel-tabs {
+ float: right;
+ list-style: none;
+ margin: 0;
+}
+#debug-kit-toolbar .panel-tab {
+ clear: none;
+ float: left;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+#debug-kit-toolbar .panel-tab > a {
+ float: left;
+ clear: none;
+ background: #efefef;
+ background: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#cacaca));
+ background: -moz-linear-gradient(top, #efefef, #cacaca);
+ color: #222;
+ padding: 6px;
+ border-right: 1px solid #ccc;
+ border-bottom: 1px solid #aaa;
+ font-size: 12px;
+ line-height: 16px;
+ margin: 0;
+ display: block;
+ text-decoration:none;
+ text-shadow:1px 1px #eee;
+ -moz-text-shadow:1px 1px #eee;
+ -webkit-text-shadow:1px 1px #eee;
+}
+#debug-kit-toolbar .panel-tab .active {
+ background: #fff;
+ background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#fff));
+ background: -moz-linear-gradient(top, #f5f5f5, #fff);
+}
+#debug-kit-toolbar .panel-tab > a:hover {
+ background: #fff;
+ background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#fff));
+ background: -moz-linear-gradient(top, #f5f5f5, #fff);
+ text-decoration:underline;
+}
+#debug-kit-toolbar .panel-tab.icon a {
+ padding: 4px;
+}
+#debug-kit-toolbar .panel-tab a.edit-value {
+ float: none;
+ display: inline;
+}
+
+/* Hovering over link shows tab, useful for no js */
+#debug-kit-toolbar .panel-tab a:hover + .panel-content,
+#debug-kit-toolbar .panel-tab a + .panel-content:hover {
+ display: block;
+}
+#debug-kit-toolbar .panel-tab.icon a {
+ -webkit-border-top-left-radius: 8px 8px;
+ -webkit-border-bottom-left-radius: 8px 8px;
+ -moz-border-radius-topleft: 8px;
+ -moz-border-radius-bottomleft: 8px
+}
+#debug-kit-toolbar .panel-tab.icon img {
+ display:block;
+}
+
+/* panel content */
+#debug-kit-toolbar .panel-content {
+ position: absolute;
+ text-align: left;
+ width: auto;
+ top:28px;
+ right:0px;
+ background: #fff;
+ color: #000;
+ width:100%;
+ box-shadow:0px 5px 6px #ccc;
+ height: 200px;
+ overflow: hidden;
+}
+
+#debug-kit-toolbar .panel-resize-region {
+ padding:15px;
+ position: absolute;
+ top: 0px;
+ bottom: 14px;
+ left: 0px;
+ right: 0px;
+ overflow: auto;
+}
+
+#debug-kit-toolbar .ui-control {
+ background:#ccc;
+ background: -webkit-gradient(linear, left top, left bottom, from(#d6d6d6), to(#c2c2c2));
+ background: -moz-linear-gradient(top, #d6d6d6, #c2c2c2);
+ text-align:center;
+ border-top:1px solid #afafaf;
+ border-bottom:1px solid #7c7c7c;
+ color:#666;
+ text-shadow: 1px 1px #eee;
+ -webkit-text-shadow: 1px 1px #eee;
+ -moz-text-shadow: 1px 1px #eee;
+}
+#debug-kit-toolbar .ui-button {
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+#debug-kit-toolbar .ui-button:hover {
+ text-decoration: none;
+ background:#ccc;
+ background: -webkit-gradient(linear, left top, left bottom, from(#c2c2c2), to(#d6d6d6));
+ background: -moz-linear-gradient(top, #c2c2c2, #d6d6d6);
+}
+#debug-kit-toolbar .panel-resize-handle {
+ cursor: row-resize;
+ height:14px;
+ line-height: 14px;
+ position: absolute;
+ bottom: 0px;
+ left: 0px;
+ right: 0px;
+}
+#debug-kit-toolbar .panel-maximize,
+#debug-kit-toolbar .panel-minimize {
+ float: right;
+ display: block;
+ width: 12px;
+ height: 12px;
+ line-height: 12px;
+ border-left: 1px solid #afafaf;
+ border-right: 1px solid #7c7c7c;
+}
+#debug-kit-toolbar .panel-maximize {
+ float: right;
+ margin: 10px 20px 0 0;
+ z-index: 999;
+ position: relative;
+}
+#debug-kit-toolbar .panel-minimize {
+ float: right;
+ margin: 10px 10px 0 0;
+ z-index: 999;
+ position: relative;
+}
+
+/* Hide panel content by default */
+#debug-kit-toolbar .panel-content {
+ display: none;
+}
+.panel-content p {
+ margin: 1em 0;
+}
+.panel-content h2 {
+ padding: 0;
+ margin-top:0;
+}
+.panel-content h3 {
+ padding: 0;
+ margin-top: 1em;
+}
+.panel-content .info {
+ padding: 4px;
+ border-top: 1px dashed #6c6cff;
+ border-bottom: 1px dashed #6c6cff;
+}
+#debug-kit-toolbar h1,
+#debug-kit-toolbar h2,
+#debug-kit-toolbar h3,
+#debug-kit-toolbar h4,
+#debug-kit-toolbar h5,
+#debug-kit-toolbar th {
+ color: #5d1717;
+ font-family: "Trebuchet MS", trebuchet, helvetica, arial, sans-serif;
+ margin-bottom:0.6em;
+ background:none;
+}
+#debug-kit-toolbar h1 {
+ font-size: 18px;
+}
+#debug-kit-toolbar h2 {
+ font-size: 16px;
+}
+#debug-kit-toolbar h4 {
+ font-size: 14px;
+}
+
+
+/* panel tables */
+#debug-kit-toolbar table.debug-table {
+ width: 100%;
+ border: 0;
+ clear:both;
+ margin-bottom: 20px;
+}
+#debug-kit-toolbar table.debug-table td,
+#debug-kit-toolbar table.debug-table th {
+ text-align: left;
+ border: 0;
+ padding: 3px;
+}
+#debug-kit-toolbar table.debug-table th {
+ border-bottom: 1px solid #222;
+ background: 0;
+ color: #252525;
+}
+#debug-kit-toolbar table.debug-table tr:nth-child(2n+1) td {
+ background:#f6f6f6;
+}
+#debug-kit-toolbar table.debug-table tr.even td {
+ background:#f7f7f7;
+}
+#debug-kit-toolbar .debug-timers .debug-table td:nth-child(2),
+#debug-kit-toolbar .debug-timers .debug-table th:nth-child(2) {
+ text-align:right;
+}
+
+/** code tables **/
+#debug-kit-toolbar .code-table td {
+ white-space: pre;
+ font-family: monaco, Consolas, "courier new", courier, monospaced;
+}
+#debug-kit-toolbar .code-table td:first-child {
+ width: 15%;
+}
+#debug-kit-toolbar .code-table td:last-child {
+ width: 80%;
+}
+
+#debug-kit-toolbar .panel-content.request {
+ display: block;
+}
+
+/** Neat Array styles **/
+#debug-kit-toolbar .neat-array,
+#debug-kit-toolbar .neat-array li {
+ list-style:none;
+ list-style-image:none;
+}
+.neat-array {
+ padding: 1px 2px 1px 20px;
+ background: #CE9E23;
+ list-style: none;
+ margin: 0 0 1em 0;
+}
+.neat-array .neat-array {
+ padding: 0 0 0 20px;
+ margin:0;
+ border-top:1px solid #CE9E23;
+}
+.neat-array li {
+ background: #FEF6E5;
+ border-top: 1px solid #CE9E23;
+ border-bottom: 1px solid #CE9E23;
+ margin: 0;
+ line-height: 1.5em;
+}
+.neat-array li:hover {
+ background: #fff;
+}
+.neat-array li strong {
+ padding: 0 8px;
+ font-weight: bold;
+}
+
+
+/* expandable sections */
+.neat-array li.expandable {
+ cursor: pointer;
+}
+.neat-array .expanded {
+ border-bottom:0;
+}
+.neat-array li.expandable.expanded > strong:before {
+ content: 'v ';
+}
+.neat-array li.expandable.collapsed > strong:before,
+.neat-array li.expandable.expanded .expandable.collapsed > strong:before {
+ content: '> ';
+}
+.neat-array li {
+ cursor: default;
+}
+
+#debug-kit-toolbar .debug-kit-graph-bar,
+#debug-kit-toolbar .debug-kit-graph-bar-value {
+ margin: 0;
+ padding: 0px;
+ border: none;
+ overflow: hidden;
+ height: 10px;
+}
+#debug-kit-toolbar .debug-kit-graph-bar {
+ background-color: #ddd;
+ padding:2px;
+}
+#debug-kit-toolbar .debug-kit-graph-bar-value {
+ background-color: #CE9E23;
+}
+
+/* Sql Log */
+#sql_log-tab td,
+#sql_log-tab .slow-query-container p {
+ font-family: Monaco, 'Consolas', "Courier New", Courier, monospaced;
+}
+#debug-kit-toolbar #sql_log-tab a.show-slow {
+ display:block;
+ margin: 3px;
+ float:none;
+}
+#sql_log-tab .slow-query-container p {
+ display:block;
+ clear:both;
+ margin: 20px 0 5px;
+}
+#debug-kit-toolbar #sql_log-tab .panel-content-data a {
+ background: none;
+ border:none;
+}
+#sql_log-tab .slow-query {
+ background:#e79302;
+ font-size:9px;
+ color:#fff;
+ padding: 2px;
+ white-space:nowrap;
+}
+#sql_log-tab input[type=submit] {
+ border: 0;
+ background: transparent;
+ cursor: pointer;
+ font-size: 12px;
+ font-family: Monaco, 'Consolas', "Courier New", Courier, monospaced;
+}
+#sql_log-tab input[type=submit]:hover {
+ color: darkred;
+}
+
+/* previous panels */
+#debug-kit-toolbar .panel-history {
+ display: none;
+ background:#eeffff;
+}
+#debug-kit-toolbar #history-tab ul {
+ margin: 20px 0 0 20px;
+}
+#debug-kit-toolbar #history-tab li {
+ margin: 0 0 5px 0;
+}
+#debug-kit-toolbar #history-tab .panel-content-data a {
+ float: none;
+ display:block;
+}
+#debug-kit-toolbar #history-tab a.active {
+ background: #FEF6E5;
+}
+#debug-kit-toolbar #history-tab a.loading:after {
+ content : ' Loading...';
+ font-style:italic;
+}
--- /dev/null
+/**
+ * Debug Toolbar Javascript.
+ *
+ * Creates the DEBUGKIT namespace and provides methods for extending
+ * and enhancing the Html toolbar. Includes library agnostic Event, Element,
+ * Cookie and Request wrappers.
+ *
+ *
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://cakephp.org
+ * @package debug_kit
+ * @subpackage debug_kit.views.helpers
+ * @since DebugKit 0.1
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+var DEBUGKIT = function () {
+ var undef;
+ return {
+ module: function (newmodule) {
+ if (this[newmodule] === undef) {
+ this[newmodule] = {};
+ return this[newmodule];
+ }
+ return this[newmodule];
+ }
+ };
+}() ;
+
+DEBUGKIT.loader = function () {
+ return {
+ //list of methods to run on startup.
+ _startup: [],
+
+ //register a new method to be run on dom ready.
+ register: function (method) {
+ this._startup.push(method);
+ },
+
+ init: function () {
+ for (var i = 0, callback; callback = this._startup[i]; i++) {
+ callback.init();
+ }
+ }
+ };
+}();
+
+//Util module and Element utility class.
+DEBUGKIT.module('Util');
+DEBUGKIT.Util.Element = {
+
+ //test if an element is a name node.
+ nodeName: function (element, name) {
+ return element.nodeName && element.nodeName.toLowerCase() == name.toLowerCase();
+ },
+
+ //return a boolean if the element has the classname
+ hasClass: function (element, className) {
+ if (!element.className) {
+ return false;
+ }
+ return element.className.indexOf(className) > -1;
+ },
+
+ addClass: function (element, className) {
+ if (!element.className) {
+ element.className = className;
+ return;
+ }
+ element.className = element.className.replace(/^(.*)$/, '$1 ' + className);
+ },
+
+ removeClass: function (element, className) {
+ if (DEBUGKIT.Util.isArray(element)) {
+ DEBUGKIT.Util.Collection.apply(element, function (element) {
+ DEBUGKIT.Util.Element.removeClass(element, className);
+ });
+ }
+ if (!element.className) {
+ return false;
+ }
+ element.className = element.className.replace(new RegExp(' ?(' + className +') ?'), '');
+ },
+
+ swapClass: function (element, removeClass, addClass) {
+ if (!element.className) {
+ return false;
+ }
+ element.className = element.className.replace(removeClass, addClass);
+ },
+
+ show: function (element) {
+ element.style.display = 'block';
+ },
+
+ hide: function (element) {
+ element.style.display = 'none';
+ },
+
+ //go between hide() and show() depending on element.style.display
+ toggle: function (element) {
+ if (element.style.display == 'none') {
+ this.show(element);
+ return;
+ }
+ this.hide(element);
+ },
+
+ _walk: function (element, walk) {
+ var sibling = element[walk];
+ while (true) {
+ if (sibling.nodeType == 1) {
+ break;
+ }
+ sibling = sibling[walk];
+ }
+ return sibling;
+ },
+
+ getNext: function (element) {
+ return this._walk(element, 'nextSibling');
+ },
+
+ getPrevious: function (element) {
+ return this._walk(element, 'previousSibling');
+ },
+
+ //get or set an element's height, omit value to get, add value (integer) to set.
+ height: function (element, value) {
+ //get value
+ if (value === undefined) {
+ return parseInt(this.getStyle(element, 'height'));
+ }
+ element.style.height = value + 'px';
+ },
+
+ //gets the style in css format for property
+ getStyle: function (element, property) {
+ if (element.currentStyle) {
+ property = property.replace(/-[a-z]/g, function (match) {
+ return match.charAt(1).toUpperCase();
+ });
+ return element.currentStyle[property];
+ }
+ if (window.getComputedStyle) {
+ return document.defaultView.getComputedStyle(element, null).getPropertyValue(property);
+ }
+ }
+};
+
+DEBUGKIT.Util.Collection = {
+ /*
+ Apply the passed function to each item in the collection.
+ The current element in the collection will be `this` in the callback
+ The callback is also passed the element and the index as arguments.
+ Optionally you can supply a binding parameter to change `this` in the callback.
+ */
+ apply: function (collection, callback, binding) {
+ var name, thisVar, i = 0, len = collection.length;
+
+ if (len === undefined) {
+ for (name in collection) {
+ thisVar = (binding === undefined) ? collection[name] : binding;
+ callback.apply(thisVar, [collection[name], name]);
+ }
+ } else {
+ for (; i < len; i++) {
+ thisVar = (binding === undefined) ? collection[i] : binding;
+ callback.apply(thisVar, [collection[i], i]);
+ }
+ }
+ }
+}
+
+
+//Event binding
+DEBUGKIT.Util.Event = function () {
+ var _listeners = {},
+ _eventId = 0;
+
+ var preventDefault = function () {
+ this.returnValue = false;
+ }
+
+ var stopPropagation = function () {
+ this.cancelBubble = true;
+ }
+
+ // Fixes IE's broken event object, adds in common methods + properties.
+ var fixEvent = function (event) {
+ if (!event.preventDefault) {
+ event.preventDefault = preventDefault;
+ }
+ if (!event.stopPropagation) {
+ event.stopPropagation = stopPropagation;
+ }
+ if (!event.target) {
+ event.target = event.srcElement || document;
+ }
+ if (event.pageX == null && event.clientX != null) {
+ var doc = document.body;
+ event.pageX = event.clientX + (doc.scrollLeft || 0) - (doc.clientLeft || 0);
+ event.pageY = event.clientY + (doc.scrollTop || 0) - (doc.clientTop || 0);
+ }
+ return event;
+ }
+
+ return {
+ // bind an event listener of type to element, handler is your method.
+ addEvent: function(element, type, handler, capture) {
+ capture = (capture === undefined) ? false : capture;
+
+ var callback = function (event) {
+ event = fixEvent(event || window.event);
+ handler.apply(element, [event]);
+ };
+
+ if (element.addEventListener) {
+ element.addEventListener(type, callback, capture);
+ } else if (element.attachEvent) {
+ type = 'on' + type;
+ element.attachEvent(type, callback);
+ } else {
+ type = 'on' + type;
+ element[type] = callback;
+ }
+ _listeners[++_eventId] = {element: element, type: type, handler: callback};
+ },
+
+ // destroy an event listener. requires the exact same function as was used for attaching
+ // the event.
+ removeEvent: function (element, type, handler) {
+ if (element.removeEventListener) {
+ element.removeEventListener(type, handler, false);
+ } else if (element.detachEvent) {
+ type = 'on' + type;
+ element.detachEvent(type, handler);
+ } else {
+ type = 'on' + type;
+ element[type] = null;
+ }
+ },
+
+ // bind an event to the DOMContentLoaded or other similar event.
+ domready: function(callback) {
+ if (document.addEventListener) {
+ return document.addEventListener("DOMContentLoaded", callback, false);
+ }
+
+ if (document.all && !window.opera) {
+ //Define a "blank" external JavaScript tag
+ document.write('<script type="text/javascript" id="__domreadywatcher" defer="defer" src="://"><\/script>');
+ var contentloadtag = document.getElementById("__domreadywatcher");
+ contentloadtag.onreadystatechange = function (){
+ if (this.readyState == "complete") {
+ callback();
+ }
+ }
+ contentloadtag = null;
+ return;
+ }
+
+ if (/Webkit/i.test(navigator.userAgent)){
+ var _timer = setInterval(function (){
+ if (/loaded|complete/.test(document.readyState)) {
+ clearInterval(_timer);
+ callback();
+ }
+ }, 10);
+ }
+ },
+
+ // unload all the events attached by DebugKit. Fix any memory leaks.
+ unload: function () {
+ var listener;
+ for (var i in _listeners) {
+ listener = _listeners[i];
+ try {
+ this.removeEvent(listener.element, listener.type, listener.handler);
+ } catch (e) {}
+ delete _listeners[i];
+ }
+ delete _listeners;
+ }
+ };
+}();
+
+//Cookie utility
+DEBUGKIT.Util.Cookie = function() {
+ var cookieLife = 60;
+
+//public methods
+ return {
+ /*
+ Write to cookie
+ @param [string] name Name of cookie to write.
+ @param [mixed] value Value to write to cookie.
+ */
+ write: function (name, value) {
+ var date = new Date();
+ date.setTime(date.getTime() + (cookieLife * 24 * 60 * 60 * 1000));
+ var expires = "; expires=" + date.toGMTString();
+ document.cookie = name + "=" + value + expires + "; path=/";
+ return true;
+ },
+
+ /*
+ Read from the cookie
+ @param [string] name Name of cookie to read.
+ */
+ read: function (name) {
+ name = name + '=';
+ var cookieJar = document.cookie.split(';');
+ for (var i = 0; i < cookieJar.length; i++) {
+ var chips = cookieJar[i];
+ //trim leading spaces
+ while (chips.charAt(0) == ' ') {
+ chips = chips.substring(1, chips.length);
+ }
+ if (chips.indexOf(name) == 0) {
+ return chips.substring(name.length, chips.length);
+ }
+ }
+ return false;
+ },
+ /*
+ Delete a cookie by name.
+ @param [string] name of cookie to delete.
+ */
+ del: function (name) {
+ var date = new Date();
+ date.setFullYear(2000,0,1);
+ var expires = " ; expires=" + date.toGMTString();
+ document.cookie = name + "=" + expires + "; path=/";
+ }
+ };
+}();
+
+
+/*
+ Object merge takes any number of arguments and glues them together
+ @param [Object] one first object
+ @return object
+*/
+DEBUGKIT.Util.merge = function() {
+ var out = {};
+ for (var i = 0; i < arguments.length; i++) {
+ var current = arguments[i];
+ for (prop in current) {
+ if (current[prop] !== undefined){
+ out[prop] = current[prop];
+ }
+ }
+ }
+ return out;
+};
+/*
+ Check if the given object is an array.
+*/
+DEBUGKIT.Util.isArray = function (test) {
+ return Object.prototype.toString.call(test) === '[object Array]';
+}
+
+
+// Simple wrapper for XmlHttpRequest objects.
+DEBUGKIT.Util.Request = function (options) {
+ var _defaults = {
+ onComplete : function () {},
+ onRequest : function () {},
+ onFail : function () {},
+ method : 'GET',
+ async : true,
+ headers : {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ }
+ };
+
+ var self = this;
+ this.options = DEBUGKIT.Util.merge(_defaults, options);
+ this.options.method = this.options.method.toUpperCase();
+
+ var ajax = this.createObj();
+ this.transport = ajax;
+
+ //event assignment
+ this.onComplete = this.options.onComplete;
+ this.onRequest = this.options.onRequest;
+ this.onFail = this.options.onFail;
+
+ this.send = function (url, data) {
+ if (this.options.method == 'GET' && data) {
+ url = url + ( (url.charAt(url.length -1) == '?') ? '&' : '?') + data; //check for ? at the end of the string
+ data = null;
+ }
+ //open connection
+ this.transport.open(this.options.method, url, this.options.async);
+
+ //set statechange and pass the active XHR object to it. From here it handles all status changes.
+ this.transport.onreadystatechange = function () {
+ self.onReadyStateChange.apply(self, arguments);
+ };
+ for (var key in this.options.headers) {
+ this.transport.setRequestHeader(key, this.options.headers[key]);
+ }
+ if (typeof data == 'object') {
+ data = this.serialize(data);
+ }
+ if (data) {
+ this.transport.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ }
+ this.onRequest();
+ this.transport.send(data);
+ };
+};
+
+DEBUGKIT.Util.Request.prototype.onReadyStateChange = function (){
+ if (this.transport.readyState !== 4) {
+ return;
+ }
+ if (this.transport.status == 200 || this.transport.status > 300 && this.transport.status < 400 ) {
+ this.response = {
+ xml: this.transport.responseXML,
+ text: this.transport.responseText
+ };
+
+ if (typeof this.onComplete == 'function') {
+ this.onComplete.apply(this, [this, this.response]);
+ } else {
+ return this.response;
+ }
+ } else if (this.transport.status > 400) {
+ if (typeof this.onFail == 'function') {
+ this.onFail.apply(this, []);
+ } else {
+ console.error('Request failed');
+ }
+ }
+};
+
+/*
+ Creates cross-broswer XHR object used for requests
+ Tries using the standard XmlHttpRequest, then IE's wacky ActiveX Objects
+*/
+DEBUGKIT.Util.Request.prototype.createObj = function(){
+ var request = null;
+ try {
+ request = new XMLHttpRequest();
+ } catch (MS) {
+ try {
+ request = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (old_MS) {
+ try {
+ request = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch(failure) {
+ request = null;
+ }
+ }
+ }
+ return request;
+};
+
+/*
+ Serializes an object literal into a querystring
+*/
+DEBUGKIT.Util.Request.prototype.serialize = function (data) {
+ var out = '';
+ for (var name in data) {
+ if (data.hasOwnProperty(name)) {
+ out += name + '=' + data[name] + '&';
+ }
+ }
+ return out.substring(0, out.length - 1);
+};
+
+
+//Basic toolbar module.
+DEBUGKIT.toolbar = function () {
+ //shortcuts
+ var Request = DEBUGKIT.Request,
+ Element = DEBUGKIT.Util.Element,
+ Cookie = DEBUGKIT.Util.Cookie,
+ Event = DEBUGKIT.Util.Event,
+ Collection = DEBUGKIT.Util.Collection,
+ toolbarHidden = false;
+
+
+ /*
+ Add neat array functionality.
+ Events are bound to depth-0 UL elements.
+ Use event delegation to find original target.
+ */
+ function _delegateNeatArray (event) {
+ var clickedEl = event.target;
+ while (!Element.nodeName(clickedEl, 'LI')) {
+ clickedEl = clickedEl.parentNode;
+ }
+ var subUl = clickedEl.lastChild;
+ if (!Element.nodeName(subUl, 'ul')) {
+ return;
+ }
+ var hide = Boolean(subUl.style.display === 'block');
+ if (hide) {
+ Element.hide(subUl);
+ Element.swapClass(clickedEl, 'expanded', 'collapsed');
+ } else {
+ Element.show(subUl);
+ Element.swapClass(clickedEl, 'collapsed', 'expanded');
+ }
+ event.stopPropagation();
+ }
+
+ return {
+ elements: {},
+ panels: {},
+
+ init: function () {
+ var i, element, lists, index;
+ this.elements.toolbar = document.getElementById('debug-kit-toolbar');
+
+ if (this.elements.toolbar === undefined) {
+ throw('Toolbar not found, make sure you loaded it.');
+ }
+
+ for (i in this.elements.toolbar.childNodes) {
+ element = this.elements.toolbar.childNodes[i];
+ if (element.nodeName && element.id === 'panel-tabs') {
+ this.elements.panel = element;
+ break;
+ }
+ }
+
+ Collection.apply(this.elements.panel.childNodes, function (element) {
+ if (Element.hasClass(element, 'panel-tab')) {
+ this.addPanel(element);
+ }
+ }, this);
+
+ if (document.getElementsByClassName) {
+ lists = this.elements.toolbar.getElementsByClassName('depth-0');
+ } else {
+ lists = this.elements.toolbar.getElementsByTagName('ul');
+ }
+ this.makeNeatArray(lists);
+ this.deactivatePanel(true);
+ },
+
+ // Add a panel to the toolbar
+ addPanel: function (tab) {
+ if (!Element.nodeName(tab, 'li')) {
+ throw ('Toolbar not found, make sure you loaded it.');
+ }
+ var panel = {
+ id : false,
+ element : tab,
+ button : undefined,
+ content : undefined,
+ active : false
+ };
+
+ Collection.apply(tab.childNodes, function (element) {
+ if (Element.nodeName(element, 'A')) {
+ panel.id = element.hash.replace(/^#/, '');
+ panel.button = element;
+ } else if (Element.nodeName(element, 'DIV')) {
+ panel.content = element;
+ }
+ });
+
+ if (!panel.id || !panel.content) {
+ return false;
+ }
+ this.makePanelDraggable(panel);
+ this.makePanelMinMax(panel);
+
+ var self = this;
+ Event.addEvent(panel.button, 'click', function (event) {
+ event.preventDefault();
+ return self.togglePanel(panel.id);
+ });
+ this.panels[panel.id] = panel;
+ return panel.id;
+ },
+
+ // find the handle element and make the panel drag resizable.
+ makePanelDraggable: function (panel) {
+
+ //create a variable in the enclosing scope, for scope tricks.
+ var currentElement = null;
+
+ // Use the elements startHeight stored Event.pageY and current Event.pageY to
+ // resize the panel
+ var mouseMoveHandler = function (event) {
+ event.preventDefault();
+ if (!currentElement) {
+ return;
+ }
+ var newHeight = currentElement._startHeight + (event.pageY - currentElement._startY);
+ Element.height(currentElement.parentNode, newHeight);
+ }
+
+ // handle the mouseup event, remove the other listeners so the panel
+ // doesn't continue to resize
+ var mouseUpHandler = function (event) {
+ currentElement = null;
+ Event.removeEvent(document, 'mousemove', mouseMoveHandler);
+ Event.removeEvent(document, 'mouseup', mouseUpHandler);
+ }
+
+ var mouseDownHandler = function (event) {
+ event.preventDefault();
+ currentElement = this;
+ this._startY = event.pageY;
+ this._startHeight = parseInt(Element.height(currentElement.parentNode));
+
+ // attach to document so mouse doesn't have to stay precisely on the 'handle'
+ Event.addEvent(document, 'mousemove', mouseMoveHandler);
+ Event.addEvent(document, 'mouseup', mouseUpHandler);
+ }
+
+ Collection.apply(panel.content.childNodes, function (element) {
+ if (Element.nodeName(element, 'DIV') && Element.hasClass(element, 'panel-resize-handle')) {
+ Event.addEvent(element, 'mousedown', mouseDownHandler);
+ }
+ });
+ },
+
+ // make the maximize button work on the panels.
+ makePanelMinMax: function (panel) {
+ var _oldHeight;
+
+ var maximize = function (event) {
+ event.preventDefault();
+ if (!_oldHeight) {
+ _oldHeight = this.parentNode.offsetHeight;
+ }
+ var windowHeight = window.innerHeight;
+ var panelHeight = windowHeight - this.parentNode.offsetTop;
+ Element.height(this.parentNode, panelHeight);
+ };
+
+ var minimize = function (event) {
+ event.preventDefault();
+ Element.height(this.parentNode, _oldHeight);
+ _oldHeight = null;
+ };
+
+ Collection.apply(panel.content.getElementsByTagName('A'), function (element) {
+ if (Element.hasClass(element, 'panel-maximize')) {
+ Event.addEvent(element, 'click', maximize);
+ }
+ if (Element.hasClass(element, 'panel-minimize')) {
+ Event.addEvent(element, 'click', minimize);
+ }
+ });
+ },
+
+ // Toggle a panel
+ togglePanel: function (id) {
+ if (this.panels[id] && this.panels[id].active) {
+ this.deactivatePanel(true);
+ } else {
+ this.deactivatePanel(true);
+ this.activatePanel(id);
+ }
+ },
+
+ // Make a panel active.
+ activatePanel: function (id, unique) {
+ if (this.panels[id] !== undefined && !this.panels[id].active) {
+ var panel = this.panels[id];
+ if (panel.content !== undefined) {
+ Element.show(panel.content);
+ }
+ Element.addClass(panel.button, 'active');
+ panel.active = true;
+ return true;
+ }
+ return false;
+ },
+
+ // Deactivate a panel. use true to hide all panels.
+ deactivatePanel: function (id) {
+ if (id === true) {
+ for (var i in this.panels) {
+ this.deactivatePanel(i);
+ }
+ return true;
+ }
+ if (this.panels[id] !== undefined) {
+ var panel = this.panels[id];
+ if (panel.content !== undefined) {
+ Element.hide(panel.content);
+ }
+ Element.removeClass(panel.button, 'active');
+ panel.active = false;
+ return true;
+ }
+ return false;
+ },
+
+ // Bind events for all the collapsible arrays.
+ makeNeatArray: function (lists) {
+ for (var i = 0, element; element = lists[i]; i++) {
+ if (Element.hasClass(element, 'neat-array') && element.className.match(/depth-0/)) {
+ var childLists = element.getElementsByTagName('UL');
+ for (var j = 0, childEl; childEl = childLists[j]; j++) {
+ Element.hide(childEl);
+ Element.addClass(childEl.parentNode, 'expandable collapsed');
+ }
+ Event.addEvent(element, 'click', _delegateNeatArray);
+ }
+ }
+ }
+ };
+}();
+DEBUGKIT.loader.register(DEBUGKIT.toolbar);
+
+//Add events + behaviors for toolbar collapser.
+DEBUGKIT.toolbarToggle = function () {
+ var toolbar = DEBUGKIT.toolbar,
+ Element = DEBUGKIT.Util.Element,
+ Cookie = DEBUGKIT.Util.Cookie,
+ Collection = DEBUGKIT.Util.Collection,
+ Event = DEBUGKIT.Util.Event,
+ toolbarHidden = false;
+
+ return {
+ init: function () {
+ var button = document.getElementById('hide-toolbar'),
+ self = this;
+
+ Event.addEvent(button, 'click', function (event) {
+ event.preventDefault();
+ self.toggleToolbar();
+ });
+
+ var toolbarState = Cookie.read('toolbarDisplay');
+ if (toolbarState != 'show') {
+ toolbarHidden = false;
+ this.toggleToolbar();
+ }
+ },
+
+ toggleToolbar: function () {
+ var display = toolbarHidden ? 'show' : 'hide';
+ Collection.apply(toolbar.panels, function (panel) {
+ Element[display](panel.element);
+ Cookie.write('toolbarDisplay', display);
+ });
+ toolbarHidden = !toolbarHidden;
+ return false;
+ }
+ };
+}();
+DEBUGKIT.loader.register(DEBUGKIT.toolbarToggle);
+
+
+DEBUGKIT.Util.Event.domready(function () {
+ DEBUGKIT.loader.init();
+ DEBUGKIT.Util.Event.addEvent(window, 'unload', DEBUGKIT.Util.Event.unload);
+});
\ No newline at end of file