Attach a Javascript function to an OOTB ribbon button - sharepoint

I want to attach a custom javascript function to the out of the box "Download a copy" ribbon button. This is to provide analytics for file downloads done through the ribbon button.
I tried this code, but it doesn't seem to work:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js">
</script>
<script>
_spBodyOnLoadFunctionNames.push("Trackdownloads");
function Trackdownloads(){
debugger;
$("a[id='Ribbon.Documents.Copies.Download-Large']").live( "click",
function() {
alert('hello');
}
);
}
</script>
Any idea how to get this to work?

Found a solution to my problem.
Actually, attaching a javascript function to the button is not the right way to implement this.
The correct implementation is to replace the OOTB button with a custom button, and call a custom javascript function to carry out the desired action.
http://msdn.microsoft.com/en-us/library/ff407619.aspx

If you do want to override a button in the ribbon. Creating a custom Page Component is a good idea. Example:
Type.registerNamespace('Company.Project.Ribbon.PageComponent');
Company.Project.Ribbon.PageComponent = function (PageComponentId) {
this._pageComponentId = PageComponentId;
Company.Project.Ribbon.PageComponent.initializeBase(this);
}
Company.Project.Ribbon.PageComponent.prototype =
{
_pageComponentId: "PageComponentIDHolder",
getId: function () {
return this._pageComponentId;
},
init: function () {
this._myCommandList = ['DownloadCopy'];
this._myHandledCommands = {};
this._myHandledCommands['DownloadCopy'] = Function.createDelegate(this, this.CMD1_Handler);
},
getFocusedCommands: function () {
return this._myCommandList;
},
getGlobalCommands: function () {
return this._myCommandList;
},
canHandleCommand: function (commandId) {
var canHandle = this._myHandledCommands[commandId];
if (canHandle)
return true;
else
return false;
},
handleCommand: function (commandId, properties, sequence) {
return this._myHandledCommands[commandId](commandId, properties, sequence);
},
isFocusable: function () {
return true;
},
CMD1_Handler: function (commandId, properties, sequence) {
alert('Download a copy-button was clicked');
}
}
Company.Project.Ribbon.PageComponent.registerClass('Company.Project.Ribbon.PageComponent', CUI.Page.PageComponent)
NotifyScriptLoadedAndExecuteWaitingJobs("/_layouts/custompagecomponents/PageComponent.js");
function init2() {
var instance = new Company.Project.Ribbon.PageComponent("ComponentID");
SP.Ribbon.PageManager.get_instance().addPageComponent(instance);
}
function init1() {
ExecuteOrDelayUntilScriptLoaded(init2, 'sp.ribbon.js');
}
ExecuteOrDelayUntilScriptLoaded(init1, '/_layouts/custompagecomponents/PageComponent.js');

Related

Click on something that's not a sprite

I'm tryng to handle a click event that does not clicked on a sprite.
My first aproach would be handling normal JS events:
class EditorListener {
constructor(editor) {
...
if(window) {
window.addEventListener('click', this.onWindowClick.bind(this));
}
}
onWindowClick(event) {
if(event.target && event.target.tagName == 'CANVAS') {
Events.fire(EventType.CLICK_NOWHERE);
}
}
}
...
The problem is that this is called when I click sprites.
The goal is to simply close a dialog when I click nowhere.
Tap anywhere and run the function:
game.input.onTap.add(onTap, this);
function onTap(pointer)
{
}
Tap on these objects and run the function onDown
// enable input for some objects
yourObject1.inputEnabled = true;
yourObject2.inputEnabled = true;
yourObject1.events.onInputDown.add(onDown, this);
yourObject2.events.onInputDown.add(onDown, this);
function onDown(object, pointer)
{
// on down function
}

How to define different context menus for different objects in autodesk forge

I want to define different context menus for different objects in forge viewer,this is my code
viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT,function(e){
if(viewer.getSelection().length==0){return;}
var selectId=viewer.getSelection()[0];
viewer.search("Cabinet",function(ids){
if(ids.indexOf(selectId)!=-1){
viewer.registerContextMenuCallback('CabinetMsg', function (menu, status) {
if (status.hasSelected) {
menu.push({
title: "CabinetMsg",
target: function () {
openLayer('CabinetMsg','954','775','CabinetMsg.html')
}
});
}
});
}else{
viewer.registerContextMenuCallback('CabinetMsg', function (menu, status) {
if (status.hasSelected) {
menu.forEach(function(el,index){
if(el.title=="CabinetMsg"){
menu.splice(menu.indexOf(index),1)
}
})
}
});
}
})
});
But push elements to the array is always later than the context menus show. My custom context menu is always show when I select another object. What I can do?
The codes you provided will create 2 new sub items to the context menu. Here is a way for this case, i.e. you have to write your own ViewerObjectContextMenu. In addition, you need do hitTest in ViewerObjectContextMenu.buildMenu to get dbId selected by the mouse right clicking. Here is the example for you:
class MyContextMenu extends Autodesk.Viewing.Extensions.ViewerObjectContextMenu {
constructor( viewer ) {
super( viewer );
}
isCabinet( dbId ) {
// Your logic for determining if selected element is cabinet or not.
return false;
}
buildMenu( event, status ) {
const menu = super.buildMenu( event, status );
const viewport = this.viewer.container.getBoundingClientRect();
const canvasX = event.clientX - viewport.left;
const canvasY = event.clientY - viewport.top;
const result = that.viewer.impl.hitTest(canvasX, canvasY, false);
if( !result || !result.dbId ) return menu;
if( status.hasSelected && this.isCabinet( result.dbId ) ) {
menu.push({
title: 'CabinetMsg',
target: function () {
openLayer( 'CabinetMsg', '954', '775', 'CabinetMsg.html' );
}
});
}
return menu;
}
}
After this, you could write an extension to replace default viewer context menu with your own menu. Here also is the example:
class MyContextMenuExtension extends Autodesk.Viewing.Extension {
constructor( viewer, options ) {
super( viewer, options );
}
load() {
this.viewer.setContextMenu( new MyContextMenu( this.viewer ) );
return true;
}
unload() {
this.viewer.setContextMenu( new Autodesk.Viewing.Extensions.ViewerObjectContextMenu( this.viewer ) );
return true;
}
}
Hope this help.

Chrome Extension - Background Script notified whenever another page updates

I'm making a Chrome Extension that gets the DOM of a closed tab and updates the popup.html. So far so good, I can do that through the background script using XMLHttpRequest.
However, I would like my popup to be updated if the closed page is updated. I was thinking of running a timer in the background script to check every 10 sends or so, but I was wondering if XMLHttpRequest has a way of knowing when its page updates? Or even if the timer would work, I couldn't get it working
I've added the relevant files below. Any help is appreciated
popup.html
<body>
<h1>Agile Board Viewer</h1>
<div class="wrapper">
<button id="mainButton">Click me</button>
<p id="testingDisplay">test</p>
</div>
</body>
popup.js
document.addEventListener('DOMContentLoaded', function () {
document.getElementById("mainButton").addEventListener('click', function () {
chrome.runtime.sendMessage({
method : 'POST',
action : 'xhttp',
url : '//My url//',
data : 'q=something'
}, function (responseText) {
document.getElementById("testingDisplay").innerHTML = responseText;
});
});
});
background.js
I've deleted some lines that are pointless (I think) to avoid clutter, just error handlers and what not, also got rid of my attempt at a timer. Basically, what it does is takes a string from the DOM and sends it to the popup. I would like that popup to update whenever the string does.
var testingString = "Testing (";
chrome.runtime.onMessage.addListener(function (request, sender, callback) {
if (request.action == "xhttp") {
`var xhttp = new XMLHttpRequest();
xhttp.onload = function () {
var testingValue = xhttp.responseText.substring(xhttp.responseText.indexOf(testingString), xhttp.responseText.indexOf(testingString) + 16);
callback(testingValue);
//callback(xhttp.responseText);
};
}
});
Sorry if the formatting is a mess, I'm not too well versed on this
Just to follow up, I've solved my issue by using a timer that checks the closed tab every couple of seconds. If the label that lists the number of items in my Testing column is different, I get my notification. Still learning XHR so I'm hoping I can improve on this again but for now, I'm happy enough. Only works for 20 seconds in my example, as I don't want an infinite timer. Will put in an off switch later
var testingString = "Testing (";
var testBuffer = "";
var i = 0;
chrome.runtime.onMessage.addListener(function (request, sender, callback) {
if (request.action == "xhttp") {
var xhttp = new XMLHttpRequest();
var method = request.method ? request.method.toUpperCase() : 'GET';
var testingValue = xhttp.responseText.substring(xhttp.responseText.indexOf(testingString), xhttp.responseText.indexOf(testingString) + 16);
function startTimer() {
window.setTimeout(function () {
if (i < 20) {
xhttp.open(method, request.url, true);
xhttp.onload = function () {
testBuffer = testingValue;
testingValue = xhttp.responseText.substring(xhttp.responseText.indexOf(testingString), xhttp.responseText.indexOf(testingString) + 16);
if (testBuffer != testingValue) {
notification = new Notification('New Item in Testing Column', {
body : "You have a new item in Testing",
});
console.log(testingValue);
}
};
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4 && xhttp.status == 200) {
callback(testingValue);
}
};
xhttp.onerror = function () {
alert("error");
callback();
};
if (method == 'POST') {
xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
xhttp.send(request.data);
console.log("count");
i++;
startTimer();
}
}, 5000);
}
startTimer();
return true;
}
});

Calling a view on click of the kendo context menu in MVC5

I am have implemented a kendo context menu and grid on my MVC 5 page. I need to navigate to another page on click of edit by passing the requestid to it. When I try to call the #{Html.RenderAction("NewRequest_Read", "Request");} it loads the view upfront along with view contains the context menu. Could somebody tell me how do I go about it
Context Menu
#(Html.Kendo().ContextMenu()
.Name("RequestMenu")
.Target("#GridRequest")
.Filter("tr")
.Orientation(ContextMenuOrientation.Vertical)
.Animation(animation =>
{
animation.Open(open =>
{
open.Fade(FadeDirection.In);
open.Duration(500);
});
})
.Items(items =>
{
items.Add()
.Text("Edit");
items.Add()
.Text("Cancel");
})
.Events(e =>
{
e.Select("onSelect");
})
)
Script
function onSelect(e) {
var grid = $("#GridTeam").data("kendoGrid");
switch ($(e.item).children(".k-link").text()) {
case "Edit":
#{Html.RenderAction("NewRequest_Read", "Request");}
break;
case "Cancel":
grid.removeRow(e.target);
break;
}
}
Controller method
public ActionResult NewRequest_Read(string id)
{
NewRequestViewModel newReqeustViewModel = new NewRequestViewModel();
return View("NewRequestView", newReqeustViewModel);
}
function onSelect(e) {
var grid = $("#GridTeam").data("kendoGrid");
switch ($(e.item).children(".k-link").text()) {
case "Edit":
window.location.href = '#Url.Action("NewRequest_Read", "Request", new { id = //add request id parameter here })';
break;
case "Cancel":
grid.removeRow(e.target);
break;
}
}

FabricJS double click on objects

I am trying to perform a special action whenever the user double clicks any object located inside the canvas. I have read the docs and not found any mouse:dblclick-like event in the documentation. I tried doing something like:
fabric.util.addListener(fabric.document, 'dblclick', callback);
Which does trigger the dblclick event but does not give specific information about the actual object that is being clicked on the canvas.
Any ideas of the most FabricJS-y way of doing this?
The more elegant way is to override fabric.Canvas._initEventListeners to add the dblclick support
_initEventListeners: function() {
var self = this;
self.callSuper('_initEventListeners');
addListener(self.upperCanvasEl, 'dblclick', self._onDoubleClick);
}
_onDoubleClick: function(e) {
var self = this;
var target = self.findTarget(e);
self.fire('mouse:dblclick', {
target: target,
e: e
});
if (target && !self.isDrawingMode) {
// To unify the behavior, the object's double click event does not fire on drawing mode.
target.fire('object:dblclick', {
e: e
});
}
}
I've also developed a library to implement more events missed in fabricjs : https://github.com/mazong1123/fabric.ext
This is similar to #LeoCreer's answer but actually gets access to the targeted object
fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (e) {
var target = canvas.findTarget(e);
});
The Correct way to add custom events to Fabric.js
window.fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function (event, self) {
yourFunction(event);
});
or use fabric.ext
I'm using this workaround:
var timer = 0;
canvas.item(0).on('mouseup', function() {
var d = new Date();
timer = d.getTime();
});
canvas.item(0).on('mousedown', function() {
var d = new Date();
if ((d.getTime() - timer) < 300) {
console.log('double click')
}
});
Here is a quick and easy way to add a double click event handler to Fabric JS -
Include following code snippet to your html file. Just ensure this is loaded after the main fabric.js library
<script type="text/javascript">
fabric = (function(f) { var nativeOn = f.on; var dblClickSubscribers = []; var nativeCanvas = f.Canvas; f.Canvas = (function(domId, options) { var canvasDomElement = document.getElementById(domId); var c = new nativeCanvas(domId, options); c.dblclick = function(handler) { dblClickSubscribers.push(handler) }; canvasDomElement.nextSibling.ondblclick = function(ev){ for(var i = 0; i < dblClickSubscribers.length; i++) { console.log(ev); dblClickSubscribers[i]({ e :ev }); } }; return c; }); return f; }(fabric));
</script>
Then add this code to listen a double click event:
canvas.dblclick(function(e) {
});
To get information about the actual object that is being clicked on the canvas, use following method -
canvas.getActiveObject();
eg.
canvas.dblclick(function(e) {
activeObject = canvas.getActiveObject();
});
I am late but now fabricjs has mousedblclick event.
Listed at: http://fabricjs.com/docs/fabric.Object.html
See all events:
http://fabricjs.com/events

Resources