jqGrid free and ace admin template integration - templates

I'm trying to play around with various admin templates and ran on to an old Bootstrap 3 one which has jqGrid support. While the demo is working great but it uses the commercial version and not the free jqGrid.
In the link to the repository of source of the demo here (Ace Admin Template), the main file is call jqgrid.html, if I use the most recent free jqGrid as shown below, then the attributes of the button images are no longer working. See the attached pictures.
Tests with commercial jqGrid:
Tests with free jqGrid
I replace the below lines
<script src="assets/js/jquery.jqGrid.min.js"></script>
by these one
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
<link rel="stylesheet" href="https://rawgit.com/free-jqgrid/jqGrid/master/css/ui.jqgrid.min.css ">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css">
<script src="https://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.min.js"></script>
So my question is what is the new code I should replace to fix this, since the below code is called in beforeShowForm?
//update buttons classes
var buttons = form.next().find('.EditButton .fm-button');
buttons.addClass('btn btn-sm').find('[class*="-icon"]').hide();//ui-icon, s-icon
buttons.eq(0).addClass('btn-primary').prepend('<i class="ace-icon fa fa-check"></i>');
buttons.eq(1).prepend('<i class="ace-icon fa fa-times"></i>')
With the premium version (Guriddo jqGrid JS - v5.0.2 - 2016-01-18), it works like a charm, see working premium images and free jqGrid images, but when I switched to free jqGrid, the buttons text are not working making hard to read action texts.
This great admin template is a nice add-on to free jQgrid to complete my side project. Not sure where to buy it since it is no longer available for purchase Ace Admin Template Info.
Updated
I still have one small display issue on the header, below is the screen shot
I used one of your demo code so you can reproduce it.
<script type="text/javascript">
jQuery(function($) {
var grid_selector = "#grid-table";
var pager_selector = "#grid-pager";
var parent_column = $(grid_selector).closest('[class*="col-"]');
//resize to fit page size
$(window).on('resize.jqGrid', function () {
$(grid_selector).jqGrid( 'setGridWidth', parent_column.width() );
})
//resize on sidebar collapse/expand
$(document).on('settings.ace.jqGrid' , function(ev, event_name, collapsed) {
if( event_name === 'sidebar_collapsed' || event_name === 'main_container_fixed' ) {
//setTimeout is for webkit only to give time for DOM changes and then redraw!!!
setTimeout(function() {
$(grid_selector).jqGrid( 'setGridWidth', parent_column.width() );
}, 20);
}
})
//if your grid is inside another element, for example a tab pane, you should use its parent's width:
/**
$(window).on('resize.jqGrid', function () {
var parent_width = $(grid_selector).closest('.tab-pane').width();
$(grid_selector).jqGrid( 'setGridWidth', parent_width );
})
//and also set width when tab pane becomes visible
$('#myTab a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
if($(e.target).attr('href') == '#mygrid') {
var parent_width = $(grid_selector).closest('.tab-pane').width();
$(grid_selector).jqGrid( 'setGridWidth', parent_width );
}
})
*/
$.jgrid.icons.aceFontAwesome = $.extend(true, {},
$.jgrid.icons.fontAwesome,
{
nav: {
add: "fa-plus-circle",
view: "fa-search-plus",
},
actions: {
save: "fa-check",
cancel: "fa-times"
},
pager: {
first: "fa-angle-double-left",
prev: "fa-angle-left",
next: "fa-angle-right",
last: "fa-angle-double-right"
},
form: {
prev: "fa-angle-left",
next: "fa-angle-right",
save: "fa-check",
cancel: "fa-times"
}
}
);
$.jgrid.icons.aceFontAwesome = $.extend(true, {},
$.jgrid.icons.fontAwesome,
{
nav: {
add: "fa-plus-circle",
view: "fa-search-plus",
},
actions: {
save: "fa-check",
cancel: "fa-times"
},
pager: {
first: "fa-angle-double-left",
prev: "fa-angle-left",
next: "fa-angle-right",
last: "fa-angle-double-right"
},
form: {
prev: "fa-angle-left",
next: "fa-angle-right",
save: "fa-check",
cancel: "fa-times"
}
}
);
var data = [
{code:"A", name:"Project A",
jan2017:1, feb2017:0, mar2017:0, apr2017:0,
may2017:0, jun2017:0, jul2017:0, aug2017:0,
sep2017:0, oct2017:0, nov2017:0, dec2017:1},
{code:"A", name:"Project A",
jan2017:1, feb2017:1, mar2017:0, apr2017:0,
may2017:1, jun2017:0, jul2017:0, aug2017:0,
sep2017:0, oct2017:1, nov2017:0, dec2017:0}
],
intTemplate = {
width: 20, template: "integer",
align: "center", editable: true
};
jQuery(grid_selector).jqGrid({
colModel: [
{ name: "code", label: "Code", width: 50, align: "center" },
{ name: "name", label: "Name", width: 70 },
{ name: "jan2017", label: "Jan", template: intTemplate },
{ name: "feb2017", label: "Feb", template: intTemplate },
{ name: "mar2017", label: "Mar", template: intTemplate },
{ name: "apr2017", label: "Apr", template: intTemplate },
{ name: "may2017", label: "May", template: intTemplate },
{ name: "jun2017", label: "Jun", template: intTemplate },
{ name: "jul2017", label: "Jul", template: intTemplate },
{ name: "aug2017", label: "Aug", template: intTemplate },
{ name: "sep2017", label: "Sep", template: intTemplate },
{ name: "oct2017", label: "Oct", template: intTemplate },
{ name: "nov2017", label: "Nov", template: intTemplate },
{ name: "dec2017", label: "Dec", template: intTemplate },
{ name: "jan2018", label: "Jan", template: intTemplate },
{ name: "feb2018", label: "Feb", template: intTemplate },
{ name: "mar2018", label: "Mar", template: intTemplate },
{ name: "apr2018", label: "Apr", template: intTemplate },
{ name: "may2018", label: "May", template: intTemplate },
{ name: "jun2018", label: "Jun", template: intTemplate },
{ name: "jul2018", label: "Jul", template: intTemplate },
{ name: "aug2018", label: "Aug", template: intTemplate },
{ name: "sep2018", label: "Sep", template: intTemplate },
{ name: "oct2018", label: "Oct", template: intTemplate },
{ name: "nov2018", label: "Nov", template: intTemplate },
{ name: "dec2018", label: "Dec", template: intTemplate }
],
cmTemplate: { autoResizable: true },
autoResizing: { compact: true },
viewrecords: true,
data: data,
iconSet: "fontAwesome",
rownumbers: true,
sortname: "invdate",
sortorder: "desc",
pager: true,
iconSet: "aceFontAwesome", //"fontAwesome",
grouping: true,
rowNum: 10,
rowList: [5, 10, 20, "10000:All"],
groupingView: {
groupField: ["name"],
groupText: ["<b>{0}</b>"]
},
loadComplete : function() {
var table = this;
var parent_column = $(grid_selector).closest('[class*="col-"]');
setTimeout(function(){
$(grid_selector).jqGrid( 'setGridWidth', parent_column.width() );
}, 0);
},
sortname : 'invid',
inlineEditing: {
keys: true
},
navOptions: {
add: false,
edit: false,
del: false,
search: false
},
inlineNavOptions: {
add: true,
edit: true
},
caption: "Test"
}).jqGrid("navGrid")
.jqGrid("inlineNav")
.jqGrid("rotateColumnHeaders",
["jan2017", "feb2017", "mar2017", "apr2017", "may2017", "jun2017",
"jul2017", "aug2017", "sep2017", "oct2017", "nov2017", "dec2017",
"jan2018", "feb2018", "mar2018", "apr2018", "may2018", "jun2018",
"jul2018", "aug2018", "sep2018", "oct2018", "nov2018", "dec2018"])
.jqGrid('setGroupHeaders', {
useColSpanStyle: true,
groupHeaders: [
{ startColumnName: 'code', numberOfColumns: 2, titleText: '<i>Project</i>' },
{ startColumnName: 'jan2017', numberOfColumns: 12, titleText: '2017' },
{ startColumnName: 'jan2018', numberOfColumns: 12, titleText: '2018' }
]
});
});
I replaced the above code in jqgrid.html. I don't know what really causes it. Could it be rotateColumnHeaders which breaks it?
Pic shows moving code after setgroupheader. The vertical lines are still cut.
More updates
After investigation and trial by error, I found out the issue but it masks an another one, I no longer have header issues but the buttons do not display nicely. Is there anyway to overwrite the css to make them look like the one without using the line : guistyle:bootstrap, seems like jqueryUI is conflicting some how with ace css.
Fix header, by adding : guiStyle: "bootstrap", action buttons do not look good. Blue color header is also gone along with button colors
Removing guiStyle: "bootstrap" breaks header, blue color header, action button look nicely
I've tried to reproduce with jsfiddle but no luck yet.

I looked through the Ace Admin template. One can see that it's created fror old jqGrid, which don't supports Font Awesome and Bootstrap. Free jqGrid supports both (see here and here). One more wiki article describes how one can use other Font Awesome icons to create his own iconSet. For example, one can define
$.jgrid.icons.aceFontAwesome = $.extend(true, {},
$.jgrid.icons.fontAwesome,
{
nav: {
add: "fa-plus-circle",
view: "fa-search-plus",
},
actions: {
save: "fa-check",
cancel: "fa-times"
},
pager: {
first: "fa-angle-double-left",
prev: "fa-angle-left",
next: "fa-angle-right",
last: "fa-angle-double-right"
},
form: {
prev: "fa-angle-left",
next: "fa-angle-right",
save: "fa-check",
cancel: "fa-times"
}
}
);
to use some other icons as defaults (see here). After that one can use iconSet: "aceFontAwesome" option instead of iconSet: "fontAwesome" used typically.
All other CSS settings of Ace Admin template are just customization of the standard CSS. I personally find Ace Admin CSS very nice, but one needs to invest some time to make free jqGrid looks exactly like Ace Admin. One needs no jqGrid knowledge for that. It's enough to use Developer Tools of Chrome to examine CSS used on http://ace.jeka.by/jqgrid.html and to implement the same (or close) settings on free jqGrid. I created the demo http://jsfiddle.net/OlegKi/jj0qbhbt/ which shows how one can do that. One needs just expend CSS settings, which I included in the demo.

Related

ChartJS Choropleth Focusing On US and Not The Entire Earth?

I created this chartJS map to showcase the distribution of registrations for this course. However, i can only see US in the map. Is there an issue with the library or should i use a different project ?
Thank you in Advance
Here is the code:
fetch('https://unpkg.com/world-atlas/countries-50m.json').then((r) => r.json()).then((data) = {
const countries = ChartGeo.topojson.feature(data, data.objects.countries).features;
const dataCountries = <?= json_encode($WorldMapData) ?>;
const chart = new Chart(canvas.getContext("2d"), {
type: 'choropleth',
data: {
labels: countries.map((d) => d.properties.name),
datasets: [{
label: 'Course Registrations',
data: countries.map((d) => ({
feature: d,
value: dataCountries[dataCountries.indexOf(d.properties.name) + 1],
})),
}]
},
options: {
legend: {
display: true
},
scale: {
projection: 'equalEarth'
},
geo: {
colorScale: {
display: true,
position: 'bottom',
quantize: 1,
legend: {
position: 'bottom-right',
},
},
},
}
});
});
This is what I see:
enter image description here
I tried to get a map showcasing the entire earth but it is only showing US.

Representing multiple subsections within a section of a doughnut chart Chart.js

I am currently trying to create a doughnut chart that represents a projects completion with 2 mains sections; complete and incomplete. is there any way that I can make it so that the complete sections is split into multiple subsections which display peoples usernames when hovered without cluttering the legend?
Beneath is an artistic rendition because I feel like I haven't given enough information.
You can use the generateLabels function as described here.
Please take a look at below runnable sample code and see how it works.
var labels = ['Incomplete', 'Sam', 'Claudia', 'Kevin', 'Sonia', 'Kate'];
var data = [14, 5, 4, 3, 7, 5];
new Chart('myChart', {
type: 'doughnut',
data: {
labels: labels,
datasets: [{
data: data,
backgroundColor: labels.map((l, i) => i ? 'yellow' : 'lightblue'),
weight: 0.6
}]
},
options: {
plugins: {
legend: {
labels: {
generateLabels: () => [{
text: 'Incomplete',
fillStyle: 'lightblue',
strokeStyle: 'lightblue',
},
{
text: 'Complete',
fillStyle: 'yellow',
strokeStyle: 'yellow',
}]
}
}
}
}
});
canvas {
max-height: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="myChart"></canvas>

problem with multiple datasets in chart.js

I'm trying to use chart.js to create a bar chart that shows the number of ad impressions in an ad buy by publication. The desired chart would show a bar for each publication representing the number of impressions for the ad on that website.
I thought that this needs to happen as multiple datasets, one for each publication, where each dataset contains one data point. Here's the code I'm using for this approach:
var chartData_webbanner_300x600 = {
labels: ["Publication 1", "Publication 2"],
datasets: [
{
label: "Publication 1",
backgroundColor: "#971317",
data: [30000]
},
{
label: "Publication 2",
backgroundColor: "#0b72ba",
data: [40000]
},
]
};
window.onload = function() {
var ctx_webbanner_300x600 = document.getElementById('chart_webbanner_300x600').getContext('2d');
window.myBar = new Chart(ctx_webbanner_300x600, {
type: 'bar',
data: chartData_webbanner_300x600,
options: {
title: {
display: true,
text: 'Web Banner Impressions'
},
responsive: true,
}
});
}; //window.onload = function()
The resulting chart only shows one bar. Here's a screenshot:
I also tried this as a single dataset, but had no luck there. This is the approach I tried with that:
var chartData_webbanner_300x600 = {
labels: ["Total Impressions"],
datasets: [
{
label: ["Publication 1", "Publication 2"],
backgroundColor: ["#971317","#0b72ba"],
data: [30000,40000]
}
]
};
window.onload = function() {
var ctx_webbanner_300x600 = document.getElementById('chart_webbanner_300x600').getContext('2d');
window.myBar = new Chart(ctx_webbanner_300x600, {
type: 'bar',
data: chartData_webbanner_300x600,
options: {
title: {
display: true,
text: 'Web Banner Impressions'
},
responsive: true,
}
});
}; //window.onload = function()
Here's how that is displaying (with no bars):
Please let me know if you have any ideas on what I'm doing wrong. Thank you for taking the time to help!
I was able to get it working with this code:
var graphData = {
labels: ['Publication 1', 'Publication 2'],
datasets: [{
label: 'Impressions',
data: [30000, 40000],
backgroundColor: [
"#971317",
"#0b72ba"
],
}, ]
};
var ctx_webbanner_300x600 = document.getElementById('chart_webbanner_300x600').getContext('2d');
var chr = new Chart(ctx_webbanner_300x600, {
data: graphData,
type: 'bar',
options: {
scales: {
yAxes: [{
display: true,
ticks: {
beginAtZero: true // minimum value will be 0.
}
}]
}
}
});
This is based on what I found here Setting specific color per label in chart.js and here How to set max and min value for Y axis - which overcame a problem where the scale was starting at the lowest value in my data set.

Sencha Touch: List does not fire itemtap

I am building a small demo application using Sencha touch:
I have run into an issue with the list display followed by the itemtap even firing.I had this working in a previous application but cannot find out why its not firing in the current application
I have added itemtap methods as listeners, on the view, in the controller, but none of them fire. Any ideas on what I am missing?
Thanks In Advance for your help.
PS
Main.js
Ext.define('KapselApp.view.Main', {
extend: 'Ext.navigation.View',
xtype: 'mainview',
requires: [
'KapselApp.view.ExpApproval',
'KapselApp.view.ExpApproval.Details',
'KapselApp.view.ExpApproval.Confirm'
],
config: {
autoDestroy: false,
navigationBar: {
ui: 'sencha',
items: [
{
xtype: 'button',
id: 'editButton',
text: 'Edit',
align: 'right',
hidden: true,
hideAnimation: Ext.os.is.Android ? false : {
type: 'fadeOut',
duration: 200
},
showAnimation: Ext.os.is.Android ? false : {
type: 'fadeIn',
duration: 200
}
},
{
xtype: 'button',
id: 'saveButton',
text: 'Save',
ui: 'sencha',
align: 'right',
hidden: true,
hideAnimation: Ext.os.is.Android ? false : {
type: 'fadeOut',
duration: 200
},
showAnimation: Ext.os.is.Android ? false : {
type: 'fadeIn',
duration: 200
}
}
]
},
items: [
{ xtype: 'expApprovals' }
]
}
});
ExpApproval.view
Ext.define('KapselApp.view.ExpApproval', {
extend: 'Ext.dataview.List',
xtype: 'expApprovals',
config: {
title: 'Expense Approval',
cls: 'x-ExpApprovals',
items: [{
xtype: 'list',
//id: 'expApproval',
store: expApprovals,
itemTpl: ['<div class="headshot" style="background-image:url(ExpType.Images/blue_btn_left.png);"></div>',
'From:{UserName} {WorkItem}',
'<div>Subject:{SUBJECT}</div>'
],
listeners: {
itemtap: function(view, index, item, e){
alert ('itemtap 1');
}
}
}],
itemtap: function(me, index, target, record){
alert ('itemtap');
//do other logic here
}
},
initialize: function() {
console.log ('KapselApp.view.ExpApproval:initialize: ');
}
});
Controller
Ext.define('KapselApp.controller.ExpApprovalApplication', {
extend: 'Ext.app.Controller',
config: {
refs: {
main: 'mainview',
editButton: '#editButton',
expApprovalDetails: 'expapproval-details',
expApprovalList: 'expApprovals',
confirmExpApprovals: 'expapproval-confirm',
contacts: 'contacts',
showContact: 'contact-show',
editContact: 'contact-edit',
saveButton: '#saveButton'
},
control: {
main: {
push: 'onMainPush',
pop: 'onMainPop'
},
editButton: {
tap: 'onContactEdit'
},
expApprovalList: {
itemtap: 'onExpApprovalsSelect'
},
saveButton: {
tap: 'onContactSave'
},
editContact: {
change: 'onContactChange'
},
'expApproval list' : {itemtap: 'onExpApprovalsSelect'},
}
},
onExpApprovalsSelect: function(list, index, node, record) {
alert ('onExpApprovalsSelect');
}
}
Ok .. found the sollution to your problem. You made the same mistake as I did. you overrode the initialize method in the list view without calling in the initiallize method "this.callParent()". By adding this in my code events started firing. I am sure it will work in yours.
So your List initialize handler should look something like this:
initialize: function(){
console.log('eventsView being initialized.');
this.callParent();
},
You can still use the code bellow to check which events are being fired for debugging in similar situations.
---- Previous post ----
I am facing a similar issue. I am extending Ext.dataview.List and have a controller capture the itemtap event but the event does not seem to be firing.
I tried adding the following code to capture all the events being fired... The list seems to fire the show event and the scroll events but no other such as itemtap, etc ...
Ext.define('Override.mixin.Observable', {
override : 'Ext.mixin.Observable',
fireEvent : function(eventName, args) {
console.log('Event:', eventName, args);
this.callOverridden(arguments);
//debugger;
},
fireAction : function(eventName) {
console.log('Action:',eventName);
this.callOverridden(arguments);
}
});
Try adding this code and see if you are getting the itemtap events.
Let me know if you make any progress.

Sencha 2.0 change title toolbar dynamically

I would dynamically change the title of my list titlebar. This is my app.js where you can view my app (see var list where there is the toolbar item and title that I would change)
How can I do this?
Thanks.
var mainForm ;
var mainFormPanel={};
var myStore = Ext.create('Ext.data.Store', {
storeId: 'MyStore',
fields: ['txt']
}); // create()
var list= Ext.create('Ext.List', {
fullscreen: true,
store: 'MyStore',
itemTpl: '{txt}',
items: [{
xtype: 'titlebar',
docked: 'top',
title:'change dinamically this title!!!!'
}] // items (list)
}); // create()
Ext.application({
glossOnIcon: false,
autoMaximize: false,
icon: {
57: 'lib/sencha-touch/resources/icons/icon.png',
72: 'lib/sencha-touch/resources/icons/icon#72.png',
114: 'lib/sencha-touch/resources/icons/icon#2x.png',
144: 'lib/sencha-touch/resources/icons/icon#114.png'
},
phoneStartupScreen: 'lib/sencha-touch/resources/loading/Homescreen.jpg',
tabletStartupScreen: 'lib/sencha-touch/resources/loading/Homescreen~ipad.jpg',
requires: [
'Ext.tab.Panel',
'Ext.form.*',
'Ext.field.*',
'Ext.Button',
'Ext.data.Store'
],
launch: function() {
mainForm = Ext.create('Ext.form.Panel', {
xtype:'formpanel',
items: [
{
xtype: 'textfield',
name : 'distance',
label: 'Distance'
},
{
xtype: 'textfield',
name : 'quantity',
label: 'Quantity'
}
]
});
mainFormPanel={
xtype: 'toolbar',
docked: 'bottom',
layout: {
pack: 'center'
},
items: [
{
xtype: 'button',
text: 'Set Data',
handler: function() {
mainForm.setValues({
distance: '300',
quantity: '25'
})
}
},
{
xtype: 'button',
text: 'Get Data',
handler: function() {
Ext.Msg.alert('Form Values', JSON.stringify(mainForm.getValues(), null, 2));
}
},
{
xtype: 'button',
text: 'Clear Data',
handler: function() {
mainForm.reset();
}
}
]
};
Ext.Viewport.add({
xtype: 'tabpanel',
items: [
{
//each item in a tabpanel requires the title configuration. this is displayed
//on the tab for this item
title: '1-tab',
layout:'fit',
//next we give it some simple html
items: [mainForm,mainFormPanel],
//then a custom cls so we can style it
cls: 'card1'
},
{
//title
title: '2-tab',
layout:'fit',
items: [list],
cls: 'card2'
},
{
//title
title: '3-tabs',
//the items html
items: {
html: 'mia auto',
centered: true
},
//custom cls
cls: 'card3'
}
]
});
}
});
Ext.List component's superclass is Ext.DataView., not Ext.Panel.
Hence, it is not possible to directly add / dock any item inside the Ext.List component.
So, I recommend you to wrap your Ext.List component inside Ext.Panel.
Do it like this,
var myStore = Ext.create('Ext.data.Store', {
storeId: 'MyStore',
fields: ['txt']
}); // create()
var listpanel = new Ext.Panel({
layout: 'fit', // important to make layout as 'fit'
items: [
{
xtype: 'titlebar',
id: 'myTitle',
docked: 'top',
title: 'Before Change title',
items: [
{
xtype:'button',
text:'Change Title',
align:'right',
listeners : {
tap : function() {
Ext.getCmp('myTitle').setTitle('After Title Change');
}
}
}
]
},
{
//Definition of the list
xtype: 'list',
itemTpl: '{txt}',
store: myStore,
}]
});
....
....
{
title: '2-tab',
layout:'fit',
items: [listpanel],
cls: 'card2'
},
....
....
Sample Output :-
Before changing the title
After changing the title
FYI, If you look inside the Ext.List class in Sencha Docs, you will see the following code inside initComponent() method,
if (Ext.isDefined(this.dockedItems)) {
console.warn("List: List is not a Panel anymore so you can't dock items to it. Please put this list inside a Panel with layout 'fit'");
}