Merge pull request #3173 from tigercat2000/nano_javashript

NanoUI Shit (Part 3) - JavaShit
This commit is contained in:
Fox McCloud
2016-01-10 18:04:22 -05:00
19 changed files with 607 additions and 646 deletions
+4 -2
View File
@@ -48,7 +48,7 @@
preload_rsc = 1 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
var/global/obj/screen/click_catcher/void
var/karma = 0
var/karma_spent = 0
var/karma_tab = 0
@@ -76,4 +76,6 @@
"off" = "borgmacro")
)
var/reset_stretch = 0 //Used by things that fiddle with client's stretch-to-fit.
var/reset_stretch = 0 //Used by things that fiddle with client's stretch-to-fit.
var/topic_debugging = 0 //if set to true, allows client to see nanoUI errors -- yes i realize this is messy but it'll make live testing infinitely easier
+3 -2
View File
@@ -29,11 +29,12 @@
#if defined(TOPIC_DEBUGGING)
world << "[src]'s Topic: [href] destined for [hsrc]."
#endif
if(href_list["nano_err"]) //nano throwing errors
world << "## NanoUI, Subject [src]: " + html_decode(href_list["nano_err"]) //NANO DEBUG HOOK
if(topic_debugging)
src << "## NanoUI: " + html_decode(href_list["nano_err"]) //NANO DEBUG HOOK
#endif
if(href_list["asset_cache_confirm_arrival"])
//src << "ASSET JOB [href_list["asset_cache_confirm_arrival"]] ARRIVED."
+6
View File
@@ -51,11 +51,17 @@ gulp.task "fonts", ["clean"], ->
gulp.task "scripts", ["clean"], ->
lib = gulp.src glob input.scripts.lib
.pipe g.order(["jquery.js",
"jquery*.js",
"*.js"])
.pipe g.concat(output.scripts.lib)
.pipe g.if(s.min, g.uglify().on('error', util.log))
.pipe gulp.dest output.dir
main = gulp.src glob input.scripts.main
.pipe g.order(["nano_utility.js",
"nano_state_manager.js"
"*.js"])
.pipe g.concat(output.scripts.main)
.pipe g.if(s.min, g.uglify().on('error', util.log))
.pipe gulp.dest output.dir
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -14,12 +14,13 @@
"gulp-if": "^2.0.0",
"gulp-less": "^3.0.5",
"gulp-load-plugins": "^1.1.0",
"gulp-order": "^1.1.1",
"gulp-postcss": "^6.0.1",
"gulp-replace": "^0.5.4",
"gulp-uglify": "^1.5.1",
"gulp-util": "^3.0.7",
"merge-stream": "^1.0.0",
"main-bower-files": "^2.9.0",
"merge-stream": "^1.0.0",
"pleeease-filters": "^2.0.0",
"postcss-color-rgba-fallback": "git+https://github.com/postcss/postcss-color-rgba-fallback",
"postcss-filter-gradient": "^0.2.1",
+9
View File
@@ -0,0 +1,9 @@
@echo off
for /f "tokens=3* delims= " %%a in (
'reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Personal"'
) do (
set documents=%%a
)
copy assets\* "%documents%\BYOND\cache" /y
-224
View File
@@ -1,224 +0,0 @@
// NanoStateManager handles data from the server and uses it to render templates
NanoStateManager = function ()
{
// _isInitialised is set to true when all of this ui's templates have been processed/rendered
var _isInitialised = false;
// the data for this ui
var _data = null;
// this is an array of callbacks which are called when new data arrives, before it is processed
var _beforeUpdateCallbacks = {};
// this is an array of callbacks which are called when new data arrives, before it is processed
var _afterUpdateCallbacks = {};
// this is an array of state objects, these can be used to provide custom javascript logic
var _states = {};
var _currentState = null;
// the init function is called when the ui has loaded
// this function sets up the templates and base functionality
var init = function ()
{
// We store initialData and templateData in the body tag, it's as good a place as any
_data = $('body').data('initialData');
if (_data == null || !_data.hasOwnProperty('config') || !_data.hasOwnProperty('data'))
{
alert('Error: Initial data did not load correctly.');
}
var stateKey = 'default';
if (_data['config'].hasOwnProperty('stateKey') && _data['config']['stateKey'])
{
stateKey = _data['config']['stateKey'].toLowerCase();
}
NanoStateManager.setCurrentState(stateKey);
$(document).on('templatesLoaded', function () {
doUpdate(_data);
_isInitialised = true;
});
};
// Receive update data from the server
var receiveUpdateData = function (jsonString)
{
var updateData;
// alert("recieveUpdateData called." + "<br>Type: " + typeof jsonString); //debug hook
try
{
// parse the JSON string from the server into a JSON object
updateData = jQuery.parseJSON(jsonString);
}
catch (error)
{
alert("recieveUpdateData failed. " + "<br>Error name: " + error.name + "<br>Error Message: " + error.message);
return;
}
// alert("recieveUpdateData passed trycatch block."); //debug hook
if (!updateData.hasOwnProperty('data'))
{
if (_data && _data.hasOwnProperty('data'))
{
updateData['data'] = _data['data'];
}
else
{
updateData['data'] = {};
}
}
if (_isInitialised) // all templates have been registered, so render them
{
doUpdate(updateData);
}
else
{
_data = updateData; // all templates have not been registered. We set _data directly here which will be applied after the template is loaded with the initial data
}
};
// This function does the update by calling the methods on the current state
var doUpdate = function (data)
{
if (_currentState == null)
{
return;
}
data = _currentState.onBeforeUpdate(data);
if (data === false)
{
alert('data is false, return');
return; // A beforeUpdateCallback returned a false value, this prevents the render from occuring
}
_data = data;
_currentState.onUpdate(_data);
_currentState.onAfterUpdate(_data);
};
// Execute all callbacks in the callbacks array/object provided, updateData is passed to them for processing and potential modification
var executeCallbacks = function (callbacks, data)
{
for (var key in callbacks)
{
if (callbacks.hasOwnProperty(key) && jQuery.isFunction(callbacks[key]))
{
data = callbacks[key].call(this, data);
}
}
return data;
};
return {
init: function ()
{
init();
},
receiveUpdateData: function (jsonString)
{
receiveUpdateData(jsonString);
},
addBeforeUpdateCallback: function (key, callbackFunction)
{
_beforeUpdateCallbacks[key] = callbackFunction;
},
addBeforeUpdateCallbacks: function (callbacks) {
for (var callbackKey in callbacks) {
if (!callbacks.hasOwnProperty(callbackKey))
{
continue;
}
NanoStateManager.addBeforeUpdateCallback(callbackKey, callbacks[callbackKey]);
}
},
removeBeforeUpdateCallback: function (key)
{
if (_beforeUpdateCallbacks.hasOwnProperty(key))
{
delete _beforeUpdateCallbacks[key];
}
},
executeBeforeUpdateCallbacks: function (data) {
return executeCallbacks(_beforeUpdateCallbacks, data);
},
addAfterUpdateCallback: function (key, callbackFunction)
{
_afterUpdateCallbacks[key] = callbackFunction;
},
addAfterUpdateCallbacks: function (callbacks) {
for (var callbackKey in callbacks) {
if (!callbacks.hasOwnProperty(callbackKey))
{
continue;
}
NanoStateManager.addAfterUpdateCallback(callbackKey, callbacks[callbackKey]);
}
},
removeAfterUpdateCallback: function (key)
{
if (_afterUpdateCallbacks.hasOwnProperty(key))
{
delete _afterUpdateCallbacks[key];
}
},
executeAfterUpdateCallbacks: function (data) {
return executeCallbacks(_afterUpdateCallbacks, data);
},
addState: function (state)
{
if (!(state instanceof NanoStateClass))
{
alert('ERROR: Attempted to add a state which is not instanceof NanoStateClass');
return;
}
if (!state.key)
{
alert('ERROR: Attempted to add a state with an invalid stateKey');
return;
}
_states[state.key] = state;
},
setCurrentState: function (stateKey)
{
if (typeof stateKey == 'undefined' || !stateKey) {
alert('ERROR: No state key was passed!');
return false;
}
if (!_states.hasOwnProperty(stateKey))
{
alert('ERROR: Attempted to set a current state which does not exist: ' + stateKey);
return false;
}
var previousState = _currentState;
_currentState = _states[stateKey];
if (previousState != null) {
previousState.onRemove(_currentState);
}
_currentState.onAdd(previousState);
return true;
},
getCurrentState: function ()
{
return _currentState;
}
};
} ();
-281
View File
@@ -1,281 +0,0 @@
// NanoBaseHelpers is where the base template helpers (common to all templates) are stored
NanoBaseHelpers = function ()
{
var _baseHelpers = {
// change ui styling to "syndicate mode"
syndicateMode: function() {
$('body').css("background-color","#8f1414");
$('body').css("background-image","url('uiBackground-Syndicate.png')");
$('body').css("background-position","50% 0");
$('body').css("background-repeat","repeat-x");
$('#uiTitleFluff').css("background-image","url('uiTitleFluff-Syndicate.png')");
$('#uiTitleFluff').css("background-position","50% 50%");
$('#uiTitleFluff').css("background-repeat", "no-repeat");
return '';
},
combine: function( arr1, arr2 ) {
return arr1 && arr2 ? arr1.concat(arr2) : arr1 || arr2;
},
dump: function( arr1 ) {
return JSON.stringify(arr1);
},
// Generate a Byond link
link: function( text, icon, parameters, status, elementClass, elementId) {
var iconHtml = '';
var iconClass = 'noIcon';
if (typeof icon != 'undefined' && icon)
{
iconHtml = '<div class="uiLinkPendingIcon"></div><div class="uiIcon16 icon-' + icon + '"></div>';
iconClass = 'hasIcon';
}
if (typeof elementClass == 'undefined' || !elementClass)
{
elementClass = 'link';
}
var elementIdHtml = '';
if (typeof elementId != 'undefined' && elementId)
{
elementIdHtml = 'id="' + elementId + '"';
}
if (typeof status != 'undefined' && status)
{
return '<div unselectable="on" class="link ' + iconClass + ' ' + elementClass + ' ' + status + '" ' + elementIdHtml + '>' + iconHtml + text + '</div>';
}
return '<div unselectable="on" class="linkActive ' + iconClass + ' ' + elementClass + '" data-href="' + NanoUtility.generateHref(parameters) + '" ' + elementIdHtml + '>' + iconHtml + text + '</div>';
},
// Since jsrender breaks the ^ operator
xor: function(number,bit) {
return number ^ bit;
},
precisionRound: function (value, places) {
if(places==0)
return Math.round(number);
var multiplier = Math.pow(10, places);
return (Math.round(value * multiplier) / multiplier);
},
// Round a number to the nearest integer
round: function(number) {
return Math.round(number);
},
fixed: function(number) {
return Math.round(number * 10) / 10;
},
// Round a number down to integer
floor: function(number) {
return Math.floor(number);
},
// Round a number up to integer
ceil: function(number) {
return Math.ceil(number);
},
// Format a string (~string("Hello {0}, how are {1}?", 'Martin', 'you') becomes "Hello Martin, how are you?")
string: function() {
if (arguments.length == 0)
{
return '';
}
else if (arguments.length == 1)
{
return arguments[0];
}
else if (arguments.length > 1)
{
stringArgs = [];
for (var i = 1; i < arguments.length; i++)
{
stringArgs.push(arguments[i]);
}
return arguments[0].format(stringArgs);
}
return '';
},
formatNumber: function(x) {
// From http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
},
// Capitalize the first letter of a string. From http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript
capitalizeFirstLetter: function(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
},
// Display a bar. Used to show health, capacity, etc.
displayBar: function(value, rangeMin, rangeMax, styleClass, showText) {
if (rangeMin < rangeMax)
{
if (value < rangeMin)
{
value = rangeMin;
}
else if (value > rangeMax)
{
value = rangeMax;
}
}
else
{
if (value > rangeMin)
{
value = rangeMin;
}
else if (value < rangeMax)
{
value = rangeMax;
}
}
if (typeof styleClass == 'undefined' || !styleClass)
{
styleClass = '';
}
if (typeof showText == 'undefined' || !showText)
{
showText = '';
}
var percentage = Math.round((value - rangeMin) / (rangeMax - rangeMin) * 100);
return '<div class="displayBar ' + styleClass + '"><div class="displayBarFill ' + styleClass + '" style="width: ' + percentage + '%;"></div><div class="displayBarText ' + styleClass + '">' + showText + '</div></div>';
},
// Convert danger level to class (for the air alarm)
dangerToClass: function(level) {
if(level==0) return 'good';
if(level==1) return 'average';
return 'bad';
},
dangerToSpan: function(level) {
if(level==0) return '"<span class="good">Good</span>"';
if(level==1) return '"<span class="average">Minor Alert</span>"';
return '"<span class="bad">Major Alert</span>"';
},
generateHref: function (parameters) {
var body = $('body'); // We store data in the body tag, it's as good a place as any
_urlParameters = body.data('urlParameters');
var queryString = '?';
for (var key in _urlParameters)
{
if (_urlParameters.hasOwnProperty(key))
{
if (queryString !== '?')
{
queryString += ';';
}
queryString += key + '=' + _urlParameters[key];
}
}
for (var key in parameters)
{
if (parameters.hasOwnProperty(key))
{
if (queryString !== '?')
{
queryString += ';';
}
queryString += key + '=' + parameters[key];
}
}
return queryString;
},
// Display DNA Blocks (for the DNA Modifier UI)
displayDNABlocks: function(dnaString, selectedBlock, selectedSubblock, blockSize, paramKey) {
if (!dnaString)
{
return '<div class="notice">Please place a valid subject into the DNA modifier.</div>';
}
var characters = dnaString.split('');
var html = '<div class="dnaBlock"><div class="link dnaBlockNumber">1</div>';
var block = 1;
var subblock = 1;
for (index in characters)
{
if (!characters.hasOwnProperty(index) || typeof characters[index] === 'object')
{
continue;
}
var parameters;
if (paramKey.toUpperCase() == 'UI')
{
parameters = { 'selectUIBlock' : block, 'selectUISubblock' : subblock };
}
else
{
parameters = { 'selectSEBlock' : block, 'selectSESubblock' : subblock };
}
var status = 'linkActive';
if (block == selectedBlock && subblock == selectedSubblock)
{
status = 'selected';
}
html += '<div class="link ' + status + ' dnaSubBlock" data-href="' + NanoUtility.generateHref(parameters) + '" id="dnaBlock' + index + '">' + characters[index] + '</div>'
index++;
if (index % blockSize == 0 && index < characters.length)
{
block++;
subblock = 1;
html += '</div><div class="dnaBlock"><div class="link dnaBlockNumber">' + block + '</div>';
}
else
{
subblock++;
}
}
html += '</div>';
return html;
},
cMirror: function(domID) {
if(!domID)
{
return "ERR - NO domID provided";
}
var html = '<script>var editor = CodeMirror.fromTextArea(document.getElementById("';
html += domID
html += '"), {lineNumbers: true, indentUnit: 4, indentWithTabs: true, theme: "lesser-dark"});';
html += '</script>'
return html;
}
};
return {
addHelpers: function ()
{
NanoTemplate.addHelpers(_baseHelpers);
},
removeHelpers: function ()
{
for (var helperKey in _baseHelpers)
{
if (_baseHelpers.hasOwnProperty(helperKey))
{
NanoTemplate.removeHelper(helperKey);
}
}
}
};
} ();
@@ -3,9 +3,7 @@ NanoBaseCallbacks = function ()
{
// _canClick is used to disable clicks for a short period after each click (to avoid mis-clicks)
var _canClick = true;
var _baseBeforeUpdateCallbacks = {}
var _baseBeforeUpdateCallbacks = {};
var _baseAfterUpdateCallbacks = {
// this callback is triggered after new data is processed
// it updates the status/visibility icon and adds click event handling to buttons/links
@@ -23,7 +21,7 @@ NanoBaseCallbacks = function ()
}
else
{
uiStatusClass = 'bad'
uiStatusClass = 'bad';
$('.linkActive').addClass('inactive');
}
$('.statusicon').each( function(i, obj) {
@@ -103,27 +101,16 @@ NanoBaseCallbacks = function ()
NanoStateManager.addAfterUpdateCallbacks(_baseAfterUpdateCallbacks);
},
removeCallbacks: function () {
for (var callbackKey in _baseBeforeUpdateCallbacks)
{
if (_baseBeforeUpdateCallbacks.hasOwnProperty(callbackKey))
{
for (var callbackKey in _baseBeforeUpdateCallbacks) {
if (_baseBeforeUpdateCallbacks.hasOwnProperty(callbackKey)) {
NanoStateManager.removeBeforeUpdateCallback(callbackKey);
}
}
for (var callbackKey in _baseAfterUpdateCallbacks)
{
if (_baseAfterUpdateCallbacks.hasOwnProperty(callbackKey))
{
for (var callbackKey in _baseAfterUpdateCallbacks) {
if (_baseAfterUpdateCallbacks.hasOwnProperty(callbackKey)) {
NanoStateManager.removeAfterUpdateCallback(callbackKey);
}
}
}
};
} ();
}();
+268
View File
@@ -0,0 +1,268 @@
// NanoBaseHelpers is where the base template helpers (common to all templates) are stored
NanoBaseHelpers = function ()
{
var _baseHelpers = {
// change ui styling to "syndicate mode"
syndicateMode: function() {
$('body').css("background-color","#8f1414");
$('body').css("background-image","url('uiBackground-Syndicate.png')");
$('body').css("background-position","50% 0");
$('body').css("background-repeat","repeat-x");
$('#uiTitleFluff').css("background-image","url('uiTitleFluff-Syndicate.png')");
$('#uiTitleFluff').css("background-position","50% 50%");
$('#uiTitleFluff').css("background-repeat", "no-repeat");
return '';
},
combine: function( arr1, arr2 ) {
return arr1 && arr2 ? arr1.concat(arr2) : arr1 || arr2;
},
dump: function( arr1 ) {
return JSON.stringify(arr1);
},
// Generate a Byond link
link: function( text, icon, parameters, status, elementClass, elementId ) {
var iconHtml = '';
var iconClass = 'noIcon';
if (typeof icon != 'undefined' && icon)
{
iconHtml = '<div class="uiLinkPendingIcon"></div><div class="uiIcon16 icon-' + icon + '"></div>';
iconClass = 'hasIcon';
}
if (typeof elementClass == 'undefined' || !elementClass)
{
elementClass = 'link';
}
var elementIdHtml = '';
if (typeof elementId != 'undefined' && elementId)
{
elementIdHtml = 'id="' + elementId + '"';
}
if (typeof status != 'undefined' && status)
{
return '<div unselectable="on" class="link ' + iconClass + ' ' + elementClass + ' ' + status + '" ' + elementIdHtml + '>' + iconHtml + text + '</div>';
}
return '<div unselectable="on" class="linkActive ' + iconClass + ' ' + elementClass + '" data-href="' + NanoUtility.generateHref(parameters) + '" ' + elementIdHtml + '>' + iconHtml + text + '</div>';
},
xor: function (number,bit) {
return number ^ bit;
},
precisionRound: function (value, places) {
if(places == 0){
return Math.round(number);
}
var multiplier = Math.pow(10, places);
return (Math.round(value * multiplier) / multiplier);
},
// Round a number to the nearest integer
round: function(number) {
return Math.round(number);
},
fixed: function(number) {
return Math.round(number * 10) / 10;
},
// Round a number down to integer
floor: function(number) {
return Math.floor(number);
},
// Round a number up to integer
ceil: function(number) {
return Math.ceil(number);
},
// Format a string (~string("Hello {0}, how are {1}?", 'Martin', 'you') becomes "Hello Martin, how are you?")
string: function() {
if (arguments.length == 0)
{
return '';
}
else if (arguments.length == 1)
{
return arguments[0];
}
else if (arguments.length > 1)
{
stringArgs = [];
for (var i = 1; i < arguments.length; i++)
{
stringArgs.push(arguments[i]);
}
return arguments[0].format(stringArgs);
}
return '';
},
formatNumber: function(x) {
// From http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
},
// Capitalize the first letter of a string. From http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript
capitalizeFirstLetter: function( string ) {
return string.charAt(0).toUpperCase() + string.slice(1);
},
// Display a bar. Used to show health, capacity, etc.
displayBar: function( value, rangeMin, rangeMax, styleClass, showText ) {
if (rangeMin < rangeMax)
{
if (value < rangeMin)
{
value = rangeMin;
}
else if (value > rangeMax)
{
value = rangeMax;
}
}
else
{
if (value > rangeMin)
{
value = rangeMin;
}
else if (value < rangeMax)
{
value = rangeMax;
}
}
if (typeof styleClass == 'undefined' || !styleClass)
{
styleClass = '';
}
if (typeof showText == 'undefined' || !showText)
{
showText = '';
}
var percentage = Math.round((value - rangeMin) / (rangeMax - rangeMin) * 100);
return '<div class="displayBar ' + styleClass + '"><div class="displayBarFill ' + styleClass + '" style="width: ' + percentage + '%;"></div><div class="displayBarText ' + styleClass + '">' + showText + '</div></div>';
},
// Convert danger level to class (for the air alarm)
dangerToClass: function(level) {
if(level == 0) return 'good';
if(level == 1) return 'average';
return 'bad';
},
dangerToSpan: function(level) {
if(level == 0) return '"<span class="good">Good</span>"';
if(level == 1) return '"<span class="average">Minor Alert</span>"';
return '"<span class="bad">Major Alert</span>"';
},
generateHref: function (parameters) {
var body = $('body'); // For some fucking reason, data is stored in the body tag.
_urlParameters = body.data('urlParameters');
var queryString = '?';
for (var key in _urlParameters)
{
if (_urlParameters.hasOwnProperty(key))
{
if (queryString !== '?')
{
queryString += ';';
}
queryString += key + '=' + _urlParameters[key];
}
}
for (var key in parameters)
{
if (parameters.hasOwnProperty(key))
{
if (queryString !== '?')
{
queryString += ';';
}
queryString += key + '=' + parameters[key];
}
}
return queryString;
},
// Display DNA Blocks (for the DNA Modifier UI)
displayDNABlocks: function(dnaString, selectedBlock, selectedSubblock, blockSize, paramKey) {
if (!dnaString)
{
return '<div class="notice">Please place a valid subject into the DNA modifier.</div>';
}
var characters = dnaString.split('');
var html = '<div class="dnaBlock"><div class="link dnaBlockNumber">1</div>';
var block = 1;
var subblock = 1;
for (var index in characters) {
if (!characters.hasOwnProperty(index) || typeof characters[index] === 'object')
{
continue;
}
var parameters;
if (paramKey.toUpperCase() == 'UI'){
parameters = { 'selectUIBlock' : block, 'selectUISubblock' : subblock };
} else {
parameters = { 'selectSEBlock' : block, 'selectSESubblock' : subblock };
}
var status = 'linkActive';
if (block == selectedBlock && subblock == selectedSubblock) {
status = 'selected';
}
html += '<div class="link ' + status + ' dnaSubBlock" data-href="' + NanoUtility.generateHref(parameters) + '" id="dnaBlock' + index + '">' + characters[index] + '</div>';
index++;
if (index % blockSize == 0 && index < characters.length) {
block++;
subblock = 1;
html += '</div><div class="dnaBlock"><div class="link dnaBlockNumber">' + block + '</div>';
} else {
subblock++;
}
}
html += '</div>';
return html;
},
cMirror: function(textbox) {
var editor = CodeMirror.fromTextArea(document.getElementById(textbox), {
lineNumbers: true,
indentUnit: 4,
indentWithTabs: true,
theme: "lesser-dark"
});
}
};
return {
addHelpers: function ()
{
NanoTemplate.addHelpers(_baseHelpers);
},
removeHelpers: function ()
{
for (var helperKey in _baseHelpers)
{
if (_baseHelpers.hasOwnProperty(helperKey))
{
NanoTemplate.removeHelper(helperKey);
}
}
}
};
}();
@@ -1,16 +1,6 @@
// This is the base state class, it is not to be used directly
function NanoStateClass() {
/*if (typeof this.key != 'string' || !this.key.length)
{
alert('ERROR: Tried to create a state with an invalid state key: ' + this.key);
return;
}
this.key = this.key.toLowerCase();
NanoStateManager.addState(this);*/
}
function NanoStateClass() {}
NanoStateClass.prototype.key = null;
NanoStateClass.prototype.layoutRendered = false;
@@ -99,7 +89,7 @@ NanoStateClass.prototype.onUpdate = function (data) {
}
catch(error)
{
alert('ERROR: An error occurred while rendering the UI: ' + error.message);
reportError('ERROR: An error occurred while rendering the UI: ' + error.message);
return;
}
};
@@ -115,5 +105,3 @@ NanoStateClass.prototype.alertText = function (text) {
alert(text);
};
@@ -11,4 +11,4 @@ function NanoStateDefaultClass() {
this.key = this.key.toLowerCase();
NanoStateManager.addState(this);
}
}
+222
View File
@@ -0,0 +1,222 @@
// NanoStateManager handles data from the server and uses it to render templates
NanoStateManager = function ()
{
// _isInitialised is set to true when all of this ui's templates have been processed/rendered
var _isInitialised = false;
// the data for this ui
var _data = null;
// this is an array of callbacks which are called when new data arrives, before it is processed
var _beforeUpdateCallbacks = {};
// this is an array of callbacks which are called when new data arrives, before it is processed
var _afterUpdateCallbacks = {};
// this is an array of state objects, these can be used to provide custom javascript logic
var _states = {};
var _currentState = null;
// the init function is called when the ui has loaded
// this function sets up the templates and base functionality
var init = function ()
{
// We store initialData and templateData in the body tag, it's as good a place as any
_data = $('body').data('initialData');
if (_data == null || !_data.hasOwnProperty('config') || !_data.hasOwnProperty('data'))
{
reportError('Error: Initial data did not load correctly.');
}
var stateKey = 'default';
if (_data['config'].hasOwnProperty('stateKey') && _data['config']['stateKey'])
{
stateKey = _data['config']['stateKey'].toLowerCase();
}
NanoStateManager.setCurrentState(stateKey);
$(document).on('templatesLoaded', function () {
doUpdate(_data);
_isInitialised = true;
});
};
// Receive update data from the server
var receiveUpdateData = function (jsonString)
{
var updateData;
// reportError("recieveUpdateData called." + "<br>Type: " + typeof jsonString); //debug hook
try
{
// parse the JSON string from the server into a JSON object
updateData = jQuery.parseJSON(jsonString);
}
catch (error)
{
reportError("recieveUpdateData failed. " + "<br>Error name: " + error.name + "<br>Error Message: " + error.message);
return;
}
// reportError("recieveUpdateData passed trycatch block."); //debug hook
if (!updateData.hasOwnProperty('data'))
{
if (_data && _data.hasOwnProperty('data'))
{
updateData['data'] = _data['data'];
}
else
{
updateData['data'] = {};
}
}
if (_isInitialised) // all templates have been registered, so render them
{
doUpdate(updateData);
}
else
{
_data = updateData; // all templates have not been registered. We set _data directly here which will be applied after the template is loaded with the initial data
}
};
// This function does the update by calling the methods on the current state
var doUpdate = function (data)
{
if (_currentState == null)
{
return;
}
data = _currentState.onBeforeUpdate(data);
if (data === false)
{
reportError('data is false, return');
return; // A beforeUpdateCallback returned a false value, this prevents the render from occuring
}
_data = data;
_currentState.onUpdate(_data);
_currentState.onAfterUpdate(_data);
};
// Execute all callbacks in the callbacks array/object provided, updateData is passed to them for processing and potential modification
var executeCallbacks = function (callbacks, data)
{
for (var key in callbacks)
{
if (callbacks.hasOwnProperty(key) && jQuery.isFunction(callbacks[key]))
{
data = callbacks[key].call(this, data);
}
}
return data;
};
return {
init: function ()
{
init();
},
receiveUpdateData: function (jsonString)
{
receiveUpdateData(jsonString);
},
addBeforeUpdateCallback: function (key, callbackFunction)
{
_beforeUpdateCallbacks[key] = callbackFunction;
},
addBeforeUpdateCallbacks: function (callbacks) {
for (var callbackKey in callbacks) {
if (!callbacks.hasOwnProperty(callbackKey))
{
continue;
}
NanoStateManager.addBeforeUpdateCallback(callbackKey, callbacks[callbackKey]);
}
},
removeBeforeUpdateCallback: function (key)
{
if (_beforeUpdateCallbacks.hasOwnProperty(key))
{
delete _beforeUpdateCallbacks[key];
}
},
executeBeforeUpdateCallbacks: function (data) {
return executeCallbacks(_beforeUpdateCallbacks, data);
},
addAfterUpdateCallback: function (key, callbackFunction)
{
_afterUpdateCallbacks[key] = callbackFunction;
},
addAfterUpdateCallbacks: function (callbacks) {
for (var callbackKey in callbacks) {
if (!callbacks.hasOwnProperty(callbackKey))
{
continue;
}
NanoStateManager.addAfterUpdateCallback(callbackKey, callbacks[callbackKey]);
}
},
removeAfterUpdateCallback: function (key)
{
if (_afterUpdateCallbacks.hasOwnProperty(key))
{
delete _afterUpdateCallbacks[key];
}
},
executeAfterUpdateCallbacks: function (data) {
return executeCallbacks(_afterUpdateCallbacks, data);
},
addState: function (state)
{
if (!(state instanceof NanoStateClass))
{
reportError('ERROR: Attempted to add a state which is not instanceof NanoStateClass');
return;
}
if (!state.key)
{
reportError('ERROR: Attempted to add a state with an invalid stateKey');
return;
}
_states[state.key] = state;
},
setCurrentState: function (stateKey)
{
if (typeof stateKey == 'undefined' || !stateKey) {
reportError('ERROR: No state key was passed!');
return false;
}
if (!_states.hasOwnProperty(stateKey))
{
reportError('ERROR: Attempted to set a current state which does not exist: ' + stateKey);
return false;
}
var previousState = _currentState;
_currentState = _states[stateKey];
if (previousState != null) {
previousState.onRemove(_currentState);
}
_currentState.onAdd(previousState);
return true;
},
getCurrentState: function ()
{
return _currentState;
}
};
} ();
@@ -5,19 +5,19 @@ var NanoTemplate = function () {
var _templates = {};
var _compiledTemplates = {};
var _helpers = {};
var _helpers = {};
var init = function () {
// We store templateData in the body tag, it's as good a place as any
_templateData = $('body').data('templateData');
_templateData = $('body').data('templateData');
if (_templateData == null)
{
alert('Error: Template data did not load correctly.');
}
if (_templateData == null)
{
reportError('Error: Template data did not load correctly.');
}
loadNextTemplate();
loadNextTemplate();
};
var loadNextTemplate = function () {
@@ -43,40 +43,36 @@ var NanoTemplate = function () {
cache: false,
dataType: 'text'
}))
.done(function(templateMarkup) {
.done( function(templateMarkup) {
templateMarkup += '<div class="clearBoth"></div>';
try
{
try {
NanoTemplate.addTemplate(key, templateMarkup);
}
catch(error)
{
alert('ERROR: An error occurred while loading the UI: ' + error.message);
catch(error) {
reportError('ERROR: An error occurred while loading the UI: ' + error.message);
return;
}
delete _templateData[key];
loadNextTemplate();
})
.fail(function () {
alert('ERROR: Loading template ' + key + '(' + _templateData[key] + ') failed!');
.fail( function () {
reportError('ERROR: Loading template ' + key + '(' + _templateData[key] + ') failed!');
});
return;
}
}
};
var compileTemplates = function () {
for (var key in _templates) {
try {
_compiledTemplates[key] = doT.template(_templates[key], null, _templates)
_compiledTemplates[key] = doT.template(_templates[key], null, _templates);
}
catch (error) {
alert(error.message);
reportError(error.message);
}
}
};
@@ -94,42 +90,40 @@ var NanoTemplate = function () {
parse: function (templateKey, data) {
if (!_compiledTemplates.hasOwnProperty(templateKey) || !_compiledTemplates[templateKey]) {
if (!_templates.hasOwnProperty(templateKey)) {
alert('ERROR: Template "' + templateKey + '" does not exist in _compiledTemplates!');
reportError('ERROR: Template "' + templateKey + '" does not exist in _compiledTemplates!');
return '<h2>Template error (does not exist)</h2>';
}
compileTemplates();
}
if (typeof _compiledTemplates[templateKey] != 'function') {
alert(_compiledTemplates[templateKey]);
alert('ERROR: Template "' + templateKey + '" failed to compile!');
reportError(_compiledTemplates[templateKey]);
reportError('ERROR: Template "' + templateKey + '" failed to compile!');
return '<h2>Template error (failed to compile)</h2>';
}
return _compiledTemplates[templateKey].call(this, data['data'], data['config'], _helpers);
},
addHelper: function (helperName, helperFunction) {
if (!jQuery.isFunction(helperFunction)) {
alert('NanoTemplate.addHelper failed to add ' + helperName + ' as it is not a function.');
return;
}
_helpers[helperName] = helperFunction;
},
addHelpers: function (helpers) {
for (var helperName in helpers) {
if (!helpers.hasOwnProperty(helperName))
{
continue;
}
NanoTemplate.addHelper(helperName, helpers[helperName]);
}
},
removeHelper: function (helperName) {
if (helpers.hasOwnProperty(helperName))
{
delete _helpers[helperName];
}
}
}
addHelper: function (helperName, helperFunction) {
if (!jQuery.isFunction(helperFunction)) {
reportError('NanoTemplate.addHelper failed to add ' + helperName + ' as it is not a function.');
return;
}
_helpers[helperName] = helperFunction;
},
addHelpers: function (helpers) {
for (var helperName in helpers) {
if (!helpers.hasOwnProperty(helperName))
{
continue;
}
NanoTemplate.addHelper(helperName, helpers[helperName]);
}
},
removeHelper: function (helperName) {
if (helpers.hasOwnProperty(helperName))
{
delete _helpers[helperName];
}
}
};
}();
@@ -1,68 +1,56 @@
// NanoUtility is the place to store utility functions
var NanoUtility = function ()
{
var NanoUtility = function () {
var _urlParameters = {}; // This is populated with the base url parameters (used by all links), which is probaby just the "src" parameter
return {
init: function ()
{
var body = $('body'); // We store data in the body tag, it's as good a place as any
_urlParameters = body.data('urlParameters');
return {
init: function () {
var body = $('body'); // We store data in the body tag, it's as good a place as any
_urlParameters = body.data('urlParameters');
},
// generate a Byond href, combines _urlParameters with parameters
generateHref: function (parameters)
{
var queryString = '?';
// generate a Byond href, combines _urlParameters with parameters
generateHref: function (parameters) {
var queryString = '?';
for (var key in _urlParameters)
{
if (_urlParameters.hasOwnProperty(key))
{
if (queryString !== '?')
{
queryString += ';';
}
queryString += key + '=' + _urlParameters[key];
}
}
for (var key in _urlParameters) {
if (_urlParameters.hasOwnProperty(key)) {
if (queryString !== '?') {
queryString += ';';
}
queryString += key + '=' + _urlParameters[key];
}
}
for (var key in parameters)
{
if (parameters.hasOwnProperty(key))
{
if (queryString !== '?')
{
queryString += ';';
}
queryString += key + '=' + parameters[key];
}
}
return queryString;
}
for (var key in parameters)
{
if (parameters.hasOwnProperty(key)) {
if (queryString !== '?') {
queryString += ';';
}
queryString += key + '=' + parameters[key];
}
}
return queryString;
}
}
} ();
} ();
if (typeof jQuery == 'undefined') {
alert('ERROR: Javascript library failed to load!');
reportError('ERROR: Javascript library failed to load!');
}
if (typeof doT == 'undefined') {
alert('ERROR: Template engine failed to load!');
}
reportError('ERROR: Template engine failed to load!');
}
(function() {
var _alert = window.alert;
window.alert = function(str) {
window.location = "byond://?nano_err=" + encodeURIComponent(str);
_alert(str);
};
})();
var reportError = function (str) {
window.location = "byond://?nano_err=" + encodeURIComponent(str);
alert(str);
}
// All scripts are initialised here, this allows control of init order
$(document).ready(function () {
NanoUtility.init();
NanoStateManager.init();
NanoTemplate.init();
NanoUtility.init();
NanoStateManager.init();
NanoTemplate.init();
});
if (!Array.prototype.indexOf)