Index: trunk/js/Msg.js
===================================================================
--- trunk/js/Msg.js	(revision 469)
+++ trunk/js/Msg.js	(revision 469)
@@ -0,0 +1,99 @@
+/*
+* The Strangecode Codebase - a general application development framework for PHP
+* For details visit the project site: <http://trac.strangecode.com/>
+* Copyright Â© 2014 Strangecode, LLC
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// All Codebase functions will be under the Strangecode namespace.
+var Strangecode = Strangecode || {};
+
+/*
+* Class for managing user messages. This is the contructor function.
+*
+* @access   public
+* @param    object containing object options:
+{
+    container: '#sc-msg-formvalidator',
+    above_msg: 'Oops!'
+}
+* @author   Quinn Comendant <quinn@strangecode.com>
+* @version  1.0
+* @since    18 Mar 2014 23:24:15
+*
+* Example of use:
+---------------------------------------------------------------------
+var sc_msg = new Strangecode.Msg({
+    container: '#sc-msg-formvalidator',
+    above_msg: 'The following errors occured:'
+});
+sc_msg.raise('Oops, you fuxt up!', 'sc-msg-error');
+sc_msg.clear();
+sc_msg.raise('Ok, now youâre cool.', 'sc-msg-success');
+---------------------------------------------------------------------
+*/
+Strangecode.Msg = function(options) {
+    // Merge options with defaults
+    this.o = $.extend({
+        container: '#sc-msg',
+        above_msg: '',
+        gotohash: true
+    }, options || {});
+};
+
+/*
+* Raises a message to the user.
+*
+* @access   public
+* @param    string message  The message to display.
+* @param    string class    The class to apply to the message div (when using codebase CSS, it is useful to use one of: sc-msg-success, sc-msg-notice, sc-msg-warning, sc-msg-error)
+* @author   Quinn Comendant <quinn@strangecode.com>
+* @version  1.0
+* @since    18 Mar 2014 23:24:15
+*/
+Strangecode.Msg.prototype.raise = function(message, msg_class) {
+    // If an "above msg" is provided, and one doesn't already exist, add it to the message box.
+    if (this.o.above_msg.length && !$(this.o.container).find('.sc-above').length) {
+        $(this.o.container).append($('<div/>', {'class': 'sc-above sc-js-msg'}).text(this.o.above_msg));
+    }
+    // Use 'sc-msg-error' as default class string.
+    msg_class = (typeof msg_class === 'undefined') ? 'sc-msg-error' : msg_class;
+    // Append this raised message to the sc-msg stack, if it doesn't exist already.
+    if (!$(this.o.container).find(':contains("' + message + '")').length) {
+        $(this.o.container).append($('<div/>', {'class': msg_class + ' sc-js-msg'}).text(message)).show();
+    }
+
+    if (this.o.gotohash) {
+        $(document.body).animate({
+            'scrollTop': $(this.o.container).offset().top
+        }, 'fast');
+    }
+};
+
+/*
+* Removes all messages previously created by Msg.raise.
+*
+* @access   public
+* @param    string message  The message to display.
+* @param    string class    The class to apply to the message div (when using codebase CSS, it is useful to use one of: sc-msg-success, sc-msg-notice, sc-msg-warning, sc-msg-error)
+* @author   Quinn Comendant <quinn@strangecode.com>
+* @version  1.0
+* @since    18 Mar 2014 23:24:15
+*/
+Strangecode.Msg.prototype.clear = function() {
+    // Append this raised message to the sc-msg stack.
+    msg_class = (typeof msg_class === 'undefined') ? 'sc-msg-error' : msg_class;
+    $(this.o.container).find('.sc-js-msg').remove();
+};
Index: trunk/lib/JS.inc.php
===================================================================
--- trunk/lib/JS.inc.php	(revision 469)
+++ trunk/lib/JS.inc.php	(revision 469)
@@ -0,0 +1,182 @@
+<?php
+/**
+ * The Strangecode Codebase - a general application development framework for PHP
+ * For details visit the project site: <http://trac.strangecode.com/codebase/>
+ * Copyright 2001-2012 Strangecode, LLC
+ *
+ * This file is part of The Strangecode Codebase.
+ *
+ * The Strangecode Codebase is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * The Strangecode Codebase is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * JS.inc.php
+ *
+ * Dynamically outputs minified JS data.
+ *
+ * @author  Quinn Comendant <quinn@strangecode.com>
+ * @version 1.2
+ */
+class JS {
+
+    // Include these style sheets.
+    private $_js_files = array('default' => array());
+
+    // JS object parameters.
+    private $_params = array(
+        'character_set' => 'utf-8',
+        'cache_js' => false,
+        'strip_whitespace' => false,
+        'output_compression' => false,
+    );
+
+    /**
+     * Set (or overwrite existing) parameters by passing an array of new parameters.
+     *
+     * @access public
+     * @param  array    $params     Array of parameters (key => val pairs).
+     */
+    public function setParam($params)
+    {
+		$app =& App::getInstance();
+
+        if (isset($params) && is_array($params)) {
+            // Merge new parameters with old overriding only those passed.
+            $this->_params = array_merge($this->_params, $params);
+        } else {
+            $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
+        }
+    }
+
+    /**
+     * Return the value of a parameter, if it exists.
+     *
+     * @access public
+     * @param string $param        Which parameter to return.
+     * @return mixed               Configured parameter value.
+     */
+    public function getParam($param)
+    {
+		$app =& App::getInstance();
+
+        if (isset($this->_params[$param])) {
+            return $this->_params[$param];
+        } else {
+            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
+            return null;
+        }
+    }
+
+    /**
+     * Add a file-path to the array of files to include as JS.
+     *
+     * @access  public
+     * @param   string  $file   Include path to JS files.
+     * @param   mixed   $realms   Realm name string or array of realm names.
+     * @return  bool    True on success, false on failure.
+     */
+    public function setFile($file, $realms='')
+    {
+		$app =& App::getInstance();
+
+        if (!is_array($realms)) {
+            $realms = array($realms);
+        }
+
+        if ($fp = fopen($file, 'r', true)) {
+            foreach ($realms as $realm) {
+                $realm = '' == $realm ? 'default' : $realm;
+                $this->_js_files[$realm][] = $file;
+            }
+            fclose($fp);
+            return true;
+        } else {
+            $app->logMsg(sprintf('JS file non-existent: %s', $file), LOG_ERR, __FILE__, __LINE__);
+            return false;
+        }
+    }
+
+    /**
+     * Output headers for JS.
+     *
+     * @access  public
+     *
+     * @return  bool    False if no files have been set.
+     */
+    public function headers($realm='')
+    {
+		$app =& App::getInstance();
+
+        $realm = '' == $realm ? 'default' : $realm;
+
+        if (empty($this->_js_files[$realm])) {
+            $app->logMsg(sprintf('JS::headers called without specifying any files.', null), LOG_WARNING, __FILE__, __LINE__);
+            return false;
+        }
+
+        // Get time of latest modified file, including this class file.
+        $files_mtime = array();
+        foreach (array_merge($this->_js_files[$realm], array(__FILE__)) as $file) {
+            $files_mtime[] = statIncludePath($file, 'mtime');
+        }
+        sort($files_mtime, SORT_NUMERIC);
+        $latest_mtime = array_pop($files_mtime);
+
+        if ($this->getParam('output_compression') && extension_loaded('zlib')) {
+            ob_start('ob_gzhandler');
+        }
+
+        if ($this->getParam('cache_js')) {
+            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $latest_mtime) . ' GMT');
+            header('Cache-Control: public, max-age=86400');
+            header('Pragma: public');
+        } else {
+            header('Expires: -1');
+            header('Pragma: no-cache');
+            header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
+        }
+        header('Content-Type: application/javascript; charset=' . $this->getParam('character_set'));
+    }
+
+    /**
+     * Include JS files specified by setFile().
+     *
+     * @access  public
+     *
+     * @return  bool    False if no files have been set.
+     */
+    public function output($realm='')
+    {
+        $realm = '' == $realm ? 'default' : $realm;
+
+        if (empty($this->_js_files[$realm])) {
+            $app->logMsg(sprintf('JS::output called without specifying any files.', null), LOG_WARNING, __FILE__, __LINE__);
+            return false;
+        }
+
+        foreach ($this->_js_files[$realm] as $file) {
+            if ($this->getParam('strip_whitespace')) {
+                // Strip whitespace and print file.
+                echo preg_replace(array('@^\s*//.*$@m', '@/\*.*?\*/@s', '/[ \t\n\r]+/'), ' ', file_get_contents($file, true));
+            } else {
+                // Include file as is.
+                include $file;
+            }
+        }
+
+        if ($this->getParam('output_compression') && extension_loaded('zlib')) {
+            ob_end_flush();
+        }
+    }
+}
Index: trunk/lib/Utilities.inc.php
===================================================================
--- trunk/lib/Utilities.inc.php	(revision 468)
+++ trunk/lib/Utilities.inc.php	(revision 469)
@@ -35,8 +35,11 @@
 function dump($var, $display=false, $var_dump=false, $file='', $line='')
 {
+    if (empty($var)) {
+        $var = '(nothing to dump)';
+    }
     if (defined('_CLI')) {
-        echo "\n$file $line\n";
-    } else {
-        echo $display ? "\n<br /><strong>$file $line</strong>\n<br /><pre>\n" : "\n\n\n<!--\n$file $line\n";
+        echo "\nDUMP FROM: $file $line\n";
+    } else {
+        echo $display ? "\n<br />DUMP: <strong>$file $line</strong>\n<br /><pre>\n" : "\n\n\n<!--\n$file $line\n";
     }
     if ($var_dump) {
Index: trunk/services/css.php
===================================================================
--- trunk/services/css.php	(revision 468)
+++ trunk/services/css.php	(revision 469)
@@ -4,5 +4,5 @@
  * For details visit the project site: <http://trac.strangecode.com/codebase/>
  * Copyright 2001-2012 Strangecode, LLC
- * 
+ *
  * This file is part of The Strangecode Codebase.
  *
@@ -11,10 +11,10 @@
  * Free Software Foundation, either version 3 of the License, or (at your option)
  * any later version.
- * 
+ *
  * The Strangecode Codebase is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  * details.
- * 
+ *
  * You should have received a copy of the GNU General Public License along with
  * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
@@ -22,5 +22,5 @@
 
 /**
- * css.php 
+ * css.php
  *
  * This file works with the CSS.inc.php class to print a "normal" css file and
@@ -28,7 +28,4 @@
  * ever modify this file.
  */
-
-require_once dirname(__FILE__) . '/_config.inc.php';
-
 if (is_a($css, 'CSS')) {
     $css->headers(getFormData('app'));
Index: trunk/services/js.php
===================================================================
--- trunk/services/js.php	(revision 469)
+++ trunk/services/js.php	(revision 469)
@@ -0,0 +1,34 @@
+<?php
+/**
+ * The Strangecode Codebase - a general application development framework for PHP
+ * For details visit the project site: <http://trac.strangecode.com/codebase/>
+ * Copyright 2001-2012 Strangecode, LLC
+ *
+ * This file is part of The Strangecode Codebase.
+ *
+ * The Strangecode Codebase is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * The Strangecode Codebase is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * js.php
+ *
+ * This file works with the JS class to print a minified JS file, to be
+ * included as any JS file would be. It should not be necessary to
+ * ever modify this file.
+ */
+if (is_a($js, 'JS')) {
+    $js->headers(getFormData('app'));
+    $js->output(getFormData('app'));
+}
+
