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.
Related
I am having trouble. So I need to get data from an api. I have a search bar and the user needs to input the search bar to look up a super hero api.
How would I get data from a search bar and put in my url all in a .click function.
var userInput;
var url;
var test;
//https://superheroapi.com/api/10215865526738981
$(document).ready(function () {
// when the user types in the data and clicks the button
$(btn1).click(function () {
// this is where the search bar is
userInput = document.getElementById('mySearch').innerHTML;
});
url = 'https://www.superheroapi.com/api.php/10215865526738981/search/batman' + userInput;
// here is where the api link in say type in batman
// and is should pop up with info about batman and
$.getJSON(url, function (data) {
var html = '';
$.each(data.results, function (i, demo) {
html += '<h2>' + demo.name + '</h2>';
//html += "<h2>" + demo.biography.alter-egos + "</h2>";
html += '<h2> Power Stats ' + demo.powerstats.combat + '</h2>';
html += '<p> Connections ' + demo.connections.relatives + '</p>';
html += '<p> appearance ' + demo.appearance.gender + '</p>';
html += '<h2> Work ' + demo.work.base + '</h2>';
html += ' Profile <img src ' + demo.image.url + '>';
});
$('#demo').html(html);
});
}
<p>
<input type="search" id="mySearch" name="mySearch">
<button id="btn1">Search</button>
<p id="demo"></p>
</p>
Here is something that works that you can use to compare with your code and make something out of it. I've used plain javascript and left comments what is going on so that you can learn from it.
There were few wrong assumptions in original question.
code was executing on page load and didn't wait for user input
url was hardcoded to start with batman + what ever user wrote
Code below is not perfect, but it is close enough to original code and it should be easy to understand. I also opted not to use jQuery, but you should be able to use it if wanted. Just replace getElementById with jQuery selectors and replace XMLHttpRequest with getJson.
I hope this helps you move ahead with your problem and that you will be able to learn something new which could help you better understand javascript. Happy coding!
var button = document.getElementById('btn1');
// when user clicks on button, we want to call function start search
button.addEventListener('click', startSearch);
function startSearch(event) {
// when we are starting the search, we want to pick up the value
// input field from user
var userInputValue = document.getElementById('mySearch').value;
// this is base API url on which we can add what user wanted
var urlBase = 'https://www.superheroapi.com/api.php/10215865526738981/search/'
// if user did not provide name in input, we want to stop executing
if (userInputValue === null || userInputValue === '') return;
// if we are still in this function, append what user typed onto urlBase
var searchUrl = urlBase + userInputValue;
// call function which actually executes the remote call
performSearch(searchUrl);
}
function performSearch(searchUrl) {
// this could be jQuery getJSON if you so prefer
// here it is vanila JS solution of how to get data via AJAX call
var requestData = new XMLHttpRequest();
// because AJAX is always async, we need to wait until file is loaded
// once it is loaded we want to call function handleResults
requestData.addEventListener('load', handleResults);
requestData.open('GET', searchUrl);
requestData.send();
}
function handleResults() {
// once we get response, because we used vanilla JS, we got response
// available in this context as "this.response", however it is type string
// we need to take that string and parse it into JSON
var responseJSON = JSON.parse(this.response);
// if there is error, we didn't find any character
if (responseJSON.error) console.log('Character not found');
else {
var html = '';
responseJSON.results.forEach(function (result) {
html += '<h2>' + result.name + '</h2>';
// html += "<h2>" + demo.biography.alter-egos + "</h2>";
html += '<h2>Power Stats ' + result.powerstats.combat + '</h2>';
html += '<p>Connections ' + result.connections.relatives + '</p>';
html += '<p>Appearance ' + result.appearance.gender + '</p>';
html += '<p>Work ' + result.work.base + '</p>';
// html += ' Profile <img src ' + result.image.url + '>';
})
// this is bad thing to do, injecting html like that into DOM
// but let's leave this lesson for later stage
// so, let's take this html and drop it onto the page
document.getElementById('demo').innerHTML = html;
}
}
<input type="search" id="mySearch" name="mySearch">
<button id="btn1">Search</button>
<div id="demo"></div>
const value = document.getElementById('mySearch').value;
And then use this value in your api url.
I'm using jQuery to get values from ajax rest call, I'm trying to concatenate these values into an 'a' tag in order to create a pagination section for my results (picture attached).
I'm sending the HTML (divHTMLPages) but the result is not well-formed and not working, I've tried with double quotes and single but still not well-formed. So, I wonder if this is a good approach to accomplish what I need to create the pagination. The 'a' tag is going to trigger the onclick event with four parameters (query for rest call, department, row limit and the start row for display)
if (_startRow == 0) {
console.log("First page");
var currentPage = 1;
// Set Next Page
var nextPage = 2;
var startRowNextPage = _startRow + _rowLimit + 1;
var query = $('#queryU').val();
// page Link
divHTMLPages = "<strong>1</strong> ";
divHTMLPages += "<a href='#' onclick='getRESTResults(" + query + "', '" + _reg + "', " + _rowLimit + ", " + _startRow + ")>" + nextPage + "</a> ";
console.log("Next page: " + nextPage);
}
Thanks in advance for any help on this.
Pagination
Rather than trying to type out how the function should be called in an HTML string, it would be much more elegant to attach an event listener to the element in question. For example, assuming the parent element you're inserting elements into is called parent, you could do something like this:
const a = document.createElement('a');
a.href = '#';
a.textContent = nextPage;
a.onclick = () => getRESTResults(query, _reg, _rowLimit, _startRow);
parent.appendChild(a);
Once an event listener is attached, like with the onclick above, make sure not to change the innerHTML of the container (like with innerHTML += <something>), because that will corrupt any existing listeners inside the container - instead, append elements explicitly with methods like createElement and appendChild, as shown above, or use insertAdjacentHTML (which does not re-parse the whole container's contents).
$(function()
{
var query=10;
var _reg="12";
var _rowLimit="test";
var _startRow="aa";
var nextPage="testhref";
//before divHTMLPages+=,must be define divHTMLPages value
var divHTMLPages = "<a href='#' onclick=getRESTResults('"+query + "','" + _reg + "','" + _rowLimit + "','" + _startRow + "')>" + nextPage + "</a>";
///or use es6 `` Template literals
var divHTMLPages1 = `` + nextPage + ``;
$("#test").append("<div>"+divHTMLPages+"</div>");
$("#test").append("<div>"+divHTMLPages1+"</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test"></div>
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.
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];
I'm working with a wordpress plugin called Wordpress Simple Paypal Shopping Cart, when the form is sent it starts this script. It takes a product, and three dropdown and puts them into a format in one string like this:
SHOP ITEM (dropdown1) (dropdown2) (dropdown3)
Here is the code.
<script type="text/javascript">
<!--
//
function ReadForm (obj1, tst)
{
// Read the user form
var i,j,pos;
val_total="";val_combo="";
for (i=0; i<obj1.length; i++)
{
// run entire form
obj = obj1.elements[i]; // a form element
if (obj.type == "select-one")
{ // just selects
if (obj.name == "quantity" ||
obj.name == "amount") continue;
pos = obj.selectedIndex; // which option selected
val = obj.options[pos].value; // selected value
val_combo = val_combo + " (" + val + ")";
}
}
// Now summarize everything we have processed above
val_total = obj1.product_tmp.value + val_combo;
obj1.product.value = val_total;
}
//-->
</script>';
I need to change the output so I can style the three options with specific CSS. The output in HTML is in a span.
I notice the line val_combo = val_combo + " (" + val + ")"; adds the brackets around the output so I tried to change it to val_combo = val_combo + " <div>" + val + "</div>"; but the output strips the divs, leaving the output like:
SHOP ITEM dropdown1 dropdown2 dropdown3
I'm not clever with Javascript so any examples as if for a child would be highly appreciated.