In a chrome extension, you can set permissions in manifest.json. I assume crossrider generates this file behind the scenes. How can change the permissions generated by a crossrider extension or is it not possible yet?
My extension in particular needs access to image and video data on all pages. This gets denied with a CORS error and I believe setting the proper permissions would solve my problem.
[EDIT]
Here's the core of my code:
try {
//all nodes in the DOM go through this function
var parseNode = function(node) {
//only get img and video tags
var nodeName = node.nodeName.toUpperCase();
if (["IMG", "VIDEO"].indexOf(nodeName) == -1)
return;
//attempt to extract their pixel data
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
try {
console.log(node.src, " ", node.clientWidth, "x", node.clientHeight);
canvas.width = node.clientWidth; //may be zero if failed CORS
canvas.height = node.clientHeight;
context.drawImage(node, 0, 0);
var dat = context.getImageData(0, 0, canvas.width, canvas.height);
console.log("Success");
canvas.remove();
return dat.pixels;
}
catch (e) {
console.log("Failed ", node, ": ", e);
canvas.remove();
}
return null;
};
//parse everything currently loaded
var everything = document.getElementsByTagName("*");
for (var i = 0; i < everything.length; i++) {
parseNode(everything[i]);
}
//use a mutation ovserver to parse everything that gets injected later
var parseMutations = function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
parseNode(mutation.addedNodes[i]);
}
}
});
};
var observer = new MutationObserver(parseMutations);
observer.observe(document, {
childList: true,
subtree: true
});
}
catch (e)
{
//this has to be here since all browsers are so shit at catching syntax errors in extensions
//not to mention the crossrider extension won't install properly if there's a typo or missing semicolon. so much pain
console.log(e, " ", e.stack); //stack is pretty useless with crossrider code injection
}
On many pages I just get a tonne of these:
DOMException {
code: 18
message: "Failed to execute 'getImageData' on 'CanvasRenderingContext2D': the canvas has been tainted by cross-origin data."
name: "SecurityError"
...
[EDIT]
I've removed the try/catch so the errors print properly. I'm still seeing lots of errors.
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': the canvas has been tainted by cross-origin data.
I'm using this page to test with: http://en.wikipedia.org/wiki/HSL_and_HSV
"Run in IFrame" is off.
try {
//all image and video nodes in the DOM go through this function
var parseNode = function(node) {
//attempt to extract their pixel data
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
node.title = "FAILED";
console.log(node.src, " ", node.clientWidth, "x", node.clientHeight);
canvas.width = Math.max(1, node.clientWidth); //may be zero if failed CORS
canvas.height = Math.max(1, node.clientHeight);
context.drawImage(node, 0, 0);
var dat = context.getImageData(0, 0, canvas.width, canvas.height);
canvas.remove();
return dat.pixels;
node.title = "SUCCESS";
return null;
};
//parse everything currently loaded
var everything = document.getElementsByTagName("*");
for (var i = 0; i < everything.length; i++) {
var node = everything[i];
var nodeName = node.nodeName.toUpperCase();
if (["IMG", "VIDEO"].indexOf(nodeName) != -1)
(function(n) {setTimeout(function(){parseNode(n);},1000);})(node);
}
//use a mutation ovserver to parse everything that gets injected later
var parseMutations = function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
var node = mutation.addedNodes[i];
var nodeName = node.nodeName.toUpperCase();
if (["IMG", "VIDEO"].indexOf(nodeName) != -1)
(function(n) {setTimeout(function(){parseNode(n);},1000);})(node);
}
}
});
};
var observer = new MutationObserver(parseMutations);
observer.observe(document, {
childList: true,
subtree: true
});
}
catch (e)
{
//this has to be here since all browsers are so shit at catching syntax errors in extensions
console.log(e, " ", e.stack); //stack is pretty useless with crossrider code injection
}
Currently, the Crossrider platform does not provide a mechanism for modifying manifest permissions though there are plans to consider this for future releases.
Hence, you may manually experiment with adding the permission in the CRX file, though bear in mind that it may hinder the ability to support your extension.
[Disclosure: I am a Crossrider employee]
Related
I have been at this problem for days now and still can't find out what the problem must be.
The HTTPClient is not being cleaned up properly and thus the apps memory is exploding when looping over say 100 images to download.
I am testing in a simple alloy template created by using appc new -t titanium.
only an index view is opened with one button to start the download loop
my index file looks like the following:
var max = 100
var i = 0
var c = Ti.Network.createHTTPClient();
c.onerror = function () {
c = null;
}
c.onload = function () {
saveFile(this.responseData)
console.log("done get")
i++
getfiles()
}
function getfiles () {
if (i < max) {
try {
c.open('GET', "https://cdn.fossilswitzerland.ch/large0/FS4931.jpg");
c.send();
} catch (e) {
}
} else {
c = null
console.log("finished")
}
}
function saveFile (response) {
console.log("STORING")
var f = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'FS4931.jpg');
f.write(response);
if (f.exists() === false) {
console.log("NOT STORED")
} else {
console.log("STORED")
}
f = null;
}
$.index.open();
Initially after the app has booted memory is at ca. 30mb
So far so good
After clicking get images button on the index page, memory goes up to ca. 62mb
Then after a while goes down to ca. 50mb which leaves 20mb unaccounted for
I am using:
Xcode 10.3
Ti SDK Version 8.1.1.GA
Simulator: iPad Pro (2nd generation) on 12.4
When changing max to 1000, memory soars to around 322mb and doesn't seem to decrease at any more.
This is a really big problem when looping through and downloading say 2000 images because the app just crashes at some point
Thank you for any help
I've changed the code a bit (for-loop, use the file property, don't re-use the httpclient (check the documentation), classic code so it is quicker to test):
var w = Ti.UI.createWindow();
var b = Ti.UI.createButton({
title: "download"
});
w.add(b);
function onError(e) {
console.log("error", e);
}
function onLoad(e) {
console.log("done get")
}
function getfiles(e) {
for (var i = 0; i < 100; ++i) {
var c = Ti.Network.createHTTPClient({
onerror: onError,
onload: onLoad
});
c.open('GET', "https://cdn.fossilswitzerland.ch/large0/FS4931.jpg");
var fname = Ti.Filesystem.applicationSupportDirectory + "/" + (new Date().getTime()) + ".jpg";
console.log("Download to", fname);
c.file = fname;
c.send();
c = null;
fname = null;
}
}
b.addEventListener("click", getfiles);
w.open();
I get a little overhead when it is releasing memory (around 5mb). You could create a JIRA ticket (https://jira.appcelerator.org/) so they can check it.
I'm building an office-js add-in for Excel. I need to upload the current workbook to a back end server. I've implemented an example from the Micrsoft Documentation, which seems to work fine the first time I call it, but on subsequent calls, it causes Excel to crash. I'm using Excel 365 version 1812 (build 11126.20132)
Here is the link to the example in the MS docs:
https://learn.microsoft.com/en-us/javascript/api/office/office.document
There are many examples on this page, to find the one I'm working from search for "The following example gets the document in Office Open XML" I've included the example below for ease of reference.
The code just get's the current file and dumps the characters to the console's log. It works fine the first but crashes Excel the second time--after it has shown the length of FileContent.
export function getDocumentAsCompressed() {
Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: 65536 /*64 KB*/ },
function (result) {
if (result.status == "succeeded") {
// If the getFileAsync call succeeded, then
// result.value will return a valid File Object.
var myFile = result.value;
var sliceCount = myFile.sliceCount;
var slicesReceived = 0, gotAllSlices = true, docdataSlices = [];
console.log("File size:" + myFile.size + " #Slices: " + sliceCount);
// Get the file slices.
getSliceAsync(myFile, 0, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
}else {
console.log("Error:", result.error.message);
}
});
}
function getSliceAsync(file, nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived) {
file.getSliceAsync(nextSlice, function (sliceResult) {
if (sliceResult.status == "succeeded") {
if (!gotAllSlices) { // Failed to get all slices, no need to continue.
return;
}
// Got one slice, store it in a temporary array.
// (Or you can do something else, such as
// send it to a third-party server.)
// console.log("file part",sliceResult.value.data)
docdataSlices[sliceResult.value.index] = sliceResult.value.data;
if (++slicesReceived == sliceCount) {
// All slices have been received.
file.closeAsync();
onGotAllSlices(docdataSlices);
}
else {
getSliceAsync(file, ++nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
}
}
else {
gotAllSlices = false;
file.closeAsync();
console.log("getSliceAsync Error:", sliceResult.error.message);
}
});
}
function onGotAllSlices(docdataSlices) {
var docdata = [];
for (var i = 0; i < docdataSlices.length; i++) {
docdata = docdata.concat(docdataSlices[i]);
}
var fileContent = new String();
for (var j = 0; j < docdata.length; j++) {
fileContent += String.fromCharCode(docdata[j]);
}
console.log("fileContent.length",fileContent.length)
// Now all the file content is stored in 'fileContent' variable,
// you can do something with it, such as print, fax...
}
Here is the result
File size:21489 #Slices: 1
fileContent.length 21489
Original example from Microsoft documentation (https://learn.microsoft.com/en-us/javascript/api/office/office.document)
// The following example gets the document in Office Open XML ("compressed") format in 65536 bytes (64 KB) slices.
// Note: The implementation of app.showNotification in this example is from the Visual Studio template for Office Add-ins.
function getDocumentAsCompressed() {
Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: 65536 /*64 KB*/ },
function (result) {
if (result.status == "succeeded") {
// If the getFileAsync call succeeded, then
// result.value will return a valid File Object.
var myFile = result.value;
var sliceCount = myFile.sliceCount;
var slicesReceived = 0, gotAllSlices = true, docdataSlices = [];
app.showNotification("File size:" + myFile.size + " #Slices: " + sliceCount);
// Get the file slices.
getSliceAsync(myFile, 0, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
}
else {
app.showNotification("Error:", result.error.message);
}
});
}
function getSliceAsync(file, nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived) {
file.getSliceAsync(nextSlice, function (sliceResult) {
if (sliceResult.status == "succeeded") {
if (!gotAllSlices) { // Failed to get all slices, no need to continue.
return;
}
// Got one slice, store it in a temporary array.
// (Or you can do something else, such as
// send it to a third-party server.)
docdataSlices[sliceResult.value.index] = sliceResult.value.data;
if (++slicesReceived == sliceCount) {
// All slices have been received.
file.closeAsync();
onGotAllSlices(docdataSlices);
}
else {
getSliceAsync(file, ++nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
}
}
else {
gotAllSlices = false;
file.closeAsync();
app.showNotification("getSliceAsync Error:", sliceResult.error.message);
}
});
}
function onGotAllSlices(docdataSlices) {
var docdata = [];
for (var i = 0; i < docdataSlices.length; i++) {
docdata = docdata.concat(docdataSlices[i]);
}
var fileContent = new String();
for (var j = 0; j < docdata.length; j++) {
fileContent += String.fromCharCode(docdata[j]);
}
// Now all the file content is stored in 'fileContent' variable,
// you can do something with it, such as print, fax...
}
// The following example gets the document in PDF format.
Office.context.document.getFileAsync(Office.FileType.Pdf,
function(result) {
if (result.status == "succeeded") {
var myFile = result.value;
var sliceCount = myFile.sliceCount;
app.showNotification("File size:" + myFile.size + " #Slices: " + sliceCount);
// Now, you can call getSliceAsync to download the files,
// as described in the previous code segment (compressed format).
myFile.closeAsync();
}
else {
app.showNotification("Error:", result.error.message);
}
}
);
Since you're using Excel, have you tried the CreateWorkbork API? Might be a good workaround if the Document API has a bug, like Xuanzhou indicated earlier.
Here's a CreateDocument snippet that you can load into Script Lab. It shows how to create a Workbook copy based on an existing file.
Hope all that is helpful.
We already have a fix for it now. But the fix still need some time to go to production. Please try it several days later and let me know if the issue still exists. Thanks.
I have found on the internet this interesting article about plugins in mongoose. From that site I got this code:
function HidePlugin(schema) {
var toHide = [];
schema.eachPath(function(pathname, schemaType) {
if (schemaType.options && schemaType.options.hide) {
toHide.push(pathname);
}
});
schema.options.toObject = schema.options.toObject || {};
schema.options.toObject.transform = function(doc, ret) {
// Loop over all fields to hide
toHide.forEach(function(pathname) {
// Break the path up by dots to find the actual
// object to delete
var sp = pathname.split('.');
var obj = ret;
for (var i = 0; i < sp.length - 1; ++i) {
if (!obj) {
return;
}
obj = obj[sp[i]];
}
// Delete the actual field
delete obj[sp[sp.length - 1]];
});
return ret;
};
}
The problem is that I use typescript together with node.js. The typescript compiler gives me errors because there are no explicit types. In fact, I do not know exactly what type I have to attribute to the variables in the code
I use this function to watch an array of objects for changes:
$scope.$watch('Data', function (newVal) { /*...*/ }, true);
How can I get an object in which property has been changed so that I can push it in an array?
For example:
var myApp = angular.module("myApp", []);
myApp.factory("Data", function(){
var Data = [{id:1, property: "Random"}, {id:2, property: "Random again"}];
return Data;
});
var myBigArray = [];
function tableCtrl($scope, Data){
$scope.TheData = Data;
$scope.$watch("TheData", function() {
//Here an object should be pushed
myBigArray.push(">>Object in which property has been changed <<<");
}, true);
}
I don't see a way currently in Angular to get the changed object... I suspect you might need to traverse the new array and try to find the differences with the old array...
Edit: Note that this solution turns out to be a bad practice as it is adding a lot of watchers, which is something you do not want because it has a performance penalty.
=======
I eventually came up with this solution:
items.query(function (result) {
_(result).each(function (item, i) {
$scope.items.push(item);
$scope.$watch('items[' + i + ']' , function(){
console.log(item); // This is the item that changed.
}, true);
});
});
There is still no option like this for $watch, but you can use jQuery plugin for that, http://archive.plugins.jquery.com/project/jquery-diff
I implemented undo/redo with AngularJS using $watch, mb this can help
//History Manager Factory
.factory('HistoryManager', function () {
return function(scope) {
this.container = Array();
this.index = -1;
this.lock = false;
//Insert new step into array of steps
this.pushDo = function() {
//we make sure that we have real changes by converting to json,
//and getting rid of all hash changes
if(this.container.length == 0 || (angular.toJson(scope.widgetSlider) != angular.toJson(this.container[this.index][0]))) {
//check if current change didn't came from "undo" change'
if(this.lock) {
return;
}
//Cutting array, from current index, because of new change added
if(this.index < this.container.length-1) {
this.container = this.container.slice(0, this.index+1);
}
var currentStepSlider = angular.copy(scope.widgetSlider);
var selectedWidgetIndex = scope.widgetSlider.widgets.indexOf(scope.widgetCurrent);
//Initialising index, because of new "Do" added
this.index = this.container.length;
this.container.push([currentStepSlider, selectedWidgetIndex]);
if (this.onDo) {
this.onDo();
}
}
}
//Upon undo returns previous do
this.undo = function() {
this.lock = true;
if(this.index>0){
this.index--;
scope.widgetSlider = angular.copy(this.container[this.index][0]);
var selectedWidgetIndex = this.container[this.index][1];
scope.widgetCurrent = scope.widgetSlider.widgets[selectedWidgetIndex];
}
this.lock = false;
}
//Upon redo returns next do
this.redo = function() {
if(this.index < this.container.length-1) {
this.index++;
scope.widgetSlider = angular.copy(this.container[this.index][0]);
var selectedWidgetIndex = this.container[this.index][1];
scope.widgetCurrent = scope.widgetSlider.widgets[selectedWidgetIndex];
}
}
}
})
;
I'm trying to create a simple chrome extension using the following google RSS reader sample,
http://code.google.com/chrome/extensions/samples.html#597015d3bcce3da693b02314afd607bec4f55291
I can add links in the pop-up window that open tabs, but not from the feeds themselves.
Looping through the items in the feed, grabbing title tags and link tags, I want the title to link the the appropriate sites
var entries = doc.getElementsByTagName('item');
var count = Math.min(entries.length, maxFeedItems);
for (var i = 0; i < count; i++) {
item = entries.item(i);
// Grab the title for the feed item.
var itemTitle = item.getElementsByTagName('title')[0];
if (itemTitle) {
itemTitle = itemTitle.textContent;
} else {
itemTitle = "Unknown title";
}
// Grab the link for this feed item
var itemLink = item.getElementsByTagName('link')[0];
if (itemLink) {
itemLink = itemLink.textContent;
} else {
itemLink = "Unknown link";
}
var title = document.createElement("a");
title.className = "item_title";
title.innerText = itemTitle; //display title in iframe
title.addEventListener("click", titleLink); // should open link when clicking on title, but does not.
}
// -------------------------------------------------------------------
// Show |url| in a new tab.
function showUrl(url) {
// Only allow http and https URLs.
if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) {
return;
}
chrome.tabs.create({url: url});
}
function moreStories(event) {
showUrl(moreStoriesUrl);
}
function titleLink(event) {
showUrl(itemLink);
}
Any thoughts on why this is not working.
If I replace title.addEventListener("click", titleLink); with title.addEventListener("click", moreStories); each title will link to moreStories, I cannot get each title to link to itemLink.
Thanks
Its a bit hard to answer your question without the whole code, but Ill give it a shot ;)
First up, titleLink() isnt going to work because itemLink isnt known. When you create title (the link) you should of attached it to that...say title.href=itemLink then in tiltleLinks you could access that href with showUrl(event.currentTarget.href)
Also did you fix the error in that example?...if not then change frameLoaded to....
function frameLoaded() {
var links = document.getElementsByTagName("A");
for (i = 0; i < links.length; i++) {
var clssName = links[i].className;
if (clssName != "item_title" && clssName != "open_box") {
links[i].addEventListener("click", showStory);
}
}
window.addEventListener("message", messageHandler);
}
If you still have probs could you attach the whole code so I can see what your doing and Ill give you a hand.
Thank you very much for your help.
code title.href=itemLink and code showUrl(event.currentTarget.href) was exactly what I needed.
For completeness, here is the full code,
<script id="iframe_script">
function reportHeight() {
var msg = JSON.stringify({type:"size", size:document.body.offsetHeight});
parent.postMessage(msg, "*");
}
function frameLoaded() {
var links = document.getElementsByTagName("A");
for (i = 0; i < links.length; i++) {
var class = links[i].className;
if (class != "item_title" && class != "open_box") {
links[i].addEventListener("click", showStory);
}
}
window.addEventListener("message", messageHandler);
}
function showStory(event) {
var href = event.currentTarget.href;
parent.postMessage(JSON.stringify({type:"show", url:href}), "*");
event.preventDefault();
}
function messageHandler(event) {
reportHeight();
}
</script>
<script>
// Feed URL.
var feedUrl = 'http://localhost/newsfeed.xml';
// The XMLHttpRequest object that tries to load and parse the feed.
var req;
function main() {
req = new XMLHttpRequest();
req.onload = handleResponse;
req.onerror = handleError;
req.open("GET", feedUrl, true);
req.send(null);
}
// Handles feed parsing errors.
function handleFeedParsingFailed(error) {
var feed = document.getElementById("feed");
feed.className = "error";
feed.innerText = "Error: " + error;
}
// Handles errors during the XMLHttpRequest.
function handleError() {
handleFeedParsingFailed('Failed to fetch RSS feed.');
}
// Handles parsing the feed data we got back from XMLHttpRequest.
function handleResponse() {
var doc = req.responseXML;
if (!doc) {
handleFeedParsingFailed("Not a valid feed.");
return;
}
buildPreview(doc);
}
// The maximum number of feed items to show in the preview.
var maxFeedItems = 10;
// Where the more stories link should navigate to.
var moreStoriesUrl;
function buildPreview(doc) {
// Get the link to the feed source.
var link = doc.getElementsByTagName("link");
var parentTag = link[0].parentNode.tagName;
if (parentTag != "item" && parentTag != "entry") {
moreStoriesUrl = link[0].textContent;
}
// Setup the title image.
var images = doc.getElementsByTagName("image");
var titleImg;
if (images.length != 0) {
var urls = images[0].getElementsByTagName("url");
if (urls.length != 0) {
titleImg = urls[0].textContent;
}
}
var img = document.getElementById("title");
// Listen for mouse and key events
if (titleImg) {
img.src = titleImg;
if (moreStoriesUrl) {
document.getElementById("title_a").addEventListener("click",moreStories);
document.getElementById("title_a").addEventListener("keydown",
function(event) {
if (event.keyCode == 13) {
moreStories(event);
}});
}
} else {
img.style.display = "none";
}
// Construct the iframe's HTML.
var iframe_src = "<!doctype html><html><head><script>" +
document.getElementById("iframe_script").textContent + "<" +
"/script></head><body onload='frameLoaded();' " +
"style='padding:0px;margin:0px;'>";
var feed = document.getElementById("feed");
// Set ARIA role indicating the feed element has a tree structure
feed.setAttribute("role", "tree");
var entries = doc.getElementsByTagName('item');
var count = Math.min(entries.length, maxFeedItems);
for (var i = 0; i < count; i++) {
item = entries.item(i);
// Grab the title for the feed item.
var itemTitle = item.getElementsByTagName('title')[0];
if (itemTitle) {
itemTitle = itemTitle.textContent;
} else {
itemTitle = "Unknown title";
}
// Grab the link for the feed item.
var itemLink = item.getElementsByTagName('link')[0];
if (itemLink) {
itemLink = itemLink.textContent;
} else {
itemLink = "Unknown link";
}
var item = document.createElement("div");
var title = document.createElement("a");
title.innerText = itemTitle; //display title in iframe
title.href=itemLink;
title.addEventListener("click", titleLink);
item.appendChild(title);
feed.appendChild(item);
}
if (moreStoriesUrl) {
var more = document.createElement("a");
more.className = "more";
more.innerText = "***Site Main Page*** \u00BB";
more.tabIndex = 0;
more.addEventListener("click", moreStories);
more.addEventListener("keydown", function(event) {
if (event.keyCode == 13) {
moreStories(event);
}});
feed.appendChild(more);
}
}
// -------------------------------------------------------------------
// Show |url| in a new tab.
function showUrl(url) {
// Only allow http and https URLs.
if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) {
return;
}
chrome.tabs.create({url: url});
}
// -------------------------------------------------------------------
function moreStories(event) {
showUrl(moreStoriesUrl);
}
function titleLink(event) {
showUrl(event.currentTarget.href);
}
function keyHandlerShowDesc(event) {
// Display content under heading when spacebar or right-arrow pressed
// Hide content when spacebar pressed again or left-arrow pressed
// Move to next heading when down-arrow pressed
// Move to previous heading when up-arrow pressed
if (event.keyCode == 32) {
showDesc(event);
} else if ((this.parentNode.className == "item opened") &&
(event.keyCode == 37)) {
showDesc(event);
} else if ((this.parentNode.className == "item") && (event.keyCode == 39)) {
showDesc(event);
} else if (event.keyCode == 40) {
if (this.parentNode.nextSibling) {
this.parentNode.nextSibling.children[1].focus();
}
} else if (event.keyCode == 38) {
if (this.parentNode.previousSibling) {
this.parentNode.previousSibling.children[1].focus();
}
}
}
function showDesc(event) {
var item = event.currentTarget.parentNode;
var items = document.getElementsByClassName("item");
for (var i = 0; i < items.length; i++) {
var iframe = items[i].getElementsByClassName("item_desc")[0];
if (items[i] == item && items[i].className == "item") {
items[i].className = "item opened";
iframe.contentWindow.postMessage("reportHeight", "*");
// Set the ARIA state indicating the tree item is currently expanded.
items[i].getElementsByClassName("item_title")[0].
setAttribute("aria-expanded", "true");
iframe.tabIndex = 0;
} else {
items[i].className = "item";
iframe.style.height = "0px";
// Set the ARIA state indicating the tree item is currently collapsed.
items[i].getElementsByClassName("item_title")[0].
setAttribute("aria-expanded", "false");
iframe.tabIndex = -1;
}
}
}
function iframeMessageHandler(e) {
// Only listen to messages from one of our own iframes.
var iframes = document.getElementsByTagName("IFRAME");
for (var i = 0; i < iframes.length; i++) {
if (iframes[i].contentWindow == e.source) {
var msg = JSON.parse(e.data);
if (msg) {
if (msg.type == "size") {
iframes[i].style.height = msg.size + "px";
}
else if (msg.type == "show") {
var url = msg.url;
if (url.indexOf("http://localhost/index.html") == 0) {
// If the URL is a redirect URL, strip of the destination and go to
// that directly. This is necessary because the Google news
// redirector blocks use of the redirects in this case.
var index = url.indexOf("&url=");
if (index >= 0) {
url = url.substring(index + 5);
index = url.indexOf("&");
if (index >= 0)
url = url.substring(0, index);
}
}
showUrl(url);
}
}
return;
}
}
}
window.addEventListener("message", iframeMessageHandler);
</script>
Thanks again for the help.
-Mike