Get kendo MVC grid Row data while clicking image icon inside row - kendo-grid

please find above image. in above image for first record there is a history image is there. for second row there is no history image.
so here is my requirement.
when i click that history icon i want to pass resource name, dept, project, charge description to action and get history values for that record. and i want to display those history values in grid in model pop up. here in my handler method how can i get current kendo grid row data.
below is my code.
columns.Bound(p => p.HoursYTD).Width(70).Filterable(false).Editable("function() {return false;}").ClientFooterTemplate("#=kendo.toString(sum, '0,0')#").HtmlAttributes(new { style = "font-weight: bold; text-align: center;" })
.HeaderHtmlAttributes(new { style = "white-space: normal; text-align: center;font-weight: bold;" }).
ClientTemplate("#= DisplayImage(data) #");
<script>
function DisplayImage(product) {
//alert(product.IsHistory);
//alert(product.HoursYTD);
//var action = '#Url.Action("ProductDetails", "Product")';
if (product.IsHistory=="Yes")
var html = kendo.format(product.HoursYTD +"<img src='/Images/" + product.IsHistory + ".png' height='22' width='22' onclick='myHandler(event)'");
else
var html = kendo.format("<div>"+product.HoursYTD+"</div>");
return html;
}
function myHandler(e) {
alert("hello");
}
</script>

Accessing the underlying data item happens by passing the TR HTML element to the dataItem() method of the grid:
function myHandler(e) {
var row = $(e.target).closest("tr");
var dataItem = $("#grid").getKendoGrid().dataItem(row); // swap 'grid' with the name of your grid
// access properties via dataItem.FieldName;
}

Related

Is it possible to view a list of all objects used in Google Slides?

When some objects in Google Slides get hidden behind another object it may be later hard to find them on the slide.
Is it possible, for example, to see a panel with a list of all objects which are present on a given slide? And possibly edit them even if they are in the bottom layer (completely hidden behind another object)? This might be useful for animations when an object is displayed later and fully covers a previously displayed object.
Your goal I believe is as follows.
Your Google Slides has several text boxes of the same size and the same position.
You want to retrieve the list of texts from the text boxes and want to change the texts using a simpler method.
In this case, I thought that when the sidebar created by Google Apps Script is used for changing the texts, your goal might be able to be simply achieved.
The sample script is as follows.
Usage:
1. Prepare script:
Please copy and paste the following script to the script editor of Google Slides and save the script. And then, please reopen the Google Slides. By this, the custom menu "sample" is created for the Google Slides. When "RUN" in the custom menu "sample" is opened, the script is run.
Code.gs
Please copy and paste this script as Code.gs.
function onOpen() {
SlidesApp.getUi().createMenu("sample").addItem("RUN", "openSidebar").addToUi();
}
function openSidebar() {
const html = HtmlService.createHtmlOutputFromFile("index").setTitle("sample");
SlidesApp.getUi().showSidebar(html);
}
function getSelectedShapes() {
const select = SlidesApp.getActivePresentation().getSelection();
const pageElementRange = select.getPageElementRange();
if (pageElementRange) {
const obj = pageElementRange.getPageElements().reduce((ar, e) => {
if (e.getPageElementType() == SlidesApp.PageElementType.SHAPE) {
const shape = e.asShape();
ar.push({objectId: shape.getObjectId(), text: shape.getText().asString().trim()});
}
return ar;
}, []).reverse();
return obj;
}
return [];
}
function updatedTexts(o) {
const select = SlidesApp.getActivePresentation().getSelection();
const slide = select.getCurrentPage();
const obj = slide.getShapes().reduce((o, e) => Object.assign(o, {[e.getObjectId()]: {shape: e, text: e.getText().asString().trim()}}), {});
o.forEach(({objectId, text}) => {
if (obj[objectId] && obj[objectId].text != text) {
obj[objectId].shape.getText().setText(text);
}
});
return "Done";
}
index.html
Please copy and paste this script as index.html.
<input type="button" id="main" value="Get selected shapes" onClick="main()">
<div id="shapes"></div>
<input type="button" id="update" value="Updated texts" onClick="updatedTexts()" style="display:none">
<script>
function main() {
document.getElementById("main").disabled = true;
document.getElementById("shapes").innerHTML = "";
google.script.run.withSuccessHandler(o => {
if (o.length == 0) {
document.getElementById("update").style.display = "none";
return;
}
const div = document.getElementById("shapes");
o.forEach(({objectId, text}) => {
const input = document.createElement("input");
input.setAttribute("type", "text");
input.setAttribute("id", objectId);
input.setAttribute("value", text);
div.appendChild(input);
});
document.getElementById("update").style.display = "";
document.getElementById("main").disabled = false;
}).getSelectedShapes();
}
function updatedTexts() {
const inputs = document.getElementById("shapes").getElementsByTagName('input');
const obj = [...inputs].map(e => ({objectId: e.id, text: e.value}));
console.log(obj)
google.script.run.withSuccessHandler(e => console.log(e)).updatedTexts(obj);
}
</script>
2. Testing:
Please reopen Google Slides. By this, the custom menu is created. Please open "sample" -> "RUN". By this, the sidebar is opened.
Please select the text boxes on Google Slides.
Click "Get selected shapes" button.
By this, the selected text boxes are retrieved and you can see the texts of text boxes.
Modify the texts.
Click "Updated texts" button.
By this, the modified texts are reflected in the text boxes.
Also, you can see it with the following demonstration movie.
Note:
This is a simple sample script. So please modify the above script and HTML style for your actual situation.
References:
Custom sidebars

Extending native HTML element in Angular 6

I have recently created a native web component which is working well in all browsers. I moved this web component into an Angular 6 application and all works as expected. I then tried to extend a native HTML element which again worked perfectly except when I brought it into my Angular 6 application.
Using the examples from Mozilla I will try and illustrate my issue. Using the following trying to extend a native 'p' element:
// Create a class for the element
class WordCount extends HTMLParagraphElement {
constructor() {
// Always call super first in constructor
super();
// count words in element's parent element
var wcParent = this.parentNode;
function countWords(node){
var text = node.innerText || node.textContent
return text.split(/\s+/g).length;
}
var count = 'Words: ' + countWords(wcParent);
// Create a shadow root
var shadow = this.attachShadow({mode: 'open'});
// Create text node and add word count to it
var text = document.createElement('span');
text.textContent = count;
// Append it to the shadow root
shadow.appendChild(text);
// Update count when element content changes
setInterval(function() {
var count = 'Words: ' + countWords(wcParent);
text.textContent = count;
}, 200)
}
}
// Define the new element
customElements.define('word-count', WordCount, { extends: 'p' });
<p is="word-count">This is some text</p>
By taking that same code and putting it into an Angular 6 application, the component never runs. I put console log statements in the constructor and connectedCallback methods and they never trigger. If I remove the {extends: 'p'} object and change the extends HTMLParagraphElement and make it an extend HTMLElement to be an autonomous custom element everything works beautifully. Am I doing something wrong or does Angular 6 not support the customized built-in element extension?
I assume the reason is the way that Angular creates those customized built-in elements when parsing component templates - it probably does not know how to properly do that. Odds are it considers is a regular attribute which is fine to add after creation of the element (which it isn't).
First creating the element and then adding the is-attribute will unfortunately not upgrade the element.
See below example: div#d has a non-working example of that customized input.
customElements.define('my-input', class extends HTMLInputElement {
connectedCallback() {
this.value = this.parentNode.id
this.parentNode.classList.add('connected')
}
}, {
extends: 'input'
})
document.addEventListener('DOMContentLoaded', () => {
b.innerHTML = `<input type="text" is="my-input">`
let el = document.createElement('input', {
is: 'my-input'
})
el.type = 'text'
c.appendChild(el)
// will not work:
let el2 = document.createElement('input')
el2.setAttribute('is', 'my-input')
el2.type = 'text'
d.appendChild(el2)
})
div {
border: 3px dotted #999;
padding: 10px;
}
div::before {
content: "#"attr(id)" ";
}
.connected {
background-color: lime;
}
<div id="a"><input type="text" is="my-input"></div>
<div id="b"></div>
<div id="c"></div>
<div id="d"></div>
So to get it to work with Angular, hook into the lifecycle of your Angular component (e.g. onInit() callback) and pick a working way to create your element there.

How to dynamically change images using Metaio

I have just start learning Metaio. I am working on a simple development test project.
I have so far made the tracking sheet, put image and two arrows (buttons) which means next image and previous image.
For testing I made one of the buttons to display the image and the other for hiding the image. All this works fine so far.
My question is when I added extra images how can I shift the images dynamically back and forward using my next and previous buttons?
My testing code:
button2.onTouchStarted = function () {
image1.hide();
};
button1.onTouchStarted = function () {
image1.display();
};
It can be done different ways, I suggest you to use arel.Scene.getObject and put your image names inside array and each time you click next or previous you count the array key up or down.
I assume you are using Metaio Creator editor.
You have to added codes 3 different places:
Previous (left arrow button)
button1.onTouchStarted = function () {
if (currentImageIndex == firstImageIndex) {
return;
}
arel.Scene.getObject(imageArray[currentImageIndex]).hide();
currentImageIndex--;
arel.Scene.getObject(imageArray[currentImageIndex]).display();
globalsVar['currentImageIndex'] = currentImageIndex;
};
Next (right arrow button)
button2.onTouchStarted = function () {
if (currentImageIndex == lastImageIndex) {
return;
}
arel.Scene.getObject(imageArray[currentImageIndex]).hide();
currentImageIndex++;
arel.Scene.getObject(imageArray[currentImageIndex]).display();
globalsVar['currentImageIndex'] = currentImageIndex;
};
On your Global Script
var imageArray = ["image1", "image2"]; // and so on extra image names
var firstImageIndex = 0;
var lastImageIndex = imageArray.length - 1;
var currentImageIndex = firstImageIndex;
globalsVar = {};
arel.Scene.getObject(imageArray[currentImageIndex]).display();

List of elements gets overridden in angular js when using in dropdown

I want to show a hierarchy like in the image. I am able to create this hierarchy and I want to show the second level elements in a dropdown. However, while doing this the hierarchy value gets overrided with dropdown value and hence I am not able to show the third level of hierarchy.
This is my Dropdown html page:
Business Domain
OK
This is my controller:
controller('domainController', ['$scope', '$state', 'DomainNameService', function($scope, $state, DomainNameService) {
$scope.busdomain = DomainNameService.getBusDomainName();
/*For populating the domain values Which I am fetching from service
Attached the json image*/
var domainList=DomainNameService.getBusDomainName();
if(domainList!=null){
domainList[0].childNode.sort();
for (var i = 0; i < domainList[0].childNode.length; i++) {
if (domainList[0].childNode[i].name!=null) {
var name=domainList[0].childNode[i].name;
domainList[0].childNode.splice(i,1,name);//for replacing the object with name as I have to show name in dropdown list
$scope.busdomainname=domainList[0].childNode;//got the list of name but after this my service list also get overrides
$scope.busdomainname.sort();
break;
}
else
{
$scope.busdomainname=$scope.busdomain[0].childNode;//Added for getting business domain list
$scope.busdomainname.sort();
}
}
}
$scope.addSubDomainTree = function(val){
var varType = "busSubDomain";
var domain=[];
var busDomain=$scope.bussubdomain;
var parent = DomainNameService.getDomainName()[0];
//Done some code here to get the hierarchy
DomainNameService.setBusDomain($scope.statements);
$scope.domain.domainName = DomainNameService.getBusDomainName[0];
$state.go('BusDomainTree', null, { reload: true });//fix for refresh issue.
}
}
}
This is my Service Method
setChildBD: function(varType,childBD,value,val){
if(varType == "busSubDomain"){
this.error=undefined;
if(childSubDomainName.indexOf(childBD)==-1){
childSubDomainName.push(childBD);
var i= childDomainName.indexOf(val);
//Done this for replacing the object name with an array which contains the child.attached the image for its value
childDomainName.splice(i,1,value.childNode[0]);
}
},
getBusDomainName: function(){
return this.busDomainValue;//here the busDomainValue gets overrided with the controller list value
},
Can anyone please suggest how to resolve this issue?
Got a solution for this. I used var domainList=angular.copy($scope.busdomain) instead of var domainList=DomainNameService.getBusDomainName(); in controller.js –

Accessing function from multiple forms on same page

I have the following function:
<script type="text/javascript">
$(function(){
// start a counter for new row IDs
// by setting it to the number
// of existing rows
var newRowNum = 2;
// bind a click event to the "Add" link
$('#addnew').click(function() {
// increment the counter
newRowNum += 1;
// get the entire "Add" row --
// "this" refers to the clicked element
// and "parent" moves the selection up
// to the parent node in the DOM
var addRow = $(this).parent().parent();
// copy the entire row from the DOM
// with "clone"
var newRow = addRow.clone();
// set the values of the inputs
// in the "Add" row to empty strings
//$('input', addRow).val('');
//$('name', addRow).val('os' + newRowNum);
// replace the HTML for the "Add" link
// with the new row number
$('td:first-child', newRow).html('<input type="hidden" name="on' + newRowNum + '" value="Email Address ' + (newRowNum - 1) + '">Recipient');
// insert a remove link in the last cell
$('td:last-child', newRow).html('<a href="" class="remove">Remove<\/a>');
// loop through the inputs in the new row
// and update the ID and name attributes
$('input:hidden', newRow).attr('id','on' + newRowNum ).attr('name','on' + newRowNum );
$('input:text', newRow).attr('id','os' + newRowNum ).attr('name','os' + newRowNum );
// insert the new row into the table
// "before" the Add row
addRow.before(newRow);
document.tp01.quantity.value = newRowNum-1;
// add the remove function to the new row
$('a.remove', newRow).click(function(){
$(this).parent().parent().remove();
return false;
});
// prevent the default click
return false;
});
});
</script>
This function is called by clicking on a link in a form (this function adds or removes rows from a table). The link looks like this:
<a id="addnew" href="">Add</a>
I need to put more forms on the same page accessed by a link in each of those forms that is, as far as the user is concerned, exactly the same as the one shown above. Can someone make suggestions as to how I can reuse the same function to accomplish this?
Thanks
Dave
move the embedded script to an external JS file:
var newRowNum = 2;
var bindLink = function(linkSelector)
{
// bind a click event to the "Add" link
$(linkSelector).click(function() {
...
}
}
Then in place of the embedded script put a call to bindLink('#addnew') in your ready handler.