Running the javascript code present on another html page through jquery - javascript

It might be a noob questions but I have just started using jquery.
My basic requirement to extract the link which is there in the javascript code present in another html (code is embedded in the html page and not in a seperate file).
The link is also present as a href attribute of <a> tag inside a tag, just to add if it is easier to extract it from there (I am using chrome so I think it considers there are no child nodes of <noscript> tag)
After this I tried doing an ajax request to the html page (using $.ajax) thinking it will run the scripts on the page but got the html code of the page in return :S . I have also heard of something called evalscripts:true but not sure if that will work here or how to use it?
I have also tried to search for the link in html code returned by my html page by using the "contains" operation of jquery.
I am doing all this to create a greasemonkey script. Please suggest
Example Code:
This is a function present inside the html of that page:
function fun() {
obj = new pollingObj('argument', "a link I want to extract comes here");
}
I want to extract the link: "a link I want to extract comes here" and then open it.on my page where I am running my jquery script
This link is also present like this on the html page:
<noscript>
blabla
</noscript>
Also is it possible to run the javascripts present on that page if the link extraction is not possible?

If you're able to get the html code of the page successfully via .ajax, and the data you want is in the HTML code, it's not worth the effort to bother with trying to run the scripts. Just access the URL through the DOM:
// ajax success function
success: function(html) {
var anchorCode = $(html)
// this assumes that noscript is a top-level element
// otherwise, use .find('noscript')
.filter('noscript')
.text(); // get the code for the anchor tag, as a string
var myLink = $(anchorCode).attr('href');
// do something with myLink
}
Edit: It turns out that jQuery is a little funny in the way it deals with noscript tags - inner tags don't appear to be considered part of the DOM, so you need to grab the text content of the tag and then use jQuery to DOM-ify it. See updated code above.

Related

Send a Google Analytics event when a specific text string is present on a page

I have somewhere on website a specific text, let's say "NewYork", and I want to fire a Google Analytics event to track all the occurrences of this string.
For example if a visitor come to a webpage that contain the string 'NewYork', I want to send a Google Analytics event.
Text string is in a span tag as <span class="city">NewYork</span>
I do not know any JavaScript codes, just tried the following code adapted from someone else. And it is not working at all.
<script>
var htmlString = $('body').html().toString();
var index = htmlString.indexOf("NewYork");
if (index != -1)
{ ga('send', 'event', 'yesNewYork', 'foundnewyork'); } </script>
Does anybody know how to do this?
Possibly a jQuery solution?
Your approach is correct in principle, but can be improved upon.
You are already using jQuery syntax so I just assume jQuery is available.
First I would suggest you follow Lars Graubner suggestion and select a more specific element and grab the text content instead of the html (as the name suggests the text()-function does not return HTML markup but text only).
$('.city').text()
will adress the span from your example - the dot in the selector says "Look for elements with a classname of".
This will actually return all elements that have the class, but for your use case that does not matter much.
However you must make sure that the text is actually rendered on the page before you call your jQuery selector; if you place it in the head of the page the text isn't there yet when the event tracking runs and thus your selector will return nothing.
You can either put the script in the footer of the page, or you can wrap it into jQuery's document.ready-call. This makes sure that the function only runs after the DOM of the document has rendered (meaning that the page structure is complete, event if images and other assets are not yet loaded. Text will be present at this point). So this would look like this:
$( document ).ready(function() {
var myString = $('.city').text();
if(myString.indexof('NewYork') > -1) {
ga('send', 'event', 'yesNewYork', 'foundnewyork');
}
});
(Obviously this assumes you have jQuery included).
If this still doesn't work you need to be more specific as to the actual error your are getting.

how to avoid fetching a part of html page which is being called inside another page?

I am calling a .html page(say A.html, which is dynamically created by another software each time a request is made) inside another webpage (say B.html). I am doing this by using the .load() function. Everything works fine but the problem is I donot want the so many "br" tags (empty tags) present at the end of A.html into B.html. Is there any way to avoid fetching those "br" tags into B.html? Any suggestion would be of great help. Thank you in advance.
You can't avoid loading part of a file when you are just accessing it.
The best option would be to simply remove the extra <br> tags from the document to begin with. There is probably a better way to accomplish whatever they are attempting to accomplish.
With some server-side scripting, it could be possible to strip them automatically when you load it, but would probably be pretty bothersome to do.
Instead, if you can't remove the <br> elements for some reason, what might be easier, if you are just dealing with a handful of <br> tags would be to simply strip them out.
Since you mention using the load() function, I'm guessing you are using jQuery.
If that's the case, something like this would cleanly strip out any extra <br> tags from the end of the document.
Here is a JSfiddle which will do it: http://jsfiddle.net/dMJ2F/
var html = "<p>A</p><br><p>B</p><br><p>C</p><br><br /><br/>";
var $html = $('<div>').append(html);
var $br;
while (($br = $html.find('br:last-child')).length > 0) {
$br.remove();
}
$('p').text($html.html());
Basically, throw the loaded stuff in to a div (in memory), then loop through and remove each <br> at the end until there aren't any. You could use regex to do this as well, but it runs a few risks that this jQuery method doesn't.
You shout delete the br-tags in your A.html.
Substitute them by changing the class .sequence with marging-top:30px
And have an other value in your B.html-file.
You also can run this:
$('br', '.sequence').remove();​
in the load-function. It will strip all br-tags.
You can't avoid fetching a part of your page, but you CAN fetch only a part of it.
According to the jQuery docs, you can call load like this:
$("#result").load("urlorpage #form-id");
That way, you only load the form html inside the result element.

what happens when you use javascript to insert a javascript widget?

can anyone explain what happens when you use javascript to insert a javascript based widget?
here's my js code:
var para = document.getElementsByTagName("p");
var cg = document.createElement("div");
cg.setAttribute("class", "twt");
cg.innerHTML='<a href="http://twitter.com/share" class="twitter-share-button"
data-count="vertical" data-via="xah_lee">Tweet</a>
<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>';
document.body.insertBefore(cg, para[1]);
it inserts the twitter widget, before the first paragraph. As you can see above, the twitter widget calls for a javascript that shows how many time the page has been tweeted.
doesn't work in Firefox, Chrome, but semi-works in IE8. What should be the expected behavior when this happens? Does the newly inserted js code supposed to execute? If so, how's it differ from if the code is on the page itself?
In order to execute the JS code you insert into a DIV via innerHTML, you need to do something like the following (courtesy of Yuriy Fuksenko at http://www.coderanch.com/t/117983/HTML-JavaScript/Execute-JavaScript-function-present-HTML )
function setAndExecute(divId, innerHTML) {
var div = document.getElementById(divId);
div.innerHTML = innerHTML;
var x = div.getElementsByTagName("script");
for (var i=0;i<x.length;i++) {
eval(x[i].text);
}
}
A slightly more advanced approach is here: http://zeta-puppis.com/2006/03/07/javascript-script-execution-in-innerhtml-the-revenge/ - look for <script> tags, take their con­tent and create a new ele­ment into the <head>.
innerHTML does not work to insert script tags (because the linked script, in most browsers, will fail to execute). Really, you should insert the script tag once on the server side and insert only the link at the location of each post (that is, if you are adding this to a blog home page that shows multiple posts, each with their own URLs).
If, for some reason, you decide that you must use one snippet of JavaScript to do it all, at least import the tweet button script in a way that will work, for example, the Google Analytics way or the MediaWiki way (look for the importScriptURI function). (Note that I do not know the specifics of the tweet button, so it might not even work.)

Injecting JavaScript into head element of website using Fiddler

I was thinking of using Fiddler for the following purpose...
I have a JavaScript based service I want to demonstrate to potential clients. In order to show them what their website could look like if they install (i.e. include) my script, I want to set up Fiddler on my PC, so that when fetching the client's website, the
<script type="text/JavaScript" src="myscript.js"></script>
line will be included in the HTML <head> section.
Can this be easily done with Fiddler? Could someone point me to where I may find the documentation covering that, if it is?
Thanks!
----Update----
For the time being I have resorted to using a BHO to add my script to the page. I use execScript(), upon onDocumentComplete, to run a simple piece of JavaScript which appends the .js file I need to the page. But EricLaw's pointers and jitter's answer seem like the way to go for a more complete (and elegant) way to do what I need.
If someone is interested I could upload the BHO code here.
-Thanks!
Open fiddler -> Menu Rules -> Customize Rules (or hit Ctrl+R)
The CustomRule.js file opens. Scroll down until you find the line
static function OnBeforeResponse(oSession: Session)
This is where your code goes. Here you can change the server response before the browser sees it.
The following code sample shows how to include a custom piece of jQuery code which replaces the Unanswered link in the horizontal menu with a link which serves as short cut to Unanswered jQuery Questions
I first show you the jQuery code I want to include
<script type='text/javascript'>
$(function() {
var newLink = 'Unanswered jQuery';
$('div#hmenus div.nav:first ul li:last a').replaceWith(newLink);
});
</script>
Now the fiddler code (based on code found in CustomRules.js and code samples from the FiddlerScript CookBook)
//is it a html-response and is it from stackoverflow.com
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "html") &&
oSession.HostnameIs("stackoverflow.com")) {
// Remove any compression or chunking
oSession.utilDecodeResponse();
var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
// Match the jQuery script tag
var oRegEx = /(<script[^>]*jquery.min.js"><\/script>)/gi;
// replace the script tag withitself (no change) + append custom script tag
oBody = oBody.replace(oRegEx, "$1<script type='text/javascript'>$(function() {$('div#hmenus div.nav:first ul li:last a').replaceWith('Unanswered jQuery');})</script>");
// Set the response body to the changed body string
oSession.utilSetResponseBody(oBody);
}
I think you should now able to hackyourself together a piece of code which fits your problem.
Example
// Match the head end
var oRegEx = /(<\/head>)/gi;
// replace with new script
oBody = oBody.replace(oRegEx, "<script type='text/javascript' src='http://url/myscript.js'></script>$1");
if you use jQuery you can add js on the fly. I would probably think you can have a method which would include/exclude your script based on some query param. This is how you would include JS with jQuery
$.getScript('someScript.js',function(){
//Do something here after your script loads
});
Haven't tried it, but how about GreaseMonkey for IE?

Dynamically inserting javascript into HTML that uses document.write

I am currently loading a lightbox style popup that loads it's HTML from an XHR call. This content is then displayed in a 'modal' popup using element.innerHTML = content This works like a charm.
In another section of this website I use a Flickr 'badge' (http://www.elliotswan.com/2006/08/06/custom-flickr-badge-api-documentation/) to load flickr images dynamically. This is done including a script tag that loads a flickr javascript, which in turn does some document.write statments.
Both of them work perfectly when included in the HTML. Only when loading the flickr badge code inside the lightbox, no content is rendered at all. It seems that using innerHTML to write document.write statements is taking it a step too far, but I cannot find any clue in the javascript implementations (FF2&3, IE6&7) of this behavior.
Can anyone clarify if this should or shouldn't work? Thanks.
In general, script tags aren't executed when using innerHTML. In your case, this is good, because the document.write call would wipe out everything that's already in the page. However, that leaves you without whatever HTML document.write was supposed to add.
jQuery's HTML manipulation methods will execute scripts in HTML for you, the trick is then capturing the calls to document.write and getting the HTML in the proper place. If it's simple enough, then something like this will do:
var content = '';
document.write = function(s) {
content += s;
};
// execute the script
$('#foo').html(markupWithScriptInIt);
$('#foo .whereverTheDocumentWriteContentGoes').html(content);
It gets complicated though. If the script is on another domain, it will be loaded asynchronously, so you'll have to wait until it's done to get the content. Also, what if it just writes the HTML into the middle of the fragment without a wrapper element that you can easily select? writeCapture.js (full disclosure: I wrote it) handles all of these problems. I'd recommend just using it, but at the very least you can look at the code to see how it handles everything.
EDIT: Here is a page demonstrating what sounds like the effect you want.
I created a simple test page that illustrates the problem:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Document Write Testcase</title>
</head>
<body>
<div id="container">
</div>
<div id="container2">
</div>
<script>
// This doesn't work!
var container = document.getElementById('container');
container.innerHTML = "<script type='text/javascript'>alert('foo');document.write('bar');<\/script>";
// This does!
var container2 = document.getElementById('container2');
var script = document.createElement("script");
script.type = 'text/javascript';
script.innerHTML = "alert('bar');document.write('foo');";
container.appendChild(script);
</script>
</body>
</html>
This page alerts 'bar' and prints 'foo', while I expected it to also alert 'foo' and print 'bar'. But, unfortunately, since the script tag is part of a larger HTML page, I cannot single out that tag and append it like the example above. Well, I can, but that would require scanning innerHTML content for script tags, and replacing them in the string by placeholders, and then inserting them using the DOM. Sounds not that trivial.
Use document.writeln(content); instead of document.write(content).
However, the better method is using the concatenation of innerHTML, like this:
element.innerHTML += content;
The element.innerHTML = content; method will replace the old content with the new one, which will overwrite your element's innerHTML!
Whereas using the the += operator in element.innerHTML += content will append your text after the old content. (similar to what document.write does.)
document.write is about as deprecated as they come. Thanks to the wonders of JavaScript, though, you can just assign your own function to the write method of the document object which uses innerHTML on an element of your choosing to append the supplied content.
Can I get some clarification first to make sure I get the problem?
document.write calls will add content to the markup at the point in the markup at which they occur. For example if you include document.write calls in a function but call the function elsewhere, the document.write output will happen at the point in the markup the function is defined not where it is called.
Therefore for this to work at all the Flickr document.write statements will need to be part of the content in element.innerHTML = content. Is this definitely the case?
You might quickly test if this should work at all by adding a single and simple document.write call in the content that is set as the innerHTML and see what this does:
<script>
var content = "<p>1st para</p><script>document.write('<p>2nd para</p>');</script>"
element.innerHTML = content;
</script>
If that works, the concept of document.write working in content set as the innerHTML of an element might just work.
My gut feeling is that it won't work, but it should be pretty straightforward to test the concept.
So you're using a DOM method to create a script element and append that to an existing element and this then causes the content of the appended script element to execute? That sounds good.
You say that the script tag is part of a larger HTML page and therefore cannot be singled out. Can you not give the script tag an ID and target it? I'm probably missing something obvious here.
In theory, yes, I can single out a script tag that way. The problem is that we potentially have dozens of situations where this occurs, so I am trying to find some cause or documentation of this behavior.
Also, the script tag does not seem to be a part of the DOM anymore after it gets loaded. In our environment, my container div remains empty, so I cannot fetch the script tag. It should work, though, because in my example above the script does not get executed, but is still part of the DOM.

Categories

Resources