how to combine window.location.href and DOMContentLoaded - javascript

I am using ipinfo.io to detect the visitors country and then reload the page with an appended querystring based on that. When the page loads I would like to do something after DOMContentLoaded.
DOMContentLoaded is called fine if I don't reload the page, but I would like it to work with the reload. How do I achieve that?
Sample code below:
jQuery.getJSON('https://ipinfo.io', function(data){
if(data){
if(data.country){
if(data.country.toLowerCase()=='us')
{
window.location.replace(window.location.href+"?location=us");
}
}
}
});
//works when page is not reloaded
document.addEventListener("DOMContentLoaded",
function() {
doSomething...
});

You have a race condition here: based on your description it is likely that the getJSON command is "racing" with the DOMContentLoaded event. If getJSON is successful before your DOM is ready, then it will redirect the page and stop all script execution on the page.
To avoid that, try moving getJSON into the DOMContentLoaded callback.
document.addEventListener("DOMContentLoaded", function() {
jQuery.getJSON('https://ipinfo.io', function(data) {
if (data) {
if (data.country) {
if (data.country.toLowerCase() == 'us') {
window.location.replace(window.location.href + "?location=us");
}
}
}
});
// Other logic here
});
On a side note, you can avoid triple nesting by combining the three if statements (and remember to use strict comparison whenever possible, ===):
jQuery.getJSON('https://ipinfo.io', function(data) {
if (data && data.country && data.country.toLowerCase() === 'us') {
window.location.replace(window.location.href + "?location=us");
}
}

Related

Include .tpl after page load

Hello its posible to load TPL file after page load?
some like:
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
docReady(function() {
console.log("OK");
{include file="modules/widgets/akj-select-menu/akj-select-menu.tpl" assign=akj_menu_content}
});
ITS not work couse i cant inster include smarty like this but i just wont to show what i need. If its possible in Smarty + JS
If your idea is not related with request optimization for fast page load (example menu.tpl is generate very long time and you want to load it later) - then: the simplest way would be to do like this:
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
docReady(function() {
console.log("OK");
document.getElementById("akj_menu_content").style.display = "block";
});
<div id="akj_menu_content" style="display:none;">
{include file="modules/widgets/akj-select-menu/akj-select-menu.tpl" assign=akj_menu_content}
</div>
But.. if it is related with request optimization then docReady() you should make an ajax request for example www.example.com/my/menu/generator where you generate this menu in php (by fetch modules/widgets/akj-select-menu/akj-select-menu.tpl in Smarty and return it as HTML so JS can insert it to <div id="akj_menu_content")

how to get jquery to run repeatedly

I currently have a piece of jquery code that looks for a specific URL (with an anchor at the end) and runs a function if it has a match. The code only runs once, if this is the first URL loaded. Is it possible to have the following code running until it has a match?
$(document).ready(function(){
var url = "https://s3-eu-west-1.amazonaws.com/datahealthcheck16-test/index.html#backup-section-3";
$(function(){
if (location.href==url){
paintLine();
}
})
});
It only runs the first time, because changing the hash does not fire the DOM ready handler again, it does however fire the hashchange event.
$(window).on('hashchange', function() {
if ( window.location.hash === '#backup-section-3' ) {
paintLine();
}
}).trigger('hashchange'); // fire on first load as well
Note that the window is always available, and does not need a DOM ready handler
you can use setTimeout() function to run your function, for example every second:
$(document).ready(function(){
var url = "https://s3-eu-west-1.amazonaws.com/datahealthcheck16-test/index.html#backup-section-3";
function test() {
if (location.href == url) {
paintLine();
} else {
setTimeout(test, 1000);
}
}
test();
});
but what is your idea, behind your code? I sure there is more convenient ways to do your task.
using adeneo's answer:
here is what matches your code:
$(document).ready(function(){
var url = "https://s3-eu-west-1.amazonaws.com/datahealthcheck16-test/index.html#backup-section-3";
$(function(){
if (location.href==url){
paintLine();
}
});
$(window).on('hashchange', function() {
if ( location.href == url ) {
paintLine();
}
});
});

Including a local version of a library that failed to load

I am using PhantomJS to take a screenshot of a page every five minutes, and it works correctly most of the time. The problem is that sometimes the page I am taking a screenshot of fails to load the AngularJS library, and then, it can't build the page after that. So I am trying to figure out how to load a local copy in its place. Here is what I have been trying...
var page = require('webpage').create(),system = require('system');
var home = 'https://smartway.tn.gov/traffic/';
page.open(home, function (status) {
if(status === "success"){
page.injectJs('angular.js');
window.setTimeout((function() {
page.evaluate(function () {
/*stuff*/
});
}), 2000);
}
});
So angular.js is the name of my local copy of what the site would normally download. The site calls the script at the end of the body with several other scripts, and I am trying to find the best way to include it. I am wondering if it needs to be included by replacing the script tag in the html so it can be loaded in sequence, but I am not sure how to do that.
Thanks
It is problematic to reload a single JavaScript file when it failed, particularly when it is the framework. There are probably many scripts which depend on it. When the core framework is not loaded, those scripts will stop executing, because the angular reference cannot be resolved.
You could inject a local version of angular, but then you would have to go over all the other scripts which reference angular and "reload" them by either downloading and evaling them in order or putting them into the page as script elements. I advise against it, because it is probably very error prone.
You should just reload the page if angular does not exist after page load (callback of page.open). Since the same problem may occurr during reload, this has to be done recursively:
function open(countDown, done){
if (countDown === 0) {
done("ERROR: not loaded");
return;
}
page.open(home, function (status) {
if(status === "success"){
var angularExists = page.evaluate(function () {
return !!angular;
});
if (angularExists){
done();
} else {
open(countDown - 1, done);
}
} else {
open(countDown - 1, done);
}
});
}
open(5, function(err){
if(err) {
console.log(err);
} else {
page.render(target);
}
});
You can also try the page.reload() function instead of a page.open().
The other possiblity is to always inject the local version when the page loading began and stop any request for the remote version of the script:
page.onLoadStarted = function() {
page.injectJs('angular.js');
};
page.onResourceRequested = function(requestData, networkRequest) {
var match = requestData.url.match(/angular\.min\.js/g);
if (match != null) {
networkRequest.abort();
}
};
page.open(home, function (status) {
if(status === "success"){
window.setTimeout((function() {
page.evaluate(function () {
/*stuff*/
});
}), 2000);
}
});
This version works entirely without reloading.

Javascript - Get text from html to string

It's a php while with javascript codes. I want that this:
Check every 1 seconds that chat_status.html -text's: status = "offline"
Full code:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
// jQuery Document
$(document).ready(function(){
function loadChatStatus(){
var status = ("http://tulyita.hu/chat/chat_status.html".text);
if(status == "offline"){
//this happens 1#
} else {
//this happens 2#
}
}
setInterval (loadChatStatus, 1); //Reload file every 1 seconds
});
</script>
but it isn't worked. :( Can someone help me?
I need the text from the "chat_status.html".
function loadChatStatus(){
$.ajax({
url: "chat_status.html",
cache: false,
success: function(html){
$("#status").html(html); //Insert status into the #status div
},
});
if($("#status") == "offline"){
//this happens #1
} else {
//this happens #2
}
}
??
You can use $.get() to load the contents from your server and do something with it in the callback. Example (not tested):
$.get('http://tulyita.hu/chat/chat_status.html', function (data) {
if (data === 'chat = off' {
// happens when offline
}
else {
// happens when online
}
}, 'text');
Note that the page's current content is chat = off and not offline. Please check the exact contents of data after implementing this in your code.
Also note that your HTML page has to be on tulyita.hu or you have to add an Access-Control-Allow-Origin header because of the same-origin policy.
First, don't declare the loadChatStatus function in .ready() but outside of it. Leave only the setInterval inside the .ready() function. And 1 second is 1000 ms. setInterval expects ms.
Second, use .load() to get the contents of the url, put it in a (hidden) div,and then check what it is. You cannot just do "string".text , as a string has no .text member.

How to use jQuery click event to change href value asynchronously, based on a JSON query

I'm using the bit.ly url shortening service to shorten certain url's being sent to a "share on twitter" function. I'd like to load the bit.ly url only when a user actually presses the share button (due to bit.ly's max 5 parallel reqs limitation). Bit.ly's REST API returns a JSON callback with the shortened url, which makes the whole scenario async.
I've tried the following to stop the click event, and wait for the JSON call to return a value before launching the click.
I have the following simplified code in jQuery(document).ready():
Updated code (oversimplified)!
jQuery("#idofaelement").click(function(event) {
event.preventDefault(); //stop the click action
var link = jQuery(this);
bitlyJSON(function(shortUrl) {
link.attr("href", function() {
//process shortUrl
//return finalized url;
}).unbind().click();
});
});
And the following code to handle the bitly shortening (works just fine):
function bitlyJSON(func) {
//
// build apiUrl here
//
jQuery.getJSON(apiUrl, function(data) {
jQuery.each(data, function(i, entry) {
if (i == "errorCode") {
if (entry != "0") {
func(longUrl);}
} else if (i == "results") {
func(entry[longUrl].shortUrl);}
});
});
} (jQuery)
The href gets its value changed, but the final .click() event never gets fired. This works fine when defining a static value for the href, but not when using the async JSON method.
As you outlined yourself:
event.preventDefault(); //stop the click action
That means, BROWSER IS NOT GOING TO THAT URL, if you wish to actually go forward to the long-url location, simply do something like:
document.location.href = longurl;
iirc, jquery doesn't trigger "click" on A elements. I'd try old good "location.href=whatever" in the callback.
bitlyJSON(function(shortUrl) {
link.attr("href", function() {
//process shortUrl
//return finalized url;
});
location.href = link.attr("href");
});
I think what you actually want is to return false; from the click event, to prevent the actual following of the href, right?
Like:
jQuery("#idofaelement").click(function(event) {
//event.preventDefault(); //stop the click action
var link = jQuery(this);
bitlyJSON(function(shortUrl) {
link.attr("href", function() {
//process shortUrl
//return finalized url;
}).unbind().click();
});
return false;
});
#Tzury Bar Yochay pointed me in the right direction by suggesting I use location.href to update the url. Also #Victor helped with his answer.
I got things kinda working combining the answers, but had issues with the history in firefox. Seems that updating window.location indeed redirected the user, but also removed the "source page" from the history. This did not happen in chrome, safari, ie8, ie8-compatibility or ie7.
Based on this response to another question I was able to create a workaround giving the following working code + made a few changes:
jQuery("#idofaelement").one("click", function(event) {
bitlyJSON(function(shortUrl) {
jQuery("#idofaelement").attr("href", function() {
//process shortUrl
//return finalized url;
});
setTimeout(function() {
window.location = jQuery("#idofaelement").attr("href");
}, 0);
});
return false;
});
Thanks for all the help!

Categories