I want to create a recursive JavaScript loop which can display all the Frames (either using IFRAMES Tag or using FRAME Tag). The result should give FrameName, NestingLevel, FrameURL, etc.
For example, when we open 'Developer Tools' in Google Chrome, we can see in all the FRAMES(even nested Frames too) in the console tab.
Please give a recursive loop with error handling (iframe security issue) for the same.!
Sample Code:
function getFramesInfo(oWin) {
arrFrames = oWin.frames;
//alert(arrFrames.length);
if (arrFrames.length == 0) {
alert('document do not have frame(s)');
} else {
for (i = 0; i < arrFrames.length; i++) {
console.log(i + ' ' + arrFrames[i].location.href);
if (arrFrames[i].document) {
getFramesInfo(arrFrames[i]);
}
}
}
}
//Calling This Function
getFramesInfo(window);
Alternate / Improved Code:
function getAllFrames(frame, allFrameArray) {
allFrameArray.push(frame.frames);
for (var i = 0; i < frame.frames.length; i++) {
getAllFrames(frame.frames[i], allFrameArray);
}
return allFrameArray;
}
//Usage:
var allFramesArray = getAllFrames(window, new Array());
console.log(allFramesArray.length); // number of frames in array
for (var i = 0; i < allFramesArray.length; i++) {
console.log('\n\n No.'+ (i+1) + '.');
try {
console.log(allFramesArray[i].id);
console.log(allFramesArray[i].name);
console.log(allFramesArray[i].location.href); // location of first frame in array}
} catch (e) {
console.log('Error in Accessing Frame No.' + (i+1) ); // location of first frame in array}
}
}
After googling and exploring I have found a simple solution, but I think this answer should be improved to avoid any possible errors (i.e. precise error handling should be done to avoid cross-domain frames issue):
Sample Solution:
// first parameter is frame (window) in which to get sub frames
// second is the array to build on
function getAllFrames(frame, allFrameArray) {
allFrameArray.push(frame.frames);
for (var i = 0; i < frame.frames.length; i++) {
getAllFrames(frame.frames[i], allFrameArray);
}
return allFrameArray;
}
Usage:
var allFramesArray = getAllFrames(window, new Array());
console.log(allFramesArray.length); // number of frames in array
for (var i = 0; i < allFramesArray.length; i++) {
try {
console.log(allFramesArray[i].location.href); // location of first frame in array}
} catch (e) {
console.log('Error in Accessing Frame No.' + i); // location of first frame in array}
}
}
Here is another one (shortcut example)
var i = new Array;
function wow(a, n) {
t = '';
for (i[n] = 0; i[n] < a.length; i[n]++) {
try {
t += a[i[n]].name + ' \n';
} catch (e) {
t += 'Error \n';
}
if (a[i[n]].frames.length) t += wow(a[i[n]].frames, n + 1);
}
return t;
}
//Usage:
console.log(wow(top.frames, 0));
While browsing for a code, I recently have learnt a new code, using this code which takes a javascript window object as input and returns all its nested windows (including multiple levels of nesting). This function however is an efficient/elegant way that can be used to grab a reference to all the windows (objects) and all the child windows (objects). I have checked this function and found that it works well, it could be understood that making/writing this function completely recursively, as the DOM object tree is actually an n-ary, not binary.
function getAllNestedWindows(window) {
var windows = [window];
if (window.length === 0) {
return windows;
} else {
for (var i = 0; i < window.length; i++) {
windows = windows.concat(getAllNestedWindows(window[i]));
}
}
return windows;
}
Related
The thing that i wanna do is similiar with this video. In p5.js, I am using get() function. After use this, I will create small images (by dividing big tileset) and push them into an array. But in my code get() returns an empty pixels array. Here is a part of my code:
tilesImages = []; // tiles array
function preload() {
let tilesImage = loadImage(TILEMAP_PATH + "tiles.png", () => {
console.log("Tiles loaded successfully"); // It logs this
}, () => {
console.log("An error occured when tiles loaded");
});
for (let i = 0; i < TILE_HORIZONTAL; i++) {
for (let j = 0; j < TILE_VERTICAL; j++) {
let x = i * TILE_SIZE + TILES_SPACE;
let y = j * TILE_SIZE + TILES_SPACE;
if (i == 0) {
x = 0;
}
if (j == 0) {
y = 0;
}
var img = tilesImage.get(x, y, TILE_SIZE, TILE_SIZE); // get tiles from tileset
tilesImages.push(img);
}
}
}
function setup() {
console.log(tilesImages[0].pixels); // returns empty
}
I tried to use this but it just draws vertical pink lines to my small image.
My tileset: https://www.kenney.nl/assets/pixel-shmup (on right)
I am using single images now but I want to know the solution of this problem. Thanks
I believe the issue here is that you are not waiting for the image to actually be loaded. The loadImage function is asynchronous. That is, it only starts the process of loading the image, but it returns before it actually finish loading the image. So any code that comes after that will run immediately, while the loading is still in progress. You can use the callback function to run code after loading is complete. Here's a modified version of your code that should alleviate the problem:
tilesImages = []; // tiles array
function preload() {
let tilesImage = loadImage(
TILEMAP_PATH + "tiles.png",
() => {
console.log("Tiles loaded successfully"); // It logs this
// Wait until loading is complete to use tilesImage.get()
for (let i = 0; i < TILE_HORIZONTAL; i++) {
for (let j = 0; j < TILE_VERTICAL; j++) {
let x = i * TILE_SIZE + TILES_SPACE;
let y = j * TILE_SIZE + TILES_SPACE;
if (i == 0) {
x = 0;
}
if (j == 0) {
y = 0;
}
var img = tilesImage.get(x, y, TILE_SIZE, TILE_SIZE); // get tiles from tileset
tilesImages.push(img);
}
}
},
() => {
console.log("An error occured when tiles loaded");
}
);
}
We are using videojs.fairplay.js for playing DRM content in MAC safari browser. At first while playing DRM video we get one standard playlist (.m3u8) that has defined stack of segments (.ts). We need to know the each segment information and there complete meta information like (length, type, url, etc..).
var video = videojs("my-video");
video.on('playing', function () {
console.log("The video has been playing");
var segment = get_current_segment_info(this);
console.log(segment.uri);
});
function get_current_segment_info(obj, old_segment = null) {
var target_media = obj.tech().hls.playlists.media();
var snapshot_time = obj.currentTime();
var segment;
var segment_time;
// Itinerate trough available segments and get first within which snapshot_time is
for (var i = 0, l = target_media.segments.length; i < l; i++) {
// Note: segment.end may be undefined or is not properly set
if (snapshot_time < target_media.segments[i].end) {
segment = target_media.segments[i];
break;
}
}
// Null segment_time in case it's lower then 0.
if (segment) {
segment_time = Math.max(0, snapshot_time - (segment.end - segment.duration));
// Because early segments don't have end property
} else {
segment = target_media.segments[0];
segment_time = 0;
}
console.log(snapshot_time);
console.log(segment.uri);
console.log(segment.resolvedUri);
console.log(segment);
return segment;
}
Alright, so, hopefully this is a simple enough question. I'm sure that it has to be something simple and stupid that I am not doing right. I'm building an app to program my exercise routine into so I can keep track of it every week (and to learn app development using Cordova). Within the code, each time I come back to the exersetup screen I want to read the saved exercise file, parse it back to an array of objects, convert those objects back into exercise objects, then display them on the screen. I have a loop that is supposed to check each element of the array to process the information, then display, then repeat until it has done this for each element in the array. It works perfectly fine for the first item, then stops. If I manually run the loop multiple times, it functions perfectly. Not listed is the code for the function addRow(), which simply adds a row of formatted dropdown selectors for input, then increments rowNum to keep track of which row it is operating on. Any help you guys can offer is appreciated. If I need to submit more information I would be happy to do so. Here's the loop in question:
EDIT: Fixed some things to the suggestions in the comments below. Code still functions the same. Works perfectly fine on first run through loop, then stops. If I continue to run the loop manually (declaring it over and over again in console) it works fine, but it will not, for some reason, run the "for" loop. I've also included the rest of the function that the for loop is nested in, in case that helps.
function readRout()
{
console.log("Reading routine...");
document.addEventListener('deviceready', getFile, false);
function getFile()
{
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function(dir)
{
console.log("got main dir",dir);
dir.getFile("exerciseroutine.txt", {create:true}, function(file)
{
console.log("got the file", file);
exerLog = file;
console.log(exerLog);
});
});
document.addEventListener('deviceready', logOut, false);
}
function logOut()
{
setTimeout(readLog, 50);
}
function readLog()
{
exerLog.file(function(file)
{
var reader = new FileReader();
reader.onloadend = function(e)
{
console.log(this.result);
exerRoutine = JSON.parse(this.result);
//console.log(exerRoutine);
//console.log(exerRoutine[0]);
var looper = exerRoutine.length + 1;
for (var i=0; i<looper; i++)
{
console.log("Loop count is: " + i);
console.log(looper);
exerRoutine[i] = new exercise(exerRoutine[i].type, exerRoutine[i].name, exerRoutine[i].sets, exerRoutine[i].reps, exerRoutine[i].pace);
console.log(exerRoutine[i]);
console.log(exerRoutine[i].description());
console.log(exerRoutine[i].type);
console.log(exerRoutine[i].name);
console.log(exerRoutine[i].sets);
console.log(exerRoutine[i].reps);
console.log(exerRoutine[i].pace);
addRow();
setTimeout(fillExer, 50);
console.log(exerRoutine);
}
console.log(looper);
};
reader.readAsText(file);
}, fail);
}
function fillExer()
{
var typeRow = "typeSel" + rowNum;
console.log(typeRow);
console.log(document.getElementById(typeRow));
var nameRow = "nameSel" + rowNum;
var setsRow = "setsSel" + rowNum;
var repsRow = "repsSel" + rowNum;
var paceRow = "paceSel" + rowNum;
fillType(typeRow);
setTimeout(fillName, 10, nameRow);
fillSets(setsRow);
fillReps(repsRow);
fillPace(paceRow);
}
function fillType(typek)
{
for (var k=0; k<document.getElementById(typek).options.length; k++)
{
//console.log(document.getElementById(typek).options.length);
console.log(exerRoutine[rowNum-1].type);
if(document.getElementById(typek).options[k].value == exerRoutine[rowNum-1].type)
{
document.getElementById(typek).selectedIndex = k;
//console.log(document.getElementById(typei).selectedIndex);
var quer = "#" + typek;
//console.log(query);
var typeInput = document.querySelector(quer);
//console.log(typeInput);
TypeSelect(typeInput);
return;
}
}
}
function fillName(namek)
{
for (var k=0; k<document.getElementById(namek).options.length; k++)
{
//console.log(document.getElementById(namek).options.length);
console.log(exerRoutine[rowNum-1].name);
if(document.getElementById(namek).options[k].value === exerRoutine[rowNum-1].name)
{
document.getElementById(namek).selectedIndex = k;
//console.log(document.getElementById(namei).selectedIndex);
return;
}
}
}
function fillSets(setsk)
{
for (var k=0; k<document.getElementById(setsk).options.length; k++)
{
console.log(exerRoutine[rowNum-1].sets);
if(document.getElementById(setsk).options[k].value === exerRoutine[rowNum-1].sets)
{
document.getElementById(setsk).selectedIndex = k;
//console.log(document.getElementById(setsk).selectedIndex);
return;
}
}
}
function fillReps(repsk)
{
for (var k=0; k<document.getElementById(repsk).options.length; k++)
{
console.log(exerRoutine[rowNum-1].reps);
if(document.getElementById(repsk).options[k].value === exerRoutine[rowNum-1].reps)
{
document.getElementById(repsk).selectedIndex = k;
//console.log(document.getElementById(repsi).selectedIndex);
return;
}
}
}
function fillPace(pacek)
{
for (var k=0; k<document.getElementById(pacek).options.length; k++)
{
console.log(exerRoutine[rowNum-1].pace);
if(document.getElementById(pacek).options[k].value === exerRoutine[rowNum-1].pace)
{
document.getElementById(pacek).selectedIndex = k;
//console.log(document.getElementById(pacek).selectedIndex);
return;
}
}
}
}
I am creating some views in a loop iterating over list of objects. Now I want to register event with each view, which does something on the current object of the list.
for (var vs = 1; vs < 4; vs++) {
iMovie = moviesList[vs];
if (!iMovie) {
break;
}
var loopView = Ti.UI.createView({
....
});
loopView.addEventListener("click", function(e) {
var mv = iMovie;
Ti.API.info("Movie: " + mv);
if (mv) {
// do something
}
});
}
This code is not working, the log which is printed is : Movie: undefined.
So my question is how I can use the loop variable in the event listener?
Try the following code
var loopView - [];
var iMovie;
for (var vs = 1; vs < 4; vs++) {
iMovie = moviesList[vs];
if (!iMovie) {
break;
}
loopView[vs] = Ti.UI.createView({
_iMovie : iMovie
});
loopView[vs].addEventListener("click", function(e) {
var mv = e.source._iMovie;
Ti.API.info("Movie: " + mv);
if (mv) {
// do something
}
});
}
Well, first I'll start that what you are doing in the code above could potentially cause a memory leak since you are holding a reference to the iMovie variable.
what you should try doing is:
var mv = e.source;
this will return the source object that fired the click event.
I have created a JavaScript application that requires all images to be preloaded first. Everything works fine in Firefox but in Internet Explorer my loop skips the count at 19 and goes to 21. Has anyone come across this problem before and what causes it?
You can copy and paste the script below for test purposes.
var preLoad = function () {
var docImages = ["http://www.sanatural.co.za/media/images/map/rsa_prov.gif", "http://www.sanatural.co.za/media/images/map/loading.gif", "http://www.sanatural.co.za/media/images/map/loading2.gif", "http://www.sanatural.co.za/media/images/map/ec_land.gif", "http://www.sanatural.co.za/media/images/map/ec_roll.gif", "http://www.sanatural.co.za/media/images/map/ec_state.gif", "http://www.sanatural.co.za/media/images/map/fs_land.gif", "http://www.sanatural.co.za/media/images/map/fs_roll.gif", "http://www.sanatural.co.za/media/images/map/fs_state.gif", "http://www.sanatural.co.za/media/images/map/gt_land.gif", "http://www.sanatural.co.za/media/images/map/gt_roll.gif", "http://www.sanatural.co.za/media/images/map/gt_state.gif", "http://www.sanatural.co.za/media/images/map/kzn_land.gif", "http://www.sanatural.co.za/media/images/map/kzn_roll.gif", "http://www.sanatural.co.za/media/images/map/kzn_state.gif", "http://www.sanatural.co.za/media/images/map/lp_land.gif", "http://www.sanatural.co.za/media/images/map/lp_roll.gif", "http://www.sanatural.co.za/media/images/map/lp_state.gif", "http://www.sanatural.co.za/media/images/map/mp_land.gif", "http://www.sanatural.co.za/media/images/map/mp_roll.gif", "mp_state.gif", "http://www.sanatural.co.za/media/images/map/nc_land.gif", "http://www.sanatural.co.za/media/images/map/nc_roll.gif", "http://www.sanatural.co.za/media/images/map/nc_state.gif", "http://www.sanatural.co.za/media/images/map/nw_land.gif", "http://www.sanatural.co.za/media/images/map/nw_roll.gif", "http://www.sanatural.co.za/media/images/map/nw_state.gif", "http://www.sanatural.co.za/media/images/map/wc_land.gif", "http://www.sanatural.co.za/media/images/map/wc_roll.gif", "http://www.sanatural.co.za/media/images/map/wc_state.gif"],
imageFolder = [],
loaded = [],
loadedCounter = 0;
this.loadImgs = function () {
for (var i = 0; i < docImages.length; i++) {
imageFolder[i] = new Image();
imageFolder[i].src = docImages[i];
loaded[i] = false;
}
intervalId = setInterval(loadedCheck, 10); //
};
function loadedCheck() {
if (loadedCounter == imageFolder.length) { // all images have been preloaded
clearInterval(intervalId);
alert('All images have been preloaded!');
return;
}
for (var i = 0; i < imageFolder.length; i++) {
if (loaded[i] === false && imageFolder[i].complete) {
loaded[i] = true;
loadedCounter++;
alert(i); // (work fine in FF but i.e goes from 19 to 21 )
}
}
}
};
var preloadObject = new preLoad();
preloadObject.loadImgs();
The reason for this is that the item on index 20 is "mp_state.gif" - its missing the complete url.
Because of this the image isn't loaded, the .complete property is set to false, and so the loop skips this item.