I built a site for a client where I have a script which moves a sidebar div below the main content when in mobile view. This script is loaded in the footer:
// Move Global nav to top for mobile
$(window).on("resize", function() {
var windowSize = $(window).innerWidth();
if(windowSize > 767){
$(".utility-nav").insertBefore($(".global-nav"));
$(".sidebar-secondary").insertAfter($(".subnav"));
} else {
$(".global-nav").insertBefore($(".utility-nav"));
$(".sidebar-secondary").insertAfter($(".content-main"));
}
}).resize();
They are adding a third party calendar which requires them to insert code snippets that include inline scripts. When these are placed in the .sidebar-secondary div, which is moved for mobile, the content disappears. I assume that, since my script is running after these have initiated, they are being canceled out.
Is there a way to just have my script rerun any inline scripts within that div?
Here is the page they are testing:
http://www.umary.edu/sandbox-training/index.php
The scripts in the left sidebar are the ones that are malfunctioning.
Thank you!
You can retrieve all the script tags within your div and eval the text inside them
$('#run').click(function(){
$('#someSideBar').find('script').each(function(){
eval( $(this).text() );
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="someSideBar">
<script type="text/javascript">
alert('hello');
</script>
<script type="text/javascript">
alert('there');
</script>
</div>
<input type="button" id="run" value="Run">
** You should research the security implications of this before proceeding.
The reason your content disappears is because the <iframe>s that hold your content are unloaded when they are detached from the DOM, and loaded upon attaching them to the DOM again. Since the <iframe>s in question seem to be generated by a script, the second load yields an empty document. See this simple DOM test-case for seeing that load/unload bevhavior. As far as I can tell there is no way to move an iframe in the DOM in such a way that this behavior is prohibited.
You explicitly ask for this, but simply rerunning the inline <script>s may not yield the results you hope for, unless these scripts are (accidentally or purposefully) written in such a way that allows this. Be very careful with this sort of stuff. If there is a single document.write() your entire document would be overwritten. This is usually not the kind of destructive power you'd want to hand to a third party script.
You could try rearranging your content using Flexbox and the order property, so content is moved in CSS and not the DOM.
You could try rearranging the other content in such a way that you don't need to move .sidebar-secondary in the DOM. You may need to split the secondary content block into a separate <div role="complimentary"> (btw. that's what <nav> is for). Once that is done, you can move #content-start before the container of .sidebar-secondary.
Related
is there a better way to replace this kind of js function by simply collapse/toggle a div and show/hide its content?
$(function() {
$('#destselect').change(function(){
$('.dest').hide();
$('#' + $(this).val()).show();
});
});
The reason this is happening is because your js file is called on the head of your page.
Because of this, when you document.getElementsByClassName('collapsible');, colls result in an empty array, as your elements in body are not yet created.
You could either create a separate js file and add it at the end of your body (in that way you make sure your colls are created when your javascript is executed), or just wrap your code on a DOMContentLoaded event listener that will trigger your code once the document has completely loaded.
My guess would be that you are loading your script before browser finishes loading dom conetent and so when it runs the elements it is trying to add event listeners to, don't yet exist.
Try wrapping all you javascript in that file in this:
document.addEventListener("DOMContentLoaded", function(event) {
// all your code goes here
});
The above makes sure that your script is run after loading all elements on the page.
You could add a script tag to the header of your HTML file, this will import the JS file into your current page as follows
<script src="File1.js" type="text/javascript"></script>
Then call the function either in onclick in a button or in another script (usually at the bottom) of your page. Something like this:
<body>
...
<script type="text/javascript">
functionFromFile1()
</script>
</body>
Seems like your script is not executing properly due to a missing variable.
In this script https://www.argentina-fly.com/js/scripts.js
Naves variable in function UpdateDetailsDestination() is not defined.
I think you should resolve this first and then check your further code is working on not.
Please take a look into Console when running page. You'll see all JavaScript related errors there.
I'm sure this sounds a little odd, but here's the background...
We utilize a company that loads their chat program, so we can support our customers, into our page. This is done via javascript and jquery, and creates a structure like this:
<div id="myid" style="...; right: 0px;..."><div><iframe></iframe></div></div>
There's a WHOLE lot more to that, but those are the important parts. Now the tool allows us to put custom scripting, which will be placed in the iframe. My goal is to just remove the "right: 0px", which I have done via the below code, but I don't want to put that code on every page that this tool integrates with. I would like to load it into the tool, and have it run when the iframe and divs are created.
working code on parent:
$(document).ready(function() {
function checkPos() {
$('#myId').each(function() {
var oldstyle = $('#myId').attr('style');
var newstyle = oldstyle.replace(' right: 0px;','');
$('#myId').attr('style', newstyle);
});
setTimeout(checkPos, 100);
};
$(document).ready(function() {
setTimeout(checkPos, 100);
});
});
Once placed in the code include method they provide, I have trouble having it wait until the div tag actually has the "right: 0px;" in its style tag. the only thing I need to run is the three lines in the $('#myId').each(function()
Basically, I need help with having the script in the iframe target the div that the iframe is nested in.
Assuming that whatever tool your using actually lets you pass in a custom script to the content rendered in the iframe (seems fishy to me), a better way of modifying the style in jquery is to use the css function:
$('#myId').css('right', '0px');
Notice I removed the $.each function as well. You are targeting an element with an id, so there isn't any need to iterate.
Edit:
Anyways, back to the problem of delaying execution to when the target, #myId, actually exists. If they are really injecting your javascript into their page (again, seems fishy), then attaching the above code to the $(document).ready() event should do the trick, as long as this listener is attached to their document.
If all else fails, try to use the waitUntilExists plugin, here:
Source:
https://gist.github.com/buu700/4200601
Relevant question:
How to wait until an element exists?
<div class="actions">
<h3>Actions</h3>
<ul>
<li>Configurations</li>
</ul>
</div>
<script type="text/javascript" src="/jquery.min.js"></script>
<script type="text/javascript">
$('ul a').click(function(){
alert("");
});
</script>
In the above code is document.ready necessary. What i mean is, is there any case when js will be executed before html
.ready is a shortcut to DOMContentLoaded (or onreadystatechange or an assortment of workarounds for other browsers). That event fires when the DOM has been built - in other words, when the whole HTML has been downloaded.
So, as long as your script tags are the last thing before </body> (they are not inside any divs or other elements) the end result is the same, you don't need $(document).ready. That is even recommended, since putting your scripts in the <head> will slow down the loading of content.
Though I'd recommend you to adopt this pattern, to avoid problems with the $ global:
<script>
(function($){
$('ul a').click(function(){
alert("")
})
})(jQuery)
</script>
These other questions are interesting reads:
How does jQuery's "document ready" function work?
Does putting scripts on the bottom of a web page speed up page load?
When do you choose to load your javascript at the bottom of the page instead of the top?
Benefits of loading JS at the bottom as opposed to the top of the document
In your case, it seems there is no problem.
But, when you use pictures (<img />), there is a possibility for the document to execute your function (it fires "ready" event) even if the pictures aren't displayed yet.
From the documentation I've found this example:
We can animate any element, such as a simple image:
<div id="clickme">
Click here
</div>
<img id="book" src="book.png" alt="" width="100" height="123" />
With the element initially shown, we can hide it slowly:
$('#clickme').click(function() {
$('#book').fadeOut('slow', function() {
// Animation complete.
});
});
I remember from 5 years ago, that you should NEVER ever refer to any element until it was defined. Does this rule still apply? So I would have to put all that code in the footer of my web page? Or can I put it in a separate file and import it in the footer? What's best practice?
The recommended way of doing this is putting all initialization code into $(document).ready, like so:
$(document).ready(function() {
$('#foobar').click(function(event) { alert("You Clicked Me!"); });
});
You are correct; you cannot interact with a DOM element before it exists.
You have two options:
Put the code below the HTML, as you suggested.
Put the code anywhere, but wrap it in $(function() { ... }).
This construct will execute the function in the page load event, after the DOM exists.
The best practice is to place all SCRIPT elements at the bottom of the HTML document (right before the </body> tag. The reasons are:
loading of external JS files blocks loading of other resources (like images)
since JS code is executed immediately, it is better to parse the HTML code of the page first, and then execute the JS code afterwards
You can see an HTML5 template that demonstrates this practice here: http://vidasp.net/HTML5-template.html
Many people put it in the bottom of the page so other code can execute first. That becomes a bit of a moot point with the document ready syntax that waits until other content loads to the dom. So, using that logic, in theory it could go anywhere.
Scripts go best in the foot of the page, to provide for the speediest rendering of the DOM. The following idiom executes only once the DOM is ready:
$(function() { /* ... your code goes here ... */ }
If you have a lot of code, or code that is shared between multiple pages, you should link it in a separate file which can then be minified, should you need to optimize your download speed.
I asked this question, albeit in a different way a little while back. You might want to look at the answers I got too - they're quite ... philosophical:
JQuery - Best way of wiring GUI objects to events?
I have some tracking code that the provider (WebTraxs) says should be placed at the bottom of the tag. The problem is that this same code is causing everything on the page (including my jQuery code) to run AFTER the WebTraxs is executed. This execution sometimes takes long enough where images rollovers, etc aren't working because the user is mousing over images before WebTraxs has finished.
Therefore, I'm trying to add the needed tags (from WebTraxs) to the body after the page is loading in the document ready handler, using the following:
setTimeout(function(){
var daScript = '<script language="JavaScript" type="text/javascript" src="/Scripts/webtraxs.js" />';
var daOtherScript = '<noscript><img alt="" src="http://db2.webtraxs.com/webtraxs.php?id=company&st=img" />';
$('body').append(daScript);
$('body').append(daOtherScript);
},
5000);
I have two problems with the above:
In Firefox, after 5 seconds, it page goes completely blank.
In IE, there's no errors thrown, but normally you can see the WebTraxs code trying to load a tracking image in the status bar. This is not occurring with the above code.
Is there a better way to accomplish my objective here? I'm basically just trying to make sure the WebTraxs code is executed AFTER the document ready handler is executed.
Why don't you use the .getScript function:
setTimeout(function(){
$.getScript("http://path.to/Scripts/webtraxs.js");
},
5000);
What it's really curious about your code is that you add a <noscript> tag using JavaScript... it does not make any sense. If the user does not have JavaScript the setTimeout won't be fired, thus it <noscript> content won't be displayed.
I'm basically just trying to make sure the WebTraxs code is executed AFTER the document ready handler is executed.
In that case, you just have to do this:
$(document).ready(function(){
$.getScript("http://path.to/Scripts/webtraxs.js");
});
You don't have to use jQuery's DOMReady event handler. The reason people use DOMReady is that it allows the full DOM to load before firing up scripts that manipulate the page. If you call your scripts too early, parts of your page may not be accessible -- for example, if you call them before <div id="footer">...</div>, they won't be able to see $('div#footer') because it's not been pulled into the DOM yet. And that's great, except that your DOMReady methods will always execute after any in-page scripts have executed first. That's why your webtrax code is getting executed first.
But you can get the same benefits of DOMReady and still control the order of execution by calling your page scripts at the end of your document, when there's nothing left but HTML closing tags. They will be executed in the order they appear.
So try this instead:
<html>
<head>
<script type="text/javascript" src="myPageScripts.js"></script>
</head>
<body>
<div id="pagesection1"></div>
<div id="pagesection2"></div>
<div id="pagesection3"></div>
<!--NO MORE CONTENT BELOW THIS LINE-->
<script type="text/javascript">//<![CDATA[
runMyPageInitializerScripts();
//]]></script>
<script language="JavaScript" type="text/javascript" src="/Scripts/webtraxs.js" ></script>
</body>
</html>
In this script, runMyPageInitializerScripts() would still have complete access to #pagesection1, pagesection2 and pagesection3, but would not see the final script tag. So the page isn't in exactly the same condition as when DOMReady is fired, but for most scripts usually there is no downside.
<script> tags cannot use a shortcut like <script/>.
You have to use <script></script>
Anyways, I don't understand where the difference is on executing those scripts on DOMready or after a specific amount of time. If it blocks the UI it will do the same after 5 seconds no?
You are missing the closing </script> and </noscript> tags.
If you want to keep the <script> tag you may need to escape it (not sure if this persists on newest browsers, but as far as i remember you can't have <script> tags inside a script tag), take old google analytics code as example:
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
Splitting the script tag also works:
document.write("<scr"+"ipt src='somescript.js'></sc"+"ript>");
But since you're using jQuery, .getScript() is your best option.