treemodel + skype-bots Cannot read property 'model' of undefined - node.js

I'm working on skype bot app. I have issue with read the node from tree-model.
Tree-model example follow the children node but my node has diff tab to read by system.
XML example-
<?xml version="1.0" encoding="UTF-8" ?>
<rootmenu id="1" title="menu" description="What scenario would you like to run?">
<MenuOption id="1.1" title="Company Data" response="You entered company data" description="What action would you like to perform">
<HierarchyMenuItem id="1.1.1.1" title="Select new data " response="You entered select new filter">
<action>Filter</action>
</HierarchyMenuItem>
<HierarchyMenuItem id="1.1.1.2" title="Navigate node" response="You entered select node">
<action description="Current Filter is ">Hierarchy</action>
<HierarchyLevel level="1" name="One" navigateHierarchy="true">
<action>RootAction</action>
<Option title="Select a Country">
<OptionChoices id="1" title="One1" refNode="ForOne1" />
<OptionChoices id="2" title="One2" refNode="ForOne2" />
<OptionChoices id="3" title="One3" refNode="ForOne3" />
<OptionChoices id="4" title="One4" refNode="ForOne4" />
</Option>
</HierarchyLevel>
</HierarchyMenuItem>
</MenuOption>
<MenuOption id="1.2" title="Adhoc Data">
<Option>
<OptionChoices id="1" title="Ad1" refNode="ForAdOne1" />
<OptionChoices id="2" title="Ad2" refNode="ForAdOne2" />
<OptionChoices id="3" title="Ad3" refNode="ForAdOne3" />
<OptionChoices id="4" title="Ad4" refNode="ForAdOne4" />
</Option>
</MenuOption>
<MenuOption id="1.3" title="(quit)">
</MenuOption>
</rootmenu>
Read the xml from server-
function getXMLData(callback) {
var request = require('request');
var DOMParser = require('xmldom').DOMParser;
var simpleconvertxml = require('simpleconvert-xml');
request('http://demo.in/RefactoredXML.xml', function (error, response, body) {
if (!error && response.statusCode == 200) {
var xmlnode = new DOMParser().parseFromString([body].join('\n'), 'text/xml');
var myNumber = simpleconvertxml.getXMLAsObj(xmlnode);
treeRoot = tree.parse(myNumber.rootmenu);
callback(treeRoot);
}
})
}
My first bot call
bot.dialog('/menu', [
function (session, args) {
getXMLData(function (treeRoot) {
//session.send('node place:'+treeRoot.model.title);
var firstChild = [];
for (var i = 0; i < treeRoot.model.MenuOption.length; i++) {
if(treeRoot.model.MenuOption[i].title !='' && treeRoot.model.MenuOption[i].title != undefined && treeRoot.model.MenuOption[i].title != null) {
firstChild.push(treeRoot.model.MenuOption[i].title);
}
}
if(firstChild.length > 0) {
builder.Prompts.choice(session, treeRoot.model.description,firstChild );
// it shows builder.Prompts.choice(session, "What scenario would you like to run? ", "company data|adhoc data|(quit)");
} else {
session.send('Something went wrong. You can use the back or top command.');
}
});
},
function (session, results) {
if (results.response && results.response.entity != '(quit)') {
session.userData.profile.treeSelectdNodeTitle = results.response.entity;
getXMLData(function (treeRoot) {
for (var i = 0; i < treeRoot.model.MenuOption.length; i++) {
if(treeRoot.model.MenuOption[i].title == session.userData.profile.treeSelectdNodeTitle) {
session.userData.profile.treeSelectdNodeId = treeRoot.model.MenuOption[i].id;
session.userData.profile.treeSelectdResponse = treeRoot.model.MenuOption[i].response;
}
}
session.send('resp ' + session.userData.profile.treeSelectdResponse);
if(treeRoot.hasChildren()) {
session.send('in the children');
session.beginDialog('/get Tree Node');
} else {
session.send('in the title');
session.beginDialog('/'+ treeRoot.model.title);
}
});
} else {
// Exit the menu
session.endDialog();
}
},
function (session, results) {
// The menu runs a loop until the user chooses to (quit).
session.replaceDialog('/menu');
}
]).reloadAction('reloadMenu', null, {matches: /^menu|show menu|top|top menu/i});
Menu dialog call should display 1.company data 2. adhoc data 3. (quit) but its showing only 1.company data 2.adhoc data and Issue in the menu is if user select the 1 option as Company Data it will not goes to treeRoot.hasChildren() condition.
bot.dialog('/get Tree Node', [
function(session,agrs) {
getTreeNode(session);
}
]);
function getTreeNode(session) {
session.send("in tree "+ session.userData.profile.treeSelectdNodeId);
getXMLData(function(treeRoot) {
var nextLevel = treeRoot.first(function (node) {
return node.model.id === session.userData.profile.treeSelectdNodeId;
});
session.send('selected title '+ nextLevel.model.HierarchyMenuItem[0].title);
/* var secondListChild = [];
for(var i = 0; i < nextLevel.model.HierarchyMenuItem.length; i++) {
if(nextLevel.model.HierarchyMenuItem[i].title !='' && nextLevel.model.HierarchyMenuItem[i].title != undefined && nextLevel.model.HierarchyMenuItem[i].title != null) {
secondListChild.push(nextLevel.model.HierarchyMenuItem[i].title);
}
}
if(secondListChild.length > 0) {
builder.Prompts.choice(session, nextLevel.model.description,secondListChild);
} else {
session.send('Something went wrong. You can use the back or top command.');
} */
});
}
issue with the getTreeNode is
session.send('selected title '+ nextLevel.model.HierarchyMenuItem[0].title);
^
TypeError: Cannot read property 'model' of undefined

Got Solution....
I have change the XML parse NPM and its working for me..
var parse = require('xml-parser');
var inspect = require('util').inspect;
function getXMLData(callback) {
var request = require('request');
request('http://ztdemo.headfitted.in/RefactoredXML.xml', function (error, response, body) {
if (!error && response.statusCode == 200) {
var obj = parse(body);
//console.log(inspect(obj, { colors: true, depth: Infinity }));
//callback(treeRoot);
treeRoot = tree.parse(obj.root);
callback(treeRoot);
}
})
}

Related

Simple console menu

I'm a beginner in node and I'm trying to build a simple console menu. I kept searching for this but coulnd't find a proper answer.
When I run the script I want to display a menu and ask the user to enter an option. After he chooses, I perform an action then display the menu again.
I tried using a while loop but it's blocking my program.
Here's an example of what I'm trying to achieve:
int userRes = -1;
while(userRes != 0){
console.log("Option 1")
console.log("Option 2")
console.log("Option 3")
userRes = readLineSync.question("Pick an option");
if(userRes == 1){
doSomething();
}else if (userRes == 2){
doSomethingElse();
}
}
EDIT: Actual code bellow. As you can see I use stomp. The while loop displays my menu and the action inside the if statement gets executed.
The problem is, when stomp sends back the response my code in the subscribe function is not being executed.
I tried without a while (just the action) and it works perfectly.
var Stomp = require("stomp-client");
const readlineSync = require("readline-sync");
var client = new Stomp(host, 61613);
function conn(res,req){
client.connect(function(sessionId) {
client.subscribe("/queue/" + res, function(body, headers) {
console.log(body);
});
var res = -1;
while (res != 0) {
displayMenu();
var res = readlineSync.question("Introduceti o optiune: ");
if (res == 1) {
client.publish("/queue/" + req, "test");
} else if (res == 0) {
process.exit();
}
}
});
}
function displayMenu() {
console.log(
"Option one\n Option two\n 0 for exit";
);
}
You can use this code
const readLineSync = require('readline-sync')
let userRes;
while (userRes !== '0') {
console.log("Option 1")
console.log("Option 2")
console.log("Option 3")
userRes = readLineSync.question("Pick an option");
if (userRes === '1') {
doSomething()
} else if (userRes === '2') {
doSomethingElse()
}
}

How can I get female voice by Web Speech API in Google Chrome

In a webpage, I want a female voice to speak my texts. I tried to do this by following code. But still now male voice is talking. How can I arrange a female voice to talk my texts? Can anybody share me a correct code that works in Google Chrome.
var voices = speechSynthesis.getVoices();
var msg = new SpeechSynthesisUtterance("Hello World!");
msg.default=false;
msg.localservice=true;
msg.lang = "en-GB";
msg.voice = voices[3].name;
speechSynthesis.speak(msg);
The below code worked for me. I hope it works for you.
var msg = new SpeechSynthesisUtterance();
var voices = window.speechSynthesis.getVoices();
msg.voice = voices[3];
msg.text = "Hello World";
speechSynthesis.speak(msg);
On the 1st try it might give out male's voice. But on the 2nd attempt (without refreshing) it will give out the female's voice and try deploying it on a dummy server, there it will work like a charm in the first go.
This happens to me that the voice doesn't change at the first time the page is loaded.
I found a solution that works for me.
getVoices() should be triggered when the document is ready.
So I add at the top of my js like this.
$(document).ready(function() {
var voices = window.speechSynthesis.getVoices();
})
On Chrome, I do something like this:
<html>
<head>
<script>
function speak(language, country, preferredNames, text) {
var resolvePromise;
var promise = new Promise(r => resolvePromise = r);
var voices = window.speechSynthesis.getVoices();
if (voices.length == 0) {
new Promise(r => {
window.speechSynthesis.onvoiceschanged = () => {
window.speechSynthesis.onvoiceschanged = null;
r();
};
})
.then(() => speak(language, country, preferredNames, text))
.then(resolvePromise);
} else {
var msg = new SpeechSynthesisUtterance(text);
voices.sort((a, b) => {
if (language != null) {
var matchA = a.lang.indexOf(language + "-") == 0;
var matchB = b.lang.indexOf(language + "-") == 0;
if (! matchA && ! matchB) return 0;
if (! matchA && matchB) return 1;
if (! matchB && matchA) return -1;
}
if (country != null) {
var matchA = a.lang.indexOf("-" + country) == a.lang.length - ("-" + country).length;
var matchB = b.lang.indexOf("-" + country) == b.lang.length - ("-" + country).length;
if (! matchA && ! matchB) return 0;
if (! matchA && matchB) return 1;
if (! matchB && matchA) return -1;
}
if (preferredNames != null) {
var indexA = voices.length;
var indexB = voices.length;
preferredNames.forEach((e, i) => {
if (indexA == voices.length && a.name.match(e) != null) indexA = i;
if (indexB == voices.length && b.name.match(e) != null) indexB = i;
});
return indexA - indexB;
}
return 0;
});
if (voices.length > 0) msg.voice = voices[0];
if (language != null) {
msg.lang = language;
if (country != null) msg.lang += "-" + country;
}
msg.onend = resolvePromise;
window.speechSynthesis.speak(msg);
// msg.onend not triggered without call to console.log(msg)?
console.log(msg);
}
return promise;
}
speak("en", null, [ /Google US English/, /Samantha/, /Fiona/, /Victoria/, /female/i ], "Hello, world.")
.then(() => speak("en", null, [ /female/i ], "Hello, world."))
.then(() => speak("en", "US", [ /female/i ], "Hello, world."))
.then(() => speak("en", "US", null, "Hello, world."))
.then(() => speak("en", "GB", [ /\Wmale/i ], "Hello, world."));
</script>
</head>
<body>
</body>
</html>
This code worked for me.
var speakObj = new SpeechSynthesisUtterance();
speakObj.text = text;
speakObj.voice = speechSynthesis.getVoices().filter(function(voice) {
return voice.name == "Google UK English Female"
})[0];
window.speechSynthesis.speak(speakObj);
After a long time of troubleshooting, I could figure out the solution.
4 persons already suggested me some solutions. But these did not work for me. But helped me to figure out the solution. Thanks to all of them.
To solve the problem, I did two things.
I had to load voices during onvoiceschanged event as follows:
var voices;
window.speechSynthesis.onvoiceschanged = function() {
voices=window.speechSynthesis.getVoices();
};
I found this tip from this link.
'Google UK English Female' does not work for me. So I used 'Microsoft Zira Desktop - English (United States)' as follows:
speech.voice = voices.filter(function(voice) { return voice.name == 'Microsoft Zira Desktop - English (United States)'; })[0];

how to turn off sliding responsive menu in wordpress responsive select menu plugin?

I am using WP Responsive Select Menu plugin in wordpress and I have responsive menu while watching the website in the mobile devices.
In my IOS based phone, the responsive menu opens automatically when I scroll the screen to left (and sometimes also when I scroll down).
My .js file is as follows:
`
// Start Code
jQuery(document).ready(function( $ ) {
var bar = $('#wpresmenu_bar'), //top bar that shows/hides the menu
bar_height = bar.outerHeight(true), //the bar height
from_width = wpresmenu.from_width,
menu = $('#wpresmenu_menu'), //the menu div
menu_ul = $('#wpresmenu_menu_ul'), //the menu ul
menu_a = menu.find('a'), //single menu link
body = $('body'),
html = $('html'),
animation_speed = 300,
ab = $('#wpadminbar'),
menu_enabled = (bar.length > 0 && menu.length > 0)? true : false,
menu_width = menu.width(),
target_height = (window.innerHeight < body.height())? body.height() : window.innerHeight,
target_width = (window.innerWidth < body.width())? body.width() : window.innerWidth;
if(menu_enabled) {
menu_ul.find('li').first().css({'border-top':'none'});
$(document).mouseup(function (e) {
if ( !menu.is(e.target) && menu.has( e.target ).length === 0) {
if(menu.is(':visible') && (!menu.hasClass('top'))) {
$.sidr('close', 'wpresmenu_menu');
}
}
});
//ENABLE NESTING
//add arrow element to the parent li items and chide its child uls
menu.find('ul.sub-menu').each(function() {
var sub_ul = $(this),
parent_a = sub_ul.prev('a'),
parent_li = parent_a.parent('li').first();
parent_a.addClass('wpresmenu_parent_item');
parent_li.addClass('wpresmenu_parent_item_li');
var expand = parent_a.before('<span class="wpresmenu_icon wpresmenu_icon_par icon_default"></span> ').find('.wpresmenu_icon_par');
sub_ul.hide();
});
//adjust the a width on parent uls so it fits nicely with th eicon elemnt
function adjust_expandable_items() {
$('.wpresmenu_parent_item_li').each(function() {
var t = $(this),
main_ul_width = 0,
icon = t.find('.wpresmenu_icon_par').first(),
link = t.find('a.wpresmenu_parent_item').first();
if(menu.hasClass('top')) {
main_ul_width = window.innerWidth;
} else {
main_ul_width = menu_ul.innerWidth();
}
if(t.find('.wpresmenu_clear').length == 0) link.after('<br class="wpresmenu_clear"/>');
});
}
adjust_expandable_items();
//expand / collapse action (SUBLEVELS)
$('.wpresmenu_icon_par').on('click',function() {
var t = $(this),
//child_ul = t.next('a').next('ul');
child_ul = t.parent('li').find('ul.sub-menu').first();
child_ul.slideToggle(300);
t.toggleClass('wpresmenu_par_opened');
t.parent('li').first().toggleClass('wpresmenu_no_border_bottom');
});
//helper - close all submenus when menu is hiding
function close_sub_uls() {
menu.find('ul.sub-menu').each(function() {
var ul = $(this),
icon = ul.parent('li').find('.wpresmenu_icon_par'),
li = ul.parent('li');
if(ul.is(':visible')) ul.slideUp(300);
icon.removeClass('wpresmenu_par_opened');
li.removeClass('wpresmenu_no_border_bottom');
});
}
//fix the scaling issue by adding/replacing viewport metatag
var mt = $('meta[name=viewport]');
mt = mt.length ? mt : $('<meta name="viewport" />').appendTo('head');
if(wpresmenu.zooming == 'no') {
mt.attr('content', 'user-scalable=no, width=device-width, maximum-scale=1, minimum-scale=1');
} else {
mt.attr('content', 'user-scalable=yes, width=device-width, initial-scale=1.0, minimum-scale=1');
}
//Additional fixes on change device orientation
if( $.browser.mozilla ) {
screen.addEventListener("orientationchange", function() {updateOrientation()}); //firefox
} else if( window.addEventListener ) {
window.addEventListener('orientationchange', updateOrientation, false);
}
else {
window.attachEvent( "orientationchange" );
}
function updateOrientation() {
window.scrollBy(1,1);
window.scrollBy(-1,-1);
menu_width = menu.width();
//update the page posion for left menu
if(menu.is(':visible') && menu.hasClass('left')) {
body.css({'left':menu_width});
body.scrollLeft(0);
}
}
//apply the SIDR for the left/right menu
if(menu.hasClass('left') || menu.hasClass('right')) {
//appy sidr
var hor_pos = (menu.hasClass('left'))? 'left' : 'right';
bar.sidr({
name:'wpresmenu_menu',
side: hor_pos,
speed: animation_speed,
onOpen: function(){ bar.addClass('menu_is_opened'); },
onClose: function(){ bar.removeClass('menu_is_opened'); close_sub_uls(); }
});
//when link is clicked - hide the menu first and then change location to new page
menu_a.on('click', function(e) {
$.sidr('close', 'wpresmenu_menu');
});
if( wpresmenu.swipe != 'no' ) {
$('body').touchwipe({
wipeLeft: function() {
// Close
$.sidr('close', 'wpresmenu_menu');
},
wipeRight: function() {
// Open
$.sidr('open', 'wpresmenu_menu');
},
min_move_x: 60,
min_move_y: 60,
preventDefaultEvents: false
});
}
$(window).resize(function(){
target_width = (window.innerWidth < body.width())? body.width() : window.innerWidth;
if(target_width > from_width && menu.is(':visible')) {
$.sidr('close', 'wpresmenu_menu');
}
});
} else if(menu.hasClass('top')) { //The top positioned menu
body.prepend(menu);
//show / hide the menu
bar.on('click', function(e) {
//scroll window top
$("html, body").animate({ scrollTop: 0 }, animation_speed);
close_sub_uls();
menu.stop(true, false).slideToggle(animation_speed);
});
//when link is clicked - hide the menu first and then change location to new page
menu_a.on('click', function(e) {
e.preventDefault();
var url = $(this).attr('href');
menu.slideUp(animation_speed,function() {
//go to the url from the link
window.location.href = url;
});
});
$(window).resize(function(){
target_width = (window.innerWidth < body.width())? body.width() : window.innerWidth;
if(target_width > from_width && menu.is(':visible')) {
close_sub_uls();
menu.slideUp(animation_speed, function() {});
}
});
} //end if class left / top /right
} //end if menu enabled
}); `
I don't want the menu to load on sliding the screen to left or right. Any idea how to do that??
I have figured it out.
Commenting out the following code stops it.
if( wpresmenu.swipe != 'no' ) {
$('body').touchwipe({
wipeLeft: function() {
// Close
$.sidr('close', 'wpresmenu_menu');
},
wipeRight: function() {
// Open
$.sidr('open', 'wpresmenu_menu');
},
min_move_x: 60,
min_move_y: 60,
preventDefaultEvents: false
});
}
:)

How to customize rows or columns color in Kendo.Scheduler?

Is there a way to customize kendo.Scheduler rows and columns color? If there is, let me know how!
UPDATE 1>
This is the answer>
view.table.find("td[role='gridcell']").each(function () {
if ($(this) != null) {
var element = $(this);
if (element != null) {
var slot = scheduler.slotByElement(element);
if (slot != null) {
var dateSlot = slot.startDate;
if ("20/09/2014 14:00"== dateSlot.toString())
element.addClass("red");
}
}
}
});
You have to add the following css too:
.k-scheduler .k-today.red {
background: #ff6f7b; /*When the slot is today*/
}
.red {
background: #ff6f7b;
}
.k-scheduler .k-state-selected.red { /*The color when you select the slot*/
background: #4070B8;
}
function scheduler_dataBound(e) {
var scheduler = $("#scheduler").data("kendoScheduler");
var view = scheduler.view();
view.table.find("td[role=gridcell]").each(function () {
if ($(this) != null) {
var element = $(this);
if (element != null) {
var slot = scheduler.slotByElement(element);
if (slot != null)
if (slot.startDate, slot.endDate, == "youre times")
element.addClass("youre css clas name ");
}
}
});

Opening tabs in Chrome news reader extension

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

Resources