Javascript element tag name undefined - javascript

So I'm not that great with Javascript so I'll put that forward right away. That being said, I've looked up as much as I could on this particular problem before asking, but the suggestions haven't solved my issues. I'm ultimately trying to pull all of the links from an iframe window on the same domain as the main page. Then I want to basically search that link array to match it with the current page to trigger a CSS modification to the html code (this part is not coded yet, FYI). So here is the part I have so far: Side note: The confirms are in there to debug the code and try to tell me where it's failing and what my queries are returning, they won't stay obviously when this is finished. I appreciate any advice that may help me fix this!
<script type="text/javascript">
// main is the iframe that I'm trying to search for a tags
document.getElementById("main").onload = function() {
confirm("test");
var main = document.getElementById("main");
var anchors = main.contentWindow.document.getElementsByTagName('a');
confirm(anchors[1]);
for (var i in anchors) {
confirm(anchors[i].getAttribute("href"));
}
};
</script>

I have created a plunker for you its working. I think its the placement of code in your file is causing the problem.
<iframe id="main" src="content_if.html"></iframe>
<script>
// main is the iframe that I'm trying to search for a tags
document.getElementById("main").onload = function() {
confirm("test");
var main = document.getElementById("main");
var anchors = main.contentWindow.document.getElementsByTagName('a');
confirm(anchors[1]);
for (var i in anchors) {
confirm(anchors[i].getAttribute("href"));
}
};
</script>
You should use jQuery to do this in a cross browser way. Include jQuery in page
<script src="https://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
and follow this post

There is a similar post about doing this and I agree with Mohamed-Yousef. If you can use jquery then you should do so!
$("#main").contents().find("a").each(function(element) {
// "each" will iterate through every a tag and inject them as the "element" argument
// visible in the scope of this anonymous function
});
EDIT:
You must include
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
above your code that references the $ variable. There are other ways to use jQuery but this is probably the easiest.

Related

Rerun Jquery function onclick

I have a simple jquery script that changes the url path of the images. The only problem is the doesn't apply after I click the load more button. So I'm trying to do a workaround where it calls the script again after clicking the button.
<script type='text/javascript'>
$(document).ready(function ReplaceImage() {
$(".galleryItem img").each(function() {
$(this).attr("src", function(a, b) {
return b.replace("s72-c", "s300")
})
})
});
</script>
HTML
Load More
While Keith's answer will get you what you are looking for, I really can't recommend that approach. You are much better off with something like this.
<script type="text/javascript">
$(function() {
var replaceImage = function() {
$('.galleryItem img').each(function() {
$(this).attr('src', function(index, value) {
return value.replace('s72-c', 's300');
});
});
};
replaceImage();
$('.js-replace-image').on('click', replaceImage);
});
</script>
Using this html
<button class="js-replace-image">Load More</button>
By taking this approach, you do not expose any global variables onto the window object, which can be a point of issue if you work with other libraries (or developers) that don't manage their globals well.
Also, by moving to a class name and binding an event handler to the DOM node via JavaScript, you future proof yourself much more. Also allows yourself to easily add this functionality to more buttons very easily but just adding a class to it.
I updated the anchor tag to a button because of the semantics of what you need to do - it doesn't link out anywhere, it's just dynamic functionality on the page. This is what buttons are best served for.
I'd also recommend putting this in the footer of your site, because then, depending on your situation, you will already have the images updated properly without having to click the button. The only need for the button would be if you are dynamically inserting more images on the page after load, or if this script was in the head of your document (meaning jQuery couldn't know about the images yet).
I hope this helps, reach out if you have questions.

Site is scrolling down automatically aftear search

This is my site URL which is developed in magento(www.theprinterdepo.com), when a user searches, the page automatically scrolls down to the bottom. I have no idea if this due to any php code, jquery or javascript but I need help to detect and fix this.
I would paste code here, but I don't know what's responsible for this behaviour.
I thought it was IE problem, but its also reflects in Google Chrome.
thanks
<script type="text/javascript">window.onload=function()
{
var deftxt='Test';
var def=document.getElementById('ea');
def.onfocus = function()
{
this.value=(this.value==deftxt)?'':this.value;
}
def.onblur= function()
{
if(this.value=='')
{
this.value=deftxt;
}
else
this.value;
}
***def.focus();***
def.blur();
}</script>
Here the textbox having id "ea" is set focus on. Please remove "def.focus();". Your issue will be solved.
Remove def.focus() from your script tag in the footer.
Perhaps unrelated - but unless I am mistaken - you have an accidental closure/circular reference. When you reference a JS object that contains a reference to a DOM object, which in turn references the JS object - you have a closure that creates a circular reference. In this case def.onBlur() / def.blur() is the culprit. (See the code below - a textbook example of a circular reference.) Not sure if this is causing your issue, but this is definitely something I would look into.
<script>
myFunction(){
var elObj = document.getElementById('myDiv');
elObj.onclick= function() {
alert('This function is leaking.');
}}
myFunction();
</script>

How to go to an specific anchor when entering the page (doesn't work)

First of all, thats my current state of play: thsbrk.de.
The black boxes should be e.g. a about section. I want to achieve that if you enter my page (thsbrk.de) you directly go to my reference section (anchor '#references'). Then, if you hit the about link you will scroll up to that about section. I already tried to make it working but it doesn't. The anchor seems to be not working.
It would be awesome if someone could look at my code and offer me a solution :)
(The scroll isn't implemented yet, I only ask for the anchor problem)
EDIT: Here I've got a example how it should work: Example
Give a script tag like this in the head.Let it be the first script also.
<script>
location.href="http://thsbrk.de/#references"
</script>
From your code, you have did the same. But just try reordering the script tags it might work.
Plain JS:
window.onload=function() {
var anchorHash = 'references';
document.getElementsByName(anchorHash)[0].scrollIntoView();
}
Here is a jQuery example from 2009 - there may be newer ways
How do I scroll a row of a table into view (element.scrollintoView) using jQuery?
In your case this might work
$(document).ready(function() {
var anchorHash = 'references';
var pos = $('#'+anchorHash).position();
window.scrollTo(0,pos.top);
});
Try this and tell me the result:
$(document).ready(function() {
window.location.href = '#references';
});
and then modify your anchor tag like this:
<a name="references">Here</a>

Trying to load an API and a JS file dynamically

I am trying to load Skyscanner API dynamically but it doesn't seem to work. I tried every possible way I could think of and all it happens the content disappears.
I tried console.log which gives no results; I tried elements from chrome's developers tools and while all the content's css remains the same, still the content disappears (I thought it could be adding display:none on the html/body sort of). I tried all Google's asynch tricks, yet again blank page. I tried all js plugins for async loading with still the same results.
Skyscanner's API documentation is poor and while they offer a callback it doesn't work the way google's API's callback do.
Example: http://jsfiddle.net/7TWYC/
Example with loading API in head section: http://jsfiddle.net/s2HkR/
So how can I load the api on button click or async? Without the file being in the HEAD section. If there is a way to prevent the document.write to make the page blank or any other way. I wouldn't mind using plain js, jQuery or PHP.
EDIT:
I've set a bounty to 250 ontop of the 50 I had previously.
Orlando Leite answered a really close idea on how to make this asynch api load although some features doesn't work such as selecting dates and I am not able to set styling.
I am looking for an answer of which I will be able to use all the features so that it works as it would work if it was loading on load.
Here is the updated fiddle by Orlando: http://jsfiddle.net/cxysA/12/
-
EDIT 2 ON Gijs ANSWER:
Gijs mentioned two links onto overwriting document.write. That sounds an awesome idea but I think it is not possible to accomplish what I am trying.
I used John's Resig way to prevent document.write of which can be found here: http://ejohn.org/blog/xhtml-documentwrite-and-adsense/
When I used this method, I load the API successfuly but the snippets.js file is not loading at all.
Fiddle: http://jsfiddle.net/9HX7N/
I belive what you want is it:
function loadSkyscanner()
{
function loaded()
{
t.skyscanner.load('snippets', '1', {'nocss' : true});
var snippet = new t.skyscanner.snippets.SearchPanelControl();
snippet.setCurrency('GBP');
snippet.setDeparture('uk');
snippet.draw(document.getElementById('snippet_searchpanel'));
}
var t = document.getElementById('sky_loader').contentWindow;
var head = t.document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange= function() {
if(this.readyState == 'complete') loaded();
}
script.onload= loaded;
script.src= 'http://api.skyscanner.net/api.ashx?key=PUT_HERE_YOUR_SKYSCANNER_API_KEY';
head.appendChild(script);
}
$("button").click(function(e)
{
loadSkyscanner();
});
It's load skyscanner in iframe#sky_loader, after call loaded function to create the SearchPanelControl. But in the end, snippet draws in the main document. It's really a bizarre workaround, but it works.
The only restriction is, you need a iframe. But you can hide it using display:none.
A working example
EDIT
Sorry guy, I didn't see it. Now we can see how awful is skyscanner API. It puts two divs to make the autocomplete, but not relative to the element you call to draw, but the document.
When a script is loaded in a iframe, document is the iframe document.
There is a solution, but I don't recommend, is really a workaround:
function loadSkyscanner()
{
var t;
this.skyscanner;
var iframe = $("<iframe id=\"sky_loader\" src=\"http://fiddle.jshell.net/orlleite/2TqDu/6/show/\"></iframe>");
function realWorkaround()
{
var tbody = t.document.getElementsByTagName("body")[0];
var body = document.getElementsByTagName("body")[0];
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
}
function snippetLoaded()
{
skyscanner = t.skyscanner;
var snippet = new skyscanner.snippets.SearchPanelControl();
snippet.setCurrency('GBP');
snippet.setDeparture('uk');
snippet.draw(document.getElementById('snippet_searchpanel'));
setTimeout( realWorkaround, 2000 );
}
var loaded = function()
{
console.log( "loaded" );
t = document.getElementById('sky_loader').contentWindow;
t.onLoadSnippets( snippetLoaded );
}
$("body").append(iframe);
iframe.load(loaded);
}
$("button").click(function(e)
{
loadSkyscanner();
});
Load a iframe with another html who loads and callback when the snippet is loaded. After loaded create the snippet where you want and after set a timeout because we can't know when the SearchPanelControl is loaded. This realWorkaround move the autocomplete divs to the main document.
You can see a work example here
The iframe loaded is this
EDIT
Fixed the bug you found and updated the link.
the for loop has gone and added a while, works better now.
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
For problematic cases like this, you can just overwrite document.write. Hacky as hell, but it works and you get to decide where all the content goes. See eg. this blogpost by John Resig. This ignores IE, but with a bit of work the trick works in IE as well, see eg. this blogpost.
So, I'd suggest overwriting document.write with your own function, batch up the output where necessary, and put it where you like (eg. in a div at the bottom of your <body>'). That should prevent the script from nuking your page's content.
Edit: OK, so I had/took some time to look into this script. For future reference, use something like http://jsbeautifier.org/ to investigate third-party scripts. Much easier to read that way. Fortunately, there is barely any obfuscation/minification at all, and so you have a supplement for their API documentation (which I was unable to find, by the way -- I only found 'code wizards', which I had no interest in).
Here's an almost-working example: http://jsfiddle.net/a8q2s/1/
Here's the steps I took:
override document.write. This needs to happen before you load the initial script. Your replacement function should append their string of code into the DOM. Don't call the old document.write, that'll just get you errors and won't do what you want anyway. In this case you're lucky because all the content is in a single document.write call (check the source of the initial script). If this weren't the case, you'd have to batch everything up until the HTML they'd given you was valid and/or you were sure there was nothing else coming.
load the initial script on the button click with jQuery's $.getScript or equivalent. Pass a callback function (I used a named function reference for clarity, but you can inline it if you prefer).
Tell Skyscanner to load the module.
Edit #2: Hah, they have an API (skyscanner.loadAndWait) for getting a callback once their script has loaded. Using that works:
http://jsfiddle.net/a8q2s/3/
(note: this still seems to use a timeout loop internally)
In the skyrunner.js file they are using document.write to make the page blank on load call back... So here are some consequences in your scenario..
This is making page blank when you click on button.
So, it removes everything from page even 'jQuery.js' that is why call back is not working.. i.e main function is cannot be invoked as this is written using jQuery.
And you have missed a target 'div' tag with id = map(according to the code). Actually this is the target where map loads.
Another thing i have observed is maps is not actually a div in current context, that is maps api to load.
Here you must go with the Old school approach, That is.. You should include your skyrunner.js file at the top of the head content.
So try downloading that file and include in head tag.
Thanks

How to dynamically insert a <script> tag via jQuery after page load?

I'm having problems getting this to work. I first tried setting my script tags as strings and then using jquery replaceWith() to add them to the document after page load:
var a = '<script type="text/javascript">some script here</script>';
$('#someelement').replaceWith(a);
But I got string literal errors on that var. I then tried encoding the string like:
var a = '&left;script type="text/javascript">some script here<\/script>';
but sending that to replaceWith() outputs just that string to the browser.
Can someone please let me know how you would go about dynamically adding a <script> tag into the browser after page load, ideally via jQuery?
You can put the script into a separate file, then use $.getScript to load and run it.
Example:
$.getScript("test.js", function(){
alert("Running test.js");
});
Try the following:
<script type="text/javascript">
// Use any event to append the code
$(document).ready(function()
{
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "http://scriptlocation/das.js";
// Use any selector
$("head").append(s);
});
http://api.jquery.com/append
Here's the correct way to do it with modern (2014) JQuery:
$(function () {
$('<script>')
.attr('type', 'text/javascript')
.text('some script here')
.appendTo('head');
})
or if you really want to replace a div you could do:
$(function () {
$('<script>')
.attr('type', 'text/javascript')
.text('some script here')
.replaceAll('#someelement');
});
A simpler way is:
$('head').append('<script type="text/javascript" src="your.js"></script>');
You can also use this form to load css.
This answer is technically similar or equal to what jcoffland answered.
I just added a query to detect if a script is already present or not.
I need this because I work in an intranet website with a couple of modules, of which some are sharing scripts or bring their own, but these scripts do not need to be loaded everytime again. I am using this snippet since more than a year in production environment, it works like a charme. Commenting to myself: Yes I know, it would be more correct to ask if a function exists... :-)
if (!$('head > script[src="js/jquery.searchable.min.js"]').length) {
$('head').append($('<script />').attr('src','js/jquery.searchable.min.js'));
}
Here is a much clearer way — no need for jQuery — which adds a script as the last child of <body>:
document.body.innerHTML +='<script src="mycdn.js"><\/script>'
But if you want to add and load scripts use Rocket Hazmat's method.
Example:
var a = '<script type="text/javascript">some script here</script>';
$('#someelement').replaceWith(a);
It should work. I tried it; same outcome. But when I used this:
var length = 1;
var html = "";
for (var i = 0; i < length; i++) {
html += '<div id="codeSnippet"></div>';
html += '<script type="text/javascript">';
html += 'your script here';
html += '</script>';
}
$('#someElement').replaceWith(a);
This worked for me.
Edit: I forgot the #someelement (btw I might want to use #someElement because of conventions)
The most important thing here is the += so the html is added and not replaced.
Leave a comment if it didn't work. I'd like to help you out!
There is one workaround that sounds more like a hack and I agree it's not the most elegant way of doing it, but works 100%:
Say your AJAX response is something like
<b>some html</b>
<script>alert("and some javscript")
Note that I've skipped the closing tag on purpose. Then in the script that loads the above, do the following:
$.ajax({
url: "path/to/return/the-above-js+html.php",
success: function(newhtml){
newhtml += "<";
newhtml += "/script>";
$("head").append(newhtml);
}
});
Just don't ask me why :-) This is one of those things I've come to as a result of desperate almost random trials and fails.
I have no complete suggestions on how it works, but interestingly enough, it will NOT work if you append the closing tag in one line.
In times like these, I feel like I've successfully divided by zero.
If you are trying to run some dynamically generated JavaScript, you would be slightly better off by using eval. However, JavaScript is such a dynamic language that you really should not have a need for that.
If the script is static, then Rocket's getScript-suggestion is the way to go.

Categories