Eval multiple javascript variables not working - javascript

I am trying to grab some text content (HTML comments) on the page and convert it into variables. The text content will be of the format:
I have constructed some Javascript that works up to a point, but will not go past the final variable declaration "var shorturl = ..."
Javascript code below:
$(document).ready(function() {
if (document.getElementById("ajax-gallery")) {
var shortcode = '<!-- [var module="gallery"; var id="1"; var type="single"; var data="only";] -->';
shortcode = shortcode.replace("<!-- [", "");
shortcode = shortcode.replace("] -->", "");
eval('shortcode');
var shorturl = "shorturl = " + module + "/shortcode_" + type + ".php?id=" + id + "&data=" + data;
eval('shorturl')
updateGallery(shorturl, "ajax-gallery");
}
});
I would have thought this would work, but apparently not. I know that eval is frowned upon but at present I cannot find a "nicer" method.

Related

Dynamically adding jquery into div

Apologies, I know there are a number of questions along the same lines and they've helped me a lot but I'm still falling at the final hurdle.
I'm trying to dynamically add some jQuery into a div using this:
function displayPage(position,page){
// position arrives looking something like '#pageW20' - ignore quotes
// page arrives looking something like 'pages/benefits.html' - ignore quotes
var pos = position.substring(1); // New variable without the '#' that appears in the first character of position
var myDiv = document.getElementById(pos); // Find the div, typically equates to a div id similar to 'pageW20'
var str = "<script type='text/javascript'>";
/* Build the script which typically looks like this:-
<script type='text/javascript'> $( "#pageB15" ).load( "pages/benefits.html", function(){openLetter()}); </script>
*/
str += '$( ' + '"' + position + '"' +' ).load(' + page + ', function(){openLetter()})';
str += '<';
str += '/script>';
alert(str); // Works to here, alert churns out expected output.
//$('"' + position + '"').append(str); // Tried this, end up with syntax error
myDiv.appendChild(str); // This gives Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
}
The last two lines show the errors I'm getting trying 2 different methods. Any clues.
Thanks appreciate your interest.
Update: Here's what I get in my console at the alert() stage which is what I was hoping for -
<script type='text/javascript'>$( "#pageW20" ).load("pages/work.html", function(){openLetter()})</script>
Update: Now solved, thanks #gaetano. My code now looks like:
function displayPage(position,page){
var pos = position.substring(1);
var myDiv = document.getElementById(pos);
myDiv.innerHTML=""; // Remove existing div content
/* Build the script which typically looks like this:-
<script type='text/javascript'> $( "#pageB15" ).load( "pages/benefits.html", function(){openLetter()}); </script>
*/
var str = '$( ' + '"' + position + '"' +' ).load(' + page + ', function(){openLetter()});';
console.log(str);
var s = document.createElement('script');
s.type = 'text/javascript';
s.text = str;
myDiv.appendChild(s);
}
I cannot understand why you are trying to create and append a script on the fly like described in the comments.
The error you get is:
myDiv.appendChild(str);
But appendChild requires as first parameter a node.
So if you need to continue in this direction you have to create a script node element and after you can append it to the html like in my example:
function displayPage(position, page) {
var pos = position.substring(1); // New variable without the '#' that appears in the first character of position
var myDiv = document.getElementById(pos); // Find the div, typically equates to a div id similar to 'pageW20'
var str = '$( ' + '"' + position + '"' + ' ).load("' + page + '", function(){openLetter()})';
var s = document.createElement('script');
s.type = 'text/javascript';
s.text = str;
myDiv.appendChild(s);
}
displayPage('_XXX', 'page');
console.log(document.getElementById('XXX').outerHTML);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="XXX"></div>
The str variable you're passing isn't a Node, it's a String. Try first using:
var line = document.createElement("p");
line.innerHTML = str;
myDiv.appendChild(line);

Umbraco Razor - Pass Array to Javascript

I have a foreach loop in Razor which takes images from the Multiple Media Picker in Umbraco. The Response.Write just allows me to see that the images are displaying fine (which they are) so you can ignore this bit.
My question is, how do I populate the image tag with the image URL using the Javascript function? (see below which currently doesn't work).
Razor View/CSHTML
var imagesList = portfolioItem.GetPropertyValue<string>("Images").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var imagesCollection = Umbraco.TypedMedia(imagesList);
foreach (var imageItem in imagesCollection)
{
Response.Write("<img src='"+ #imageItem.Url +"' />");
}
Javascript
openInfoWindow = function (name, imagesCollection, location, mw, url, marker) {
var infoText = "<img src='" + imagesCollection + "' alt='" + imagesCollection + "'title='" + imagesCollection + "' />";
}
try using jquery, if u use razor to set the url as an invisible input value. Then use jquery to pull that value out and add it to the img tag itself by using the following:
var inputVal = $("input").val();
$("#my_image").attr("src",inputVal );
if you put the invisble input value as a variable you can set the img atr ursing jquery like I've shown above.

Edit, save, self-modifying HTML document; format generated HTML, JavaScript

Motivation: https://stackoverflow.com/questions/28120689/create-self-modifying-html-page-on-box
Bug: String escaping , formatting html , js generated by initial edited , saved html , js
e.g.,
a) if open "saveFile.html" at local browser ;
b) type "abc" into textarea ;
c) click save file button ;
d) click Save at Save File dialog ;
e) file-*[date according to universal time].html saved to disk ;
f) open file-*[date according to universal time].html in browser ;
g) type "def" into textarea ;
h) repeat d) , e) , f) ;
i) Bug: result at second file-*[date according to universal time].html does display textarea containing "abc def" text content ; button not displayed at html:
// at rendered `html` from second `file-*[date according to universal time].html`
// `textarea` containing "abc def" displayed here ,
// `button` _not_ displayed ; following string displayed following `textarea`:
');"console.log(clone);var file = new Blob([clone], {'type':'text/html'});a.href = URL.createObjectURL(file);a.download = 'file-' + new Date().getTime() + '.html';a.click();};
generated at line 26 , "saveFile.html"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
"saveFile.html" v 1.0.0
html , js
<!doctype html>
<html>
<!-- saveFile.html 1.0.0 2015 guest271314 edit, save `html` document -->
<head>
</head>
<body>
<textarea>
</textarea>
<button>save file</button>
<script type="text/javascript">
var saveFile = document.getElementsByTagName("button")[0];
var input = document.getElementsByTagName("textarea")[0];
var a = document.createElement("a");
saveFile.onclick = function(e) {
var clone = ["<!doctype html><head></head><body><textarea>"
+ input.value
+ "</textarea>"
+ "<button>save file</button>"
+ "<script type='text/javascript'>"
+ "var saveFile = document.getElementsByTagName('button')[0];"
+ "var input = document.getElementsByTagName('textarea')[0];"
+ "var a = document.createElement('a');"
+ "saveFile.onclick = function(e) {"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
+ "console.log(clone);"
+ "var file = new Blob([clone], {'type':'text/html'});"
+ "a.href = URL.createObjectURL(file);"
+ "a.download = 'file-' + new Date().getTime() + '.html';"
+ "a.click();"
+ "};"
+ "</scr"+"ipt>"
+ "</body>"
+ "</html>"];
var file = new Blob([clone], {"type":"text/html"});
a.href = URL.createObjectURL(file);
a.download = "file-" + new Date().getTime() + ".html";
a.click();
};
</script>
</body>
</html>
Your replace function replaces until the /textarea> that is in your clone variable. It doesn't do it from the first file because there's a newline character after textarea in the html. One way to fix it would be to add a newline character in the generated html. Like this:
var clone = ["<!doctype html><head></head><body><textarea>"
+ input.value
// add newline here
+ "</textarea>\n"
+ "<button>save file</button>"
+ "<script type='text/javascript'>"
+ "var saveFile = document.getElementsByTagName('button')[0];"
+ "var input = document.getElementsByTagName('textarea')[0];"
+ "var a = document.createElement('a');"
+ "saveFile.onclick = function(e) {"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
+ "console.log(clone);"
+ "var file = new Blob([clone], {'type':'text/html'});"
+ "a.href = URL.createObjectURL(file);"
+ "a.download = 'file-' + new Date().getTime() + '.html';"
+ "a.click();"
+ "};"
+ "</scr"+"ipt>"
+ "</body>"
+ "</html>"];
I'm not sure what is breaking the third-generation clone so that it results in the js info being output to the page, but it would probably be better to use an actual document object to clone/manipulate the original and output its contents as string for the Blob object. For example, I tested using your base saveFile.html with the following changes:
//remove original clone var and replace with:
var clone = document.cloneNode(true);
// grab textarea elements from both original document and clone:
var doc_input = document.getElementsByTagName("textarea")[0];
var clone_input = clone.getElementsByTagName("textarea")[0];
// set clone textarea's innerHTML to current textarea value:
clone_input.innerHTML = doc_input.value;
// use outerHTML of clone.documentElement to get string for Blob
var clone_string = [clone.documentElement.outerHTML];
var file = new Blob([clone_string], {"type":"text/html"});
The only downsides I am seeing are:
This may be hard to expand into a more generic framework for generating a "live HTML file" of current state of loaded HTML page (though it shouldn't be more complicated than your example approach).
The string returned by clone.documentElement.outerHTML appears to drop the document type declaration to a simple element so that :
is not in the output string. You could probably use something like:
var clone_string = ["<!doctype html>" + clone.documentElement.outerHTML];
as a workaround. Or, for something more robust:
var doc_doctype = new XMLSerializer().serializeToString(document.doctype);
var clone_string = [doc_doctype + clone.documentElement.outerHTML];

HTML in string with JavaScript code, JS not working

Here is my test javascript function
<script type="text/javascript">
function test() {
var sHTML = "<script type='text/javascript'> " +
"function showmsg() { " +
"alert('message'); " +
"} " +
"<\/script>" +
"<div>" +
"<a href='#' onclick='javascript:showmsg(); return false;'>click</a>" +
"</div>";
var divTemp = document.createElement("div");
divTemp.innerHTML = sHTML;
var d = document.getElementById("div1");
d.appendChild(divTemp);
}
</script>
When I run this function, the div along with a tag is added in the div1, but when I click on anchor tag, it says showmsg is not defined, which is indicating that browser is NOT parsing the script tag.
How to achieve this without any 3rd party library?
Update:
The possible usage is, I want to allow user to create HTML templates along with JavaScript code, then my JS library will use those HTML templates to render user defined markup, plus allowing user to implement his/her custom logics through JS.
You need to run eval on the script contents when using innerHTML. Try something like:
var scripts = divTemp.getElementsByTagName('script');
for(var i=0; i<scripts.length; i++) {
eval(scripts[i].textContent);
}
Obviously, you need to do this in end, after injecting the innerHTML into the DOM.
Browsers do not run JavaScript code when a <script> tag is dynamically inserted like that.
Instead of that, you can just define the function directly!
function test() {
window.showmsg = function() {
alert("message");
};
var sHTML = "<div>" +
"<a href='#' onclick='javascript:showmsg(); return false;'>click</a>" +
"</div>";
var divTemp = document.createElement("div");
divTemp.innerHTML = sHTML;
var d = document.getElementById("div1");
d.appendChild(divTemp);
}
Libraries like jQuery have code to strip <script> blocks out of text that's being stuffed into some element's innerHTML, and then evaluate it with eval(), so that's one thing to do if the code is somehow "stuck" in a block of content.
Using jquery, is this can help you :
$('<script>function test(){alert("message");};</' + 'script><div>click</div>').appendTo(document.body)
http://jsfiddle.net/TSWsF/

Not all Ajax content loading on one domain

I have the domain http://whatthecatdragged.in/ forwarded (cloaked) to http://moppy.co.uk/wtcdi/
The root page (index.html) uses Ajax to load the content. At the original host (moppy.co.uk/wtcdi) the page and all content loads. However, at the domain forwarded domain (whatthecatdragged.in), some of the content does not load. Has it something to do with the way .each is used to fire off Ajax calls, as mentioned by AnthonyWJones?
I've attempted to debug this, but peculiarly turning on the Firebug console in Firefox 3.5 actually seems to make all the content load.
// Content building code:
$(function() {
// Set a few variables (no need for secrecy with Flickr API key).
var apiKey = 'myapikey';
// var tags = '';
var tagsArr = new Array();
// Get the photos of flickr user WhatTheCatDraggedIn.
// This Ajax call always seems to complete.
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' +
apiKey +
'&user_id=46206266#N05&extras=date_taken,tags&format=json&jsoncallback=?',
function(data) {
// Set some variables to ensure alldata is fecthed from second API
// call (below) before building majority of content.
var totalExpected = data.photos.total;
var totalFetched = 0;
var photohtml = '';
// For each photo, do the following:
$.each(data.photos.photo, function(i, item) {
// Set size of photo thumbnail to display.
var size = 's';
var append = '';
if (i == 0) {
// Display most recent thumbnail larger, and add a line
// break for small pics beneath it.
size = 'm';
append = '<br />'
}
//Only display thmbnails of 4 most recent catches (1 large, 3 small).
if (i <= 3) {
var photoSrc =
'http://farm' + item.farm + '.static.flickr.com/' +
item.server + '/' + item.id + '_' + item.secret + '_' +
size + '.jpg'
//Each thumbnail links to that photo's Flickr page.
var flickrPage =
'http://flickr.com/photos/' + item.owner +
'/' + item.id + '/';
// Each thumbnail has a big tooltip, with tags formatted appropriately.
var formattedTags = item.tags.replace(/\s/g, "<br />");
formattedTags = formattedTags.replace(/cat/, "cat: ");
formattedTags = formattedTags.replace(/loc/, "location: ");
formattedTags = formattedTags.replace(/victim/, "victim: ");
formattedTags = formattedTags.replace(/status/, "status: ");
formattedTags = formattedTags.replace(/floor/, " floor");
formattedTags = formattedTags.replace(/toy/, " toy");
//Append the built html to one varable for adding to page shortly
photohtml +=
'<a class="flickr-page-link" href="' +
flickrPage + '"><img src = "' +
photoSrc + '" title="' + formattedTags + '"/>' +
append + '</a>';
}
var photoID = item.id;
// Get the detailed photo information (including tags) for the photo.
// This is the call that perhaps fails or at least content
// generated after this call does not load.
$.getJSON(
'http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' +
apiKey + '&photo_id=' + photoID +
'&format=json&jsoncallback=?',
function(data) {
if (data.photo.tags.tag != '') {
$.each(data.photo.tags.tag, function(j, item) {
// Place all tags in an aray for easier handling.
tagsArr.push(item.raw);
});
// Incrememt number of photos fetched.
totalFetched += 1;
// Have we got them all?
if (totalFetched == totalExpected)
fetchComplete();
}
});
// Builds a shedload more content once all JSON calls are completed.
function fetchComplete() {
// ### BUILD VICTIM list ###
// format a regex to match tags beginnign : "victim: "
var vicRe = /^v[a-z]+:\s([a-z\s]+)/
// Match the regex to the tags and count number of matches per tag.
var vicCounts = tagsArr.countVals(vicRe);
var victimsHtml = "";
// For each victim.
for (var i in vicCounts) {
var strippedTag = [i].toString().replace(/\W/g, "");
console.debug(strippedTag);
// Add a line of html with the type of victim and the number of victims of that type
victimsHtml +=
"<a href='http://flickr.com/photos/46206266#N05/tags/victim" +
strippedTag + "/'>" + [i] +
" (" + vicCounts[i] + ") </a><br />";
};
// Replace existing HTML with new version.
$('#types-dragged').html(victimsHtml);
// ### BUILD STATUS PIE CHART ###
// Build a theme for chart colours.
var wtcdicharttheme = {
colors: ['#C66800', '#D3C70B', '#DD3D0B', '#D30729',
'#DDA70B'
],
marker_color: '#000000',
font_color: '#000000',
background_colors: ['#ffffff', '#ffffff']
};
// Create a new chart object, include css id of canvas
// where chart will be drawn.
var g = new Bluff.Pie('status', '275x250');
// Set a theme and stuff.
g.set_theme(wtcdicharttheme);
// No title, as this exists via the raw page HTML.
g.title = '';
g.legend_font_size = "50px";
g.marker_font_size = "20px";
// Build a regex string to match tags beginning "status: ".
var statRe = /^s[a-z]+:\s([a-z\s]+)/
// Match regex to tags and return an object with tag
// names and number of occurences.
var statCounts = tagsArr.countVals(statRe);
// For each status.
for (var i in statCounts) {
// Add data to the chart
g.data([i], [statCounts[i]]);
};
// Draw the chart.
g.draw();
// ### BUILD LOCATION LIST ###
// Build a regex that matches tags beginning "loc: "
var locRe = /^l[a-z]+:\s([a-z\s]+)/
// Match regex to tags and return an object with
// tag names and number of occurences.
var locCounts = tagsArr.countVals(locRe);
var locatHtml = "";
// For each location.
for (var i in locCounts) {
var strippedTag = [i].toString().replace(/\W/g, "");
// Add a line of html with the location and the
//number of times victims found in that location.
locatHtml +=
"<a href='http://flickr.com/photos/46206266#N05/tags/loc" +
strippedTag + "/'>" + [i] + " (" +
locCounts[i] + ") <br />";
};
// Replace existing html with newly built information.
$('#locations').html(locatHtml);
// ### BUILD CAT LIST ###
// Build a regex that maches tags beginning "cat: ".
var catRe = /^c[a-z]+:\s([a-z_\s]+)/
//Match regex to find number of catches each cat has made
var catCounts = tagsArr.countVals(catRe);
// For each cat.
for (var i in catCounts) {
var strippedTag = [i].toString().replace(/\W/g, "");
// Insert number of catches to div titled "(catname)-catch"
$('#' + [i] + '-catch').html(
"<a href='http://flickr.com/photos/46206266#N05/tags/" +
strippedTag + "/'>" + catCounts[i] + "</a>");
};
}
});
// Insert total dragged onto page.
$('#total-dragged').html(data.photos.total);
// Insert photos onto page.
$('#latest-catches').html(photohtml);
// Add tooltips to the images from Flickr.
$('img').each(function() {
$(this).qtip({
style: {
name: 'wtcdin'
},
position: {
target: 'mouse',
adjust: {
x: 8,
y: 10
}
}
})
});
});
});
UPDATE 1: I contacted the domain name company, their advice was basically "don't use JavaScript". Still can't see why it would work under one domain name and not another... Could it be to do with the fact that they "forward" the domain by means of a frame?
The browser will block AJAX requests that are sent outside of the domain that the script is hosted on. This is most likely the cause of your problem from the sound of things.
EDIT: I've found the problem, you have console.debug() calls in your script. This method is defined by the Firebug Console which is why it's only working while the Console is active. Try removing any calls to console.debug() and see how it goes.

Categories