Skip to content

Instantly share code, notes, and snippets.

@max19931
Forked from waleedka/primer.js
Created July 24, 2019 13:14
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 max19931/5ef55d0df65aa076174398c91699e0d2 to your computer and use it in GitHub Desktop.
Save max19931/5ef55d0df65aa076174398c91699e0d2 to your computer and use it in GitHub Desktop.
A simple lib to handle AJAX, dialogs, and forms
!function() {
var doc = document,
htm = doc.documentElement,
lct = null, // last click target
nearest = function(elm, tag) {
while (elm && elm.nodeName != tag) {
elm = elm.parentNode;
}
return elm;
};
htm.onclick = function(e) {
e = e || window.event;
lct = e.target || e.srcElement;
var elem = nearest(lct, 'A') || htm,
href = elem.getAttribute('ajaxify') || elem.href;
switch (elem.rel) {
case 'dialog':
case 'dialog-post':
dialog_bootstrap(href, elem);
break;
case 'async':
case 'async-post':
var cid=elem.getAttribute("context");
var context = $(cid ? "#" + cid : elem);
var tid=elem.getAttribute("target");
var target = $(tid ? "#" + tid : context);
ajax_send(href, extract_args(elem), context, target);
break;
default:
return;
}
return false;
};
htm.onsubmit = function(e) {
e = e || window.event;
var elem = e.target || e.srcElement;
if (!elem || elem.nodeName != 'FORM' || !elem.getAttribute('ajaxify')) {
return;
}
form_send(elem);
return false;
};
// Remove the no JS class, if it is here
htm.className = htm.className.replace('no_js', '');
function dialog_bootstrap(href, elem)
{
// Insert dialog markup
if ($("#primer_dialog").length == 0)
$('<div id="primer_dialog" style="display:none;">' +
'<div id="primer_dialog_content"></div>' +
'<div id="primer_dialog_loading">' +
'<div class="blog_loading">Loading...</div>' +
'</div>' +
'</div>').appendTo('body');
$("#primer_dialog_content").html("");
$('#primer_dialog').dialog({
width: elem.getAttribute("width"),
modal: true,
title: elem.getAttribute("title"),
close: function(event, ui) {
// callback
if ($(elem).attr('onclose'))
eval($(elem).attr('onclose'));
},
open: function() {
ajax_send(href,
$.extend(extract_args(elem), {"showonwait":"#primer_dialog_loading"}),
null, $("#primer_dialog_content"));
}
});
}
function extract_args(elem)
{
var args = {};
$.each(elem.attributes, function(i, attr) {
args[attr.name] = attr.value;
});
return args;
}
function ajax_send(href, args, context, target)
{
if (context){
context = $(context);
context.addClass("ajax_wait");
context.removeClass("ajax_success");
context.removeClass("ajax_error");
}
$(args.hideonwait).hide();
$(args.showonwait).show();
if (args.waitcss)
var spinner = ajax_spinner(context, args.waitcss);
$.ajax({
type: (args.rel == "async" || args.rel == "dialog") ? "GET" : "POST",
url: href,
dataType: "json",
data: args.data ? args.data:null,
success: function(data){
if (context) context.removeClass("ajax_wait");
$(args.hideonwait).show();
$(args.showonwait).hide();
if (spinner) remove_spinner(context, spinner);
handle_response(args, context, target, data);
},
error: function(xhr, status, errorThrown){
if (context) context.removeClass("ajax_wait");
$(args.hideonwait).show();
$(args.showonwait).hide();
if (spinner) remove_spinner(context, spinner);
ajax_error(args, context, status,
errorThrown ? errorThrown.string() : "");
}
});
}
// todo: update this function to use ajax_send to reduce duplicate code.
function form_send(elem)
{
var cid=elem.getAttribute("context");
var context = $(cid ? "#" + cid : elem);
var tid=elem.getAttribute("target");
var target = $(tid ? "#" + tid : elem);
context.addClass("ajax_wait");
context.removeClass("ajax_success");
context.removeClass("ajax_error");
data = $(elem).serialize();
href = $(elem).attr("ajaxify");
$.ajax({
type: elem.method,
url: href,
dataType: "json",
data: data,
success: function(data){
handle_response(elem, context, target, data);
},
error: function(xhr, status, errorThrown){
context.removeClass("ajax_wait");
ajax_error(elem, context, status,
errorThrown ? errorThrown.tostring():"");
}
});
}
function handle_response(args, context, target, data)
{
// Replace html fragments
if (data && data.html)
if (typeof data.html == "string")
target.html(data.html);
else
for (var k in data.html){
if (k == '__target__')
target.html(data.html[k]);
else
$("#" + k).html(data.html[k]);
}
// Check for errors
if (data && data.error)
ajax_error(args, context, data.error.code, data.error.message, data);
else {
if (context) context.addClass("ajax_success");
// callback
if (args.onsuccess)
if (typeof args.onsuccess === "function")
(args.onsuccess)(data);
else
eval(args.onsuccess);
}
}
function ajax_error(args, context, error_code, error_message, data)
{
if (context) context.addClass("ajax_error");
if (args.onerror)
eval(args.onerror);
else if (data && data.html)
return; // if html is supplied, assume it handles displaying the error.
else if (error_code == "UserError")
alert(error_message);
else
alert("Opps, an error happened. Please try again.\n" +
"code: " + error_code + ", message: " + error_message);
}
function ajax_spinner(elem, waitcss)
{
var position = $(elem).offset();
elem.css('visibility', 'hidden');
return $('<div class="' + waitcss +'"></div>')
.css('position','absolute')
.css({top: position.top, left: position.left,
width: $(elem).width(), height: $(elem).height()})
.appendTo('body');
}
function remove_spinner(elem, spinner)
{
spinner.remove();
elem.css('visibility', 'visible');
}
// Create object to expose publicly.
var Primer = {
ajax : ajax_send
};
window.Primer = Primer;
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment