Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

More javascript improvements; build jQuery extensions.

  • Loading branch information...
commit feaddab53d64dfb4cd7bc83f69ba5383c52ead92 1 parent 7e0fad5
@Deconstrained authored
View
12 CHANGELOG.md
@@ -1,5 +1,12 @@
Pre-release:
=====
+##9/11/12
+- Consolidated alert widgets into a single jQuery UI widget
+- Converted content loading and load overlay functions to jQuery extensions, even applyJsToContent.
+- Improved hash history (tightened rules)
+- Discovered Dojo ShrinkSafe, so added a conditional statement to use the minified code.
+- Added NoScript message and global/system messages area
+
##9/9/12
- Updated to latest Yii
- Updated to newest Foundation. Had to remove all but the CSS.
@@ -11,7 +18,10 @@ Pre-release:
- Major strides towards universal permalinking
- Added some documentation here and there as I progressed
- Refactored controllers and some components to have "G" prefix
-- Improved the schema definition (I learned how to use MySQL workbench, so from now I'm using forward-engineer to generate it)
+- Improved the schema definition;
+ - I learned how to use MySQL workbench, so from now I'm using forward-engineer to generate it. Now the schema for creation is generated by it.
+ - Added site log table
+ - Added tables for inserting long textual data
- Some changes to InstallController::actionInstall
- Refactoring in InstallController; passing $model and $db as arguments. May not work.
- Added options table and new tables for long written submissions
View
3  README.md
@@ -7,6 +7,7 @@ This aims to be a social writing/publishing and peer review web application. Cur
##Acknowledgments
- [Zurb Inc.](http://foundation.zurb.com/)
- [HTML5 Boilerplate](http://html5boilerplate.com/)
+- Dean Edwards, for [Packer](http://dean.edwards.name/packer/)
- The following users on StackOverflow, for the useful information they have shared:
- [CoolAJ86](http://stackoverflow.com/a/6969486)
- [janogonzalez](http://stackoverflow.com/a/3261380)
@@ -43,7 +44,7 @@ This aims to be a social writing/publishing and peer review web application. Cur
<code> <?php return array('/loading.png','/css/images/overlay.png'); ?></code>
-11. Protect the theme folder by copying the .htaccess file from another theme's folder into the root level of your theme's folder. It will then be safe to override view files by putting them in (yourtheme)/views/(controller ID)/(view name) (see: [Special topics: Theming](http://www.yiiframework.com/doc/guide/1.1/en/topics.theming#creating-a-theme)
+Finally, protect the theme folder by copying the .htaccess file from another theme's folder into the root level of your theme's folder. It will then be safe to override view files by putting them in (yourtheme)/views/(controller ID)/(view name) (see: [Special topics: Theming](http://www.yiiframework.com/doc/guide/1.1/en/topics.theming#creating-a-theme)
Happy theming!
View
25 TODO.md
@@ -1,13 +1,23 @@
TODO
=====
-- Develop / test permalink method. Idea: use jQuery.find to see if an element with name equal to the permalink format
-- Simplify the plan for dummy data; simplify everything in general
-- Messages area, global NoScript message.
+- Develop a way of minifying javascript
+- RBAC:
+ - Write a script to parse the codebase and generate auth items for each action
+ - Formalize the process of adding actions as children, i.e. comment format for leaving reminders
+ - Develop a new filter class that does comparisons
+ - Find out how business rule data is inherited
+- Dummy data for:
+ - A single long thread, to test permalinking
+ - Several users
+- Write model/view/controller for threads:
+ - Have a lookup feature; send it a child ID, and it shall render the appropriate range of posts that contains it
+ - Requests for the thread only retrieve a little at a time (chunks dictated by a page range)
+ - Pagination buttons
+- Develop / test permalink method using dummy data and the thread view
+
- Experiment: once installed, see if db changes to a user show up in CWebUser immediately or after logout/login.
-- GENERATE DUMMY DATA! Add it. Churn out some views!
- For the schema:
- - Schema: add site log table
- - Come up with a "periodic table" of type labels. Think of what we want to do, and all thread-like objects (things users post that can be commented on).
+ - Continue building a "periodic table" of type labels. Think of what we want to do, and all thread-like objects (things users post that can be commented on).
- Come up with a general way to rank posts using other posts
- Come up with a way to cache statistics based on it, to make them easier to retrieve.
- Make sure it is possible to constrain the creation of new tags
@@ -18,8 +28,7 @@ TODO
- Put another few fields in to user; "theme" for instance. Add everything into user :-P
- Add theme picker to installer and have it write into the options table
- Come up with pages or error messages displayed for the user identity statuses ERROR_STATUS_NOTACTIV and ERROR_STATUS_BAN.
-- Write a behavioral class that instantiates DateTime objects in fields for DATETIME-type MySQL fields (after retrieval).
+- Write a behavioral class that instantiates DateTime objects in fields for DATETIME-type MySQL fields (after retrieval). Change time to long int or something
- Study critiquecircle.com, and get some more ideas!
- Sometime in the future: some method of taking initial configuration values (in an installer), i.e. the form, and putting them into the config file "custom.php"
- Replace user emailing with a fancy schmancy instantiation of PHPMailer (use a Yii extension or toss PHPMailer in components, it doesn't matter that much how), and have it send nice HTML emails to users for authentication. Use view files for email templates.
-- Much later: RBAC
View
46 webroot/css/main.css
@@ -24,8 +24,7 @@ h2 {
}
#mainmenu {
- border-width: 0 1px 1px 1px;
- border-style: solid;
+
}
#mainmenu-items {
@@ -49,32 +48,54 @@ div.loading-overlay
height: 0px;
}
-.ui-custom-alert {
+.ui-gummii-notice {
display: inline-block;
padding: 5px;
}
-.ui-custom-alert .ui-icon.ui-custom-alert-icon {
+.ui-gummii-notice > .ui-icon.ui-gummii-notice-icon {
display: inline-block;
margin-right: 0.5em;
+ margin-bottom: 0;
+}
+.ui-gummii-notice > .ui-gummii-notice-dismiss {
+ cursor: pointer;
}
-.ui-custom-alert .ui-custom-elt {
+.ui-gummii-notice > .ui-gummii-elt {
display: inline-block;
vertical-align: middle;
}
-.error.ui-custom-alert.ui-state-error .ui-custom-elt-text {
+.error.ui-gummii-notice.ui-state-error > .ui-gummii-elt-text {
font-weight: bold;
margin:3px;
}
-.ui-custom-alert .ui-custom-elt-text {
+.ui-gummii-notice .ui-gummii-elt-text {
font-size: 14px;
-
+
}
-.ui-custom-alert .ui-custom-elt > * {
+.ui-gummii-notice > * {
vertical-align:center;
padding: 0;
}
+header {
+ position:fixed;
+ width: 100%;
+ padding: 0;
+ top:0;
+ z-index:1;
+}
+
+header > #system-notice div {
+ text-align: center;
+}
+header > #system-notice div div {
+ display: inline-block;
+ margin-left: 10px;
+ vertical-align: middle;
+ font-weight: bold;
+ font-size: 14px;
+}
/* Overrides & resets of Foundation stuff */
a {color: blue;}
a:visited {color: purple;}
@@ -84,7 +105,12 @@ a:hover {color: red;}
.nav-bar>li.mainmenu{background:transparent;}
.nav-bar>li>a {vertical-align: middle; line-height: 40px;}
.row{width:100%}
-#mainmenu {position:fixed; width: 100%; z-index:1}
+
+#mainmenu {
+ width: 100%;
+ border-width: 0 1px 1px 1px;
+ border-style: solid;
+}
#content-wrapper {margin-top:41px;}
@media only screen and (max-width: 767px) {
View
371 webroot/js/gummii-base.js
@@ -1,371 +0,0 @@
-
-//
-//
-// // Escape regex characters)
-// (with thanks to CoolAJ86 on StackOverflow (http://stackoverflow.com/a/6969486/1325798)
-escapeRegExp = function (str) {
- return str.replace(RegExp('[' + ["-", "[", "]", "/", "{", "}", "(", ")", "*", "+", "?", ".", "\\", "^", "$", "|"].join('\\') + ']', 'g'), "\\$&");
-};
-
-// http://stackoverflow.com/a/3261380
-function isBlank(str) {
- return (!str || /^\s*$/.test(str));
-}
-// Regular expression turning any URL fragment into a javascript-friendly object name.
-reqToScriptId = new RegExp('[;\/\?\+:@=#&]','g');
-
-// Function for turning a unique request into a unique ID for scripts
-function createScriptId(reqUrl) {
- return reqUrl.replace(appBaseUrl,'').replace(reqToScriptId,'_')+'_';
-}
-
-$ = jQuery;
-
-/////////////////////////////////////////////////////////////
-// Load overlay and AJAX-Driven content handling functions //
-/////////////////////////////////////////////////////////////
-
-// Flag for loading content upon hash change
-_respondToHashChange = true;
-
-// Remove a loading overlay from an element.
-function removeLoadOverlay(elt) {
- $(elt).removeClass('loading').find('.loading-overlay').remove();
-}
-
-// Mark an element as loading, and return the Timeout object so it can be
-// cleared if necessary.
-//
-// container (string): Selector for the containing block that is loading
-// full (bool): whether or not to put the overlay over the full screen
-function setLoading(container,full) {
- removeLoadOverlay(container); // remove any preexisting ones
- var jcont = $(container).addClass('loading');
- return setTimeout(function(){
- // Cases:
- // 1. Small piece of content loading: overlay covers piece
- // 2. Content loading, large screen: overlay fixed, covers window below main menu
- // 3. Content loading, small scrreen: overlay fixed, covers full window
- //
- // Get dimensions:
- var mobile = (window.innerWidth < 767); // See media query in css/foundation.css
- var cHeight = jcont.outerHeight(); // Container height
- var wHeight = mobile ? window.outerHeight : window.innerHeight-41; // Window height
- var content = (cHeight > wHeight)||full; // Whether to apply the load overlay to the whole main content
- var jOffset = jcont.offset();
- var offset = {
- 'top':content&&mobile?0:jOffset.top,
- 'left':jOffset.left
- };
- var contDim = [jcont.outerWidth(),(content&&mobile)||full?wHeight:Math.min(cHeight,wHeight)];
- var minDim = Math.min(contDim[0],contDim[1]);
- var imgDim = Math.min(minDim/2,100);
- var imgPix = Math.floor(imgDim);
- // Construct the loading image:
- var loadingImg = $('<img>').attr({
- 'src':themeBaseUrl+'/loading.png',
- 'width':imgPix,
- 'height':imgPix
- }).css({
- 'position':'absolute',
- 'top':Math.floor(((contDim[1])-imgDim)/2.0)+'px',
- 'left':Math.floor((contDim[0]-imgDim)/2)+'px'
- });
- // Construct the overlay:
- var overlay = $('<div class="loading-overlay">').append(loadingImg).css({
- 'position':content ? 'fixed' : 'absolute',
- 'top':offset.top,
- 'left':offset.left,
- 'width':Math.floor(contDim[0])+'px',
- 'height':Math.min(Math.floor(contDim[1]),window.innerHeight)+'px'
- });
- // Add the overlay to the containing block
- jcont.append(overlay);
-
- // Rotate the loading image:
- var angle = 0;
- setInterval(function(){
- angle+=6;
- $(loadingImg).rotate(angle);
- },25);
-
- },250); // Only invoked after 250 ms of waiting. Otherwise, just snap to it.
-}
-
-// Global object for storing and manipulating content loading timeout objects
-loadOverlay = {
- list:[]
-}
-// Cancel a load overlay timeout and remove it from the list
-loadOverlay.clear = function(timeout) {
- this.list = $.grep(this.list, function(x){
- return x!=timeout;
- });
- clearTimeout(timeout);
-};
-// Cancel all timeouts
-loadOverlay.cancelAll = function() {
- $(this.list).each(function(i,timeOut) {
- clearTimeout(timeOut);
- });
- this.list = [];
-};
-// Cancel all timeouts and remove all loading visual overlays
-loadOverlay.clearAll = function() {
- this.cancelAll(); // Prevent new ones from forming
- // Remove all "loading" visual overlay elements from an element.
- $('.loading').each(function(i,elt) {
- removeLoadOverlay(elt);
- });
-};
-// Object for queueing and tracking of content loading via AJAX:
-ajaxQueue = {
- queue:[]
-}
-// Cancels all XMLHttpRequests that have been inserted in the queue
-ajaxQueue.abortAll = function() {
- $(this.queue).each(function(i,req){
- if(req.status != 200) {
- console.log('aborting:');
- console.log(req);
- req.abort();
- }
- });
- this.queue = [];
-}
-
-// Obtain content from the server and display within an element.
-//
-// This is the master function used for loading pages.
-// reqUrl (string) : request URL
-// elt (mixed) : selector or DOM element in which to load the content.
-// f (boolean,optional) : whether or not to put the loading overlay on the full main content section. Default is no.
-// p (boolean,optional) : whether or not to push the current state into history; default is no.
-// r (boolean,optional) : retrieve content even if the hash fragment isn't changing; default is yes.
-function loadContent(url,elt,f,p,r) {
- // Whether or not it's a full page load. Assume it is by default.
- var full = f?f:false;
- var push = p?p:false;
- var reload = r?r:true;
- var req = url.split(hashBoundary);
- var reqUrl = req[0];
-
- if(url.replace(appBaseUrl+'/','') != $.param.fragment() || reload) {
- // A new page or location is being accessed.
- if(push) {
- // New page/location, new state. Disable the listener to avoid
- // redundant (and potentially hazardous) extra call to this function
- // by setting the flag to false:
- _respondToHashChange = false;
- $.bbq.pushState(reqUrl.replace(appBaseUrl+'/','#'));
- }
- // Mark the element/page as loading:
- var loadOverCont = setLoading(elt,full);
- if(full) { // Clear all the other loading overlays and requests; whole page refresh.
- console.log('queue, pre-abort:');
- console.log(ajaxQueue.queue);
- ajaxQueue.abortAll();
- loadOverlay.clearAll();
- }
- loadOverlay.list.push(loadOverCont);
- // Request content from the server via AJAX
- //
- // TODO: Make it so that for intra-site links, if the permalink is
- // available within the document already, avoid making a superfluous
- // AJAX request (instead, merely change the scroll location).
- ajaxQueue.queue.push($.ajax({
- 'dataType':'html',
- 'url':reqUrl,
- 'success':function(d,t,j) {
- loadOverlay.clear(loadOverCont);
- console.log('in javascript, script id = '+'#'+createScriptId(reqUrl));
- console.log($(d).find('#'+createScriptId(reqUrl)));
- $(elt).html(d);
- applyJsToContent(elt);
- console.log('queue, post-abort:');
- console.log(ajaxQueue.queue);
- },
- // TODO: expand on this, maybe have some kind of error reporting
- // mechanism, i.e. an error symbol and little portlet / dialog that
- // shows the errors.
- 'error':function(d,t,j) {
- loadOverlay.clear(loadOverCont);
- applyJsToContent(elt);
- }
- }));
- // Get rid of the load overlay now that everything is done (whether an
- // error or success):
- removeLoadOverlay(elt);
- }
-
- if(req[1]) {
- var permalink = url.replace(appBaseUrl+'/','');
-
- }
-}
-
-
-////////////////////////////////
-// UI functions and variables //
-////////////////////////////////
-
-// Widget for informational messages:
-$.widget( "custom.notice", {
- // default options
- options: {
- // callbacks
- dismiss: null
- },
- // the constructor
- _create: function() {
- var that = this;
- var uiState = "ui-state-highlight";
- var uiIcon = "ui-icon-info";
- this.icon = $( "<div>", {
- "class": "ui-icon ui-custom-alert-icon ui-custom-elt "+uiIcon
- });
- this.dismissButton = $("<div>", {
- "class":"ui-state-default ui-corner-all, ui-custom-elt ui-custom-notice-dismiss"
- }).append($("<div>",{
- "class":"ui-icon ui-icon-close ui-custom-notice-elt"
- })).button();
- this.textWrapper = $('<div>', {
- 'class':"ui-custom-elt ui-custom-elt-text"
- }).html(that.element.html());
- console.log(that.element.innerWidth()-(that.dismissButton.outerWidth()+that.icon.outerWidth()+10));
- this.element.addClass( "ui-custom-alert ui-corner-all "+uiState).disableSelection().html('').append(that.icon).append(that.textWrapper).append(that.dismissButton);
- this.textWrapper.css({
- 'width':that.element.innerWidth()-(that.dismissButton.outerWidth()+that.icon.outerWidth()+30)+'px'
- });
-
- this.dismissButton.bind("click.ui-custom-notice", function(e){
- that.element.fadeOut();
- });
- }
-});
-// Widget for error messages:
-$.widget( "custom.error", {
- // default options
- options: {
- // callbacks
- dismiss: null
- },
- // the constructor
- _create: function() {
- var that = this;
- var uiState = "ui-state-error";
- var uiIcon = "ui-icon-alert";
- this.icon = $( "<div>", {
- "class": "ui-icon ui-custom-alert-icon ui-custom-elt "+uiIcon
- });
- this.dismissButton = $("<div>", {
- "class":"ui-state-default ui-corner-all, ui-custom-elt ui-custom-notice-dismiss"
- }).append($("<div>",{
- "class":"ui-icon ui-icon-close ui-custom-notice-elt"
- })).button();
- this.textWrapper = $('<div>', {
- 'class':"ui-custom-elt ui-custom-elt-text"
- }).html(that.element.html());
- console.log(that.element.innerWidth()-(that.dismissButton.outerWidth()+that.icon.outerWidth()+10));
- this.element.addClass( "ui-custom-alert ui-corner-all "+uiState).disableSelection().html('').append(that.icon).append(that.textWrapper).append(that.dismissButton);
- this.textWrapper.css({
- 'width':that.element.innerWidth()-(that.dismissButton.outerWidth()+that.icon.outerWidth()+30)+'px'
- });
-
- this.dismissButton.bind("click.ui-custom-notice", function(e){
- that.element.fadeOut();
- });
- }
-});
-
-
-// Function for applying jQuery UI styling and construction.
-//
-// EVERYTHING pertaining to the UI such that it can appear in the main
-// content section, that is not an event listener, shall be placed in this
-// function. This is because when markup retrieved by AJAX is rendered, Javascript
-// that would otherwise apply to it has already run (when the page initially
-// loaded). Hence, it won't apply to new markup, and must be run again to
-// transform it as necessary. However, this can be circumvented in the case
-// of event handling by using the "live" function, thus lightening the load.
-// See: http://stackoverflow.com/a/4742845
-//
-// content (mixed): selector or DOM object inside which to apply jQuery
-function applyJsToContent(content) {
- console.log(content);
- var c = $(content);
- var f = function (sel) {
- return c.find(sel);
- };
- // jQuery UI buttons:
- f('.button').button();
- f('.notice').notice();
- f('.error').error();
-}
-
-// Javascript to be run when the DOM has fully loaded:
-jQuery(document).ready(function ($) {
- var fragment = $.param.fragment();
- loadContent(appBaseUrl+'/'+fragment,'#content-wrapper',!isBlank(fragment),true,true);
-
- // Global keybindings:
- $(document).keydown(function(e) {
- var KEYCODE_ESC = 27;
- var KEYCODE_F5 = 116;
- if(e.keyCode == KEYCODE_F5) { // Refresh main content
- e.preventDefault();
- e.stopPropagation();
- loadContent(appBaseUrl+'/'+$.param.fragment(),'#content-wrapper',true,false,true);
- }
- if(e.keyCode == KEYCODE_ESC) { // Abort all content requests
- ajaxQueue.abortAll();
- loadOverlay.clearAll();
- }
- });
-
- // Hash change event listener; allows the back button to work in the AJAX-driven system
- $(window).bind('hashchange.internal', function(e) {
- if(_respondToHashChange===true)
- loadContent(appBaseUrl+'/'+$.param.fragment(),'#content-wrapper',true,false,true);
- // If the current hash change has been skipped over, re-enable response.
- _respondToHashChange = true;
- });
-
- // For intra-site links: instead of going to them, change the hash and reload
- // the main content section with content served via AJAX
- $('a').live('click.internal',function(event) {
- // First, stop it from requesting the actual page
- event.preventDefault();
- var url=$(this).attr('href');
- var internal = new RegExp(escapeRegExp(appBaseUrl)+'\\/.*');
- if(internal.test(url)) {
- var notBase = new RegExp(escapeRegExp(appAbsBaseUrl)+'\\/[^#].*');
- if(notBase.test(window.location.href)) {
- // Remove everything out of the base URL,append the hash and change
- // browser window location in order to keep the URL clean.
- window.location.href = appAbsBaseUrl+'/#'+url.replace(appBaseUrl+'/','');
- } else {
- // Retrieve partial content from the server:
- loadContent(url,'#content-wrapper',true,true,false);
- }
- } else {
- // Free to go; it's an external link.
- window.location.href = url;
- }
- });
-
- // Main menu stuff:
- $('div#mainmenu').find('li').hover(
- function() {
- $(this).addClass('ui-state-hover').removeClass('mainmenu');
- },
- function() {
- $(this).removeClass('ui-state-hover').addClass('mainmenu');
- }).bind('mouseup mousedown',function(){
- $(this).toggleClass('ui-state-active');
- });
-
- // Final document initialization:
- applyJsToContent(document);
-
-});
View
353 webroot/js/gummii-core.js
@@ -0,0 +1,353 @@
+////
+// Consolidated core Javascript file.
+//
+// This contains all the most basic javascript features of the app.
+
+// Escape regex characters)
+// (with thanks to CoolAJ86 on StackOverflow (http://stackoverflow.com/a/6969486/1325798)
+escapeRegExp = function (str) {
+ return str.replace(RegExp('[' + ["-", "[", "]", "/", "{", "}", "(", ")", "*", "+", "?", ".", "\\", "^", "$", "|"].join('\\') + ']', 'g'), "\\$&");
+};
+
+// http://stackoverflow.com/a/3261380
+function isBlank(str) {
+ return (!str || /^\s*$/.test(str));
+}
+// Regular expression turning any URL fragment into a javascript-friendly object name.
+reqToScriptId = new RegExp('[;\/\?\+:@=#&]','g');
+
+// Function for turning a unique request into a unique ID for scripts
+function createScriptId(reqUrl) {
+ return reqUrl.replace(appBaseUrl,'').replace(reqToScriptId,'_')+'_';
+}
+
+$ = jQuery;
+
+/////////////////////////////////////////////////////////////
+// Load overlay and AJAX-Driven content handling functions //
+/////////////////////////////////////////////////////////////
+
+// Flag for loading content upon hash change
+_respondToHashChange = true;
+
+// Global object for storing and manipulating content loading timeout objects
+loadOverlay = {
+ list:{},
+ // Cancel a load overlay timeout and remove it from the list
+ clear: function(jqElt) {
+ clearTimeout(this.list[jqElt]);
+ jqElt.find('.loading-overlay').remove();
+ },
+ remove: function(jqElt) {
+ this.clear(jqElt);
+ delete(this.list[jqElt]);
+ },
+ clearAll: function() {
+ for (i in this.list)
+ this.clear(i);
+ this.list = {};
+ }
+}
+
+// Object for queueing and tracking of content loading via AJAX:
+ajaxQueue = {
+ queue:{},
+ // Cancel all timeouts and remove all loading visual overlays
+ remove: function(jqElt) {
+ if(this.queue[jqElt]!=undefined)
+ delete(this.queue[jqElt]);
+ },
+ // Cancels all XMLHttpRequests that have been inserted in the queue
+ abortAll: function() {
+ for (i in this.queue)
+ if(this.queue[i].status != 200)
+ this.queue[i].abort();
+ this.queue = {};
+ }
+}
+
+// Obtain content from the server and display within an element.
+//
+// This is the master function used for loading pages. The options are as follows:
+// url (string) : The url being requested.
+// elt (mixed) : selector or DOM element in which to load the content.
+// full (boolean, default false) : whether or not to put the loading overlay on the full main content section.
+// reload (boolean, default true) : retrieve content even if the hash fragment isn't changing.
+// done (callback) : function to run after successfully making the request
+// always (callback) : function to run after the request ends
+$.fn.loadContent = function(options) {
+ var that = this;
+ var opt = $.extend( {
+ full: false,
+ reload: true,
+ done: function(){},
+ always: function(){},
+ error: function(){}
+ }, options);
+ var req = opt.url.split('#');
+
+ if(req[0].replace(appBaseUrl+'/','') != $.param.fragment().split(hashBoundary)[0] || opt.reload) {
+ // A new page or location is being accessed.
+ if(opt.full) { // Clear all the other loading overlays and requests; whole page refresh.
+ ajaxQueue.abortAll();
+ loadOverlay.clearAll();
+ }
+
+ // Mark the element/page as loading:
+ var loadOverCont = this.setLoading({
+ full:true
+ });
+
+ // Request content from the server via AJAX
+ //
+ // TODO: Make it so that for intra-site links, if the permalink is
+ // available within the document already, avoid making a superfluous
+ // AJAX request (instead, merely change the scroll location).
+ //
+ // TODO: expand on this, maybe have some kind of error reporting
+ // mechanism, i.e. an error symbol and little portlet / dialog that
+ // shows the errors.
+ ajaxQueue.queue[loadOverCont] = $.ajax({
+ 'dataType':'html',
+ 'url':req[0]
+ }).done(function(d,t,j) {
+ that.html(d).applyJsToContent();
+ opt.done();
+ }).always(function(d,t,j) {
+ // Get rid of the load overlay now that everything is done (whether an
+ // error or success):
+ loadOverlay.remove(loadOverCont);
+ ajaxQueue.remove(loadOverCont);
+ opt.always();
+ });
+ }
+ return this;
+}
+
+
+////////////////////////////////
+// UI functions and variables //
+////////////////////////////////
+
+// Mark an element as loading.
+//
+// container (string): Selector for the containing block that is loading
+// full (bool): whether or not to put the overlay over the full screen
+$.fn.setLoading = function (options) {
+ var that = this;
+ var opt = $.extend( {
+ full: false
+ }, options);
+ var mobile = (window.innerWidth < 767); // See media query in css/foundation.css
+ var wHeight = mobile ? window.outerHeight : window.innerHeight-41; // Window height
+
+ loadOverlay.list[this] = setTimeout(function(){
+ // Cases:
+ // 1. Small piece of content loading: overlay covers piece
+ // 2. Content loading, large screen: overlay fixed, covers window below main menu
+ // 3. Content loading, small scrreen: overlay fixed, covers full window
+ //
+ // Get dimensions:
+ var cHeight = that.outerHeight(); // Container height
+ var content = (cHeight > wHeight)||opt.full; // Whether to apply the load overlay to the whole main content
+ var jOffset = that.offset();
+ var offset = {
+ 'top':content&&mobile?0:jOffset.top,
+ 'left':jOffset.left
+ };
+ var contDim = [that.outerWidth(),(content&&mobile)||opt.full?wHeight:Math.min(cHeight,wHeight)];
+ var minDim = Math.min(contDim[0],contDim[1]);
+ var imgDim = Math.min(minDim/2,100);
+ var imgPix = Math.floor(imgDim);
+ // Construct the loading image:
+ var loadingImg = $('<img>').attr({
+ 'src':themeBaseUrl+'/loading.png',
+ 'width':imgPix,
+ 'height':imgPix
+ }).css({
+ 'position':'absolute',
+ 'top':Math.floor(((contDim[1])-imgDim)/2.0)+'px',
+ 'left':Math.floor((contDim[0]-imgDim)/2)+'px'
+ });
+ // Construct the overlay:
+ var overlay = $("<div>").addClass("loading-overlay").append(loadingImg).css({
+ 'position':content ? 'fixed' : 'absolute',
+ 'top':offset.top,
+ 'left':offset.left,
+ 'width':Math.floor(contDim[0])+'px',
+ 'height':Math.min(Math.floor(contDim[1]),window.innerHeight)+'px'
+ });
+ // Add the overlay to the containing block
+ that.addClass('loading').append(overlay);
+
+ // Rotate the loading image:
+ var angle = 0;
+ setInterval(function(){
+ angle+=6;
+ $(loadingImg).rotate(angle);
+ },25);
+
+ },100); // Only invoked after 100 ms of waiting. Otherwise, just snap to it.
+ return this;
+}
+
+// Widget for informational messages:
+$.widget("custom.notice", {
+ options: {
+ type: null,
+ bold: false
+ },
+ _create: function() {
+ var that = this;
+ this.icon = $( "<div>", {
+ "class": "ui-icon ui-gummii-notice-icon ui-gummii-elt" // +uiIcon
+ });
+ this.dismissButton = $("<div>", {
+ "class":"ui-gummii-elt ui-gummii-notice-dismiss"
+ }).append($("<div>",{
+ "class":"ui-icon ui-icon-close ui-gummii-notice-elt"
+ }));
+ this.textWrapper = $('<div>', {
+ 'class':"ui-gummii-elt ui-gummii-elt-text"
+ }).html(that.element.html());
+ this.dismissButton.bind("click.ui-gummii-notice", function(e){
+ that.element.fadeOut();
+ });
+ var uiState = ({
+ error:'ui-state-error',
+ info:'ui-state-highlight'
+ })[this.options.type];
+ var uiIcon = ({
+ error:'ui-icon-alert',
+ info:'ui-icon-info'
+ })[this.options.type];
+ this.icon.addClass(uiIcon);
+ if(uiIcon != undefined) {
+ this.element.addClass( "ui-gummii-notice ui-corner-all "+uiState).disableSelection().html('')
+ .append(that.icon)
+ .append(that.textWrapper)
+ .append(that.dismissButton);
+ }
+ this.textWrapper.css({
+ 'width':that.element.innerWidth()-(that.dismissButton.outerWidth()+that.icon.outerWidth()+30)+'px',
+ 'font-weight':that.options.bold ? 'bold' : 'normal'
+ });
+ }
+});
+
+// Function for applying jQuery UI styling and construction.
+//
+// EVERYTHING pertaining to the UI such that it can appear in the main
+// content section, that is not an event listener, shall be placed in this
+// function. This is because when markup retrieved by AJAX is rendered, Javascript
+// that would otherwise apply to it has already run (when the page initially
+// loaded). Hence, it won't apply to new markup, and must be run again to
+// transform it as necessary. However, this can be circumvented in the case
+// of event handling by using the "live" function, thus lightening the load.
+// See: http://stackoverflow.com/a/4742845
+//
+// content (mixed): selector or DOM object inside which to apply jQuery
+$.fn.applyJsToContent = function() {
+ var f = function (jq,sel) {
+ return jq.find(sel);
+ };
+ this.find('.gummii-notice').notice({
+ type:'info'
+ });
+ this.find('.gummii-error').notice({
+ type:'error',
+ bold:true
+ });
+}
+
+// Javascript to be run when the DOM has fully loaded:
+jQuery(document).ready(function ($) {
+ var fragment = $.param.fragment();
+ $('#content-wrapper').loadContent({
+ url:appBaseUrl+'/'+fragment,
+ full:!isBlank(fragment),
+ reload:true
+ });
+
+ // Global keybindings:
+ $(document).keydown(function(e) {
+ var KEYCODE_ESC = 27;
+ var KEYCODE_F5 = 116;
+ if(e.keyCode == KEYCODE_F5) { // Refresh main content
+ e.preventDefault();
+ e.stopPropagation();
+ $('#content-wrapper').loadContent({
+ url:appBaseUrl+'/'+$.param.fragment(),
+ full:true,
+ reload:true
+ });
+ }
+ if(e.keyCode == KEYCODE_ESC) { // Abort all content requests
+ ajaxQueue.abortAll();
+ loadOverlay.clearAll();
+ _respondToHashChange = true;
+ }
+ });
+
+ // Hash change event listener; allows the back button to work in the AJAX-driven system
+ $(window).bind('hashchange.internal', function(e) {
+ if(_respondToHashChange===true)
+ $('#content-wrapper').loadContent({
+ url:appBaseUrl+'/'+$.param.fragment(),
+ full:true,
+ reload:true
+ });
+ // If the current hash change has been skipped over, re-enable response.
+ _respondToHashChange = true;
+ });
+
+ // For intra-site links: instead of going to them, change the hash and reload
+ // the main content section with content served via AJAX
+ $('a').on('click.internal',function(event) {
+ // First, stop it from requesting the actual page
+ event.preventDefault();
+ var url = $(this).attr('href');
+ var internal = new RegExp(escapeRegExp(appBaseUrl)+'\\/.*');
+ if(internal.test(url)) {
+ var notBase = new RegExp(escapeRegExp(appAbsBaseUrl)+'\\/[^#].*');
+ if(notBase.test(window.location.href)) {
+ // Remove everything out of the base URL,append the hash and change
+ // browser window location in order to keep the URL clean.
+ window.location.href = appAbsBaseUrl+'/#'+url.replace(appBaseUrl+'/','');
+ } else {
+ // New page/location, new state. Disable the listener to avoid
+ // redundant (and potentially hazardous) extra call to the above
+ // function by setting the flag to false:
+ _respondToHashChange = false;
+ $('#content-wrapper').loadContent({
+ 'url':url,
+ full:true,
+ reload:false
+ });
+ $.bbq.pushState(url.replace('#',hashBoundary).replace(appBaseUrl+'/','#'));
+ // Push the route into the hash state after converting it from
+ // its Javascript-agnostic form. Do so *after* loading to
+ // emulate true browser behavior.
+
+ }
+ } else {
+ // Free to go; it's an external link.
+ window.location.href = url;
+ }
+ });
+
+ // Main menu stuff:
+ $('div#mainmenu').find('li').hover(
+ function() {
+ $(this).addClass('ui-state-hover').removeClass('mainmenu');
+ },
+ function() {
+ $(this).removeClass('ui-state-hover').addClass('mainmenu');
+ }).bind('mouseup mousedown',function(){
+ $(this).toggleClass('ui-state-active');
+ });
+
+ // Final document initialization:
+ $(document).applyJsToContent();
+
+});
View
158 webroot/js/gummii-core.min.js
@@ -0,0 +1,158 @@
+escapeRegExp=function(_1){
+return _1.replace(RegExp("["+["-","[","]","/","{","}","(",")","*","+","?",".","\\","^","$","|"].join("\\")+"]","g"),"\\$&");
+};
+function isBlank(_2){
+return (!_2||/^\s*$/.test(_2));
+};
+reqToScriptId=new RegExp("[;/?+:@=#&]","g");
+function createScriptId(_3){
+return _3.replace(appBaseUrl,"").replace(reqToScriptId,"_")+"_";
+};
+$=jQuery;
+_respondToHashChange=true;
+loadOverlay={list:{},clear:function(_4){
+clearTimeout(this.list[_4]);
+_4.find(".loading-overlay").remove();
+},remove:function(_5){
+this.clear(_5);
+delete (this.list[_5]);
+},clearAll:function(){
+for(i in this.list){
+this.clear(i);
+}
+this.list={};
+}};
+ajaxQueue={queue:{},remove:function(_6){
+if(this.queue[_6]!=undefined){
+delete (this.queue[_6]);
+}
+},abortAll:function(){
+for(i in this.queue){
+if(this.queue[i].status!=200){
+this.queue[i].abort();
+}
+}
+this.queue={};
+}};
+$.fn.loadContent=function(_7){
+var _8=this;
+var _9=$.extend({full:false,reload:true,done:function(){
+},always:function(){
+},error:function(){
+}},_7);
+var _a=_9.url.split("#");
+if(_a[0].replace(appBaseUrl+"/","")!=$.param.fragment().split(hashBoundary)[0]||_9.reload){
+if(_9.full){
+ajaxQueue.abortAll();
+loadOverlay.clearAll();
+}
+var _b=this.setLoading({full:true});
+ajaxQueue.queue[_b]=$.ajax({"dataType":"html","url":_a[0]}).done(function(d,t,j){
+_8.html(d).applyJsToContent();
+_9.done();
+}).always(function(d,t,j){
+loadOverlay.remove(_b);
+ajaxQueue.remove(_b);
+_9.always();
+});
+}
+return this;
+};
+$.fn.setLoading=function(_c){
+var _d=this;
+var _e=$.extend({full:false},_c);
+var _f=(window.innerWidth<767);
+var _10=_f?window.outerHeight:window.innerHeight-41;
+loadOverlay.list[this]=setTimeout(function(){
+var _11=_d.outerHeight();
+var _12=(_11>_10)||_e.full;
+var _13=_d.offset();
+var _14={"top":_12&&_f?0:_13.top,"left":_13.left};
+var _15=[_d.outerWidth(),(_12&&_f)||_e.full?_10:Math.min(_11,_10)];
+var _16=Math.min(_15[0],_15[1]);
+var _17=Math.min(_16/2,100);
+var _18=Math.floor(_17);
+var _19=$("<img>").attr({"src":themeBaseUrl+"/loading.png","width":_18,"height":_18}).css({"position":"absolute","top":Math.floor(((_15[1])-_17)/2)+"px","left":Math.floor((_15[0]-_17)/2)+"px"});
+var _1a=$("<div>").addClass("loading-overlay").append(_19).css({"position":_12?"fixed":"absolute","top":_14.top,"left":_14.left,"width":Math.floor(_15[0])+"px","height":Math.min(Math.floor(_15[1]),window.innerHeight)+"px"});
+_d.addClass("loading").append(_1a);
+var _1b=0;
+setInterval(function(){
+_1b+=6;
+$(_19).rotate(_1b);
+},25);
+},100);
+return this;
+};
+$.widget("custom.notice",{options:{type:null,bold:false},_create:function(){
+var _1c=this;
+this.icon=$("<div>",{"class":"ui-icon ui-gummii-notice-icon ui-gummii-elt"});
+this.dismissButton=$("<div>",{"class":"ui-gummii-elt ui-gummii-notice-dismiss"}).append($("<div>",{"class":"ui-icon ui-icon-close ui-gummii-notice-elt"}));
+this.textWrapper=$("<div>",{"class":"ui-gummii-elt ui-gummii-elt-text"}).html(_1c.element.html());
+this.dismissButton.bind("click.ui-gummii-notice",function(e){
+_1c.element.fadeOut();
+});
+var _1d=({error:"ui-state-error",info:"ui-state-highlight"})[this.options.type];
+var _1e=({error:"ui-icon-alert",info:"ui-icon-info"})[this.options.type];
+this.icon.addClass(_1e);
+if(_1e!=undefined){
+this.element.addClass("ui-gummii-notice ui-corner-all "+_1d).disableSelection().html("").append(_1c.icon).append(_1c.textWrapper).append(_1c.dismissButton);
+}
+this.textWrapper.css({"width":_1c.element.innerWidth()-(_1c.dismissButton.outerWidth()+_1c.icon.outerWidth()+30)+"px","font-weight":_1c.options.bold?"bold":"normal"});
+}});
+$.fn.applyJsToContent=function(){
+var f=function(jq,sel){
+return jq.find(sel);
+};
+this.find(".gummii-notice").notice({type:"info"});
+this.find(".gummii-error").notice({type:"error",bold:true});
+};
+jQuery(document).ready(function($){
+var _1f=$.param.fragment();
+$("#content-wrapper").loadContent({url:appBaseUrl+"/"+_1f,full:!isBlank(_1f),reload:true});
+$(document).keydown(function(e){
+var _20=27;
+var _21=116;
+if(e.keyCode==_21){
+e.preventDefault();
+e.stopPropagation();
+$("#content-wrapper").loadContent({url:appBaseUrl+"/"+$.param.fragment(),full:true,reload:true});
+}
+if(e.keyCode==_20){
+ajaxQueue.abortAll();
+loadOverlay.clearAll();
+_respondToHashChange=true;
+}
+});
+$(window).bind("hashchange.internal",function(e){
+if(_respondToHashChange===true){
+$("#content-wrapper").loadContent({url:appBaseUrl+"/"+$.param.fragment(),full:true,reload:true});
+}
+_respondToHashChange=true;
+});
+$("a").on("click.internal",function(_22){
+_22.preventDefault();
+var url=$(this).attr("href");
+var _23=new RegExp(escapeRegExp(appBaseUrl)+"\\/.*");
+if(_23.test(url)){
+var _24=new RegExp(escapeRegExp(appAbsBaseUrl)+"\\/[^#].*");
+if(_24.test(window.location.href)){
+window.location.href=appAbsBaseUrl+"/#"+url.replace(appBaseUrl+"/","");
+}else{
+_respondToHashChange=false;
+$("#content-wrapper").loadContent({"url":url,full:true,reload:false});
+$.bbq.pushState(url.replace("#",hashBoundary).replace(appBaseUrl+"/","#"));
+}
+}else{
+window.location.href=url;
+}
+});
+$("div#mainmenu").find("li").hover(function(){
+$(this).addClass("ui-state-hover").removeClass("mainmenu");
+},function(){
+$(this).removeClass("ui-state-hover").addClass("mainmenu");
+}).bind("mouseup mousedown",function(){
+$(this).toggleClass("ui-state-active");
+});
+$(document).applyJsToContent();
+});
+
View
2  webroot/protected/components/Gummii.php
@@ -12,7 +12,7 @@ class Gummii extends CWebApplication {
* request route, so this is used to distinguish the necessary part of a
* URI to request from the server.
*/
- const URI_HASH_BOUNDARY = '---';
+ const URI_HASH_BOUNDARY = '~';
/**
* A hash algorithm to be used in the hash function; see
View
1  webroot/protected/config/main.php
@@ -14,7 +14,6 @@
'import' => array(
'application.models.*',
'application.components.*',
- 'application.extensions.*',
),
'theme' => 'gummy',
// application components
View
17 webroot/protected/controllers/InstallController.php
@@ -10,6 +10,7 @@
* @author Demitri Morgan <demitri.morgan@gmail.com>
* @package application.controllers
*/
+
class InstallController extends GController {
public $defaultAction = 'install';
@@ -19,7 +20,7 @@ class InstallController extends GController {
protected function beforeAction($action) {
$app = Yii::app();
- if(isset($_GET['theme']))
+ if (isset($_GET['theme']))
$app->theme = $_GET['theme'];
$this->menu = array(
array('label' => CHtml::image($app->theme->baseUrl . '/logo.png', $app->name, array('width' => 40, 'height' => 40)), 'url' => array('testing')),
@@ -51,7 +52,7 @@ public function actionCheckRequirements() {
public function actionTesting() {
$this->renderDefault('testing');
}
-
+
/**
* The installation form / action.
*/
@@ -62,7 +63,8 @@ public function actionInstall() {
if (isset($_POST['Install'])) {
$model->attributes = $_POST['Install'];
- $model->YII_DEBUG = $model->YII_DEBUG ? '' : '//';
+ $debug = $model->YII_DEBUG;
+ $model->YII_DEBUG = $debug ? '' : '//';
$model->baseUrl = Yii::app()->baseUrl;
$dbError = $this->testDb(&$model);
if ($dbError) // Ad-hoc validation for database connection errors
@@ -74,11 +76,10 @@ public function actionInstall() {
$this->applySchema($db);
$messages[] = 'Initialized the database schema.';
-
- $this->createSysOp($model, $db);
- $messages[] = 'Created initial SysOp user.';
- $this->setupRBAC($model, $db);
- $messages[] = 'Set up RBAC.';
+// $this->createSysOp($model, $db);
+// $messages[] = 'Created initial SysOp user.';
+// $this->setupRBAC($model, $db);
+// $messages[] = 'Set up RBAC.';
if ($model->dummyData) {
$messages[] = 'Inserted dummy data.';
View
11 webroot/protected/views/install/_messages.php
@@ -1,9 +1,8 @@
-<?php
-if ($model->hasErrors()):
- echo CHtml::errorSummary($model, '<span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span><strong>Please fix the following:</strong>', '', array('class' => 'ui-state-error ui-corner-all', 'style' => 'padding:5px'));
-
-else:
- ?>
+<?php if ($model->hasErrors()): ?>
+ <div class="custom-error">
+ <?php echo CHtml::errorSummary($model, '<strong>Please fix the following:</strong>'); ?>
+ </div>
+<?php else: ?>
<div class="ui-state-highlight ui-corner-all">
<span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>
<?php echo $this->recursiveList($messages); ?>
View
5 webroot/protected/views/install/install.php
@@ -1,7 +1,6 @@
<div id="install-form">
<div class="six columns offset-by-three">
- <a name="#installMessages"><div id="installMessages"></div></a>
<div id="testRemote"></div>
<h1><?php echo $this->pageTitle; ?></h1>
<?php $form = $this->beginWidget('CActiveForm', array('id' => 'install-form')); ?>
@@ -55,7 +54,7 @@
<br />
<div style="display: inline-block;" id="dbTest">
<?php echo CHtml::ajaxSubmitButton('Test connection', array('testDbAjax'), array('update' => '#dbTestOutput', 'complete' => 'function(){applyJsToContent("#dbTestOutput");}'), array('style'=>'margin-bottom:10px;','class' => 'button', 'id' => $this->createScriptId() . '-testDb')); ?>
- </div>
+ </div><br />
<div style="display: inline-block;" id="dbTestOutput"><?php echo $form->error($model, 'dbError'); ?></div>
</div>
@@ -71,7 +70,7 @@
<?php echo $form->checkBox($model, 'dummyData'); ?>
</div>
</div>
- <?php echo CHtml::ajaxSubmitButton('Install', array(''), array('update' => '#installMessages'), array('class' => 'button')); ?>
+ <?php echo CHtml::ajaxSubmitButton('Install', array(''), array('update' => '#install-form','complete'=>'function(){applyJsToContent("#install-form");}'), array('class' => 'button')); ?>
<?php $this->endWidget(); ?>
</div>
View
4 webroot/protected/views/install/testDb.php
@@ -1,5 +1,5 @@
<?php if ($error): ?>
- <div class="error"><?php echo $error->getMessage(); ?></div>
+ <div class="gummii-error"><?php echo $error->getMessage(); ?></div>
<?php else: ?>
- <div class="notice">Connection successful!</div>
+ <div class="gummii-notice">Connection successful!</div>
<?php endif; ?>
View
5 webroot/protected/views/layouts/column1.php
@@ -1,5 +0,0 @@
-<?php $this->beginContent('//layouts/main'); ?>
-<div id="content">
- <?php echo $content; ?>
-</div><!-- content -->
-<?php $this->endContent(); ?>
View
21 webroot/protected/views/layouts/column2.php
@@ -1,21 +0,0 @@
-<?php $this->beginContent('//layouts/main'); ?>
-<div class="span-19">
- <div id="content">
- <?php echo $content; ?>
- </div><!-- content -->
-</div>
-<div class="span-5 last">
- <div id="sidebar">
- <?php
- $this->beginWidget('zii.widgets.CPortlet', array(
- 'title' => 'Operations',
- ));
- $this->widget('zii.widgets.CMenu', array(
- 'items' => $this->menu,
- 'htmlOptions' => array('class' => 'operations'),
- ));
- $this->endWidget();
- ?>
- </div><!-- sidebar -->
-</div>
-<?php $this->endContent(); ?>
View
82 webroot/protected/views/layouts/main.php
@@ -35,22 +35,27 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
<?php
- // Commonly-used variables
+ /////////////////////////////
+ // Commonly-used variables //
+ /////////////////////////////
+ $app = Yii::app();
$common = array(
- 'appBaseUrl' => Yii::app()->baseUrl,
- 'themeBaseUrl' => Yii::app()->theme->baseUrl,
- 'appAbsBaseUrl' => Yii::app()->getBaseUrl(True),
+ 'appBaseUrl' => $app->baseUrl,
+ 'themeBaseUrl' => $app->theme->baseUrl,
+ 'appAbsBaseUrl' => $app->getBaseUrl(True),
'hashBoundary' => Gummii::URI_HASH_BOUNDARY,
- 'forceLoadKw' => Yii::app()->params->forceLoadKw,
- );
+ 'forceLoadKw' => $app->params->forceLoadKw,
+ );
?>
<script type="text/javascript" id="globalVars">
- <?php foreach($common as $var=>$val) { // Make important variables available
- echo "$var ='$val';\n";
- } ?>
+<?php
+foreach ($common as $var => $val) { // Make important variables available
+ echo "$var ='$val';\n";
+}
+?>
</script>
<script type="text/javascript" src="<?php echo $common['appBaseUrl']; ?>/js/libraries.js"></script>
- <script type="text/javascript" src="<?php echo $common['appBaseUrl']; ?>/js/gummii-base.js"></script>
+ <script type="text/javascript" src="<?php echo $common['appBaseUrl']; ?>/js/gummii-core<?php echo YII_DEBUG ? '' : '.min'; ?>.js"></script>
<title><?php echo CHtml::encode($this->pageTitle); ?></title>
@@ -59,7 +64,7 @@
<link rel="icon" href="<?php echo $common['themeBaseUrl']; ?>/favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="<?php echo $common['themeBaseUrl']; ?>/favicon.ico" type="image/x-icon">
-
+
<!-- CSS Libraries: -->
<link rel="stylesheet" type="text/css" href="<?php echo $common['appBaseUrl']; ?>/css/foundation.css" />
<link rel="stylesheet" type="text/css" href="<?php echo $common['themeBaseUrl'] . '/css/jquery-ui.css'; ?>" />
@@ -76,44 +81,47 @@
<header> <!-- class="row" -->
- <div id="mainmenu"> <!-- class="twelve columns" -->
+ <div id="system-notice">
+ <noscript>
+ <div class="ui-state-error"><div class="ui-icon ui-icon-alert"></div><div><?php echo Yii::t('app', "This web application runs best with Javascript enabled. Please enable Javascript in your web browser before continuing.") ?></div></div>
+ </noscript>
+ </div>
+ <div id="mainmenu">
+ <?php
+ // Main site menu
+ $this->widget('zii.widgets.CMenu', array(
+ 'encodeLabel' => false,
+ 'id' => 'mainmenu-items',
+ 'items' => $this->menu,
+ 'htmlOptions' => array('class' => 'nav-bar tight'), //tight ui-state-default ui-widget
+ 'itemCssClass' => ' ui-state-default ui-widget mainmenu',
+ ));
+ ?>
+
+ </div><!-- #mainmenu -->
+<!-- <div class="row">
+ <?php if (isset($this->breadcrumbs)): ?>
<?php
-// Main site menu
- $this->widget('zii.widgets.CMenu', array(
- 'encodeLabel' => false,
- 'id' => 'mainmenu-items',
- 'items' => $this->menu,
- 'htmlOptions' => array('class' => 'nav-bar tight'), //tight ui-state-default ui-widget
- 'itemCssClass' => ' ui-state-default ui-widget mainmenu',
+ $this->widget('zii.widgets.CBreadcrumbs', array(
+ 'links' => $this->breadcrumbs,
));
- ?>
-
- </div><!-- mainmenu -->
-
-
- <div class="row">
- <?php if (isset($this->breadcrumbs)): ?>
- <?php
- $this->widget('zii.widgets.CBreadcrumbs', array(
- 'links' => $this->breadcrumbs,
- ));
- ?><!-- breadcrumbs -->
- <?php endif ?>
- </div>
+ ?> breadcrumbs
+ <?php endif ?>
+ </div>-->
</header>
<div class="container" id="content-wrapper">
<div class="row" role="main" id="content">
- <?php echo $content; ?>
+<?php echo $content; ?>
</div>
</div><!-- container -->
<footer class="row">
- <?php echo Yii::powered(); ?>
+<?php echo Yii::powered(); ?>
</footer>
- <?php foreach (require_once(Yii::app()->theme->basePath . '/img_preload.php') as $img): // preload images ?>
+ <?php foreach (require_once($app->theme->basePath . '/img_preload.php') as $img): // preload images ?>
<img height="0" width="0" style="padding:0; margin:0; border-width:0;" src="<?php echo $common['themeBaseUrl'] . $img ?>" />
- <?php endforeach; ?>
+<?php endforeach; ?>
</body>
</html>
View
13 webroot/protected/views/layouts/menu.php
@@ -1,13 +0,0 @@
-<?php
-// Main site menu
-$this->widget('zii.widgets.CMenu', array(
- 'items' => array(
- array('label' => 'Home', 'url' => array('site/index')),
- array('label' => 'About', 'url' => array('site/page', 'view' => 'about')),
- array('label' => 'Contact', 'url' => array('site/contact')),
- array('label' => 'Login', 'url' => array('site/login'), 'visible' => Yii::app()->user->isGuest),
- array('label' => 'Logout (' . Yii::app()->user->name . ')', 'url' => array('site/logout'), 'visible' => !Yii::app()->user->isGuest)
- ),
-));
-?>
-
View
4 webroot/protected/views/site/testing.php
@@ -29,8 +29,8 @@
<p>Hash algo: <?php echo Yii::app()->hashAlgo; ?></p>
<p><?php echo Yii::app()->getBaseUrl(True);?></p>
-<div class="notice">Hi, I'm a notice.</div>
-<div class="error">Shit's on fire, yo. I be an error.</div>
+<div class="gummii-notice">Hi, I'm a notice.</div>
+<div class="gummii-error">Shit's on fire, yo. I be an error.</div>
<?php $this->widget('zii.widgets.jui.CJuiButton',array('name'=>'IamajQuerybutton','caption'=>'Iama jQuery button')); ?>
Please sign in to comment.
Something went wrong with that request. Please try again.