Capture embedded variable from jQuery Ajax call - javascript

I'm trying to convert our current javascript framework to jQuery cause we'll need the additional functionality of jQuery for further projects. There is one particular function that is all over the place (and it was setup how it was setup......) that I'd like to just override with a jQuery equivalent. Here's the original Javascript function that makes an ajax call to a php page.
function ajax(n,f,v){
var ajaxRequest;
if(window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
ajaxRequest=new XMLHttpRequest();
}
else{// code for IE6, IE5
ajaxRequest=new ActiveXObject("Microsoft.XMLHTTP");
}
ajaxRequest.onreadystatechange=function(){
if(ajaxRequest.readyState==4 && ajaxRequest.status==200){
//This is where the result is stored
result = ajaxRequest.responseText;
//parseScript pulls out the content and the div and populates the div with the retrieved content.
parsed_result = parseScript(result);
document.getElementById(parsed_result.div).innerHTML = parsed_result.source;
}
}
ajaxRequest.open("GET","view.php?n="+n+"&f="+f+"&v="+v+"&time="+(new Date).getTime(),true);
ajaxRequest.send();
}
function parseScript(_source) {
var source = _source;
var scripts = new Array();
while(source.indexOf("<script") > -1 || source.indexOf("</script") > -1) {
var s = source.indexOf("<script");
var s_e = source.indexOf(">", s);
var e = source.indexOf("</script", s);
var e_e = source.indexOf(">", e);
scripts.push(source.substring(s_e+1, e));
source = source.substring(0, s) + source.substring(e_e+1);
}
for(var i=0; i<scripts.length; i++) {
try {
eval(scripts[i]);
var div = div;
}
catch(ex) {
}
}
return {source: source, div: div};
}
This is at the top of page that was just retrieve (hence the parseScript function). This div variable tells where to put the retrieved content.
<script>
var div = 'content_1';
</script>
<!-- some retrieved html -->
The jQuery function I'd like to just "set on top" of the javascript function would require that I don't edit the retrieve ajax file at all. See below for my attempt at the jQuery call.
function jAjax(n,f,v) {
$.get('view.php', 'n='+n+'&f='+f+'&v='+v, function(result) {
if(result) {
if($('#'+result.div).length) {
$('#'+result.div).html(result);
} else {
console.log("Couldn't find the div= "+result.div);
}
} else {
console.log("Couldn't find the names for n="+n+' f='+f+' v='+v);
}
});
}
So the question I have is how to I use jQuery to capture a variable from an ajax call so that I can populate that capture div with the retrieved html?
One other thing, yes I can can think of a bunch of ways to do it besides doing this, but this way would be easiest with the current framework that was already set in place when I got here. So, please only suggest ways of retrieving the variable from the ajax script. Thanks muchly!

There is no built in way to get the value of variables in a javascript file that you retrieved through jquery ajax methods. You could, however, just call the parseScript function inside the $.get callback:
$.get('view.php', 'n='+n+'&f='+f+'&v='+v, function(result) {
if(result) {
parsed_result = parseScript(result);
if($('#' + parsed_result.div).length) {
$('#' + parsed_result.div).html(parsed_result.source);
} else {
console.log("Couldn't find the div= " + parsed_result.div);
}
} else {
console.log("Couldn't find the names for n="+n+' f='+f+' v='+v);
}
});
EDIT:
You may have to make this call with the longer $.ajax(...) method, setting the content type to text, because you have a script tag in the page.
EDIT (ALTERNATIVE):
You could simply reference the variable 'div' in the $.get callback because at that point the script would have been executed:
$.get('view.php', 'n='+n+'&f='+f+'&v='+v, function(result) {
if(result) {
if($('#' + div).length) {
$('#' + div).html(result);
} else {
console.log("Couldn't find the div= " + div);
}
} else {
console.log("Couldn't find the names for n="+n+' f='+f+' v='+v);
}
});

Related

Load Javascript into ajax loaded content

I am new to working with AJAX and have some experience with Java/Jquery. I have been looking around for an solution to my problem but i cant seem to find any.
I am trying to build a function in a webshop where the product will appear in a popup window instead of loading a new page.
I got it working by using this code:
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
$("#product-overlay-inner").load(myUrl, function() {
});
$("#product-overlay").fadeIn();
return false;
});
product-slot a = Link to the product in the category page.
product-content = the div i want to insert in the popup from the product page.
product-overlay-inner = The popup window.
product-overlay = The popup wrapper.
The problem that i now have is that my Javascript/Jquery isnt working in the productpopup. For example the lightbox for the product image or the button to add product to shoppingcart doesnt work. Is there anyway to make the javascript work inside the loaded content or to load javascript into the popup?
I hope you can understand what my problem is!
Thank you in advance!
EDIT: The platform im using has jquery-ui-1.7.2
I know this is an old thread but I've been working on a similar process with the same script loading problem and thought I'd share my version as another option.
I have a basic route handler for when a user clicks an anchor/button etc that I use to swap out the main content area of the site, in this example it's the ".page" class.
I then use a function to make an ajax call to get the html content as a partial, at the moment they are php files and they do some preliminary rendering server side to build the html but this isn't necessary.
The callback handles placing the new html and as I know what script I need I just append it to the bottom in a script tag created on the fly. If I have an error at the server I pass this back as content which may be just a key word that I can use to trigger a custom js method to print something more meaningful to the page.
here's a basic implementation based on the register route handler:
var register = function(){
$(".page").html("");
// use the getText ajax function to get the page content:
getText('partials/register.php', function(content) {
$(".page").html(content);
var script = document.createElement('script');
script.src = "js/register.js";
$(".page").append(script);
});
};
/******************************************
* Ajax helpers
******************************************/
// Issue a Http GET request for the contents of the specified Url.
// when the response arrives successfully, verify it's plain text
// and if so, pass it to the specified callback function
function getText(url, callback) {
var request = new XMLHttpRequest();
request.open("GET", url);
request.onreadystatechange = function() {
// if the request is complete and was successful -
if (request.readyState === 4 && request.status === 200) {
// check the content type:
var type = request.getResponseHeader("Content-Type");
if (type.match(/^text/)) {
callback(request.responseText);
}
}
};
// send it:
request.send(null); // nothing to send on GET requests.
}
I find this a good way to 'module-ize' my code into partial views and separated JavaScript files that can be swapped in/out of the page easily.
I will be working on a way to make this more dynamic and even cache these 'modules' for repeated use in an SPA scenario.
I'm relatively new to web dev so if you can see any problems with this or a safer/better way to do it I'm all ears :)
Yes you can load Javascript from a dynamic page, but not with load() as load strips any Javascript and inserts the raw HTML.
Solution: pull down raw page with a get and reattach any Javascript blocks.
Apologies that this is in Typescript, but you should get the idea (if anything, strongly-typed TypeScript is easier to read than plain Javascript):
_loadIntoPanel(panel: JQuery, url: string, callback?: { (): void; })
{
// Regular expression to match <script>...</script> block
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts: string = "";
var match;
// Do an async AJAX get
$.ajax({
url: url,
type: "get",
success: function (data: string, status: string, xhr)
{
while (match = re.exec(data))
{
if (match[1] != "")
{
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
// Replace the contents of the panel
//panel.html(data);
// If you only want part of the loaded view (assuming it is not a partial view)
// using something like
panel.html($(data).find('#product-content'));
// Add the scripts - will evaluate immediately - beware of any onload code
panel.append(scripts);
if (callback) { callback(); }
},
error: function (xhr, status, error)
{
alert(error);
}
});
}
Plain JQuery/Javascript version with hooks:
It will go something like:
var _loadFormIntoPanel = function (panel, url, callback) {
var that = this;
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts = "";
var match;
$.ajax({
url: url,
type: "get",
success: function (data, status, xhr) {
while(match = re.exec(data)) {
if(match[1] != "") {
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
panel.html(data);
panel.append(scripts);
if(callback) {
callback();
}
},
error: function (xhr, status, error) {
alert(error);
}
});
};
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
_loadFormIntoPanel($("#product-overlay-inner"), myUrl, function() {
// Now do extra stuff to loaded panel here
});
$("#product-overlay").fadeIn();
return false;
});

jQuery - load data to variable, check data and update in DIV

I make very, very simple intranet chat. I load every 2 sec data from URL to DIV. But I want (and I don't know how) load data to variable, compare data from DIV and if !=, update in DIV. And scroll to down "page" in this DIV. Please, help me stackoverflowers! :)
var chatInterval;
function chatLoad(){
chatInterval = setInterval(function(){
$('#chat-conversations').load('/AJAX/Chat.app');
}, 2000);
}
Instead of just loading it directly put it on a variable first and compare it. That's why I use .get instead of .load, .load loads the content directly into the element.
var chatInterval;
var chatContent = "";
function chatLoad(){
chatInterval = setInterval(function(){
$.get('/AJAX/Chat.app',function(data){
if(data!=chatContent){
$('#chat-conversations').html(data);
chatContent = data;
}
})
}, 2000);
}
First of all you must understand that compare all data is bad idea, you just need check that user have new messages whatever.
Also you must now about long polling and short polling good explanation.
Why its bad idea to compare all data?
Because after a 5 minutes you will receive a BIG BIG bunch of data (performance).
Hor compare if you want:
var _current_data = null;
var interval = setInterval(function(){
// your logic to receive data, we receive response from server
if(!_current_data) _current_data = response;
else if(_current_data != response){
// Render logic (insert data into html tags and return html as string)
$("div").html(render(current_data));
}
}, 2000);
You can use ajax to get the latest posts without reloading the page as you said with the interval of 2 second.
function getXmlHttpRequest() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
// code for IE7+, Firefox, Chrome, Opera, Safari
}
else if (window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
// code for IE5 and IE6
}
else {
alert("Browser doesn't support Ajax..!!");
}
return xmlhttp;
}
function loadData() {
xmlhttp = getXmlHttpRequest();
if (xmlhttp !== null) {
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState < 4) {
document.getElementById('your-div').innerHTML = "<img src = 'loader-animation.gif'/>";
}
else if (xmlhttp.readyState === 4) {
var res = xmlhttp.responseText;
if (res.trim() !== "error") {
document.getElementById('your-div').innerHTML = res;
} else {
document.getElementById('your-div').innerHTML = "<img src = 'error.png' style='vertical-align:middle;'/>";
}
}
}
xmlhttp.open("POST", "data_loading_page.php", true);
xmlhttp.send(null);
}
}
on data_loading_page.php (any media of you use php or jsp or anything) print your posts using a while. so whenever the function calls the php page then you'll get the updates;
call the script by
setInterval(function() {
loadData();
}, 2000);

How to use onhashchange with dynamic items

So, I have two select boxes on a webpage, but in different anchors (one on the page, the other in an iframe) and I'm trying to get the code to detect which anchor it's in, and then relay the selected value in that box to a link. Here's my code:
function locationHashChanged() {
if (location.hash === "#player") {
function setText(text) {
var selectVal = text;
var url = $('twitter').attr("href");
url = 'https://twitter.com/intent/tweet?button_hashtag=stream&text=Just enjoying ' + selectVal + ' on';
$('#twitter').attr("href", url);
}
}
if (location.hash === "#embeds") {
$(function () {
var $twitter = $('twitter');
$('#iframe').on('load', function () {
$(this).contents().find('#cds').change(function () {
var selectVal = $(this).val() || 'nothing much';
url = 'https://twitter.com/intent/tweet?button_hashtag=stream&text=Just enjoying ' + selectVal + ' on';
$('#twitter').attr("href", url);
}).change();
});
});
}
}
I know this is probably not right, or anywhere near right, but am I on the right track? I'm honestly a complete noob when it comes to javascript. Thanks in advance
Apart from what exactly your function looks like, it's not executed on hash change right now.
You use jQuery, so you can listen for hash change like this:
$(window).on('hashchange', function() {
// your locationHashChanged() function goes here
});
With this, every time the hash changes your function will be executed. The very base of your code is alright:
if (location.hash === "#player") {
// this is executed if hash changed to #player
}
if (location.hash === "#embeds") {
// this is executed if hash changed to #embeds
}
Although, inside your if blocks you declare functions (which doesn't make much sense here).
Also note that if the iframe is not from your domain, you won't be able to get any data from it. If that's the case, read more about same origin policy.

Function scope within IF Statement

hoping some one can shed some light on my problem. Basicly I only want to execute a block of code if a certain DOM element exists. If it does I then perform a few bits and bobs and then call a function. However it complains that the function is not defined, suggesting that the function is not in scope. Below is the code :
$(document).ready(function ()
{
if ((document.getElementById("view<portlet:namespace/>:editSplash")!= null)) {
console.log("notifications scripted started");
// hide loading box/ notify on body load
$('.ajaxErrorBox').hide();
$('.loadingNotifications').hide();
$('.notifyWindow').hide();
getFeed();
// set up refresh button for reloading feed
$('.refreshFeed').click(function() {
$('.notifyWindow').hide();
$('.notifyWindow').empty();
console.log("notifications clicked");
getFeed();
});
// begin ajax call using jquery ajax object
function getFeed ()
{
$('.notifyWindow').empty();
console.log("ajax call for feed starting");
$.ajax ({
type: "GET",
url: "http://cw-pdevprt-05.tm-gnet.com:10040/notificationsweb/feed?username=uid=<%# taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %><wps:user attribute="uid"/>",
dataType: "text/xml",
timeout: 10000,
success: parseXml
});
};
// show loading box on start of ajax call
$('.notifyWindow').ajaxStart(function() {
$('.refreshFeed').hide("fast");
$('.notifyWindow').hide();
$('.ajaxErrorBox').hide();
$('.loadingNotifications').show("fast");
});
// hide loading box after ajax call has stopped
$('.notifyWindow').ajaxStop(function() {
$('.loadingNotifications').hide("slow");
$('.refreshFeed').show("fast");
});
$('.notifyWindow').ajaxError(function() {
$('.loadingNotifications').hide("slow");
$('.ajaxErrorBox').show("fast");
$('.refreshFeed').show("fast");
});
// parse the feed/ xml file and append results to notifications div
function parseXml (xml) {
console.log("xml parsing begining");
if (jQuery.browser.msie)
{
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.loadXML(xml);
xml = xmlDoc;
}
$(xml).find("entry").each(function()
{
var $item = $(this);
var title = $item.find("title").text();
var linkN = $item.find("link").attr("href");
var output = "<a href='" + linkN + "' target='_self'>" + title + "</a><br />";
$(".notifyWindow").append($(output)).show();
});
}
}
else {
console.log("notifications not available");
return false;
}
});
If the DOM element exists I then try and call the getFeed function "getFeed();" however it comes back undefined. If anyone could shed some light on this it would be greatly appreciated.
Thanks in advance
It seems that you're calling getFeed before it is defined. Try moving the if statement to after the function definition. Note that this behaviour is actually implementation specific, so some browsers may work this way and some may not.
Oh - And seriously? view<portlet:namespace/>:editSplash for an id?
Problem solved - I moved my functions outside of the if statement. We live and learn lol :-)

Replacing whole HTML content kills HEAD and BODY tags after HTTP Request!

After pressing a button, I'm sending the whole HTML content from a webpage (the part within the <html> tags) to a CGI script which manipulates the content and sends it back.
Now I'm trying to replace the existing content with the new one. Unfortunately after assignment, every single <head> or <body> tag (as well as the closing ones) will be killed.
By using some alerts I looked through the returning value as well as the original HTML stuff. Both are absolutely as expected.
But after the assignment there is some magic going on. Please help me to figure out what's going on.
Here is the used JavaScript code I used:
var originalBodyInnerHTML = document.body.innerHTML;
var htmlNode = document.getElementsByTagName('html')[0];
var post_parameters = encodeURIComponent(htmlNode.innerHTML);
makePOSTRequest("POST", "http://whatever.com/cgi-bin/doit.cgi", post_parameters, htmlNode);
function makePOSTRequest(method, url, parameters, htmlNode) {
var http_request = getRequestObj();
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function()
{
if (http_request.readyState < 4)
{
var waitingPageBody = '< img src="/img/ajaxloader.gif" alt="in progress..."/>';
document.body.innerHTML = waitingPageBody;
}
else //if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
alert('1response: ' + http_request.responseText);
alert('2innerhtml: ' + document.getElementsByTagName('html')[0].innerHTML);
document.getElementsByTagName('html')[0].innerHTML = http_request.responseText;
}//end of if (http_request.status == 200)
else
{//other http statuses
alert("There was a problem (" + http_request.statusText + ", " + http_request.status + ' error)');
bodyNode.innerHTML = originalBodyInnerHTML;
}
}//end of else if http_request.readyState == 4
}
http_request.open(method, url, true); //async
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Accept", "application/atom+xml,application/xml,text/xml");
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}
function getRequestObj() {
var http_request = false;
if (window.XMLHttpRequest)
{ // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType)
{
http_request.overrideMimeType('text/html');
}
}
else if (window.ActiveXObject)
{ // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
return http_request;
}
This is a simple solution that worked for me. Just as a reference.
document.clear();
document.write(newHtml);
where newHtml is the complete html of new web page.
well, with this
document.getElementsByTagName('html')[0].innerHTML = http_request.responseText
you are replacing everything insidee the html, "killing" body, head and everything...
maybe you wanted
document.body.innerHTML = http_request.responseText
Also, I'd use jquery, it makes your life sooo much easier
You cannot do that. It's not possible to replace the contents of the whole html tag. You can get away with replacing only the contents of the body tag. The head element is kind of magical and browser generally don't support replacing it.
If you want to change the whole document, redirect to it.
If you want to change only parts of the head, try sending them in a different form (like JSON), and make appropriate changes using javascript APIs.
Thanks qbeuek for your answer!
To change only the header, Firefox in fact will allow something like this:document.getElementsByTagName('head')[0] += "e.g. some scripts"
But for Internet Explorer it is necessary to add each element separately to the DOM tree.
var script = document.createElement("script");
script.setAttribute('type','text/javascript');
objHead.appendChild(script);
However, it is really weird that Firefox behaves like this and not popup with some error...

Categories