Initial commit. Transferred from an Eclipse/Brainstorm environment to NodeJS.

This commit is contained in:
Wynne Crisman
2015-10-25 15:20:42 -07:00
commit 7bba9dc2b0
386 changed files with 22589 additions and 0 deletions

160
public/js/dialog.js Normal file
View File

@@ -0,0 +1,160 @@
//
// Requires jquery at a minimum.
//
function Dialog() {
}
Dialog.prototype.constructor = Dialog;
Dialog.prototype.currentId = null; //Currently displayed dialog division ID.//
Dialog.prototype.currentReset = null; //Called after the dialog is closed to reset the dialog for the next opening.//
Dialog.prototype.postCloseHandler = null; //Called after the dialog is closed to perform any post close operation.//
Dialog.prototype.topOffset = 40; //Number of pixels of padding between the dialog top and the window top.//
//
// Shows the dialog with the given dialogId (the ID of the hidden div containing the dialog content).
// @param dialogId The identifier of the dialog.
// @param reset The optional function called when the dialog is closed (for cleanup).
//
Dialog.prototype.open = function(dialogId, reset) {
//Ensure the dialog isn't already open. Note: We are not currently counting the calls to open it as this is not expected to be a needed feature. This is more of a precaution.//
if(this.currentId != dialogId && dialogId) {
//If a dialog is already showing then hide it without altering the dialog background, otherwise create the dialog background.//
if(this.currentId) {
try {
var oldDialog = $('#' + this.currentId);
oldDialog.parent().children('.dialogClose').remove();
oldDialog.unwrap();
oldDialog.hide();
//Call the reset if available.//
if(this.currentReset) {
this.currentReset();
}
}
catch(err) {
alert(err);
}
}
else {
//Create the background div and display it.//
$('body').prepend("<div id='dialogBackground' class='dialogBackground'/>");
}
//Create wrapper divs around the dialog div to display a close box and provide some padding and give it a background.//
var dialog = $('#' + dialogId);
dialog.wrap("<div class='dialogWindow'/>");
dialog.parent().prepend("<div class='dialogShadowTopRight'/>");
dialog.parent().prepend("<div class='dialogShadowRight'/>");
dialog.parent().prepend("<div class='dialogShadowBottomRight'/>");
dialog.parent().prepend("<div class='dialogShadowBottom'/>");
dialog.parent().prepend("<div class='dialogShadowBottomLeft'/>");
dialog.wrap("<div class='dialogPanel'/>"); // style='background: " + dialog.css('background') + ";' //This would take the background from the parent, but this works differently on different browsers (firefox returns nothing if nothing is set, chrome returns a clear background - which overrides the default css settings in dialog.css).
dialog.parent().prepend("<div class='dialogClose' onClick='javascript: dialog.close();'/>");
//Show the dialog.//
dialog.show();
//Store a reference to the currently displayed dialog & reset function for later use.//
this.currentId = dialogId;
this.currentReset = reset;
//Initialize the resize handler and call it.//
$(window).resize(this.resize).resize();
}
};
//
// Closes the currently open dialog.
//
Dialog.prototype.close = function() {
//Ensure a dialog is open.//
if(this.currentId) {
try {
var dialog = $('#' + this.currentId);
//Remove the wrappering divs from the dialog.//
dialog.parent().children('.dialogClose').remove();
dialog.unwrap();
dialog.parent().children('.dialogShadowTopRight').remove();
dialog.parent().children('.dialogShadowRight').remove();
dialog.parent().children('.dialogShadowBottomRight').remove();
dialog.parent().children('.dialogShadowBottom').remove();
dialog.parent().children('.dialogShadowBottomLeft').remove();
dialog.unwrap();
//Hide the dialog.//
dialog.hide();
//Delete the background div.//
$('#dialogBackground').remove();
//Remove the resize handler.//
$(window).unbind('resize', this.resize);
//Call the reset if available.//
if(this.currentReset) {
try {
this.currentReset();
}
catch(err) {
alert(err);
}
this.currentReset = null;
}
//Call the post close handler if available.//
if(this.postCloseHandler) {
try {
this.postCloseHandler();
}
catch(err) {
alert(err);
}
this.postCloseHandler = null;
}
//Cleanup the dialog references.//
this.currentId = null;
this.currentReset = null;
}
catch(err) {
alert(err);
}
}
};
//
// Closes the currently open dialog.
//
Dialog.prototype.resize = function() {
if(dialog.currentId) {
var windowHeight = 0;
var windowWidth = 0;
var dialogContent = $('#' + dialog.currentId);
var dialogWindow = dialogContent.parent().parent();
var background = $('#dialogBackground');
if(navigator.appName.indexOf("Microsoft") != -1) {
var htmlHeight = document.body.parentNode.clientHeight;
windowHeight = htmlHeight < window.screen.height ? htmlHeight : window.screen.height;
windowWidth = document.body.offsetWidth;
}
else {
windowHeight = window.innerHeight;
windowWidth = window.innerWidth;
}
var dialogHeight = dialogContent.height() + 62; //10 for the shadow, 20 for the insets, 1 for the border (x2).//
var dialogWidth = dialogContent.width() + 62;
background.css({'top': 0, 'left': 0, 'bottom': windowHeight, 'right': windowWidth, 'height': windowHeight, 'width': windowWidth});
dialogWindow.css(
{
'top':
(dialogHeight > windowHeight ? "0px" : dialogHeight + (dialog.topOffset * 2) < windowHeight ? dialog.topOffset + 'px' : Math.round((windowHeight - dialogHeight) / 2) + "px"),
'left':
(dialogWidth > windowWidth ? "0px" : Math.round((windowWidth - dialogWidth) / 2) + "px"),
'height': dialogHeight + 'px', 'width': dialogWidth + 'px'
}
);
}
};
var dialog = new Dialog();

489
public/js/framework.js Normal file
View File

@@ -0,0 +1,489 @@
//
// Requires jquery at a minimum.
//
var framework = new BrainstormFramework();
var brainstormFramework = framework;
function BrainstormFramework() {
//The set of open views. The data for each view is an object containing the:
// divId of the view's outer HTML tag; and the
// displayId used to reference the view on the server.
var openViews = [];
//The display ID last used from the client side sequence. The server has its own sequence (negative numbers) that it can issue from.//
var nextDisplayId = 1;
var cleanupStarted = false;
var clientId = 0;
//Set by the application - a function that is called (no parameters) when a call to retrieve a view is not allowed due to the user not being logged in or not having sufficient permissions.
this.disallowedHandler = null;
//
// The function called every N seconds to cleanup after orphaned views.
//
this.cleanup = function() {
if(openViews) {
for(var index = 0; index < openViews.length; index++) {
var next = openViews[index];
if(!$('#frameworkViewContent' + next.id)) {
//Close the view.//
closeViewInternal(next);
//Remove the metadata from the open views array.//
openViews.splice(index--, 1);
}
}
}
//Re-call cleanup every minute.//
setTimeout("brainstormFramework.cleanup()", 60000);
};
//
// Loads the html at the given URL into the container. The container will be emptied of all content prior to loading. Any scripts inside <runonce>..</runonce> tags will be removed and executed as soon as the html is loaded.
// @param containerRef The jquery reference to the container for the html. This can be for example 'body' to reference the body node, or '#body' to reference the node with the ID of 'body'.
// @param url The URL of the html to be loaded.
//
this.append = function(containerRef, url) {
var _this = this;
var container = containerRef ? $(containerRef) : null;
$.ajax({url: url, dataType: 'html', async: false, success: function(data) {
data = _this.extractViewData(data);
if(data.view) {
if(container) {
container.append(data.view);
}
else {
htmlHandler(data.view);
}
}
if(data.script && data.script.length > 0) {
try {
eval(data.script);
} catch(err) {
alert(err);
}
}
}});
}
//
// Loads the html at the given URL into the container. The container will be emptied of all content prior to loading. Any scripts inside <runonce>..</runonce> tags will be removed and executed as soon as the html is loaded.
// @param containerRef The jquery reference to the container for the html. This can be for example 'body' to reference the body node, or '#body' to reference the node with the ID of 'body'.
// @param url The URL of the html to be loaded.
// @param htmlHandler The optional handler to be called to place the html. This may be specified in place of the container ID. The handler will be passed the HTML for the view as a string.
//
this.load = function(containerRef, url, htmlHandler) {
var _this = this;
var container = containerRef ? $(containerRef) : null;
if(container) {
container.empty();
}
$.ajax({url: url, dataType: 'html', async: false, success: function(data) {
data = _this.extractViewData(data);
if(data.view) {
if(container) {
container.html(data.view);
}
else {
htmlHandler(data.view);
}
}
if(data.script && data.script.length > 0) {
try {
eval(data.script);
} catch(err) {
alert(err);
}
}
}});
}
//
// Opens a view given the container for the view and the view controller's class name.
// @param displayContainerId The ID of the container that the view will be appended to.
// @param viewController The java class name for the view controller.
//
this.openView = function(displayContainerId, viewController) {
var displayId = nextDisplayId++;
var divId = "frameworkViewContent" + displayId;
var success = false;
var _this = this;
var displayContainer = $('#' + displayContainerId);
$.ajax({url: "/FrameworkController.java?Request=OpenView&ClientId=" + clientId + "&Controller=" + viewController + "&DisplayId=" + displayId, dataType: 'json', async: false, success: function(data) {
if(data) {
try {
if(data.result == 'client-switch') {
//TODO: Send the client stored view controller metadata to the server, then re-run this call.
//For now we will simply refresh the display, causing us to rebuild everything and get a new client id.//
location.reload();
}
else if(data.result == "success") {
var viewData = _this.extractViewData(data.content);
//Setup the container for the view.//
displayContainer.append("<div id='" + divId + "' displayId='" + displayId + "'>" + "</div>");
//Place the contents of the view.//
$('#' + divId).append(viewData.view);
//TODO: Store any cleanup script?
openViews[openViews.length] = {'divId': divId, 'displayId': displayId};
if(!brainstormFramework.cleanupStarted) {
brainstormFramework.cleanupStarted = true;
brainstormFramework.cleanup();
}
success = true;
//Run the script if one came with the view.//
if(viewData.script.length > 0) {
try {
eval(viewData.script);
} catch(err) {
alert(err);
}
}
}
else if(data.result == "disallowed") {
if(_this.disallowedHandler) _this.disallowedHandler();
}
else {
//TODO: Properly handle this.
alert(data.result);
}
} catch(err) {
alert(err);
}
}
else {
//Error: View creation failed.
}
}});
return success ? displayId : 0;
};
//
// Refreshes the given view by reloading the view's HTML.
// @param frameworkContainer The DIV jquery object that encloses the view's contents. This can be obtained by calling parent() on the jquery object for any root element in the view being refreshed. Note that this is the FRAMEWORK's container which is in turn placed in the container supplied when opening the view.
//
this.refreshView = function(frameworkContainer) {
var frameworkContainerId = frameworkContainer.attr("id");
var _this = this;
frameworkContainer.empty();
for(var index = 0; index < openViews.length; index++) {
var next = openViews[index];
if(next.divId == frameworkContainerId) {
$.ajax({url: "/FrameworkController.java?Request=RefreshView&ClientId=" + clientId + "&DisplayId=" + next.displayId, dataType: 'json', async: false, success: function(data) {
if(data) {
if(data.result == 'client-switch') {
//TODO: Send the client stored view controller metadata to the server, then re-run this call.
//For now we will simply refresh the display, causing us to rebuild everything and get a new client id.//
location.reload();
}
else if(data.result == "success") {
var viewData = _this.extractViewData(data.content);
frameworkContainer.append(viewData.view);
//Run the script if one came with the view.//
if(viewData.script.length > 0) {
try {
eval(viewData.script);
} catch(err) {
alert(err);
}
}
}
}
}});
break;
}
}
};
//
// Gets the URL to call a view for use within a form. Sometimes a form submittal requires a URL string and can't call the BrainstormFramework.callView() method.
// @param displayId The ID number of the view controller (not the view's outer div's id attribute).
// @param query The function to be called on the view controller.
// @param parameters The parameters to add to the call. The parameters should be in URL format with &amp; characters separating parameters. Example: "param1=abc&param2=xyz".
//
this.getCallViewUrl = function(displayId, query, parameters) {
return "/FrameworkController.java?Request=CallView&ClientId=" + clientId + "&DisplayId=" + displayId + "&Query=" + query + (parameters ? "&" + parameters: "");
}
//
// Calls the view controller. If the view controller opens another view, it will use a view id from the server (different range) and return {view: ..., viewId: xx}.
// @param displayId The ID number of the view controller (not the view's outer div's id attribute).
// @param query The function to be called on the view controller.
// @param parameters The parameters to add to the call. The parameters should be in URL format with &amp; characters separating parameters. Example: "param1=abc&param2=xyz".
// @param isAsync Whether the call should be asynchronous.
// @param resultViewContainer The jquery view container where the view resulting from this call will be placed. If this is not specified and a view is returned then a dialog will be created.
// @param resultHandler The function called passing the result if specified. Otherwise the result is returned.
// @return The result if one is generated by the call, otherwise the dialog object if a view is the result, otherwise null.
//
this.callView = function(displayId, query, parameters, isAsync, resultViewContainer, resultHandler) {
var _this = this;
var result;
$.ajax({url: "/FrameworkController.java?Request=CallView&ClientId=" + clientId + "&DisplayId=" + displayId + "&Query=" + query + (parameters ? "&" + parameters: ""), dataType: 'json', cache: false, async: false, success: function(data, statusText, jqXHR) {
if(data) {
if(data.error) {
alert(data.error);
}
if(data.result == 'client-switch') {
//TODO: Send the client stored view controller metadata to the server, then re-run this call.
//For now we will simply refresh the display, causing us to rebuild everything and get a new client id.//
location.reload();
}
else {
try {
if(data.view) {
var viewData = _this.extractViewData(data.view);
if(resultViewContainer) {
var newDisplayId = data.displayId;
var divId = "frameworkViewContent_" + (newDisplayId < 0 ? '_' + Math.abs(newDisplayId) : newDisplayId);
//Save the view data.//
openViews[openViews.length] = {'divId': divId, 'displayId': newDisplayId};
if(!brainstormFramework.cleanupStarted) {
brainstormFramework.cleanupStarted = true;
brainstormFramework.cleanup();
}
//Create the container for the view.//
resultViewContainer.append("<div id='" + divId + "' displayId='" + newDisplayId + "'></div>");
//Append the view HTML to the container.//
$('#' + divId).append(viewData.view);
//TODO: Setup cleanup code.
//Store the result as the div id.//
result = divId;
//Run the script if one came with the view.//
if(viewData.script.length > 0) {
try {
eval(viewData.script);
} catch(err) {
alert(err);
}
}
}
else {
var newDisplayId = data.displayId;
var divId = "frameworkViewContent_" + Math.abs(newDisplayId);
var metadata = viewData.metadata ? $(viewData.metadata).find('metadata') : undefined;
//Save the view data.//
openViews[openViews.length] = {'divId': divId, 'displayId': newDisplayId};
if(!brainstormFramework.cleanupStarted) {
brainstormFramework.cleanupStarted = true;
brainstormFramework.cleanup();
}
//Create the container for the dialog.//
$("body").append("<div id='" + divId + "' displayId='" + newDisplayId + (metadata && metadata.attr('height') && metadata.attr('width') ? "' style='height: " + metadata.attr('height') + "; width: " + metadata.attr('width') + "": "") + "'></div>");
//Populate the dialog contents.//
$('#' + divId).append(viewData.view);
//Open the dialog and cleanup when it closes.//
dialog.open(divId, function() {
brainstormFramework.closeView(divId);
$('#' + divId).remove();
});
//result = divId;
result = dialog;
//Run the script if one came with the view.//
if(viewData.script && viewData.script.length > 0) {
try {
eval(viewData.script);
} catch(err) {
alert(err);
}
}
}
}
if(data.result) {
result = data.result;
}
if(resultHandler) {
resultHandler(result);
}
} catch(err) {
alert(err);
}
}
}
else {
//Error: Call failed.
}
}, error: function(jqXHR, textStatus, errorThrown) {
alert("Failed");
}});
return result;
};
this.extractViewData = function(viewData) {
var data = {script: "", metadata: undefined, view: ""};
var start;
//Remove the escaping that allowed it to be sent as part of a JSON response.//
viewData = this.unescape(viewData);
//Strip out any run-once scripts to be run after loading the html.//
while(viewData.indexOf("<runonce>") != -1) {
//extract the script.//
data.script += viewData.substring(viewData.indexOf("<runonce>") + 9, viewData.indexOf("</runonce>")).replace("<!--", "").replace("//-->", "");
//Remove the script from the view data.//
viewData = viewData.substring(0, viewData.indexOf("<runonce>")) + viewData.substring(viewData.indexOf("</runonce>") + 10);
}
//Detect and remove any metadata.//
if((start = viewData.indexOf('<metadata>')) != -1) {
var end = viewData.indexOf('</metadata>', start + 10);
var metadata = viewData.substring(start, end + 11);
//Remove the metadata from the document.//
viewData = viewData.substring(0, start) + viewData.substring(end + 11);
//Parse the metadata XML.//
data.metadata = $.parseXML(metadata);
}
else if((start = viewData.indexOf('<metadata ')) != -1) {
var end = viewData.indexOf('/>', start + 10);
var metadata = viewData.substring(start, end + 2);
//Remove the metadata from the document.//
viewData = viewData.substring(0, start) + viewData.substring(end + 2);
//Parse the metadata XML.//
data.metadata = $.parseXML(metadata);
}
else if((start = viewData.indexOf('<metadata/>')) != -1) {
viewData = viewData.substring(0, start) + viewData.substring(start + 11);
}
//Strip out any comments.//
while(viewData.indexOf("<!--") != -1) {
//Remove the comment from the view data.//
viewData = viewData.substring(0, viewData.indexOf("<!--")) + viewData.substring(viewData.indexOf("-->") + 3);
}
data.view = viewData;
return data;
}
//
// Closes the view given the view's div ID (the div is created to wrapper the view content and is the only child of the container passed when creating the view, the div's ID is returned by the call to openView(..)).
// @param id The view's div's ID, or display ID.
//
this.closeView = function(id) {
for(var index = 0; index < openViews.length; index++) {
var next = openViews[index];
//Allow the passed id to be either the div ID or the display ID.//
if(next.divId == id || next.displayId == id) {
//Remove the metadata from the open views array.//
openViews.splice(index, 1);
//Close the actual view.//
this.closeViewInternal(next);
break;
}
}
};
//
// Closes the view given the view metadata. The caller is expected to remove the metadata from the view set.
// @param metadata The metadata for the view being removed.
//
this.closeViewInternal = function(metadata) {
//Remove the view HTML from the DOM.//
$('#' + metadata.divId).remove();
//Notify the server that the view has closed.//
$.ajax({url: "/FrameworkController.java?Request=CloseView&ClientId=" + clientId + "&DisplayId=" + metadata.displayId, dataType: 'json', async: true, success: function(data) {
if(data) {
if(data.success == "true") {
//Do nothing?
}
else if(data.result == 'client-switch') {
//Do nothing for now. Ideally this call failing can be ignored since this close view code should remove the server view controller metadata stored on the client which will be used at some future time to restore the client's session on the server.//
}
else {
//TODO:
}
}
else {
//Error: View removal failed.
}
}});
};
//
// Removes escape characters from text.
// @param text The text whose escape characters are to be removed.
//
this.unescape = function(text) {
var result = text.replace(/\x7C1/g, "\\").replace(/\x7C2/g, "'").replace(/\x7C3/g, "\"").replace(/\x7C4/g, "\x0D").replace(/\x7C5/g, "\x09").replace(/\x7C7/g, "&").replace(/\x7C8/g, "<").replace(/\x7C9/g, ">").replace(/\x7C6/g, "\x7C");
return result;
};
//
// Adds escape characters to text.
// @param text The text whose escape characters are to be added. If this is undefined then the result will be an empty string.
//
this.escape = function(text) {
var result;
if(text) {
result = text.replace(/\x0A\x0D/g, "\n").replace(/\x7C/g, "\x7C6").replace(/\\/g, "\x7C1").replace(/\'/g, "\x7C2").replace(/\"/g, "\x7C3").replace(/\n/g, "\x7C4").replace(/\x09/g, "\x7C5").replace(/%/g, "\x7C6").replace(/&/g, "\x7C7").replace(/\x3C/g, "\x7C8").replace(/\x3E/g, "\x7C9");
}
else {
result = "";
}
return result;
};
//Get this view's client id. Each window/tab or refresh requires a new client ID from the server so it can track which set of displays belongs to which view.//
$.ajax({url: "/FrameworkController.java?Request=CreateId", dataType: 'json', async: false, success: function(data) {
if(data) {
clientId = data.result;
}
}});
$(window).onunload = function() {
while(openViews.length > 0) {
var next = openViews[openViews.length - 1];
closeViewInternal(next);
openViews.splice(openViews.length - 1, 1);
}
};
this.cleanup();
}

4
public/js/jquery-1.11.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
public/js/jquery-migrate-1.2.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,49 @@
//
//Notes:
// The element should look something like:
// <span class='custom-checkbox' css-unchecked="checkbox-unchecked" css-checked="checkbox-checked" value="false"> My text goes here!</span>
// The unchecked and checked css should at a minimum specify a height & width and a background image set to no-repeat.
//
// Depends on several CSS classes:
// .non-selectable-text {-webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none;}
// .clickable {cursor: pointer; cursor: hand;}
//
(function($) {
$.fn.buildCustomCheckBox = function() {
for(var index = 0; index < this.length; index++) {
var next = $(this[index]);
var isWrapped = next.data('is-wrapped');
if(isWrapped != true) {
var cssChecked = next.attr('css-checked');
var cssUnchecked = next.attr('css-unchecked');
var value = next.attr('value');
value = value == 'true' || value == true ? true : false;
next.attr('value', value);
next.prepend("<div class='" + (value == true ? cssChecked : cssUnchecked) + "' style='display: inline-block;'/>");
next.addClass("clickable");
next.addClass("non-selectable-text");
next.add(next.children().first()).click(function() {
var _this = $(this);
var isChecked = _this.attr('value') != true;
var cssChecked = next.attr('css-checked');
var cssUnchecked = next.attr('css-unchecked');
_this.attr('value', isChecked);
_this.children().first().removeClass(isChecked ? cssUnchecked : cssChecked);
_this.children().first().addClass(isChecked ? cssChecked : cssUnchecked);
});
next.keypress(function(event) {
if(event.which == 32 || event.which == 13) {
var _this = $(event.target);
_this.children().first().click();
}
});
}
}
return this;
}
})(jQuery);

View File

@@ -0,0 +1,68 @@
//
//Notes:
// The element should look something like:
// <span class='custom-radiobutton' css-unchecked="radiobutton-unchecked" css-checked="radiobutton-checked" value="false"> My text goes here!</span>
// The unchecked and checked css should at a minimum specify a height & width and a background image set to no-repeat.
//
// Depends on several CSS classes:
// .non-selectable-text {-webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none;}
// .clickable {cursor: pointer; cursor: hand;}
//
(function($) {
$.fn.buildCustomRadioButton= function() {
for(var index = 0; index < this.length; index++) {
var next = $(this[index]);
var isWrapped = next.data('is-wrapped');
if(isWrapped != true) {
var cssChecked = next.attr('css-checked');
var cssUnchecked = next.attr('css-unchecked');
var value = next.attr('value');
value = value == 'true' || value == true ? true : false;
next.attr('value', value);
//next.prepend("<div class='" + (value == true ? cssChecked : cssUnchecked) + "' style='display: inline-block;'/>");
next.prepend("<span class='" + (value == true ? cssChecked : cssUnchecked) + "' style='display: inline-block;'/>");
next.addClass("clickable");
next.addClass("non-selectable-text");
next.data('radioButtonGroup', this);
next.add(next.children().first()).click(function() {
var _this = $(this);
var isChecked = _this.attr('value') == true;
//Radio buttons should never be un-checked.//
if(!isChecked) {
var cssChecked = next.attr('css-checked');
var cssUnchecked = next.attr('css-unchecked');
var allButtons = next.data('radioButtonGroup');
//Uncheck any of the buttons that are checked.//
for(var buttonIndex = 0; buttonIndex < allButtons.length; buttonIndex++) {
var nextButton = $(allButtons[buttonIndex]);
if(nextButton.attr('value') == true) {
nextButton.attr('value', false);
nextButton.children().first().removeClass(cssChecked);
nextButton.children().first().addClass(cssUnchecked);
}
}
//Check this selected button.//
_this.attr('value', true);
_this.children().first().removeClass(cssUnchecked);
_this.children().first().addClass(cssChecked);
}
});
next.keypress(function(event) {
if(event.which == 32 || event.which == 13) {
var _this = $(event.target);
_this.children().first().click();
}
});
}
}
return this;
}
})(jQuery);

1491
public/js/jquery.cycle.js Normal file

File diff suppressed because it is too large Load Diff

10
public/js/jquery.cycle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1547
public/js/jquery.cycle2.js Normal file

File diff suppressed because it is too large Load Diff

16
public/js/jquery.cycle2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
(function($) {
$.fn.display = function(show) {
if(this.hasClass('inline')) {
this.css('visibility', show ? 'visible' : 'hidden');
}
else {
if(show) this.show();
else this.hide();
}
};
})(jQuery);

194
public/js/jquery.history.js Normal file
View File

@@ -0,0 +1,194 @@
/*
* jQuery history plugin
*
* The MIT License
*
* Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari)
* Copyright (c) 2010 Takayuki Miwa
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
(function($) {
var locationWrapper = {
put: function(hash, win) {
(win || window).location.hash = this.encoder(hash);
},
get: function(win) {
var hash = ((win || window).location.hash).replace(/^#/, '');
try {
return $.browser.mozilla ? hash : decodeURIComponent(hash);
}
catch (error) {
return hash;
}
},
encoder: encodeURIComponent
};
var iframeWrapper = {
id: "__jQuery_history",
init: function() {
var html = '<iframe id="'+ this.id +'" style="display:none" src="javascript:false;" />';
$("body").prepend(html);
return this;
},
_document: function() {
return $("#"+ this.id)[0].contentWindow.document;
},
put: function(hash) {
var doc = this._document();
doc.open();
doc.close();
locationWrapper.put(hash, doc);
},
get: function() {
return locationWrapper.get(this._document());
}
};
function initObjects(options) {
options = $.extend({
unescape: false
}, options || {});
locationWrapper.encoder = encoder(options.unescape);
function encoder(unescape_) {
if(unescape_ === true) {
return function(hash){ return hash; };
}
if(typeof unescape_ == "string" &&
(unescape_ = partialDecoder(unescape_.split("")))
|| typeof unescape_ == "function") {
return function(hash) { return unescape_(encodeURIComponent(hash)); };
}
return encodeURIComponent;
}
function partialDecoder(chars) {
var re = new RegExp($.map(chars, encodeURIComponent).join("|"), "ig");
return function(enc) { return enc.replace(re, decodeURIComponent); };
}
}
var implementations = {};
implementations.base = {
callback: undefined,
type: undefined,
check: function() {},
load: function(hash) {},
init: function(callback, options) {
initObjects(options);
self.callback = callback;
self._options = options;
self._init();
},
_init: function() {},
_options: {}
};
implementations.timer = {
_appState: undefined,
_init: function() {
var current_hash = locationWrapper.get();
self._appState = current_hash;
self.callback(current_hash);
setInterval(self.check, 100);
},
check: function() {
var current_hash = locationWrapper.get();
if(current_hash != self._appState) {
self._appState = current_hash;
self.callback(current_hash);
}
},
load: function(hash) {
if(hash != self._appState) {
locationWrapper.put(hash);
self._appState = hash;
self.callback(hash);
}
}
};
implementations.iframeTimer = {
_appState: undefined,
_init: function() {
var current_hash = locationWrapper.get();
self._appState = current_hash;
iframeWrapper.init().put(current_hash);
self.callback(current_hash);
setInterval(self.check, 100);
},
check: function() {
var iframe_hash = iframeWrapper.get(),
location_hash = locationWrapper.get();
if (location_hash != iframe_hash) {
if (location_hash == self._appState) { // user used Back or Forward button
self._appState = iframe_hash;
locationWrapper.put(iframe_hash);
self.callback(iframe_hash);
} else { // user loaded new bookmark
self._appState = location_hash;
iframeWrapper.put(location_hash);
self.callback(location_hash);
}
}
},
load: function(hash) {
if(hash != self._appState) {
locationWrapper.put(hash);
iframeWrapper.put(hash);
self._appState = hash;
self.callback(hash);
}
}
};
implementations.hashchangeEvent = {
_init: function() {
self.callback(locationWrapper.get());
$(window).bind('hashchange', self.check);
},
check: function() {
self.callback(locationWrapper.get());
},
load: function(hash) {
locationWrapper.put(hash);
}
};
var self = $.extend({}, implementations.base);
if($.browser.msie && ($.browser.version < 8 || document.documentMode < 8)) {
self.type = 'iframeTimer';
} else if("onhashchange" in window) {
self.type = 'hashchangeEvent';
} else {
self.type = 'timer';
}
$.extend(self, implementations[self.type]);
$.history = self;
})(jQuery);

1
public/js/jquery.history.min.js vendored Normal file
View File

@@ -0,0 +1 @@
!function(t){function n(n){function c(t){return t===!0?function(t){return t}:"string"==typeof t&&(t=a(t.split("")))||"function"==typeof t?function(n){return t(encodeURIComponent(n))}:encodeURIComponent}function a(n){var e=new RegExp(t.map(n,encodeURIComponent).join("|"),"ig");return function(t){return t.replace(e,decodeURIComponent)}}n=t.extend({unescape:!1},n||{}),e.encoder=c(n.unescape)}var e={put:function(t,n){(n||window).location.hash=this.encoder(t)},get:function(n){var e=(n||window).location.hash.replace(/^#/,"");try{return t.browser.mozilla?e:decodeURIComponent(e)}catch(c){return e}},encoder:encodeURIComponent},c={id:"__jQuery_history",init:function(){var n='<iframe id="'+this.id+'" style="display:none" src="javascript:false;" />';return t("body").prepend(n),this},_document:function(){return t("#"+this.id)[0].contentWindow.document},put:function(t){var n=this._document();n.open(),n.close(),e.put(t,n)},get:function(){return e.get(this._document())}},a={};a.base={callback:void 0,type:void 0,check:function(){},load:function(){},init:function(t,e){n(e),o.callback=t,o._options=e,o._init()},_init:function(){},_options:{}},a.timer={_appState:void 0,_init:function(){var t=e.get();o._appState=t,o.callback(t),setInterval(o.check,100)},check:function(){var t=e.get();t!=o._appState&&(o._appState=t,o.callback(t))},load:function(t){t!=o._appState&&(e.put(t),o._appState=t,o.callback(t))}},a.iframeTimer={_appState:void 0,_init:function(){var t=e.get();o._appState=t,c.init().put(t),o.callback(t),setInterval(o.check,100)},check:function(){var t=c.get(),n=e.get();n!=t&&(n==o._appState?(o._appState=t,e.put(t),o.callback(t)):(o._appState=n,c.put(n),o.callback(n)))},load:function(t){t!=o._appState&&(e.put(t),c.put(t),o._appState=t,o.callback(t))}},a.hashchangeEvent={_init:function(){o.callback(e.get()),t(window).bind("hashchange",o.check)},check:function(){o.callback(e.get())},load:function(t){e.put(t)}};var o=t.extend({},a.base);o.type=t.browser.msie&&(t.browser.version<8||document.documentMode<8)?"iframeTimer":"onhashchange"in window?"hashchangeEvent":"timer",t.extend(o,a[o.type]),t.history=o}(jQuery);

View File

@@ -0,0 +1,5 @@
(function($) {
$.history.replace = function(hash) {
window.location.replace(window.location.href.substring(0, window.location.href.indexOf("#")) + "#" + hash);
}
})(jQuery);

11
public/js/jquery.mousewheel.min.js vendored Normal file
View File

@@ -0,0 +1,11 @@
/* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
*
* Version: 3.0.2
*
* Requires: 1.2.2+
*/
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);

104
public/js/jquery.shadow.js Normal file
View File

@@ -0,0 +1,104 @@
//
//Notes:
//Requires that the element getting the shadow have a fixed height and width defined in the html, and that both a left and right or top and bottom reference be provided.
//Alternatively a shadow-class="xxx" attribute can be supplied that references a css class with those properties. The css class must have width and height that includes the contents, border, and shadow size (10px x 10px).
// Example: <div class="shadow" shadow-class="shadowDivCss" style="">...</div>
//
(function($) {
$.fn.buildShadow = function() {
for(var index = 0; index < this.length; index++) {
var next = $(this[index]);
//Prevent a double shadow.//
if(!next.parent().data('is-shadow')) {
//<div style="position: relative; top: -8px; left: 0px; width: 256px; height: 164px; float: left;">
//Wrap the image with a div and leave space for shadows.//
next.wrap(function(index) {
$next = $(next);
var p = $next.css('position');
var f = $next.css('float');
var w = parseInt($next.css('width'));
var h = parseInt($next.css('height'));
var classes = $next.attr('shadow-class');
var c = $next.css('clear');
var padT = parseInt($next.css('padding-top'));
var padR = parseInt($next.css('padding-right'));
var padB = parseInt($next.css('padding-bottom'));
var padL = parseInt($next.css('padding-left'));
var marT = $next.css('margin-top');
var marR = $next.css('margin-right');
var marB = $next.css('margin-bottom');
var marL = $next.css('margin-left');
var borL = parseInt($next.css('border-left-width'));
var borR = parseInt($next.css('border-right-width'));
var borT = parseInt($next.css('border-top-width'));
var borB = parseInt($next.css('border-bottom-width'));
var html;
html = "<div " + (classes ? " class='" + classes + "'" : "") + " style='" + (w > 0 && h > 0 ? "width: " + (w + 10 + padL + padR + borL + borR) + "px; height: " + (h + 10 + padT + padB + borT + borB) + "px;" : "");
if(p != 'static') {
var left = $next.css('left');
var right = $next.css('right');
var top = $next.css('top');
var bottom = $next.css('bottom');
html += " position: " + p + ";";
//TODO: Assuming for now that a left & right or top & bottom were not defined.
if(left) {
html += " left: " + left + ";";
}
else {
html += " right: " + right + ";";
}
if(top) {
html += " top: " + top + ";";
}
else {
html += " bottom: " + bottom + ";";
}
//Make the image static.//
$next.css({left: 0, right: 0, top: 0, bottom: 0, position: 'static'});
}
else {
//Make the position relative such that the absolutely positioned shadow backgrounds are absolute relative to the parent div.//
html += " position: relative;";
$next.css({left: 0, top: 0, position: 'absolute'});
}
//Transfer the float to the container, from the image.//
if(f && f != 'none') {
html += " float: " + f + ";";
$next.css('float', undefined);
}
if(c && c != 'none') {
html += " clear: " + c + ";";
$next.css('clear', undefined);
}
//Margins & Padding//
html += " margin-top: " + marT + "; margin-right: " + marR + "; margin-bottom: " + marB + "; margin-left: " + marL + ";"
// padding-top: " + padT + "; padding-right: " + padR + "; padding-bottom: " + padB + "; padding-left: " + padL + ";";
//$next.css({margin: 0, padding: 0});
$next.css('margin', 0);
html += "'/>";
return html;
});
//Place the shadows.//
next.each(function(index) {
$next = $(next);
$next.before("<div style='position: absolute; right: 0px; top: 0px; height: 10px; width: 10px; background: url(\"images/shadow_tr.png\");'></div><div style='position: absolute; top: 10px; right: 0px; bottom: 10px; width: 10px; background: url(\"images/shadow_r.png\");'></div><div style='position: absolute; right: 0px; bottom: 0px; height: 10px; width: 10px; background: url(\"images/shadow_br.png\");'></div><div style='position: absolute; left: 10px; right: 10px; bottom: 0px; height: 10px; background: url(\"images/shadow_b.png\");'></div><div style='position: absolute; left: 0px; bottom: 0px; height: 10px; width: 10px; background: url(\"images/shadow_bl.png\");'></div>");
});
next.parent().data('is-shadow', true);
}
}
return this;
}
})(jQuery);

View File

@@ -0,0 +1,46 @@
//
//Notes:
//Requires that the element getting the shadow have a fixed height and width defined in the css, and that both a left and right or top and bottom reference be provided.
//
(function($) {
$.fn.buildShadowText = function() {
for(var index = 0; index < this.length; index++) {
var next = $(this[index]);
//Setup all the shadow text fields to show their shadow text when the field is empty and out of focus.//
var shadowText = next.attr('shadow-text');
var val = next.val();
if(!val || val.length == 0) {
next.data('originalColor', next.css('color'));
next.css('color', '#999');
next.data('isShowingShadowText', true);
next.val(shadowText);
}
next.focus(function() {
var next = $(this);
var isShowing = next.data('isShowingShadowText');
if(isShowing) {
next.css('color', next.data('originalColor'));
next.val("");
next.data('isShowingShadowText', false);
}
});
next.blur(function() {
var next = $(this);
var shadowText = next.attr('shadow-text');
var val = next.val();
if(!val || val.length == 0) {
next.data('originalColor', next.css('color'));
next.css('color', '#999');
next.data('isShowingShadowText', true);
next.val(shadowText);
}
});
}
return this;
}
})(jQuery);

364
public/js/layout.js Normal file
View File

@@ -0,0 +1,364 @@
//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;
}
}
}
function LayoutManager(viewName) {
//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";
}
//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);
//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/>");
}
}

47
public/js/main.js Normal file
View File

@@ -0,0 +1,47 @@
var slideShowIndex = 0;
var slideShowSlides = []; //An array of arrays - each sub-array contains the image path, title, description, width, and height.//
var scrollerScrollTime = 3500;
var scrollerInitialDelay = 5000;
var scrollerTransitionTime = 1000;
window.status="";
//Handle the document ready event which is where any initialization code goes.
$(document).ready(function($) {
var layoutManager = new LayoutManager("main-view");
//layoutManager.defaultUrl = '#!/holidays';
layoutManager.defaultUrl = '#!/Farm';
layoutManager.pageClassFades = [
{cls: 'full', fadeIn: null, fadeOut: null}
];
layoutManager.viewMetadataDefaults = {classes: 'full'};
layoutManager.viewMetadata = {
weddings: {
load: "element.data('scroller', new ItemScroller($('div.scrollViewport'), 142, scrollerScrollTime, scrollerInitialDelay, scrollerTransitionTime, false));",
unload:"element.data('scroller').release(); element.data('scroller', undefined);"
},
};
//Associate a function with the history jquery addon that will load the url content after the history is updated.
$.history.init(function(url) {
if(!url || url.length == 0) {
url = layoutManager.defaultUrl;
}
layoutManager.show(url);
});
/*
var websocket = new WebSocket('ws://petitteton.com/');
websocket.onopen = function() {
websocket.ping();
};
websocket.onerror = function(error) {
console.log('Websocket error: ' + error);
};
websocket.onmessage = function(message) {
console.log('Server: ' + message);
};
*/
});

213
public/js/scroller.js Normal file
View File

@@ -0,0 +1,213 @@
/**
* Creates and starts the item scroller which must receive the ID of the node containing the elements to be scrolled,
* an optional increment size for the scroll (may be zero if auto), and an optional autoscroll time interval (millseconds).
* Transition is the number of milliseconds for the animation of shifting one increment.
* @param viewport The jquery wrapper around the viewport container.
* @param increment The number of pixels to shift. If not defined then it will be pulled from the first child of the page.
* @param autoTimer The number of milliseconds to wait between automatic shifts. If undefined or <= 0 then there won't be any auto shifts.
* @param initialDelay The number of milliseconds to wait before starting automatic shifts, or zero if undefined or less than zero.
* @param transition The number of milliseconds to animate the shifting of the page. Will default to 1000.
* @param resetPosition Whether the scroll position is reset upon releasing the item scroller. This defaults to true.
*/
function ItemScroller(viewport, increment, autoTimer, initialDelay, transition, resetPosition) {
this.viewport = viewport;
this.increment = increment != undefined && increment != 0 ? this.stripMetric(increment) : undefined;
if(resetPosition != undefined) {
this.resetPosition = resetPosition;
}
this.init();
if(autoTimer != undefined) {
this.autoscroll(autoTimer, initialDelay);
}
if(transition != undefined && transition > 0) {
this.transition = transition;
}
}
ItemScroller.prototype.constructor = ItemScroller;
ItemScroller.prototype.viewport = null;
ItemScroller.prototype.page = null;
ItemScroller.prototype.increment = null;
ItemScroller.prototype.pageWidth = null;
ItemScroller.prototype.isShifting = false;
ItemScroller.prototype.autoscrollPause = false;
ItemScroller.prototype.isReleased = false;
ItemScroller.prototype.transition = 1000;
ItemScroller.prototype.copyCount = 0;
ItemScroller.prototype.resetPosition = true;
ItemScroller.prototype.currentIndex = 0;
ItemScroller.prototype.length = 0;
ItemScroller.prototype.init = function() {
this.page = this.viewport.children(':first');
var children = this.page.children();
this.length = children.length;
//Calculate the increment size for each left/right scroll.//
if(this.increment == undefined) {
this.increment = this.stripMetric(children.first().outerWidth());
}
//Calculate the width of the original set of displayed elements.//
var viewportWidth = this.viewport.outerWidth();
var pageWidth = 0;
this.page.children().each(function() {
pageWidth += $(this).outerWidth();
});
this.pageWidth = pageWidth;
//Calculate the wrap size that will be needed on the tail of the original set of elements to simulate a wrap around effect.//
var remainder = this.pageWidth / this.increment != 0 ? this.pageWidth % this.increment : this.increment;
var tailLength = remainder;
//Clone children until we have enough to properly simulate a wrap around scrolling action.//
for(var index = 0; index < children.length && tailLength < viewportWidth; index++) {
var next = $(children[index]);
tailLength += next.outerWidth();
next.clone(true, true).appendTo(this.page);
this.copyCount++;
}
//Now: Fix the spacing the browser adds between inline elements that have any kind of spacing or line feeds between them (bad browsers!).//
children = this.page.children();
this.page.css({position: 'relative'});
var offset = 0;
children.each(function() {
var next = $(this);
next.css({position: 'absolute', left: offset, top: 0, display: 'block'});
offset += next.outerWidth();
});
if(this.resetPosition) {
//Start at the beginning.//
this.viewport.scrollLeft(0);
}
else {
var lastIndex = this.viewport.data('lastIndex');
if(lastIndex) {
this.currentIndex = lastIndex;
this.viewport.parents().css('display', 'block');
this.viewport.scrollLeft(lastIndex * this.increment);
//this.viewport.one('scroll', function() {
// this.viewport.scrollLeft(this.currentIndex * this.increment);
//});
}
else {
this.viewport.scrollLeft(0);
}
}
}
ItemScroller.prototype.release = function() {
//this.page.stop(true, false);
//this.page.css({left: 0});
if(!this.released) {
//Stop the animation.//
this.viewport.stop(true, false);
//Remove the children that were added upon initialization.//
var children = this.page.children();
children.slice(children.length - this.copyCount).detach();
//Flag ourselves as released.//
this.isReleased = true;
if(this.resetPosition) {
//Start at the beginning.//
//this.viewport.scrollLeft(0);
}
this.viewport.data('lastIndex', this.currentIndex);
}
}
ItemScroller.prototype.next = function(fn) {
if(!this.isShifting) {
var pageLeft = this.viewport.scrollLeft();
var newPageLeft = pageLeft + this.increment;
var wrapPosition = this.pageWidth;
var shift = this.pageWidth;
var _this = this;
this.isShifting = true;
//this.viewport.data('nextScrollLeft', newPageLeft);
this.currentIndex = (this.currentIndex + 1) % this.length;
this.viewport.animate({scrollLeft: newPageLeft}, {duration: this.transition, queue: true, step: function(now, fx) {
if(fx.now >= wrapPosition) {
fx.start -= shift;
fx.end -= shift;
fx.now -= shift;
}
}, complete: function() {
_this.isShifting = false;
if(fn) fn();
}});
}
return this;
}
ItemScroller.prototype.prev = function(fn) {
if(!this.isShifting) {
var pageLeft = this.viewport.scrollLeft();
var newPageLeft = pageLeft - this.increment;
var wrapPosition = 0;
var shift = this.pageWidth;
var _this = this;
this.isShifting = true;
this.currentIndex = this.currentIndex - 1 < 0 ? this.length : this.currentIndex - 1;
this.viewport.animate({scrollLeft: newPageLeft}, {duration: this.transition, queue: true, step: function(now, fx) {
if(fx.now <= wrapPosition) {
fx.start += shift;
fx.end += shift;
fx.now += shift;
}
}, complete: function() {_this.isShifting = false; if(fn) fn();}});
}
return this;
}
ItemScroller.prototype.pause = function() {
this.autoscrollPause = true;
return this;
}
ItemScroller.prototype.resume = function() {
this.autoscrollPause = false;
return this;
}
ItemScroller.prototype.autoscroll = function(delay, initialDelay) {
var _this = this;
/* Pause scrolling on mouse over.
this.page.mouseover(function(eventObject) {
_this.autoscrollPause = true;
});
this.page.mouseout(function(eventObject) {
_this.autoscrollPause = false;
});
*/
if(initialDelay == undefined || initialDelay <= 0) {
this.autoscrollIncrement(delay);
}
else {
window.setTimeout(function() {_this.autoscrollIncrement(delay);}, initialDelay);
}
}
ItemScroller.prototype.autoscrollIncrement = function(delay) {
var _this = this;
if(!this.isReleased) {
var fn = function() {
window.setTimeout(function() {_this.autoscrollIncrement(delay);}, delay);
};
if(!this.autoscrollPause) {
this.next(fn);
}
else {
fn();
}
}
}
ItemScroller.prototype.stripMetric = function(value) {
return parseInt(value);
}