I'm pulling in ALL my event data from my server and since I have a lot of events to pull, the angular-bootstrap-calendar takes a lot of time to load.
I was wondering if its possible to pull only a month's worth of data for the current view I'm in (month, week, day..I would hide the year view). As I change the view to the next month, I'd pull the data for that month only.
Right now, I pull ALL the data only once, when the calendar loads, but not sure how to pull the data when the view changes.
var urlapievents = $location.protocol() + "://" + $location.host() + "/api/events/" ;
$http.get(urlapievents).success(function(events) {
Good solution for me
Get year and month of view, send it to API, and only retrieve events for that year-month:
js
vm.viewChangeClicked = function() {
var viewDateYearMonth = moment(vm.viewDate).format('YYYY-MM');
var urlapieventsall = $location.protocol() + "://" + $location.host() + "/api/events/" + viewDateYearMonth ;
$http.get(urlapieventsall).success(function(events) {
vm.events = events.events;
});
};
html
<div class="col-md-6 text-center">
<div class="btn-group">
<label class="btn btn-primary" ng-model="vm.calendarView" uib-btn-radio="'month'" ng-click="vm.cellIsOpen = false; vm.viewChangeClicked()">Month</label>
<label class="btn btn-primary" ng-model="vm.calendarView" uib-btn-radio="'week'" ng-click="vm.cellIsOpen = false; vm.viewChangeClicked()">Week</label>
<label class="btn btn-primary" ng-model="vm.calendarView" uib-btn-radio="'day'" ng-click="vm.cellIsOpen = false; vm.viewChangeClicked()">Day</label>
</div>
</div>
I've also added logic to check if previous yyyy-mm is equal to current yyyy-mm to save some unnecessary calls to the API.
If you grab your events as a json feed, you can use additional options - startParam and endParam. They can be used like this:
$('#calendar').fullCalendar({
events: function(start, end, timezone, callback) {
if (request) {
request.abort();
};
$.mobile.loading('show');
request = $.ajax({
type: "POST",
url: "../Services/Calendar/CalendarService.asmx/GetEvents",
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{ dtStart: " + JSON.stringify(start) + ", dtEnd: " + JSON.stringify(end) + "}",
success: function(data) {
var events1 = [];
$(data.d).each(function() {
events1.push({
title: this.Title,
start: this.Start,
end: this.End,
id: this.Id
});
});
callback(events1);
$.mobile.loading('hide');
},
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.statusText == 'abort') {
$.mobile.loading('hide');
return;
} else {
alert('There was an error');
$.mobile.loading('hide');
}
}
});
}
});
You can read more about those parameters here: https://fullcalendar.io/docs/event_data/events_json_feed/
The functionality you describe is a sort of date pagination, although this functionality isn't built in (shame, because it sounds really useful), you can implement your own with some small amount of work
First, the datepicker stores a JS Date object inside the ng-model, you can $watch it and get the current year/month/day out of it
$scope.modelDate = new Date()
...
$scope.$watch('modelDate', function(newDate, oldDate) {
newDate.getDay(); // 5
newDate.getMonth(); // 11
newDate.getYear(); // 116
})
Now you can query your database to get all the event for your selected month
Also, you can utilize the datepicker's mode (showing wether you are viewing the datepicker in the day/month/year mode, you set it up inside the options object).
datepickerMode C (Default: day) - Current mode of the datepicker (day|month|year). Can be used to initialize the datepicker in a specific mode.
Using this property you can query a month, year or years of events.
Related
Apologies if the title seemed a bit vague, but I am at a complete loss as to why this may be happening now.
I have an online application that has been used for more than 2 years by a team of people, and we had a new starter about 6 months ago who when using the application, approx once a month, an event fires twice for this one user, and no other person.
It is a very basic onclick event the fires to controller, that updates a DB, I have tried to replicate the issue but am unable to on anyone else's machine.
<button class="btn btn-primary" type="button" onclick="advanceJob()">Advance Job</button>
function advanceJob() {
var details = {
Id: selectedJob,
MovedOnBy: '#ViewBag.DisplayName',
Frequency: $('#jobFrequency').val()
}
$.ajax({
type: 'POST',
url: '/Home/MoveJobOn',
cache: false,
data: details,
success: function (data) {
$('#jobModal').modal('hide');
alert(data);
},
error: function (x, y, z) {
alert(x.responseText + " " + y.responseText + " " + z.responseText);
}
}
});
I can only think it may be something specific to that persons machine, but have never encountered this before with any other of my applications.
Try to test this event using different browsers, if they all click twice, perhaps the issue is the Mouse is broken, try to replace the new Mouse.
Besides, you could also refer to the following code to disable the button after fist click the button.
<button class="btn btn-primary" type="button" onclick="advanceJob(this)">Advance Job</button>
<span id="output"></span>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var count = 0;
function advanceJob(e) {
$(e).attr("disabled", true);
//after 3 seconds, enable the button.
setTimeout(function () {
$(e).removeAttr("disabled");
}, 3000);
count++;
$("#output").html(count.toString());
////other actions
//var details = {
// Id: selectedJob,
// MovedOnBy: '#ViewBag.DisplayName',
// Frequency: $('#jobFrequency').val()
//}
//$.ajax({
// type: 'POST',
// url: '/Home/MoveJobOn',
// cache: false,
// data: details,
// success: function (data) {
// $('#jobModal').modal('hide');
// alert(data);
// },
// error: function (x, y, z) {
// alert(x.responseText + " " + y.responseText + " " + z.responseText);
// }
//}
};
</script>
Also you could refer to this article to prevent multiple click the button.
I am trying to display a simple rating option on a website, a thumbs up & down that when clicked will send the response to my external URL.
The site will be displayed on mobile devices as well as desktops (that's why i'm using touchstart and click).
I need to post the following values to my external URL;
date
time
feedback (good / bad)
I'm successfully receive the date and time, but not feedback type. Looking at the console I can see the following;
My code is as follows;
HTML
<form id="kioskFeedback">
<i class="fa fa-thumbs-o-up fa-4x"></i>
<i class="fa fa-thumbs-o-down fa-4x"></i>
</form>
AJAX
$(document).ready(function() {
var today = new Date();
var date = today.getDate() + '/' + (today.getMonth() + 1) + '/' + today.getFullYear();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
$("#kioskFeedback").on("touchstart, click", function(e) {
event.preventDefault();
var serializedData = $(this).serialize();
$.ajax({
url: "my external url here",
type: "post",
data: serializedData + '&Date=' + date + '&Time=' + time
});
.done(function(response, textStatus, jqXHR) {
console.log('success');
});
});
});
Expanding on #ADyson's comment, look at the docs for $.serialize() http://api.jquery.com/serialize/
To Make what you have work...
Change this var serializedData = $(this).serialize();
to this var serializedData = $(this).attr('value');
That should get you started. Once you read the documentation and understand that <a></a> elements are not form elements and the $.serialize() method will not return the expected results you may want to go back and update the rest of the click handler to use a different variable name like so,
$("#kioskFeedback a").on("touchstart, click", function(e) {
e.preventDefault();
var feedbackVal = $(this).attr('value');
$.ajax({
url: "my external url here",
type: "post",
data: {
// If the script is expecting "Feedback" swap in place of "value"
value: feedbackVal,
Date: date,
Time: time
}
});
.done(function(response, textStatus, jqXHR) {
console.log('success');
});
});
Also you should change event.preventDefault(); to e.preventDefault() seeing that your event information is being passed as e and not event.
Your target needs to get updated also, so adding an a to $("#kioskFeedback")
like this $("#kioskFeedback a") will shrink the scope to the link element. Allowing you to get the attribute value.
I am also attaching a working fiddle.
$("#kioskFeedback a").on("touchstart, click", function(e) {
e.preventDefault();
var feedbackVal = $(this).attr('value');
console.log(feedbackVal);
/* $.ajax({
url: "my external url here",
type: "post",
data: {
// If the script is expecting "Feedback" swap in place of "value"
value: feedbackVal,
Date: date,
Time: time
}
});
.done(function(response, textStatus, jqXHR) {
console.log('success');
}); */
});
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="kioskFeedback">
<i class="fa fa-thumbs-o-up fa-4x"></i>
<i class="fa fa-thumbs-o-down fa-4x"></i>
</form>
Good morning, I come to you guys looking for some assistance getting two functions to work. I think I'm almost there but I'm missing something. I cannot get the field in SharePoint to update but I can get my document to open no problem. Is something missing in the code below?
<script type="text/javascript">
function fnUpdateRecord(userId, id) {
$.getJSON("PROGRAM/_vti_bin/ListData.svc/List(" + id + ")?$select=ViewBy", function (data) {
var viewby = data.d.ViewBy;
var username = userId;
var doc = new Object();
doc.ViewBy = username;
$.ajax({
method: "POST",
url: "PROGRAM/_vti_bin/listdata.svc/List(" + id + ")",
contentType: "application/json; charset=utf-8",
processData: false,
beforeSend: beforeSendFunction,
data: JSON.stringify(doc),
dataType: "json",
error: function (xhr) {
alert(xhr.status + ": " + xhr.statusText);
},
success: function () {
}
});
});
}
function fnRecordAccess(id, path) {
$.ajax({
url: "GetCurrentUser.aspx",
context: document.body
}).success(function(result) {
var userId = $(result).find('.wtf').text()
fnUpdateRecord(userId, id);
window.open(path, "othrWn");
}).error(function(error) {
console.log(error);
});
}
</script>
I think call those functions via an OnClick:
onclick='fnRecordAccess(" + i.Id + ", "" + path + "")'><i class='fa fa-lg fa-pencil'></i> View</a>
I can get the item/infopath form to load in another window but it doesn't seem to run the function to add the username in the ViewBy column. Any ideas? Thank you for assisting!
Edit: Added fnCountrySearch; this calls the other functions.
function fnCountrySearch(choice) {
fnWaitDialog("show");
var searchId = choice;
$("#tableBody tr").remove();
$.getJSON("PROGRAM/_vti_bin/ListData.svc/List?$filter=Country eq '" + searchId + "'&$orderby=Name", function (data) {
var d = data.d;
if (d.results.length == 0) {
$("#noResultsAlert").show();
$("#notingQueried").hide();
}
else {
$.each(d.results, function (n, i) {
var path = i.Path + "/" + i.Name;
$("#tableBody").append("<tr><td>" + "<a class='btn btn-sm btn-default' class='pull-left' href='#' onclick='fnRecordAccess(" + i.Id + ", "" + path + "")'><i class='fa fa-lg fa-pencil'></i> View</a></td></tr>");
});
$("#noResultsAlert").hide();
$("#notingQueried").hide();
}
})
.always(function () {
fnWaitDialog("hide");
});
}
The beforeSendFunction:
function beforeSendFunction(xhr) {
// Manipulate headers for update
xhr.setRequestHeader("If-Match", "*");
// Using MERGE so that the entire entity doesn't need to be sent over the wire.
xhr.setRequestHeader("X-HTTP-Method", 'MERGE');
}
REST
To compare your code with published examples, you can refer to Microsoft's documentation of SharePoint 2010's REST interface here:
Data Access for Client Applications: Using the REST Interface
Reference Implementation: Client: Using the REST Interface from JavaScript
JSOM
SharePoint 2010 does have a JavaScript client object model that you can use as an alternative to the REST API. This can be an especially attractive option if you find yourself invoking the REST API via JavaScript, since the client object model does not require additional libraries.
If you were to rewrite your fnUpdateRecord method to use the JavaScript client object model it would look like this:
fnUpdateRecord(userId, id){
var listName = "List", fieldName = "ViewBy", newValue = userId + " # " + new Date() + ";\n";
var clientContext = new SP.ClientContext();
var list = clientContext.get_web().get_lists().getByTitle(listName);
var item = list.getItemById(id);
clientContext.load(item);
clientContext.executeQueryAsync(Function.createDelegate(this,function(){
// get current field value...
var currentValue = item.get_item(fieldName);
item.set_item(fieldName, newValue + currentValue);
item.update();
// update the field with the new value
clientContext.executeQueryAsync();
}),Function.createDelegate(this,function(sender,args){alert(args.get_message());}));
}
Note that when using the JavaScript Client Object Model, you need to wait for the SP.JS library to load first. This can be accomplished using the built-in ExecuteOrDelayUntilScriptLoaded method like so:
ExecuteOrDelayUntilScriptLoaded(yourFunctionName,"SP.JS");
or
ExecuteOrDelayUntilScriptLoaded(function(){
// your code here
},"SP.JS");
I have a page that displays a calendar into with a attribute "data-date" that as a date like: "11/29/2014" and I need to check server if there's a log file for that date and change css for that div on mouse hover.
So far i get this code:
$(document).ready(function() {
var lab = $( ".label.day" ).hover(
function() {
dd = $(this).attr("data-date").split("/");
ddo = $(this).attr("data-date");
dday = ("0" + (dd[1])).slice(-2);
dmonth = ("0" + (dd[0])).slice(-2);
dyear = dd[2];
url = "logs/log." + dyear + "-" + dmonth + "-" + dday;
$.ajax({
type: 'HEAD',
url: url,
error: function(xhr, status, error) {
console.log(status)
},
success: function(xhr, status, error) {
console.log(status)
}
});
$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
console.log(thrownError)
if ( thrownError == "Not Found" ) {
$(".label.day").filter(ddo).addClass( "error" );
}
});
}, function() {
$(".label.day").filter(ddo).addClass( "noerror" );
}
);
});
<div data-date="1/16/2014" class="label day " original-title="Quinta" style="display: block;">16</div>
I can't change the class for the individual , without the .filter it changes all and .attr("data-date") doesn't work also.
There are several issues with your script:
You are not passing any data to the URL specified, via the data object in the $.ajax() function. Also, you need to specify to expected type of data (dataType) received (is it in JSON, plain text or otherwise?).
Use deferred objects and promises to check the status of the AJAX call
Use context, i.e. $(this), in your hover function so you can dictate which elements to modify without doing any filtering.
HEAD is an invalid value for the type object in the AJAX call. You should use POST or GET instead, depending on how the destination script is written to handle incoming data. Here's a good guide to deciding between the two.
Listen to mouseover instead of hover, as you are adding classes based on the status of the AJAX request, not the toggling between mouseover and mouseout events.
Use var when declaring functions to contain/restrict them within the function's scope, otherwise you risk polluting global variables :)
An improved code is as follow, but might not work unless you furnish more details on how you're checking the server for information.
$(document).ready(function() {
$('.label.day').on('mouseover', function() {
// Cache $(this)
var $t = $(this);
// Reset class
$t.removeClass('error noerror');
// Declare variables within function scope (not global)
var dd = $t.attr("data-date").split("/"),
ddo = $t.attr("data-date"),
dday = ("0" + (dd[1])).slice(-2),
dmonth = ("0" + (dd[0])).slice(-2),
dyear = dd[2],
url = "logs/log." + dyear + "-" + dmonth + "-" + dday;
// Perform AJAX call
var $check = $.ajax({
type: 'POST', //or "GET"
url: url;
});
// jQuery deferred object
$check.fail(function(jqXHR, textStatus) {
// If AJAX request failed and returned an error
console.log(textStatus);
$t.addClass('error');
}).done(function(data) {
// If AJAX request is successful
console.log(data);
$t.addClass('noerror');
});
});
});
In Full Calendar, i have some droppable external items. When i drag and drop one of them and immediately i delete it, it gets deleted, everything works fine. However, when i drop multiple items, such as 2 and when i delete 2 of them, both gets removed from calendar in the view, actually one gets removed from database, if i refresh the page i can see that.
When i check the form input hidden's value which is event's id fetched from database or returned from database as last insert id via ajax, both are the same it seems, actually they are not the same.
I think what i need is, resetting the eventID variable after they got dragged and dropped. I tried to initiliza them as empty, but it doesn't work.
How can i reset their values after ajax submit for the next units, hence keeping that variable to attached to current. Also its a global variable, i think this is the problem.
My Codes:
var eventID; // global variable
Drop Function:
drop: function(date, allDay) {
var originalEventObject = $(this).data('eventObject');
// 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;
if($extraEventClass) copiedEventObject['className'] = [$extraEventClass];
var tempDate = new Date(date);
copiedEventObject.start = $.fullCalendar.formatDate(copiedEventObject.start, "yyyy-MM-dd HH:mm:ss");
eventID = '';
$.ajax({
url: '<?=site_url("admin/calendar/add");?>',
data: 'title='+ copiedEventObject.title,
type: "POST",
success: function(newID){
eventID = newID;
//copiedEventObject._id = newID;
}
});
calendar.fullCalendar('renderEvent',
{
title: copiedEventObject.title,
start: date,
//id: copiedEventObject._id,
id: eventID,
}),
true // make the event "stick"
}
Event Click Function:
eventClick: function(calEvent, jsEvent, view) {
if(!eventID){
eventID = calEvent._id;
}
var form = $("<form id='changeName'>" +
"<h3 class='eventHeader'>Edit</h3>" +
"</div></form>");
form.append("<div class='controls'>" +
"<label class='control-label' for='title'>Name: </label>" +
"<input class='span3' name='title' autocomplete=off type='text' value='" + calEvent.title + "' />" +
"</div>");
form.append("<input type=hidden value='" + eventID + "' /> ");
form.append("<div class='controls'>" +
"<button type='submit'> Save </button>");
var div = bootbox.dialog(form,
[
{
"label" : "Delete",
"callback": function() {
deleteOrNot = confirm("Sure ??");
if (deleteOrNot) {
calendar.fullCalendar('removeEvents' , function(ev){
$.ajax({
url: '<?=site_url("admin/calendar/delete");?>',
data: 'id='+ eventID,
type: "POST"
});
return (ev._id == calEvent._id);
})
}
}
}
]);
$("#changeName").submit(function() {
calEvent.title = form.find("input[name=title]").val();
calEvent.description = form.find("input[name=description]").val();
calEvent.id = form.find("input[type=hidden]").val();
$.ajax({
url: '<?=site_url("admin/calendar/editTitle");?>',
data: 'title='+ calEvent.title+'&id='+ calEvent.id,
type: "POST"
});
calendar.fullCalendar('updateEvent', calEvent);
div.modal("hide");
return false;
});
}
In your delete process...you shouldn't be relying on the global eventID, rather just getting the ID from specific event
Change:
if(!eventID){
eventID = calEvent._id;
}
To:
var eventID = calEvent._id;
I suspect you also have a problem within drop by using the global eventID when dropping more than one at a time. Would have to see what // some methods here does.
What I would suggest is getting rid of the global eventID completely. When adding, wait for the id to be returned from server before passing the data to fullCalandar within your success callback
Similarly...within deleteOrNot...should make ajax request first, then only call the calendar.fullCalendar('removeEvents' within success callback of $.ajax. This will give confirmation of ajax success before user sees event removed. If ajax fails, user won't know using your approach