Outlook add in On-Send event is firing - outlook

Im trying to get a simple function to append some data to the mail body using the on-send function.
in my manifest file, I have this setting the extension point
<ExtensionPoint xsi:type="Events">
<Event Type="ItemSend" FunctionExecution="synchronous" FunctionName="setItemBody" />
</ExtensionPoint>
my javascript is taken from https://learn.microsoft.com/en-us/office/dev/add-ins/outlook/outlook-on-send-addins?tabs=windows
function validateBody(event) {
console.log('validateBody');
item.body.getAsync("html", { asyncContext: event }, checkBodyOnlyOnSendCallBack);
}
// <param name="asyncResult">MessageSend event passed from the calling function.</param>
function checkBodyOnlyOnSendCallBack(asyncResult) {
var listOfBlockedWords = new Array("blockedword", "blockedword1", "blockedword2");
var wordExpression = listOfBlockedWords.join('|');
// \b to perform a "whole words only" search using a regular expression in the form of \bword\b.
// i to perform case-insensitive search.
var regexCheck = new RegExp('\\b(' + wordExpression + ')\\b', 'i');
var checkBody = regexCheck.test(asyncResult.value);
if (checkBody) {
mailboxItem.notificationMessages.addAsync('NoSend', { type: 'errorMessage', message: 'Blocked words have been found in the body of this email. Please remove them.' });
// Block send.
asyncResult.asyncContext.completed({ allowEvent: false });
}
// Allow send.
asyncResult.asyncContext.completed({ allowEvent: true });
}
But when i hit send on the email i just keep getting 'The add-in has prevented this item from being sent.'
and looking in the browser debugger i cannot see that it has written out the console.log in the validateBody event.
Any body any ideas what I have done wrong?

As an update to this, as I have now solved it, its due to where the called function (in my case setItemBody) resides in your Function.js (or what ever is set as your function file)
The method being called by the ItemSend needs to be at the very root, even before the Office.initialize function. This at least solved it for me as I found it by reading this article https://theofficecontext.com/2017/06/12/the-most-anticipated-officejs-feature-is-here/

Related

How to validate user content on real time with ckeditor's accessibility checker?

I am new in using ckeditor and its API. I would like to find a way to validate the content of the users through the accessibility checker while they are typing.
The information available in the documentation do not make clear how to do this.
I'm trying to figure out how to do this...
<script>
var instance = CKEDITOR.replace('editorck');
instance.on('focus', function(event) {
var editor = CKEDITOR.instances['editorck'];
if(editor.plugins.a11ychecker){
var a11ycheckerCommand = new CKEDITOR.command(editor, {
exec: function( editor ) {
editor.execCommand("a11ychecker");
}
});
a11ycheckerCommand.setState(CKEDITOR.TRISTATE_ON);
a11ycheckerCommand.exec(editor);
}
});
instance.on('key', function (event) {
var editor = CKEDITOR.instances['editorck'];
editor.execCommand("a11ychecker.listen");
});
</script>
The code above expects two events. The first is the "onfocus" which activate the accessibility checker when the editor area is focused. The second is what I'm looking for, call some command or execute something to validate the content while keyup event is occuring.
The next step is to allow the user to save the content if it is validated. Perhaps a way to get the current accessibility issues list?
CKEDITOR.plugins.a11ychecker.IssueList or editor.plugins.a11ychecker.IssueList ?

Add or trigger event after inner content to page

I have links on a table to edit or delete elements, that elements can be filtered. I filtered and get the result using ajax and get functions. After that I added (display) the result on the table using inner.html, the issue here is that after filtering the links on the elements not work, cause a have the dojo function like this
dojo.ready(function(){
dojo.query(".delete-link").onclick(function(el){
var rowToDelete = dojo.attr(this,"name");
if(confirm("Really delete?")){
.......
}
});
I need to trigger the event after filtering, any idea?
(I'm assuming that you're using Dojo <= 1.5 here.)
The quick answer is that you need to extract the code in your dojo.ready into a separate function, and call that function at the end of your Ajax call's load() callback. For example, make a function like this:
var attachDeleteEvents = function()
dojo.query(".delete-link").onclick(function(el){
var rowToDelete = dojo.attr(this,"name");
if(confirm("Really delete?")){
.......
}
});
};
Then you call this function both in dojo.ready and when your Ajax call completes:
dojo.ready(function() { attachDeleteEvents(); });
....
var filter = function(someFilter) {
dojo.xhrGet({
url: "some/url.html?filter=someFilter",
handleAs: "text",
load: function(newRows) {
getTableBody().innerHTML = newRows;
attachDeleteEvents();
}
});
};
That was the quick answer. Another thing that you may want to look into is event delegation. What happens in the code above is that every row gets an onclick event handler. You could just as well have a single event handler on the table itself. That would mean there would be no need to reattach event handlers to the new rows when you filter the table.
In recent versions of Dojo, you could get some help from dojo/on - something along the lines of:
require(["dojo/on"], function(on) {
on(document.getElementById("theTableBody"), "a:click", function(evt) {...});
This would be a single event handler on the whole table body, but your event listener would only be called for clicks on the <a> element.
Because (I'm assuming) you're using 1.5 or below, you'll have to do it a bit differently. We'll still only get one event listener for the whole table body, but we have to make sure we only act on clicks on the <a> (or a child element) ourselves.
dojo.connect(tableBody, "click", function(evt) {
var a = null, name = null;
// Bubble up the DOM to find the actual link element (which
// has the data attribute), because the evt.target may be a
// child element (e.g. the span). We also guard against
// bubbling beyond the table body itself.
for(a = evt.target;
a != tableBody && a.nodeName !== "A";
a = a.parentNode);
name = dojo.attr(a, "data-yourapp-name");
if(name && confirm("Really delete " + name + "?")) {
alert("Will delete " + name);
}
});
Example: http://fiddle.jshell.net/qCZhs/1/

jQuery Event when Validation Errors Corrected

I have buttons that trigger jQuery validation. If the validation fails, the button is faded to help draw attention away from the button to the validation messages.
$('#prev,#next').click(function (e)
{
var qform = $('form');
$.validator.unobtrusive.parse(qform);
if (qform.valid())
{
// Do stuff then submit the form
}
else
{
$('#prev').fadeTo(500, 0.6);
$('#next').fadeTo(500, 0.6);
}
That part works fine.
However, I would like to unfade the buttons once the invalid conditions have been cleared.
Is it possible to hook into jQuery Validation to get an appropriate event (without requiring the user to click a button)? How?
Update
Based on #Darin's answer, I have opened the following ticket with the jquery-validation project
https://github.com/jzaefferer/jquery-validation/issues/459
It might sound you strange but the jQuery.validate plugin doesn't have a global success handler. It does have a success handler but this one is invoked per-field basis. Take a look at the following thread which allows you to modify the plugin and add such handler. So here's how the plugin looks after the modification:
numberOfInvalids: function () {
/*
* Modification starts here...
* Nirmal R Poudyal aka nicholasnet
*/
if (this.objectLength(this.invalid) === 0) {
if (this.validTrack === false) {
if (this.settings.validHandler) {
this.settings.validHandler();
}
this.validTrack = true;
} else {
this.validTrack = false;
}
}
//End of modification
return this.objectLength(this.invalid);
},
and now it's trivial in your code to subscribe to this event:
$(function () {
$('form').data('validator').settings.validHandler = function () {
// the form is valid => do your fade ins here
};
});
By the way I see that you are calling the $.validator.unobtrusive.parse(qform); method which might overwrite the validator data attached to the form and kill the validHandler we have subscribed to. In this case after calling the .parse method you might need to reattach the validHandler as well (I haven't tested it but I feel it might be necessary).
I ran into a similar issue. If you are hesitant to change the source as I am, another option is to hook into the jQuery.fn.addClass method. jQuery Validate uses that method to add the class "valid" to the element whenever it is successfully validated.
(function () {
var originalAddClass = jQuery.fn.addClass;
jQuery.fn.addClass = function () {
var result = originalAddClass.apply(this, arguments);
if (arguments[0] == "valid") {
// Check if form is valid, and if it is fade in buttons.
// this contains the element validated.
}
return result;
};
})();
I found a much better solution, but I am not sure if it will work in your scenario because I do not now if the same options are available with the unobtrusive variant. But this is how i did it in the end with the standard variant.
$("#form").validate({
unhighlight: function (element) {
// Check if form is valid, and if it is fade in buttons.
}
});

jquery mobile ajax sends both GET and POST requests

Here is the problem:
By default jQuery Mobile is using GET requests for all links in the application, so I got this small script to remove it from each link.
$('a').each(function () {
$(this).attr("data-ajax", "false");
});
But I have a pager in which I actually want to use AJAX. The pager link uses HttpPost request for a controller action. So I commented the above jQuery code so that I can actually use AJAX.
The problem is that when I click on the link there are two requests sent out, one is HttpGet - which is the jQuery Mobile AJAX default (which I don't want), and the second one is the HttpPost that I actually want to work. When I have the above jQuery code working, AJAX is turned off completely and it just goes to the URL and reloads the window.
I am using asp.net MVC 3. Thank you
Instead of disabling AJAX-linking, you can hijack clicks on the links and decide whether or not to use $.post():
$(document).delegate('a', 'click', function (event) {
//prevent the default click behavior from occuring
event.preventDefault();
//cache this link and it's href attribute
var $this = $(this),
href = $this.attr('href');
//check to see if this link has the `ajax-post` class
if ($this.hasClass('ajax-post')) {
//split the href attribute by the question mark to get just the query string, then iterate over all the key => value pairs and add them to an object to be added to the `$.post` request
var data = {};
if (href.indexOf('?') > -1) {
var tmp = href.split('?')[1].split('&'),
itmp = [];
for (var i = 0, len = tmp.length; i < len; i++) {
itmp = tmp[i].split('=');
data.[itmp[0]] = itmp[1];
}
}
//send POST request and show loading message
$.mobile.showPageLoadingMsg();
$.post(href, data, function (serverResponse) {
//append the server response to the `body` element (assuming your server-side script is outputting the proper HTML to append to the `body` element)
$('body').append(serverResponse);
//now change to the newly added page and remove the loading message
$.mobile.changePage($('#page-id'));
$.mobile.hidePageLoadingMsg();
});
} else {
$.mobile.changePage(href);
}
});
The above code expects you to add the ajax-post class to any link you want to use the $.post() method.
On a general note, event.preventDefault() is useful to stop any other handling of an event so you can do what you want with the event. If you use event.preventDefault() you must declare event as an argument for the function it's in.
Also .each() isn't necessary in your code:
$('a').attr("data-ajax", "false");
will work just fine.
You can also turn off AJAX-linking globally by binding to the mobileinit event like this:
$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
Source: http://jquerymobile.com/demos/1.0/docs/api/globalconfig.html

Event removal in Mootools, and syntax of event addition

So I have been adding my events thusly:
element.addEvent('click', function() {
alert('foobar');
});
However, when attempting to remove said event, this syntactically identical code (with "add" switched to "remove") does not work.
element.removeEvent('click', function() {
alert('foobar');
});
I assume this is because the two functions defined are not referenced the same, so the event is not technically removed. Alright, so I redefine the event addition and removal:
element.addEvent('click', alert('foobar'));
element.removeEvent('click', alert('foobar'));
Which works great, except now when the page loads, the click event is fired even before it's clicked!
The function is removed, though, which is great......
update: when you do .addEvent('type', function(){ }) and .removeEvent('type', function(){ }), even though the functions may have the same 'signatures', they are two separte anonymous functions, assigned on the fly. function 1 is !== to function 2 - hence there is no match when MooTools tries to remove it.
to be able to remove an exact handler, o:
function handler(){ ... }
el.addEvent('click', handler);
// .. later
el.removeEvent('click', handler);
Internally, events are actually a map of keys to functions in element storage. have a look at this fiddle i did a while back for another SO question - http://www.jsfiddle.net/mVJDr/
it will check to see how many events are stacked up for a particular event type on any given element (or all events).
similarly, removeEvent looks for a match in the events storage - have a look on http://jsfiddle.net/dimitar/wLuY3/1/. hence, using named functions like Nikolaus suggested allows you to remove them easily as it provides a match.
also, you can remove events via element.removeEvents("click") for all click events.
your page now alerts because you pass on alert as the function as well as execute it with the params 'foobar'. METHOD followed by () in javascript means RUN THE METHOD PRECEDING IT IMMEDIATELY, NOT LATER. when you bind functions to events, you pass the reference (the method name) only.
to avoid using an anonymous function and to pass argument,s you can do something like:
document.id('foobar').addEvent('click', alert.bind(this, 'foo'));
as bind raps it for you, but removing this will be even more complicated.
as for event delegation, it's:
parentEl.addEvents({
"click:relay(a.linkout)": function(e, el) {
},
"mouseover:relay(li.menu)": function(e, el) {
}
});
more on that here http://mootools.net/docs/more/Element/Element.Delegation#Element:removeEvent
keep in mind it's not great / very stable. works fine for click stuff, mouseenter is not to be used delegated, just mouseover - which means IE can fire mouseout when it should not. the way i understand it, it's coming improved in mootools 2.0
edit updating to show an example of bound and unbound method within a class pattern in mootools
http://www.jsfiddle.net/wmhgw/
var foo = new Class({
message: "hi",
toElement: function() {
return this.element = new Element("a", {
href: "http://www.google.com",
text: "google",
events: {
"click": this.bar.bind(this), // bind it
"mouseenter": this.bar // unbound -> this.element becomes this
}
});
},
bar: function(event) {
event.stop();
// hi when bound to class instance (this.message will exist)
// 'undefined' otherwise.
console.log(this.message || "undefined");
}
});
document.id(new foo()).inject(document.body);
the mouseenter here will be unbound where this will refer to the default scope (i.e the element that triggered the event - the a href). when bound, you can get the element via event.target instead - the event object is always passed on to the function as a parameter.
btw, this is a slightly less familiar use of class and element relation but it serves my purposes here to illustrate binding in the context of classes.
assig the function to a variable and use the same reference to add and remove the event.
if you use an anonymous function you will get to different references
var test = function(){ alert('test: ' + this.id); }
$('element').addEvent('click', test);
...
$('element').removeEvent('click', test);
addEvent : Attaches an event listener to a DOM element.
Example -
$('myElement').addEvent('click', function(){
alert('clicked!');
});
removeEvent : Works as Element.addEvent, but instead removes the specified event listener.
Example -
var destroy = function(){ alert('Boom: ' + this.id); } // this refers to the Element.
$('myElement').addEvent('click', destroy);
//later...
$('myElement').removeEvent('click', destroy);
This means when you add an event with a eventhandler not an anonymous function if you than remove the event than it will be removed.

Resources