Skip to content

Instantly share code, notes, and snippets.

@oleics
Last active December 20, 2017 10:48
Show Gist options
  • Save oleics/c8bb6ee9b47551b1107369e70476d790 to your computer and use it in GitHub Desktop.
Save oleics/c8bb6ee9b47551b1107369e70476d790 to your computer and use it in GitHub Desktop.
jQuery Ajax Load
(function(global){
var $ = global.$ || global.jQuery;
var history = global.history;
var VAR_NAME = 'ac-jload';
var loadSpinnerURL = '/loading.gif';
var overlayHtml = '<div style="position:absolute;text-align:center;z-index:99999">';
overlayHtml += '<img style="display:block;margin: 30px auto 0 auto" src="'+loadSpinnerURL+'">';
overlayHtml += '<div>Lädt...</div>';
overlayHtml += '</div>';
var detectFormSelector = 'form[data-'+VAR_NAME+']';
detectAndAddForms();
function detectAndAddForms(el) {
if(el == null) el = document;
if($(el).is(detectFormSelector)) {
addForm(el);
} else {
$(detectFormSelector, el||document).each(function(index, formEl){
addForm(formEl);
});
}
}
function addForm(formEl) {
if(formEl.tagName !== 'FORM') return;
var $formEl = $(formEl);
var formSelector = '#'+$formEl.attr('id');
// listen to submit-events
$formEl.bind('submit', function(e){
// setup all important vars
var formConf = $formEl.data(VAR_NAME)||{};
var formData = $formEl.serialize();
var defaultMethod = ($formEl.attr('method')||'GET').toUpperCase();
var defaultUrl = $formEl.attr('action')||location.href;
var defaultSelector = formSelector;
// prevent double-submits
$.each(formEl.elements, function(index, _el){
_el.readOnly = true;
_el.setAttribute('readonly', 'readonly');
_el.disabled = true;
_el.setAttribute('disabled', 'disabled');
});
//
var jobs = [];
if(formConf && formConf.length) {
$.each(formConf, function(index, c){
jobs.push({
method: c.method||defaultMethod,
url: c.url||defaultUrl,
selector: c.selector||defaultSelector,
selectorTarget: c.selectorTarget||c.selector||defaultSelector
});
});
} else {
jobs.push({
method: defaultMethod,
url: defaultUrl,
selector: defaultSelector,
selectorTarget: defaultSelector
});
}
// overlay with loading-spinner
$.each(jobs, function(index, c){
var $el = $(c.selectorTarget);
if($el.length === 0) return;
var $overlay = $(overlayHtml);
$el.prepend($overlay);
$overlay.css('height', $el.height());
$overlay.css('width', $el.width());
});
// submit the data
setTimeout(function() {
loadUrls(jobs, formData)
.then(function(pageResults){
replaceIt(jobs, pageResults);
// linkable url
if(historyApiIsAvailable()) {
var pageUrl = setQueryStringOfUrl(defaultUrl, formData);
history.pushState(null, null, pageUrl);
}
})
;
}, 800);
e.preventDefault();
});
// submit the form on changes
$.each(formEl.elements, function(index, _el){
if(_el.tagName !== 'INPUT' && _el.tagName !== 'TEXTAREA') {
$(_el).bind('change', function(e){
$formEl.submit();
});
}
});
}
// Url & QueryString
if(historyApiIsAvailable()) {
global.onpopstate = function(event) {
document.location.reload();
};
}
function historyApiIsAvailable() {
return !!(history && history.pushState);
}
function setQueryStringOfUrl(url, queryString) {
var posQ = url.indexOf('?'),
posH = url.indexOf('#');
if(posH === -1) posH = url.length;
if(posQ === -1) posQ = posH;
if(posQ > posH) {
posQ = posH;
}
var s = url.slice(posQ, posH);
s = '?'+mergeQueryStrings(s, queryString);
url = url.slice(0, posQ) + s + url.slice(posH);
return url;
}
function mergeQueryStrings(queryString /*, queryString2, ...*/) {
var query = parseQueryString(queryString),
args = Array.prototype.slice.call(arguments, 1),
i, len = args.length, value, key;
for(i=0; i<len; i++) {
value = parseQueryString(args[i]);
for(key in value) {
if(value.hasOwnProperty(key)) {
query[key] = value[key];
}
}
}
return buildQueryString(query);
}
function parseQueryString(queryString) {
if(queryString[0] === '?') queryString = queryString.slice(1);
if(queryString.length === 0) return {};
var query = {}, parts = queryString.split('&'), i, len = parts.length, value;
for(i=0; i<len; i++) {
value = parts[i].split('=');
query[decodeURIComponent(value[0])] = decodeURIComponent(value.slice(1).join('='));
}
return query;
}
function buildQueryString(query) {
var qs = '', key;
for(key in query) {
if(query.hasOwnProperty(key)) {
qs += '&'+encodeURIComponent(key)+'='+encodeURIComponent(query[key]);
}
}
if(qs.length) qs = qs.slice(1);
return qs;
}
//
function loadUrls(jobs, data) {
var dfd = jQuery.Deferred();
var pageResults = new PageResults();
var pending = 0;
dequeue(jobs.slice(0), data);
function dequeue(jobs, data) {
while(jobs.length) {
var job = jobs.shift();
if(pageResults.has(job.method, job.url)) continue;
pageResults.set(job.method, job.url, '');
++pending;
loadIt(job.method, job.url, data)
.then(function(pageData){
pageResults.set(pageData.method, pageData.url, pageData.result);
done();
})
.fail(function(err){
console.error(err.stack||err);
pageResults.set(job.method, job.url, (err instanceof Error) ? err : new Error((err.stack||err)+''));
done();
})
;
}
}
function done() {
--pending;
if(pending) return;
dfd.resolve(pageResults);
}
return dfd.promise();
}
function loadIt(method, url, data) {
var dfd = jQuery.Deferred();
fetch();
function fetch() {
$.ajax({
method: method,
url: url,
data: data,
success: function(result){
dfd.resolve({
method: method,
url: url,
data: data,
result: result,
});
},
error: function(xhr, statusText, errorThrown) {
// var err = new Error(errorThrown);
// err.status = xhr.status;
// err.url = this.url;
// dfd.reject(err);
setTimeout(fetch, 800);
}
});
}
return dfd.promise();
}
function replaceIt(jobs, pageResults) {
$.each(jobs, function(index, c){
var data = pageResults.get(c.method, c.url);
if(data instanceof Error) {
return;
}
var $nextEl = $(c.selector, $('<div>'+data+'</div>'));
$(c.selectorTarget).replaceWith($nextEl);
$nextEl.each(function(i, el) {
detectAndAddForms(el);
});
});
}
//
function PageResults() {
this._results = {};
}
PageResults.prototype.set = function(method, url, pageData) {
if(this._results[method] == null) this._results[method] = {};
this._results[method][url] = pageData;
};
PageResults.prototype.has = function(method, url) {
return this._results[method] != null && this._results[method][url] != null;
};
PageResults.prototype.get = function(method, url) {
if(this._results[method] == null) return;
return this._results[method][url];
};
})(window||global);
<!doctype html>
<html>
<head>
</head>
<body>
<pre id="testMoreResults">
<?php echo time(); ?>
</pre>
</body>
</html>
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<form
id="testForm2"
data-ac-jload
>
<select name="whatsyourchoice" class="form-control">
<?php
foreach(['a','b','c'] as $value) {
echo '<option value="'.$value.'" '.($value === @$_REQUEST['whatsyourchoice'] ? 'selected="selected"' : '').'>'.$value.'</option>';
}
?>
</select>
<button>OK</button>
</form>
<form
id="testForm"
data-ac-jload='[{
"url": "/test.php",
"selector": "#testForm"
},{
"selector": "#testForm2"
},{
"url": "/test.php",
"selector": "#testResults"
},{
"url": "/more.php",
"selector": "pre",
"selectorTarget": "#testMoreResults"
}]'
>
<select name="whatsyourchoice" class="form-control">
<?php
foreach(['a','b','c'] as $value) {
echo '<option value="'.$value.'" '.($value === @$_REQUEST['whatsyourchoice'] ? 'selected="selected"' : '').'>'.$value.'</option>';
}
?>
</select>
<select name="whatsyourchoice2" class="form-control">
<?php
foreach(['a','b','c'] as $value) {
echo '<option value="'.$value.'" '.($value === @$_REQUEST['whatsyourchoice2'] ? 'selected="selected"' : '').'>'.$value.'</option>';
}
?>
</select>
<button>OK</button>
</form>
<pre
id="testResults"
>
<?php echo time(); ?>
<?php print_r($_REQUEST); ?>
</pre>
<div id="testMoreResults">
</div>
</div>
<script
src="https://code.jquery.com/jquery-1.12.4.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
crossorigin="anonymous"></script>
<script src="ac-jload.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment