Last active
December 20, 2017 10:48
-
-
Save oleics/c8bb6ee9b47551b1107369e70476d790 to your computer and use it in GitHub Desktop.
jQuery Ajax Load
This file contains 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
(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); |
This file contains 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
<!doctype html> | |
<html> | |
<head> | |
</head> | |
<body> | |
<pre id="testMoreResults"> | |
<?php echo time(); ?> | |
</pre> | |
</body> | |
</html> |
This file contains 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
<!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