FullCalendar: Use Location attribute of Google Calendar Event - javascript

I have setup FullCalendar (v3.8.0) to pull event data from Google Calendar, using qTip2 for displaying event information. This works fine.
I am now trying to display the event's location attribute. Sadly, I cannot seem to figure out how to get FullCalendar to save the information from Google Calendar in the event.
<head>
<meta charset="utf-8">
<title>Test</title>
<meta name="description" content="Test">
<meta name="author" content="Test">
<link rel='stylesheet' href='fullcalendar/fullcalendar.css' />
<link rel='stylesheet' href='qtip/jquery.qtip.min.css' />
<script src='lib/jquery.min.js'></script>
<script src='qtip/jquery.qtip.min.js'></script>
<script src='lib/moment.js'></script>
<script src='fullcalendar/fullcalendar.js'></script>
<script type='text/javascript' src='fullcalendar/gcal.js'></script>
</head>
<body>
<script type='text/javascript'>
$(document).ready(function() {
$('#calendar').fullCalendar({
googleCalendarApiKey: '<<hidden>>',
events: {
googleCalendarId: '<<hidden>>'
},
header: {
left: 'title',
center: 'listWeek, agendaWeek, month',
right: 'prev,next'
},
weekends: false,
eventRender: function(event, element) {
element.qtip({
content: event.description,
title: event.title,
position: {
my: 'center', //Ecke des Tooltips
at: 'center', //Position auf der Seite (auch Target möchlich)
target: $(window)
},
show: 'click'
});
},
eventClick: function(event) {
if (event.url) {
return false;
}
}
});
});
</script>
<div id='calendar'></div>
</body>
I have tried to add the location attribute to EventDef.defineStandardProps, but this apperas to have no effect.
EventDef.defineStandardProps({
// not automatically assigned (`false`)
_id: false,
id: false,
className: false,
source: false,
// automatically assigned (`true`)
title: true,
url: false,
rendering: true,
constraint: true,
overlap: true,
editable: true,
startEditable: true,
durationEditable: true,
color: true,
backgroundColor: true,
borderColor: true,
textColor: true,
location: true
});
This was also discussed at "fullcalendar jQuery - Possible to retrieve description from Google Calendar events?", but the solution provided appears to be outdated and not applicable anymore.
Every other thread about this topic has either no or no conclusive answer.
Which steps can I take to be able to use the event location?

During the eventRender callback (https://fullcalendar.io/docs/event_rendering/eventRender/) you shuld be able to access event.location, assuming Google has provided you with that field in the JSON you receive. You can check the content of the event by inserting the line console.log(JSON.stringify(event)); into your eventRender code, to log the event properties available to you.
FullCalendar happily keeps custom properties on the event object, if the data source supplies them. Once you've got that data, you can insert it into the event's HTML however you please.
I don't know where in the process you were trying to add things to the event standard properties, but anyway that makes no sense - it would just pre-define an empty attribute, it doesn't cause it to be actually populated with anything.

Related

how to use MdPersianDateTime

Here is my code :
<script type="text/javascript">
$('#calan').MdPersianDateTimePicker({
Placement: 'botto',
Trigger: 'focus',
EnableTimePicker: true,
TargetSelector: '',
GroupId: '',
ToDate: false,
FromDate: false,
});
</scrip>
How to use MdPersianDateTime to date in input.
according to PersianDateTimePicker Documents
you can use it by
`$('#id').MdPersianDateTimePicker({targetTextSelector: '#inputTextDate1',targetDateSelector: '#inputHiddenDate1',});`
just
add these files to you html:
<link href="/dist/jquery.md.bootstrap.datetimepicker.style.css" rel="stylesheet"/>
<script src="/dist/jquery.md.bootstrap.datetimepicker.js"></script>
I suggest to add scripts at the end of body tag and after jQuery library.
for Options and Functions you can refer to document

jtable not triggering to clicks made on custom action buttons

My site is code in ASP.NET MVC 3.0.
with libraries:
jQuery 3.0.0,
jQuery Validation 1.17.0,
(I'm not sure which others can be useful mentioning).
My problem happens when testing in Internet Explorer 11, exactly when user press a button created as a "Custom Action" using jTable.org. This test happens in a Windows 2012 Server.
The same site tested on Firefox in same server is working without this or any other issue.
In IE, the regular buttons created by jTable for Create, Edit and Delete actions, are working.
This is the code for the View:
#model SuperSBL2.WebMVC3.ViewModels.HTEList
#{
ViewBag.Title = "Administrar HTEs";
}
#section CssImport{
<style>
div.filtering
{
border: 1px solid #999;
margin-bottom: 5px;
padding: 10px;
background-color: #EEE;
}
</style>
}
<h2>Administrar HTEs</h2>
<div class="filtering">
<form>
<label>Línea de Producción: <input type="text" name="ProductionLineName" id="ProductionLineName" /></label>
<label>Area: <input type="text" name="AreaName" id="AreaName" /></label>
<label>Operación: <input type="text" name="OperationName" id="OperationName" /></label>
<br /><label>Modelo: <input type="text" name="ModelName" id="ModelName" /></label>
<label>Tipo (ensameble/subensamble): <input type="text" name="HTETypeName" id="HTETypeName" /></label>
<button type="submit" id="LoadRecordsButton" class="btn btn-primary">Buscar registros</button>
</form>
</div>
<div id="HTEContainer" style="width: 1200px; "></div>
<br />
<button type="submit" id="GoBack" class="btn btn-default">REGRESAR</button>
<script type="text/javascript">
$(document).ready(function () {
//Localization texts
var spanishMessages = {
serverCommunicationError: 'Error de comunicación con el servidor, no puedo conectarme a la API.',
loadingMessage: 'Obteniendo datos...',
noDataAvailable: 'No hay datos disponibles!',
addNewRecord: 'Nuevo HTE',
editRecord: 'Editar HTE',
areYouSure: 'Estás seguro?',
deleteConfirmation: 'Estás a punto de borrar éste registro. Por favor confirma.',
save: 'Guardar HTE',
saving: 'Grabando',
cancel: 'Cancelar',
deleteText: 'Borrar HTE',
deleting: 'Borrando',
error: 'Error',
close: 'Cerrar',
cannotLoadOptionsFor: 'No puedo cargar opciones para campo {0}',
pagingInfo: 'Mostrando {0} a {1} de {2} registros',
pageSizeChangeLabel: 'Registros',
gotoPageLabel: 'Ir a página',
canNotDeletedRecords: 'No puedo borrar {0} de {1} registros!',
deleteProggress: 'Borrado {0} de {1} registros, procesando...'
};
$('#HTEContainer').jtable({
messages: spanishMessages, //Localizacion
title: 'Lista de HTEs',
paging: true,
pageSize: 10,
sorting: true,
defaultSorting: 'AreaName ASC',
selecting: true,
actions: {
listAction: '#Url.Action("HTEListForGrid")',
deleteAction: '#Url.Action("DeleteHTE")',
updateAction: '#Url.Action("UpdateHTE")',
createAction: '#Url.Action("CreateHTE")'
},
fields: {
HTEHeaderId: {
key: true,
create: false,
edit: false,
list: false
},
HTETypeID: {
title: 'Tipo',
list: true,
edit: false,
create: true,
options: '#Url.Action("GetHTETypeOptions","HTE")'
},
LineID: {
title: 'Línea de Producción',
//width: '35%',
list: true,
options: '#Url.Action("GetProductionLinesOptions","MasterData")'
},
AreaId: {
title: 'Area',
dependsOn: 'LineID', // jTable builds cascade dropdowns!
//width: '35%',
list: true,
options: function (data) {
if (data.source == 'list') {
//Return url of all countries for optimization.
//This method is called for each row on the table and jTable caches options based on this url.
return '/MasterData/GetAreasOptionsByProductionLineID?productionLineId=0';
}
//This code runs when user opens edit/create form or changes continental combobox on an edit/create form.
//data.source == 'edit' || data.source == 'create'
return '/MasterData/GetAreasOptionsByProductionLineID?productionLineId=' + data.dependedValues.LineID;
}
},
OperationID: {
title: 'Operación',
dependsOn: 'AreaId', // jTable builds cascade dropdowns!
//width: '35%',
list: true,
options: function (data) {
if (data.source == 'list') {
//Return url of all countries for optimization.
//This method is called for each row on the table and jTable caches options based on this url.
return '/MasterData/GetOperationOptionsByAreaID?areaId=0';
}
//This code runs when user opens edit/create form or changes continental combobox on an edit/create form.
//data.source == 'edit' || data.source == 'create'
return '/MasterData/GetOperationOptionsByAreaID?areaId=' + data.dependedValues.AreaId;
}
},
ModelID: {
title: 'Modelo',
dependsOn: 'LineID', // jTable builds cascade dropdowns!
//width: '35%',
list: true,
options: function (data) {
if (data.source == 'list') {
//Return url of all countries for optimization.
//This method is called for each row on the table and jTable caches options based on this url.
return '/MasterData/GetModelOptionsByProductionLine?productionLineId=0';
}
//This code runs when user opens edit/create form or changes continental combobox on an edit/create form.
//data.source == 'edit' || data.source == 'create'
return '/MasterData/GetModelOptionsByProductionLine?productionLineId=' + data.dependedValues.LineID;
}
},
OperationAvailableTime: {
title: 'Tiempo disponible',
//width: '35%',
list: true,
edit: false,
create: false
} ,
Effiency: {
title: 'Effciencia',
//width: '35%',
list: true
} ,
RevisionNumber: {
title: '# Revisión',
//width: '35%',
list: true,
edit: false,
create: false,
defaultValue: '0'
},
RevisionDate: {
title: 'Fecha Revisión',
//width: '15%',
type: 'date',
list: true,
edit: false,
create: false,
displayFormat: 'yy-mm-dd'
},
ProductionRate: {
title: 'Producción Diaria',
//width: '35%',
list: true
},
Taktime: {
title: 'Taktime',
//width: '35%',
list: true
},
RequiredHeadCount: {
title: 'Head Count',
//width: '35%',
list: true
},
HTEStatus: {
title: 'Status',
//width: '35%',
list: true,
edit: false,
create: false,
options: '#Url.Action("GetHTEStatusOptions","HTE")'
},
Active: {
title: 'Activo?',
//width: '12%',
type: 'checkbox',
list: true,
edit: false,
create: false,
values: { 'false': 'No Activo', 'true': 'Activo' },
defaultValue: 'true'
},
Overspeed: {
title: 'OverSpeed',
create: true,
edit: true,
list: true
//, defaultValue: #Html.Raw(Json.Encode(ViewBag.OverSpeed))
},
CustomActionAdmin: {
title: '',
//width: '1%',
sorting: false,
create: false,
edit: false,
list: true,
display: function (data) {
if (data.record) {
return '<button title="" id="btnAdmin" class="jtable-command-button glyphicon glyphicon-cog" onclick="transferAdmin(' + data.record.HTEHeaderId + '); return false;"></button>';
}
}
},
CustomActionActivities: {
title: '',
//width: '1%',
sorting: false,
create: false,
edit: false,
list: true,
display: function (data) {
if (data.record) {
return '<button title="" id="btnAdmin" class="jtable-command-button glyphicon glyphicon-wrench" onclick="transferHTEDetails(' + data.record.HTEHeaderId + '); return false;"></button>';
}
}
}
}
});
//Re-load records when user click 'load records' button.
$('#LoadRecordsButton').click(function (e) {
e.preventDefault();
$('#HTEContainer').jtable('load', {
ProductionLineName: $('#ProductionLineName').val(),
AreaName: $('#AreaName').val(),
OperationName: $('#OperationName').val(),
ModelName: $('#ModelName').val(),
HTETypeName: $('#HTETypeName').val()
});
});
//Load all records when page is first shown
$('#LoadRecordsButton').click();
$('#GoBack').click(function (e) {
e.preventDefault();
window.location.replace("/HTE");
});
});
function transferAdmin(hteHeaderId) {
window.location.replace("/HTE/AdminSettings/" + hteHeaderId);
};
function transferHTEDetails(hteHeaderId) {
window.location.replace("/HTE/HTEActivitiesList/?HTEHeaderId=" + hteHeaderId);
};
</script>
<br />
#section scripts {
}
Now, this is the code for the _Layout.cshtml in use:
<!DOCTYPE html>
#{
var jTableStyle = "metro/blue/jtable.css";
if (!string.IsNullOrEmpty(Request["jTableStyle"]))
{
jTableStyle = Request["jTableStyle"];
}
}
<html lang="es-mx">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Super Sistema Balanceo de Líneas - #ViewBag.Title - </title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/metroblue/jquery-ui.css")" rel="stylesheet" type="text/css" />
#*<link href="#Url.Content("~/Content/highlight.css")" rel="stylesheet" type="text/css" />*#
<link href="#Url.Content("~/Scripts/jtable/themes/" + jTableStyle)" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Scripts/syntaxhighligher/styles/shCore.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Scripts/syntaxhighligher/styles/shThemeDefault.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/bootstrap.min.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/base/jquery-ui.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/base/core.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/base/datepicker.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/themes/base/theme.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/bootstrap-theme.min.css")" rel="stylesheet" type="text/css" />
#RenderSection("CssImport", false)
<script src="#Url.Content("~/Scripts/jquery-3.0.0.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-migrate-3.0.0.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.12.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui.unobtrusive-3.0.0.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.date.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#* <script src="#Url.Content("~/Scripts/jquery.validate-vsdoc.js")" type="text/javascript"></script>*#
<script src="#Url.Content("~/Scripts/modernizr-2.8.3.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/syntaxhighligher/shCore.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/syntaxhighligher/shBrushJScript.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/syntaxhighligher/shBrushXml.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/syntaxhighligher/shBrushCSharp.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/syntaxhighligher/shBrushSql.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/bootstrap.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/moment.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/respond.min.js")" type="text/javascript"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jtable/jquery.jtable.js")"></script>
<script src="#Url.Content("~/Scripts/jtablesite.js")" type="text/javascript"></script>
</head>
<body>
#Html.Partial("_NavBar")
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - Super Sistema Balanceo de Líneas</p>
</footer>
</div>
#RenderSection("scripts", required: false)
#RenderSection("CustomScripts", required: false)
</body>
</html>
This is a picture of system in Internet Explorer, displayed as expected:
page displayed in Internet Explorer
You can see the rendering is as expected, not issue on this area with Internet Explorer.
Red arrows indicates the buttons created as Custom Action, once pressed up, nothings happens. When the IE developer tools are displayed, I press the buttons indicated with Read arrows, nothing happens: not even an error in console, not even an error in Network tab, nothing at all. This is error I'm having.
Green arrows indicates the buttons created by jTable for EDIT, CREATE and DELETE actions as part of the grid. These buttons are working perfect. No issue on this area. See these pictures:
Page in IE showing modal for New record
Page in IE showing modal for Edit record
I hopes you guys can provide any idea.
Thanks,
Gerardo.
This a complex senario, so I cannot replicate it.
I observe from your code, that you are adding click handlers via javascript in the button definitions. Have you tried applying the click handler via jQuery
display: function (data) {
var $but = '';
if (data.record) {
$but = $('<button title="" class="jtable-command-button glyphicon glyphicon-cog" ></button>');
$but.click(transferAdmin(data.record.HTEHeaderId));
}
return $but;
}
I would also point out your original code was creating a button using the same id btnAdmin on every row of the table which is neither good practice or useful, so I have omitted that, as it is possibly another reason why IE gets confused.
Thanks #misterP for his reply. After having bad times with this, I managed to understand what was wrong, and fixed it.
Let me try to explain fixes to issue I was having.
1) Main problem was that in IE, my jQuery logic was not working, when it worked in Firefox and Chrome. I was not aware of IE compatilibity modes that are fixed with the meta tag at level. So, on file _layout.chtml, I set the following:
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
...
2) Regarding how I managed the functionality on the custom action, I read online that when working with jQuery targeting dynamic elements, we should start the filtering against a fixed tag --- hence I used ContainerForJTable. I declare a custom attribute seleccionable on the dynamic object:
display: function (data) {
if (data.record) {
return '<button id="' + data.record.FileID + '" class="jtable-command-button glyphicon glyphicon-eye-open seleccionable"></button>';
}
}
3) I wrote a function (outside of the jtable object creation --- $('#ContainerForJTable').jtable({..) to add an event to objects matching a filter using my custom attribute:
$('#ContainerForJTable').on('click', '.seleccionable', function () {
var theID = $(this).attr("id");
//console.log("The id is " + theID);
viewFiles(theID);
});
After these changes, the jtables objects had been working without any issues.
thanks,

Node js, Express and handlebars rendering fullcalendar plugin not working

I have been unable to implement fullcalendar into my application and cannot find any information detailing exactly how to implement it using node, express and handlebars. I've tried multiple ways of adding fullcalendar without any luck. Other web pages in my application are working and render their information so I don't know why fullcalendar won't work after following the instructions on the website.
<!-- main.handlebars -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M"
crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!-- Page level plugin CSS-->
<link href="vendor/datatables/dataTables.bootstrap4.css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- Link and script for calendar -->
<link rel='stylesheet' href='../../node_modules/fullcalendar/dist/fullcalendar.css' />
<script src='../../node_modules/jquery/dist/jquery.min.js'></script>
<script src='../../node_modules/moment/min/moment.min.js'></script>
<script src='../../node_modules/fullcalendar/dist/fullcalendar.js'></script>
<script>
$(document).ready(function() {
// page is now ready, initialize the calendar...
$('#calendar').fullCalendar({
// put your options and callbacks here
header: {
left: 'prev, next, today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
timezone: "local",
defaultView: "month",
firstHour: "7",
weekMode: "liquid"
});
});
</script>
<title>Workmate</title>
</head>
<body>
{{#if user}}
{{> _appNavbar}}
{{else}}
{{> _navbar}}
{{/if}}
<div class="container">
{{> _msg}}
{{> _errors}}
{{{body}}}
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1"
crossorigin="anonymous"></script>
</body>
</html>
After the main.handlebars I have the schedule.handlebars which should load the empty calendar.
<div id='calendar'></div>
I've followed the instructions on the fullcalendar website and it doesn't render the calendar on the schedule.handlebars page.
// webapp.js
//App schedules route
router.get('/schedules', ensureAuthenticated, (req, res) =>{
res.render('webapp/schedules');
});
This is all the code I have to implement the application. Any help will be greatly appreciated as this is for my final year project in college.
Thanking you all in advance.
Not sure if anyone would be interested, but after quite some time spent on trial & errors (lots of errors), I managed to make this work in conjunction with Handlebars.
First, I had to write a separate .js file (calendar.js) for the $(document).ready function:
$(document).ready(function() {
// Let's make sure that this 2 little critters get loaded, otherwise fullcalendar wont work.
$.when (
$.getScript("/s/js/moment.min.js"),
$.getScript("/s/calendar/fullcalendar.min.js"))
.done(function()
{
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'listDay,listWeek,month'
},
// customize the button names,
// otherwise they'd all just say "list"
views: {
listDay: { buttonText: 'list day' },
listWeek: { buttonText: 'list week' }
},
defaultView: 'listWeek',
defaultDate: '2018-03-12',
navLinks: true, // can click day/week names to navigate views
editable: true,
eventLimit: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2018-03-01'
},
{
title: 'Long Event',
start: '2018-03-07',
end: '2018-03-10'
},
{
id: 999,
title: 'Repeating Event',
start: '2018-03-09T16:00:00'
},
{
id: 999,
title: 'Repeating Event',
start: '2018-03-16T16:00:00'
},
{
title: 'Conference',
start: '2018-03-11',
end: '2018-03-13'
},
{
title: 'Meeting',
start: '2018-03-12T10:30:00',
end: '2018-03-12T12:30:00'
},
{
title: 'Lunch',
start: '2018-03-12T12:00:00'
},
{
title: 'Meeting',
start: '2018-03-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2018-03-12T17:30:00'
},
{
title: 'Dinner',
start: '2018-03-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2018-03-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2018-03-28'
}
]
}
);
}
);
});
Then onto the Handlebars template:
<section>
<style>
#calendar {
max-width: 800px;
margin: 0 auto;
}
</style>
<div id='calendar'></div>
and finally my app.jes file looked something like this:
app.get("/", async(req, res, next) => {
try {
let projectid = '2188'
let users = await req.app.locals.db.getRate(projectid);
res.render("listview", {
title: "Calendar",
rows: users,
scripts: ["/js/views/calendar.js"]
});
} catch (ex) {
return next(ex);
}
});
There are a couple of required css files, which were linked on the master Handlebars template.
I'm sure this isn't the best way to integrate it, as I'm really new to NodeJS and overall Javascript, but after a long weekend trying to figure this out, seeing the calendar render was refreshing.
Hope this helps anyone.
cheers!
I can see two potential issues. You are including some local scripts like that:
<!-- Link and script for calendar -->
<link rel='stylesheet' href='../../node_modules/fullcalendar/dist/fullcalendar.css' />
<script src='../../node_modules/jquery/dist/jquery.min.js'></script>
<script src='../../node_modules/moment/min/moment.min.js'></script>
<script src='../../node_modules/fullcalendar/dist/fullcalendar.js'></script>
Do you expose the node_modules directory through express in order to be able to serve those files? Have a look here:
https://expressjs.com/en/starter/static-files.html
It is not good practice though to expose the node_modules directory though, it is better if you have a building step of your application that will copy over all your libraries into a dedicated dist directory and ideally will minify and uglify them as well.
The second thing that can be problematic is the place that you include your script. It is good practice to move all the js imports inside the body just before the body closing tag (). You already defined some there. The document ready function will run but the div with the id calendar will not be there. More details here: Where should I put <script> tags in HTML markup?
Update 1
You need to be able to server the files in the node_modules (it is not a good practice though) like that:
app.use('/modules', express.static(path.join(__dirname, 'node_modules')))
And then include your script paths like that:
<link rel='stylesheet' href='/modules/fullcalendar/dist/fullcalendar.css' />
<script src='/modules/jquery/dist/jquery.min.js'></script>
<script src='/modules/moment/min/moment.min.js'></script>
<script src='/modules/fullcalendar/dist/fullcalendar.js'></script>

Edit master column Title in kendo grid on clicking column headers in detailInit

Following is a kendo grid sample with detailInit:
My requirement is that on sorting a column in a particular sub-grid(detailInit), its header i.e. FirstName field should be changed like shown below:
Just that particular sub-grid's header should be changed. I have tried by registering onclick event in databound function of detailInit but unable to find the column header and change it :
$("th[role='columnheader']").on("click", function (ev) {
// access clicked column in sub- grid
// change master row's title
};
Please someone suggest me a solution as I am new to kendo grid, js, HTML, so not aware of many functions.
Any help would be much appreciated.
Please find my code below :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.3.1028/styles/kendo.common.min.css" />
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.3.1028/styles/kendo.rtl.min.css" />
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.3.1028/styles/kendo.silver.min.css" />
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.3.1028/styles/kendo.mobile.all.min.css" />
<script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.3.1028/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
var element = $("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Employees"
},
pageSize: 6,
serverPaging: true,
serverSorting: true
},
height: 450,
sortable: true,
pageable: true,
detailInit: detailInit,
dataBound: function () {
this.expandRow(this.tbody.find("tr.k-master-row").first());
},
columns: [
{
field: "FirstName",
title: " "
}
]
}).on("click", ".btn-refresh", function (e) {
debugger;
var childGrid = $(e.target).closest(".k-grid").data("kendoGrid");
childGrid.dataSource.read();
});
function detailInit(e) {
$("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 6,
filter: { field: "EmployeeID", operator: "eq", value: e.data.EmployeeID }
},
scrollable: false,
sortable: true,
pageable: true,
toolbar: [{ text: "Refresh", className: "btn-refresh" }],
columns: [
{ field: "OrderID", width: 70 },
{ field: "ShipCountry", title: "Ship Country", width: 100 },
{ field: "ShipAddress", title: "Ship Address" },
{
field: "ShipName", title: "Ship Name", width: 200
}
]
});
}
</script>
</body>
</html>
There are, at least, two main ways to do this. However, I didn't understand if you want to:
a) Clear all the "updated" texts, letting only the last clicked with it
b) Keep all them tracked, putting the text as the user sorts the grids
Anyway, let's see both strategies.
Using jQuery only
a)
element.on('click', "th[role='columnheader']", function(e) {
// always remove all, to put again in the right place
$("strong[attr-id=updated]").remove();
var firstNameCell = $(this)
.closest("tr.k-detail-row") // Finds the closest detail row ...
.prev("tr.k-master-row") // ... in order to get the first previous row of class "k-master-row" (which stores the FirstName)
.find("td[role='gridcell']"); // and, then, get the td gridcell
firstNameCell.append("<strong attr-id='updated'> - Address updated</strong>");
});
b)
element.on('click', "th[role='columnheader']", function(e) {
var firstNameCell = $(this)
.closest("tr.k-detail-row")
.prev("tr.k-master-row")
.find("td[role='gridcell']");
// Check if the msg already exits, to not duplicate it
if (!(firstNameCell).find('strong[attr-id=updated]').length) {
firstNameCell.append("<strong attr-id='updated'> - Address updated</strong>");
}
});
The attr-id helps to identify the text element along the page, once it's not a good practice using id (only once per page).
Using KendoUI JavaScript objects
That's not the best way, since you cannot append HTML like we did with jQuery approach. Also, you'll have to refresh the whole table every time a sort is made.
That's why I'll show only case b)
element.on('click', "th[role='columnheader']", function(e) {
var masterRow = $(this)
.closest("tr.k-detail-row")
.prev("tr.k-master-row"); // Finds the closest master row ...
var rowIndex = $("tr.k-master-row").index(masterRow); // ... gets the index of it among all the others
kendoGrid = element.data('kendoGrid');
var firstName = kendoGrid.dataSource._data[rowIndex].FirstName; // gets current name based on the index
if (!firstName.includes('Address updated')) {
selectedCell = rowIndex; // sets the index to be used when grid refreshes
kendoGrid.dataSource._data[rowIndex].FirstName = firstName + " - Address updated";
kendoGrid.refresh(); // refreshed the whole grid
}
});
Still, in order to make KendoUI to expand the right row every time its grids are refreshed, you have to create the global variable selectedCell and check at dataBound function whether it has a value or not:
dataBound: function () {
if (selectedCell) {
this.expandRow(this.tbody.find("tr.k-master-row:eq(" + selectedCell + ")"));
} else {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
},
Here, you can see more about Kendo Grid refreshing: Reloading/refreshing Kendo Grid
Hope it helps! :)

jqGrid custom editfunc doesn't work when custom search parameters are specified

Version jqGrid used here:
#license Guriddo jqGrid JS - v5.2.0 - 2016-11-27 Copyright(c) 2008, Tony Tomov, tony#trirand.com
The first block of code below is an entire self contained implementation of jqGrid. It is in fact mostly taken from one of the examples on the jqGrid site. In it I added a snippet, the part between the comment lines with the clip markings.
That added snipped adds a custom editfunc. It works nicely (in the example it is of course more or less a stub, only doing an alert). Also, searching works, with all of its default parameters. For both, select a row and click on the respective icon of Edit or Search.
<!DOCTYPE html>
<html lang="en">
<head>
<!-- The jQuery library is a prerequisite for all jqSuite products -->
<script type="text/ecmascript" src="./lib/jquery/jquery.min.js"></script>
<!-- This is the Javascript file of jqGrid -->
<script type="text/ecmascript" src="./lib/jqGrid-js-free/js/jquery.jqGrid.js"></script>
<!-- This is the localization file of the grid controlling messages, labels, etc.-->
<!-- We support more than 40 localizations -->
<script type="text/ecmascript" src="./lib/jqGrid-js-free/js/i18n/grid.locale-en.js"></script>
<!-- A link to a jQuery UI ThemeRoller theme, more than 22 built-in and many more custom -->
<link rel="stylesheet" type="text/css" media="screen" href="./lib/jquery-ui/jquery-ui.css" />
<!-- The link to the CSS that the grid needs -->
<link rel="stylesheet" type="text/css" media="screen" href="./lib/jqGrid-js-free/css/ui.jqgrid.css" />
<meta charset="utf-8" />
<title>jqGrid without PHP - Loading Data - JSON Live</title>
</head>
<body>
<table id="jqGrid"></table>
<div id="jqGridPager"></div>
<script type="text/javascript">
$(document).ready(function () {
$("#jqGrid").jqGrid({
colModel: [
{
label: 'Title',
name: 'Title',
width: 150,
formatter: formatTitle
},
{
label: 'Link',
name: 'Link',
width: 80,
formatter: formatLink
},
{
label: 'View Count',
name: 'ViewCount',
width: 35,
sorttype:'integer',
formatter: 'number',
align: 'right'
},
{
label: 'Answer Count',
name: 'AnswerCount',
width: 25
}
],
viewrecords: true, // show the current page, data rang and total records on the toolbar
width: 780,
height: 200,
rowNum: 15,
datatype: 'local',
pager: "#jqGridPager",
caption: "Load live data from stackoverflow"
});
fetchGridData();
function fetchGridData() {
var gridArrayData = [];
// show loading message
$("#jqGrid")[0].grid.beginReq();
$.ajax({
url: "http://api.stackexchange.com/2.2/questions?order=desc&sort=activity&tagged=jqgrid&site=stackoverflow",
success: function (result) {
for (var i = 0; i < result.items.length; i++) {
var item = result.items[i];
gridArrayData.push({
Title: item.title,
Link: item.link,
CreationDate: item.creation_date,
ViewCount: item.view_count,
AnswerCount: item.answer_count
});
}
// set the new data
$("#jqGrid").jqGrid('setGridParam', { data: gridArrayData});
// hide the show message
$("#jqGrid")[0].grid.endReq();
// refresh the grid
$("#jqGrid").trigger('reloadGrid');
}
});
}
function formatTitle(cellValue, options, rowObject) {
return cellValue.substring(0, 50) + "...";
};
function formatLink(cellValue, options, rowObject) {
return "<a href='" + cellValue + "'>" + cellValue.substring(0, 25) + "..." + "</a>";
};
/*---- 8< ------*/
// editfunc here works (an alert is popped up), although the format of the function parameters is not according to spec:
// searchfunc also works (it is the default)
$('#jqGrid').jqGrid( 'navGrid', '#jqGridPager',{
add:false, del:false, view:false,
editfunc: function(){alert('EDIT');}
});
/*---- >8 ------*/
});
</script>
</body>
</html>
Now take the same file, remove the small snippet between the snip lines, and replace it with the following snippet, that looks more like something I need to implement:
/*---- 8< ------*/
// editfunc does NOT work as desired here (no alert)
// search function works, WITH the parameters as specified here
// from the file jquery.jqGrid.js (): navGrid : function parameters: (elem, p, pEdit, pAdd, pDel, pSearch, pView)
// (=jqGrid-free #license Guriddo jqGrid JS - v5.2.0 - 2016-11-27 Copyright(c) 2008, Tony Tomov, tony#trirand.com)
$('#jqGrid').jqGrid( 'navGrid', '#jqGridPager',
{ add:false, del:false, view:false }, // p
{ editfunc: function(r){alert('EDIT');} }, // pEdit (does NOT work)
{ }, // pAdd
{ }, // pDel
{ multipleSearch: true, closeAfterSearch:true, closeOnEscape:true, searchOnEnter:true, showQuery:true }, // pSearch (works with these options)
{ } // pView
);
/*---- >8 ------*/
Here, alas the editfunc does not work at all, I get the default edit function. Search now works though, as desired with the custom specified parameters.
In short: I cannot seem to get both a customized editfunc and search with custom parameters working!
I cannot see anything wrong with the second snippet. It is btw. also per some examples on the jqGrid wiki.
Any hints to get both working together would be appreciated.
The problem is very easy: you placed editfunc in the wrong place in your last snippet. The editfunc should be specified as the property of the second parameter of navGrid (together with add:false, del:false, view:false). You used the editfunc correctly in the first part of your code, but you placed it in the second part of the code on the wrong place. You can fix your code by usage
$('#jqGrid').jqGrid( 'navGrid', '#jqGridPager',
{ add:false, del:false, view:false, editfunc: function(r){alert('EDIT');} }, // p
{ }, // pEdit
{ }, // pAdd
{ }, // pDel
{ multipleSearch: true, closeAfterSearch:true, closeOnEscape:true,
searchOnEnter:true, showQuery:true }, // pSearch (works with these options)
{ } // pView
);
By the way, you placed the code of commercial product Guriddo jqGrid JS in the directory jqGrid-js-free, which sounds strange. Guriddo jqGrid JS can't be used for free. You can see the current prices here. I started development of free jqGrid fork of jqGrid, which can be used completely free of charge, exactly because of that. Free jqGrid implemented many new features, which can be helpful for you. The demo https://jsfiddle.net/OlegKi/odvxefra/3/ is a small modification of your code, which displays
I used additionally
url: "https://api.stackexchange.com/2.2/questions",
// add sending of custom parameters to the URL
postData: {
order: "desc",
sort: "activity",
tagged: "jqgrid",
site: "stackoverflow"
},
datatype: "json",
// below prmNames remove sending all standard jqGrid paranmeters
prmNames: {
page: null,
rows: null,
sort: null,
order: null,
search: null,
nd: null,
id: "question_id"
},
jsonReader: {
root: "items",
repeatitems: false,
id: "question_id"
},
loadonce: true,
forceClientSorting: true,
sortname: "creation_date",
sortorder: "desc"
The data will be loaded from the same URL "http://api.stackexchange.com/2.2/questions?order=desc&sort=activity&tagged=jqgrid&site=stackoverflow", sorted locally by creation_date property in the desc order and displayed in the grid. One can use other properties in the custom formatter by adding the properties in additionalProperties. For example you can add additionalProperties: ["owner", "is_answered", "score", "last_activity_date"] to save the properties locally and to have access to the properties inside of, for example, custom formatter.

Categories

Resources