I'm using the excellent answer to this question to convert svg images into inline html.
The function looks through the container or body, finds each .svg
image
and converts them to inline html.
However, it uses a $.get()
call to retrieve the svg files
which makes the function asynchronous.
I'd like to convert the function to a promise so that I can wait for it to complete before running other things (like adding or removing classes to the new inline html etc)
My current attempt looks like this:
util.convertSvgImages = function(container) {
var deferred = Q.defer();
container = typeof container !== 'undefined' ? container : $("body");
var getsToComplete = jQuery('img.svg', container).length; // the total number of $get.() calls to complete within the $.each() loop
var getsCompleted = 0; // the current number of $get.() calls completed (counted within the $get.() callback)
jQuery('img.svg', container).each(function(index) {
var img = jQuery(this);
var imgID = img.attr('id');
var imgClass = img.attr('class');
var imgURL = img.attr('src');
jQuery.get(imgURL, function(data) {
getsCompleted += 1;
var svg = jQuery(data).find('svg'); // Get the SVG tag, ignore the rest
if (typeof imgID !== 'undefined') { // Add replaced image's ID to the new SVG
svg = svg.attr('id', imgID);
}
if (typeof imgClass !== 'undefined') {
svg = svg.attr('class', imgClass + ' replaced-svg'); // Add replaced image's classes to the new SVG
}
svg = svg.removeAttr('xmlns:a'); // Remove any invalid XML tags as per http://validator.w3.org
svg.attr('class', img.attr("data-svg_class") + " svg"); // add class to svg object based on the image data-svg_class value
$('rect', svg).attr("stroke", "").attr("fill", "");
$('line', svg).attr("stroke", "").attr("fill", "");
$('path', svg).attr("stroke", "").attr("fill", "");
$('polyline', svg).attr("stroke", "").attr("fill", "");
$('polygon', svg).attr("stroke", "").attr("fill", "");
$('circle', svg).attr("stroke", "").attr("fill", "");
img.replaceWith(svg); // Replace image with new SVG
if (getsCompleted === getsToComplete){
deferred.resolve('OK');
}
}, 'xml');
});
return deferred.promise;
};
What is the best way to use promises within asynchronous calls inside an $.each()
loop ? Using q.all()
?