Customize Email's regardingobjectid lookup dropdown - javascript

I've tried customizing Email's regardingobjectid lookup dropdown, using the following code:
var regardingobjectid = Xrm.Page.getControl("regardingobjectid");
/* The value of viewId is a dummy value,
and only needs to be unique among the other available views for the lookup. */
var viewId = '{00000000-0000-0000-0000-000000000001}';
var entityName = 'lu_service';
var viewDisplayName = 'service - custom view';
var fetchXml =
'<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" >' +
'<entity name="lu_service">' +
'<attribute name="lu_serviceid" />' +
'<attribute name="lu_name" />' +
'<attribute name="createdon" />' +
'<order attribute="lu_name" descending="false" />' +
'</entity>' +
'</fetch>';
var lookupService = new RemoteCommand("LookupService", "RetrieveTypeCode");
lookupService.SetParameter("entityName", "lu_service");
var result = lookupService.Execute();
var objectTypeCode = result.ReturnValue;
var layoutXml =
'<grid name="resultset" object="' + objectTypeCode + '" jump="lu_name" select="1" icon="1" preview="1">' +
'<row name="lu_service" id="lu_serviceid">' +
'<cell name="lu_name" width="300" />' +
'<cell name="createdon" width="125" />' +
'</row>' +
'</grid>';
regardingobjectid.addCustomView(viewId, entityName, viewDisplayName, fetchXml, layoutXml, true);
I thought that this code should do two things:
1. Customize the lookup dropdown, i.e., display the records of the required type (in my example: lu_service) on the dropdown displayed when clicking the lookup field.
2. Add a custom view onto the window opened when clicking the "Look Up More Records" link (listed at the end of the lookup dropdown).
The result is that 1 doesn't work, and 2 works.
My question is: Should've 1 worked? If not, is it possible to achieve this?

For point #1 in 2015 version, you have to use addPreSearch and addCustomFilter to filter out the unwanted entities in the dropdown list. This is the only supported way/workaround. Read more
For example, the below filter will show lu_service & remove any account from regardingobjectid lookup. Trick is account will not have null accountid.
var serviceFilter = "<filter type='and'><condition attribute='lu_serviceid' operator='not-null' /></filter>";
//remove accounts
var accountFilter = "<filter type='and'><condition attribute='accountid' operator='null' /></filter>";
Xrm.Page.getControl('regardingobjectid').addCustomFilter(serviceFilter, "lu_service");
Xrm.Page.getControl('regardingobjectid').addCustomFilter(accountFilter, "account");

Related

querySelectorAll with two or more dataset as queries

I have a table i created lets call it RPT_ACCOUNTS
CODE|DESCRIPTION|TYPE
01|BANK|BA
02|TAX|TA
When I pull the information from the datatable i create the table visually in html
row.dataset.rpt_accounts_code= DBRow.CODE;
row.dataset.rpt_accounts_description= DBRow.DESCRIPTION;
row.dataset.rpt_accounts_type= DBRow.TYPE;
So now I have the 3 datasets.
now I want to filter so i can run through a for loop. (this is my problem)
if i use
var ROWS= RPT_ACCOUNTS.querySelectorAll('tr[data-rpt_accounts_code="' + searchvalue + '"]');
IT WORKS!
But now i need two search values
so i read up and saw it is supported with a "," but it doesn't work. i have tried many combinations
var ROWS= RPT_ACCOUNTS.querySelectorAll('tr[data-rpt_accounts_code="' + searchvalue + '"],tr[data-rpt_accounts_type="' + searchvalue2 + '"]');
var ROWS= RPT_ACCOUNTS.querySelectorAll('tr[data-rpt_accounts_code="' + searchvalue + '"],[data-rpt_accounts_type="' + searchvalue2 + '"]');
var ROWS= RPT_ACCOUNTS.querySelectorAll('tr[data-rpt_accounts_code="' + searchvalue + '"]','tr[data-rpt_accounts_type="' + searchvalue2 + '"]');
anyone one of the above methods go through, but it pulls all the data not just the line I'm looking for.
Any help would be awesome.
jsfiddle
https://jsfiddle.net/custardcs/q8a6uysg/5/
If you want to query multiple attributes, express them like el[propA=val][propB=val], so, in your case
var ROWS= RPT_ACCOUNTS.querySelectorAll('tr[data-rpt_accounts_code="' + searchvalue + '"][data-rpt_accounts_type="' + searchvalue2 + '"]')

How to get URL from current active Browser window/tab from within a script running in an XUL <browser> (e.g. in a sidebar)

I am creating a simple bootstrapped add-on for Firefox. I need to capture the current URL from the browser through sidebar with a button click.
My bootstrap.js:
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
/*start - windowlistener*/
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function (aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow =aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal||Ci.nsIDOMWindow);
aDOMWindow.addEventListener("load", function () {
aDOMWindow.removeEventListener("load", arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
//START - EDIT BELOW HERE
var browser = aDOMWindow.document.querySelector('#browser')
if (browser) {
var splitter = aDOMWindow.document.createElement('splitter');
var propsToSet = {
id: 'demo-sidebar-with-html_splitter',
//I'm just copying what Mozilla does for their social sidebar splitter
// I left it out, but you can leave it in to see how you can style
// the splitter
class: 'sidebar-splitter'
}
for (var p in propsToSet) {
splitter.setAttribute(p, propsToSet[p]);
}
var sidebar = aDOMWindow.document.createElement('vbox');
var propsToSet = {
id: 'demo-sidebar-with-html_sidebar',
//Mozilla uses persist width here, I don't know what it does and can't
// see it how makes a difference so I left it out
//persist: 'width'
}
for (var p in propsToSet) {
sidebar.setAttribute(p, propsToSet[p]);
}
var htmlVal = loadJsonHTML(0);
var sidebarBrowser = aDOMWindow.document.createElement('browser');
var propsToSet = {
id: 'demo-sidebar-with-html_browser',
type: 'content',
context: 'contentAreaContextMenu',
disableglobalhistory: 'true',
tooltip: 'aHTMLTooltip',
autoscrollpopup: 'autoscroller',
flex: '1', //do not remove this
//you should change these widths to how you want
style: 'min-width: 14em; width: 18em; max-width: 36em;',
//or just set this to some URL like http://www.bing.com/
src: 'data:text/html,'+ htmlVal
}
for (var p in propsToSet) {
sidebarBrowser.setAttribute(p, propsToSet[p]);
}
browser.appendChild(splitter);
sidebar.appendChild(sidebarBrowser);
browser.appendChild(sidebar);
}
//END - EDIT BELOW HERE
},
unloadFromWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
//START - EDIT BELOW HERE
var splitter = aDOMWindow.document
.querySelector('#demo-sidebar-with-html_splitter');
if (splitter) {
var sidebar = aDOMWindow.document
.querySelector('#demo-sidebar-with-html_sidebar');
splitter.parentNode.removeChild(splitter);
sidebar.parentNode.removeChild(sidebar);
}
//END - EDIT BELOW HERE
}
};
/*end - windowlistener*/
function startup(aData, aReason) {
windowListener.register();
}
function shutdown(aData, aReason) {
if (aReason == APP_SHUTDOWN) return;
windowListener.unregister();
}
function loadJsonHTML(val=0){
var fileContent = "";
var localFile = Cc["#mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
//full path is okay if directory exists
localFile.initWithPath("/Users/tinuy/Desktop/test_addodn/input.txt");
//otherwise specify directory, create it if necessary, and append leaf.
//localFile.initWithPath("C:\Users\tinuy\Documents\test\input.txt");
if ( localFile.exists() == false ) {
fileContent = "File does not exist";
}
var istream = Cc["#mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
istream.init(localFile, 0x01, 4, null);
var fileScriptableIO = Cc["#mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
fileScriptableIO.init(istream);
// parse the XML into our internal document
istream.QueryInterface(Ci.nsILineInputStream);
//fileContent = fileScriptableIO.read( '1' );
var csize = 0;
while ((csize = fileScriptableIO.available()) != 0) {
fileContent += fileScriptableIO.read( csize );
}
var array = fileContent.split("&");
fileScriptableIO.close();
istream.close();
return makeHTML(array[val], val);
}
function makeHTML(value, key){
var arrValues = value.split(",");
var htmlContent = '<div name="content" class="content">' +
'<p> Name :' + arrValues[0] + '</p>';
htmlContent += '<p> Price :' + arrValues[2] + '</p>';
htmlContent += '<p> Color :' + arrValues[3] + '</p>';
htmlContent += '<p> UID :' + arrValues[1] + '</p>';
htmlContent += '<p><input type="radio" name="valid" value="yes" />Yes ' +
'<input type="radio" name="valid" value="no" /> No</p>' +
'<p><input type="text" placeholder="Reason" name="checkreason"></p>' +
'<p><input type="text" placeholder="Feedback" name="feedback"></p>' +
'</div><div><button name="load" type="button" id="loadit" onclick="loadHtml()" ' +
'loadurl="'+arrValues[4]+'">Load</button> <button name="save" type="button">' +
'Save </button> <button name="next" type="button" key="'+key+'">Next </button> ' +
'</div> <script> function loadHtml() {' +
'var a = gBrowser.contentWindow.location.href ;alert(a);' +
'} </script>';
return htmlContent;
}
function install() {}
function uninstall() {}
I tried all suggestions from Get current page URL from a firefox sidebar extension but nothing worked.
However, from the fact that you have set:
var propsToSet = {
id: 'demo-sidebar-with-html_browser',
type: 'content', //<---------------------------This
the <browser> type to content, I am assuming one of two things:
That you are not actually trying to get the active tab's URI from within the code you are loading into the <browser> through the src attribute.
If this is the case, please see my answer to "How to Get Active Tab Location by e10s add-on". In that case, the context from which you are running should allow you to use the code in that answer.
This possible assumption, #1, is not the case for your code.
You want to gain access to the URI form code within the <browser> you have loaded into the sidebar and are unaware of the restrictions which setting the <browser> type to content imposes upon the code you load into the <browser>.
It looks like you are trying to access the currant tab's URL from the code in your <browser>. You should consider restructuring your code such that access to chrome privileges is not required from the content that is in the <browser>. In other words, if possible, you should write your code such that you do not need to have access to the URL, or other information, directly from code running in the <browser> you insert. However, doing so may end up being significantly more complex.
Getting access to chrome privileges within the <browser> you are adding:
Setting the <browser> type to content is for:
A browser for content. The content that is loaded inside the browser is not allowed to access the chrome above it.
Setting the <browser> type to chrome is for:
(default behaviour): A browser, intended to be used for loading privileged content using a chrome:// URI. Don't use for content from web, as this may cause serious security problems!
To set the the <browser> type to chrome you can do:
var propsToSet = {
id: 'demo-sidebar-with-html_browser',
type: 'chrome', //<---------------------------This
The code provided by Noitidart comes close to what you need. However, it needs to be slightly modified, as gBrowser.currentURI is a nsIURI, not a string). Thus, you need to use gBrowser.currentURI.spec. You can get it working by changing your makeHTML() to:
function makeHTML(value, key){
var arrValues = value.split(",");
var htmlContent = '<html><head></head>'
+ '<body style="background-color: white;">'
+ ' <div name="content" class="content">'
+ ' <p> Name :' + arrValues[0] + '</p>';
htmlContent += '<p> Price :' + arrValues[2] + '</p>';
htmlContent += '<p> Color :' + arrValues[3] + '</p>';
htmlContent += '<p> UID :' + arrValues[1] + '</p>';
htmlContent +=
' <p><input type="radio" name="valid" value="yes" />Yes '
+ ' <input type="radio" name="valid" value="no" /> No</p>'
+ ' <p><input type="text" placeholder="Reason" name="checkreason" /></p>'
+ ' <p><input type="text" placeholder="Feedback" name="feedback" /></p>'
+ ' </div>'
+ ' <div>'
+ ' <button name="load" type="button" id="loadit" onclick="loadHtml()" '
+ ' loadurl="' + arrValues[4] + '">Load</button>'
+ ' <button name="save" type="button">Save </button>'
+ ' <button name="next" type="button" key="' + key + '">Next </button>'
+ ' </div>'
+ ' <script>'
+ ' function loadHtml() {'
+ ' const Cu = Components.utils;'
+ ' Cu.import("resource://gre/modules/Services.jsm");'
+ ' var win = Services.wm.getMostRecentWindow("navigator:browser");'
+ ' if (win) {'
+ ' var url = win.gBrowser.currentURI.spec;'
+ ' alert("URL=" + url);'
+ ' }'
+ ' }'
+ ' </script>'
+ '</body></html>';
return htmlContent;
}
Security concerns:
There are some really significant security concerns that you may be running into. Just from the fact that you want the URL for the current page implies that you may be rapidly approaching where these are a real issue. It is going to depend on what exactly you are going to do. Given that you are not providing that information, I am not going to go too in depth as to what the issues are. However, you should read "Firefox Security Basics for Developers" and "Security best practices in extensions"
Additional information about sidebars:
You should seriously consider creating an Add-on SDK based add-on, instead of a bootstrap one, and using the ui/sidebar API.
If you are interested, I created some code which can be used to create a "sidebar" that is located at the top, left, right, or bottom of the active tab, or in a separate window (similar to what the devtools panel will do). The sidebar created is associated with the currently active tab, not all tabs (I guess I should have made it an option to have it associated with all tabs, or just the current tab) in my answer to: "How to create a bottom-docked panel with XUL in Firefox?" and "Firefox Extension, Window related sidebar"

js/jquery iterate through html elements to dynamically build a string

I'd like to build a string based on values defined in an html form only if they have been populated. I've successfully parsed the form fields and dropdown with a for loop ($.each()) but my ultimate goal is to dynamically build a string with the results. The string is being used to create a REST query, this is currently the only way to search based on our technologies. Does anyone have a recommended solution?
thx in advance
sample html element:
<input data-param=" prefix like '%" data-name="prefix" class="prefix uno" type="text" placeholder="pre">
working btn click event loop to capture filled in form fields:
var children = $(this).parent().children('.uno');
$.each(children, function(i, val){
if($(val).val() !== ''){
console.log($(val).data('name') + " "+ $(val).data('param') + " " + $(val).val());
}
});
goal:
var newString = field1.param + field1.val + '% ' + field2.param + field2.val + '% ';
translated:
var newString = prefix like '%01%' and name like '%tree%';
Thanks David Fregoli for the jquery serialize reference, that was close, but the solution ended up being to place the strings into a single array, change it toString(), and remove the ',' from the new string.
code:
var samp = [],
thisVal = $(this).parent().children('.uno');
$.each(thisVal, function(i, val){
if($(val).val() !== ''){
samp.push(
$(val).data('param'),
$(val).val(),
$(val).data('close')
);
}
});
itQuery.where = samp.toString().replace( /,/g , '');
result search string:
"number like '%08%' and field = 34"

Change MSCRM 2011 subgrid entity

I know how to modify the FetchXml of the subgrid. I'm attempting to dynamically change a subgrid based on selections from optionsets with JS. Based on the optionsets, the subgrid will need to be able to display different entities (not at the same time).
Example: The subgrid is currently showing Accounts with a specific relationship type. An optionset changes and now the subgrid should show Leads whose first name is John.
The error I'm receiving is "Entity Name specified in FetchXml does not match the entity name in the EntityExpression"
I feed the below fetch into the grid. It's just a multi-value search. rc_entitylist contains all entities in the system. rc_attributelist contains all the fields for the selected entity. The user selects an entity, selects a field to search, enters search criteria (one value per line) and then it populates the subgrid accordingly.
function runSearch() {
var entityname = Xrm.Page.getAttribute("rc_entitylist").getText();
var sgrid = "searchResults";
var fetchXml = '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">'+
'<entity name="' + entityname + '">'+
'<all-attributes />' +
'<filter type="and">'+
'<filter type="or">';
var textBoxLines = document.getElementById("rc_searchcriteria").innerText;
var attributename = Xrm.Page.getAttribute("rc_attributelist").getText();
var lines = textBoxLines.split(/\n/);
for(var i=0;i < lines.length; i++){
fetchXml = fetchXml + '<condition attribute="' + attributename + '" operator="eq" value="'+ lines[i] +'" />';
}
fetchXml = fetchXml + '</filter>'+
'</filter>'+
'</entity>'+
'</fetch>';
updateXml(sgrid, fetchXml, entityname);
}
function updateXml(grid, xmlfield, entityname) {
try {
var g = document.getElementById(grid).control;
g.setParameter("fetchXml", xmlfield);
} catch (e) { }
// Refresh the grid
document.getElementById(grid).control.refresh();
}
Have you thought about adding multiple subgrids to the form, and hiding/showing them based on the on-change event of the optionset?

Pass string from one function to the next javascript

I've got a simple JavaScript client that pulls from a REST API to present some book data, however I seem unable to call the function createBookRow(bookid) and return the appropriate html string to the document ready function where it is called,
The output is currently being produced correctly as verified by the append to .row-fluid on the html page, ideas or suggestions welcome
function createBookRow(bookid)
{
$.get('http://mysite.co.uk/atiwd/books/course/'+bookid+'/xml', function(xml){
$(xml).find('book').each(function(){
var $book = $(this);
var id = $book.attr("id");
var title = $book.attr("title");
var isbn = $book.attr("isbn");
var borrowedcount = $book.attr("borrowedcount");
var html = '<div class="span3"><img name="test" src="http://covers.openlibrary.org/b/isbn/'+isbn+'-L.jpg" width="32" height="32" alt=""></p>' ;
html += '<p> ' + title + '</p>' ;
html += '<p> ' + isbn + '</p>' ;
html += '<p> ' + borrowedcount + '</p>' ;
html += '</div>';
$('.row-fluid').append($(html));
});
});
}
$(document).ready(function()
{
$.get('xml/courses.xml', function(xml){
$(xml).find('course').each(function(){
var $course = $(this);
var id = $course.attr("id");
var title = $course.text();
var html = '<div class="span12"><p>' + title + '</p><row id="'+id+'" >'+createBookRow(id)+'</row></div>' ;
$('.row-fluid').append($(html));
$('.loadingPic').fadeOut(1400);
});
});
});
The line
var html = '<div class="span12"><p>' + title + '</p><row id="'+id+'" >'+createBookRow(id)+'</row></div>' ;
should be just
var html = '<div class="span12"><p>' + title + '</p><row id="'+id+'" ></row></div>' ;
createBookRow(id);
createBookRow(id) function is making a get request to get some details, which happens asynchronously. Unless you explicitly mention it is a synchronous call(which is not advised).
I guess the functionality you need is to render some rows for course and in between you need books details displayed. In that case you need to explicitly say where your book row needs to be appended.
$('.row-fluid').append($(html));
The above code will always append book row at the end.
You aren't returning anything in the code you provided. You just append some HTML to a jQuery object. Try adding a return statement
return html;

Categories