The website I'm developing needs to comply with the WCAG 2.0 guidelines, meaning a person should be able to access all information on the site using a screen reader. Since it's a BI dashboard making heavy use of Kendo Charts it failed the test.
I need a way for screen readers to be able to read the Kendo Charts on my website, while reusing the chart's datasource.
I solved this by automatically generating a table for each chart on the page.
Create partial view which generates HTML table
#{
var divId = Guid.NewGuid().ToString();
var tableId = Guid.NewGuid().ToString();
var templateId = Guid.NewGuid().ToString();
}
/* Chart ID */
#model string
<div id="#divId" class="hiddenTable"></div>
<script>
(function () {
var template = kendo.template($("##templateId").html());
var chartData = $("##Model").data("kendoChart").dataSource;
$("##divId").prepend(template(chartData.data()));
})();
</script>
<script id="#templateId" type="text/x-kendo-tmpl">
# var columnNames = Chart.getColumnNamesFromData(data) #
<table id="#tableId">
<thead>
<tr>
# for(var columnIndex = 0; columnIndex < columnNames.length; columnIndex++) { #
<th scope="col">#= S(columnNames[columnIndex]).humanize().s #</th>
# } #
</tr>
</thead>
<tbody>
# for(var i = 0, len = data.length; i < len; i++) { #
# if (data[i][columnNames[0]] != undefined) { #
<tr>
# for(var columnIndex = 0; columnIndex < columnNames.length; columnIndex++) { #
# if(columnNames[columnIndex] == 'Date') { #
<th scope="row">#= kendo.toString(data[i][columnNames[columnIndex]], "MMMM yyyy") #</th>
#} else { #
<td>#= kendo.toString(data[i][columnNames[columnIndex]] != undefined ? data[i][columnNames[columnIndex]] : 0, "n1") #</td>
# } #
# } #
</tr>
# } #
# } #
</tbody>
</table>
</script>
Add CSS to hide table from view
.hiddenTable {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
Add img role to chart
#(Html.Kendo().Chart<MyModel>()
.Name(Guid.NewGuid().ToString())
.HtmlAttributes(new { role = "img" })
.DataSource(ds => ds
.Read("GetData", "Home")
)
)
Result
Related
I have a problem with my asp.net app. This is my index.html
#using BricksBreaking;
#model FieldModel
#{
ViewData["Title"] = "Game";
}
<h2>Index</h2>
<table class="field">
#for (int row = 0; row < Model.Field.RowCount; row++)
{
<tr>
#for (int column = 0; column < Model.Field.ColumnCount; column++)
{
var tile = Model.Field.Tiles[row, column];
if (tile == null)
{
<td />
}
else
{
if (Model.Field.Tiles[row, column].Color == TileColor.Red) {
<td>
<a href='/BricksBreaking/Click?r=#row?c=#column'>
<img src='/images/cervena.png' />
</a>
</td>
}if(Model.Field.Tiles[row, column].Color == TileColor.Yellow)
{
<td>
<a href='/BricksBreaking/Click?r=#row?c=#column'>
<img src='/images/zlta.png' />
</a>
</td>
}if(Model.Field.Tiles[row, column].Color == TileColor.Blue)
{
<td>
<a href='/BricksBreaking/Click?r=#row?c=#column'>
<img src='/images/modra.png' />
</a>
</td>
}
}
}
</tr>
}
</table>
And this is my controller
public class BricksBreakingController : Controller
{
ScoreServiceDatabase scoreService = new ScoreServiceDatabase();
public IActionResult Index()
{
var field = new Field(9, 9, 5);
HttpContext.Session.SetObject("field", field);
var model = new FieldModel
{ Field = field, Scores = scoreService.GetTopScores() };
return View(model);
}
public IActionResult Click(int r, int c)
{
var field = HttpContext.Session.GetObject("field") as Field;
field.ClickTile(r,c);
HttpContext.Session.SetObject("field", field);
var model = new FieldModel
{ Field = field, Scores = scoreService.GetTopScores() };
return View("Index", model);
}
}
}
Problem is. that always here at this line
<a href='/BricksBreaking/Click?r=#row?c=#column'>
Arguments passed to Function Click in controller are always 0. No matter if i write something like this
<a href='/BricksBreaking/Click?r=2?c=2'>
There will be always 0.
Can somebody help me with this? I am new to .NET.
You only need to write a ? before the first parameter. Every parameter after the first needs a &
<a href='/BricksBreaking/Click?r=2&c=2'>
I have an asp.net mvc application with razor view's engine. I need to store the values of a list passed as a model in my view by using javascript
#section logout {
<a href='#Url.Action("Retour", "Client")'><img src="~/Content/images/home-icon.png" /></a>
<img src="~/Content/images/images.jpg" style="width:37px; height:37px" />
}
#Json.Encode(Model.Get_List_Tache());
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="~/Content/jquery.treeview.css" />
<script src="~/Content/jquery.cookie.js" type="text/javascript"></script>
<script src="~/Content/jquery.treeview.js" type="text/javascript"></script>
<script type="text/javascript" src="~/Content/demo.js"></script>
<!-- partie calendrier-->
<link rel="stylesheet" href="~/Scripts/Calendar/theme.css" />
<link href="~/Scripts/Calendar/fullcalendar.css" rel="stylesheet" />
<link href="~/Scripts/Calendar/fullcalendar.print.css" rel="stylesheet" media="print" />
<script src="~/Scripts/Calendar/fullcalendar.min.js"></script>
<style>
body
{
background-color:#eee;
}
#tree {
background-color:#eee;
}
.affaire {
color:black;
font-size: 16px;
}
.tache {
color:black;
font-size: 12px;
}
.projet {
color:blue;
font-size: 20px;
}
.sequence {
color:blue;
font-size: 13px;
}
#calendar {
width: 700px;
margin: 0 auto;
}
</style>
<script>
$(document).ready(function () {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var titles= Json.Parse(Model.Get_List_Tache());
$('#calendar').fullCalendar({
theme: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
events: [
{
id: 999,
title: titles[0],
start: new Date(y, m, d - 3, 16, 0),
allDay: false
}
]
});
});
</script>
</head>
<body>
<table><tr><td style="width:200px;display:block;margin-top:80px;" id="tree">
<ul id="red" style="width: 100%; display:block;width:100%;margin-top:0%">
#for (int i = 0; i < Model.Get_List_Projet().Count; i++)
{
<li><span class="projet">Projet : #Model.Get_List_Projet()[#i].Description</span>
<br />
<br />
<ul>
#for (int j = 0; j < Model.Get_List_Affaire_By_Projet(Model.Get_List_Projet()[#i].Id_projet).Count; j++)
{
int id_affaire = #Model.Get_List_Affaire_By_Projet(Model.Get_List_Projet()[#i].Id_projet)[#j].Id_affaire;
<li><span class="affaire"> #Model.Get_List_Affaire_By_Projet(Model.Get_List_Projet()[#i].Id_projet)[#j].Affaire_description</span>
<br />
<br />
<ul>
#for (int k = 0; k < #Model.Get_List_Sequence_By_Affaire(id_affaire).Count; k++)
{
int id_sequence = #Model.Get_List_Sequence_By_Affaire(id_affaire)[k].Id_séquence;
<li><span class="sequence">#Model.Get_List_Sequence_By_Affaire(id_affaire)[k].Sequence_description </span>
<ul>
#for (int t = 0; t < #Model.Get_List_Tache_By_Sequence(id_sequence).Count; t++)
{
int id_tache = #Model.Get_List_Tache_By_Sequence(id_sequence)[t].Id_tache;
<li><span class="tache">Tache : #Html.ActionLink((string)#Model.Get_List_Tache_By_Sequence(id_sequence)[t].Tache_description, "GererTache", new { id = id_tache })</span></li>
}
<li>#Html.ActionLink("AjouterTache", "AjouterTache", new { id = id_affaire }) </li>
<li>#Html.ActionLink("GérerSéquence", "GererSequence", new { id = id_sequence }) </li>
</ul>
</li>
}
#for (int g = 0; g < #Model.Get_List_Tache_By_Affaire(id_affaire).Count; g++)
{
int id_task = #Model.Get_List_Tache_By_Affaire(id_affaire)[g].Id_tache;
<li><span class="tache">Tache: #Html.ActionLink((string)#Model.Get_List_Tache_By_Affaire(id_affaire)[g].Tache_description, "GererTache", new { id = id_task })</span>
</li>
}
</ul>
<ul><li>#Html.ActionLink("AjouterSéquence", "AjouterSéquence", new { id = id_affaire }) </li>
<li>#Html.ActionLink("AjouterTache", "AjouterTache", new { id = id_affaire }) </li>
<li>#Html.ActionLink("Gérer cette affaire", "GererAffaire", new { id = id_affaire }) </li>
</ul>
</li>
}
</ul>
</li>
}
<br />
</ul>
</td> <td >
<div id='calendar'></div>
</td>
</tr>
</table>
<a href='#Url.Action("Choice", "Travail")'>Retour</a>
</body>
</html>
But i don't know how can i pass from server side to client side, to pass from a C# List to Javascript table.
So i need suggestions to do this task
You need to wrap your code in a loop, consider something like this:
var someArray = []
#for (int i=0; i < this.Model.myArray.length; i++)
{
someArray.push([{ Prop = this.Model.myArray[i].someProp . . . } ]);
}
Alternatively you could add a property to your model, eg.
public class MyModel
{
public string SerialisedData {
get {
return string.Format("[{ name = {0}, someProp = {1} ...... }]", this.Name, this.someProp .....);
}
}
}
But remember to escape quotes.
I am trying to load models and set every model in a separate, <td> when I reach 5 <td> I want to automatically start a new <tr> but it isn't really working with an if statement. Is it possible or should I go for an entire different approach?
Here is my code:
<tr>
#for (int i = 0; i < Model.Count; i++)
{
<td>
<img width="200px" src="#Url.Action("GetImage", "Beheer", new { productId = Model[i].product_id }) " alt="pasfoto"/><br />
<center><b>#Html.ActionLink(Model[i].naam, "PrProduct", "Categorie", new { id = Model[i].product_id }, null)</b></center>
<center>€ #Html.Label(Model[i].prijs)</center>
</td>
}
</tr>
Use the modulo operator %. Each time i%5 == 0, print a row around the td
#for (int i = 0; i < Model.Count; i++)
{
#if(i%5 == 0)
{
<tr>
}
<td>
<img width="200px" src="#Url.Action("GetImage", "Beheer", new { productId = Model[i].product_id }) " alt="pasfoto"/><br />
<center><b>#Html.ActionLink(Model[i].naam, "PrProduct", "Categorie", new { id = Model[i].product_id }, null)</b></center>
<center>€ #Html.Label(Model[i].prijs)</center>
</td>
#if(i%5 == 0)
{
</tr>
}
}
So you're going to have a table row when i is 0, 5, 10, 15, etc.
#for (int i = 0; i < Model.Count; i++)
{
#if(i%5 == 0)
{
<tr></tr>
}
<td>
<img width="200px" src="#Url.Action("GetImage", "Beheer", new { productId = Model[i].product_id }) " alt="pasfoto"/><br />
<center><b>#Html.ActionLink(Model[i].naam, "PrProduct", "Categorie", new { id = Model[i].product_id }, null)</b></center>
<center>€ #Html.Label(Model[i].prijs)</center>
</td>
}
The above code worked for me. Is it not much different from the answer Havelock gave, but it will not close the brackets in the above code if you do not close the html tags within the same if statement. This way may not look as good if you use borders because I think it will display one empty row? But, for me this worked fine:)
I want have a table in my view that is going to put 3 elements from my Model in each row. So the way I was going to do this is to loop through the model and inside of the foreach loop do a check on a count variable I have set up. If count mod 3 == 0 I would do something like </tr><tr> to start a new row. This isn't working the way I want it to because I would have a } following the <tr>. So basically my question is, how would I create a dynamic table inside of a razor view based on the elements in the model where each row has 3 items?
#{
int count = 0;
<div>
<table>
<tr>
#foreach (var drawing in Model)
{
<td style="width:240px;margin-left:30px; margin-right:30px;">
<img src="#Url.Action("GetImage", "Home", new { id = drawing.drw_ID })" alt="drawing" />
</td>
count++;
if(count%3==0)
{
</tr>
<tr>
}
}
</tr>
</table>
</div>
}
Maybe there is a much easier way of doing this that I am not thinking of
How about using two loops - this will make your document be setup much more nicely and make it a bit more readable. Also, it takes care of the problems that occur if the number of rows is not divisible by three:
<div>
<table>
#for(int i = 0; i <= (Model.Count - 1) / 3; ++i) {
<tr>
for(int j = 0; j < 3 && i + j < Model.Count; ++j) {
<td style="width:240px;margin-left:30px; margin-right:30px;">
<img src="#Url.Action("GetImage", "Home", new { id = Model[i + j].drw_ID })" alt="drawing" />
</td>
}
</tr>
}
</table>
</div>
Edited to reflect your pasted code. Note, this assumes the model implements IList or an array
Maybee this is the solution you are looking for works for me
#{
int count = 0;
**
var tr = new HtmlString("<tr>");
var trclose = new HtmlString("</tr>");
**
<div>
<table>
<tr>
#foreach (var drawing in Model)
{
<td style="width:240px;margin-left:30px; margin-right:30px;">
<img src="#Url.Action("GetImage", "Home", new { id = drawing.drw_ID })" alt="drawing" />
</td>
count++;
if(count%3==0)
{
**
trclose
tr
**
}
}
</tr>
</table>
</div>
}
Check this out, this should work for you !!!
<h2>Index</h2>
<table>
<tr>
#{
var index = 0;
}
#foreach (int num in Model)
{
if ((index % 10) == 0)
{
#Html.Raw("</tr>");
#Html.Raw("<tr>");
}
<td>
<h2>#num</h2>
</td>
index++;
}
</tr>
</table>
The #christian solution worked for me.I was not sure of "trclose" and "tr" hence posting here the solution that worked for me in razor view.
<table>
<tr><td><input type="checkbox" id="chkAssetCategories" /> SELECT ALL</td></tr>
<tr>
#{
var count=0;
foreach (var item in Model.AssetCategories)
{
<td><input type="checkbox" class = "Catgories" id='#item.ID' value ='#item.ID' /><label>#item.Name</label></td>
if (count%5 == 0)
{
#:</tr><tr>
}
count++;
}
}
</table>
#{ int counter = 0;}
<div>
<table>
#for(int i = 0; i <= (Model.Count - 1) / 3; ++i) {
<tr>
for(int j = 0; j < 3; ++j) {
<td style="width:240px;margin-left:30px; margin-right:30px;">
#Model[counter]
</td>
counter++;
}
</tr>
}
</table>
</div>
I have 3 paragraphs of text on a page...I want to change the font size of the paragraphs after every 3 seconds....is this possible?
What i want is when the page loads para 1 is 10px and para 2 is 8px and then after 3 seconds para 2 is 10px and para 1 is 8px.
I mean like using an update panel or something? js ...any way?
You can use the setInterval method to run a function at an interval:
CSS:
#para1 { font-szie: 10px; }
#para2 { font-szie: 8px; }
#para3 { font-szie: 8px; }
HTML:
<p id="para1">asdf</p>
<p id="para2">asdf</p>
<p id="para3">asdf</p>
Javascript:
window.onload = function(){
var current = 0;
var ids = ['para1', 'para2', 'para3'];
window.setInterval(function(){
current = (current + 1) % 3;
for (var i = 0; i < ids.length; i++) {
document.getElementById(ids[i]).style.fontSize = (i == current ? '10px' : '8px');
}
}, 3000);
};
Try this:
<div>
<p id="p1">Para1 </p>
<p id="p2">Para2 </p>
</div>
$(function() {
var pa1 = 20, pa2 = 8, pa3;
$('#p1').css('fontSize', pa1);
$('#p2').css('fontSize', pa2);
function fstyle() {
pa3 = pa1;
pa1 = pa2;
pa2 = pa3;
$('#p1').css('fontSize', pa1);
$('#p2').css('fontSize', pa2);
}
setInterval(fstyle, 3000);
});