Drawing a user interface based on preferences - javascript

I want to use the built-in preference system for my xulrunner (Firefox) application. But I can't figure out how to easily drive the user interface based on preferences.
The user can specify a list of home pages, and each home page will show up in a different tab. Because the tabs are in the presentation layer, I'd like to create them using a template in the xul code. Is this possible?
I haven't seen a way to do this with xul templates. Is there an alternative templating system that would allow me to change the UI based on user preferences?

No, templating in XUL is not powerful enough, so you're stuck with writing JavaScript code that reads the preferences and opens the needed tabs.

XML.prototype.function::domNode = function domNode() {
function addPrefix(prefix, name) {
if (typeof(prefix) == "undefined" || prefix == null || prefix == "") {
return name;
} else {
return prefix + ":" + name;
}
}
function recurse(xml) {
var domNode = document.createElementNS(xml.namespace().uri, addPrefix(xml.namespace().prefix, xml.localName()));
for each (let attr in xml.#*::*) {
let attrNode = document.createAttributeNS(attr.namespace().uri, addPrefix(attr.namespace().prefix, attr.localName()));
attrNode.nodeValue = attr;
domNode.setAttributeNode(attrNode);
}
if (xml.hasComplexContent()) {
for each (let node in xml.*) {
domNode.appendChild(recurse(node));
}
} else if (xml.hasSimpleContent()) {
domNode.appendChild(document.createTextNode(xml));
}
return domNode;
}
return recurse(this);
};
var name = "example"
var xml = {name};
document.querySelector("#example-statusbar-panel").appendChild(xml.domNode());
works as a charm, there's some minor glitches with namespaces though.
You could always convert dom back to XML with
var str = serializer.serializeToString( xml.domNode() );

Related

ANTLR4 Javascript get tree

Currently I am busy with parsers and tried ANTLR. I understand the grammar so far and now I wanted to implement it in javascript.
Here is a small but important snippet of my code.
if (selected == "Funktionen") {
console.log("You selected functions")
const chars = new antlr4.InputStream(data.stringToLex);
const lexer = new FunktionLexer(chars);
const tokens = new antlr4.CommonTokenStream(lexer);
const parser = new FunktionParser(tokens);
parser.buildParseTrees = true;
const tree = parser.start();
tree.accept(new Visitor());
}
My visitor looks like this
class Visitor {
visitChildren(ctx) {
if (!ctx) {
return;
}
if (ctx.children) {
return ctx.children.map(child => {
if (child.children && child.children.length != 0) {
return child.accept(this);
} else {
return child.getText();
}
});
}
}
}
I have oriented myself to this tutorial and everything works.
https://github.com/antlr/antlr4/blob/master/doc/javascript-target.md
http://lab.antlr.org/ Just hit on start and u will see what I mean.
The object of my tree I get back from my start() function with a right input looks like this:
The big problem is, I want to get the Tree and output it (at least in console log), like on the official ANTLR lab website.
The big problem is, I want to get the Tree and output it
The object returned by parser.start() is the tree of your parsed input. You don't need a visitor for this.
What you mean by "and output it", I do not know. Just print it to your console? That can be done by doing:
const tree = parser.start();
console.log(tree.toStringTree(parser));
// or if the line above doesn't work, try:
// console.log(tree.toStringTree());

D365 Error when calling function from another JS

I am having an issue calling JS function from another JS file.
Main JS where the function is defined.
var Common = Common || {};
Common.BaseAction = Common.BaseAction || {};
Common.BaseAction.SetNotification = function (message, level, uniqueId)
{
Xrm.Page.ui.setFormNotification(message, level, uniqueId);
}
Common.BaseAction.clearNotification = function (uniqueId) {
Xrm.Page.ui.clearFormNotification(uniqueId);
}
JS from where I am calling the function
var apItem = apItem || {};
apItem.BaseForm = apItem.BaseForm || {};
apItem.BaseForm.SetName = function ()
{
var bookName = Xrm.Page.getAttribute("ap_bookid").getValue()[0].name;
var condition = Xrm.Page.getAttribute("ap_condition").getText();
if (bookName !== null && condition !== null) {
Xrm.Page.getAttribute("ap_name").setValue(bookName + " - " + condition);
}
}
apItem.BaseForm.CountOverDueBy = function() {
var rentedTill = Xrm.Page.getAttribute("ap_rented_till").getValue();
var nowD = Date.now();
if (rentedTill !== null) {
var overdueBy = parseInt((Date.now() - rentedTill) / 86400000);
if (overdueBy > 0) {
Xrm.Page.getAttribute("ap_overdue_by").setValue(overdueBy);
Common.BaseAction.SetNotification("Book is Overdue by " + overdueBy
+ " Days.", "WARNING", "OverDueWarning");
}
else {
Xrm.Page.getAttribute("ap_overdue_by").setValue(null);
Common.BaseAction.clearNotification("OverDueWarning");
}
}
}
In the entity's form, I have added both above files with common.js being at the top and from the event handler I am calling function apItem.BaseForm.CountOverDueBy
Save + Published and Ctrl + F5 gives following error
ReferenceError: Common is not defined
at Object.apItem.BaseForm.CountOverDueBy (https://<domain>/%7B636651014350000438%7D/WebResources/ap_ItemFormBase.js?ver=2091450722:24:13)
at eval (eval at RunHandlerInternal (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:153:1), <anonymous>:1:17)
at RunHandlerInternal (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:159:1)
at RunHandlers (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:118:1)
at OnScriptTagLoaded (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:233:1)
at https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:202:1
I have tried everything but nothing seems to be working.
The way you register the JS files in form, starting from common.js on top & then ap_ItemFormBase.js should work. But product team made few performance improvements around script files like lazy script loading/parallel script loading. This is little tricky & modern scripting is messy between different clients like UUI & web.
Like explained in blog post, if you set the pre-requisite js as dependency, it will load before you consume it in dependent files.
Open the ap_ItemFormBase.js web resource from solution (not from Form Properties), go to Dependencies tab & add the common.js. This will make sure file is ready before reference is used.

JS URL persistence to create templates

I have an interactive UI of elements, and I was encouraged to use divs and spans exclusively, and avoid checkboxes. I have converted the site over to the same functionality, but don't know much about persistence to begin with, but with checkboxes, it seemed approachable given the idea of being 'checked' or 'not checked'. How would I begin to use this approach with tracking each element's visibility?
Here is the page I am trying to implement persistence on.
Previous implementation (not my code, as I am new to JS and persistence) used the following:
// Persistence
//¿¿??
var formvals = {};
var keyval = location.search.replace('?', '').split('&');
$.each(keyval, function () {
var splitval = this.split('=');
formvals[splitval[0]] = splitval[1];
});
$.each($('form')[0].elements, function () {
var key = $(this).attr('name');
if (key && formvals[key]) {
$('#' + key).val(formvals[key]);
} else {
if ($(this).attr('type') == 'checkbox') {
$('#'+key)[0].checked = false;
}
}
});
I would like to know how to use the visibility of the elements to help develop different templates.
I can't find any intros into URL persistence, and Im not quite sure what the previous code does, so any explanation or guidance is greatly appreciated.
If you need more information, please ask, and hopefully you can help send me down the right path.
If URL will be like http://site.com/page.html?id_block_to_click1=1&id_block_to_click2=1 it should work
$(function(){
var formvals = {};
var keyval = location.search.replace('?', '').split('&');
$.each(keyval, function () {
var splitval = this.split('=');
formvals[splitval[0]] = splitval[1];
});
$.each(formvals, function(key,val){
if (val == 1) {
$('#'+key).click();
}
})
});

Appending to External Browser Window

I have a Windows app that contains a browser control that loads pages from my website. However, due to the Windows app, I cannot debug Javascript in the usual ways (Firebug, console, alerts, etc).
I was hoping to write a jQuery plug-in to log to an external browser window such that I can simply do something like:
$.log('test');
So far, with the following, I am able to create the window and display the templateContent, but cannot write messages to it:
var consoleWindow;
function getConsoleWindow() {
if (typeof (consoleWindow) === 'undefined') {
consoleWindow = createConsoleWindow();
}
return consoleWindow;
}
function createConsoleWindow() {
var newConsoleWindow = window.open('consoleLog', '', 'status,height=200,width=300');
var templateContent = '<html><head><title>Console</title></head>' +
'<body><h1>Console</h1><div id="console">' +
'<span id="consoleText"></span></div></body></html>';
newConsoleWindow.document.write(templateContent);
newConsoleWindow.document.close();
return newConsoleWindow;
}
function writeToConsole(message) {
var console = getConsoleWindow();
var consoleDoc = console.document.open();
var consoleMessage = document.createElement('span');
consoleMessage.innerHTML = message;
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
consoleDoc.close();
}
jQuery.log = function (message) {
if (window.console) {
console.log(message);
} else {
writeToConsole(message);
}
};
Currently, getElementById('consoleText') is failing. Is what I'm after possible, and if so, what am I missing?
Try adding
consoleDoc.getElementById('consoleText');
right before
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
If the line you added is the one that fails, then that means consoleDoc is not right, if the next line is the only one that fails then ..ById('consoleText') is not matching up
If I don't close() the document, it appears to work as I hoped.

Posting data into JavaScript from an URL

I have a javascript on my server, and i need to set a value / calling a function inside the javascript when calling a URL. Is there anyway of doing that ?
UPDATE:
<script type="application/x-javascript" src="test-test.js"></script>
Thats how it its loaded on the HTML site. And I want to call the function test(e,e) inside test-test.js, by putting in the URL in a browser with some values for e,e..
Unless you are using one of the few web servers that employs server-side JavaScript, your script is going to run in the browser after the page is loaded. If you want to include information from the URL in your script (and this assumes that you can use a query string without changing the server's behavior), you can use window.location.search to get everything from the question mark onwards.
This function will return either the entire query string (without the question mark) or a semicolon-delimited list of values matching the name value you feed it:
function getUrlQueryString(param) {
var outObj = {};
var qs = window.location.search;
if (qs != "") {
qs = decodeURIComponent(qs.replace(/\?/, ""));
var paramsArray = qs.split("&");
var length = paramsArray.length;
for (var i=0; i<length; ++i) {
var nameValArray = paramsArray[i].split("=");
nameValArray[0] = nameValArray[0].toLowerCase();
if (outObj[nameValArray[0]]) {
outObj[nameValArray[0]] = outObj[nameValArray[0]] + ";" + nameValArray[1];
}
else {
if (nameValArray.length > 1) {
outObj[nameValArray[0]] = nameValArray[1];
}
else {
outObj[nameValArray[0]] = true;
}
}
}
}
var retVal = param ? outObj[param.toLowerCase()] : qs;
return retVal ? retVal : ""
}
So if the URL was, say:
http://www.yoursite.com/somepage.html?name=John%20Doe&occupation=layabout
if you call getUrlQueryString() you would get back name=John Doe&occupation=layabout. If you call getUrlQueryString("name"), you would get back John Doe.
(And yes, I like banner-style indents. So sue me.)
You can use address plugin to be able to pass some condition in urls trough # symbol: http://my_site/my_page#your_condition
in the html you can write something like this:
<script>
$(function(){
// Init and change handlers
$.address.init().change(function(event) {
if (event.value == "your_condition")
run_my_finction();
});
)};
<script>
See this exaple for the futher help.
If you want to execute JavaScript from the browsers' address bar, you can use a self-invoking function:
javascript:(function () {
alert('Hello World');
/* Call the JavaScript functions you require */
})();

Categories