FullCalendar's eventClick not working after changing view - javascript

Supposing that I want to open a modal popup when user clicks on a FullCalendar's event, I wrote some logic on the "eventClick" part of Full Calendar. This works fine until I'm on the default view, which I setted as "month".
If I try to switch from a view to another, though, this doesn't get fired, almost like it died.
What am I doing wrong? This is the code that I have for my Full Calendar. I've also tried to add a viewRender event as per the documentation but it's not working
function initCalendar2(oggetti){
debugger;
$('.calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
//right: 'month,agendaWeek,agendaDay,' +vistaAgenda
right: 'month,agendaWeek,agendaDay,listDay,listWeek'
},
views: {
listDay: { buttonText: 'Lista Giorno'},
listWeek: { buttonText: 'Lista Sett'}
},
eventClick: function(calEvent, jsEvent, view) {
debugger;
//Send 2 values to the modal
$("#dataArrivo").val(calEvent.start.toISOString().split('T')[0]);
$("#dataConsegna").val(calEvent.end.toISOString().split('T')[0]);
//Opens the modal
var targeted_popup_class = $(this).attr('data-popup-open');
$('[data-popup="' + targeted_popup_class + '"]').fadeIn(350);
//e.preventDefault();
var newDateOne;
var newDateTwo;
//This triggers only when the save button of the modal is clicked
setTimeout(function() {
$("#save").click(function() {
var tmp1 = $("#dataArrivo").val();
var tmp2 = $("#dataConsegna").val();
newDateOne = new Date(tmp1);
newDateOne.setDate(newDateOne.getDate());
newDateTwo = new Date(tmp2);
newDateTwo.setDate(newDateTwo.getDate());
var tmp = calEvent.id.split("&");
var idToSend = "";
for (var i = 0; i < tmp.length-1; i++) {
if (i == tmp.length-2) {
idToSend += tmp[i];
} else {
idToSend += tmp[i]+"&";
}
} if (newDateOne !== calEvent.start || newDateTwo !== calEvent.end) {
var actualDate = new Date(calEvent.start);
debugger;
//This ajax call will save the event's new dates in the DB
$.ajax({
url: 'calendariomanagement/listaPraticheFormJSONByIdProgettoCommittenteAndTipoVal/'+ idToSend +'/modDate/' + nuovaDataArrivo.toDateString() + '&' + nuovaDataConsegna.toDateString() + '&' + actualDate.toDateString(),
type:'POST',
async:false,
success: function(data) {
var targeted_popup_class = $(this).attr('data-popup-close');
$('[data-popup="' + targeted_popup_class + '"]').fadeOut(350);
location.reload();
/*calEvent.start = dataUno;
calEvent.end = dataDue;
$('#calendar').fullCalendar('updateEvent', calEvent);*/
}
});
}
}), 350}
);
},
viewRender: function(view, element) {
debugger;
$('#calendar').fullCalendar('rerenderEvents');
},
locale: 'it',
defaultView: 'month',
defaultDate: moment(),
navLinks: true, // can click day/week names to navigate views
editable: false,
eventDurationEditable: false,
//weekends:false,
eventLimit: true, // allow "more" link when too many events
events: oggetti
});

Putting here for anybody that might fall in something similar my problem.
This was the modal popup that I was defining with HTML
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
*<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Cambio data</h4>
</div>
<div class="modal-body">
<p> Inserire i nuovi valori nel formato anno-mese-giorno (es.: 2018-07-03). Nel
caso non si volesse modificare nessun campo, semplicemente chiudere questo pop-up</p>
<label for="arrivo">Data Arrivo:</label>
<input type="text" name="dataArrivo" id="dataArrivo" class="form-control">
<label for="consegna">Data Riconsegna:</label>
<input type="text" name="dataConsegna" id="dataConsegna" class="form-control">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Chiudi</button>
<button type="button" class="btn btn-default" id="save" data-dismiss="modal">Salva</button>
</div>
</div>
*
After FullCalendar's load, I added this with jQuery
$(".fc-content").attr('data-toggle', 'modal');
$(".fc-content").attr('data-target','#myModal');
But of course, after changing the view, those attributes were lost and there was no chance to reinsert them. As a solution (pointed out by ADyson), the workaround was to define a modal with a bootbox object so that I could have it dynamically

Related

Closing Bootstrap's modal from Knockout

I wrote a function (basing on some other I found on the Internet), which aids in displaying dynamically-generated modals without need to create ones in page's HTML.
To simplify code analysis, briefly:
I add new binding handler to Knockout to allow disabling binding on specific element
Modal is generated from a template using Mustache
Mustache fills in relevant parts of the modal (title, body, buttons)
Modal is wrapped in div, which stops data binding (modalWrapper)
... so that I can apply custom viewmodel to the modal with ko.applyBindings
Buttons are generated automatically basing on description, like:
{
label: "OK",
cssClass: "default",
handler: "handleClick", // sets data-bind="click: handleClick"
autoClose: true // adds data-dismiss="modal"
}
Relevant parts of the code follows:
ko.bindingHandlers.stopBinding = {
init: function () {
return { controlsDescendantBindings: true };
}
};
var modalTemplate = '<div class="modal fade">\
<div class="modal-dialog {{size}}">\
<div class="modal-content">\
<div class="modal-header">\
<h5 class="modal-title">{{title}}</h5>\
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>\
</div>\
<div class="modal-body">{{&body}}</div>\
<div class="modal-footer">{{&buttons}}</div>\
</div>\
</div>\
</div>';
/**
* Displays modal on the screen.
* #param {Object} options Options
* #param {string} options.title Title of the modal
* #param {html} options.body Body of the modal
* #param {string} options.size Size of the modal. Can be small, default, large or xlarge.
* #param {Object} options.actions Describes buttons to display on the modal. For each, specify label, cssClass, handler and optionally autoClose.
*/
var showModal = function(options) {
options = options || {};
options = $.extend({
title: '',
body: '',
size: false,
actions: false,
viewModel: {}
}, options);
var modalClass = {
small: "modal-sm",
default: "",
large: "modal-lg",
xlarge: "modal-xl"
};
var modalWrapper = $('<div data-bind="stopBinding: true"></div>').appendTo('body');
var buttons;
if (options.actions === false) {
buttons = '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>';
} else {
buttons = "";
for (var i = 0, len = options.actions.length; i < len; i++) {
var currentButton = $.extend({
label: '<No label>',
cssClass: 'default',
handler: '',
autoClose: true
}, options.actions[i]);
var btn = '<button type="button" class="btn ' +
options.actions[i].cssClass +
'" data-bind="click: ' +
options.actions[i].handler +
(options.actions[i].autoClose === true ? '" data-dismiss="modal"' : '')
+ '>'
+ options.actions[i].label
+ '</button>';
buttons += btn;
}
}
var templateData = {
title: options.title,
body: options.body,
size: modalClass[options.size],
buttons: buttons
};
var modalHtml = Mustache.render(modalTemplate, templateData);
var $modal = $(modalHtml).appendTo(modalWrapper);
$modal.on('hidden.bs.modal', function (e) {
modalWrapper.remove();
});
ko.applyBindings(options.viewModel, $modal.get()[0]);
$modal.modal(options);
};
I have a problem with this autoclosing feature. If it is on, viewmodel processes the click, modal is closed by Bootstrap mechanisms and then removed from DOM after hiding.
But when I want a button to be non-auto-closing, I have no means to close modal from the viewmodel. The solution I thought of was to inject a method to viewmodel like:
viewmodel['close'] = function() { $modal.modal('hide'); };
However this seems to be a hackish solution (even for Javascript ;)). Similarly, I may inject the $modal itself to the viewmodel, but that would be even more ugly.
What would be then the best way to close the modal from within modal's viewmodel?
I solved a similar requirement by assigning an (auto-generated) id to the modal div tag.
var modalId = ('modal' + Math.random()).replace('.', '');
var modalTemplate = '<div class="modal fade" id="' + modalId + '">'\ // remaining code here
Then, that id is being passed to viewmodel, which allows it to close the corresponding modal via
$('#' + _self.modalId).modal('hide');
A comparable event subscription to 'hidden.bs.modal' handles the cleanup.
I would create a custom Knockout binding for handling the visibility of the modal.
This binding connects the bound modal element to the supplied model observable. Click handlers in the model now only have to manage this observable to control the modal visibility.
You could apply this binding for example in your modalTemplate variable: var modalTemplate = `<div class="modal fade" data-bind="bootstrapModalVisible: yourObservable">\...
I haven't incorporated the binding in your case, but below is an example of the working of this binding.
the modalVisible observable is initialized to true, so the modal immediately shows
the close button immediately hides the modal by setting the observable to false
the upper-right close button closes the modal because of data-dismiss="modal". The event handlers in the binding's init will make sure the correct state is written to the observable.
the save button only closes the modal when confirmed, showing the possibility to postpone closing the modal
ko.bindingHandlers['bootstrapModalVisible'] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
$(element).on('hidden.bs.modal', function () { valueAccessor()(false); })
$(element).on('shown.bs.modal', function () { valueAccessor()(true); })
},
update: function (element, valueAccessor) {
if (ko.unwrap(valueAccessor())) {
$(element).modal('show');
} else {
$(element).modal('hide');
}
}
};
function Test() {
var self = this;
self.modalVisible = ko.observable(true);
self.showModal = function() {
self.modalVisible(true);
};
self.hideModal = function() {
self.modalVisible(false);
};
self.save = function() {
if (window.confirm('Close modal?')) {
self.modalVisible(false);
}
}
}
ko.applyBindings(new Test());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<button type="button" class="btn btn-primary" data-bind="click: showModal">
Launch demo modal
</button>
<div class="modal fade" data-bind="bootstrapModalVisible: modalVisible">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Example modal</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bind="click: hideModal">Close</button>
<button type="button" class="btn btn-primary" data-bind="click: save">Save changes</button>
</div>
</div>
</div>
</div>

Symfony - Fullcalendar event description undefined

I have a controller that gets data from database and turns it in events for fullcalendar, when I display a modal clicking in one of this events, it shows that description and email are undefined.
Image of modal undefined fields
But in XHR I can see that im receiving all the data from the controller.
Image of XHR GET
Modal:
<div id="fullCalModal" class="modal fade" style="z-index: 9999;>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 id="modalTitle" class="modal-title"></h4>
</div>
<div id="modalBody" class="modal-body">
<p id="ev_start" class="modal-body"></p>
<p id="ev_end" class="modal-body"></p>
<p id="ev_mail" class="modal-body"></p>
<p id="ev_desc" class="modal-body"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button class="btn btn-primary"><a id="eventUrl" target="_blank">Event Page</a></button>
</div>
</div>
</div>
Javascript:
eventClick: function(info) {
var eventObj = info.event;
alert('Clicked ' + eventObj.title + ' with id: ' + eventObj.id + eventObj.description);
$('#modalTitle').html(eventObj.title);
$('#ev_titulo').html(eventObj.title);
$('#ev_start').html('Fecha inicio: ' + eventObj.start);
$('#ev_end').html('Fecha fin: ' + eventObj.end);
$('#ev_desc').html('Descripcion: ' + eventObj.description);
$('#ev_mail').html('Mail: ' + eventObj.mail);
$('#fullCalModal').modal('show');
},
Controller:
public function loadAction()
{
$em = $this->getDoctrine()->getManager();
$eventos = $em->getRepository('App:Evento')->findAll();
$data = array();
foreach ($eventos as $evento)
{
$events['id'] = $evento->getId();
$events['title'] = $evento->getTitle();
$events['start'] = $evento->getBeginAt()->format('Y-m-d');;
$events['end'] = $evento->getEndAt()->format('Y-m-d');;
$events['color'] = $evento->getColor();
$events['description'] = $evento->getDescription();
$events['mail'] = $evento->getMail();
array_push($data, $events);
}
return $this->json($data);
}
The event parsing documentation states that
Every other non-standard prop will be transferred over to the
extendedProps hash in the Event Object.
Since description and mail are not standard event properties in fullCalendar (as listed in that documentation), then they will be placed under the "extendedProps" object in the final event object which fullCalendar creates based on the data it receives from your server.
Therefore in your eventClick code you should be able to write
$('#ev_desc').html('Descripcion: ' + eventObj.extendedProps.description);
$('#ev_mail').html('Mail: ' + eventObj.extendedProps.mail);
and populate the properties successfully into your modal.
P.S. This behaviour is also mentioned in the event object documentation as well. If you have previously used fullCalendar version 3 or below, then this is a change from how these earlier versions worked.

After clicked on Link Count One Down (-1) from Total of Count JavaScript - MVC

I have page ,where im showing all messages and in header im showing Total of messages by counting them and im looking for something with javascript or MVC ,when user click on link (its means message be opened) count one down (-1) of total count which is messages and then use localstorage or Cookies to remember the count for next time, when user coming back to check their messages.
Can anyone please help me or point me in the right direction!
Thanks in advance :)
For example : lets say i have 14 messages , when user click on link i should be 13
Controller:
public ActionResult Messages(RMAHistory m2)
{
string EmailID = Session["Email"].ToString();
ViewBag.CountMSG = (new DbNamespace().Besked.Where(x => x.KundensEmail == EmailID).Select(f => f.KundensEmail).ToList().Count);
var bla7 = (from RB in db.Besked
where RB.KundensEmail == EmailID
select new RMAHistory.Comment_List
{
id = RB.ID,
MSG = RB.MSG,
se = RB.Seen,
Date = RB.Date,
Forfatter = RB.Writer,
KundensEmail =RB.KundensEmail,
Id = RB.RMAID,
MSGType =RB.MSGType
});
m2.Comment_Lists = bla7.ToList();
return View(m2);
}
View:
<div class="col-lg-8 col-md-7 col-md-offset-2">
<div class="card">
<div class="card-header" data-background-color="purple">
<span class="category">(You have #ViewBag.CountMSG New Messages)</span>
</div>
<div class="content">
#if (!Model.Comment_Lists.Any())
{
<div class="bs-callout bs-callout-danger">
<h4>You Do not Have New Messages</h4>
</div>
}
else
{
foreach (var item in Model.Comment_Lists)
{
if (item.se == "Kunde")
{
<div class="bs-callout bs-callout-success message">
<div class="col-xs-3 text-right">
<a target="_blank" href="/Account/RMADetails?id=#item.Id" id="#item.id" class="btn btn-sm btn-success btn-icon btnChangestu"><i class="fa fa-envelope"></i></a>
</div>
<h4><i class="fa fa-bookmark-o" aria-hidden="true"></i> Message number #item.Id</span></h4>
<span class="text-muted"><small> #item.Date.ToString("dd/MMMM/yyy")</small></span><br />
<span class="text-muted status"><span> #item.MSGType</span></span>
<input type="hidden" name="ChangeStu" id="ChangeStu" value="read massage" />
</div>
}
}
}
</div>
</div>
</div>
JavaScript:
<script>
$(document).ready(function () {
$('.btnChangestu').click(function () {
var id = $(this).attr('id');
if (!id) {
return;
}
var button = $(this);
var status = $(this).closest('.message').find('.status');
$.ajax({
type: "POST",
url: '#Url.Action("UpdateMSGStatus", "Account")',
data: {
IDMSG: id,
ChangeStu: $("#ChangeStu").val()
},
dataType: 'json',
success: function (result) {
if (result) {
status.text("read message");
button.removeData('id')
console.log("Ok")
} else {
// display error?
console.log("error");
}
},
error: function () {
console.log('something went wrong - debug it!');
}
})
});
});
</script>

Entries are one month ahead when using PHP dates in fullcalendar.js

I included a calendar in my project using fullcalendar.js. My database entries are showing up but they are one month ahead.
If I enter something for 16.octobre.2015, it will be saved in the database as 16.octobre.2015 but will be displayed as 16.novembre.2015. This happens with every single one of my entries.
I searched a lot here on Stack Overflow and found a few similar topics. In one, someone explained that this has something to do with how months are indexed.
PHP counts from 1 to 12.
JavaScript counts from 0 to 11.
I guess that maybe this is my problem?
Can someone tell me what I need to change, so that my entries show correctly? Here is my code:
<!-- inline scripts related to this page -->
<script type="text/javascript">
jQuery(function($) {
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events div.external-event').each(function() {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
<?php
print "var date = new Date();\n";
print "var d = date.getDate();\n";
print "var m = date.getMonth();\n";
print "var y = date.getFullYear();\n";
print "var unixTimestamp = Date.now(); // in milliseconds;"
?>
var calendar = $('#calendar').fullCalendar({
//isRTL: true,
buttonHtml: {
prev: '<i class="ace-icon fa fa-chevron-left"></i>',
next: '<i class="ace-icon fa fa-chevron-right"></i>'
},
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
<?php
$dates=getPcalInfoOfHour($gl_userid,0,0);
print "events: [\n";
for ($x=0;$x<count($dates["id"]);$x++) {
print " {\n";
print " title: '".$dates["title"][$x]."',\n";
print " start: new Date(".date("Y",$dates["start"][$x]).", ".date("n",$dates["start"][$x]).", ".date("j",$dates["start"][$x]).", ".date("G",$dates["start"][$x]).", ".date("i",$dates["start"][$x]).",0,0),\n";
print " end: new Date(".date("Y",$dates["end"][$x]+1).", ".date("n",$dates["end"][$x]+1).", ".date("j",$dates["end"][$x]+1).", ".date("G",$dates["end"][$x]+1).", ".date("i",($dates["end"][$x]+1)).",0,0),\n";
print " allDay: false,\n";
print " className: 'label-info'\n";
if ($x<(count($dates["id"])-1)) {
print " },\n";
} else {
print " }\n";
}
}
print "]\n";
?>
,
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
var $extraEventClass = $(this).attr('data-class');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
if($extraEventClass) copiedEventObject['className'] = [$extraEventClass];
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
,
selectable: true,
selectHelper: true,
select: function(start, end, allDay) {
calendar.fullCalendar('unselect');
}
,
eventClick: function(calEvent, jsEvent, view) {
//display a modal
var modal =
'<div class="modal fade">\
<div class="modal-dialog">\
<div class="modal-content">\
<div class="modal-body">\
<button type="button" class="close" data-dismiss="modal" style="margin-top:-10px;">×</button>\
<form class="no-margin">\
<label>Title </label>\
<label>$dates["title"][0]</label>\
<button type="submit" class="btn btn-sm btn-success"><i class="ace-icon fa fa-check"></i> Save</button>\
</form>\
</div>\
<div class="modal-footer">\
<button type="button" class="btn btn-sm btn-danger" data-action="delete"><i class="ace-icon fa fa-trash-o"></i> Delete Event</button>\
<button type="button" class="btn btn-sm" data-dismiss="modal"><i class="ace-icon fa fa-times"></i> Cancel</button>\
</div>\
</div>\
</div>\
</div>';
var modal = $(modal).appendTo('body');
modal.find('form').on('submit', function(ev){
ev.preventDefault();
calEvent.title = $(this).find("input[type=text]").val();
calendar.fullCalendar('updateEvent', calEvent);
modal.modal("hide");
});
modal.find('button[data-action=delete]').on('click', function() {
calendar.fullCalendar('removeEvents' , function(ev){
return (ev._id == calEvent._id);
})
modal.modal("hide");
});
modal.modal('show').on('hidden', function(){
modal.remove();
});
console.log(calEvent.id);
console.log(jsEvent);
console.log(view);
// change the border color just for fun
//$(this).css('border-color', 'red');
}
});
})
</script>
The answer is literally in the question. I'll just quote you:
I searched a lot here on Stack Overflow and found a few similar topics. In one, someone explained that this has something to do with how months are indexed.
PHP counts from 1 to 12.
JavaScript counts from 0 to 11.
I guess that maybe this is my problem?
Yes. If you need a finger pointed in the right direction, let's take this part of your code:
print " start: new Date(".date("Y",$dates["start"][$x]).", ".date("n",$dates["start"][$x]).", ".date("j",$dates["start"][$x]).", ".date("G",$dates["start"][$x]).", ".date("i",$dates["start"][$x]).",0,0),\n";
print " end: new Date(".date("Y",$dates["end"][$x]+1).", ".date("n",$dates["end"][$x]+1).", ".date("j",$dates["end"][$x]+1).", ".date("G",$dates["end"][$x]+1).", ".date("i",($dates["end"][$x]+1)).",0,0),\n";
More precisely this:
date("n", $dates["start"][$x])
date("n", $dates["end"][$x]+1)
Simply subtract one from the month value:
(date("n", $dates["start"][$x]) - 1)
(date("n", $dates["end"][$x]+1) - 1)
Do this everytime you output a PHP month value in a JavaScript source.
Even better, you could just use the timestamps directly (remember that JavaScript uses milliseconds):
print " start: new Date(".($dates["start"][$x] * 1000)."),\n";
print " end: new Date(".(($dates["end"][$x]+1) * 1000)."),\n";

Javascript syntax error not sure what I am doing wrong

I'm rather new to JavaScript but I am learning..
But now I am stuck, I made this JavaScript Except I get Syntax error
$(function () {
$(function () {
$('#date').datepicker({
showButtonPanel: true,
changeMonth: true,
changeYear: true,
dateFormat: "yy-mm-dd",
firstDay: 1,
onSelect: function (dateText) {
$('#EndDate').datepicker('option', 'minDate', new Date(dateText));
}
});
});
});
if (!((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i)))) {
$(function () {
$("#startTime").timePicker({
step: 15,
endTime: "23:45"
});
});
$(function () {
$("#endTime").timePicker({
step: 15,
endTime: "23:45"
});
});
$(function () {
$("#breakTime").timePicker({
step: 5,
endTime: "03:00"
});
});
}
function SetDate(dt) {
$('#date').val(dt);
}
var n = #(Model.Projects.Count);
function AddProject() {
n++;
$.ajax({
type: "GET",
url: "#(Url.Action("Project"))/" + n + "/?showDescription=false",
dataType: "html",
success: function(data) {
$('#projects').append(data);
}
});
}
It is on my AddProject function I get my error, how ever I can't see what could be wrong?
And this is the view I want to use the script on.
#if (ViewData["posted"] != null)
{
<div class="alert alert-success">
<strong>Inställningar sparade</strong>
</div>
}
#using (Html.BeginForm("Settings", "Reports", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<span class="caption-subject font-green-sharp bold uppercase">Inställngar</span>
</div>
</div>
<table class="table table-striped table-bordered table-hover">
<tr>
<td>Starttid:</td>
<td>#Html.TextBox("startTime", Model.Times.StartTime)</td>
</tr>
<tr>
<td>Sluttid:</td>
<td>#Html.TextBox("endTime", Model.Times.EndTime)</td>
</tr>
<tr>
<td>Rastlängd:</td>
<td>#Html.TextBox("breakTime", Model.Times.BreakTime)</td>
</tr>
</table>
</div>
<div id="projects">
#foreach (var data in Model.Projects)
{
Html.RenderPartial("Project", data, ViewData["vd"] as ViewDataDictionary);
var viewDataDictionary = ViewData["vd"] as ViewDataDictionary;
if (viewDataDictionary != null)
{
viewDataDictionary["id"] = (int)viewDataDictionary["id"] + 1;
}
}
</div>
Lägg till projekt
<button type="submit" class="btn btn-primary">Spara</button>
}
</div>
</div>
</div>
</div>
</div>
</div>
Javascript files do not support Razor compilation. Only views do that. You cannot have Razor in separate JS files.
Instead inject any required information into the view (e.g. into the elements as data- or other attributes) and have your JS pick up those values from the elements (or from a few global vars you set in the view).
I will add some examples for you...
Example HTML (attribute injection):
<a id="addProject" href="#(Url.Action("Project") + "/{id}/?showDescription=false")" class="btn btn-primary">Lägg till projekt</a>
JQuery
$('#addProject').click(function(){
var url = $(this).attr('href');
url = url.replace("{id}", myNewId);
$.ajax({
url: url
...
});
});
I strongly recommend never using inline event handlers (like onclick="") with jQuery as the separate the event code from the registration aking maintenance harder and do not have all the same features as jQuery event handling.
Example HTML (global var injection)
Place this code snippet in the view
<script type="text/javascript>
var projectCount = #(Model.Projects.Count);
// or
window.projectCount = #(Model.Projects.Count);
</script>
Then you can access projectCount from other JS files with:
var count = projectCount + 1;
or
var count = window.projectCount + 1;

Categories