I've found this great extension which does exactly what I want in terms of functionality e.g it switches the hidden input fields and makes them visible.
The only thing I've been trying to figure out is how to make it so it will work as an extension icon button and not as a shortcut key combination?.
Extension:
https://chrome.google.com/webstore/detail/hidden-field-switcher/gfkfklknjmlpldiggcjgdgkonoicfngp
Thanks
My Current Setup:
I've been able to add the button but on click it doesn't do anything:
Manifest.json
{
"name": "Display Hidden",
"version": "1.0",
"manifest_version": 2,
"description": "Display hidden",
"background": {"page": "background.html", "persistent": false},
"browser_action": {"default_icon": "icon.png"},
"content_scripts":[{"js": ["background.js"], "matches": ["https://*/*"]}],
"permissions": ["tabs", "http://*/*"]
}
background.html
<html>
<head>
<script src="background.js">
chrome.browserAction.onClicked.addListener(function(tab) {alert('icon clicked')});
</script>
</head>
</html>
background.js Source
var allFields = new Array();
var visible = false;
function switchHidden() {
if(visible == true){
hideHidden();
visible = false;
}
else {
showHidden();
visible = true;
}
}
function showHidden() {
var allHidden = document.getElementsByTagName("input");
for (var Key in allHidden) {
if(allHidden[Key].type == "hidden") {
allFields.push(allHidden[Key]);
allHidden[Key].type = "text";
/*for (var SettingsKey in Settings) {
var subSection = SettingsKey.substring(7,0);
var subKey = SettingsKey.substring(7);
if(subSection == "styles_") {
allHidden[Key].style.setProperty(subKey,Settings[SettingsKey]);
}
}*/
if(allHidden[Key].name)
allHidden[Key].title = allHidden[Key].name;
if(!allHidden[Key].name && allHidden[Key].id)
allHidden[Key].title = allHidden[Key].id;
allHidden[Key].style.setProperty("background-color","#CCFFFF");
}
}
}
function hideHidden() {
for (var Key in allFields) {
allFields[Key].type = "hidden";
}
allFields = new Array();
}
Related
I'm just trying to get started with the sample addon Google describes here for extending the compose UI:
https://developers.google.com/gsuite/add-ons/gmail/extending-compose-ui
However when I run it I'm getting this error:
Error with the add-on. Run time error. Cannot return a card markup
from the callback function of a universal action.
I have not setup any universal actions in my manifest file:
{
"timeZone": "America/New_York",
"oauthScopes":[
"https://www.googleapis.com/auth/script.send_mail",
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/gmail.addons.execute",
"https://www.googleapis.com/auth/gmail.addons.current.message.metadata",
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.addons.current.action.compose"
],
"gmail":{
"name": "My Mail Merge",
"logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/label_googblue_24dp.png",
"composeTrigger": {
"draftAccess": "METADATA",
"selectActions": [
{
"text": "show UI",
"runFunction": "buildImageComposeCard"
}
]
},
"openLinkUrlPrefixes": [
"https://mail.google.com/"
],
"primaryColor": "#42585F4",
"secondaryColor": "#42585F4"
},
"exceptionLogging": "STACKDRIVER"
}
Below is Code.gs:
function getInsertImageComposeUI(e) {
return [buildImageComposeCard()];
}
function buildImageComposeCard() {
// Get a list of image URLs to display in the UI.
// This function is not shown in this example.
var imageUrls = [
"https://mail.google.com/1",
"https://mail.google.com/2",
"https://mail.google.com/3"
];
var card = CardService.newCardBuilder();
var cardSection = CardService.newCardSection().setHeader('My Images');
for (var i = 0; i < imageUrls.length; i++) {
var imageUrl = imageUrls[i];
cardSection.addWidget(
CardService.newImage()
.setImageUrl(imageUrl)
.setOnClickAction(CardService.newAction()
.setFunctionName('applyInsertImageAction')
.setParameters({'url' : imageUrl})));
}
return card.addSection(cardSection).build();
}
function applyInsertImageAction(e) {
var imageUrl = e.parameters.url;
var imageHtmlContent = '<img style=\"display: block\" src=\"'
+ imageUrl + '\"/>';
var response = CardService.newUpdateDraftActionResponseBuilder()
.setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction()
.addUpdateContent(
imageHtmlContent,
CardService.ContentType.HTML)
.setUpdateType(
CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
.build();
return response;
}
In the manifest file, runFunction has to be set to "getInsertImageComposeUI",
Also, in the code file, CardService.ContentType.HTML has to be one of
CardService.ContentType.MUTABLE_HTML
or
CardService.ContentType.IMMUTABLE_HTML
I have the same error message and couldn't get that example to work. However, I created a simpler Hello-World example that actually works. I think it is more useful for newbies to start with. Don't forget to set the runFunction in the manifest to getComposeCard.
function getComposeCard(e) { return [buildComposeCard()]; }
function buildComposeCard() {
var card = CardService.newCardBuilder();
var cardSection = CardService.newCardSection().setHeader('Test Header');
testVar = ['item1', 'item2'];
for (var i = 0; i < testVar.length; i++) {
var item = testVar[i];
cardSection.addWidget(
CardService.newTextParagraph().setText(item));
}
return card.addSection(cardSection).build();
}
Probably it's way too late, but the problem can be fixed by simply wrap the result of buildImageComposeCard as array
return [card.addSection(cardSection).build()]
I want to write a chrome extension where it is possible to mark features on a website and save it in a table, for this, I want to use the Chrome web inspector.
Unfortunately, I am new to this area (chrome plugins) and therefore I am looking for help (links, tutorials, related work etc.) to use the web inspector in my own extension.
Simple example on this website https://ieeexplore.ieee.org/document/1005630.
My idea is to mark for example the date of publication, and the plugin write the complete div to a table.
actually, I found a simple solution.
Sample
http://g.recordit.co/5CCFjXpe8J.gif
It's only a small part of my tool to keep it simple.
The main idea comes from Google Chrome Extension: highlight the div that the mouse is hovering over
'iframe' is the injected sidebar
marker.js contains the script to mark divs
manifest.json
{
"name": "Feature extractor",
"version": "1.0",
"description": "Feature extractor from website",
"permissions": ["activeTab", "declarativeContent", "storage", "contextMenus", "<all_urls>", "tabs"],
"browser_action": {},
"web_accessible_resources": ["iframe.html","iframe.js"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"css": [
"marker.css"
],
"js": [
"js/jquery-1.8.3.min.js",
"marker.js"
]
}
],
"manifest_version": 2
}
background.js
'use strict';
chrome.runtime.onInstalled.addListener(function() {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
pageUrl: {hostEquals: 'developer.chrome.com'},
})],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
});
// sidebar
chrome.browserAction.onClicked.addListener(function(){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id,"toggle");
})
});
// message passing
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
console.log(request);
callback({'request':request});
});
// context menu
var labels = ['author','date','abstract']
for(var label in labels) {
console.log(labels[label])
chrome.contextMenus.create({id: labels[label], "title": labels[label], "contexts":['all']});
}
chrome.contextMenus.onClicked.addListener(function(info, tab) {
if (info.menuItemId == labels[0]) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id,labels[0]);
})
}
});
iframe.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/jquery.mobile-1.2.1.min.css" />
<script src="js/jquery-1.8.3.min.js"></script>
<script src="js/jquery.mobile-1.2.1.min.js"></script>
<script src="iframe.js"></script>
</head>
<body>
<button id="send">
send
</button>
<div id="responses">
</div>
</body>
</html>
I need the jQuery.fn.. script to identify the selected div Get unique selector of element in Jquery
iframe.js
// unique selector
jQuery.fn.extend({
getPath: function () {
var path, node = this;
while (node.length) {
var realNode = node[0], name = realNode.localName;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var sameTagSiblings = parent.children(name);
if (sameTagSiblings.length > 1) {
var allSiblings = parent.children();
var index = allSiblings.index(realNode) + 1;
if (index > 1) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
}
});
window.addEventListener('DOMContentLoaded', function () {
var callback = function (data) {
$("#responses").append("<div>" + data + "</div>");
};
var send = function () {
chrome.runtime.sendMessage(Date(), callback);
}
chrome.runtime.onMessage.addListener(function(msg, data){
if (msg.command == "append-author") {
$("#responses").append("<div>" + msg.el + "</div>")
}
})
document.getElementById('send').addEventListener('click', send);
});
Google Chrome Extension: highlight the div that the mouse is hovering over
marker.js
// Unique ID for the className.
var MOUSE_VISITED_CLASSNAME = 'crx_mouse_visited';
var MOUSE_MARKED_CLASSNAME = 'crx_mouse_marked';
// Previous dom, that we want to track, so we can remove the previous styling.
var prevDOM = null;
// Mouse listener for any move event on the current document.
document.addEventListener('mousemove', function (e) {
let srcElement = e.srcElement;
// Lets check if our underlying element is a IMG.
if (prevDOM != srcElement && srcElement.nodeName == 'DIV' ) {
// For NPE checking, we check safely. We need to remove the class name
// Since we will be styling the new one after.
if (prevDOM != null) {
prevDOM.classList.remove(MOUSE_VISITED_CLASSNAME);
}
// Add a visited class name to the element. So we can style it.
srcElement.classList.add(MOUSE_VISITED_CLASSNAME);
// The current element is now the previous. So we can remove the class
// during the next ieration.
prevDOM = srcElement;
// console.info(srcElement.currentSrc);
// console.dir(srcElement);
}
}, false);
var iframe = document.createElement('iframe');
iframe.style.background = "green";
iframe.id = "comm-test-container";
iframe.style.height = "100%";
iframe.style.width = "0px";
iframe.style.position = "fixed";
iframe.style.top = "0px";
iframe.style.right = "0px";
iframe.style.zIndex = "9000000000000000000";
iframe.frameBorder = "none";
iframe.src = chrome.extension.getURL("iframe.html")
document.body.appendChild(iframe);
function toggle(){
if(iframe.style.width == "0px") {
iframe.style.width="400px";
} else {
iframe.style.width="0px";
}
}
chrome.runtime.onMessage.addListener(function(msg, sender){
if(msg == "toggle"){
toggle();
}
if(msg == "author") {
prevDOM.classList.add(MOUSE_MARKED_CLASSNAME);
chrome.runtime.sendMessage({command:"append-author",el:prevDOM.innerHTML,selector:$(prevDOM).getPath()}, function(response) {});
}
})
// find unique selector
jQuery.fn.extend({
getPath: function () {
var path, node = this;
while (node.length) {
var realNode = node[0], name = realNode.localName;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var sameTagSiblings = parent.children(name);
if (sameTagSiblings.length > 1) {
var allSiblings = parent.children();
var index = allSiblings.index(realNode) + 1;
if (index > 1) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
}
});
marker.css
.crx_mouse_visited {
background-clip: #bcd5eb!important;
outline: 1px dashed #e9af6e!important;
z-index : 0!important;
}
.crx_mouse_marked {
background-clip: #bcd5eb!important;
outline: 5px solid #e9af6e!important;
z-index : 0!important;
}
I am building chrome application for POS Terminal printers. The problem that I have is that chrome application for some reason can't find USB device and I am not sure why it is not working. I tried few methods (converted hexadecimal vendor/product ID to decimal, used hexadecimal product/vendor id to connect to USB printer) and all of the reports that device can't be found...
EDIT:
I got this error from device log:
Failed to open device: Operation not supported or unimplemented on this platform
Does someone know where is the problem?
Here is details about printer (DATECS DPP 255):
Manifest:
{
"manifest_version": 2,
"name": "Thermal Printer Extension",
"description": "Thermal Printer Extension for ESC/POS Commands",
"version": "1.0",
"app": {
"background": {
"scripts": ["main.js"]
}
},
"permissions": ["usb", "notifications"],
"optional_permissions": [
{
"usbDevices": [
{
"vendorId": 65520, "productId": 98
}
]
}
],
"externally_connectable": {
"matches": ["http://localhost:3000/*"]
}
}
main.js
chrome.runtime.onMessageExternal.addListener(function (stuff) {
if(stuff){
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
var port = 0;
var endpoint = 0x01;
// needs to be set in optional permissions for each VID/PID pair
var device = {vendorId: 0xfff0, productId: 0x0062};
// var device = {vendorId: 65520, productId: 98};
String.prototype.toBytes = function() {
var arr = [];
for (var i=0; i < this.length; i++) {
arr.push(this[i].charCodeAt(0));
}
return arr;
}
// setting variables for printing, array for data, and calculations
var alignLeft = [0x01B, 0x061, 0];
var alignCenter = [0x01B, 0x061, 1];
var alignRight = [0x01B, 0x061, 2];
var endPrint = [0x01B, 0x064, 2];
// enter new line
var lineFeed = [0x00A];
var buzz = [07];
var drawLineMiddle = "________________________________________________".toBytes();
var drawLineSmall = "________________________________".toBytes();
var horizontalTab = [0x009];
var cutpaperFull = [0x01D, 0x056, 1];
var cutpaperPartial = [0x01D, 0x056, 0];
function createAnything() {
var anything = alignCenter;
anything = anything.concat("Awesome Chrome Extension".toBytes());
anything = anything.concat(lineFeed);
anything = anything.concat(drawLineMiddle);
anything = anything.concat(stuff.stuffToPrint.toBytes());
anything = anything.concat(lineFeed);
return anything;
}
function createReceipt(devices) {
var data = [];
data = data.concat(createAnything());
data = data.concat(endPrint);
data = data.concat(cutpaperPartial);
var buffer = new Uint8Array(data).buffer;
var transferinfo = {direction: "out", endpoint: endpoint, data: buffer };
chrome.usb.bulkTransfer({handle: devices[0].handle, vendorId: devices[0].vendorId, productId: devices[0].productId}, transferinfo, function(response) {
if (response.resultCode == 0) {
chrome.usb.closeDevice({handle: devices[0].handle, vendorId: devices[0].vendorId, productId: devices[0].productId}, chrome.notifications.create("4", {type: "basic", iconUrl: "icon.png", title: "Success!", message: "Printing receipt..."}, function() {console.log("Success!")}));
} else {
console.log("Error ", response);
}
});
}
var connect = function(callback) {
chrome.permissions.getAll(function(p) {
if (p.permissions.indexOf("usb") >= 0) {
//construct permission object for our device
var obj = { usbDevices: [device] };
//now request the permissions
chrome.permissions.request({ permissions: [obj] }, function(granted) {
if (granted) {
chrome.usb.findDevices(device, function(devices) {
if (devices && devices.length > 0) {
//use the first found device
var foundDevice = devices[0];
//now lets reset the device
chrome.usb.resetDevice(foundDevice, function() {
//perform some error checking to make sure we reset the device
if ( ! chrome.runtime.lastError) {
//now claim the interface using the port we specified
chrome.usb.claimInterface(foundDevice, port, function() {
if ( ! chrome.runtime.lastError) {
callback(devices);
} else {
throw chrome.runtime.lastError.message;
}
});
} else {
throw chrome.runtime.lastError.message;
}
});
} else {
chrome.notifications.create("1", {type: "basic", iconUrl: "icon.png", title: "Error", message: "Device not found!"}, function() {console.warn("Device not found!")});
console.warn("Device not found!");
}
});
} else {
chrome.notifications.create("2", {type: "basic", iconUrl: "icon.png", title: "Error", message: "USB Permission not granted."}, function() {console.warn("USB Permission not granted.")});
console.warn("USB Permission not granted.");
}
});
} else {
chrome.notifications.create("3", {type: "basic", iconUrl: "icon.png", title: "Error", message: "No USB permissions granted."}, function() {console.warn("No USB permissions granted.")});
console.warn("No USB permissions granted.");
}
});
}
connect(createReceipt);
}
});
I currently have a huge JSON file (over 15k lines, size might increase) with which I want to construct a bootstrap-treeview. Adding all the nodes would make loading of page really slow, so I plan to create a service to fetch JSON of selected nodes and populate the treeview accordingly. This is what I have right now.
<!DOCTYPE html>
<html>
<head>
<title>Bootstrap Tree View</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="./TreeView_files/bootstrap-treeview.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Bootstrap Tree View - DOM Tree</h1>
<br/>
<div class="row">
<div class="col-sm-12">
<label for="treeview"></label>
<div id="treeview"/>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="./TreeView_files/bootstrap-treeview.js"></script>
<script type="text/javascript">
function buildDomTree() {
var tree = [
{
text: "Parent 1",
nodes: [
{
text: "Child 1",
nodes: [
{
text: "Grandchild 1"
},
{
text: "Grandchild 2"
}
]
},
{
text: "Child 2"
}
]
},
{
text: "Parent 2"
},
{
text: "Parent 3"
},
{
text: "Parent 4"
},
{
text: "Parent 5"
}
];
return tree;
}
$(function() {
var options = {
bootstrap2: false,
showTags: true,
levels: 5,
data: buildDomTree()
};
$('#treeview').treeview(options);
});
</script>
</body>
Treeview can go 4 levels deep, and I want to fetch next level JSON each time a node is clicked. So, if I click on "Parent 5", it should pop out sub nodes.
I have no clue how to add nodes dynamically. Any help would be really appreciated.
Answer on request: I have found a way to do it, although, it is a tad inefficient. What I've done is, I keep a state of all expanded nodes, and when I click on a node to expand it, I make an HTTP request, add the new nodes to the old one, redraw the entire tree and re-expand all the previously expanded nodes. I know this is inefficient, but it is the only way I could find without going into the nitty-gritty and essentially recreating the entire tree myself (which is just a glorified recursion application).
Here's the code I ran with when I posted the question. There is obviously room for improvement.
var expandedNodes = [];
var tree = [];
$(function()
{
$.post("http://localhost:8000/getLevel1", function( data )
{
var JSObject = JSON.parse(data);
for (j in JSObject)
tree.push(JSObject[j]);
createTree();
});
});
function createTree(){
var options = {
bootstrap2: false,
showTags: true,
levels: 0,
data: tree,
expandIcon: 'fa fa-chevron-right',
collapseIcon: 'fa fa-chevron-down',
onNodeExpanded: nodeExpand,
onNodeCollapsed: nodeCollapse,
onNodeSelected: nodeSelect,
onNodeUnselected: nodeUnselect
}
$('#treeview').treeview(options);
for (node in expandedNodes)
$('#treeview').treeview('expandNode', [ expandedNodes[node], { levels: 0, silent: true } ]);
$('#treeview').treeview('expandNode', 0, { silent: true } );
};
function nodeExpand(event, data)
{
expandedNodes.push(data.nodeId);
var requestObject = []
requestObject.push(data.text);
var parent, dummy = data;
while ((parent = $('#treeview').treeview('getParent', dummy.nodeId))["nodeId"] != undefined)
{
requestObject.push(parent.text);
dummy = parent;
}
$.post("http://localhost:8000/getNode?param=" + JSON.stringify(requestObject), function(retVal)
{
var JSObject = JSON.parse(retVal);
var node = findNode(requestObject);
node.nodes = JSObject;
createTree();
});
}
function nodeCollapse(event, data)
{
var index = expandedNodes.indexOf(data.nodeId);
if (index > -1)
expandedNodes.splice(index, 1);
}
function nodeSelect(event, data)
{
if (data.state.expanded == true)
$('#treeview').treeview('collapseNode', data.nodeId);
else
$('#treeview').treeview('expandNode', data.nodeId);
//$('#treeview').treeview('unselectNode', [ data.nodeId, { silent: true } ]);
}
function nodeUnselect(event, data)
{
}
function findNode(array)
{
var searchIn = tree; //array
var lastFound = tree;
for (var i = array.length - 1; i >= 0; i--)
{
var obj = searchInObject(searchIn, array[i]);
searchIn = obj.nodes;
lastFound = obj;
}
return lastFound;
}
function searchInObject(objectArray, string)
{
for (var index in objectArray)
if (objectArray[index].text == string)
return objectArray[index];
}
$(document).ready(function () {
var trigger = $('.hamburger'),
overlay = $('.overlay'),
isClosed = false;
hamburger_cross();
$('#wrapper').toggleClass('toggled');
trigger.click(function () {
hamburger_cross();
});
function hamburger_cross() {
if (isClosed == true) {
overlay.hide();
trigger.removeClass('is-open');
trigger.addClass('is-closed');
isClosed = false;
$('#open_arrow').removeClass('fa-chevron-circle-left').addClass('fa-chevron-circle-right');
} else {
overlay.show();
trigger.removeClass('is-closed');
trigger.addClass('is-open');
isClosed = true;
$('#open_arrow').removeClass('fa-chevron-circle-right').addClass('fa-chevron-circle-left');
}
}
$('[data-toggle="offcanvas"]').click(function () {
$('#wrapper').toggleClass('toggled');
});
});
Point of interest would be nodeExpand and createTree methods.
Using MenuBar template and have menu working. However, say you hover over a top level menu items like videos. The Video page automatically loads within the presentation area. BUT when you go to select a video it begins to autoplay before a user click thus inhibiting users from selecting other videos but the first video. I simply want the videos not to autoplay and await an input from the user. I tried an eventListener but it was ignored. I am at a loss of what to do.
Presenter.js
var Presenter = {
defaultPresenter: function(xml) {
if(this.loadingIndicatorVisible) {
navigationDocument.replaceDocument(xml, this.loadingIndicator);
this.loadingIndicatorVisible = false;
} else {
navigationDocument.pushDocument(xml);
}
},
modalDialogPresenter: function(xml) {
navigationDocument.presentModal(xml);
},
menuBarItemPresenter: function(xml, ele) {
var feature = ele.parentNode.getFeature("MenuBarDocument");
if (feature) {
var currentDoc = feature.getDocument(ele);
if (!currentDoc) {
feature.setDocument(xml, ele);
}
}
},
load: function(event) {
console.log(event);
var self = this,
ele = event.target,
templateURL = ele.getAttribute("template"),
presentation = ele.getAttribute("presentation");
videoURL = ele.getAttribute("videoURL");
if(videoURL) {
var player = new Player();
var playlist = new Playlist();
var mediaItem = new MediaItem("video", videoURL);
player.playlist = playlist;
player.playlist.push(mediaItem);
player.present();
}
if (templateURL) {
self.showLoadingIndicator(presentation);
resourceLoader.loadResource(templateURL,
function(resource) {
if (resource) {
var doc = self.makeDocument(resource);
doc.addEventListener("select", self.load.bind(self));
doc.addEventListener("highlight", self.load.bind(self));
if (self[presentation] instanceof Function) {
self[presentation].call(self, doc, ele);
} else {
self.defaultPresenter.call(self, doc);
}
}
}
);
}
},
makeDocument: function(resource) {
if (!Presenter.parser) {
Presenter.parser = new DOMParser();
}
var doc = Presenter.parser.parseFromString(resource, "application/xml");
return doc;
},
showLoadingIndicator: function(presentation) {
if (!this.loadingIndicator) {
this.loadingIndicator = this.makeDocument(this.loadingTemplate);
}
if (!this.loadingIndicatorVisible && presentation != "modalDialogPresenter" && presentation != "menuBarItemPresenter") {
navigationDocument.pushDocument(this.loadingIndicator);
this.loadingIndicatorVisible = true;
}
},
removeLoadingIndicator: function() {
if (this.loadingIndicatorVisible) {
navigationDocument.removeDocument(this.loadingIndicator);
this.loadingIndicatorVisible = false;
}
},
loadingTemplate: `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<loadingTemplate>
<activityIndicator>
<text>Loading...</text>
</activityIndicator>
</loadingTemplate>
</document>`
}
--- application.js ---
var resourceLoader;
App.onLaunch = function(options) {
var javascriptFiles = [
`${options.BASEURL}js/ResourceLoader.js`,
`${options.BASEURL}js/Presenter.js`
];
evaluateScripts(javascriptFiles, function(success) {
if (success) {
resourceLoader = new ResourceLoader(options.BASEURL);
var index = resourceLoader.loadResource(`${options.BASEURL}templates/CalvaryTVMenuBar.xml.js`,
function(resource) {
var doc = Presenter.makeDocument(resource);
doc.addEventListener("select", Presenter.load.bind(Presenter));
navigationDocument.pushDocument(doc);
});
} else {
var alert = createAlert("Evaluate Scripts Error", "There was an error attempting to evaluate the external JavaScript files.\n\n Please check your network connection and try again later.");
navigationDocument.presentModal(alert);
throw ("Playback Example: unable to evaluate scripts.");
}
});
}
var createAlert = function(title, description) {
var alertString = `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<alertTemplate>
<title>${title}</title>
<description>${description}</description>
</alertTemplate>
</document>`
var parser = new DOMParser();
var alertDoc = parser.parseFromString(alertString, "application/xml");
return alertDoc
}
Hi Josh,
Try removing the highlight event that you are attaching while loading the document using resourceLoader.loadResource method.
It seems, you are attaching both the events
doc.addEventListener("select", self.load.bind(self));
doc.addEventListener("highlight", self.load.bind(self));
Try removing the second one.