I am trying to change page but without any reloading
here's what I do:
AJAX:
app.ajax.client.request = function(headers, path, method, queryObj, payload, cb) {
// Set defaults
headers = typeof(headers) == 'object' && headers !== null ? headers : {};
path = typeof(path) == 'string' ? path : '/';
method = typeof(method) == 'string' && ['POST','PUT','DELETE','GET'].indexOf(method.toUpperCase()) > -1 ? method.toUpperCase() : 'GET';
queryObj = typeof(queryObj) == 'object' && queryObj !== null ? queryObj : {};
payload = typeof(payload) == 'object' && payload !== null ? payload : {};
cb = typeof(cb) == 'function' ? cb : false;
// For each query string parameter sent, add it to the path
let requestUrl = path + '?';
let counter = 0;
// Set the request url based on the query object
for (let i in queryObj) {
if (queryObj.hasOwnProperty(i)) {
counter++
if (counter > 1) {
requestUrl += '&';
}
requestUrl += i + '=' + queryObj[i];
}
}
// Form the http request as a JSON type
let xhr = new XMLHttpRequest();
xhr.open(method, requestUrl, true);
xhr.setRequestHeader('Content-Type', 'application/json');
// For each header sent, add it to the request
for (let i in headers) {
if (headers.hasOwnProperty(i)) {
xhr.setRequestHeader(i, headers[i]);
}
}
// When the request comes back, handle the response
xhr.onreadystatechange = function() {
// Set the parameters that will be called back
let readyState = xhr.readyState;
let statusCode = xhr.status;
let responseReturned = xhr.responseText;
// Parse the response
let parsedResponse = app.isJsonString(responseReturned);
if (parsedResponse) { // If the response text is a JSON, callback parsedResponse, if not, callback the not parsed response instead
cb(readyState, statusCode, parsedResponse);
} else {
cb(readyState, statusCode, responseReturned);
}
}
// Send the payload as JSON
let payloadString = JSON.stringify(payload);
xhr.send(payloadString);
}
Client Requests:
app.changeToIndexPage = function(e) {
e.preventDefault();
if (!app.mainContainer.hasClass('index')) {
app.closePage(); // show a loading screen
history.pushState({}, '', '/'); //Set the url to the index's url
setTimeout(function() {
app.ajax.client.request(undefined, 'public/request/index.txt', 'GET', undefined, undefined, function(readyState, statusCode, response) { // Get the request
console.log(readyState);
if (readyState < 3) {
app.preloader.addClass('loading');
} else if (readyState == 4 && statusCode == 200) {
app.navContainer.attr('class', app.navContainer.attr('class').replace(/index|project|about|contact/g, 'index'));
setTimeout(function() {
app.mainContainer.html(response);
}, 500);
}
});
}, 100);
}
}
So, for example:
If I am not on the index page, and wanted to go to the index page, i can run the changeToIndexPage function, and the ajax will request the needed file and change the html element based on the needed action. The only problem that I had is, are there any better solution??
If you're going to take the approach of fetching pages with AJAX and slapping them into the document, which I wouldn't recommend in the first place, you should have a generalized function to do so.
That function should have a signature like function navigate(path) { ... }. It should add the history entry, fetch the appropriate document and insert it onto the page.
Then, you'll need to attach an event listener to catch popState events, so when the user presses the back button you retrieve the path from the history entry that was popped and pass it to navigate().
Again, if you're looking to build an SPA I wouldn't recommend building it like this. One of the major benefits of SPAs are the performance gain from rendering your documents on the client, which this approach doesn't leverage. Consider using a component-based client-side rendering library like React or Angular.
Related
I've been having a hard time writing websockets in PHP, so I decided to try to download a datastream.
It works, I can get content in different times, parse it, and use it, but the entire response is saved into memory...
Is there a way to reset the request's response every time in onreadystatechange function? (where that comment is)
Removing the comment, I get this error:
test.html:20 Uncaught TypeError: Cannot assign to read only property
'responseText' of object '#'
A working code for streaming:
class HTTPStream {
constructor(url, callback, error) {
this.request = new XMLHttpRequest();
var previous_text = '';
if (typeof error === "function")
this.request.onerror = error;
this.request.onreadystatechange = () => {
if (this.request.readyState > 2) {
var new_response = this.request.responseText.substring(previous_text.length);
if(new_response != "") {
var result = JSON.parse(new_response);
callback(result);
}
previous_text = this.request.responseText;
//this.request.responseText = "";
}
};
this.request.open("GET", url, true);
this.request.send();
}
cancel() {
this.request.abort();
}
}
new HTTPStream('test.php', (m) => console.log(m));
Here is a log:
EDIT:
By suggestions, I tried doing this, but unfortunately you can set it to writable only once, and that is it. I have lots of outputs, not just once.
I'm using hls.js with video Js and I was wondering how I could implement a custom loader that loads the content using fetch API instead of XMLHttpRequest.
The following is what I managed to achive:
hlsConfig: {
loader: function() {
this.load = function(url, responseType, onSuccess, onError, timeout, maxRetry, retryDelay) {
var onProgress = arguments.length <= 8 || arguments[8] === undefined ? null : arguments[8];
var frag = arguments.length <= 9 || arguments[9] === undefined ? null : arguments[9];
this.url = url;
if (frag && !isNaN(frag.byteRangeStartOffset) && !isNaN(frag.byteRangeEndOffset)) {
this.byteRange = frag.byteRangeStartOffset + '-' + (frag.byteRangeEndOffset - 1);
}
this.responseType = responseType;
this.onSuccess = onSuccess;
this.onProgress = onProgress;
this.onError = onError;
this.stats = {
trequest: performance.now(),
retry: 0
};
this.timeout = timeout;
this.maxRetry = maxRetry;
this.retryDelay = retryDelay;
if (self.fetch) {
// use fetch API
} else {
// fallback to XMLHttpRequest loader
}
return true;
}
}
hls.js only takes xmlHTTPrequest events. You have to modify hls.js to make it handle the input the way you like, search for 'loadsuccess' in unminified hls.js and change it to how you would handle the data yourself. Make sure the payload is the requested responseType; make sure payload is an ArrayBuffer if it asks for it, and just a plain string for empty responseType.
Personally I have coded the following shim in order to pass the data came from WebRTC or whatever else:
function CustomLoaderResponse(response)
{
this.currentTarget = {};
this.currentTarget.getResponseHeader = function() { return '' };
this.currentTarget.response = response;
this.currentTarget.responseText = typeof(response) == "string" ? response : '';
}
<...>
var response = new CustomLoaderResponse(/* pass string or arraybuffer here */);
I guess that the should propose handling the regular JavaScript dictionaries in the future releases of hls.js, as this can't be considered as a good practice either.
is there a way to detect resources on the page with response 404?
Also why the browser api- performance.getEntriesByType("resource") doesn't include the failed resources?
Well, with this function :
function UrlExists(url) {
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
if (http.status == 404) {
// do something
}
}
And you pass the URL of your resource. but it's not the best solution ever to check this. Let's say it's the simplest :)
EDIT :
After you can also do it for every kind of resources (CSS, Images, ...), a function like this one :
var styleSheetExists = function(name) {
for (var i in document.styleSheets) {
if (typeof document.styleSheets[i] == "object") {
link = document.styleSheets[i].href;
if (link === null) {
continue;
}
if (link.indexOf(name, link.length - name.length) !== -1) {
return true;
}
}
}
return false;
}
That you can use like :
$(document).ready(function() {
console.log(styleSheetExists('jquery-ui.css'));
console.log(styleSheetExists('doesnotexist.css'));
});
(Source of the function : How to check for 403 and 404 errors when changing the url of a resource?)
and by checking every kind of resource, you can assure that there is or not a 404 status about them.
I have an ajax call where I used jQuery.ajax() to make a request to an mvc action. This all worked fine. However due to some forms having a file control I changed it from using jQuery.ajax() to using the XMLHttpRequest to send it using the HTML5 File API.
Since making this change the MVC action method no longer see's it as an ajax request. Using Fiddler2 I have noticed that it no longer adds the "X-Requested-With: XMLHttpRequest" to the request and I assume this is the problem.
The form I am trying to send does not have a file input in it, only normal textboxes etc, but I was trying to keep the method generic to deal with both. The following is the code I am using to send the ajax request:
// get the edit tender form
var $Form = $Button.closest('form');
var Url = $Form.attr('action');
var AjaxRequestObject = new XMLHttpRequest();
var FormDataToSend = new FormData();
$Form.find(':input').each(function () {
if ($(this).is('input[type="file"]')) {
var files = $(this)[0].files;
if (files.length > 0) {
FormDataToSend.append(this.name, files[0]);
}
} else {
FormDataToSend.append(this.name, $(this).val());
}
});
AjaxRequestObject.open('POST', Url, true);
AjaxRequestObject.onreadystatechange = function () {
if (AjaxRequestObject.readyState == 4) {
// handle response.
if (AjaxRequestObject.status == 200) {
if (!AjaxErrorExists(AjaxRequestObject.responseText, )) {
alert("success");
console.log(AjaxRequestObject.responseText);
}
else {
alert('failure');
}
}
else {
alert('failure');
}
}
};
AjaxRequestObject.send(FormDataToSend);
This code was provided following a problem I had which Darin Dimitrov provided the solution to, so I could send the file inputs by ajax.
Any ideas why this request would not send the header for an ajax call?
X-Requested-With is automatically added by jQuery. You can just as easily add it yourself with AjaxRequestObject.setRequestHeader(). Docs
I was having troubles with detecting if my request was ajax. So, maybe this sample will save someone a minute or two:
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', URL, true); // `true` for async call, `false` for sync.
// The header must be after `.open()`, but before `.send()`
xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlhttp.onreadystatechange = function() {
// 4th state is the last:
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { ... }
};
xmlhttp.send();
Tested with Flask.
You can override natively all XMLHttpRequest.open method calls and add in it X-Requested-With header like:
(function () {
// #author https://github.com/stopsopa jfdsa78y453cq5hjfd7s877834h4h3
if (window.XMLHttpRequest.prototype.onOpen) {
return console.log('XMLHttpRequest.onOpen is already defined');
}
function over(method, on, off) {
var old = window.XMLHttpRequest.prototype[method];
if (!old.old) {
var stack = [];
window.XMLHttpRequest.prototype[on] = function (fn) {
if (typeof fn === 'function') {
stack.push(fn);
}
}
window.XMLHttpRequest.prototype[off] = function (fn) {
for (var i = 0, l = stack.length ; i < l ; i += 1 ) {
if (stack[i] === fn) {
stack.splice(i, 1);
break;
}
}
}
window.XMLHttpRequest.prototype[method] = function () {
var args = Array.prototype.slice.call(arguments);
var ret = old.apply(this, args);
for (var i = 0, l = stack.length ; i < l ; i += 1 ) {
stack[i].apply(this, args);
}
return ret;
}
window.XMLHttpRequest.prototype[method].old = old;
}
}
over('open', 'onOpen', 'offOpen')
XMLHttpRequest.prototype.onOpen(function () {
this.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
});
}());
I am using an html form to upload a file to my server. I want to execute a javascript function only after the form has been submitted and the file has been successfully uploaded. The form opens a new page with the text "upload succeeded" if the file upload worked. I tried using a while loop that would loop until the file was found in the database but it crashed my browser. How can I do this? I'm using myform.submit() to submit my form right now.
If the post went well, and you save the file before flushing the page contents, this is easy. The page won't return until the post cycle is ready, so you could insert javascript code to the page after the saving of the file.
You can use AJAX to upload you file and you the async return function (this is a event that will trigger when your request is done) to ether a success or failed message from you php.
EDIT:
Here is a ajax function iv made that u can use, just load this in an extenal file:
var ajax = function(data){
// Return false is no url... You need an url to get url data..
if(typeof data.url !== 'undefined'){
var url = data.url;
// Adept the function depending on your method
if(data.method === 'GET' && data.params !== 'undefined'){
url+='?'+data.params;
}
}else{
return(false);}
var // Set some vars 'n' stuff
method = ( data.method === 'GET') ? 'GET' : 'POST',
params = (typeof data.params !== 'undefined') ? data.params : null,
async = ( data.async === true) ? true : false,
done = (typeof data.done === 'function') ? data.done : false,
return_value = null,
length = (data.method === 'POST') ? data.method.length : '';
var // Find out what ajax methods the browser support
request_method = function(){
var xmlhttp = false;
try {
xmlhttp = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
xmlhttp = false;
}
}
}
return xmlhttp;
}// This thing connet to the server
connect = function(){
if(request = request_method()){}else{
return(false);
}
request.open(method, url, async);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", length);
request.setRequestHeader("Connection", "close");
request.send(params);
request_handle(request);
},// This is where the result get processed
request_handle = function(request){
if(async){
request.onreadystatechange = function() {
if(request.readyState === 4 && request.status === 200) {
done(data);
}
}
}else{
done(data);
}
};
connect();
return(return_value);
}
usage:
ajax({
url: 'test.php',
//// Your ajax request url // no default // Must be set!
method: 'POST',
//// Method of sending ajax data // default is POST
async: true,
//// What to do when done with the request // no default
done: function(http){
table(http,'test');
}
});
one simple thing you can do
use executescalar to insert uploading file as soon as it inserts the file return boolean value to check whether it is inserted,if so then set hiddenfield value. in javascript check the value of the hiddenfield and according to that you can call your javascript function