Major changes to the structure of pages to utilize the flex layout system.
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
//
|
||||
//A dropdown menu. Pass it a container and an array of data, and it will build the button, caret, and list of selectable elements inside the container.
|
||||
//
|
||||
(function($) {
|
||||
var Dropdown = function($element, data, options) {
|
||||
var _this = this
|
||||
var _this = this;
|
||||
var textSpan = $("<span>" + options.defaultText + "</span>");
|
||||
|
||||
this.$element = $element;
|
||||
|
||||
337
public/admin/js/EditableSelect.js
Normal file
337
public/admin/js/EditableSelect.js
Normal file
@@ -0,0 +1,337 @@
|
||||
"use strict";
|
||||
|
||||
//
|
||||
// Takes a input form element and a hidden form element (to store the selected id in) along with an array of objects, to build a dropdown select control that allows the user to type part of the selection to filter the list.
|
||||
//
|
||||
(function($) {
|
||||
var EditableSelect = function($input, $hidden, data, options) {
|
||||
var _this = this;
|
||||
|
||||
this.$input = $input;
|
||||
this.$hidden = $hidden;
|
||||
this.options = $.extend({}, EditableSelect.DEFAULTS, options);
|
||||
this.$selected = null;
|
||||
this.$listContainer = $('<div/>', {style: 'position: relative; height: 0;'});
|
||||
this.$list = $('<ul/>', {role: 'menu', class: this.options.listClass});
|
||||
|
||||
//Ensure that if the hidden field exists and changes, that the hidden field's id matches the text in the input field. If not then the hidden id field was changed manually and externally and the text field should be updated.
|
||||
if(this.$hidden) {
|
||||
this.$hidden.on('change', function(event) {
|
||||
var id = _this.$hidden.val();
|
||||
var $li = _this.$list.children("[role!='node']");
|
||||
|
||||
for(var i = 0; i < $li.length; i++) {
|
||||
var $next = $($li[i]);
|
||||
|
||||
if($next.data('model').id == id) {
|
||||
if(_this.$input.val() != $next.text())
|
||||
_this.$input.val($next.text());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//this.$list.appendTo($input.parent());
|
||||
this.$list.appendTo(this.$listContainer);
|
||||
this.$listContainer.appendTo($input.parent());
|
||||
|
||||
//Setup the list to highlight the item the user is hovering over, to select the item the user clicks, and to remove the hover styling when the list closes due to a selection being made.
|
||||
this.$list
|
||||
.on('mousemove', 'li', function() {
|
||||
// _this.$list.find(_this.options.selectionClass).removeClass(_this.options.selectionClass);
|
||||
var $this = $(this);
|
||||
|
||||
//Skip nodes.
|
||||
while($this && $this.attr('role') == 'node') {
|
||||
$this = $this.next();
|
||||
}
|
||||
|
||||
//If we could find a non-node element then highlight it.
|
||||
if($this) $this.addClass(_this.options.selectionClass).siblings().removeClass(_this.options.selectionClass);
|
||||
})
|
||||
.on('mousedown', 'li', function() {
|
||||
var $this = $(this);
|
||||
|
||||
//Skip nodes.
|
||||
while($this && $this.attr('role') == 'node') {
|
||||
$this = $this.next();
|
||||
}
|
||||
|
||||
//If we could find a non-node element then highlight it.
|
||||
if($this) _this.select($this);
|
||||
})
|
||||
.on('mouseup', function() {
|
||||
//Remove the selection highlighting.
|
||||
_this.$list.children().removeClass(_this.options.selectionClass);
|
||||
//Hide the list.
|
||||
_this.hide();
|
||||
});
|
||||
//Setup the input field to handle opening the list when it receives focus, and close it when it loses focus.
|
||||
this.$input
|
||||
.on('focus', $.proxy(_this.focus, _this))
|
||||
.on('blur', $.proxy(_this.blur, _this));
|
||||
//Handle key events on the input field. Up/down arrows should change the selection in the list. Enter should select an item and close the list. Tab and escape should hide the list before moving to the next focusable element on the page.
|
||||
this.$input.on('input keydown', function(event) {
|
||||
switch(event.keyCode) {
|
||||
case 38: //Up
|
||||
var visibles = _this.$list.find('li.visible[role!="node"]');
|
||||
var selected = visibles.index(visibles.filter('.' + _this.options.selectionClass)) || 0;
|
||||
_this.highlight(selected - 1);
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 40: //Down
|
||||
var visibles = _this.$list.find('li.visible[role!="node"]');
|
||||
var selected = visibles.index(visibles.filter('li.selected')) || 0;
|
||||
_this.highlight(selected + 1);
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 13: //Enter
|
||||
if(_this.$list.is(':visible')) {
|
||||
_this.select(_this.$list.find('li.selected'));
|
||||
event.preventDefault();
|
||||
}
|
||||
case 9: //Tab
|
||||
_this.select(_this.$list.find('li.selected'));
|
||||
case 27: //Esc
|
||||
_this.hide();
|
||||
break;
|
||||
default:
|
||||
_this.filter();
|
||||
_this.highlight(0);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Adds one or more elements to the control.
|
||||
// data: The item or array of items to add. This will be the root tree elements if groupFunctions is provided.
|
||||
function add(data) {
|
||||
var groupFunctions = _this.options.groupFunctions;
|
||||
|
||||
var addOne = function(data, parent) { //role is optional.
|
||||
var text = $.isFunction(_this.options.textAttr) ? _this.options.textAttr(data) : data[_this.options.textAttr];
|
||||
var li = $("<li" + (parent ? " role='leaf'" : "") + ">" + text + "</li>");
|
||||
|
||||
li.appendTo(_this.$list);
|
||||
li.data('model', data);
|
||||
if(parent) li.data('parent-li', parent);
|
||||
};
|
||||
var addOneGroup = function(data, text, children) {
|
||||
var li = $("<li role='node'>" + text + "</li>");
|
||||
|
||||
li.appendTo(_this.$list);
|
||||
li.data('model', data);
|
||||
|
||||
for(var childIndex = 0; childIndex < children.length; childIndex++) {
|
||||
addOne(children[childIndex], li);
|
||||
}
|
||||
};
|
||||
var addOneBranch = function(data) {
|
||||
var parents = $.isFunction(groupFunctions.groupParents) ? groupFunctions.groupParents(data) : data;
|
||||
|
||||
//Since there may be one or more parents identified for each data element passed to us...
|
||||
if(Array.isArray(parents)) {
|
||||
for(var parentIndex = 0; parentIndex < parents.length; parentIndex++) {
|
||||
addOneGroup(parents[parentIndex], groupFunctions.parentText(parents[parentIndex]), groupFunctions.children(parents[parentIndex]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
addOneGroup(parents, groupFunctions.parentText(parents), groupFunctions.children(parents));
|
||||
}
|
||||
};
|
||||
|
||||
if(groupFunctions instanceof Object && $.isFunction(groupFunctions.children) && $.isFunction(groupFunctions.parentText)) {
|
||||
if(Array.isArray(data)) {
|
||||
for(var dataIndex = 0; dataIndex < data.length; dataIndex++) {
|
||||
addOneBranch(data[dataIndex]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
addOneBranch(data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(Array.isArray(data)) {
|
||||
for(var dataIndex = 0; dataIndex < data.length; dataIndex++) {
|
||||
addOne(data[dataIndex]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
addOne(data);
|
||||
}
|
||||
}
|
||||
|
||||
//Filter the set of elements so that only those matching the text in the input field are marked as visible.
|
||||
_this.filter();
|
||||
}
|
||||
|
||||
//Add the initial set of data.
|
||||
add(data);
|
||||
};
|
||||
|
||||
EditableSelect.DEFAULTS = {
|
||||
textAttr: 'text', //The attribute of the data elements to use for the name. This can also be a function that takes the data object and returns the text.
|
||||
idAttr: 'id', //The attribute of the data elements to use for the ID. This can also be a function that takes the data obejct and returns the ID.
|
||||
// groupFunctions: The object containing three functions: 'groupParent', 'parentText', 'children'.
|
||||
// groupParents(data) will take a data element and return the objects that best represents the parents of the children (for a multi layer tree, this would be the node just before the leaf nodes).
|
||||
// parentText(parent) will be passed the group parent and the data object that generated it, and will return the text that represents the path to that parent.
|
||||
// children(parent) will be passed the group parent (returned by groupParents()), and will return an array of children or leaf nodes for the tree.
|
||||
groupFunctions: undefined,
|
||||
filter: true, //Whether to filter the list as the user types.
|
||||
effects: 'fade',
|
||||
duration: '200',
|
||||
listClass: 'editable-select-list',
|
||||
selectionClass: 'selected' //The class to use for the selected element in the dropdown list.
|
||||
};
|
||||
|
||||
EditableSelect.prototype.select = function($li) {
|
||||
if($li.length == 0) {
|
||||
if(this.$input.val() != '') {
|
||||
this.$input.val("")
|
||||
if(this.$hidden) this.$hidden.val(undefined);
|
||||
this.filter();
|
||||
//Note: Don't trigger the select event - for some reason it causes the dropdown to reopen and the control to retain focus when clicking out of the widget.
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!this.$list.has($li) || !$li.is('li.visible')) return;
|
||||
|
||||
//No need to change selection if the selection has not changed.
|
||||
if(this.$input.val() != $li.text()) {
|
||||
this.$input.val($li.text()); //Save the selected text into the text input.
|
||||
if(this.$hidden) this.$hidden.val($li.data('model')[this.options.idAttr]); //Save the ID into the hidden form input if it exists.
|
||||
this.hide();
|
||||
this.filter();
|
||||
//this.trigger('select', $li);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Filters the list items by marking those that match the text in the text field as having the class 'visible'.
|
||||
EditableSelect.prototype.filter = function() {
|
||||
try {
|
||||
var search = this.$input.val();
|
||||
var _this = this;
|
||||
|
||||
search = search ? search : "";
|
||||
search = search.toLowerCase().trim();
|
||||
|
||||
//Show all list elements.
|
||||
this.$list.find('li').addClass('visible').show();
|
||||
//Hide any node list elements.
|
||||
this.$list.find('li[role="node"]').removeClass('visible').hide();
|
||||
|
||||
if(this.options.filter) {
|
||||
//Hide non-node elements (leaf nodes) that don't match.
|
||||
var li = this.$list.children();
|
||||
|
||||
//Iterate over the list elements:
|
||||
// hide all list items that are nodes;
|
||||
// show all list items that are not nodes and whose text matches the input value;
|
||||
// show all node list items associated with visible child list items (they occur after the parent, so the parent will be hidden first, then made visible).
|
||||
for(var i = 0; i < li.length; i++) {
|
||||
var $next = $(li[i]);
|
||||
var node = $next.attr('role') == 'node';
|
||||
var hidden = node || $next.text().toLowerCase().indexOf(search) < 0;
|
||||
|
||||
if(hidden) $next.removeClass('visible').hide();
|
||||
|
||||
//If this isn't hidden and we have a tree with grouping, then turn on the group (parent) associated with this option.
|
||||
if(!hidden && _this.options.groupFunctions) {
|
||||
var parent = $next.data('parent-li');
|
||||
|
||||
if(!parent.hasClass('visible')) parent.addClass('visible').show();
|
||||
}
|
||||
}
|
||||
|
||||
//If we hid all elements then hide the whole list.
|
||||
if(this.$list.find('li.visible').length == 0) this.hide();
|
||||
}
|
||||
}catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
EditableSelect.prototype.focus = function() {
|
||||
this.show();
|
||||
this.$input.select();
|
||||
};
|
||||
|
||||
EditableSelect.prototype.blur = function() {
|
||||
this.hide();
|
||||
this.select(this.$list.find('li.selected'));
|
||||
};
|
||||
|
||||
EditableSelect.prototype.show = function() {
|
||||
//Position the list relative to the edit field.
|
||||
this.$list.css({position: 'absolute', top: 0, left: 0, width: this.$input.outerWidth()});
|
||||
|
||||
if(!this.$list.is(':visible') && this.$list.find('li.visible').length > 0) {
|
||||
var fns = {default: 'show', fade: 'fadeIn', slide: 'slideDown'};
|
||||
var fn = fns[this.options.effects];
|
||||
|
||||
this.trigger('show');
|
||||
this.$input.addClass('open');
|
||||
this.$list[fn](this.options.duration, $.proxy(this.trigger, this, 'shown'));
|
||||
}
|
||||
};
|
||||
|
||||
EditableSelect.prototype.hide = function() {
|
||||
var fns = {default: 'hide', fade: 'fadeOut', slide: 'slideUp'};
|
||||
var fn = fns[this.options.effects];
|
||||
|
||||
this.trigger('hide');
|
||||
this.$input.removeClass('open');
|
||||
this.$list[fn](this.options.duration, $.proxy(this.trigger, this, 'hidden'));
|
||||
};
|
||||
|
||||
// goDown: true/false - defaults to true - indicating whether the highlighting should go up or down if the requested item is a node. Nodes cannot be highlighted or selected.
|
||||
EditableSelect.prototype.highlight = function(index) {
|
||||
var _this = this;
|
||||
|
||||
this.show();
|
||||
|
||||
setTimeout(function() {
|
||||
var visibles = _this.$list.find('li.visible[role!="node"]');
|
||||
var oldSelected = _this.$list.find('li.' + _this.options.selectionClass).removeClass(_this.options.selectionClass);
|
||||
var oldSelectedIndex = visibles.index(oldSelected);
|
||||
|
||||
if(visibles.length > 0) {
|
||||
var selectedIndex = (visibles.length + index) % visibles.length;
|
||||
var selected = visibles.eq(selectedIndex);
|
||||
var top = selected.position().top;
|
||||
|
||||
if(selected.attr('role') != 'node') selected.addClass(_this.options.selectionClass);
|
||||
|
||||
if(selectedIndex < oldSelectedIndex && top < 0)
|
||||
_this.$list.scrollTop(_this.$list.scrollTop() + top);
|
||||
if(selectedIndex > oldSelectedIndex && top + selected.outerHeight() > _this.$list.outerHeight())
|
||||
_this.$list.scrollTop(_this.$list.scrollTop() + selected.outerHeight() + 2 * (top - _this.$list.outerHeight()));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
EditableSelect.prototype.trigger = function(event) {
|
||||
var params = Array.prototype.slice.call(arguments, 1);
|
||||
var args = [event + '.editable-select'];
|
||||
|
||||
args.push(params);
|
||||
|
||||
if(this.$select) this.$select.trigger.apply(this.$select, args);
|
||||
this.$input.trigger.apply(this.$input, args);
|
||||
};
|
||||
|
||||
$.fn.buildEditableSelect = function(data, options) {
|
||||
for(var index = 0; index < this.length; index++) {
|
||||
var $next = $(this[index]);
|
||||
var nextEditableSelect = new EditableSelect($next, $next.siblings('input[type=hidden]').first(), data, options);
|
||||
|
||||
$next.data("editable-select", nextEditableSelect);
|
||||
}
|
||||
};
|
||||
$.fn.editableSelect = function() {
|
||||
if(this.length > 0) {
|
||||
return $(this[0]).data('editable-select');
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
File diff suppressed because it is too large
Load Diff
2
public/admin/js/chosen.jquery.min.js
vendored
2
public/admin/js/chosen.jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,153 +0,0 @@
|
||||
//
|
||||
// Requires jquery at a minimum.
|
||||
//
|
||||
|
||||
var framework = new BrainstormFramework();
|
||||
var brainstormFramework = framework;
|
||||
|
||||
function BrainstormFramework() {
|
||||
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
this.extractViewData = function(viewData) {
|
||||
if(viewData != undefined) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
};
|
||||
}
|
||||
30
public/admin/js/jquery.disableSelection.js
Normal file
30
public/admin/js/jquery.disableSelection.js
Normal file
@@ -0,0 +1,30 @@
|
||||
(function($){
|
||||
$.fn.disableSelection = function() {
|
||||
return this
|
||||
.attr('unselectable', 'on')
|
||||
.css('user-select', 'none')
|
||||
.css('-moz-user-select', 'none')
|
||||
.css('-khtml-user-select', 'none')
|
||||
.css('-webkit-user-select', 'none')
|
||||
.on('selectstart', false)
|
||||
.on('contextmenu', false)
|
||||
.on('keydown', false)
|
||||
.on('mousedown', false)
|
||||
.css({cursor: 'default'});
|
||||
};
|
||||
|
||||
$.fn.enableSelection = function() {
|
||||
return this
|
||||
.attr('unselectable', '')
|
||||
.css('user-select', '')
|
||||
.css('-moz-user-select', '')
|
||||
.css('-khtml-user-select', '')
|
||||
.css('-webkit-user-select', '')
|
||||
.off('selectstart', false)
|
||||
.off('contextmenu', false)
|
||||
.off('keydown', false)
|
||||
.off('mousedown', false)
|
||||
.css({cursor: 'auto'});
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
272
public/admin/js/jquery.editable.select.js
Normal file
272
public/admin/js/jquery.editable.select.js
Normal file
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
* jQuery Editable Select
|
||||
* Indri Muska <indrimuska@gmail.com>
|
||||
*
|
||||
* Source on GitHub @ https://github.com/indrimuska/jquery-editable-select
|
||||
*/
|
||||
|
||||
+(function($) {
|
||||
// jQuery Editable Select
|
||||
EditableSelect = function(select, options) {
|
||||
var that = this;
|
||||
|
||||
if(select.nodeName == "SELECT") {
|
||||
var inputProperties = {
|
||||
type: "text",
|
||||
autocomplete: "off"
|
||||
};
|
||||
|
||||
//Add the user input properties to the ones specified above.
|
||||
if(options.inputProperties && options.inputProperties instanceof Object) $.extend(inputProperties, options.inputProperties);
|
||||
|
||||
this.$select = $(select);
|
||||
this.$input = $('<input/>', inputProperties);
|
||||
//Replace the select with an input widget in the view.
|
||||
this.$select.replaceWith(this.$input);
|
||||
}
|
||||
else if(select.nodeName == "INPUT") {
|
||||
this.$select = undefined;
|
||||
this.$input = $(select);
|
||||
}
|
||||
|
||||
//Save the options.
|
||||
this.options = options;
|
||||
|
||||
//Add the list to the input's parent or the appendTo in the options.
|
||||
this.$list = $('<ul class="es-list">');
|
||||
this.$list.appendTo(this.options.appendTo || this.$input.parent());
|
||||
|
||||
this.utility = new EditableSelectUtility(this);
|
||||
|
||||
//If the trigger is not focus or manual, then default it to focus.
|
||||
if(['focus', 'manual'].indexOf(this.options.trigger) < 0) this.options.trigger = 'focus';
|
||||
//Set the default transition.
|
||||
if(['default', 'fade', 'slide'].indexOf(this.options.effects) < 0) this.options.effects = 'default';
|
||||
//Ensure the duration is a number, fast, or slow, defaulting to fast.
|
||||
if(isNaN(this.options.duration) || ['fast', 'slow'].indexOf(this.options.duration) < 0) this.options.duration = 'fast';
|
||||
|
||||
// initalization
|
||||
this.utility.initialize();
|
||||
this.utility.initializeList();
|
||||
this.utility.initializeInput();
|
||||
this.utility.trigger('created');
|
||||
this.$select.data('editable-select', this);
|
||||
};
|
||||
|
||||
EditableSelect.DEFAULTS = { filter: true, effects: 'default', duration: 'fast', trigger: 'focus' };
|
||||
|
||||
EditableSelect.prototype.filter = function() {
|
||||
var hiddens = 0;
|
||||
var search = this.$input.val().toLowerCase().trim();
|
||||
|
||||
this.$list.find('li').addClass('es-visible').show();
|
||||
|
||||
if(this.options.filter) {
|
||||
hiddens = this.$list.find('li').filter(function (i, li) { return $(li).text().toLowerCase().indexOf(search) < 0; }).hide().removeClass('es-visible').length;
|
||||
if (this.$list.find('li').length == hiddens) this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
EditableSelect.prototype.show = function() {
|
||||
this.$list.css({
|
||||
top: this.$input.position().top + this.$input.outerHeight() - 1,
|
||||
left: this.$input.position().left,
|
||||
width: this.$input.outerWidth()
|
||||
});
|
||||
|
||||
if (!this.$list.is(':visible') && this.$list.find('li.es-visible').length > 0) {
|
||||
var fns = { default: 'show', fade: 'fadeIn', slide: 'slideDown' };
|
||||
var fn = fns[this.options.effects];
|
||||
|
||||
this.utility.trigger('show');
|
||||
this.$input.addClass('open');
|
||||
this.$list[fn](this.options.duration, $.proxy(this.utility.trigger, this.utility, 'shown'));
|
||||
}
|
||||
};
|
||||
|
||||
EditableSelect.prototype.hide = function() {
|
||||
var fns = { default: 'hide', fade: 'fadeOut', slide: 'slideUp' };
|
||||
var fn = fns[this.options.effects];
|
||||
|
||||
this.utility.trigger('hide');
|
||||
this.$input.removeClass('open');
|
||||
this.$list[fn](this.options.duration, $.proxy(this.utility.trigger, this.utility, 'hidden'));
|
||||
};
|
||||
|
||||
EditableSelect.prototype.select = function($li) {
|
||||
if (!this.$list.has($li) || !$li.is('li.es-visible')) return;
|
||||
this.$input.val($li.text());
|
||||
this.hide();
|
||||
this.filter();
|
||||
this.utility.trigger('select', $li);
|
||||
};
|
||||
|
||||
EditableSelect.prototype.add = function(text, index, attrs, data) {
|
||||
var $li = $('<li>');
|
||||
$li.html(text);
|
||||
var $option = $('<option>');
|
||||
$option.text(text);
|
||||
var last = this.$list.find('li').length;
|
||||
|
||||
if(isNaN(index)) index = last;
|
||||
else index = Math.min(Math.max(0, index), last);
|
||||
|
||||
if(index == 0) {
|
||||
this.$list.prepend($li);
|
||||
if(this.$select) this.$select.prepend($option);
|
||||
}
|
||||
else {
|
||||
this.$list.find('li').eq(index - 1).after($li);
|
||||
if(this.$select) this.$select.find('option').eq(index - 1).after($option);
|
||||
}
|
||||
|
||||
this.utility.setAttributes($li, attrs, data);
|
||||
this.utility.setAttributes($option, attrs, data);
|
||||
this.filter();
|
||||
};
|
||||
|
||||
EditableSelect.prototype.remove = function(index) {
|
||||
var last = this.$list.find('li').length;
|
||||
|
||||
if (isNaN(index)) index = last;
|
||||
else index = Math.min(Math.max(0, index), last - 1);
|
||||
this.$list.find('li').eq(index).remove();
|
||||
if(this.$select) this.$select.find('option').eq(index).remove();
|
||||
this.filter();
|
||||
};
|
||||
|
||||
EditableSelect.prototype.destroy = function () {
|
||||
this.$list.off('mousemove mousedown mouseup');
|
||||
this.$input.off('focus blur input keydown');
|
||||
this.$input.replaceWith(this.$select);
|
||||
this.$list.remove();
|
||||
if(this.$select) this.$select.removeData('editable-select');
|
||||
};
|
||||
|
||||
// Utility
|
||||
EditableSelectUtility = function(es) {
|
||||
this.es = es;
|
||||
};
|
||||
EditableSelectUtility.prototype.initialize = function() {
|
||||
var that = this;
|
||||
|
||||
if(this.es.$select) that.setAttributes(that.es.$input, that.es.$select[0].attributes, that.es.$select.data());
|
||||
|
||||
//that.es.$input.addClass('es-input');
|
||||
that.es.$input.data('editable-select', that.es);
|
||||
|
||||
if(this.es.$select) that.es.$select.find('option').each(function (i, option) {
|
||||
var $option = $(option).remove();
|
||||
that.es.add($option.text(), i, option.attributes, $option.data());
|
||||
if ($option.attr('selected')) that.es.$input.val($option.text());
|
||||
});
|
||||
|
||||
that.es.filter();
|
||||
};
|
||||
EditableSelectUtility.prototype.initializeList = function() {
|
||||
var that = this;
|
||||
that.es.$list
|
||||
.on('mousemove', 'li', function () {
|
||||
that.es.$list.find('.selected').removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
})
|
||||
.on('mousedown', 'li', function () {
|
||||
that.es.select($(this));
|
||||
})
|
||||
.on('mouseup', function () {
|
||||
that.es.$list.find('li.selected').removeClass('selected');
|
||||
});
|
||||
};
|
||||
EditableSelectUtility.prototype.initializeInput = function() {
|
||||
var that = this;
|
||||
switch (this.es.options.trigger) {
|
||||
default:
|
||||
case 'focus':
|
||||
that.es.$input
|
||||
.on('focus', $.proxy(that.es.show, that.es))
|
||||
.on('blur', $.proxy(that.es.hide, that.es));
|
||||
break;
|
||||
case 'manual':
|
||||
break;
|
||||
}
|
||||
that.es.$input.on('input keydown', function (e) {
|
||||
switch (e.keyCode) {
|
||||
case 38: // Up
|
||||
var visibles = that.es.$list.find('li.es-visible');
|
||||
var selected = visibles.index(visibles.filter('li.selected')) || 0;
|
||||
that.highlight(selected - 1);
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 40: // Down
|
||||
var visibles = that.es.$list.find('li.es-visible');
|
||||
var selected = visibles.index(visibles.filter('li.selected')) || 0;
|
||||
that.highlight(selected + 1);
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 13: // Enter
|
||||
if (that.es.$list.is(':visible')) {
|
||||
that.es.select(that.es.$list.find('li.selected'));
|
||||
e.preventDefault();
|
||||
}
|
||||
case 9: // Tab
|
||||
case 27: // Esc
|
||||
that.es.hide();
|
||||
break;
|
||||
default:
|
||||
that.es.filter();
|
||||
that.highlight(0);
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
EditableSelectUtility.prototype.highlight = function(index) {
|
||||
var that = this;
|
||||
that.es.show();
|
||||
|
||||
setTimeout(function() {
|
||||
var visibles = that.es.$list.find('li.es-visible');
|
||||
var oldSelected = that.es.$list.find('li.selected').removeClass('selected');
|
||||
var oldSelectedIndex = visibles.index(oldSelected);
|
||||
|
||||
if (visibles.length > 0) {
|
||||
var selectedIndex = (visibles.length + index) % visibles.length;
|
||||
var selected = visibles.eq(selectedIndex);
|
||||
var top = selected.position().top;
|
||||
|
||||
selected.addClass('selected');
|
||||
if(selectedIndex < oldSelectedIndex && top < 0)
|
||||
that.es.$list.scrollTop(that.es.$list.scrollTop() + top);
|
||||
if(selectedIndex > oldSelectedIndex && top + selected.outerHeight() > that.es.$list.outerHeight())
|
||||
that.es.$list.scrollTop(that.es.$list.scrollTop() + selected.outerHeight() + 2 * (top - that.es.$list.outerHeight()));
|
||||
}
|
||||
});
|
||||
};
|
||||
EditableSelectUtility.prototype.setAttributes = function ($element, attrs, data) {
|
||||
if(attrs && attrs instanceof Object) $.each({}, function (i, attr) { $element.attr(attr.name, attr.value); });
|
||||
if(data && data instanceof Object) $element.data(data);
|
||||
};
|
||||
EditableSelectUtility.prototype.trigger = function (event) {
|
||||
var params = Array.prototype.slice.call(arguments, 1);
|
||||
var args = [event + '.editable-select'];
|
||||
args.push(params);
|
||||
if(this.es.$select) this.es.$select.trigger.apply(this.es.$select, args);
|
||||
this.es.$input.trigger.apply(this.es.$input, args);
|
||||
};
|
||||
|
||||
// Plugin
|
||||
Plugin = function (option) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data('editable-select');
|
||||
var options = $.extend({}, EditableSelect.DEFAULTS, $this.data(), typeof option == 'object' && option);
|
||||
|
||||
if(!data) data = new EditableSelect(this, options);
|
||||
if(typeof option == 'string') data[option].apply(data, args);
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.editableSelect = Plugin;
|
||||
$.fn.editableSelect.Constructor = EditableSelect;
|
||||
|
||||
})(jQuery);
|
||||
1532
public/admin/js/jquery.validate.js
vendored
1532
public/admin/js/jquery.validate.js
vendored
File diff suppressed because it is too large
Load Diff
4
public/admin/js/jquery.validate.min.js
vendored
4
public/admin/js/jquery.validate.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,364 +0,0 @@
|
||||
//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/>");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@ var LinkedTable;
|
||||
//Notify the handler of the new selection, and the selection's model.
|
||||
_this.options.selectionChanged(_this.$selectedRow, _this.$selectedRow ? _this.$selectedRow.data(_this.options.modelPropName) : null);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
//Takes a callback function with three parameters:
|
||||
@@ -143,6 +145,7 @@ var LinkedTable;
|
||||
this.updateCell($cell, attribute, model, supportingData);
|
||||
//Add the cell to the row.
|
||||
$cell.appendTo(row);
|
||||
$cell.disableSelection();
|
||||
}
|
||||
|
||||
if(this.options.postAddRowHandler) {
|
||||
@@ -193,6 +196,9 @@ var LinkedTable;
|
||||
selectionCSS: 'selected',
|
||||
selection: 'row', //Currently only row is supported.
|
||||
selectionChanged: undefined, //An optional handler called when the selection changes, and passed the selected element (jquery wrapper for the table row 'tr' HTML element currently selected), and the model associated with the row.
|
||||
selectionOpened: undefined, //An optional handler called when the user double clicks a row.
|
||||
keyDownHandler: undefined, //An optional handler called when a key is pressed on a row.
|
||||
keyUpHandler: undefined, //An optional handler called when a key is pressed on a row.
|
||||
supportingData: [], //An array of objects, one for each collection of supporting data. Each object must have a 'name', 'url', and optional 'parameters'. The url and parameters are used the same as for the primary query. The name is used to store the results for use in rendering the data. Optional 'postProcess' attribute can be a function that takes the data and returns a modified set of data.
|
||||
cellDataHandlers: {}, //An object containing a function for each attribute, where the attribute is the table header object key, and the function is called to convert the primary data object into a cell value. The function will be passed the jquery table data wrapper object for the cell, the primary data object for the row, and the object containing the supporting data returned from running the supporting data queries.
|
||||
postAddRowHandler: null, //Optional function that is passed the jquery table row and the data object sent by the server for that row. Allows post processing of the row prior to display.
|
||||
|
||||
@@ -6,30 +6,105 @@ var scrollerTransitionTime = 1000;
|
||||
|
||||
window.status="";
|
||||
|
||||
var layoutManager;
|
||||
|
||||
//Handle the document ready event which is where any initialization code goes.
|
||||
$(document).ready(function($) {
|
||||
var layoutManager = new LayoutManager("main-view");
|
||||
// layoutManager = new LayoutManager("main-view");
|
||||
//
|
||||
// layoutManager.defaultUrl = '#!/Home';
|
||||
// layoutManager.pageClassFades = [
|
||||
// {cls: 'full', fadeIn: "#menu", fadeOut: null},
|
||||
// {cls: 'dialog', fadeIn: null, fadeOut: "#menu"}
|
||||
// ];
|
||||
// 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);"
|
||||
// // },
|
||||
// };
|
||||
|
||||
layoutManager.defaultUrl = '#!/Home';
|
||||
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);"
|
||||
},
|
||||
};
|
||||
var lastHash;
|
||||
var delimiter = '-';
|
||||
var $viewContainer = $('#contentContainer');
|
||||
|
||||
//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;
|
||||
$.history.init(function(hash) {
|
||||
//Remove any prefix characters.
|
||||
if(hash) {
|
||||
if(hash.startsWith('!/')) hash = hash.substring(2);
|
||||
else if(hash.startsWith('/')) hash = hash.substring(1);
|
||||
}
|
||||
|
||||
//Default the hash if not provided.
|
||||
if(!hash || hash.length == 0) {
|
||||
hash = 'menu';
|
||||
}
|
||||
|
||||
//Shouldn't happen - but in case it does then ignore the case.
|
||||
if(lastHash != hash) {
|
||||
var lastHashPageName = getPageName(lastHash);
|
||||
var hashPageName = getPageName(hash);
|
||||
var hashPageData = getPageData(hash);
|
||||
|
||||
lastHash = hash;
|
||||
|
||||
//If the page has changed then load the new page and transition, otherwise transition to the new view within the page.
|
||||
if(!lastHashPageName || lastHashPageName != hashPageName) {
|
||||
$.ajax({url: hashPageName + ".html", dataType: 'html', async: true}).done(function(data) {
|
||||
$viewContainer.fadeOut(250, function() {
|
||||
$viewContainer.empty();
|
||||
$viewContainer.html(data);
|
||||
//TODO: First ensure the view is setup correctly? Use the hash to run the correct handler attached to the view's first element?
|
||||
setupPage($viewContainer.children().first(), hashPageData, false);
|
||||
|
||||
$viewContainer.fadeIn(500, function() {
|
||||
//TODO: Done?
|
||||
});
|
||||
});
|
||||
}).fail(function(error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
else {
|
||||
setupPage($viewContainer.children().first(), hashPageData, true);
|
||||
}
|
||||
}
|
||||
|
||||
layoutManager.show(url);
|
||||
});
|
||||
|
||||
function setupPage($view, data, internal) {
|
||||
var handler = $view.data('display-handler');
|
||||
|
||||
if(handler) {
|
||||
handler(data, internal);
|
||||
}
|
||||
}
|
||||
function getPageName(hash) {
|
||||
if(hash) {
|
||||
var index = hash.indexOf(delimiter);
|
||||
|
||||
if(index > 0) { //Should never be zero.
|
||||
return hash.substring(0, index);
|
||||
}
|
||||
else {
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
function getPageData(hash) {
|
||||
if(hash) {
|
||||
var index = hash.indexOf(delimiter);
|
||||
|
||||
if(index > 0) { //Should never be zero.
|
||||
return hash.substring(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
var websocket = new WebSocket('ws://petitteton.com/');
|
||||
|
||||
@@ -47,24 +122,24 @@ $(document).ready(function($) {
|
||||
|
||||
|
||||
//Override the jQuery.html(html) function to strip any <runonce>..</runonce> scripts and execute them.
|
||||
(function(){
|
||||
var htmlOriginal = jQuery.fn.html;
|
||||
jQuery.fn.html = function(html) {
|
||||
if(html != undefined) {
|
||||
var data = brainstormFramework.extractViewData(html);
|
||||
|
||||
htmlOriginal.apply(this, [data.view]);
|
||||
|
||||
if(data.script && data.script.length > 0) {
|
||||
try {
|
||||
eval(data.script);
|
||||
} catch(err) {
|
||||
alert(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
htmlOriginal.apply(this, html);
|
||||
}
|
||||
}
|
||||
})();
|
||||
// (function(){
|
||||
// var htmlOriginal = jQuery.fn.html;
|
||||
// jQuery.fn.html = function(html) {
|
||||
// if(html != undefined) {
|
||||
// var data = brainstormFramework.extractViewData(html);
|
||||
//
|
||||
// htmlOriginal.apply(this, [data.view]);
|
||||
//
|
||||
// if(data.script && data.script.length > 0) {
|
||||
// try {
|
||||
// eval(data.script);
|
||||
// } catch(err) {
|
||||
// alert(err);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// htmlOriginal.apply(this, html);
|
||||
// }
|
||||
// }
|
||||
// })();
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user