Created
June 19, 2012 03:42
-
-
Save jmarnold/2952177 to your computer and use it in GitHub Desktop.
Ajax continuation js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// fubuvalidation.js v0.5.7 | |
// | |
// Copyright (C)2011 Joshua Arnold | |
// Distributed under Apache License, Version 2.0 | |
// | |
// https://github.com/DarthFubuMVC/fubuvalidation-js | |
(function ($, continuations) { | |
_.templateSettings = { interpolate: /\{\{(.+?)\}\}/g }; | |
var handlers = []; | |
var finders = []; | |
var defaultHandler = function () { }; | |
defaultHandler.prototype = { | |
matches: function (context) { return true; }, | |
reset: function (context) { | |
var self = this; | |
context.container.find('.validation-summary').html(''); | |
context.container.hide(); | |
$('.error', context.form).each(function () { | |
self.unhighlight($(this)); | |
}); | |
}, | |
process: function (context) { | |
var self = this; | |
var container = $('.validation-container', context.form); | |
context.container = container; | |
context.summary = container.find('ul.validation-summary'); | |
this.reset(context); | |
if (context.errors.length == 0) { | |
return; | |
} | |
container.show(); | |
$.fubuvalidation.eachError(context, function (error) { | |
self.append(context, error); | |
self.highlight(error); | |
}); | |
}, | |
append: function (context, error) { | |
var found = false; | |
context | |
.summary | |
.find("li[data-field='" + error.field + "']") | |
.each(function () { | |
if (found) return; | |
if ($(this).find('a').html() == error.message) { | |
found = true; | |
return; | |
} | |
}); | |
if (!found) { | |
var self = this; | |
var token = $(_.template('<li data-field="{{ label }}"><a href="javascript:void(0);">{{ token }}</a></li>', { | |
field: error.field, | |
label: error.label, | |
token: self.generateToken(error) | |
})); | |
token.find('a').click(function () { | |
$.fubuvalidation.findElement(context, error.field).focus(); | |
}); | |
context.summary.append(token); | |
} | |
}, | |
generateToken: function (error) { | |
return _.template('{{ label }} - {{ message }}', error); | |
}, | |
highlight: function (error) { | |
if (error.element) { | |
$(error.element).addClass('error'); | |
} | |
}, | |
unhighlight: function (element) { | |
element.removeClass('error'); | |
} | |
}; | |
// This instance is registered by default and made public via $.fubuvalidation.defaultHandler | |
var theDefault = new defaultHandler(); | |
var validation = function () { }; | |
validation.prototype = { | |
init: function () { | |
this.setupDefaults(); | |
}, | |
// this is here for testing | |
reset: function () { | |
handlers.length = 0; | |
finders.length = 0; | |
this.setupDefaults(); | |
}, | |
setupDefaults: function () { | |
this.findElementsWith(function (searchContext) { | |
searchContext.element = $('#' + searchContext.key, searchContext.form); | |
}); | |
this.registerHandler(theDefault); | |
}, | |
registerHandler: function (handler) { | |
handlers.push(handler); | |
return this; | |
}, | |
findHandler: function (context) { | |
var handler; | |
for (var i = 0; i < handlers.length; i++) { | |
var x = handlers[i]; | |
if (x.matches(context)) { | |
handler = x; | |
} | |
} | |
return handler; | |
}, | |
findElementsWith: function (finder) { | |
finders.push(finder); | |
return this; | |
}, | |
findElement: function (context, key, error) { | |
var searchContext = { | |
key: key, | |
error: error, | |
form: context.form | |
}; | |
for (var i = 0; i < finders.length; i++) { | |
var finder = finders[i]; | |
finder(searchContext); | |
} | |
return searchContext.element; | |
}, | |
toValidationContext: function (continuation) { | |
var self = this; | |
this.eachError(continuation, function (e) { | |
if (!e.element) { | |
e.element = self.findElement(continuation, e.field, e); | |
} | |
}); | |
return continuation; | |
}, | |
eachError: function (context, action) { | |
for (var i = 0; i < context.errors.length; i++) { | |
action(context.errors[i]); | |
} | |
}, | |
process: function (continuation) { | |
var context = this.toValidationContext(continuation); | |
var handler = this.findHandler(context); | |
handler.process(context); | |
} | |
}; | |
var module = new validation(); | |
module.init(); | |
$.fubuvalidation = module; | |
// export the class for extension | |
$.fubuvalidation.defaultHandlerClass = defaultHandler; | |
$.fubuvalidation.defaultHandler = theDefault; | |
var reset = $.fn.resetForm; | |
$.fn.resetForm = function () { | |
var context = { | |
form: $(this), | |
container: $('.validation-container', $(this)) | |
}; | |
$.fubuvalidation.defaultHandler.reset(context); | |
reset.call(this); | |
}; | |
$.continuations.applyPolicy({ | |
matches: function (continuation) { | |
return continuation.matchOnProperty('form', function(form) { | |
return form.size() != 0; | |
}); | |
}, | |
execute: function (continuation) { | |
if (!continuation.errors) { | |
continuation.errors = []; | |
} | |
$.fubuvalidation.process(continuation); | |
} | |
}); | |
} (jQuery)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// jquery.continuations v0.3.8 | |
// | |
// Copyright (C)2011 Joshua Arnold, Jeremy Miller | |
// Distributed Under Apache License, Version 2.0 | |
// | |
// https://github.com/DarthFubuMVC/jquery-continuations | |
(function ($, aggregator) { | |
"use strict"; | |
// Sanity check of dependencies | |
if (typeof ($) !== 'function') { | |
throw 'jQuery.continuations: jQuery not found.'; | |
} | |
var CORRELATION_ID = 'X-Correlation-Id'; | |
var policies = []; | |
var theContinuation = function () { }; | |
theContinuation.prototype = { | |
success: false, | |
errors: [], | |
refresh: false, | |
correlationId: null, | |
options: {}, | |
matchOnProperty: function(prop, predicate) { | |
return typeof(this[prop]) !== 'undefined' && predicate(this[prop]); | |
}, | |
isCorrelated: function () { | |
return this.matchOnProperty('correlationId', function(id) { | |
return id != null; | |
}); | |
} | |
}; | |
var refreshPolicy = function () { | |
this.matches = function (continuation) { | |
return continuation.refresh && continuation.refresh.toString() === 'true'; | |
}; | |
this.execute = function (continuation) { | |
$.continuations.windowService.refresh(); | |
}; | |
}; | |
var navigatePolicy = function () { | |
this.matches = function (continuation) { | |
return continuation.navigatePage != undefined && continuation.navigatePage != ''; | |
}; | |
this.execute = function (continuation) { | |
$.continuations.windowService.navigateTo(continuation.navigatePage); | |
}; | |
}; | |
var errorPolicy = function () { | |
this.matches = function (continuation) { | |
return continuation.errors && continuation.errors.length != 0; | |
}; | |
this.execute = function (continuation) { | |
$.continuations.eventAggregator.publish('ContinuationError', continuation); | |
}; | |
}; | |
var payloadPolicy = function () { | |
this.matches = function (continuation) { | |
return continuation.topic != null && continuation.payload != null; | |
}; | |
this.execute = function (continuation) { | |
$.continuations.eventAggregator.publish(continuation.topic, continuation.payload); | |
}; | |
}; | |
var continuations = function () { }; | |
continuations.prototype = { | |
init: function () { | |
$(document).ajaxComplete(function (e, xhr, options) { | |
$.continuations.eventAggregator.publish('AjaxCompleted', { | |
correlationId: xhr.getResponseHeader(CORRELATION_ID) | |
}); | |
}); | |
var self = this; | |
$.ajaxSetup({ | |
cache: false, | |
success: function (continuation, status, jqXHR) { | |
var options = this.options; | |
if(typeof(options) === 'undefined') { | |
options = {}; | |
} | |
if(typeof(continuation) !== 'undefined') { | |
continuation.options = options; | |
} | |
self.onSuccess({ | |
continuation: continuation, | |
callback: this.continuationSuccess, | |
status: status, | |
response: jqXHR | |
}); | |
}, | |
beforeSend: function (xhr, settings) { | |
self.setupRequest(xhr, settings); | |
} | |
}); | |
this.setupDefaults(); | |
}, | |
setupDefaults: function () { | |
this.applyPolicy(new refreshPolicy()); | |
this.applyPolicy(new navigatePolicy()); | |
this.applyPolicy(new errorPolicy()); | |
this.applyPolicy(new payloadPolicy()); | |
}, | |
onSuccess: function (msg) { | |
var contentType = msg.response.getResponseHeader('Content-Type'); | |
if (!contentType || contentType.indexOf('json') == -1) { | |
return; | |
} | |
var continuation = msg.continuation; | |
continuation.correlationId = msg.response.getResponseHeader('X-Correlation-Id'); | |
if($.isFunction(msg.callback)) { | |
msg.callback(continuation); | |
} | |
this.process(continuation); | |
}, | |
// Keep this public for form correlation | |
setupRequest: function (xhr, settings) { | |
// this could come from the ajax options | |
var id = settings.correlationId; | |
if (typeof(id) === 'undefined') { | |
id = new Date().getTime().toString(); | |
} | |
xhr.setRequestHeader(CORRELATION_ID, id); | |
$.continuations.eventAggregator.publish('AjaxStarted', { | |
correlationId: id | |
}); | |
}, | |
applyPolicy: function (policy) { | |
policies.push(policy); | |
return this; | |
}, | |
// Mostly for testing | |
reset: function() { | |
policies.length = 0; | |
this.setupDefaults(); | |
}, | |
process: function (continuation) { | |
var standardContinuation = new $.continuations.continuation(); | |
continuation = $.extend(standardContinuation, continuation); | |
var matchingPolicies = []; | |
for (var i = 0; i < policies.length; ++i) { | |
var p = policies[i]; | |
if (p.matches(continuation)) { | |
matchingPolicies.push(p); | |
} | |
} | |
for (var i = 0; i < matchingPolicies.length; ++i) { | |
matchingPolicies[i].execute(continuation); | |
} | |
}, | |
useAmplify: function () { | |
$.continuations.eventAggregator = amplify; | |
} | |
}; | |
continuations.prototype.windowService = { | |
refresh: function () { | |
window.location.reload(); | |
}, | |
navigateTo: function (url) { | |
window.location = url; | |
} | |
}; | |
continuations.prototype.eventAggregator = { | |
publish: function (topic, payload) { | |
// no-op | |
}, | |
subscribe: function(topic, context, callback) { | |
// no-op | |
} | |
}; | |
var module = new continuations(); | |
module.init(); | |
// Make it global | |
$.continuations = module; | |
$.continuations.useAmplify(); | |
$.continuations.continuation = theContinuation; | |
$.fn.correlatedSubmit = function (options) { | |
if(typeof(options) === 'undefined') { | |
options = {}; | |
} | |
return this.each(function () { | |
var self = $(this); | |
var correlationId = options.correlationId; | |
if (typeof(correlationId) === 'undefined') { | |
var id = self.attr('id'); | |
if (!id) { | |
id = 'form_' + new Date().getTime().toString(); | |
self.attr('id', id); | |
} | |
correlationId = id; | |
} | |
self.ajaxSubmit({ | |
correlationId: correlationId, | |
continuationSuccess: function(continuation) { | |
continuation.form = self; | |
continuation.options = options; | |
if($.isFunction(options.continuationSuccess)) { | |
options.continuationSuccess(continuation); | |
} | |
} | |
}); | |
}); | |
}; | |
} (jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment