Calling a view on click of the kendo context menu in MVC5 - asp.net-mvc-5

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;
}
}

Related

how to pass along structure property via similar method to Bixby onclick

In a Bixby result-view on the Detail mode I want to provide the user with the option to select from one or more Actions and pass along a hidden parameter "identifier" that corresponds to a database field name to include in the http request made by the Action.
layout {
match: AltBrainsData (this)
mode (Details)
content{
section {
content {
image {
//aspect-ratio (16:9)
url {
template ("#{value(this.icon_image)}")
}
}
}
}
section {
content {
title-area {
slot1 {
text("[#{value(this.name)}]")
{style(Title_M)}
}
}
}
}
section {
content {
paragraph { value ("#{value(this.description)}") style (Detail_L) }
}
}
section {
content {
cell-card {
slot2 {
content {
order (PrimarySecondary)
primary ("Show me the latest news headlines")
}
}
on-click {
intent {
goal: altbrains.persistencetest.GetNews
value: altbrains.persistencetest.AltBrainsData("#{value(this.identifier)}")
}
}
}
}
}
...
I get an error saying that the value must be a primitive.
How can I accomplish this? Basically, I want the result "Detail" card to be populated with one or more possible Actions and each action should pass along this identifier to the corresponding function in code/.
A bit difficult to include all the necessary bits and pieces in Stack Overflow. The money part of the GetNews function is:
function getNews(AltBrainsData) {
const url = properties.get("config", "baseUrl") + "content"
console.log("i got this far and the url is ", url);
const query = {
apikey: properties.get("secret", "apiKey"),
q: "{\"" + "identifier" + "\":\"" + AltBrainsData.identifier + "\"}"
}
Change to the following:
on-click {
intent {
goal: altbrains.persistencetest.GetNews
value: $expr(this)
}
}
You can read more about $expr() syntax in expression language

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.

Identify true activeElement in a frame hierarchy

I'm looking for a way to get the focused input of any page with the goal to update it's value.
I have a content script that receives the value and checks if activeElement is an <input>.
The challenge is when the main document's activeElement is an iframe. I can set all_frames: true in manifest, which will find any active <input>, but I only want to set the value of the activeElement of the active iframe.
Currently I'm solving this by letting the child content script(s) blur() all activeElements except the current one (attaching a handler to focusin), but a solution that does not modify the document state would be better imho.
Is it possible to send a message only to the main document and if this one's activeElement is an iframe, get that frameId (and try again)?
I don't control the web pages.
Inject a new content script that checks the full hierarchy of frames, including cross-domain frames.
main content script asks the background/event page if needed:
if (document.activeElement.matches('input') && window == parent) {
console.log('Input', document.activeElement);
document.activeElement.value += ' gotcha!';
} else {
chrome.runtime.sendMessage({action: 'modifyInput'});
}
background/event page script executes the additional content script in all frames:
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse)) {
if (msg.action == 'modifyInput') {
chrome.tabs.executeScript(sender.tab && sender.tab.id, {
file: 'modify-input.js',
allFrames: true,
matchAboutBlank: true,
runAt: 'document_end',
});
}
});
modify-input.js, IIFE is used to makes sure garbage collection removes the injected stuff.
;(function() {
if (isInputActive()) {
if (window == parent) {
foundTheInput();
} else {
askParent();
}
} else if (isFrameActive()) {
window.addEventListener('message', function onMessage(e) {
if (!e.data || e.data.id != chrome.runtime.id)
return;
switch (e.data.action) {
// request from a child frame
case 'checkme':
if (window == parent) {
confirmChild(e.source);
window.removeEventListener('message', onMessage);
} else {
askParent();
}
break;
// response from a parent
case 'confirmed':
window.removeEventListener('message', onMessage);
if (isInputActive()) {
foundTheInput();
} else if (isFrameActive()) {
confirmChild(e.source);
}
break;
}
});
}
function isInputActive() {
return document.activeElement.matches('input');
}
function isFrameActive() {
return document.activeElement.matches('frame, iframe');
}
function askParent() {
parent.postMessage({id: chrome.runtime.id, action: 'checkme'}, '*');
}
function confirmChild(childWindow) {
console.log('Frame', document.activeElement);
childWindow.postMessage({id: chrome.runtime.id, action: 'confirmed': true}, '*');
}
function foundTheInput() {
console.log('Input', document.activeElement);
document.activeElement.value += ' gotcha!';
}
})();
I didn't test this, but did use and saw similar code previously.

Add tab to the tabpanel on mvc

I have a menu and some menu items.when I clcik to menu item I create new panle codebehind and add it to main tabpanel.so far so good ,but it seems for every click on the menu,panel created from the begining,plus,change place of the the tabs.how can I solve this.
here is the my Index.cshtml
<body>
#Html.X().ResourceManager()
#(
Html.X().Viewport()
.Layout(LayoutType.Border)
.Items(
Html.X().Panel()
.Region(Region.West)
.Title("main menu")
.Width(200)
.Collapsible(true)
.Split(true)
.MinWidth(175)
.MaxWidth(400)
.MarginSpec("5 0 5 5")
.Layout(LayoutType.Accordion)
.Items(
Html.X().MenuPanel()
.Collapsed(true)
.Icon(Icon.Note)
.AutoScroll(true)
.Title("menu")
.ID("PNL34")
.BodyPadding(0)
.Menu(menu => {
menu.Items.Add(Html.X().MenuItem().ID("1a").Text("test1").Icon(Icon.Anchor)
.DirectEvents(m => { m.Click.Url = "Desktop/AddTab";
m.Click.ExtraParams.Add(new { conid = "TabPanel1" ,pnlid="tabpnl10",viewname="Urunler"});
}));
menu.Items.Add(Html.X().MenuItem().ID("2a").Text("test2").Icon(Icon.Anchor)
.DirectEvents(m =>
{
m.Click.Url = "Desktop/AddTab";
m.Click.ExtraParams.Add(new { conid = "TabPanel1", pnlid = "tabpnl11", viewname = "Siparisler" });
}));
})
)
,
Html.X().TabPanel()
.ID("TabPanel1")
.Region(Region.Center)
.Title("E-TICARET")
.MarginSpec("5 5 5 0")
))
and codebehind controller
public ActionResult AddTab(string conid,string pnlid,string viewname)
{
var cmp = this.GetCmp<Panel>(pnlid);
var cmp2 = this.GetCmp<TabPanel>(conid);
if (cmp.ActiveIndex==-1)
{
var result = new Ext.Net.MVC.PartialViewResult
{
ViewName = viewname,
ContainerId = conid,
RenderMode = RenderMode.AddTo,
WrapByScriptTag = false
};
cmp2.SetActiveTab(pnlid);
return result;
}
else
{
return null;
}
}
This is not going to work.
if (cmp.ActiveIndex == -1)
In WebForms it is retrieved from the Post data. There is no a WebForms-like Post in MVC. You should send all the required information with a request.
Also if you don't need a tab to be rendered if it is already exists, just stop a request. You can determine on client if a tab is already there or not.

Attach a Javascript function to an OOTB ribbon button

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');

Resources