JS script dynamic loading inconsitent - javascript

I need help on getting some dynamic js loading working properly. the issue I'm having now is that it is not consistently loading the js script when loading the page. here is the script that I have at the bottom of the page that I'm opening:
function getJSOnload() {
var element;
var parent = document.body;
var cdn = [
LoadFormValidationScript(LoginFormValidator),
LoadFormValidationScript(SetFormLocaleLang)
];
var i = 0, file;
for (i;i<cdn.length;i++) {
file = cdn[i];
element = document.createElement("script");
element.type = "text/javascript";
element.src = file;
parent.appendChild(element);
//free file's value
file = null;
}
};
if (window.addEventListener) {
window.addEventListener("load", getJSOnload(), false);
}
else if (window.attachEvent) {
window.attachEvent("onload", getJSOnload());
}
else window.onload = getJSOnload();
this is the LoadFormValidationScript that i have in an external js file
function LoadFormValidationScript(callback){
function LoadValidationScripts() {
$.getScript('/plugins/script1.min.js', function() {
$.getScript('/plugins/script2.min.js', function() {
$.getScript('/plugins/script3.addons.min.js', function() {
$.getScript('/plugins/script.es_ES.js', function() {
$.getScript('/plugins/script4.fr_FR.js', function() {
$.getScript('/plugins/script5.de_DE.js', callback);
});
});
});
});
});
}
if (!$.fn.formValidation){
LoadValidationScripts();
} else {
if (callback && typeof(callback) === "function") {
callback();
}
}
}
and this is the "setFormLocaleLang" function as an example since it is short one
function SetFormLocaleLang(){
var nberOfForm = document.forms.length; //get number of forms on the page
// if there are no forms in the page don't waist your time
if (nberOfForm > 0) {
var Locale = "en_US"; //default formVlaidation language
//var lang = $('html').attr('lang'); // get the page language
var lang = $("#selectedLanguage").attr('data-lang-id');
// assign the Locale depending on page language
switch (lang) {
case "en" : Locale = 'en_US'; break;
case "fr" : Locale = 'fr_FR'; break;
case "es" : Locale = 'es_ES'; break;
case "de" : Locale = 'de_DE'; break;
default : break;
};
//set the locale for all the forms in the page
for (var i = 0; i < nberOfForm; i++) {
var strFormID = "#" + document.forms[i].id;
$(strFormID).formValidation('setLocale', Locale);
}
}
}
like is said it does work and load the scripts but not all the time, sometimes i have to refresh the page like 3 time for the script to load and sometimes it loads on the first try as soon as i open the page. not sure what is going on and why i get this behaviour.

You're attaching the handlers incorrectly - you're calling getJSOnload() immediately, instead of waiting for document-loaded, as you intend. Reference, don't call, the function:
if (window.addEventListener) {
window.addEventListener("load", getJSOnload, false);
}
else if (window.attachEvent) {
window.attachEvent("onload", getJSOnload);
}
else window.onload = getJSOnload;

Related

block the access to href url to any third-party javascript code

I am running third-party javascripts on my page and they are grabbing the href url without my consent. Is there a way to block it and avoid them accessing it without calling them from iframes?
Maybe I could redefine the window.location.href value so that they cannot access it as it is in the url?
Thank you for your help!
The location.href property is readonly. I can only come with a partial solution to this using a modified version of the greasemonkey script outlined in this stackoverflow post: Stop execution of Javascript function (client side) or tweak it
In the script below the function displayUrl() is called which alerts the document.location.href to screen. The greasemonkey script uses the Document.onbeforescriptexecute event to intercept the javascript before it get's executed and replace document.location.href with another string.
onbeforescriptexecute is only supported by firefox and is non-standard: https://developer.mozilla.org/en-US/docs/Web/API/Document/onbeforescriptexecute
So not exactly an ideal solution but this example may give you some ideas.
<html>
<head>
</head>
<body>
<script>
function checkForBadJavascripts (controlArray) {
/*--- Note that this is a self-initializing function. The controlArray
parameter is only active for the FIRST call. After that, it is an
event listener.
The control array row is defines like so:
[bSearchSrcAttr, identifyingRegex, callbackFunction]
Where:
bSearchSrcAttr True to search the SRC attribute of a script tag
false to search the TEXT content of a script tag.
identifyingRegex A valid regular expression that should be unique
to that particular script tag.
callbackFunction An optional function to execute when the script is
found. Use null if not needed.
*/
if ( ! controlArray.length) return null;
checkForBadJavascripts = function (zEvent) {
for (var J = controlArray.length - 1; J >= 0; --J) {
var bSearchSrcAttr = controlArray[J][0];
var identifyingRegex = controlArray[J][1];
if (bSearchSrcAttr) {
if (identifyingRegex.test (zEvent.target.src) ) {
stopBadJavascript (J);
return false;
}
}
else {
if (identifyingRegex.test (zEvent.target.textContent) ) {
stopBadJavascript (J);
return false;
}
}
}
function stopBadJavascript (controlIndex) {
zEvent.stopPropagation ();
zEvent.preventDefault ();
var callbackFunction = controlArray[J][2];
//if (typeof callbackFunction == "function") {
//callbackFunction ();
if (bSearchSrcAttr) {
var jsScript = zEvent.target.src;
} else {
var jsScript = zEvent.target.textContent;
}
jsScript = jsScript.replace("document.location.href", "'http://example.com'");
eval(jsScript);
//}
//--- Remove the node just to clear clutter from Firebug inspection.
zEvent.target.parentNode.removeChild (zEvent.target);
//--- Script is intercepted, remove it from the list.
controlArray.splice (J, 1);
if ( ! controlArray.length) {
//--- All done, remove the listener.
window.removeEventListener (
'beforescriptexecute', checkForBadJavascripts, true
);
}
}
}
/*--- Use the "beforescriptexecute" event to monitor scipts as they are loaded.
See https://developer.mozilla.org/en/DOM/element.onbeforescriptexecute
Note that it does not work on acripts that are dynamically created.
*/
window.addEventListener ('beforescriptexecute', checkForBadJavascripts, true);
return checkForBadJavascripts;
}
function addJS_Node (text, s_URL, funcToRun) {
var D = document;
var scriptNode = D.createElement ('script');
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
//--- Don't error check here. if DOM not available, should throw error.
targ.appendChild (scriptNode);
}
/*--- Check for bad scripts to intercept and specify any actions to take.
*/
checkForBadJavascripts ( [
[ false,
/document.location.href/,
function () {
addJS_Node (replaceScript);
}
]
] );
</script>
<script>
function displayUrl()
{
var pageUrl = document.location.href;
alert(pageUrl);
}
displayUrl();
</script>
</body>
</html>
Note: I've added the below code to the original greasemonkey script:
//if (typeof callbackFunction == "function") {
//callbackFunction ();
if (bSearchSrcAttr) {
var jsScript = zEvent.target.src;
} else {
var jsScript = zEvent.target.textContent;
}
jsScript = jsScript.replace("document.location.href", "'http://example.com'");
eval(jsScript);
//}

Check if my website is open in another tab

I want to check with JavaScript if the user has already opened my website in another tab in their browser.
It seems I cannot do that with pagevisibility...
The only way I see is to use WebSocket based on a session cookie, and check if the client has more than one socket. But by this way, from current tab, I have to ask my server if this user has a tab opened right next to their current browser tab. It is a little far-fetched!
Maybe with localstorage?
The shorter version with localStorage and Storage listener
<script type="text/javascript">
// Broadcast that you're opening a page.
localStorage.openpages = Date.now();
var onLocalStorageEvent = function(e){
if(e.key == "openpages"){
// Listen if anybody else is opening the same page!
localStorage.page_available = Date.now();
}
if(e.key == "page_available"){
alert("One more page already open");
}
};
window.addEventListener('storage', onLocalStorageEvent, false);
</script>
Update:
Works on page crash as well.
Stimulate page crash in chrome: chrome://inducebrowsercrashforrealz
Live demo
Using local storage I created a simple demo that should accomplish what your looking to do. Basically, it simply maintains a count of currently opened windows. When the window is closed the unload events fire and remove it from the total window count.
When you first look at it, you may think there's more going on than there really is. Most of it was a shotty attempt to add logic into who was the "main" window, and who should take over as the "main" window as you closed children. (Hence the setTimeout calls to recheck if it should be promoted to a main window) After some head scratching, I decided it would take too much time to implement and was outside the scope of this question. However, if you have two windows open (Main, and Child) and you close the Main, the child will be promoted to a main.
For the most part you should be able to get the general idea of whats going on and use it for your own implementation.
See it all in action here:
http://jsbin.com/mipanuro/1/edit
Oh yeah, to actually see it in action... Open the link in multiple windows. :)
Update:
I've made the necessary changes to have the the local storage maintain the "main" window. As you close tabs child windows can then become promoted to a main window. There are two ways to control the "main" window state through a parameter passed to the constructor of WindowStateManager. This implementation is much nicer than my previous attempt.
JavaScript:
// noprotect
var statusWindow = document.getElementById('status');
(function (win)
{
//Private variables
var _LOCALSTORAGE_KEY = 'WINDOW_VALIDATION';
var RECHECK_WINDOW_DELAY_MS = 100;
var _initialized = false;
var _isMainWindow = false;
var _unloaded = false;
var _windowArray;
var _windowId;
var _isNewWindowPromotedToMain = false;
var _onWindowUpdated;
function WindowStateManager(isNewWindowPromotedToMain, onWindowUpdated)
{
//this.resetWindows();
_onWindowUpdated = onWindowUpdated;
_isNewWindowPromotedToMain = isNewWindowPromotedToMain;
_windowId = Date.now().toString();
bindUnload();
determineWindowState.call(this);
_initialized = true;
_onWindowUpdated.call(this);
}
//Determine the state of the window
//If its a main or child window
function determineWindowState()
{
var self = this;
var _previousState = _isMainWindow;
_windowArray = localStorage.getItem(_LOCALSTORAGE_KEY);
if (_windowArray === null || _windowArray === "NaN")
{
_windowArray = [];
}
else
{
_windowArray = JSON.parse(_windowArray);
}
if (_initialized)
{
//Determine if this window should be promoted
if (_windowArray.length <= 1 ||
(_isNewWindowPromotedToMain ? _windowArray[_windowArray.length - 1] : _windowArray[0]) === _windowId)
{
_isMainWindow = true;
}
else
{
_isMainWindow = false;
}
}
else
{
if (_windowArray.length === 0)
{
_isMainWindow = true;
_windowArray[0] = _windowId;
localStorage.setItem(_LOCALSTORAGE_KEY, JSON.stringify(_windowArray));
}
else
{
_isMainWindow = false;
_windowArray.push(_windowId);
localStorage.setItem(_LOCALSTORAGE_KEY, JSON.stringify(_windowArray));
}
}
//If the window state has been updated invoke callback
if (_previousState !== _isMainWindow)
{
_onWindowUpdated.call(this);
}
//Perform a recheck of the window on a delay
setTimeout(function()
{
determineWindowState.call(self);
}, RECHECK_WINDOW_DELAY_MS);
}
//Remove the window from the global count
function removeWindow()
{
var __windowArray = JSON.parse(localStorage.getItem(_LOCALSTORAGE_KEY));
for (var i = 0, length = __windowArray.length; i < length; i++)
{
if (__windowArray[i] === _windowId)
{
__windowArray.splice(i, 1);
break;
}
}
//Update the local storage with the new array
localStorage.setItem(_LOCALSTORAGE_KEY, JSON.stringify(__windowArray));
}
//Bind unloading events
function bindUnload()
{
win.addEventListener('beforeunload', function ()
{
if (!_unloaded)
{
removeWindow();
}
});
win.addEventListener('unload', function ()
{
if (!_unloaded)
{
removeWindow();
}
});
}
WindowStateManager.prototype.isMainWindow = function ()
{
return _isMainWindow;
};
WindowStateManager.prototype.resetWindows = function ()
{
localStorage.removeItem(_LOCALSTORAGE_KEY);
};
win.WindowStateManager = WindowStateManager;
})(window);
var WindowStateManager = new WindowStateManager(false, windowUpdated);
function windowUpdated()
{
//"this" is a reference to the WindowStateManager
statusWindow.className = (this.isMainWindow() ? 'main' : 'child');
}
//Resets the count in case something goes wrong in code
//WindowStateManager.resetWindows()
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id='status'>
<span class='mainWindow'>Main Window</span>
<span class='childWindow'>Child Window</span>
</div>
</body>
</html>
CSS:
#status
{
display:table;
width:100%;
height:500px;
border:1px solid black;
}
span
{
vertical-align:middle;
text-align:center;
margin:0 auto;
font-size:50px;
font-family:arial;
color:#ba3fa3;
display:none;
}
#status.main .mainWindow,
#status.child .childWindow
{
display:table-cell;
}
.mainWindow
{
background-color:#22d86e;
}
.childWindow
{
background-color:#70aeff;
}
(2021) You can use BroadcastChannel to communicate between tabs of the same origin.
For example, put the following at the top level of your js code, then test by opening 2 tabs:
const bc = new BroadcastChannel("my-awesome-site");
bc.onmessage = (event) => {
if (event.data === `Am I the first?`) {
bc.postMessage(`No you're not.`);
alert(`Another tab of this site just got opened`);
}
if (event.data === `No you're not.`) {
alert(`An instance of this site is already running`);
}
};
bc.postMessage(`Am I the first?`);
I know it is late, but maybe help someone
This snippet of code, will detect how many tabs are open and how many are active (visible) and if none of tabs is active, it will choose last opened tab, as active one.
This code will handle windows/tab crash too and it will refresh the count at crash.
Because localStorage is not supported on Stack Overflow currently, please test here.
<html>
<body>
Open in several tabs or windows
<div id="holder_element"></div>
<script type="text/javascript">
//localStorage.clear();
manage_crash();
//Create a windows ID for each windows that is oppened
var current_window_id = Date.now() + "";//convert to string
var time_period = 3000;//ms
//Check to see if PageVisibility API is supported or not
var PV_API = page_visibility_API_check();
/************************
** PAGE VISIBILITY API **
*************************/
function page_visibility_API_check ()
{
var page_visibility_API = false;
var visibility_change_handler = false;
if ('hidden' in document)
{
page_visibility_API = 'hidden';
visibility_change_handler = 'visibilitychange';
}
else
{
var prefixes = ['webkit','moz','ms','o'];
//loop over all the known prefixes
for (var i = 0; i < prefixes.length; i++){
if ((prefixes[i] + 'Hidden') in document)
{
page_visibility_API = prefixes[i] + 'Hidden';
visibility_change_handler = prefixes[i] + 'visibilitychange';
}
}
}
if (!page_visibility_API)
{
//PageVisibility API is not supported in this device
return page_visibility_API;
}
return {"hidden": page_visibility_API, "handler": visibility_change_handler};
}
if (PV_API)
{
document.addEventListener(PV_API.handler, function(){
//console.log("current_window_id", current_window_id, "document[PV_API.hidden]", document[PV_API.hidden]);
if (document[PV_API.hidden])
{
//windows is hidden now
remove_from_active_windows(current_window_id);
//skip_once = true;
}
else
{
//windows is visible now
//add_to_active_windows(current_window_id);
//skip_once = false;
check_current_window_status ();
}
}, false);
}
/********************************************
** ADD CURRENT WINDOW TO main_windows LIST **
*********************************************/
add_to_main_windows_list(current_window_id);
//update active_window to current window
localStorage.active_window = current_window_id;
/**************************************************************************
** REMOVE CURRENT WINDOWS FROM THE main_windows LIST ON CLOSE OR REFRESH **
***************************************************************************/
window.addEventListener('beforeunload', function ()
{
remove_from_main_windows_list(current_window_id);
});
/*****************************
** ADD TO main_windows LIST **
******************************/
function add_to_main_windows_list(window_id)
{
var temp_main_windows_list = get_main_windows_list();
var index = temp_main_windows_list.indexOf(window_id);
if (index < 0)
{
//this windows is not in the list currently
temp_main_windows_list.push(window_id);
}
localStorage.main_windows = temp_main_windows_list.join(",");
return temp_main_windows_list;
}
/**************************
** GET main_windows LIST **
***************************/
function get_main_windows_list()
{
var temp_main_windows_list = [];
if (localStorage.main_windows)
{
temp_main_windows_list = (localStorage.main_windows).split(",");
}
return temp_main_windows_list;
}
/**********************************************
** REMOVE WINDOWS FROM THE main_windows LIST **
***********************************************/
function remove_from_main_windows_list(window_id)
{
var temp_main_windows_list = [];
if (localStorage.main_windows)
{
temp_main_windows_list = (localStorage.main_windows).split(",");
}
var index = temp_main_windows_list.indexOf(window_id);
if (index > -1) {
temp_main_windows_list.splice(index, 1);
}
localStorage.main_windows = temp_main_windows_list.join(",");
//remove from active windows too
remove_from_active_windows(window_id);
return temp_main_windows_list;
}
/**************************
** GET active_windows LIST **
***************************/
function get_active_windows_list()
{
var temp_active_windows_list = [];
if (localStorage.actived_windows)
{
temp_active_windows_list = (localStorage.actived_windows).split(",");
}
return temp_active_windows_list;
}
/*************************************
** REMOVE FROM actived_windows LIST **
**************************************/
function remove_from_active_windows(window_id)
{
var temp_active_windows_list = get_active_windows_list();
var index = temp_active_windows_list.indexOf(window_id);
if (index > -1) {
temp_active_windows_list.splice(index, 1);
}
localStorage.actived_windows = temp_active_windows_list.join(",");
return temp_active_windows_list;
}
/********************************
** ADD TO actived_windows LIST **
*********************************/
function add_to_active_windows(window_id)
{
var temp_active_windows_list = get_active_windows_list();
var index = temp_active_windows_list.indexOf(window_id);
if (index < 0)
{
//this windows is not in active list currently
temp_active_windows_list.push(window_id);
}
localStorage.actived_windows = temp_active_windows_list.join(",");
return temp_active_windows_list;
}
/*****************
** MANAGE CRASH **
******************/
//If the last update didn't happened recently (more than time_period*2)
//we will clear saved localStorage's data and reload the page
function manage_crash()
{
if (localStorage.last_update)
{
if (parseInt(localStorage.last_update) + (time_period * 2) < Date.now())
{
//seems a crash came! who knows!?
//localStorage.clear();
localStorage.removeItem('main_windows');
localStorage.removeItem('actived_windows');
localStorage.removeItem('active_window');
localStorage.removeItem('last_update');
location.reload();
}
}
}
/********************************
** CHECK CURRENT WINDOW STATUS **
*********************************/
function check_current_window_status(test)
{
manage_crash();
if (PV_API)
{
var active_status = "Inactive";
var windows_list = get_main_windows_list();
var active_windows_list = get_active_windows_list();
if (windows_list.indexOf(localStorage.active_window) < 0)
{
//last actived windows is not alive anymore!
//remove_from_main_windows_list(localStorage.active_window);
//set the last added window, as active_window
localStorage.active_window = windows_list[windows_list.length - 1];
}
if (! document[PV_API.hidden])
{
//Window's page is visible
localStorage.active_window = current_window_id;
}
if (localStorage.active_window == current_window_id)
{
active_status = "Active";
}
if (active_status == "Active")
{
active_windows_list = add_to_active_windows(current_window_id);
}
else
{
active_windows_list = remove_from_active_windows(current_window_id);
}
console.log(test, active_windows_list);
var element_holder = document.getElementById("holder_element");
element_holder.insertAdjacentHTML("afterbegin", "<div>"+element_holder.childElementCount+") Current Windows is "+ active_status +" "+active_windows_list.length+" window(s) is visible and active of "+ windows_list.length +" windows</div>");
}
else
{
console.log("PageVisibility API is not supported :(");
//our INACTIVE pages, will remain INACTIVE forever, you need to make some action in this case!
}
localStorage.last_update = Date.now();
}
//check storage continuously
setInterval(function(){
check_current_window_status ();
}, time_period);
//initial check
check_current_window_status ();
</script>
</body>
</html>

pjax/ajax and browser back button issues

I use pjax to ajaxify my menu links. This works fine until I use the browser back button. In my javascript file I use Common Script files (to load all the necessary js files when the user hits the url) and Script files with respect to each menu links (when navigated through pjax)
function myFunction(){
/*All the script files */
}
$(document).ready(function(){
myFunction();
/*pjax menu loading block*/
$(document).on('click', 'a[data-pjax]', function(event) {
$.pjax.click(event, '#pjax-container');
$(document).on('pjax:end', function() {
myFunction();
});
});
});
Now when I navigate to a menu item and try to come back by clicking the browser back button, the script files are getting duplicated (eg: slider images getting duplicated and table sorting not working).How to overcome this issue?
You can implement the url specific loading this way, create a queue of functions which you want to load and unload on pjax complete
The solution is based on js prototyping
// create queue for load and unload
var onLoad = new PjaxExecQueue();
var onUnload = new PjaxExecQueue();
// way to add functions to queue to run on pjax load
onLoad.queue(function() {
someFunction();
});
// way to add functions to queue to unload on pjax load
onUnload.queue(function() {
someOtherFunction();
});
// load function if url contain particular path name
onLoad.queue_for_url(function_name, 'url_section');
// check for url specific function
var URLPjaxQueueElement = function(exec_function, url) {
this.method = exec_function;
if(url) {
this.url = new RegExp(url);
} else {
this.url = /.*/;
}
};
// create a queue object
var PjaxExecQueue = function () {
this.url_exec_queue = [];
this.id_exec_queue = [];
this.fired = false;
this.indicating_loading = false;
this.content = $('#content');
};
PjaxExecQueue.prototype = {
queue: function (exec_function) {
this.url_exec_queue.unshift(new URLPjaxQueueElement(exec_function));
},
queue_for_url: function (exec_function, url_pattern) {
this.url_exec_queue.unshift(new URLPjaxQueueElement(exec_function, url_pattern));
},
queue_if_id_present: function(exec_function, id) {
this.id_exec_queue.unshift(new IDPjaxQueueElement(exec_function, id));
},
fire: function () {
if(this.indicating_loading) {
this.content.removeClass("indicate-loading");
this.indicating_loading = false;
}
if(!this.fired) {
var match_loc = window.location.pathname;
var i = this.url_exec_queue.length;
while(i--) {
this.url_exec_queue[i].fire(match_loc);
}
i = this.id_exec_queue.length;
while(i--) {
this.id_exec_queue[i].fire(match_loc);
}
}
this.fired = true;
},
reset: function() {
this.fired = false;
},
loading: function () {
this.content.addClass("indicate-loading");
this.indicating_loading = true;
this.reset();
},
count: function () {
return exec_queue.length;
},
show: function (for_url) {
for (var i=0; i < exec_queue.length; i++) {
if(for_url) {
if(exec_queue[i].url.test(for_url)) {
console.log("" + exec_queue[i].method);
}
} else{
console.log(exec_queue[i].url + " : " + exec_queue[i].method);
}
}
}
};
// before send
$(document).on('pjax:beforeSend', function() {
onLoad.loading();
onUnload.fire();
});
// after pjax complete
$(document).on('pjax:complete', function() {
onLoad.fire();
onUnload.reset();
});

Close an injected iframe

I have a content script that runs from my chrome extension.
this script injects an iframe to the body of the current page.
i want to have the possibility to close the iframe from within the iframe.
how do i do this?
when i searched this issue on the web, almost each solution uses the window.parent.document property which for some reason is undefined in my case. any ideas?
EDIT - Code Sample:
in the HTML of the iframe:
<script type="text/javascript">
function frameClose() {
var windowFrames = window.parent.frames;
for (var i = 0; i < windowFrames.length; i++) {
var aFrame = windowFrames[i];
if (aFrame.name == 'myFrame') {
alert('in frame');
// WHAT TO DO HERE?
// window.parent.document is undefined
// aFrame.parentNode.removeChild(aFrame); - THIS DOES NOT WORK ALSO
break;
}
}
}
</script>
this is how i inject the iframe:
Extension.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {
file : "/js/PushIFrame.js"
}, function() {
if (chrome.extension.lastError) {
}
});
});
and in PushIFrame.js i have:
chrome.extension.sendMessage({
action: "pushFrame",
source: pushIframe(document)
});
function pushIframe(document) {
var existingFrame = document.getElementById('bmarkFrame');
if (existingFrame == null) {
var temp = document.createElement('iframe');
temp.id = 'myFrame';
temp.name = 'myFrame';
temp.setAttribute('scrolling', 'no');
temp.setAttribute('allowtransparency', 'true');
temp.style.border = 'none';
temp.style.height = '100%';
temp.style.width = '100%';
temp.style.position = 'fixed';
temp.style.zIndex = 99999999;
temp.style.top = 0;
temp.style.left = 0;
temp.style.display = 'block';
temp.src = 'https://www.mysite.com/';
document.body.appendChild(temp);
}
else {
existingFrame.style.display = 'block';
}
}
Let the content script (say PushIframe.js) bind a message event to the main frame. Then, whenever you want to hide the iframe, call parent.postMessage to notify the main frame. This message is received by the content script, from where you can hide the frame (as defined in your function pushIframe).
// PushIframe.js:
addEventListener('message', function(ev) {
if (ev.data === 'closeIframe') {
pushIframe(document); // Your code
}
});
// Iframe:
<script>
function frameClose() {
parent.postMessage('closeIframe', '*');
}
</script>

setInterval with other jQuery events - Too many recursions

I'm trying to build a Javascript listener for a small page that uses AJAX to load content based on the anchor in the URL. Looking online, I found and modified a script that uses setInterval() to do this and so far it works fine. However, I have other jQuery elements in the $(document).ready() for special effects for the menus and content. If I use setInterval() no other jQuery effects work. I finagled a way to get it work by including the jQuery effects in the loop for setInterval() like so:
$(document).ready(function() {
var pageScripts = function() {
pageEffects();
pageURL();
}
window.setInterval(pageScripts, 500);
});
var currentAnchor = null;
function pageEffects() {
// Popup Menus
$(".bannerMenu").hover(function() {
$(this).find("ul.bannerSubmenu").slideDown(300).show;
}, function() {
$(this).find("ul.bannerSubmenu").slideUp(400);
});
$(".panel").hover(function() {
$(this).find(".panelContent").fadeIn(200);
}, function() {
$(this).find(".panelContent").fadeOut(300);
});
// REL Links Control
$("a[rel='_blank']").click(function() {
this.target = "_blank";
});
$("a[rel='share']").click(function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
}
function pageURL() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
$.get("loader.php", query, function(data) {
$("#load").fadeIn("fast");
$("#content").fadeOut(100).html(data).fadeIn(500);
$("#load").fadeOut("fast");
});
}
}
This works fine for a while but after a few minutes of the page being loaded, it drags to a near stop in IE and Firefox. I checked the FF Error Console and it comes back with an error "Too many Recursions." Chrome seems to not care and the page continues to run more or less normally despite the amount of time it's been open.
It would seem to me that the pageEffects() call is causing the issue with the recursion, however, any attempts to move it out of the loop breaks them and they cease to work as soon as setInterval makes it first loop.
Any help on this would be greatly appreciated!
I am guessing that the pageEffects need added to the pageURL content.
At the very least this should be more efficient and prevent duplicate handlers
$(document).ready(function() {
pageEffects($('body'));
(function(){
pageURL();
window.setTimeout(arguments.callee, 500);
})();
});
var currentAnchor = null;
function pageEffects(parent) {
// Popup Menus
parent.find(".bannerMenu").each(function() {
$(this).unbind('mouseenter mouseleave');
var proxy = {
subMenu: $(this).find("ul.bannerSubmenu"),
handlerIn: function() {
this.subMenu.slideDown(300).show();
},
handlerOut: function() {
this.subMenu.slideUp(400).hide();
}
};
$(this).hover(proxy.handlerIn, proxy.handlerOut);
});
parent.find(".panel").each(function() {
$(this).unbind('mouseenter mouseleave');
var proxy = {
content: panel.find(".panelContent"),
handlerIn: function() {
this.content.fadeIn(200).show();
},
handlerOut: function() {
this.content.slideUp(400).hide();
}
};
$(this).hover(proxy.handlerIn, proxy.handlerOut);
});
// REL Links Control
parent.find("a[rel='_blank']").each(function() {
$(this).target = "_blank";
});
parent.find("a[rel='share']").click(function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
}
function pageURL() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
var content = $("#content");
$.get("loader.php", query, function(data) {
$("#load").fadeIn("fast");
content.fadeOut(100).html(data).fadeIn(500);
$("#load").fadeOut("fast");
});
pageEffects(content);
}
}
Thanks for the suggestions. I tried a few of them and they still did not lead to the desirable effects. After some cautious testing, I found out what was happening. With jQuery (and presumably Javascript as a whole), whenever an AJAX callback is made, the elements brought in through the callback are not binded to what was originally binded in the document, they must be rebinded. You can either do this by recalling all the jQuery events on a successful callback or by using the .live() event in jQuery's library. I opted for .live() and it works like a charm now and no more recursive errors :D.
$(document).ready(function() {
// Popup Menus
$(".bannerMenu").live("hover", function(event) {
if (event.type == "mouseover") {
$(this).find("ul.bannerSubmenu").slideDown(300);
} else {
$(this).find("ul.bannerSubmenu").slideUp(400);
}
});
// Rollover Content
$(".panel").live("hover", function(event) {
if (event.type == "mouseover") {
$(this).find(".panelContent").fadeIn(200);
} else {
$(this).find(".panelContent").fadeOut(300);
}
});
// HREF Events
$("a[rel='_blank']").live("click", function(event) {
var target = $(this).attr("href");
window.open(target, "_blank");
event.preventDefault();
});
$("a[rel='share']").live("click", function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
setInterval("checkAnchor()", 500);
});
var currentAnchor = null;
function checkAnchor() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
$.get("loader.php", query, function(data) {
$("#load").fadeIn(200);
$("#content").fadeOut(200).html(data).fadeIn(200);
$("#load").fadeOut(200);
});
}
}
Anywho, the page works as intended even in IE (which I rarely check for compatibility). Hopefully, some other newb will learn from my mistakes :p.

Categories