Files
PetitTeton/public/js/layout.js
Wynne Crisman e82078174b Updated site to scale better on small screens; Added clearfix css; Updated shadow feature to use css shadows instead of js/images.
Added code to the admin part of the site - still non-functional.  Need to fix JSON streaming over HTTP such that native types (boolean, Date, int) are preserved for the DB;  Need to finish the restore functionality & the hide/show of the edit, delete, and restore buttons on each editor page.
2016-10-26 14:48:11 -07:00

374 lines
14 KiB
JavaScript

//Requires JQuery, and the JQuery History plugin.//
function FadeManager() {
}
FadeManager.prototype.constructor = FadeManager;
FadeManager.prototype.fadeIns = null;
FadeManager.prototype.fadeOuts = null;
//
// Fades the element IN.
// @param elements The jquery object, or jquery selector(s) ('#ID', '.class', 'tag', object) of the elements to become visible.
//
FadeManager.prototype.fadeIn = function(elements) {
if(elements) {
elements = $(elements);
if(this.fadeIns) {
this.fadeIns = this.fadeIns.add(elements);
}
else {
this.fadeIns = elements;
}
}
}
//
// Fades the element OUT.
// @param elements The jquery object, or jquery selector(s) ('#ID', '.class', 'tag', object) of the elements to become visible.
//
FadeManager.prototype.fadeOut = function(elements) {
if(elements) {
elements = $(elements);
if(this.fadeOuts) {
this.fadeOuts = this.fadeOuts.add(elements);
}
else {
this.fadeOuts = elements;
}
}
}
/**
* Note: Used to pass viewName - now passes view (a JQuery object containing the view div.)
*/
function LayoutManager(view) {
//PRIVATE MEMBERS
var _this = this;
//var view = $('[bs-view="' + viewName + '"]');
var lastUrl = null;
var oldContainer = null;
var container = null;
//PUBLIC MEMBERS
this.hashPrefix = '!'; //Should be empty or null if no html5 search engine framework is not being used.
this.isLoading = false;
this.postLoadHandler = null;
//
// Applications should alter this value. Use #!/xxx if using HTML5's search engine protocols.
//
this.defaultUrl = '#/landing';
//
// These page classes can be modified by the website to include any style class that might be applied to a page section viewed through the layout manager.
//
this.pageClassFades = [{cls: 'topPage', fadeIn: '#menuBar,#titleBar', fadeOut: null}, {cls: 'halfPage', fadeIn: '#menuBar,#lowerRightLogo', fadeOut: null}, {cls: 'fullPage', fadeIn: '#bottomCenterLogo', fadeOut: null}];
//
// A map of view name to metadata objects.
// If no metadata is provide for a view, or for any property of a view, then the defaults will be used (url is derrived from the view name by adding .html, the rest are null).
// Example:
// layoutManager.viewMetadata = {
// home: {
// url: 'home.html',
// classes: ['fullPage'],
// load: 'alert("starting loading home");',
// loaded: 'alert("loaded home");',
// unload: 'alert("starting unloading home");',
// unloaded: 'alert("unloaded home");',
// fadeIn: 'menuBar, leftNav',
// fadeOut: 'bottomBar'
// },
// anotherViewName: {...}
// }
//
this.viewMetadata = {};
//
// The defaults to be used for the view metadata if any values are not provided for a view. Any value may be empty. Url is not utilized (url's default to the view name + ".html").
// Example:
// layoutManager.viewMetadataDefaults = {
// classes: ['halfPage'];
// }
//
this.viewMetadataDefaults = {};
//CONSTRUCTOR
//Ensure the view is properly found.
if(view && view.length == 1) {
view.data('layout-manager', this);
}
else {
view = null;
//throw "view with name: '" + viewName + "' not found";
throw "View does not exist!";
}
//PRIVILEGED METHODS (public with private access)
//
// Sets the handler to be run immediately or after the display currently being shown is completed.
// @param fn The function to be run. This allows the code to change the display, even if the display is in the middle of changing.
//
this.setPostLoadHandler = function(fn) {
if(_this.isLoading) {
_this.postLoadHandler = fn;
}
else {
fn();
}
}
//
// Displays the new URL and hides the lastUrl.
// Passed elements can define "load", "loaded", "unload", and "unloaded" functions (as attributes OR as jquery 'data') that will be called. The present tense functions will be called prior to the fades and are passed the jquery element object, along with a LayoutManager instance allowing alterations of what becomes visible and invisible. The past tense functions are called after the fades and are passed only the jquery elements involved.
// Passed elements may also have attributes OR jquery 'data' named: 'fadeIn' and 'fadeOut' that each contain a jquery object, or a comma delimited list of jquery selectors to fade IN and OUT upon loading (these lists fade type are inverted when unloading).
// Example: <div id='showableDiv' fadeIn="showMeElement,showMe2" fadeOut="hideMeElement,hideMe2" load="function(element, fadeManager) {/*do something*/}" loaded='function(element) {/*do something*/} unload="function(element, fadeManager) {/*do something*/} unloaded='function(element) {/*do something*/}"/>
// @param url The url to be shown.
// @param lastUrl The url last shown (to be hidden).
// @return The URL, usually as passed to the show, otherwise what the show call redirected to.
//
this.show = function(url) {
if(url.indexOf('#') == 0) url = url.substring(1);
_this.isLoading = true;
var lastUrl = _this.lastUrl;
var initialize;
var menuId;
var urlParts = url.replace('%7C', '|').split('|');
var oldUrlParts = lastUrl ? lastUrl.replace('%7C', '|').split('|') : [""];
var isIE = navigator.userAgent.match("MSIE");
var prefix = _this.hashPrefix + "/";
//Check for the prefix and strip it.
if(urlParts[0].indexOf(prefix) == 0) {
urlParts[0] = urlParts[0].substring(prefix.length);
oldUrlParts[0] = oldUrlParts[0].substring(prefix.length);
//Determine whether the new element being shown is different from the old element.
//Ignore sub-elements that may be part of the hash URI (sub elements are divided by a '|' character or the %7C equivalent).
if(oldUrlParts[0] != urlParts[0]) {
//Cleanup just in case.
if(oldContainer) {
oldContainer.remove();
}
//Set the current container as the old container.
oldContainer = container;
container = $('<div/>');
container.appendTo(view);
var fadeManager = new FadeManager();
var viewMetadata = _this.viewMetadata[urlParts[0]];
var hasOldUrl = oldUrlParts[0].length > 0;
var oldViewMetadata = hasOldUrl ? _this.viewMetadata[oldUrlParts[0]] : null;
//Clone the view metadata and old view metadata and set defaults where necessary.
viewMetadata = viewMetadata ? $.extend(true, {}, _this.viewMetadataDefaults, viewMetadata) : $.extend(true, {}, _this.viewMetadataDefaults);
oldViewMetadata = hasOldUrl ? oldViewMetadata ? $.extend(true, {}, _this.viewMetadataDefaults, oldViewMetadata) : $.extend(true, {}, _this.viewMetadataDefaults) : null;
viewMetadata.url = viewMetadata.url ? viewMetadata.url : urlParts[0] + ".html";
if(oldViewMetadata) oldViewMetadata.url = oldViewMetadata.url ? oldViewMetadata.url : oldUrlParts[0] + ".html";
viewMetadata.classes = viewMetadata.classes && $.isArray(viewMetadata.classes) ? viewMetadata.classes : viewMetadata.classes ? [viewMetadata.classes] : [];
if(oldViewMetadata) oldViewMetadata.classes = oldViewMetadata.classes && $.isArray(oldViewMetadata.classes) ? oldViewMetadata.classes : oldViewMetadata.classes ? [oldViewMetadata.classes] : [];
var loadFunction = viewMetadata.load;
var loadedFunction = viewMetadata.loaded;
var unloadFunction = hasOldUrl ? oldViewMetadata.unload : null;
var unloadedFunction = hasOldUrl ? oldViewMetadata.unloaded : null;
var urlObjectFadeIns = viewMetadata.fadeIn;
var urlObjectFadeOuts = viewMetadata.fadeOut;
var oldUrlObjectFadeIns = hasOldUrl ? oldViewMetadata.fadeOut : null;
var oldUrlObjectFadeOuts = hasOldUrl ? oldViewMetadata.fadeIn : null;
//Add the elements being faded in/out in the fade manager.//
fadeManager.fadeIn(container);
if(hasOldUrl) fadeManager.fadeOut(oldContainer);
if(urlObjectFadeIns) fadeManager.fadeIn(urlObjectFadeIns)
if(urlObjectFadeOuts) fadeManager.fadeOut(urlObjectFadeIns);
if(oldUrlObjectFadeIns) fadeManager.fadeIn(oldUrlObjectFadeIns)
if(oldUrlObjectFadeOuts) fadeManager.fadeOut(oldUrlObjectFadeOuts);
//If the element being shown is set to load upon showing, do the load of the contents now.//
//brainstormFramework.load(container[0], viewMetadata.url);
$.ajax({url: viewMetadata.url, dataType: 'html', async: false}).done(function(data) {
container.html(data);
}).fail(function(error) {
console.log(error);
});
//Some presets via the element's class, to fade things in and out based on the element's style.//
for(var index = 0; index < _this.pageClassFades.length; index++) {
for(var classIndex = 0; classIndex < viewMetadata.classes.length; classIndex++) {
if(_this.pageClassFades[index] && _this.pageClassFades[index].cls && _this.pageClassFades[index].cls == viewMetadata.classes[classIndex]) {
fadeManager.fadeIn(_this.pageClassFades[index].fadeIn);
fadeManager.fadeOut(_this.pageClassFades[index].fadeOut);
}
}
}
if(hasOldUrl) {
for(var index = 0; index < _this.pageClassFades.length; index++) {
for(var classIndex = 0; classIndex < oldViewMetadata.classes.length; classIndex++) {
if(_this.pageClassFades[index] && _this.pageClassFades[index].cls && _this.pageClassFades[index].cls == oldViewMetadata.classes[classIndex]) {
fadeManager.fadeOut(_this.pageClassFades[index].fadeIn);
fadeManager.fadeIn(_this.pageClassFades[index].fadeOut);
}
}
}
}
//If there is a load function then call it now passing the element being displayed, and the fadeManager reference.//
if(unloadFunction) {
if(typeof unloadFunction == 'string') {
if(unloadFunction.length > 0) {
var element = oldContainer;
//Call the unload function passing the jquery object for the element being unloaded and hidden, and the fade manager so that additional fade in/out's can be specified.//
eval(unloadFunction);
}
}
else {
//Call the unload function passing the jquery object for the element being unloaded and hidden, and the fade manager so that additional fade in/out's can be specified.//
unloadFunction(oldContainer, fadeManager);
}
}
if(loadFunction) {
if(typeof loadFunction == 'string') {
if(loadFunction.length > 0) {
var element = container;
//Call the load function passing the jquery object for the element being unloaded and hidden, and the fade manager so that additional fade in/out's can be specified.//
eval(loadFunction);
}
}
else {
//Call the load function passing the jquery object for the element being loaded and displayed, and the fade manager so that additional fade in/out's can be specified.//
loadFunction(container, fadeManager);
}
}
//Remove fade elements that match. No reason to fade things out and in at the same time.//
if(fadeManager.fadeOuts && fadeManager.fadeIns) {
for(var outIndex = fadeManager.fadeOuts.length - 1; outIndex >= 0; outIndex--) {
var match = false;
for(var inIndex = fadeManager.fadeIns.length - 1; !match && inIndex >= 0; inIndex--) {
if(fadeManager.fadeOuts[outIndex] == fadeManager.fadeIns[inIndex]) {
fadeManager.fadeOuts.splice(outIndex, 1);
fadeManager.fadeIns.splice(inIndex, 1);
match = true;
}
}
}
}
try {
//Fade in the elements marked for it.//
if(fadeManager.fadeIns && fadeManager.fadeIns.length > 0) {
var all = fadeManager.fadeIns;
var block = all.filter(':not(.inline)');
var inline = all.filter('.inline');
if(isIE) {
block.show();
inline.css('visibility', 'visible');
}
else {
var fade = all.filter(':not(.nofade)');
//Ensure they are completely faded out and displayed.//
fade.fadeTo(0, 0);
block.show();
inline.css('visibility', 'visible');
//Fade over 1 second to fully visible.//
fade.fadeTo(!oldContainer ? 0 : 1000, 1, function() {
if(unloadedFunction) {
if(typeof unloadedFunction == 'string') {
if(unloadedFunction.length > 0) {
var element = oldContainer;
//Call the unloaded function passing the jquery object for the element being unloaded and hidden.//
eval(unloadedFunction);
}
}
else {
//Call the unloaded function passing the jquery object for the element being unloaded and hidden.//
unloadedFunction(oldContainer, fadeManager);
}
}
if(loadedFunction) {
if(typeof loadedFunction == 'string') {
if(loadedFunction.length > 0) {
var element = container;
//Call the loaded function passing the jquery object for the element being loaded and displayed.//
eval(loadedFunction);
}
}
else {
//Call the loaded function passing the jquery object for the element being loaded and displayed.//
loadedFunction(container, fadeManager);
}
}
//Clean up after the old container now that the fades are done.//
if(hasOldUrl && oldContainer) {
oldContainer.remove();
oldContainer = null;
}
});
}
}
//Fade out the elements marked for it.//
if(fadeManager.fadeOuts && fadeManager.fadeOuts.length > 0) {
var all = fadeManager.fadeOuts;
var block = all.filter(':not(.inline)');
var inline = all.filter('.inline');
if(isIE) {
block.hide();
inline.css('visibility', 'hidden');
}
else {
var blockNoFade = block.filter('.nofade');
var blockFade = block.filter(':not(.nofade)');
var inlineNoFade = inline.filter('.nofade');
var inlineFade = inline.filter(':not(.nofade)');
var fade = all.filter(':not(.nofade)');
blockNoFade.hide();
inlineNoFade.css('visibility', 'hidden');
fade.fadeTo(!oldContainer ? 500 : 0, 0, function() {blockFade.hide(); inlineFade.css('visibility', 'hidden');});
}
}
}
catch(err) {
alert(err);
}
}
_this.lastUrl = url;
_this.isLoading = false;
if(_this.postLoadHandler) {
var fn = _this.postLoadHandler;
_this.postLoadHandler = null;
fn();
}
}
else if(url == _this.defaultUrl) {
//Fail! Bad default URL.
throw "Bad Default URL";
}
else {
//Missing prefix: malformed url
window.location.replace(_this.defaultUrl);
_this.show(_this.defaultUrl); //Note: This could create a stack overflow if the defaultUrl is malformed!
}
//$('#log').prepend("Showing: " + url + "<br/>");
}
}