Skip to content

Instantly share code, notes, and snippets.

@Ilink
Created December 4, 2011 07:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ilink/1429498 to your computer and use it in GitHub Desktop.
Save Ilink/1429498 to your computer and use it in GitHub Desktop.
Javascripts - Ian Link
/*------------------------------------------------------------------------------------
*
* Bind from JSON - uses JSON to set up UI bindings. Utilizes jquery's 'bind'
*
* Usage:
* Supply JSON file formatted like this:
* var json = [{
* 'selector' : '#id',
* 'bind_to' : 'click',
* 'func' : [
* func1,
* func2
* ]
* }];
*
* Call the function:
* jsUtil.bind_from_json(json)
*
* Note that you can include any valid jquery selector or combination of selectors
*
* Changelog:
*
* Version 0.3: Better typechecking
*
* Version 0.2: Added support for binding to multiple functions
* - Better error reporting for type-checking errors
*
* Version 0.1: Initial commit
*
-----------------------------------------------------------------------------------*/
if (typeof jsUtil === 'undefined'){
var jsUtil = {};
}
jsUtil.bind_from_json = function(json){
"use strict";
if(typeof json == 'undefined') return 'No json supplied'
for (var i = 0; i < json.length; i++){
if (typeof json[i].selector !== 'string'){
throw "Error in supplied JSON at index "+ i + ". Expects 'Selector' as String";
}
if (typeof json[i].bind_to !== 'string'){
throw "Error in supplied JSON at index "+ i + ". Expects 'Bind_to as String";
}
if (json[i].hasOwnProperty('func')) {
if (typeof json[i].func === 'object') {
for (var j = 0; j < json[i].func.length; j++){
if (typeof json[i].func[j] !== 'function'){
throw "Error in supplied JSON at index " + i + ". Expects 'func' to be functions. The " + j + "th entry for 'functions' is not a function";
}
$(json[i].selector).bind(json[i].bind_to, json[i].func[j]);
}
}
else {
if (typeof json[i].func !== 'function'){
throw "Error in supplied JSON at index " + i + ". Expects 'func' to be a function.";
}
$(json[i].selector).bind(json[i].bind_to, json[i].func);
}
}
else throw 'Has no functions to bind to!'
}
}
// This class is basically the undo & redo structure of a command pattern - it keeps track of all undo-able commands
// Each undo-able command would have an execute() and an unexecute() command.
// The user will call this function to undo / redo commands. Note the specific use of garbage collection to avoid a memory leak
var history = (function() {
var iterator = -1; //marks the "present" command, the last command issued
var end = -1;
var start = -1;
var max_size = 3;
var command_history = []; //array to store all the commands
return {
//TODO if this method isnt fast enough, I can try a linkedlist or an array shift
add : function( command ) {
if( end >= (max_size - 1) ) { //assuming the client wants max_size in terms of '# of elements' not 'size of base-0 array'
command_history[start] = undefined; //we need to let the unused data (the oldest commands) get garbage collected
start++, end++; //move the array onwards so we can ignore + safely delete the oldest command in history
iterator = end; //move the iterator to the front when a new command is added
command_history.push(command);
console.log('trying to remove earliest command');
}
else {
end++;
if (start == -1) start = 0;
iterator = end;
command_history.push(command);
}
},
undo : function() {
if (iterator == (start-1)) return null
else {
if (iterator == end + 1) iterator = end;
if (iterator >= start) {
command_history[iterator].unexecute();
iterator--;
console.log("iter:" + iterator);
}
}
},
redo : function() {
if (iterator == (end+1)) return null
else {
if (iterator <= end) {
iterator++;
}
if (iterator <= end) {
command_history[iterator].execute();
}
}
},
logger : function() {
console.log("start: " + start + " end: " + end);
}
}
})();
// This function makes it easy to keep a div on top of the screen, no matter where the user scrolls
var make_sticky = function(selector, location, threshold){
(function(){ // the extra closure is for these variables below
var former_position = $(selector).css('position');
var former_top = $(selector).css('top');
$(window).scroll(function () {
if($(this).scrollTop() > threshold){
$(selector).css({
"position" : "fixed",
"top" : '0px'
});
}
if ($(this).scrollTop() < threshold){
$(selector).css({
"position" : former_position,
"top" : former_top
});
}
});
})();
}
/*
Usage:
var provided = {
arg1 : "arg1",
arg1 : 2
}
var should_be = {
arg1 : "string",
arg2 : "object"
}
This would throw an error for arg2 because it is the wrong type.
*/
var Type_checker = function(){
if(this instanceof Type_checker){
var errors = [];
this.check = function(check_me, should_be, extra_error_message){
$.each(check_me, function(key, value) {
if(typeof value !== should_be[key]){
var should_be_val = should_be[key];
var error = key + ' is a(n) ' + typeof value + ' when it should be a(n) ' + should_be_val;
error = error + '. ' + extra_error_message;
errors.push(error);
}
});
return errors;
}
this.log_errors = function(){
$.each(errors, function(key, value){
console.log(value);
});
}
}
else return new Type_checker()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment