Custom event handler - Dynamics crm online - javascript

I have requirement on Dynamics crm 2015 online:
I have a lookup and subgrid on a custom entity.
When the user clicks on the 'search' button, which shows search box, I want that search to be pre-populated with the lookup field value, so to save the user from copy/pasting or typing the lookup value into the search box.
What I have tried so far!
I have written a JavaScript in which I tried to catch the event of '+' button on sub grid, using 'addEventListener' on 'gridname_addImageButton' id but the event was not caught. This is quite basic stuff for normal web development, but not happening on dynamics crm.
UPDATE
This the HTML of the "+" button that appears on the grid.
<a action="tec|ManyToMany|SubGridStandard|Mscrm.AddExistingRecordFromSubGridAssociated" tabindex="1340"
title="Add record." class="ms-crm-ImageStrip-addButton" style="display: block; cursor: pointer;"
onclick="return false;" id="tec_addImageButton" href="#">
<img class="ms-crm-add-button-icon" title="Add Experlogix Model record." alt="Add record."
id="Tec_addImageButtonImage" src="/_imgs/imagestrips/transparent_spacer.gif?ver=-893257913" />
</a>
And this is the javascript that I tried:
var elem = document.getElementById('tec_addImageButton');
elem.addEventListener('click',myFunc(),false);
What am I missing?
Regards,
Momi

CRM forms are not "normal web development" as the product does not support direct DOM manipulation. The only manipulation allowed is that done using CRM's Xrm.Page object. The general how-to of using Xrm.Page is documented in the SDK: https://msdn.microsoft.com/en-us/library/gg328261.aspx.
Specifically, you are looking to add a custom filter to a lookup, which can be done with the code:
Xrm.Page.getControl(arg).addCustomFilter(filter, entityLogicaName)
Where filter is a string with a valid FetchXML filter, i.e.:
<filter type="and">
<condition attribute="new_somefieldname" operator="eq" value="somevalue" />
</filter>
You can call addCustomFilter in the OnLoad event or you can use a PreSearch event handler to add your filter:
Xrm.Page.getControl(arg).addPreSearch(handler)
Credit to http://missdynamicscrm.blogspot.com/2014/08/crm-2013-using-addcustomfilter-to-get-filtered-lookup-field-based-on-linked-entity.html for this fully implemented example.
function onLoad()
{
addEventHandler();
}
function addEventHandler() {
// add the event handler for PreSearch Event
Xrm.Page.getControl("parentcontactid").addPreSearch(addFilter);
}
function addFilter() {
//find contact contains this #example.com
var email = "%#example.com%";
//create a filter xml
var filter = "<filter type='and'>" +
"<condition attribute='emailaddress1' operator='like' value='" + email + "'/>" +
"</filter>";
//add filter
Xrm.Page.getControl("parentcontactid").addCustomFilter(filter);
}

Make sure that event is attaching to the anchor and add the function without brackets () while adding the event listener like in the following example.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
window.onload = function () {
document.getElementById('tec_addImageButton').addEventListener('click', myFunc, false)
}
function myFunc() {
alert("testing");
}
</script>
</head>
<body>
<a id="tec_addImageButton" href="#">test button</a>
</body>
</html>

You have to put the html script as a web resource in your solution.
Insert HTML inside your Form
You have to put the js script as a web resource in your solution.
You have to event the frame on Form Libraries : web resource
You have to event the frame on Event Handler -> Form -> onload Add: myObj.init()
if (typeof (myObj) == "undefined") {
myObj = {};
}
(function () {
myObj.init = function () {
Xrm.Page.ui.controls.get('id_iframe').getObject().onload= function() {
var el = Xrm.Page.ui.controls.get('id_iframe').getObject().contentWindow.document.getElementById('myLabel');
addEvent(el, 'click', function () { alert('Evento'); });
};
}
function addEvent(element, evnt, funct) {
if (element.attachEvent)
return element.attachEvent('on' + evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
})();
<HTML>
<BODY onload="SetupEvents()">
<label id="myLabel" >Click me</label>
</HTML>

Related

youtube api v3 search by keyword javascript

The javascript example for "search by keyword" that is given at the google developers page isn't working for me. https://developers.google.com/youtube/v3/code_samples/javascript
When I run the code, I get a disabled search box with "cats" inside. Also, the example doesn't explain how to write in the API key as opposed to the Client ID. It says it's possible, but gives no concrete example of how to do it. Can someone point out where this code is going wrong. The code for the two .js files and the html is as follows:
auth.js file:
// The client ID is obtained from the Google Developers Console
// at https://console.developers.google.com/.
// If you run this code from a server other than http://localhost,
// you need to register your own client ID.
var OAUTH2_CLIENT_ID = '__YOUR_CLIENT_ID__';
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube'
];
// Upon loading, the Google APIs JS client automatically invokes this callback.
googleApiClientReady = function() {
gapi.auth.init(function() {
window.setTimeout(checkAuth, 1);
});
}
// Attempt the immediate OAuth 2.0 client flow as soon as the page loads.
// If the currently logged-in Google Account has previously authorized
// the client specified as the OAUTH2_CLIENT_ID, then the authorization
// succeeds with no user intervention. Otherwise, it fails and the
// user interface that prompts for authorization needs to display.
function checkAuth() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: true
}, handleAuthResult);
}
// Handle the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
// Authorization was successful. Hide authorization prompts and show
// content that should be visible after authorization succeeds.
$('.pre-auth').hide();
$('.post-auth').show();
loadAPIClientInterfaces();
} else {
// Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
// client flow. The current function is called when that flow completes.
$('#login-link').click(function() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: false
}, handleAuthResult);
});
}
}
// Load the client interfaces for the YouTube Analytics and Data APIs, which
// are required to use the Google APIs JS client. More info is available at
// http://code.google.com/p/google-api-javascript-client /wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
gapi.client.load('youtube', 'v3', function() {
handleAPILoaded();
});
}
search.js file:
// After the API loads, call a function to enable the search box.
function handleAPILoaded() {
$('#search-button').attr('disabled', false);
}
// Search for a specified string.
function search() {
var q = $('#query').val();
var request = gapi.client.youtube.search.list({
q: q,
part: 'snippet'
});
request.execute(function(response) {
var str = JSON.stringify(response.result);
$('#search-container').html('<pre>' + str + '</pre>');
});
}
search.html
<!doctype html>
<html>
<head>
<title>Search</title>
</head>
<body>
<div id="buttons">
<label> <input id="query" value='cats' type="text"/><button id="search-button" disabled onclick="search()">Search</button></label>
</div>
<div id="search-container">
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="auth.js"></script>
<script src="search.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"> </script>
</body>
</html>
The documentation is misleading a bit (one might even say incorrect); the HTML for the "search by keyword" is loading the same "auth.js" that the other two examples on that page are, but it doesn't then have any HTML elements to actually trigger the login process (i.e. a "login button" if a user isn't already authorized) like the other two examples do. Bascially, if you're using that provided auth.js, you need to have, in your HTML, a section that looks like this:
<div id="login-container" class="pre-auth">
This application requires access to your YouTube account.
Please authorize to continue.
</div>
Then, you can also add the class of "post-auth" on a new div that wraps around your existing buttons and search container. The demo will then, when a user visits, only present the login link; when clicked on, and when a user allows the authorization, then the login link will be hidden and your search area will be shown (and the button enabled). That's just how the demo is set up.
Of course, search by keyword does NOT require oAuth2, and so (to answer your 2nd question) you might find it easier to A) remove the handleApiLoaded method (so your button is never disabled), and B) call gapi.client.load() manually (i.e. not triggered by an oAuth success). Then, call gapi.client.setApiKey({YOUR KEY}) so that all of your requests will include your key in their header.
Thanks so much jlmcdonald for your help. It took me a while to figure out the second part of your response, but I finally had success. The following html gets the example on the google developers webpage to work. Note though, at first I was getting a 401 error. To fix it, I had to go to the google developers console and select my project. Then, APIs&auth->consent screen and then fill in the email address and product name:
<!doctype html>
<html>
<head>
<title>Search</title>
</head>
<body>
<div id="login-container" class="pre-auth">
This application requires access to your YouTube account.
Please authorize to continue.
</div>
<div id="buttons" class="post-auth">
<label> <input id="query" value='cats' type="text"/><button id="search-button" disabled onclick="search()">Search</button></label>
</div>
<div id="search-container">
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="/files/theme/auth.js"></script>
<script src="/files/theme/search.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"> </script>
</body>
</html>
As you noted in your response, oAuth2 isn't necessary for a simple keyword search. The following is some html that just uses the API key. I didn't reference the two .js files like before, rather, I just included the script in the html. Your post at gapi.client.youtube is undefined? really helped me figure it out:
<!doctype html>
<html>
<head>
<title>Search</title>
</head>
<body>
<div id="buttons">
<label> <input id="query" value='cats' type="text"/><button id="search-button" onclick="keyWordsearch()">Search</button></label>
</div>
<div id="search-container">
</div>
<script>
function keyWordsearch(){
gapi.client.setApiKey('API key here');
gapi.client.load('youtube', 'v3', function() {
makeRequest();
});
}
function makeRequest() {
var q = $('#query').val();
var request = gapi.client.youtube.search.list({
q: q,
part: 'snippet'
});
request.execute(function(response) {
var str = JSON.stringify(response.result);
$('#search-container').html('<pre>' + str + '</pre>');
});
}
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"> </script>
</body>
</html>
Now that I got the search part, could you explain how I can display the thumbnails and titles of the results and then when I click them, the video opens in an embedded player on the same page? Thanks.
Thank you for your coding. Let me share my code:
function makeRequest(){
var q = $('#query').val();
var request = gapi.client.youtube.search.list({
q: q,
part: 'snippet'
});
request.execute(function(response){
var str = JSON.stringify(response.result,'',4);
$('#search-container').val( str);
makeControl(response);
});
}
function makeControl(resp){
var stList = '<table id="res1" border="1" cellspacing="1" width="100%"><tbody>';
for (var i=0; i<resp.items.length;i++){
var vid = resp.items[i].id.videoId;
var tit = resp.items[i].snippet.title;
if(typeof vid != 'undefined'){
stList += '<tr><td style="width:80px;vertical-align:top">'+
'<a class="show" href="#" title="'+ vid + '" onclick="playVid(this);'+
' return false">'+
'<img width="80" height="60" src="http://img.youtube.com/vi/'+
vid +'/default.jpg"></a></td>'+
'<td><b>'+i+'</b>-'+ tit +'</td></tr>';
}
}
document.getElementById('list1').innerHTML = stList + '</tbody></table>';
//HTML: <div id="list1"
//style="width:853px;height:400px;overflow:auto;background-color:#EEEEEE">
//</div>
}
function playVid(thi){
var st = 'https://www.youtube.com/embed/'+thi.title+'?autoplay=1';
document.getElementById('player').src = st;
//HTML: <iframe id="player" width="853" height="480" src="" frameborder="1" allowfullscreen>
//</iframe>
}

Document.writeln in a New frame not window.open

How can I write new lines on a frame in the same window? For now I have it creating a new Window with window.open. But now I need it in a frame.
I have an html with the two frames(form and result) and I need to write in the second by pressing a button on the first frame.
HTML
<html>
<head>
<title> Create Curriculum</title>
<meta charset="UTF-8"/>
</head>
<frameset rows="50%,50%">
<frame id="form" src="from.html"/>
<frame id="curri" src=""/>
</frameset>
You intercat with the form adding info to the inputs and saving the information. There's also a button that generates the curriculum using the info entered below.
JAVASCRIPT:
function genCurriculum() {
//I want to capture the second frame with id "curri"
var curri = parent.document.getElementById("curri");
curri.document.writeln("<h2>Head of the curriculum...</h2>");
//The others writeln for creating the curriculum
}
I want to know how to write in the frame, not in a new window.
And NOT using Jquery, just pure JavaScript. (Teacher requirement)
Is this jsfiddle what you want to have happen?
Html:
<form>
<input name="nextLine" type="text" />
<button type="button">
<span>Add a line</span>
</button>
</form>
<iframe height="100" width="200"></iframe>
JavaScript:
(function () {
'use strict';
var button, iframe, input;
function addLine (cD, input, val) {
return function () {
var body, line;
body = cD.getElementsByTagName('body')[0]
line = cD.createElement('p');
line.innerText = val.toString() + ': ' + input.value;
body.appendChild(line);
val += 1;
}
}
button = document.getElementsByTagName('button')[0];
iframe = document.getElementsByTagName('iframe')[0];
input = document.getElementsByTagName('input')[0];
button.addEventListener('click', addLine(iframe.contentDocument, input, 0), true);
}());

Disabling a jQuery function

I have a jQuery function which monitors the 'beforeunload' status.
So therefore every time i do a refresh this method is executed.
The function is as follows:
<script type="text/javascript">
var bIsSafeRedirect = false;
$('#reload').click(function()
{
bIsSafeRedirect = true;
location.reload();
});
$(window).bind('beforeunload', function()
{
if (!bIsSafeRedirect )
{
return '>>>>>Before You Go<<<<<<<< \n Your custom message go here';
}
});
</script>
Now i have other components such as
<td onClick="window.location.replace('try.html')" id="reload" target="Content">
which onclick reloads the same page.
I this scenario where the table data is clicked i dont want the jQuery function to be invoked.I want it to be skipped as a special case.
How can i achieve it.
The entire code is shown below
<html>
<head>
<title>Refresh a page in jQuery</title>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript">
function load()
{
document.getElementById("first").value="hello";
}
</script>
</head>
<body>
<h1>Stop a page from exit with jQuery</h1>
<button id="reload">Refresh a Page in jQuery</button>
<script type="text/javascript">
var bIsSafeRedirect = false;
function unload(type, url){
if(type === 'noReturn'){
$(window).unbind("beforeunload");
window.location.replace(url);
} else if(!bIsSafeRedirect && type === 'return') {
var conf = confirm('do you want to quit');
if(conf){
alert("ajax");
} else {
return false;
}
}
}
$(window).bind("beforeunload", function(){
unload('return');
});
</script>
<table>
<tr>
<td onClick="window.location.replace('try.html')" id="reload" target="Content">
<td onClick="unload('noReturn','try.html')">
Usual Refresh
</td>
</tr>
</table>
<input type="text" id="first" size="15"/>
<input type="button" onclick="load()" value="load"/>
</body>
</html>
Try this:
<td onClick="replaceContent();" id="reload" target="Content">
Here is the replaceContent() function:
function replaceContent(){
$(window).unbind('beforeunload');
window.location.replace('try.html');
}
one way is to prepend this to onClick:
$(window).unbind('beforenload');
the other way is to use a global flag, exactly like the bIsSafeRedirect you're currently using. Change the beforeunload handler body like this:
if (shouldRefresh && !bIsSafeRedirect)
{
return '>>>>>Before You Go<<<<<<<< \n Your custom message go here';
}
and set shouldRefresh value to false in onClick.
Make a function that handles both of these:
function unload(type, url){
if(type === 'noReturn'){
$(window).unbind("beforeunload");
window.location.replace(url);
} else if(!bIsSafeRedirect && type === 'return') {
var conf = confirm('Confirmation message');
if(conf){
// fire ajax call here
} else {
return false;
}
}
}
And then fire this function in your bind() call:
$(window).bind("beforeunload", function(){
unload('return');
});
Since we supply the return string to the type parameter, it fires the else if part of the if statement, which doesn't unbind the beforeunload event and so returns that string.
And for your other components:
<td onClick="unload('noReturn','try.html')"></td>
So now, since we have supplied the noReturn string to the type parameter, the first part of the if statement will execute and load the page without the interference of the beforeunload handler by unbinding it.
With this method, you can use the unload function on multiple elements' inline onclick handlers and make it a more globally usable script.

__doPostBack not working for me

Is there an error in the way i use the __doPostBack?
function displaymessage() {
var scl = "aaaaaa";
var pageId = '<%= Page.ClientID %>';
__doPostBack(pageId, 'OtherInformation');
alert(scl);
}
<input type="button" value="Click me!" id="Button2" onclick="displaymessage()" />
When i press the button it should call the RaisePostBackEvent in the code file, but it doesn't. If i comment the doPostBack it reaches the alert but when it is uncommented it does not. So it must be an error in the usage of the doPostBack.
I followed this post: Call ASP.NET function from JavaScript?
Place the following script on the header section of your html file:
<script>
function __doPostBack(eventTarget, eventArgument) {
document.Form1.__EVENTTARGET.value = eventTarget;
document.Form1.__EVENTARGUMENT.value = eventArgument;
document.Form1.submit();
}
</script>
for me the _dopostback() was not firing only on IE and chrome browser. I have resolved by adding "return false;" statement in the javascript function. for example:-
function test()
{
_dopostback("logout","");
return false;
}
now its working fine.
Change you code to this:
setTimeout(function () { __doPostBack('btnSave', '') }, 500);
Use btnSave Id. It will work in all browsers.
Drop your second argument of __doPostBack ('OtherInformation'), and replace with an empty string, ''. You could put that data in a hidden input field if you need it, and retrieve it using Request.Form.
I also followed the same post you mentioned and got an error, I tried to use the other answers here but it still didn't work.
Until I've found this post:
http://forums.asp.net/t/1197643.aspx
(look in the 8th reply made by NC01).
1.basically the idea is that your aspx should have something like this:
<script type="text/javascript" language="javascript">
function myfunction() {
if ('<%=Page.IsPostBack%>' == 'False') {
var pageId = '<%= this.UniqueID %>';
__doPostBack(pageId, 'do_something_good');
}
}
</script>
2.then in your .cs you should add interface IPostBackEventHandler (for example:)
public partial class _default : System.Web.UI.Page, IPostBackEventHandler
3.and in your .cs in page_load add this line:
this.ClientScript.GetPostBackEventReference(this, string.Empty);
4.don't forget to implement the interface:
public void RaisePostBackEvent(string eventArgument)
{
if (eventArgument == "do_something_good")
{
//bla
}
}
And guess what - it even works!
#Subhash Dike - The PageMethods works only for static methods, AFAIK.
Add EnableEventValidation="false" into your <%Page tag to solve __doPostBack problem

Getting and setting form values client side with javascript, json and jquery

I am building out an ajax enabled UI using webforms in asp.net. I really want this interaction to be extremely light. What I would like to do is make a call to get the data and then bind it to my form client side.
Here is my working example.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Page</title>
<script type="text/javascript" src="http://jqueryui.com/jquery-1.3.2.js"></script>
<style type="text/css">
body { font-family: Arial; font-size:10px; }
#formRow label { display:block;}
#formRow input { display:block; margin-bottom: 10px;}
</style>
<script type="text/javascript">
(function ($) {
$.formUtil = {
bind: function (row, entity) {
for (property in entity) {
//take the property name and put it together with the entity and eval it
var propertyValue = entity[property];
//take the property name and use it to build a selector to go find the input value in the form
//need a switch to be able to determine different element types
$(row).find('#' + property).val(propertyValue);
}
},
reverseBind: function (row, entity) {
for (property in entity) {
//Get the value from the target form element
entity[property] = $(row).find('#' + property).val();
alert(entity[property]);
}
}
};
})(jQuery);
//Create an object to fill the form in with
//This will not be needed once there is a web service call to get the object
function detailItem() {
this.name = "Widget 123";
this.description = "Some wonderful description";
this.category = "2";
}
//Define the detail object on a global scale so that later it can be used to set the values into in reverse bind
var detail = null;
$(document).ready(function () {
detail = new detailItem();
$.formUtil.bind('#formRow', detail); //Initial bind for page load
});
</script>
</head>
<body>
<div id="formRow">
<label>Name:</label>
<input type="text" id="name" /><!--Notice the id is he same as the field name in the object-->
<label>Description:</label>
<input type="text" id="description" /><!--Notice the id is he same as the field name in the object-->
<label>Category:</label>
<select id="category">
<option value="1">Apples</option>
<option value="2">Oranges</option>
<option value="3">Banannas</option>
</select>
<input type="button" onclick="$.formUtil.reverseBind($(this).parents('div').get(0), detail)" value="Get Data From Form" />
</div>
</body>
</html>
My question is: Is there a better way to do this already? Because the JSon object's properties are all variant type how should I best communicate what type I am working with so that if I am binding the data to a select I can eval the correct jquery?
What are your general feelings about this code? Good? Bad?
Edit: I replaced eval with entity[property]
Edit: Used namespace suggestion
Edit: Altered the selector so that it would work with any form element
If it were me i would namespace your function instead of haveing them free floating:
(function($){
$.myNamespace = {
bind = function(row, entity){},
reverseBind = function(row, entity){}
};
})(jQuery);
$(document).ready(function () {
detail = new detailItem();
/* note i pass in a selector instead of the jQ node list - IMO using jQ on the selector
should be done and verified within the functions not as part of the argument. */
$.myNamespace.bind('#formRow', detail);
});

Categories