JPlayer - Help replacing image filename with mp3 filename using JS - javascript

I'm trying to use the following code to play a song in JPlayer using the Getsong.php, that plays fine, the problem I'm having is with the song image(or album photo), I need to check a directory to see if that image file exists, and if it does, show it, otherwise show the "no_img_file.jpg file.
I do this by checking the domain path / user_id folder / and the song_filename .jpg
But I can't get it to work.
Please HELP
$(document).ready(function(){
$("#jquery_jplayer_1").jPlayer({
ready: function () {
var data = $.ajax({
url: "getsong.php",
async: false
}).responseText;
var string = data.split('|');
$(this).jPlayer("setMedia", {
mp3: string[0]
}).jPlayer("play");
$('ol#artist').html(string[1]);
$('ol#songname').html(string[2]);
$('ol#filename').html(string[3]);
},
ended: function (event) {
var data = $.ajax({
url: "getsong.php",
async: false
}).responseText;
var string = data.split('|');
$(this).jPlayer("setMedia", {
mp3: string[0]
}).jPlayer("play");
$('ol#artist').html(string[1]);
$('ol#songname').html(string[2]);
$('ol#filename').html(string[3]);
},
swfPath: "js",
supplied: "mp3"
});
});
/////////////////////////////
function checkImage(src) {
var img = new Image();
img.onload = function() {
// code to set the src on success
$('#image-test').css('background', 'url(' + src + ') no-repeat 50% 100%');
};
img.onerror = function() {
// doesn't exist or error loading
//alert('no image');
checkImage('http://mydomain.com/images/no_img_file.jpg');
};
img.src = src; // fires off loading of image
}
//checkImage('http://www.google.com/images/logo_sm.gif');
// uncomment to test error function
checkImage('http://mydomain.com/mp3/'<?php echo $user_id; ?>'/'.string[3]);

Instead of trying to perform this check on the client, I would perdonally recommend recommend handling it at the server end and save yourself (and USERS!) that extra request.
The simplest means (add your own interpretational logic and validation later) would be to have a file called something like "coverart.php" and when you try to get the cover art make a request to coverart.php?name=MY_COVER_ART_FILE
Then within coverart.php:
$strCoverName = $_GET['name'];
$strArtDir = 'YOUR_COVER_ART_DIRECTORY';
$strCommonExtenstion = '.jpg';
$strFile = $strArtDir.$strCoverName.$strCommonExtension;
header('Content-Type: image/jpeg');
if(is_file($strFile)) {
readfile($strFile);
} else {
readfile($strArtDir.'no_img_file'.$strCommonExtension);
}
This is a KISS way of achieving what you want, I'd recommend you look further in to the various ways of achieving this however but along similar lines

Related

How to check when srcset images have been loaded when appending them via Ajax

I'm appending the text and images of a php-page via Ajax to a container and showing it after all the images have been loaded. This works perfectly If I'm using only src, but not if I'm using srcset.
So far, I'm using this snippet of code, to check if all the ajaxed src-tagged images have been loaded. But of course, it's not actually working because it's checking the src and not the srcset.
$.fn.imagesLoaded = function () {
var $imgs = this.find('img[src!=""]');
if (!$imgs.length) {
return $.Deferred().resolve().promise();
}
var dfds = [];
$imgs.each(function(){
var dfd = $.Deferred();
dfds.push(dfd);
var img = new Image();
img.onload = function(){
dfd.resolve();
}
img.onerror = function(){
dfd.resolve();
}
img.src = this.src;
});
return $.when.apply($,dfds);
}
This is my Ajax code:
$.ajax({
cache: false,
url: "somefile.php",
success: function(data) {
$("body").prepend(data).imagesLoaded().then(function(){
// show the images etc.
})
)}
The expected result should be, that the checking if all images have been loaded should also work with srcset not only with src. The actual result is, that it's just not respecting the imagesLoaded().

Cascading jQuery Image Fallback

I'm looking to dynamically load in an image:
<img data-src="test01">
And then use jQuery to take the data-src and then load in the image associated with that name, PLUS the extension. If THAT extension fails, then move onto the next extension, so on and so on until we get to the bottom when I just load in a default image. But I don't know how to check if there's an error AFTER I've set the image's attr once. Here's the loop I have so far, and I'm getting ".error not a function"
$("img").each(function(){
var newSource = $(this).data('src').toString();
$(this).attr('src', 'images/'+newSource+'.gif').error(function(){
$(this).attr('src', 'images/'+newSource+'.jpg').error(function(){
$(this).attr('src', 'images/'+newSource+'.png').error(function(){
$(this).attr('src', 'images/default.jpg');
});
});
});
});
The reason I'm doing this is because we have a database that holds the title of the image only, yet, over the years, different people have uploaded different image formats to the site, and we want to be able to load all of them on the page, sans extension, and then loop through each extension until we find a file that exists, and if not, default to a pre-set hard coded image URL
One alternative would be to do a HEAD request for the urls. A benefit of a HEAD request is that it just tries to get headers for the endpoint, without trying to return data, so it can be super fast. In your case, it could be a quick check to see if an image url is valid or not.
function changeTheSrcIfTheUrlIsValid ( element, url ) {
return $.ajax({
url: url,
type: 'HEAD',
success: function(){
//got a success response, set the src
element.src = url;
}
});
}
$("img").each(function(){
var img = this;
var newSource = img.getAttribute('src');
//check for a gif
changeTheSrcIfTheUrlIsValid( img, 'images/'+ newSource +'.gif' )
.then(null, function(){
//error handler, try jpg next
changeTheSrcIfTheUrlIsValid( img, 'images/'+ newSource +'.jpg' )
.then(null, function(){
//error handler, try png next
changeTheSrcIfTheUrlIsValid( img, 'images/'+ newSource +'.png' )
.then(null, function(){
//error handler, use default
img.src = 'images/default.jpg';
});
});
});
});
Can use a Promise and a new Image() each time. The promise gets resolved or rejected in the onload or onerror of the new Image.
Then there is a chain of catch() to try various extensions and finally set a default noImageUrl if all else fail
Something like:
function setImageSrc(src, ext, el){
return new Promise(resolve, reject){
var url = 'images/'+src+ ext;
var img = new Image()
img.src = url
img.onerror = reject;
img.onload = function(){
el.src = url; // set src of current element in dom
resolve(url)
}
}
}
$("img").each(function(){
var newSource = $(this).data('src').toString();
var self = this
setImageSrc(newSource, '.jpg', self)
.catch(setImageSrc(newSource, '.png', self))
.catch(setImageSrc(newSource, '.gif', self))
.catch(function(){
self.src = 'noImageUrl';
});
});

First Image not being loaded

I have the following code snippet which is called on the success of the image uploading procedure.
success(data){
$avatar.attr('src', "/images/common/loading.gif");
$avatar.attr('src', data.url);
}
Here $avatar is the container for an image tag. The idea is to load this image with loading.gif until data.url is loaded successfully. Here data.url may contain a large size image which takes long time to load.
The problem is loading.gif is never loaded to the image container until I use setTimeOut as:
success(data){
$avatar.attr('src', "/images/common/loading.gif");
setTimeOut(function(){
$avatar.attr('src', data.url);
},100);
}
Can anyone suggest me some different approach rather than to use setTimeOut?
Showing uploaded image is more important than showing loader image But if you are doing it your way, go with the onload-event.
Also listen onerror event if loader image fails, or else avatar image will never get loaded!
success(data) {
var loader = new Image();
var loadMainImage = function() {
var mainImage = new Image();
mainImage.onload = function() { //avatar is loaded!
$avatar.attr('src', this.src);
}
mainImage.src = data.url;
}
loader.onload = function() { //loader is loaded!
$avatar.attr('src', this.src);
loadMainImage();
};
loader.onerror = mainImage; //loader is failed!
loader.src = "/images/common/loading.gif";
}
I think you can use beforeSend to handle async promises

asynchronous processing (callbacks in libraries + controllers)

My code is working fine, but I do not like at all.
I would like to split one file into two files, one containing webServices and another one with a controller.
My file do something like this:
File: Validacion.js (controller)
// Load next view
var MainView = Alloy.createController('index').getView('tabGroup');
// this a function call when I click a button "validar" on ValidaciĆ³n View.
function btnClick(){
var url = 'www.cocoloco.com/whatever';
var webService = Ti.Network.createHTTPClient({
onload: function(e){
// open new view
MainView.open();
// close actual view
$.tabValidacion.close();
$.tabValidacion = null;
},
onerror: function(e){
alert('onerror: ' + e.error);
},
timeout: 5000
});
webService.open('POST', url);
webService.send();
}
But I would like to do something like this below (divided in two files: webServices.js -library- and validation.js -controller-).
The problem is that I always have the message "error" because I pass throught "success = webServices.protocol();" but as far as it is "asynchronous" it doesn't stop and goes to following line of code without having server answer yet.
File: webServices.js (library)
exports.protocol = function(){
var url = 'www.cocoloco.com/whatever';
var webService = Ti.Network.createHTTPClient({
onload: function(e){
// on sucess exit with true
return(true);
},
onerror: function(e){
alert('onerror: ' + e.error);
// on sucess exit with false
return(false);
},
timeout: 5000
});
webService.open('POST', url);
webService.send();
}
File: Validacion.js (controller)
// Load next view
var MainView = Alloy.createController('index').getView('tabGroup');
function btnClick(){
var webServices = require('webServices');
var success = webServices.protocol();
if(success){
// open new view
MainView.open();
// close actual view
$.tabValidacion.close();
$.tabValidacion = null;
}else{
alert('error');
}
}
I have thought about two possible options:
Using promises.
Fire a new event on "success" and use that event run another callback function (in this function I open the new view and close the previous one).
I do not know how difficult is this as far as the event is one file (library) and the callback function in another one (controller)
I have never used any of these solutions, so I do not know how "good" they are.
Any suggestion?
The callback approach works fine in most cases. Just pass the function as a parameter, you can return an object containing anything from a success message to responseText and status.
webServices.js
exports.protocol = function(callback) {
var url = 'www.cocoloco.com/whatever';
var webService = Ti.Network.createHTTPClient({
onload: function(e){
// on success call callback
callback({ success: true });
},
onerror: function(e){
// on error call callback
callback({ success: false });
},
timeout: 5000
});
webService.open('POST', url);
webService.send();
}
Validacion.js
function btnClick(){
var webServices = require('webServices');
webServices.protocol(function(e) {
if(e.success){
// open new view
MainView.open();
// close actual view
$.tabValidacion.close();
$.tabValidacion = null;
} else {
alert('error');
}
});
}

Load download in browser background, tell when finished

I'm trying to get a file which takes a good few seconds to load in the background, so I can display a spinner at the same time.
I'm currently trying with an iframe in the background, and this works but I'm not sure how I can be notified when it's finished loading (so I can remove the spinner).
Any good ways of doing this? Any better solution than an iframe?
Here's my code so far:
<script>
$(document).ready(function() {
var link = $('.generate-pdf');
link.click(function(e) {
e.preventDefault();
var spinner = $("<img src='/assets/images/ajax-loader.gif' />");
var iframe = $('<iframe src="' + link.attr('href') + '" style="height:0;width:0;visibility;hidden;display:none;"></iframe>');
link.before(spinner);
link.before(iframe);
});
})
</script>
According to this site, given that my Content-disposition is attachment I can't guarantee to receive any events. Can I poll any properties on the iframe to find out?
Have you tried
iframe.load(function(){
log("done");
})
In the end, I had to do this by contacting the server, and seeing if the file had been sent to the browser. I'd still like to see a pure client-based implementation.
Thankfully the download was generated with PHP so this was ok.
<script>
$(document).ready(function() {
var link = $('.generate-pdf');
link.click(function(e) {
e.preventDefault();
var spinner = $("<div class='spinner'><img src='/assets/images/ajax-loader.gif' /><span>Your PDF is being generated...</span></div>");
var downloadKey = new Date().getTime();
var iframe = $('<iframe src="' + link.attr('href') + '&downloadKey='+downloadKey+'" style="height:0;width:0;visibility;hidden;display:none;" onload="alert(\'hello\')"></iframe>');
link.before(spinner);
link.before(iframe);
var hasFinished = function(downloadKey, callback) {
var that = this;
$.ajax({
url: "index.php?controller=is-download-finished&downloadKey=" + downloadKey,
success: function(data) {
if (data) {
callback();
} else {
setTimeout(function() {
that(downloadKey, callback);
}, 1000);
}
}
})
};
hasFinished(downloadKey, function() {
spinner.remove();
iframe.remove();
});
});
})
</script>
The extra request just returns JSON true or false.

Categories

Resources