Highcharts one input of the three not working - highcharts

I have created three input boxes that should filter the chart. The second option seems not to be working. I have not found any problem in the code so far.
//JSON query
var json_data = [
{
"mip": {
"id": 125,
"name": "One",
"code": "One"
},
"briefNetSpendInEuro": 2200,
"postNetSpendInEuro": 0,
"proposalSpendInEuro": 3530
},
{
"mip": {
"id": 125,
"name": "Two",
"code": "Two"
},
"briefNetSpendInEuro": 12052,
"postNetSpendInEuro": 2516,
"proposalSpendInEuro": 5358
},
{
"mip": {
"id": 531,
"name": "Three",
"code": "Three"
},
"briefNetSpendInEuro": 5391,
"postNetSpendInEuro": 9812,
"proposalSpendInEuro": null
}
]
var categories = [];
var series = [];
var brief = [];
var post = [];
var proposal = [];
//JSON manipulation to prepare the data for the highchart
json_data.forEach(function(element) {
categories.push(element.mip.code);
brief.push(element.briefNetSpendInEuro = element.briefNetSpendInEuro || 0);
post.push(element.postNetSpendInEuro = element.postNetSpendInEuro || 0);
proposal.push(element.proposalSpendInEuro = element.proposalSpendInEuro || 0);
});
//Filter creation
$(function() {
var chart = new Highcharts.Chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Spend per Media Group'
},
xAxis: {
categories: [{
"class": "One",
"name": "One"
}, {
"class": "Two",
"name": "Two"
}, {
"class": "Three",
"name": "Three"
}],
labels: {
formatter: function() {
return this.value.name;
},
useHTML: true
}
},
yAxis: {
min: 0,
title: {
text: 'Spend (EUR)'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key.name}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.,0f} </b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
},
series: [{
name: 'Brief Net',
data: brief
}, {
name: 'Post Net',
data: post
}, {
name: 'Proposal',
data: proposal
}]
}, function() {
$('input[type=checkbox]').bind('click', function() {
togglePointsByClass(this.value, $(this).is(':checked'), chart)
});
});
var visibleArr = [0, 1, 2];
function togglePointsByClass(className, shouldShow, chart) {
var isChartDirty = false;
if (shouldShow) {
chart.xAxis[0].userOptions.categories.forEach(function(category, i) {
if (category.class === className) {
visibleArr.push(i);
}
});
} else {
chart.xAxis[0].userOptions.categories.forEach(function(category, i) {
if (category.class === className && visibleArr.indexOf(i) > -1) {
visibleArr.splice(visibleArr.indexOf(i), 1);
}
});
}
if (visibleArr.length) {
chart.xAxis[0].update({
min: Math.min.apply(null, visibleArr),
max: Math.max.apply(null, visibleArr)
})
}
}
$('#container').highcharts().redraw();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div class="row">
<div class="col-xs-12">
<div class="box-first box-container">
<div class="row">
<div class="col-xs-4">
<input type="checkbox" name="One" value="One" checked> One
</div>
<div class="col-xs-4">
<input type="checkbox" name="Two" value="Two" checked> Two
</div>
<div class="col-xs-4">
<input type="checkbox" name="Three" value="Three" checked> Three
</div>
</div>
</div>
</div>
</div>
<div id="container" style="min-width: 310px; max-width: 800px; height: 400px; margin: 0 auto"></div>

The concept is to recalculate your series each time and determine which to show.
I took your initial calculation of data and turned it to a function like this, calling each time with the visibleArr.
const calcData = (arr) => {
const brief = [];
const proposal = [];
const post = [];
json_data.forEach((element, i) => {
if (arr.includes(i)) {
brief.push(element.briefNetSpendInEuro || 0);
post.push(element.postNetSpendInEuro || 0);
proposal.push(element.proposalSpendInEuro || 0);
}
});
return [{ name: 'Brief Net', data: brief },
{ name: 'Post Net', data: post },
{ name: 'Proposal', data: proposal }];
};
Take a look at this jsfiddle: http://jsfiddle.net/ueso3bc6/1/

Related

Leaflet use popup not display

I use highchart chart to present in popup.
It can be presented when the marker is clicked for the first time.
But opening another popup cannot display the chart.
If I close the original one and open a new one, it can be displayed.
What is the problem?
Turn on for the first time
When opening another
Code:
function onEachFeature(feature, layer) {
var popupContent = '<p style="font-size:130%;">' + feature.properties.id + "<br>PM2.5: " + air + '</p><div class="d-flex"> <button class="day-button">24 hr</button> <button class="week-button">7 Days</button> <button class="mon-button ">30 Days</button></div>' + '</p><div id="container" style="min-width: 350px; height: 190px; margin: 0 auto"></div> <p> ';
if (feature.properties && feature.properties.popupContent) {
popupContent += feature.properties.popupContent;
}
layer.bindPopup(popupContent, { minWidth: 370 }).on("popupopen", function(e) {
var id1 = feature.properties.id;
Highcharts.setOptions({ global: { useUTC: false } });
var chart = null;
test(id1);
}
}
Highchart:
function test (station){
var ob = [];
var json_hour ="data.csv";
var count_nul = 0;
d3.csv(json_hour, function (error, result) {
function date_to_epoch(key) {
var epoch_seconds = new Date(key).getTime();
return Math.floor(epoch_seconds);
}
for (var i = 0; i < result.length; i++) {
var apoche = date_to_epoch(result[i]['date']).toString();
apoche = parseFloat(apoche);
if (parseFloat(result[i]['pm25']).toString() == 'NaN') {
count_nul++;
} else {
var miles = parseFloat(result[i]['pm25']);
}
ob.push([apoche, miles]);
}
if (count_nul >= 24) {
$("#con").text("no data");
}
else {
$("#con").empty();
console.log((ob));
new Highcharts.Chart({
chart: {
renderTo: 'con',
type: 'line'
},
title: { text: '' },
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
minute: '%H:%M',
hour: '%H:%M',
day: '%Y<br/>%m%d',
week: '%Y<br/>%m-%d',
month: '%Y<br/>%m',
year: '%Y'
}
, crosshair: true,
},
tooltip: {
split: false,
shared: true,
animation: true,
xDateFormat: '%Y-%m-%d %H:%M',
valueSuffix: ' µm'
},
series: [{
name: "PM2.5",
data: ob,
showInLegend: true
}
],
credits: {
enabled: false
},
exporting: {
enabled: false
},
plotOptions: {
line: {
connectNulls: true,
}
},
responsive: {
rules: [{
condition: {
maxWidth: 330
},
}]
}
});
}
});
}
Change your code to:
function onEachFeature(feature, layer) {
var popupContent = '<p style="font-size:130%;">' + feature.properties.id + "<br>PM2.5: " + air + '</p><div class="d-flex"> <button class="day-button">24 hr</button> <button class="week-button">7 Days</button> <button class="mon-button ">30 Days</button></div>' + '</p><div id="container" style="min-width: 350px; height: 190px; margin: 0 auto"></div> <p> ';
if (feature.properties && feature.properties.popupContent) {
popupContent += feature.properties.popupContent;
}
layer.bindPopup(popupContent, { minWidth: 370 }).on("popupopen", function(e) {
var id1 = e.popup._source.feature.properties.id;
Highcharts.setOptions({ global: { useUTC: false } });
var chart = null;
test(id1);
}
}
With e.popup._source.feature.properties.id you are sure that the id is from the current open layer

I have list of users which is used to send mail to them. I want to display selected users in another list box. How can I do that?

I have following code which displays list of users and when i select user and click on send, it sends mail. But I want to display another list which takes users from selected values and then send mail.
View Code:
<div class="modal fade small" id="invitiesModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h5 class="modal-title" id="myModalLabel">Share</h5>
</div>
<div class="modal-body">
<table id="tblMeeting"> </table>
<div id="pager"></div>
</div>
<input type="hidden" value="0" id='meetingId' name='meetingId'>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="btnShareMOM" data-dismiss="modal">Send Mail</button>
</div>
</div>
</div>
</div>
JQGrid:
var idsOfSelectedRows = new Array();
$("#DraftFile").change(function () {
if (window.File && window.FileReader && window.FileList && window.Blob) {
document.getElementById("mom_btn1").style.display = "inline-block";
document.getElementById("mom_btn2").style.display = "inline-block";
}
});
checkName = function (value) {
//debugger;
if (value.length == 0) {
return [false, "Please enter the Name!"]
}
return [true];
};
function ShareMOM(meetingId) {
var InvityIds = new Array();
//alert(meetingId);
$.ajax({
url: '#Url.Action("ShareView", "PostMeetingDocument", new { area = "Postmeeting" })',
type: "Get",
async: false,
data: { "meetingId": meetingId },
cache: false,
success: function (data) {
InvityIds = data;
//console.log(data);
},
error: function () {
//alert('oops something wrong!!');
}
})
idsOfSelectedRows = new Array();
//$.each(InvityIds, function (index, val) {
// idsOfSelectedRows.push(val);
//});
var updateIdsOfSelectedRows = function (id, isSelected) {
var contains = idsOfSelectedRows.indexOf(id);
if (!isSelected && contains>=0) {
for (var i = 0; i < idsOfSelectedRows.length; i++) {
if (idsOfSelectedRows[i] == id) {
idsOfSelectedRows.splice(i, 1);
break;
}
}
}
else if (contains<0) {
idsOfSelectedRows.push(id);
}
};
$("#tblMeeting").jqGrid("GridUnload")
$("#meetingId").val(meetingId);
$("#Invities").show();
var URL = '#Url.Action("GetInvitees", "PostMeetingDocument", new { area = "Postmeeting", meetingId = "_MeetingId" })';
URL = URL.replace("_MeetingId", meetingId);
$('#tblMeeting').jqGrid({
url: URL,
datatype: "json",
mytype: "GET",
colNames: ["UserID", "FirstName","LastName"],
colModel: [
{ name: 'UserID', index: 'UserID', width: 55, hidden: true, key: true, editable: false, checked: true },
{ name: 'FirstName', index: 'FirstName', sortable: false, align: "left", width: 150, editable: true, search: false, editrules: { custom: true, custom_func: checkName }, searchoptions: { sopt: ['cn'] } },
{ name: 'LastName', index: 'LastName', sortable: false, align: "left", width: 150, editable: true, search: false, editrules: { custom: true, custom_func: checkName } },
//{ name: 'Department', index: 'Department', sortable: false, align: "left", width: 150, editable: true, search: false, editrules: { custom: true, custom_func: checkName } }
],
rowNum: 30,
rowList: [30, 60, 90],
multiSort: true,
sortname: 'FirstName asc,LastName',
sortorder: 'asc',
height: 350,
pager: jQuery('#pager'),
width: 510,// 450,
multiselect: true,
multiPageSelection: true,
viewrecords: true,
//caption: "Add Invities",
onSelectRow: function (rowid, status) {
//selected[rowid] = status;
//setSelectedDeviceCount();
updateIdsOfSelectedRows(rowid, status);
},
onSelectAll: function (aRowids, status) {
var i, count, id;
for (i = 0, count = aRowids.length; i < count; i++) {
//selected[rowids[i]] = status;
id = aRowids[i];
updateIdsOfSelectedRows(id, status);
}
},
loadComplete: function () {
$.each(idsOfSelectedRows, function (index, val) {
//var ids = grid.jqGrid('getDataIDs');
//for (var i = 0; i < ids.length; i++) {
// if (selected[ids[i]] === true) {
// grid.setSelection(ids[i], false);
// }
//}
$('#tblMeeting').jqGrid("setSelection", val, true);
});
},
shrinkToFit: true
}).navGrid(pager, { edit: false, add: false, del: false, search: false, refresh: true, addtext: "Share MOM", searchtext: "Search", refreshtext: "Refresh" },
{
//Edit.
},
{
// add options.
},
{
//Delete.
}
);
}
$("#btnShareMOM").on('click', function () {
//var UserId = new Array();
$.ajax({
url: '#Url.Action("SendMomAll", "PostMeetingDocument", new { area = "Postmeeting" })',
type: "Get",
async: false,
data: { "meetingId": $("#MeetingID").val(), "userId": idsOfSelectedRows.join() },
cache: false,
success: function (data) {
// InvityIds = data;
//console.log(data);
},
error: function () {
//alert('oops something wrong!!');
}
})
});
Controller:
public ActionResult SendMomAll(int meetingId, string userId)
{
var EmailTemplate = db.EmailTempletes.Where(l => l.Name == "FinalMOM").FirstOrDefault();
List<int> userIds = Array.ConvertAll<string, int>(userId.Split(','), new Converter<string, int>(Convert.ToInt32)).ToList();
List<string> UserMailList = (from u in db.VMUsers where userIds.Contains(u.UserID) select u.Email.Trim()).ToList();
string UserMail = string.Join(",", UserMailList.ToArray());
//var Note = db.Notes.OrderByDescending(l => l.NoteId).FirstOrDefault(l => (l.PreviousNoteId == (-1) || l.PreviousNoteId == (-2)) && (l.ParentNoteId == (-1) || l.ParentNoteId == (-2)) && l.MeetingId == meetingId);
//var Note = db.Notes.OrderByDescending(l => l.NoteId).FirstOrDefault(l => l.MeetingId == meetingId);
//var Document = db.Files.OrderByDescending(l => l.FileId).FirstOrDefault(l => l.NoteId == Note.NoteId);
var strMappath = Server.MapPath("~/Repository/Meetings/" + meetingId.ToString() + "/");
//strMappath += Document.FileName;
var dir = new DirectoryInfo(strMappath).GetFiles("*.*").OrderByDescending(l=>l.LastWriteTime).FirstOrDefault();
MailBox mailbox = new MailBox();
mailbox.MailTo = UserMail;
mailbox.Subject = EmailTemplate.Subject;
mailbox.Body = EmailTemplate.TempleteBody;
mailbox.IsAttachment = true;
mailbox.AttachmentsPath = strMappath + dir.Name;
mailbox.Status = false;
db.MailBox.Add(mailbox);
db.SaveChanges();
//return View("Index");
return Json(mailbox,JsonRequestBehavior.AllowGet);
}
Now i want to display list for selected users from this list

how to bind & show standard deviation, min, max and average on bar chart in highcharts

I have a trellis chart and I want to show the Standard Deviation, min max and average on top of them. I have the values for standard deviation, min, max and average coming into my dataset.
Need to show SD(standard deviation) as a different color of the bar on the respective bar.
min with down arrow, max with up arrow and average with any symbol.
currently my chart looks like as below
and I want to show the SD, min max and average value on top of my current chart as like here
The complete code is as below.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Network Visualization</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<style type="text/css">
${demo.css}
</style>
<script type="text/javascript">
$(function () {
servicesName = [];
servicesName.push('Activity Store', 'Bec', 'bl2-dpx-a-Azure', 'DPX-s1-am3a', 'DPX-s1-bl2/DPX');
var seriesDataSet = [
{
name: 'AvgSRTT',
data: [674167, 221349, 40049, 635006, 43978],
stack: 2544
}, {
name: 'MaxCount',
data: [1410, 12, 284, 497, 1499],
stack: 3553
}, {
name: 'maxDataBytesIn',
data: [104034610, 97935, 2781481799, 114003343, 24964398065],
stack: 6556889
}, {
name: 'maxDataBytesOut',
data: [61710601, 78619, 262050684, 8902916, 2331402781],
stack: 3557879
}, {
name: 'avgAvgSRTT',
data: [674167, 221349, 40049, 635006, 43978],
stack: 68699
}, {
name: 'avgDataBytesIn',
data: [104034610, 97935, 2781481799, 114003343, 24964398065],
stack: 477889094
}, {
name: 'avgDataBytesOut',
data: [61710601, 78619, 262050684, 8902916, 2331402781],
stack: 36547568
}
];
var charts = [],
$containers = $('#trellis td'),
datasets = seriesDataSet;
$.each(datasets, function (i, dataset) {
var yAxisMax = 25000000000;
if (i == 0 || i == 4) {
yAxisMax = 1000000;
}
else if (i == 1) {
yAxisMax = 4000;
}
charts.push(new Highcharts.Chart({
chart: {
renderTo: $containers[i],
type: 'bar',
marginLeft: i === 0 ? 110 : 10
},
title: {
text: dataset.name,
align: 'left',
x: i === 0 ? 90 : 0
},
credits: {
enabled: false
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
},
stacking: 'normal'
},
series: {
minPointLength: 3
}
},
xAxis: {
categories: servicesName,
labels: {
enabled: i === 0,
},
title: {
text: null,
align: 'left'
},
},
yAxis: {
allowDecimals: false,
title: {
text: null
},
min: 0,
max: yAxisMax
},
legend: {
enabled: false
},
series: [dataset],
minPointLength: 3
}));
});
});
</script>
</head>
<body>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<h1> Network traffic details for each services</h1>
<span id="date_time"></span>
<table id="trellis">
<tr>
<td style="min-width: 300px; height: 450px; margin: 0 auto"></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</body>
</html>

How to filter array type of resource in Telerik MVC Scheduler?

I'm trying to filter calendar MeetingAttendees which can have multiple users. I've built a filter and tested with various options, but it doesn't work. The basic example shows how to filter a calendar owner (which is a single value) and it works fine for me. But Attendees is an array and when I'm trying to filter that all my events disappear.
Here is my filter code:
var checked = $.map($("#teamMembers :checked"), function (checkbox) {
return parseInt($(checkbox).val());
});
var filter = {
logic: "or",
filters: $.map(checked, function (value) {
return {
operator: "eq",
field: "Attendees",
value: value
};
})
};
var scheduler = $("#scheduler").data("kendoScheduler");
scheduler.dataSource.filter(filter);
Attendees in MeetingViewModel are loaded as an array:
Attendees = meeting.MeetingAttendees.Select(m => m.AttendeeID).ToArray(),
Here is the scheduler configuration:
#(Html.Kendo().Scheduler<Itsws.Models.MeetingViewModel>()
.Name("scheduler")
.Date(DateTime.Today)
.Editable(editable =>
{
editable.TemplateName("CustomEditorTemplate");
})
.StartTime(new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 7, 00, 00))
.Height(600)
.Views(views =>
{
views.DayView();
views.WeekView(weekView => weekView.Selected(true));
views.MonthView();
views.AgendaView();
views.TimelineView();
})
.Timezone("Etc/UTC")
.DataSource(d => d
.Model(m =>
{
m.Id(f => f.MeetingID);
m.Field(f => f.Title).DefaultValue("No title");
m.RecurrenceId(f => f.RecurrenceID);
m.Field(f => f.Title).DefaultValue("No title");
})
.Read("Meetings_Read", "Scheduler")
.Create("Meetings_Create", "Scheduler")
.Destroy("Meetings_Destroy", "Scheduler")
.Update("Meetings_Update", "Scheduler")
)
)
Apparently operator field can also be a function that does filter comparison. Here is the sample code generously provided by Telerik support.
More info here:
http://www.telerik.com/forums/how-to-filter-array-type-of-resource-(e-g-attendees)
<!DOCTYPE html>
<html>
<head>
<base href="http://demos.telerik.com/kendo-ui/scheduler/resources-grouping-vertical">
<style>html { font-size: 12px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.408/styles/kendo.common.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.408/styles/kendo.moonlight.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.408/styles/kendo.dataviz.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.408/styles/kendo.dataviz.moonlight.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.408/styles/kendo.default.mobile.min.css" />
<script src="http://cdn.kendostatic.com/2015.1.408/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2015.1.408/js/kendo.all.min.js"></script>
<script src="http://cdn.kendostatic.com/2015.1.408/js/kendo.timezones.min.js"></script>
</head>
<body>
<div id="example" class="k-content">
<div id="team-schedule">
<div id="attendees">
<ul>
<li>Alex: <input type="checkbox" id="alex" value="1"></li>
<li>BoB: <input type="checkbox" id="bob" value="2"></li>
<li>Charlie: <input type="checkbox" id="charlie" value="3"></li>
</ul>
</div>
</div>
<div id="scheduler"></div>
</div>
<script>
$(function() {
$("#scheduler").kendoScheduler({
date: new Date("2013/6/13"),
height: 600,
views: [
"timelineMonth"
],
timezone: "Etc/UTC",
dataSource: {
batch: true,
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/meetings",
dataType: "jsonp"
},
update: {
url: "http://demos.telerik.com/kendo-ui/service/meetings/update",
dataType: "jsonp"
},
create: {
url: "http://demos.telerik.com/kendo-ui/service/meetings/create",
dataType: "jsonp"
},
destroy: {
url: "http://demos.telerik.com/kendo-ui/service/meetings/destroy",
dataType: "jsonp"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
schema: {
model: {
id: "meetingID",
fields: {
meetingID: { from: "MeetingID", type: "number" },
title: { from: "Title", defaultValue: "No title", validation: { required: true } },
start: { type: "date", from: "Start" },
end: { type: "date", from: "End" },
startTimezone: { from: "StartTimezone" },
endTimezone: { from: "EndTimezone" },
description: { from: "Description" },
recurrenceId: { from: "RecurrenceID" },
recurrenceRule: { from: "RecurrenceRule" },
recurrenceException: { from: "RecurrenceException" },
roomId: { from: "RoomID", nullable: true },
attendees: { from: "Attendees", nullable: true },
isAllDay: { type: "boolean", from: "IsAllDay" }
}
}
}
},
group: {
resources: ["Rooms", "Attendees"],
orientation: "vertical"
},
resources: [
{
field: "roomId",
name: "Rooms",
dataSource: [
{ text: "Meeting Room 101", value: 1, color: "#6eb3fa" },
{ text: "Meeting Room 201", value: 2, color: "#f58a8a" }
],
title: "Room"
},
{
field: "attendees",
name: "Attendees",
dataSource: [
{ text: "Alex", value: 1, color: "#f8a398" },
{ text: "Bob", value: 2, color: "#51a0ed" },
{ text: "Charlie", value: 3, color: "#56ca85" }
],
multiple: true,
title: "Attendees"
}
]
});
$("#attendees :checkbox").change(function(e) {
var checked = $.map($("#attendees :checked"), function(checkbox) {
return parseInt($(checkbox).val());
});
var scheduler = $("#scheduler").data("kendoScheduler");
scheduler.dataSource.filter({
field: "attendees",
operator: function(item, value) {
var found = true;
for (var i = 0; i < checked.length; i++) {
if (item.indexOf(checked[i]) < 0) {
found = false;
}
}
return found;
}
});
});
});
</script>
</body>
</html>

Multiple columns in popup edit mode

I think the popup edit mode is the nicest of the edit modes, but with a larger model the popup becomes very long which doesn't look nice.
I've found a solution for this and I'm curious on your ideas/feedback/enhancements for this solution.
I created two custom attributes:
public class NumberOfColumnsAttribute : Attribute, IMetadataAware
{
private readonly int _numberOfColumns;
public NumberOfColumnsAttribute(int numberOfColumns)
{
_numberOfColumns = numberOfColumns;
}
public void OnMetadataCreated(ModelMetadata metadata)
{
if (!metadata.AdditionalValues.ContainsKey("NumberOfColumns"))
{
metadata.AdditionalValues.Add("NumberOfColumns", _numberOfColumns);
}
}
}
public class ShowInColumnAttribute : Attribute, IMetadataAware
{
private readonly int _column;
public ShowInColumnAttribute(int column)
{
_column = column;
}
public void OnMetadataCreated(ModelMetadata metadata)
{
if (!metadata.AdditionalValues.ContainsKey("ShowInColumn"))
{
metadata.AdditionalValues.Add("ShowInColumn", _column);
}
}
}
Then use the [NumberOfColumns(m)] attribute above your edit model and use the [ShowInColumn(n)] attribute above a property (n=1 is assumed when no attribute is applied).
I created a Object.cshtml file in Views/Shared/EditorModels/ as follows.
#if (ViewData.TemplateInfo.TemplateDepth > 1)
{
#ViewData.ModelMetadata.SimpleDisplayText
} else {
for (var i = 1; i <= (int)(!ViewData.ModelMetadata.AdditionalValues.ContainsKey("NumberOfColumns") ? 1 : ViewData.ModelMetadata.AdditionalValues["NumberOfColumns"]);i++)
{
<div class="editor-column">
#foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm) && ((int)(!pm.AdditionalValues.ContainsKey("ShowInColumn") ? 1 : pm.AdditionalValues["ShowInColumn"])) == i))
{
if (prop.HideSurroundingHtml) {
#Html.Editor(prop.PropertyName)
} else {
<div class="editor-label">
#Html.Label(prop.PropertyName)
#(prop.IsRequired ? "*" : "")
</div>
<div class="editor-field">
#Html.Editor(prop.PropertyName)
#Html.ValidationMessage(prop.PropertyName, "*")
</div>
}
}
</div>
}
<div class="editor-seperator"></div>
}
And the following lines of CSS:
.k-edit-form-container {
width: auto;
}
.editor-column {
width: 400px;
float: left;
}
.editor-seperator {
clear: both;
}
What do you think?
I think, this would be much simpler. Please run this script on wide screen.
var crudServiceBaseUrl = "//demos.telerik.com/kendo-ui/service",
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/Products",
dataType: "jsonp"
},
update: {
url: crudServiceBaseUrl + "/Products/Update",
dataType: "jsonp"
},
destroy: {
url: crudServiceBaseUrl + "/Products/Destroy",
dataType: "jsonp"
},
create: {
url: crudServiceBaseUrl + "/Products/Create",
dataType: "jsonp"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
batch: true,
pageSize: 20,
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { editable: false, nullable: true },
ProductName: { validation: { required: true } },
UnitPrice: { type: "number", validation: { required: true, min: 1} },
Discontinued: { type: "boolean" },
UnitsInStock: { type: "number", validation: { min: 0, required: true } }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
height: 550,
toolbar: ["create"],
columns: [
{ field:"ProductName", title: "Product Name" },
{ field: "UnitPrice", title:"Unit Price", format: "{0:c}", width: "120px" },
{ field: "UnitsInStock", title:"Units In Stock", width: "120px" },
{ field: "Discontinued", width: "120px" },
{ command: ["edit", "destroy"], title: " ", width: "250px" }],
editable: "popup",
edit: fnMultipleLayoutForm
});
function fnMultipleLayoutForm(){
$(".k-edit-form-container").prepend('<div class="column1" style="display: inline-block; float: left;padding-right:30px"></div><div class="column2" style="display: inline-block;float: left;padding-right:30px;"></div>');
$(".k-edit-form-container").children(".k-edit-label, .k-edit-field").slice(0, parseInt($(".k-edit-form-container").children(".k-edit-label, .k-edit-field").length / 2)).appendTo(".column1");
$(".k-edit-form-container").children(".k-edit-label, .k-edit-field").appendTo(".column2");
$(".k-edit-form-container").css("width", "auto");
$('.k-window').css({ top: '50%', left: '50%', margin: '-' + ($('.k-window').height() / 2) + 'px 0 0 -' + ($('.k-window').width() / 2) + 'px' });
};
<script src="//kendo.cdn.telerik.com/2015.3.1111/js/jquery.min.js"></script>
<script src="//kendo.cdn.telerik.com/2015.3.1111/js/kendo.all.min.js"></script>
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2015.3.1111/styles/kendo.common.min.css" />
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2015.3.1111/styles/kendo.default.min.css" />
<div id="grid"></div>

Resources