Setting html5 media source using ajax - javascript

I needed to aid authentication headers for my audio files i was grabbing from a external server. So now im trying to use ajax, i can grab the files fine, but i cant set them as the media source for my player. How do you approach setting a ajax loaded file as a audio source?
EDIT
Ended up fixing it in case someone comes back this way.
if (this.mAudioPlayer.canPlayType("audio/mpeg")) {
this.mExtension = '.mp3';
}else if (this.mAudioPlayer.canPlayType("audio/ogg")) {
this.mExtension = '.ogg';
} else if (this.mAudioPlayer.canPlayType("audio/mp4")) {
this.mExtension = '.m4a';
}
this.CreateAudioData = function() {
//downloading audio for use in data:uri
$.ajax({
url: aAudioSource + this.mExtension + '.txt',
type: 'GET',
context: this,
async: false,
beforeSend: function(xhr) {xhr.setRequestHeader('Authorization', window.userId);},
success: this.EncodeAudioData,
error: function(xhr, aStatus, aError) { HandleError('Audio Error: ' + aStatus); }
});
};
this.EncodeAudioData = function(aData) {
//this.mAudioData = base64_encode(aData);
this.mAudioData = aData;
if (this.mExtension == '.m4a') {
Debug("playing m4a");
this.mAudioSrc = "data:audio/mp4;base64," + this.mAudioData;
} else if (this.mExtension == '.ogg') {
Debug("playing ogg");
this.mAudioSrc = "data:audio/ogg;base64," + this.mAudioData;
} else if (this.mExtension == '.mp3') {
Debug("playing mp3");
this.mAudioSrc = "data:audio/mp3;base64," + this.mAudioData;
}
};
this.play = function() {
if (this.mAudioPlayer.src != this.mAudioSrc) {
this.mAudioPlayer.src = this.mAudioSrc;
}
this.mAudioPlayer.load();
this.mAudioPlayer.play();
};
Had to do asynch:false, otherwise i would get a small chunk of the audio instead of all of it. Though removing the asynch made debugging easier in the end.

Are you actually downloading the file, or returning it in base64 encoded format (i.e. as a Data URI)?
Changing the source of an audio element via JavaScript is quite straightforward.
<audio id="myAudio" controls />
And then once you have the source,:
var audio = document.getElementById("myAudio");
audio.src = myAudioFile;
audio.type = "type/ogg"; // ony showing an OGG example here

if (this.mAudioPlayer.canPlayType("audio/mpeg")) {
this.mExtension = '.mp3';
}else if (this.mAudioPlayer.canPlayType("audio/ogg")) {
this.mExtension = '.ogg';
} else if (this.mAudioPlayer.canPlayType("audio/mp4")) {
this.mExtension = '.m4a';
}
this.CreateAudioData = function() {
//downloading audio for use in data:uri
$.ajax({
url: aAudioSource + this.mExtension + '.txt',
type: 'GET',
context: this,
async: false,
beforeSend: function(xhr) {xhr.setRequestHeader('Authorization', window.userId);},
success: this.EncodeAudioData,
error: function(xhr, aStatus, aError) { HandleError('Audio Error: ' + aStatus); }
});
};
this.EncodeAudioData = function(aData) {
//this.mAudioData = base64_encode(aData);
this.mAudioData = aData;
if (this.mExtension == '.m4a') {
Debug("playing m4a");
this.mAudioSrc = "data:audio/mp4;base64," + this.mAudioData;
} else if (this.mExtension == '.ogg') {
Debug("playing ogg");
this.mAudioSrc = "data:audio/ogg;base64," + this.mAudioData;
} else if (this.mExtension == '.mp3') {
Debug("playing mp3");
this.mAudioSrc = "data:audio/mp3;base64," + this.mAudioData;
}
};
this.play = function() {
if (this.mAudioPlayer.src != this.mAudioSrc) {
this.mAudioPlayer.src = this.mAudioSrc;
}
this.mAudioPlayer.load();
this.mAudioPlayer.play();
};
Had to do asynch:false, otherwise i would get a small chunk of the audio instead of all of it. Though removing the asynch made debugging easier in the end.

Related

JavaScript localStorage of image src doesn't work with Firefox

I have 2 array of path items:
var images = [
imgPath + 'earth-png/a1.png',
imgPath + 'earth-png/a2.png',
...
var images2 = [
imgPath + 'eye-lens/01.png',
imgPath + 'eye-lens/02.png',
imgPath + 'eye-lens/03.png',
...
Then in order to make an animation with multiple images, I try to load it first :
this.loadImages = function() {
if (typeof(Storage) == "undefined" ) {
console.log("Your browser does not support HTML5 localStorage. Try upgrading.");
return false;
}
else {
console.log("Both localStorage and sessionStorage support is there.");
}
var totalImg = images.length + images2.length
i = 0,
j = 0
var myImages1 = [];
var myImages2 = [];
function loadImgs() {
if (i < totalImg && (myImages1Storage.length > 0 && myImages2Storage.length > 0)) {
if (i < 20) {
$.ajax({
type: 'GET',
url: images[i],
crossDomain: true,
xhrFields: {
withCredentials: false
},
complete: function() {
myImages1.push(images[i]);
i++;
loadImgs();
}
});
} else {
$.ajax({
type: 'GET',
url: images2[j],
crossDomain: true,
xhrFields: {
withCredentials: false
},
complete: function() {
myImages2.push(images2[j]);
j++;
i++;
loadImgs();
}
});
}
} else {
try {
localStorage.setItem("images1", JSON.stringify(myImages1));
localStorage.setItem("images2", JSON.stringify(myImages2));
}
catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
console.log("Error: Local Storage limit exceeds.");
} else {
console.log("Error: Saving to local storage.");
}
}
}
}
loadImgs();
};
And then, to the TimelineMax:
eyeLensAnimation
.to(obj, 0.5, {
curImg: images2.length,
roundProps: "curImg",
immediateRender: true,
ease: Linear.easeNone,
onUpdate: function() {
//next image on update
eyePng.src = images2[obj.curImg];
}
});
Well, here comes my question.
As you can see, I store the data in a localStorage. It seems to be successful when I go through the array load with a:
JSON.parse(localStorage.getItem("images1"));
Nevertheless, it seems to work only with Chrome.
With Firefox, it continues to request a get when it's time to trigger the animation (on scroll with scrollmagic).
So, is there something I do wrong?
Should I load first the array stored and use the array loaded as path for my animation or does it not occur if - at least - the path asked is already stored in cache?

Getting total page size: syncronicity problems

I'm trying to set up a script to get total page size, including images. I'm having serious problems with ajax asyncronicity and JQuery throws error when I try to set async: false due to negative effects in user experience.
The problem is, ajax calls to get image size return NaN in a random and very frequent way, surely due to too many concurrent connections.
Is there a way you can think to overcome this?
This is my code (it was much shorter in origin, callback approach was based on this post, but didn't work):
function getPageSize(callback)
{
var pageWeight = 0;
var lastWeight = 0;
var xhr = $.ajax({
type: "HEAD",
// async: false,
url: "test01.html",
success: function(msg)
{
if (xhr.readyState == 4)
{
if (xhr.status == 200 || xhr.status == 0)
{
if ( !isNaN(xhr.getResponseHeader('Content-Length')) && !isNaN($('#size').html()) )
{
pageWeight = parseInt(xhr.getResponseHeader('Content-Length'));
callback(pageWeight);
// lastWeight = parseInt($('#size').html());
// $('#size').html(pageWeight + lastWeight);
console.log("Page " + pageWeight);
}
}
}
}
});
}
function getImagesSize(callback)
{
var imageWeight = 0;
var lastWeight = 0;
$('img').each(function()
{
var imgPath = $(this).attr('src');
xhr = null;
xhr = $.ajax(
{
type: "HEAD",
url: $(this).attr('src'),
async: false,
success: function(msg)
{
if (xhr.readyState == 4)
{
if (xhr.status == 200 || xhr.status == 0)
{
if (!isNaN(xhr.getResponseHeader('Content-Length')) && !isNaN($('#size').html()) )
{
imageWeight = parseInt(xhr.getResponseHeader('Content-Length'));
callback(imageWeight);
// lastWeight = parseInt($('#size').html());
// $('#size').html(imageWeight + lastWeight);
console.log("Image " + imgPath + ": " + imageWeight);
}
}
}
}
});
});
}
function updateTotalPageSize(size)
{
var lastWeight = 0;
lastWeight = parseInt($('#size').html());
$('#size').html(size + lastWeight);
}
$(document).ready(function()
{
getPageSize(function(size)
{
//alert(size);
updateTotalPageSize(size);
});
getImagesSize(function(size)
{
//alert(size);
updateTotalPageSize(size);
});
});
SOLUTION by #Regent
function getImagesSize(callback)
{
var allImages = $('img');
function handleNext(index)
{
if (index >= allImages.length)
{
return;
}
var imgPath = allImages.eq(index).attr('src');
$.ajax({
type: "HEAD",
url: imgPath,
success: function(msg, status, xhr)
{
if (!isNaN(xhr.getResponseHeader('Content-Length')) && !isNaN($('#size').html()))
{
var imageWeight = parseInt(xhr.getResponseHeader('Content-Length'));
callback(imageWeight);
console.log("Image " + imgPath + ": " + imageWeight);
handleNext(index + 1);
}
}
});
}
handleNext(0);
}

Jquery form submit not working, instead get js warning 'body.scrollLeft is deprecated in strict mode' in console

I have the following code in my js file:
function PS_SL_HandleEvent()
{
$(document).ready(function() {
$('#form').removeAttr('onsubmit').submit(function(e) {
if(acceptCGV())
{
e.preventDefault();
if ($('#send_order_form input[type="radio"]:checked').val() == "")
{
resetAjaxQueries();
delSelection(1);
}
else
{
var carrierClass = $('input:radio[name="order_choose"]:checked').attr('class');
carrierClass = carrierClass.replace("carrier_","");
var radio_selector = '.delivery_options_address input[value="' + carrierClass + ',"], #carrierTable input[value="' + carrierClass + '"]';
$(radio_selector).attr('checked','checked');
resetAjaxQueries();
saveSelection(1);
}
}
else
e.preventDefault();
});
});
}
function saveSelection(is_submit)
{
$('#sendwithorder_errors').slideUp();
$('#sendwithorder_errors_list').children().remove();
//displayWaitingAjax('block', SL_RedirectTS);
//$('.SE_SubmitRefreshCard').fadeOut('fast');
var query = $.ajax({
type: 'POST',
headers: { "cache-control": "no-cache" },
url: baseDir + 'modules/sendwithorder/ajax.php' + '?rand=' + new Date().getTime(),
data: 'method=saveSelection&' + 'order_choose=' + $('#send_order_form input[name=order_choose]:checked').val(),
dataType: 'json',
success: function(json) {
if (json.length)
{
for (error in json)
$('#sendwithorder_errors_list').append('<li>'+json[error]+'</li>');
$('#sendwithorder_errors').slideDown();
displayWaitingAjax('none', '');
}
else
{
displayWaitingAjax('none', '');
if(is_submit==1)
{
$('#form').submit();
alert("sam");
}
//$('#show_carrier, .SE_SubmitRefreshCard span').show();
//$('.SE_SubmitRefreshCard').fadeIn('fast');
//$('#SE_AjaxSuccess').show().delay(3000).fadeOut();
//location.reload(true);
}
}
});
ajaxQueries.push(query);
return false;
}
Even "sam" is alerted but the form does not submit. Instead, I get the following warning on submit:
body.scrollLeft is deprecated in strict mode. Please use 'documentElement.scrollLeft' if in strict mode and 'body.scrollLeft' only if in quirks mode.
Even though there is a javascript warning, but this should not hinder form submit.
Your form cannot be submitted since you call e.preventDefault(); at every submit.
Try reorganizing the logic in submit() to either preventDefault() and go through your checks, or do nothing and let the form be submitted.
I did it like this and the code worked:
var js_submit = false;
function PS_SL_HandleEvent() {
$(document).ready(function () {
$('#form').removeAttr('onsubmit').submit(function (e) {
if (js_submit == false) {
if (acceptCGV()) {
e.preventDefault();
if ($('#send_order_form input[type="radio"]:checked').val() == "") {
resetAjaxQueries();
delSelection(1);
} else {
var carrierClass = $('input:radio[name="order_choose"]:checked').attr('class');
carrierClass = carrierClass.replace("carrier_", "");
var radio_selector = '.delivery_options_address input[value="' + carrierClass + ',"], #carrierTable input[value="' + carrierClass + '"]';
$(radio_selector).attr('checked', 'checked');
resetAjaxQueries();
saveSelection(1);
}
} else
e.preventDefault();
}
});
});
}
function saveSelection(is_submit) {
$('#sendwithorder_errors').slideUp();
$('#sendwithorder_errors_list').children().remove();
//displayWaitingAjax('block', SL_RedirectTS);
//$('.SE_SubmitRefreshCard').fadeOut('fast');
var query = $.ajax({
type: 'POST',
headers: {
"cache-control": "no-cache"
},
url: baseDir + 'modules/sendwithorder/ajax.php' + '?rand=' + new Date().getTime(),
data: 'method=saveSelection&' + 'order_choose=' + $('#send_order_form input[name=order_choose]:checked').val(),
dataType: 'json',
success: function (json) {
if (json.length) {
for (error in json)
$('#sendwithorder_errors_list').append('<li>' + json[error] + '</li>');
$('#sendwithorder_errors').slideDown();
displayWaitingAjax('none', '');
} else {
displayWaitingAjax('none', '');
if (is_submit == 1) {
js_submit = true;
$('#form').submit();
}
//$('#show_carrier, .SE_SubmitRefreshCard span').show();
//$('.SE_SubmitRefreshCard').fadeIn('fast');
//$('#SE_AjaxSuccess').show().delay(3000).fadeOut();
//location.reload(true);
}
}
});
ajaxQueries.push(query);
return false;
}

Using another variable in order to initialize the knockout observables

I am just wondering why one has to use a temporary variable "that" (initialized with the currently allocated object i.e. "this") in the script below:
$(document).ready(function() {
function ChatViewModel() {
var that = this;
that.userName = ko.observable('');
that.chatContent = ko.observable('');
that.message = ko.observable('');
that.messageIndex = ko.observable(0);
that.activePollingXhr = ko.observable(null);
var keepPolling = false;
that.joinChat = function() {
if (that.userName().trim() != '') {
keepPolling = true;
pollForMessages();
}
}
function pollForMessages() {
if (!keepPolling) {
return;
}
var form = $("#joinChatForm");
that.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
}));
$('#message').focus();
}
that.postMessage = function() {
if (that.message().trim() != '') {
var form = $("#postMessageForm");
$.ajax({url: form.attr("action"), type: "POST",
data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
error: function(xhr) {
console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
}
});
that.message('');
}
}
that.leaveChat = function() {
that.activePollingXhr(null);
resetUI();
this.userName('');
}
function resetUI() {
keepPolling = false;
that.activePollingXhr(null);
that.message('');
that.messageIndex(0);
that.chatContent('');
}
}
//Activate knockout.js
ko.applyBindings(new ChatViewModel());
});
Why can't I just use "this"? Can anyone please explain?
this always refers to the object that is in scope when the call has been made, and this can change depending on your code. If you want it to still be your object in a sub-function, then assigning it to a variable that won't change in value gets around this issue.
This refers to the owner.
You can rewrite your code like this :
$(document).ready(function() {
function ChatViewModel() {
var that = this;
this.userName = ko.observable('');
this.chatContent = ko.observable('');
this.message = ko.observable('');
this.messageIndex = ko.observable(0);
this.activePollingXhr = ko.observable(null);
var keepPolling = false;
this.joinChat = function() {
if (that.userName().trim() != '') {
keepPolling = true;
pollForMessages();
}
}
function pollForMessages() {
if (!keepPolling) {
return;
}
var form = $("#joinChatForm");
this.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
}));
$('#message').focus();
}
this.postMessage = function() {
if (that.message().trim() != '') {
var form = $("#postMessageForm");
$.ajax({url: form.attr("action"), type: "POST",
data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
error: function(xhr) {
console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
}
});
that.message('');
}
}
this.leaveChat = function() {
that.activePollingXhr(null);
resetUI();
that.userName('');
}
function resetUI() {
keepPolling = false;
that.activePollingXhr(null);
that.message('');
that.messageIndex(0);
that.chatContent('');
}
}
//Activate knockout.js
ko.applyBindings(new ChatViewModel());
//fixing bracet
});
Check this link: http://www.quirksmode.org/js/this.html

Function as a KnockoutJS observable

I have the following script (see below). I have two questions regarding it:
1.What does the following line mean in the context of Knockoutjs?
ko.observable(null);
2.How can I invoke a function not yet defined as in here:
that.activePollingXhr(...
Here is the full script:
$(document).ready(function() {
function ChatViewModel() {
var that = this;
that.userName = ko.observable('');
that.chatContent = ko.observable('');
that.message = ko.observable('');
that.messageIndex = ko.observable(0);
that.activePollingXhr = ko.observable(null);
var keepPolling = false;
that.joinChat = function() {
if (that.userName().trim() != '') {
keepPolling = true;
pollForMessages();
}
}
function pollForMessages() {
if (!keepPolling) {
return;
}
var form = $("#joinChatForm");
that.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
}));
$('#message').focus();
}
that.postMessage = function() {
if (that.message().trim() != '') {
var form = $("#postMessageForm");
$.ajax({url: form.attr("action"), type: "POST",
data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
error: function(xhr) {
console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
}
});
that.message('');
}
}
that.leaveChat = function() {
that.activePollingXhr(null);
resetUI();
this.userName('');
}
function resetUI() {
keepPolling = false;
that.activePollingXhr(null);
that.message('');
that.messageIndex(0);
that.chatContent('');
}
}
//Activate knockout.js
ko.applyBindings(new ChatViewModel());
});
ko.observable(null); creates an observable with a value of null. Nothing different than ko.observable(5);, where the value would be 5.
I see that you're using the that.activePollingXhr observable by passing it the result of an ajax call. However, this call is asynchronous and $.ajax doesn't return the data it got from the server, but rather a jquery deferred. You need to use that.activePollingXhr insude the success callback. Here's is how your code might look like:
$.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
that.activePollingXhr(messages); // <-- Note where the call to activePollingXhr is
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
});
As for the comment under your question: that.activePollingXhr is defined as that.activePollingXhr = ko.observable(null); - an observable with value of null.
That just initializes an observable with null as the initial value.
If you need to invoke a function that is an observable, just add a second set of parenthesis.
that.activePollingXhr()()

Categories

Resources