Add a class to "selected" column headers in SlickGrid - slickgrid

When a cell is selected in SlickGrid, how can I apply a class to it's column header?
If you look at Excel or Google docs, both apply an effect to the header cell to give a visual indication of which cell is selected. I want to add this effect to SlickGrid, but I am not sure how.

The headerCssClass column option will apply styling to the cells but that would require the headers to be rendered again to apply the changes.
So the primary events of concern are onActiveCellChanged and if applicable onColumnsReordered. I've chosen instead to subscribe to onHeaderRowCellRendered as that will also be called after a column reorder.
<html>
<link rel="stylesheet" type="text/css" href="http://mleibman.github.io/SlickGrid/slick.grid.css">
<link rel="stylesheet" href="http://mleibman.github.io/SlickGrid/examples/examples.css" type="text/css"/>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
<script src="http://mleibman.github.io/SlickGrid/lib/jquery.event.drag-2.2.js"></script>
<script src="http://mleibman.github.io/SlickGrid/slick.core.js"></script>
<script src="http://mleibman.github.io/SlickGrid/slick.grid.js"></script>
<style>
.selected_header {
background: #b8f8A8;
}
</style>
<div id="myGrid" style="width:500px;height:100px;"></div>
<script>
var grid;
var data = [];
var columns = [
{id: "server", name: "Server", field: "server", width: 180}
];
for (var i = 0; i < 4; i++) {
columns.push({
id: "id" + i,
name: "Id" + i,
field: i
});
}
var options = {
editable: false,
showHeaderRow: true,
headerRowHeight: 30,
enableCellNavigation: true
};
$(function () {
for (var i = 0; i < 5; i++) {
var d = (data[i] = {});
d.server = "Server " + i;
for (var j = 0; j < columns.length; j++) {
d[j] = Math.round(Math.random() * 100);
}
}
grid = new Slick.Grid("#myGrid", data, columns, options);
grid.onActiveCellChanged.subscribe(function(e, args){
var headerColumns = $('.slick-header-columns').children();
for(i = 0; i< headerColumns.length; ++i){
$(headerColumns[i])[i == args.cell ? "addClass" : "removeClass" ]('selected_header')
}
})
grid.onHeaderRowCellRendered.subscribe(function(e, args){
if(grid.getActiveCell() ){
var columnIndex = grid.getActiveCell().cell
var headers = $('.slick-header-columns').children()
if(headers.length < columnIndex){return;}
$(headers[columnIndex]).addClass('selected_header')
}
})
});
</script>
</html>

Related

JQueryUI autocomplete search with Django not working

I am working on a project with Django, for a restaurant management system. I wanted to use an autocomplete feature to take orders at the table.
As far as I understand JQueryUI function autocomplete() is what I need.
However I cannot seem to get it to work.
Following is my my HTML code for the page. It works in such a way that once the number of people in the party is inserted the same number of form input fiels is inserted in the table by a Javascrip script.
addOrder.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<script type="text/javascript" src={% static "js/jquery-3.3.1.min.js" %}></script>
<script src={% static "js/jquery-ui.min.js" %}></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src={% static "js/createOrderIn.js" %}> </script>
<script type="text/javascript" src={% static "js/autocompleteDrink.js" %}></script>
<script type="text/javascript" src={% static "js/autocompleteMenu.js" %}></script>
<style>
.move {
margin: 30px;
}
</style>
<title>Add Order</title>
</head>
<body>
<div class="move">
<form action="/orders/addOrder" method="post" id="the-form" class="ui-widget">
<label> Party of </label>
<input type="text" id="people">
<input type="submit" class="btn btn-primary" value="Submit order">
</form>
</div>
</body>
</html>
This is the script I use to spawn new form input fields
createOrderIn.js
$(document).ready(function () {
var previous = 0;
var considered = 0;
$("#people").keyup(function ( ) {
var actual = this.value;
if(actual==null){
actual=1;
}
var toAdd = actual-previous;
previous = actual;
if(toAdd > 0){
for(var i=0; i<toAdd; i++){
considered+=1;
var htmlToAdd = $("<div class="+considered+"><input type=\"text\" name=\"menu_"+considered+"\" id=\"menu\"><input type=\"text\" name=\"drink_"+considered+"\" value=\"No drink\" id=\"drink\"><br></div>");
$("#the-form").append(htmlToAdd);
}
}
else{
for(var j=0; j<(-1*toAdd); j++) {
if (considered > 0) {
$("."+considered).remove();
considered -= 1;
}
}
}
});
});
The following are the relative Python/Django files
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.ordersIndex, name = "index"),
path('changeStatus/<int:pk>', views.changeStatus, name="changeStatus"),
path('addOrder', views.addOrder, name="addOrder"),
path('addOrderRender', views.addOrderRender, name="addOrderRender"),
path('getDrinks', views.getDrinks, name="getDrinks"),
path('getMenus', views.getMenus, name="getMenu"),
]
views.py (only function getMenus())
def getMenus(request):
print("I am called")
if request.is_ajax():
q = request.GET.get('term', '')
menus = Menu.objects.filter(name__contains=q)
results=[]
for menu in menus:
menu_json = {}
menu_json['name'] = menu.name
menu_json['n_courses'] = menu.number_of_courses
menu_json['price'] = menu.price
results.append(menu_json)
data = json.dump(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
And lastly this is the function that is supposed to use JQueryUI to make the ajax call and retrieve the possible menu's
autocompleteMenu.js
$(function() {
$("#menu").autocomplete({
source: "/orders/getMenus/",
});
});
As you can probably see from the getMenus() function in views.py I also print a check line ("I am called"), which sure enough does not get printed on console. Also even by switching the autocomplete() source parameter to a local array there is no result.
I do feel like I am doing some very naive mistake but I really cannot seem to figure it out (I am also pretty new with JQuery).
I think the error should be in the provided files, but I'll be happy to post edits in just in case
Thank you in advance!
I realized that the problem was due to the fact that I had to bind autocomplete to the id of the newly created id's (which I changed to classes). Also the JSON data must have a lable field, (and I had to use json.dumps(), not json.dump() :p).
The followings did the trick:
createOrderIn.js
$(document).ready(function () {
var previous = 0;
var considered = 0;
$("#people").keyup(function ( ) {
var actual = this.value;
if(actual==null){
actual=1;
}
var toAdd = actual-previous;
previous = actual;
if(toAdd > 0){
for(var i=0; i<toAdd; i++){
considered+=1;
var htmlToAdd = $("<div class="+considered+"><input type=\"text\" name=\"menu_"+considered+"\" class=\"menu\"><input type=\"text\" name=\"drink_"+considered+"\" value=\"No drink\" class=\"drink\"><br></div>");
$("#the-form").append(htmlToAdd);
$('#the-form').find('input[class=menu]:last').autocomplete({
source: "/orders/getMenus"
});
$('#the-form').find('input[class=drink]:last').autocomplete({
source: "/orders/getDrinks"
});
}
}
else{
for(var j=0; j<(-1*toAdd); j++) {
if (considered > 0) {
$("."+considered).remove();
considered -= 1;
}
}
}
});
});
views.py
def getDrinks(request):
if request.is_ajax():
q = request.GET.get('term', '')
drinks = Drink.objects.filter(name__contains=q)
results=[]
for drink in drinks:
drink_json = {}
drink_json['label'] = drink.name
results.append(drink_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
def getMenus(request):
if request.is_ajax():
q = request.GET.get('term', '')
menus = Menu.objects.filter(name__contains=q)
results=[]
for menu in menus:
menu_json = {}
menu_json['label'] = menu.name
menu_json['id'] = menu.number_of_courses
results.append(menu_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)

Ace editor blurring the text

I'd like to use the Ace Editor to display program code as part of a tutorial, like Twilio does.
How can I tell Ace to highlight some text and blur the rest? See below.
add a css class for applying blur filter, and add blur class to lines from afterRender event
editor.renderer.on("afterRender", function(e, renderer) {
var textLayer = renderer.$textLayer;
var config = textLayer.config;
var session = textLayer.session;
var first = config.firstRow;
var last = config.lastRow;
var lineElements = textLayer.element.childNodes;
var lineElementsIdx = 0;
var row = first;
var foldLine = session.getNextFoldLine(row);
var foldStart = foldLine ? foldLine.start.row : Infinity;
var useGroups = textLayer.$useLineGroups();
while (true) {
if (row > foldStart) {
row = foldLine.end.row + 1;
foldLine = textLayer.session.getNextFoldLine(row, foldLine);
foldStart = foldLine ? foldLine.start.row : Infinity;
}
if (row > last)
break;
var lineElement = lineElements[lineElementsIdx++];
if (lineElement) {
if (row < 2 || row > 7 && row < 23 || row > 25)
lineElement.classList.add("blur")
}
row++;
}
})
.ace_line.blur {
-webkit-filter: blur(0.1em);
-moz-filter: blur(0.1em);
-ms-filter: blur(0.1em);
-o-filter: blur(0.1em);
filter: blur(0.1em);
}
<script src="https://ajaxorg.github.io/ace-builds/src/ace.js"></script>
<style>
html, body, #editor { height: 100%; margin: 0; padding: 0 }
</style>
<pre id="editor"></pre>
<div id="return"></div>
<script>
var editor = ace.edit("editor");
editor.session.setMode("ace/mode/html");
editor.session.setValue(document.documentElement.outerHTML);
</script>

How to avoid image flicker in IE using timer

I have the following code which causes smooth playback in Chrome. but in IE10 it causes a flicker. Are there workarounds at all?
Thanks
HTML
<a href="#" title="Play Motion Clip from Beginning">
<img alt="Play Motion" src="../Images/play_green_controls.png" style="border-style: none; width: 32px; height: 32px; background-color: #000000; cursor: pointer;"
id="btnPlay" />
</a>
<div id="divImage" >
hello andy
</div>
Javascript
<script type="text/javascript">
var cache = [];
var cacheImage = document.createElement('img');
var interval = 100;
var _total = 0;
$("#btnPlay").click(function () {
$.ajax({
type: "POST",
url: "Default3.aspx/GetClips",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
cache = [];
_total = 0;
$.each(msg.d, function () {
var cacheImage = document.createElement('img');
cacheImage.src = this['Text'];
cache[_total] = cacheImage;
_total++;
}
);
setInterval('swapImages()', interval);
},
error: function (msg) {
alert(msg.d);
}
});
});
var div = document.getElementById('divImage');
var _index = 0;
function swapImages() {
if (_index < _total) {
if (_index > 0) {
div.removeChild(cache[_index - 1]);
}
div.appendChild(cache[_index]);
}
else {
interval = 0;
}
_index++;
if (_index == _total)
{
div.removeChild(cache[_index - 1]);
_index = 0;
div.appendChild(cache[_index]);
}
}
Code Behind:
[WebMethod]
public static ArrayList GetClips()
{
ArrayList _arr = new ArrayList();
int _max = 250; //seems to be safe
string[] _files = Directory.GetFiles(#"C:\Cloud\Catalogues\000EC902F17F\2\2013\10\6\10\f1fe61da-4684-48ed-a503-4a5586ece9c8","*.jpg"); //731
for (int _index = 0; _index < _files.Length; _index++)
{
string _file = _files[_index];
string[] _bits = _file.Split('\\');
string _url = "Portal/Catalogues/000EC902F17F/2/2013/10/6/10/f1fe61da-4684-48ed-a503-4a5586ece9c8/" + _bits[10];
ListItem _item = new ListItem();
_item.Text = _url;
_arr.Add(_item);
if (_index == _max - 1)
{
break;
}
}
return _arr;
}

jQGrid asp.net mvc 3 implementation from scratch

I am trying to implement jQGrid in my application with some basic features including filtering and sub grid. I looked numerous articles but many of them seem to be old and outdated. I think i am struggling with the basics of implementing it. I will really appreciate if you can provide basic controller view structure or refer to any sort of tutorial from scratch with asp. net mvc 3.
Here is the code in the View (first mark-up, then JS):
#model SampleApp.SampleModel
#{
ViewBag.Title = "Stackoverflow Title";
Layout = "~/Views/Shared/_defaultLayout.cshtml";
}
<link href="#Url.Content("~/Content/themes/cupertino/jquery-ui-1.8.13.custom.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/grid/ui.jqgrid.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/ui/jquery-ui-1.8.12.custom.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/grid/grid.locale-en.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/grid/jquery.jqGrid.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/myJSHelper.js")" type="text/javascript"></script>
<script type="text/javascript" id="loadGridResultsScript1">
// This code LOADs the grid by calling the MVC Action to get Data
$(document).ready(function () { helper.loadSearchResults('#Model.JobCode'); });
</script>
<!-- these are the jQuery Grid controls -->
<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
<div id="pager" class="scroll" style="text-align:center;"></div>
Here is the JS function from myHelper JS file:
loadSearchResults: function (id) {
$("#list").jqGrid({
url: vpath + '/Sample/GetTargets/' + id,
datatype: 'json', mtype: 'POST', colNames: cols,
colModel: colModel, pager: $('#pager'),
rowNum: 15, rowList: [5, 10, 15, 25, 50, 100], sortname: cols[1],
sortorder: "asc", viewrecords: true,
imgpath: '', caption: ' '
});
$("#list").setGridWidth(1000, true);
$("#list").setGridHeight(350, true);
}
and here is the Action that jQuery calls:
public ActionResult GetTargets(string id, string sidx, string sord, int page, int rows)
{
var repo = IOCContainer.Resolve<DataRepository>();
////////////////////////////////////////////////////////////////////
var job = svc.GetJobByCode(id);
// job is my 'Model', it is a System.Data.DataSet
int pageIndex = Convert.ToInt32(page) - 1;
int pageSize = rows;
int totalRecords = (job.Targets == null) ? 0 : job.Tables[0].Rows.Count;
int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
List<DataRow> pageSet = Enumerable.Empty<DataRow>().ToList();
if (totalRecords > 0)
{
// Get rows for current page!!!
if (sord == "asc")
{
if (sidx == " ") sidx = job.Tables[0].Columns[0].ColumnName;
pageSet = job.Tables[0].Rows.Cast<DataRow>()
.OrderBy(q => q[sidx])
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToList();
}
else
pageSet = job.Targets.Tables[0].Rows.Cast<DataRow>()
.OrderBy(q => q[sidx])
.Reverse()
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToList();
}
var cols = GetColumnNames(job.Tables[0]);
// Func to get Cells, called later on in code...
Func<DataRow, string[], string[]> getCells = (pkg, columns) =>
{
var cellList = new List<string>();
cellList.Add(pkg[0].ToString());
foreach (var col in columns)
{
if (col.StartsWith("_")) continue;
object cellContent = pkg[col];
string cellText = string.Empty;
if (cellContent is DateTime)
{
cellText = ((DateTime)cellContent).ToString("MM/dd/yyyy");
}
else if (cellContent is decimal || cellContent is double)
{
cellText = string.Format("{0:c}", cellContent);
}
else
{
cellText = String.Format("{0}", cellContent);
}
cellList.Add(cellText);
}
return cellList.ToArray();
};
var jsonData = new
{
total = totalPages,
page,
records = totalRecords,
rows = (
from item in pageSet
select new
{
i = item[0].ToString(),
cell = getCells(item, cols)
}).ToArray()
};
return Json(jsonData);
}
I hope you find this helpful. Let me know if there are any questions

changing rally basic dropdown menus after display

I have a rally.sdk.ui.basic.Dropdown menu in a Rally App that I would like to change based on user input. So I will call display() on the dropdown menu, and then later I want to change the contents of that menu.
Has anybody done this? When I try, it crashes. I've also tried calling destroy() on the dropdown menu and then calling display() on a new menu that I allocate, but that crashes as well with an obscure dojo error.
Any suggestions on how to change dropdown menus on the fly?
I've included a very stripped down example below of trying to destroy and then re-display the menu:
<html>
<head>
<title>Incoming Defects by Severity</title>
<meta http-equiv="X-UA-Compatible" content="IE=7" >
<meta name="Name" content="Defects by Severity" />
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.29/sdk.js"></script>
<script type="text/javascript">
function DefectChart() {
this.display = function() {
var defectVersionDropdown;
var count = 1;
function makeDefectChart(results){
initDefectVersionDropdown();
};
function renderPage() {
var queryConfig = [];
var startDate = '2011-06-06';
var endDate = '2012-02-02';
var queryArray = ['CreatedDate >= "' + startDate + '"', 'CreatedDate <= "' + endDate + '"'];
var versionFilter = defectVersionDropdown ? defectVersionDropdown.getDisplayedValue() : 'ALL';
if (versionFilter != 'ALL') {
queryArray.push('FoundInBuild contains "' + versionFilter + '"');
}
// console.log(queryArray);
queryConfig.push({
type : 'Defects',
key : 'defects',
query: rally.sdk.util.Query.and(queryArray),
fetch: 'Severity,State,LastUpdateDate,CreationDate,OpenedDate,AcceptedDate,LastUpdateDate,ClosedDate,Environment,FoundInBuild'
});
rallyDataSource.findAll(queryConfig, makeDefectChart);
}
function defectVersionChange(sender, eventArgs) {
var version = eventArgs.value;
renderPage();
}
function initDefectVersionDropdown() {
if (defectVersionDropdown != null) {
defectVersionDropdown.destroy();
defectVersionDropdown = null;
}
if (defectVersionDropdown == null) {
console.log('initDefectVersionDropdown');
count++;
var menuItems = [{label: "ALL", value: "ALL"}];
for (var i=0; i < count; i++) {
menuItems.push({label: count, value: count});
}
var config = {
label: "Found In Version:",
items: menuItems
};
defectVersionDropdown = new rally.sdk.ui.basic.Dropdown(config);
defectVersionDropdown.addEventListener("onChange", defectVersionChange);
defectVersionDropdown.display("defectVersionDiv");
}
}
var workspaceOid = '__WORKSPACE_OID__'; if (workspaceOid.toString().match(/__/)) { workspaceOid = XXX; }
var projectOid = '__PROJECT_OID__'; if (projectOid.toString().match(/__/)) { projectOid = XXX; }
rallyDataSource = new rally.sdk.data.RallyDataSource( workspaceOid,
projectOid,
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
initDefectVersionDropdown();
renderPage();
}
}
function getDataAndShow() {
var defectChart = new DefectChart();
defectChart.display();
}
function loadRally() {
rally.addOnLoad(getDataAndShow);
}
loadRally();
</script>
</head>
<body>
<div id="defectVersionDiv"></div>
</body>
</html>
Destroying the old one creating and displaying a new one is the correct way to do this. This is a common pattern when developing apps using the App SDK. If you provide a code snipped along with the dojo error you are getting the community can probably be of better assistance.

Resources