Embeded script only running properly on second pageview - javascript

I am having a bit of my website only properly work whenever you visit the page the second time. 3 fields are not shown in the page the first time you view it, but after going to another section of the site and coming back, so long as you do not reload the page, the fields will properly display.
To reproduce the issue, go to http://imperialgaming.tech/.
Click on the Minecraft logo. Take note of the seemingly bad grammar in at the bottom of the area of text as the page tries to inform you about the status of the server. Now, click on the teamspeak logo at the bottom of the page, and then click again on the minecraft icon at the bottom of the page. You will now notice that the message at the bottom of the text has much better grammar, and more information to it. Refreshing the page resets this back to the broken version. You can find the code here. I apologize, squarespace breaks my indentation. Let me know if you have any idea what causes this or how to fix it.
Thanks!

I think the problem is because the script is running before the elements have been created in the DOM. Try adding the script section after this div block instead of before it:
<div class="server-status">
Our server is currently <span class="server-online"></span>!
There are <span class="server-players"></span> of <span class="server-max-players"></span> online.
</div>
<script>
MinecraftAPI.getServerStatus('mc.imperialgaming.tech', {
port: 25565 // optional, only if you need a custom port
}, function (err, status) {
if (err) {
return document.querySelector('.server-status').innerHTML = 'Error loading status';
}
document.querySelector('.server-online').innerHTML = status.online ? 'up' : 'down';
document.querySelector('.server-players').innerHTML = status.players.now;
document.querySelector('.server-max-players').innerHTML = status.players.max;
});
</script>
Updated
If within squarespace you are unable to move the script to be after (as I see that it is in the <head>) then try wrapping the entire code in jquery document ready block (this way the script will wait for the DOM to load) and use jquery selectors:
<script>
jQuery(document).ready(function($) {
MinecraftAPI.getServerStatus('mc.imperialgaming.tech', {
port: 25565 // optional, only if you need a custom port
}, function (err, status) {
if (err) {
return document.querySelector('.server-status').innerHTML = 'Error loading status';
}
$('.server-online').innerHTML = status.online ? 'up' : 'down';
$('.server-players').innerHTML = status.players.now;
$('.server-max-players').innerHTML = status.players.max;
});
});
</script>

Related

Re-run an html <script> in React

I'm making a component in React that has Facebook data pulled from an API call. The API call returns and updates a list, which render() will then populate with tags that are supposed to be converted to actual images by a script from Facebook's website. Something like this:
<a data-pin-do={'embedData'} href={'https://www.facebook.com/data/12345'} />
My html file includes this script, which I assume runs through the HTML code and converts the tags to something viewable.
<script async defer src="//assets.pinterest.com/js/pinit.js"></script>
However, the problem I'm running into is that the script only runs when the webpage initially loads, and then never again. Since I'm adding more tags in an API call and then updating the list via the props, it means I'm left with a bunch of tags that don't get converted when the call returns.
I've inspected the React console & html and can confirm the tags are there, it's just that the dynamically converted tags don't show up as pins.
I've already tried using jquery and document.appendChild() to add/get the script in componentDidUpdate(), but it doesn't seem to be working. Anybody have any clue how I can get around this?
If you look in your devtools you should see that when the html page loads this script it is just making a GET request to the script src (http://assets.pinterest.com/js/pinit.js). So, you should be able to recreate that behavior by making a simple http GET request to that url each time you need to rerun the script.
Try using:a do-while in your script:
var repeat = 0
Do {
// Your code goes here
repeat = repeat + 1
} while(repeat <= 10)
Note: replace 10 with times you want the script to repeat
If you wan't to add a rule to this (so it only runs when...) do:
var repeat = 'yes'
Do {
// Your code goes here
} while(repeat == 'yes')
Now your code will only run when repeat is equal to yes
In action
Stop repeating
Start repeating
<script>
var repeat = 'yes'
Do {
// Your code goes here
If(var1 == var2) { repeat = 'no' }
} while(repeat == 'yes')
</script>

If user came from previous page on site then this, else do this

What would be a viable way to accomplish the following:
A website has two pages; Parent page and Inside page. If user came to the Inside page directly by typing in the address or by following a link from a page other than Parent page, then show "foo". If user came to the Inside page from the parent page, then show "bar".
I would need this done in JS if possible. If not, PHP is a secondary choice.
You can get the page the user came from with document.referrer.
So you could implement your solution like this:
if (document.referrer === 'yoursite.com/parentpage') {
// do bar
} else {
// do foo
}
Please try this
This code in second page
jQuery(window).load(function() {
if (sessionStorage.getItem('dontLoad') == null) {
//show bar
}
else{
//show foo
}
});
This code in parent page
jQuery(window).load(function() {
sessionStorage.setItem('dontLoad','true')
});
with php:
There is a simple way is to create a mediator page which redirect to inner page after make a session / cookie.. then if you'll get session / cookie, you show foo & unset session.
if someone directly come from url, no session / cookie found & it show bar..
You can use the document.referrer but this is not always set. You could add a parameter to the URL on the parent page and then check for its existance in the child page
Link on the parent page:
<a href='myChildPage.html?fromParent=1'>My Child Page</a>
JS code on your child page:
var fromParent=false;
var Qs = location.search.substring(1);
var pairs = Qs.split("&");
for(var i = 0; i < pairs.length; i++){
var pos = pairs[i].indexOf('=');
if(pos!==-1){
var paramName = pairs[i].substring(0,pos);
if(paramName==='fromParent'){
fromParent=true;
break;
}
}
}
if(fromParent){
alert("From Parent");
}else{
alert("NOT From Parent");
}
This method isnt 100% foolproof either as users could type in the same URL as your parent page link. For better accuracy check the document.referrer first and if not set use the method i've outlined above
intelligent rendering with jQuery
After using #Rino Raj answer, i noticed it needed improvement.
In javascript, the load() or onload() event is most times much slower,
since it waits for all content and images to load before executing your attached functions.
While an event attached to jQuery’s ready() event is executed as soon as the DOM is fully loaded, or all markup content, JavaScript and CSS, but not images.
Let me explain this basing, on code.
When i used #Rino Raj's code, with load() event, it works but on the second/called page, the content appears before class="hide fade" is added (which I don't really want).
Then i refactored the code, using the ready() event, and yes,
the content that i intended to hide/fade doesn't appear at all.
Follow the code, below, to grasp the concept.
<!-- Parent/caller page -->
<script type="text/javascript">
$(document).ready(function() {
sessionStorage.setItem('dontLoad', 'true');
});
</script>
<!-- Second/called page -->
<script type="text/javascript">
$(document).ready(function() {
if(sessionStorage.getItem('dontLoad') == null) {
$("#more--content").removeClass("hide fade");
} else {
$("#more--content").addClass("hide fade");
}
});
</script>

how to get actual page load after replacing content by using Jquery replaceWith()

I am working on a project that has a html page that has links to libraries- in addition it dynamically prints part of the page with Jquery replaceWith().
The dynamically printed part includes src to images, etc.
What is happening is the images are not loaded, so the page is not rendering immediately.
I need to somehow get the equivalent of a window.onload event that tells me when the page
has loaded all that stuff, so that I start the code, etc that affects the page.
I have tried tacking it on at the end of the script- that does not seem to work-
any suggestions/ideas anyone?
I have tried window.onload, etc, I am wondering if I attach
$("#content").ready() that would work vs load, or if I have to write a window onload inside the content that is written in by replaceWith(). I have actually tried some of this already and nothing seems to work, but I may be implementing it incorectly.
Thanks!
Note, No html , js appear at original post.
Try below (adjustable) pattern, i.e.g., assign different class to "original content" (.ocontent) , "new content" (.ncontent), check utilizing $.is()
var callback = function (status) {
if (status === false) {
console.log(status);
// new content ready
// do stuff
};
if (status === true) {
console.log(status);
// old content present
// do stuff
};
};
$.when($(".ocontents").replaceWith("<img class=ncontents />"))
.done(function(o) {
callback($("#content *").is(o));
});
jsfiddle http://jsfiddle.net/guest271314/6agJz/
See http://api.jquery.com/is/

How to refresh a Div every 10 seconds without refreshing the entire page?

I'm working on a website platform that doesn't allow for any server sided scripting, so jquery and javascript are pretty much all I have to work with. I am trying to create a script to work with the site that will update a div that contains an inbox message count every 10 seconds. I've been successful with making the div refresh every ten seconds, but the trouble lies in the page views count. My script is refreshing the whole page and counting for a page view, but I only want to refresh just the one div. An example of the trouble my script causes is when viewing anything on the site that has a page view counter (forum posts, blog posts, ect...), the page views go crazy because of the script refreshing. I'm pretty new to Javascript, so I'm not entirely sure there is a way around this.
What I'm working with is below:
<div id="msgalert" style="display: none"; "width: 100px !important">
You have $inbox_msg_count new messages.
</div>
$inbox_msg_count is a call that grabs the message count, and provided by the platform the site is on. It displays the message count automatically when used.
Then the script that does all the work is this:
<script>
setInterval(function(facepop){
var x= document.getElementById("SUI-WelcomeLine-InboxNum");
var z = x.innerText;
if(x.textContent.length > 0)
$("#msgalert").show('slow');
}, 1000);
facepop();
</script>
<script>
setInterval(function() {
$("#msgalert").load(location.href+" #msgalert>*","");
}, 1000); // seconds to wait, miliseconds
</script>
I realize I've probably not done the best job of explaining this, but that's because I'm pretty confused in it myself. Like I mentioned previously, this code function just how I want it, but I don't want it to refresh the entire page and rack up the page views. Any help is much appreciated.
You might try to look into iframe and use that as a way to update/refresh your content (div). First setup an iframe, and give it an id, then with JS grab the object and call refresh on it.
well your prob seems a little diff so i think submitting a from within the div might help you so ...
$(document).ready(function()
{
// bind 'myForm' and provide a simple callback function
$("#tempForm").ajaxForm({
url:'../member/uploadTempImage',//serverURL
type:'post',
beforeSend:function()
{
alert(" if any operation needed before the ajax call like setting the value or retrieving data from the div ");
},
success:function(e){
alert("this is the response data simply set it inside the div ");
}
});
});
I think this could probably be done without a form, and definitely without iframes (shudder)..
Maybe something like this?
$(document).ready(function()
{
setInterval(function(facepop)
{
var x= document.getElementById("SUI-WelcomeLine-InboxNum");
var z = x.innerText;
if(x.textContent.length > 0)
$("#msgalert").show('slow');
$.ajax({
type: "POST",
url: location.href,
success: function(msg)
{
$("#msgalert").html(msg);
}
});
},1000);
It's not entirely clear exactly what you're trying to do (or it may just be that I'm ultra tired (it is midnight...)), but the $.ajax() call in the above is the main thing I would suggest.
Encapsulating both functions in a single setInterval() makes things easier to read, and will extinguish the 1 second gap between showing the msgalert element, and "re-loading" it.

shadowbox stops working after jquery function call

I have a shadowbox script. When I load the page everything works fine, but when I call this jquery load function and then try to trigger the shadowbox by clicking on the image, the large image opens in new window instead.
Here's the code:
<link href="CSS/main.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="shadowbox-3.0.3/shadowbox.js"></script>
<script type="text/javascript">
Shadowbox.init();
</script>
<p id="compas"></p>
Any idea why this is happening?
EDIT
So, we finally get the bottom of this. 15 hours after first commenting on this issue, and at least 50 iterations later, we finally have identified what the problem is and how to fix it.
It actually struck me suddenly when I was creating local aaa.html and bbb.html on my server. That was when it hit me that the element nodes for the content that was being replaced was being removed altogether from the DOM when $.load() runs the callback function. So, once the #menu-home content elements were replaced, they were removed from the DOM and no longer had Shadowbox applied to them.
Once I figured this out, it was just a matter of a single web search and I found:
Nabble-Shadowbox - Reinit Shadowbox
Specifically, the response from mjijackson. What he describes is how to "restart" (reinitialize) Shadowbox using:
Shadowbox.clearCache();
Shadowbox.setup();
So once the #menu-home content was reloaded, what needs to happen is the Shadowbox cache needs to be cleared (essentially, shutting it down on the page), then the Shadowbox.setup() is run, which will detect the elements all over again. You don't run the Shadowbox.init() method again either.
I noticed that you had tried to copy/paste the Shadowbox.setup() in after the $.load(), at least sequentially in the code. However, this wasn't going to work, due to the cache clearing that needs to happen first, and primarily because the .clearCache() and .setup() functions need to be run after the $.load() completes (finishes and runs any callbacks). Those two functions need to be run in the $.load() callback handler; otherwise, you're running it's immediately, but the $.load() is asynchronous and will complete at some later time.
I'm going to go over some other changes I made, just so you understand what, why and wherefore.
Note, I'm not sure if you're familiar with <base>, but the following is at the top of the HEAD element:
<base href="http://62.162.170.125/"/>
This just let's me use the resource files on your computer. You'll not want to use this on your actual site more than likely. If you copy/paste, make sure and remove this line.
<div id="menu">
<ul>
<li><a id="menu-home" href="index.html" rel="http://jfcoder.com/test/homecontent.html">Home</a></li>
<li><a id="menu-services" href="services.html" rel="http://jfcoder.com/test/servicescontent.html">Services</a></li>
<li><a id="menu-tour" href="tour.html" rel="http://jfcoder.com/test/tourcontent.html">Tour</a></li>
<li><a id="menulogin" href="login.html">Login</a></li>
</ul>
</div>
Here, you'll notice I have a relative url in the HREF attribute, and a link to some pages on my server. The reason for the links to my server is that I couldn't access your aaa.html and bbb.html files through AJAX due to cross-site scripting limitations. The links to my website should be removed as well.
Now, the reason I'm using the rel attribute here is that I want allow for the links by way of the href attribute to continue to work in case the JS doesn't function correctly or there's some other error. If you have separate files, one for full HTML document and another for just the fragments, this is what you'll want to do. If you can serve both the full document AND the content-only from the linked file, then you probably don't need the rel attribute, but you'll need to manage the request so the server knows how to respond (full document or just the content part).
var boxInitialize = function(){
try {
if (!Shadowbox.initialized) {
Shadowbox.init();
Shadowbox.initialized = true;
} else {
Shadowbox.clearCache();
Shadowbox.setup();
}
} catch(e) {
try {
Shadowbox.init();
} catch(e) {};
}
};
All I've done here is create a central location for the initialization/setup requests. Fairly straightforward. Note, I added the Shadowbox.initialized property so I could keep track of if the Shadowbox.init() had run, which can only be run once. However, keeping it all in one spot is a good idea if possible.
I also created a variable function which can be called either as a regular function:
boxInitialize();
Or as a function reference:
window.onload = boxInitialize; // Note, no () at the end, which execute the function
You'll probably notice I removed the $() and replaced them with jQuery() instead. This can turn into a real nightmare if you end up with an environment with multiple frameworks and libraries competing for $(), so it's best to avoid it. This actually just bit me real good the other day.
Since we have a closure scope within the .ready() callback, we can take advantage of that to save several "private" variables for ow use at different times in the scripts execution.
var $ = jQuery,
$content = jQuery("#content"), // This is "caching" the jQuery selected result
view = '',
detectcachedview = '',
$fragment,
s = Object.prototype.toString,
init;
Note the , at the end of all but the last line. See how I "imported" the $ by making it equal to the jQuery variable, which means you could actually use it in that#.
var loadCallback = function(response, status, xhr){
if (init != '' && s.call(init) == '[object Function]') {
boxInitialize();
}
if (xhr.success()
&& view != ''
&& typeof view == 'string'
&& view.length > 1) {
$fragment = $content.clone(true, true);
cacheContent(view, $fragment);
}
};
This runs when the $.load() completes the process of the AJAX request. Note, the content returned in the request has already been placed on the DOM by the time this runs. Note as well that we're storing the actual cached content in the $content.data(), which should never be removed from the page; only the content underneath it.
var cacheContent = function(key, $data){
if (typeof key == 'string'
&& key.length > 1
&& $data instanceof jQuery) {
$content.data(key, $data.html());
$content.data(detectcachedview, true);
}
};
cacheContent() is one a method you may not want; essentially, if it was already loaded on a previous request, then it will be cached and then directly retrieved instead of initiating another $.load() to get the content from the server. You may not want to do this; if so, just comment out the second if block in the menuLoadContent() function.
var setContent = function(html){
$content.empty().html(html);
if (init != '' && s.call(init) == '[object Function]') {
boxInitialize();
}
};
What this does is first empty the $content element of it's contents/elements, then add the specified string-based markup that we saved earlier by getting the $content.html(). This is what we'll re-add when possible; you can see once the different links have been clicked and loaded, reclicking to get that to redisplay is really quick. Also, if it's the same request as currently loaded, it also will skip running the code altogether.
(We use $content like because it is a reference to a variable containing a jQuery element. I am doing this because it's in a closure-scope, which means it doesn't show up in the global scope, but will be available for things like event handlers.
Look for the inline comments in the code.
var menuLoadContent = function(){
// This is where I cancel the request; we're going to show the same thing
// again, so why not just cancel?
if (view == this.id || !this.rel) {
return false;
}
// I use this in setContent() and loadCallback() functions to detect if
// the Shadowbox needs to be cleared and re-setup. This and code below
// resolve the issue you were having with the compass functionality.
init = this.id == 'menu-home' ? boxInitialize : '';
view = this.id;
detectcachedview = "__" + view;
// This is what blocks the superfluous $.load() calls for content that's
// already been cached.
if ($content.data(detectcachedview) === true) {
setContent($content.data(view));
return false;
}
// Now I have this in two different spots; there's also one up in
// loadCallback(). Why? Because I want to cache the content that
// loaded on the initial page view, so if you try to go back to
// it, you'll just pickup what was sent with the full document.
// Also note I'm cloning $content, and then get it's .html()
// in cacheContent().
$fragment = $content.clone(true, true);
cacheContent(view, $fragment);
// See how I use the loadCallback as a function reference, and omit
// the () so it's not called immediately?
$content.load(this.rel, loadCallback);
// These return false's in this function block the link from navigating
// to it's href URL.
return false;
};
Now, I select the relevant menu items differently. You don't need a separate $.click() declaration for each element; instead, I select the #menu a[rel], which will get each a element in the menu that has a rel="not empty rel attribute". Again, note how I use menuLoadContent here as a function reference.
jQuery("#menu a[rel]").click(menuLoadContent);
Then, at the very bottom, I run the boxInitialize(); to setup Shadowbox.
Let me know if you have any questions.
I think I might be getting to the bottom of this. I think the flaw is the way you're handling the $.load() of the new content when clicking a menu item, coupled with an uncaught exception I saw having to do with an iframe:
Uncaught exception: Unknown player iframe
This Nabble-Shadowbox forum thread deals with this error. I'm actually not getting that anymore, however I think it came up with I clicked on the tour menu item.
Now, what you're doing to load the content for the menu items really doesn't make any sense. You're requesting an entire HTML document, and then selecting just an element with a class="content". The only benefit I can see for doing this is that the page never reloads, but you need to take another approach to how to get and display the data that doesn't involve downloading the entire page through AJAX and then trying to get jQuery to parse out just the part you want.
I believe handling the content loading this way is the root cause of your problem, hence the $.load() toggling of menu views breaks your page in unexpected ways.
Question: Why don't you just link to the actual page and skip all the $.load() fanciness? Speed-wise, it won't make that much of an impact, if any at all. It just doesn't make sense to use AJAX like this, when you could just link them to the same content without issue.
There are two alternatives that would allow you to prevent roundtrip page reloads:
Setup your AJAX calls to only request the .content portion of the markup if you have the ?contentonly=true flag in the URL, not the entire HTML document. This is how it's traditionally done, and is usually relative simple to do if you have a scripting environment.
$(".content").load('index.html?contentonly=true');
Then your server responds only with the content view requested.
Serve all of the content views within the same HTML document, then show as appropriate:
var $content = $('.content');
$content.find('.content-view').hide();
$content.find('#services-content').show();
It doesn't look like you have a whole lot of content to provide, so the initial page load probably won't have that much of an impact with this particular approach. You might have to look into how to preload images, but that's a very well known technique with many quality scripts and tutorials out there.
Either one of these techniques could use the #! (hashbang) technique to load content, although I believe there are some issues with this for search engines. However, here is a link to a simple technique I put together some time ago:
http://jfcoder.com/test/hash.html
Also, this is just a tip, but don't refer to your "content" element with a class, ie, .content. There should only be one content-displaying element in the markup, right? There's not more than one? Use an id="content"; that's what ID attributes are for, to reference a single element. classes are meant to group elements by some characteristic they share, so above when I .hide() the inline content views (see #2), I look for all of the class="content-view" elements, which are all similar (they contain content view markup). But the $content variable should refer to $('#content');. This is descriptive of what the elements are.
This worked for us, we made a site that used vertical tabs and called in the pages with our shadowbox images using jQuery.load
Just give all of your anchor tags the class="sbox" and paste this script in the header.
<script>
Shadowbox.init({
skipSetup:true,
});
$(document).ready(function() {
Shadowbox.setup($('.sbox'));//set up links with class of sbox
$('a.sbox').live('click',function(e){
Shadowbox.open(this);
//Stops loading link
e.preventDefault();
});
});
</script>
Note: we had to put the .sbox class on all our rel="shadowbox" anchors as well as the on the anchor for the tab that called the .load
Thanks to this guy-> http://www.webmuse.co.uk/blog/shadowbox-ajax-and-other-generated-content-with-jquery-and-javascript/
Well, based on Shem's answer, this is my solution.
Every click on specific class, setup and open shadowbox with elements from same class:
jQuery('.sb-gallery a').live('click',function(e){
Shadowbox.setup(jQuery('.sb-gallery a'));
Shadowbox.open(this);
//Stops loading link
e.preventDefault();
});
Thanks to all

Categories

Resources