I am new to JavaScript and I have an html page that loads the source code from this page into a given div and I am using the code provided by the user rob-w which works fine but my main goal is to learn how to show only part of the returned text starting at a given value and ending at a given value after that
popup.js
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.action == "getSource") {
message.innerText = request.source;
}
});
function onWindowLoad() {
var message = document.querySelector("#message");
chrome.tabs.executeScript(null, {
file: "getPagesSource.js"
}, function() {
// If you try and inject into an extensions page or the webstore/NTP you'll get an error
if (chrome.runtime.lastError) {
message.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
}
});
}
window.onload = onWindowLoad;
getPagesSource.js
// #author Rob W <http://stackoverflow.com/users/938089/rob-w>
// Demo: var serialized_html = DOMtoString(document);
function DOMtoString(document_root) {
var html = '',
node = document_root.firstChild;
while (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
html += node.outerHTML;
break;
case Node.TEXT_NODE:
html += node.nodeValue;
break;
case Node.CDATA_SECTION_NODE:
html += '<![CDATA[' + node.nodeValue + ']]>';
break;
case Node.COMMENT_NODE:
html += '<!--' + node.nodeValue + '-->';
break;
case Node.DOCUMENT_TYPE_NODE:
// (X)HTML documents are identified by public identifiers
html += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
break;
}
node = node.nextSibling;
}
return html;
}
chrome.runtime.sendMessage({
action: "getSource",
source: DOMtoString(document)
});
I have played around with many DOM functions and getBy functions but I have not been able to apply them correctly and I don't think they are exactly what I am after. If someone can point me in the right direction it would be appreciated
My solution uses String.prototype.match() to get an array containing all values between strings x and y but not including strings x and y.
function getStringsBetweenXandY(html) {
var matches = html.match(/x[\s\S]*?y/g), i = matches.length;
while(i--) {
matches[i] = matches[i].match(/x([\s\S]*?)y/)[1];
}
return matches;
}
var array = getStringsBetweenXandY(html);
You need to make sure that strings x and y contain backslashes where necessary.
matches will contain an array or an array-like object containing all of the html fragments you are looking for
Related
I got this code here in a JS file, where I've put two console.log(), one at the beginning and one at the end, to see why I'm having problems targeting the with a specific ID / class. Now I see that the console.log() at the end loads before the one in the beginning. Even when I place a console.log() outside of the file underneath the <script> tag which loads this JS file, it loads before the JS file, which doesn't make any sense to me. How can I fix this problem?
/*!
* jquery.instagramFeed
*
* #version 1.2.7
*
* #author Javier Sanahuja Liebana <bannss1#gmail.com>
* #contributor csanahuja <csanahuja10#gmail.com>
*
* https://github.com/jsanahuja/jquery.instagramFeed
*
*/
(function($){
var defaults = {
'host': "https://www.instagram.com/",
'username': 'username',
'tag': '',
'container': '#instagram',
'display_profile': true,
'display_biography': true,
'display_gallery': true,
'display_igtv': false,
'get_data': false,
'callback': null,
'styling': true,
'items': 8,
'items_per_row': 4,
'margin': 0.5,
'image_size': 640
};
var image_sizes = {
"150": 0,
"240": 1,
"320": 2,
"480": 3,
"640": 4
};
var escape_map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
'`': '`',
'=': '='
};
function escape_string(str){
return str.replace(/[&<>"'`=\/]/g, function (char) {
return escape_map[char];
});
}
$.instagramFeed = function(opts){
//console log at the beginning of the function
console.log("Beginning instagramFeed");
var options = $.fn.extend({}, defaults, opts);
if(options.username == "" && options.tag == ""){
console.error("Instagram Feed: Error, no username or tag found.");
return false;
}
if(typeof options.get_raw_json !== "undefined"){
console.warn("Instagram Feed: get_raw_json is deprecated. See use get_data instead");
options.get_data = options.get_raw_json;
}
if(!options.get_data && options.container == ""){
console.error("Instagram Feed: Error, no container found.");
return false;
}
if(options.get_data && options.callback == null){
console.error("Instagram Feed: Error, no callback defined to get the raw json");
return false;
}
var is_tag = options.username == "",
url = is_tag ? options.host + "explore/tags/"+ options.tag + "/" : options.host + options.username + "/";
$.get(url, function(data){
try{
data = data.split("window._sharedData = ")[1].split("<\/script>")[0];
}catch(e){
console.error("Instagram Feed: It looks like the profile you are trying to fetch is age restricted. See https://github.com/jsanahuja/InstagramFeed/issues/26");
return;
}
data = JSON.parse(data.substr(0, data.length - 1));
data = data.entry_data.ProfilePage || data.entry_data.TagPage;
if(typeof data === "undefined"){
console.error("Instagram Feed: It looks like YOUR network has been temporary banned because of too many requests. See https://github.com/jsanahuja/jquery.instagramFeed/issues/25");
return;
}
data = data[0].graphql.user || data[0].graphql.hashtag;
if(options.get_data){
options.callback(data);
return;
}
//Setting styles
var styles = {
'profile_container': "",
'profile_image': "",
'profile_name': "",
'profile_biography': "",
'gallery_image': ""
};
if(options.styling){
styles.profile_container = " style='text-align:center;'";
styles.profile_image = " style='border-radius:10em;width:15%;max-width:125px;min-width:50px;'";
styles.profile_name = " style='font-size:1.2em;'";
styles.profile_biography = " style='font-size:1em;'";
var width = (100 - options.margin * 2 * options.items_per_row)/options.items_per_row;
styles.gallery_image = " style='margin:"+options.margin+"% "+options.margin+"%;width:"+width+"%;float:left;'";
}
var html = "";
//Displaying profile
if(options.display_profile){
html += "<div class='instagram_profile'" +styles.profile_container +">";
html += "<img class='instagram_profile_image' src='"+ data.profile_pic_url +"' alt='"+ (is_tag ? data.name + " tag pic" : data.username + " profile pic") +"'"+ styles.profile_image +" />";
if(is_tag)
html += "<p class='instagram_tag'"+ styles.profile_name +"><a href='https://www.instagram.com/explore/tags/"+ options.tag +"' rel='noopener' target='_blank'>#"+ options.tag +"</a></p>";
else
html += "<p class='instagram_username'"+ styles.profile_name +">#"+ data.full_name +" (<a href='https://www.instagram.com/"+ options.username +"' rel='noopener' target='_blank'>#"+options.username+"</a>)</p>";
if(!is_tag && options.display_biography)
html += "<p class='instagram_biography'"+ styles.profile_biography +">"+ data.biography +"</p>";
html += "</div>";
}
//image size
var image_index = typeof image_sizes[options.image_size] !== "undefined" ? image_sizes[options.image_size] : image_sizes[640];
if(options.display_gallery){
if(typeof data.is_private !== "undefined" && data.is_private === true){
html += "<p class='instagram_private'><strong>This profile is private</strong></p>";
}else{
var imgs = (data.edge_owner_to_timeline_media || data.edge_hashtag_to_media).edges;
max = (imgs.length > options.items) ? options.items : imgs.length;
html += "<div class='instagram_gallery'>";
for(var i = 0; i < max; i++){
var url = "https://www.instagram.com/p/" + imgs[i].node.shortcode,
image, type_resource, caption, date, likes, comments;
switch(imgs[i].node.__typename){
case "GraphSidecar":
type_resource = "sidecar"
image = imgs[i].node.thumbnail_resources[image_index].src;
date = new Date(imgs[i].node.taken_at_timestamp * 1000);
likes = imgs[i].node.edge_media_preview_like.count;
comments = imgs[i].node.edge_media_to_comment.count;
break;
case "GraphVideo":
type_resource = "video";
image = imgs[i].node.thumbnail_src
break;
default:
type_resource = "image";
image = imgs[i].node.thumbnail_resources[image_index].src;
date = new Date(imgs[i].node.taken_at_timestamp * 1000);
likes = imgs[i].node.edge_media_preview_like.count;
comments = imgs[i].node.edge_media_to_comment.count;
}
console.log(date);
console.log(likes);
console.log(comments);
if(
typeof imgs[i].node.edge_media_to_caption.edges[0] !== "undefined" &&
typeof imgs[i].node.edge_media_to_caption.edges[0].node !== "undefined" &&
typeof imgs[i].node.edge_media_to_caption.edges[0].node.text !== "undefined" &&
imgs[i].node.edge_media_to_caption.edges[0].node.text !== null
){
caption = imgs[i].node.edge_media_to_caption.edges[0].node.text;
}else if(
typeof imgs[i].node.accessibility_caption !== "undefined" &&
imgs[i].node.accessibility_caption !== null
){
caption = imgs[i].node.accessibility_caption;
}else{
caption = (is_tag ? data.name : data.username) + " image " + i;
}
html += "<a id='instagramID" + i + "' class='instagramimg instagram-" + type_resource + "' rel='noopener' target='_blank'>";
html += "<img class='instagramicon' src='https://cdn.shopify.com/s/files/1/0278/9644/7113/files/instagram-icon.svg?v=1592246117' alt='instagramicon'>";
html += "<div class='instagramhover'></div>";
html += "<img src='" + image + "' alt='" + escape_string(caption) + "'"/* + styles.gallery_image*/ +" />";
html += "</a>";
}
}
}
if(options.display_igtv && typeof data.edge_felix_video_timeline !== "undefined"){
var igtv = data.edge_felix_video_timeline.edges,
max = (igtv.length > options.items) ? options.items : igtv.length
if(igtv.length > 0){
html += "<div class='instagram_igtv'>";
for(var i = 0; i < max; i++){
html += "<a href='https://www.instagram.com/p/"+ igtv[i].node.shortcode +"' rel='noopener' target='_blank'>";
html += "<img src='"+ igtv[i].node.thumbnail_src +"' alt='"+ options.username +" instagram image "+ i+"'"+styles.gallery_image+" />";
html += "</a>";
}
html += "</div>";
}
}
$(options.container).html(html);
}).fail(function(e){
console.error("Instagram Feed: Unable to fetch the given user/tag. Instagram responded with the status code: ", e.status);
});
return true;
};
// Ending of the code
console.log("Ending instagramFeed");
})(jQuery);
This function gets called like this in the html part. Also here, the console.log("before instagramFeed.JS"); loads together with console.log("after instagramFeed.JS");, and after that I receive the
console.log(date);
console.log(likes);
console.log(comments);
which are inside the for loop of the function.
<script src="{{ 'jquery.instagramFeed.js' | asset_url }}"></script>
<div id="instagram"></div>
<script>
console.log("before instagramFeed.JS");
(function($){
$(window).on('load', function(){
$.instagramFeed({
'username': 'username',
'container': "#instagram",
'display_profile': false,
'display_biography': false,
'display_gallery': true,
'callback': null,
'styling': true,
'items': 10,
'items_per_row': 5,
'margin': 0.2
});
});
})(jQuery);
console.log("after instagramFeed.JS");
</script>
Your code is executed in the following order:
first snippet (definition of instagramFeed plugin) is executed during page load. console.log statements outside of that plugin are executed as well.
window is loaded (all script tag contents are read and executed), your window load handler kicks in. It calls your instagramFeed function the way you set it in the second snippet. before/after instagramFeed.JS logs are executed here. instagramFeed function starts a network call the result of which is processed after the load handler finishes running.
network call response is processed. comments, likes and date are logged at this stage.
As a result, everything is working as expected if I understand the purpose correctly.
UPD: to use the elements generated by network call response handler (provided you have an opportunity to edit the plugin code directly) you can add a function into options object, say onImageElementsCreated and call it after the loop in the plugin. Then you can provide your function as another option in the second snippet.
I can't say this with 100% certainty, as I haven't run the code.
However, I think the line console.log("Ending instagramFeed"); is being run before the line console.log("Beginning instagramFeed");, because it's outside the function $.instagramFeed = function(opts).
The function is created, then the ending log line is called, then something is calling the function, then the beginning log line is called.
Where in your code do you call $.instagramFeed()?
I'm using postman to test the following, later it will be automated but that's not the issue.
I'm requesting data from an XML based API and need to use the same data to send to a different API in XML format.
I've already figured out that I need to convert the XML to a JSON format in order to save it in a var. Which works.
However, the issue that I have is that this process creates extra characters in my data, in the form of: [{"$":
When I then continue to convert it back to XML (using the full function below), it doesn't work and I end up with an XML code with all over it. Which isn't accepted in the last post to the XML Api.
I want to achieve to remove all occurences of and in the XML var. But I think that I will need to get rid of the in the first step. [{"$":
I've already found a function (.replace) which removes it, but only the first occurence
Function JSON2XML
function json2xml(o, tab) {
var toXml = function(v, name, ind) {
var xml = "";
if (v instanceof Array) {
for (var i=0, n=v.length; i<n; i++)
xml += ind + toXml(v[i], name, ind+"\t") + "\n";
}
else if (typeof(v) == "object") {
var hasChild = false;
xml += ind + "<" + name;
for (var m in v) {
if (m.charAt(0) == "#")
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
else
hasChild = true;
}
xml += hasChild ? ">" : "/>";
if (hasChild) {
for (var m in v) {
if (m == "#text")
xml += v[m];
else if (m == "#cdata")
xml += "<![CDATA[" + v[m] + "]]>";
else if (m.charAt(0) != "#")
xml += toXml(v[m], m, ind+"\t");
}
xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">";
}
}
else {
xml += ind + "<" + name + ">" + v.toString() + "</" + name + ">";
}
return xml;
}, xml="";
for (var m in o)
xml += toXml(o[m], m, "");
return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
}
// Get the JSON from environment and parse it
let targetJSON = JSON.parse(pm.environment.get('firstTarget'));
// Convert it to XML String
let xmlString = json2xml(targetJSON);
// You can check the console if your string is correct
console.log(xmlString);
// Store the XML string as a variable and use this variable in your request body
pm.environment.set('targetXML', xmlString);
let resp = xml2Json(pm.response.text()),
targetData = resp.eExact.Accounts;
console.log({ targetData });
pm.environment.set('firstTarget', JSON.stringify(targetData));
This is the code which creates the [{"$":
I am having difficulty figuring out the best method of doing the following. I am getting anywhere from 0 to x number of string names, ie: Zillow, Trulia. What I am wanting to do is associate an image with those string names and then display them into a list. I am attempting to do a switch statement, but am unsure if that will work for more than 1 condition...please correct me if I am wrong.
So for instance, the variable list is holding two items (Zillow/Trulia), how can I check ky split function variable for multiple values and then add the output: $('#review-icon-list').wrapInner('<li class="review-icon">' + zillowImg + '</li>');
Right now my switch case is throwing an unexpected token error, but I do not think I am using the right method anyways. Does anyone know how I would do this? Would I be doing some sort of loop and if so, how would I structure it?
var reviewSiteNames = 'Zillow,Trulia';
reviewSiteNames = reviewSiteNames.split(',');
console.log(reviewSiteNames);
var zillowImg = '<img src="https://s3.amazonaws.com/retain-static/www/zillow.jpg" alt="Zillow">';
var truliaImg = '<img src="https://s3.amazonaws.com/retain-static/www/trulia.png" alt="Trulia">';
if (reviewSiteNames == '') {
$('#no-current-reviewSites').html('No review sites currently added')
}
/*else if (reviewSiteNames) {
$('#review-icon-list').wrapInner('<li class="review-icon"></li>');
}*/
switch (true) {
case (reviewSiteNames.indexOf('Zillow') >= 0):
$('#review-icon-list').wrapInner('<li class="review-icon">' + zillowImg + '</li>');
break;
case (reviewSiteNames.indexOf('Realtor.com') >= 0):
$('#review-icon-list').wrapInner('<li class="review-icon">' + realtorDotComImg + '</li>');
break;
case (reviewSiteNames.indexOf('Trulia') >= 0):
$('#review-icon-list').wrapInner('<li class="review-icon">' + truliaImg + '</li>');
default: return '';
};
New method of trying this. The only image that is displaying is the last if statement in the each function.
$.each(reviewSiteNames, function (index, value) {
if (reviewSiteNames.includes('Zillow')) {
$('#review-icon-current').wrapInner('<li class="review-icon">' + zillowImg + '</li>');
}
if (reviewSiteNames.includes('Trulia')) {
$('#review-icon-current').wrapInner('<li class="review-icon">' + truliaImg + '</li>');
}
//return (value !== 'three');
});
Here is how I would write what I understand from your code:
I think you want to check if some specific word are in the reviewSiteNames array to determine how to wrap the #review-icon-list element.
// Site names as a string
var reviewSiteNames = 'Zillow,Trulia';
// Site names as an array
reviewSiteNames = reviewSiteNames.split(',');
//console.log(reviewSiteNames);
// Some images used in li wrappers...
var zillowImg = '<img src="https://s3.amazonaws.com/retain-static/www/zillow.jpg" alt="Zillow">';
var truliaImg = '<img src="https://s3.amazonaws.com/retain-static/www/trulia.png" alt="Trulia">';
// If the array is empty
if (reviewSiteNames.length == 0) {
$('#no-current-reviewSites').html('No review sites currently added')
}
var myHTMLtoInsert = "";
// Check if specific values are in array
if( $.inArray('Zillow', reviewSiteNames) ){
myHTMLtoInsert += '<li class="review-icon">' + zillowImg + '</li>';
}
if( $.inArray('Realtor.com', reviewSiteNames) ){
myHTMLtoInsert += '<li class="review-icon">' + realtorDotComImg + '</li>';
}
if( $.inArray('Trulia',, reviewSiteNames) ){
myHTMLtoInsert += '<li class="review-icon">' + truliaImg + '</li>';
}
$('#review-icon-list').html(myHTMLtoInsert);
// The names:
var names = 'Zillow,Trulia';
names = names.split(',');
// The images mapper: an object that has names as keys and images as values
var images = {
"Zillow": '<img src="https://s3.amazonaws.com/retain-static/www/zillow.jpg" alt="Zillow">',
"Trulia": '<img src="https://s3.amazonaws.com/retain-static/www/trulia.png" alt="Trulia">'
};
// if names is empty: (names == '' won't work because names is no longer a string, it's an array now)
if (names.length === 0) {
$('#no-current-reviewSites').html('No review sites currently added')
}
// if there is names
else {
// loop through all names
names.forEach(function(name) {
// if this name got an image in the images mapper (images[name] !== undefined)
if(images[name]) {
// then do magic stuff with it
$('#review-icon-list').wrapInner('<li class="review-icon">' + images[name] + '</li>');
}
});
}
I hope this is usefull as I'm not quite sure what the goal really is.
I am writing code to generate thumbnails based on user selected image manipulation actions which may be multiple as choosen by user using lwip npm package module.
For multiple actions lwip provides batch function and then chaining other manipulating functions.The problem i faced is that user may select any combination of host of manipulating functions and it is too cumbersome to check for each and every combinations of selected actions.
So, i have generated the code dynamically as js code string which i need to execute as function without using eval that may compromise application security
Below is my code
'use strict';
(function(uploadhandler){
var lwip=require('lwip'),
imageSettingProvider=require('../data/imagesettingprovider'),
uploadFolder='public/uploads/',
imageManipulatorHelper=require('./imagemanipulationactions'),
manipulatedImage='';
uploadhandler.generateThumbnail=function(filePath,filename,ImageUploadSetting,fs){
// compound effects
var thumbnailPath='';
lwip.open(filePath, function(err, image) {
if (err) {
console.log(err);
}else{
imageSettingProvider.getImageSetting(ImageUploadSetting,{},function(err,imageSettings){
imageSettings.forEach(function(element,index,array){
thumbnailPath=uploadFolder + element.folderName + '/' + filename;
var imageAction=element.action;
if(imageAction.indexOf(',')>-1){
var imageManipulationActions=imageAction.split(',');
var manipulationHtml='';
manipulationHtml += 'image.batch()';
var actionHtml='';
imageManipulationActions.forEach(function(actionelement,actionindex,actionarray){
actionHtml += uploadhandler.PerformMultipleImageManipulation(actionelement,element,actionHtml);
});
manipulationHtml += actionHtml;
console.log('----------------------------------------------------------------------------------------------------------');
manipulationHtml += '.writeFile(thumbnailPath, function(err) { if (err) throw err;});';
console.log(manipulationHtml);
}
});
});
}
});
};
uploadhandler.PerformMultipleImageManipulation=function(imageAction,imageOpts,actionHtml){
switch (imageAction){
case "crop":
actionHtml = '.crop(' + imageOpts.width + ',' + imageOpts.height + ')';
break;
case "cropbycoordinates":
actionHtml = '.crop(' + imageOpts.cropLeftPos + ',' + imageOpts.cropTopPos + ',' + imageOpts.cropRightPos + ',' + imageOpts.cropBottomPos + ')';
break;
case "resize":
actionHtml = '.resize(' + imageOpts.width + ',' + imageOpts.height + ')';
break;
case "resizecrop":
actionHtml = '.resize(' + imageOpts.width + ',' + imageOpts.height + ')' + '.crop(' + imageOpts.width + ',' + imageOpts.height + ')';
break;
case "rotate":
actionHtml = '.rotate(' + imageOpts.rotateDegree + ',' + imageOpts.backgroundColor + ')';
break;
case "blur":
actionHtml = '.blur(' + imageOpts.blurVal + ')';
break;
case "scale":
actionHtml = '.scale(' + imageOpts.scaleVal + ')';
break;
case "mirror":
actionHtml = '.mirror(' + imageOpts.flipAxes + ')';
break;
case "fade":
actionHtml = '.fade(' + imageOpts.fadeVal + ')';
break;
}
return actionHtml;
};
})(module.exports);
Now when i log the manipulation variable to the console,it gives:
image.batch()
.resize(480,320)
.crop(480,320)
.rotate(75,white)
.writeFile(thumbnailPath, function(err) {
if (err) throw err;
});
Now i need to execute this above js code string as function to generate thumbnail image without using javascript eval function.
I have tried using following approach from sitepoint website:
// function we want to run
var fnstring = "runMe";
// find object
var fn = window[fnstring];
// is object a function?
if (typeof fn === "function") fn();
But it gives me with the error " ReferenceError: window is not defined
"
Please guide me to solve this problem.
Fetch the actions into global object and execute each one using each particular function's namespace.
var helper = {};
helper.b = function() {
console.log("foo");
}
helper.c = function() {
console.log("bar");
}
//execute them
function execute(key) {
try {
helper[key]();
} catch (e) {
throw new Error("Function does not exist");
}
}
execute("b");
execute("c");
execute("d");
If it helps, you could run a regex replace function.
Note: I have not tested this.
// if worried about security with eval, you may want to put functions in an object instead of using global
const myFunctions = {
runMe: function(){/* do stuff */},
runMe2: function(){/* do stuff */}
};
const allowedFuncs = ['runMe', 'runMe2'];
// or dynamic to entire object
const allowedFuncs = Object.keys(myFunctions);
str = str.replace(new RegExp('(''+allowedFuncs.join('|')+)\\((.*?)\\)', 'g'), (str, func, attrs) => {
// check allowed list for added security
if(allowedFuncs.includes(func)){
attrs = attrs.split(',');
myFunctions[func](...attrs); // 3 dots makes js expand array to params separated by camas
}
return str; // returning str replaces nothing
});
I seem to be unable to check if a audio file exists before it actions anything due to No Access-Control-Allow-Origin'.
Is it possible to have this and if so, how ?
pText[n] = any word, for example: and, about.
But googles API do not hold names, so I need to check if a name is added to the text, and if so, use a different source url.
// audio check
var audioCheck = $.get('https://ssl.gstatic.com/dictionary/static/sounds/de/0/' + pText[n] +'.mp3');
console.log(audioCheck);
I have also tried $.ajax but without success.
This is the full script so you can see what I am doing
function populate(pText) {
for(var n=0; n < pText.length; n++) {
// audio check
var audioCheck = $.get('https://ssl.gstatic.com/dictionary/static/sounds/de/0/' + pText[n] +'.mp3');
console.log(audioCheck);
// if(audioCheck) { link is live } else { link is 404 }
//console.log(pText[n]);
$('[name=p1_1]').append('<span id="s' + n + '"><audio id="a' + n + '" src="https://ssl.gstatic.com/dictionary/static/sounds/de/0/' + pText[n] +'.mp3" type="audio/mpeg"></audio>' + pText[n] + '</span> ');
}
}
And help would be appreciated :)
I have managed to resolve this using the simple method of onerror
Here is the full code :)
function populate(pText) {
var tex = '';
for(var n=0; n < pText.length; n++) {
//console.log(pText[n]);
tex += '<span id="s' + n + '"><audio id="a' + n + '" src="https://ssl.gstatic.com/dictionary/static/sounds/de/0/' + pText[n] +'.mp3" onerror="mediaerro(' + n + ',"' + pText[n] +'")" type=audio/mpeg"></audio>' + pText[n] + ' </span>';
}
$('[name=p1Text]').html(tex);
}
$(document).on("click", "span", function() {
$(this).find('audio')[0].play();
});
mediaerro = function(id, word) {
console.log(word);
switch(word) {
case "Rocko":
$('#a' + id).attr('src', 'http://domain.com/books/book1/words/rocko.mp3');
break;
case "Caroline":
$('#a' + id).attr('src', 'http://domain.com/books/book1/words/caroline.mp3');
break;
case "Benji":
$('#a' + id).attr('src', 'http://domain.com/books/book1/words/benji.mp3');
break;
}
};
Using the dynamic audio id and managed to create a function based on an error, which replaces the broken link with a new one where the new recording is. Works a treat!