Get object id on drop with fullCalendar - javascript

I am using the fullCalendar plugin to show a calendar with the different events and elements in. Some of then are draggable and therefore possible to alter the date etc. which I need to update in the database as well. But I'm getting stuck because I can't seem to find a way to get that id of the object that is being moved.
I have the code that takes the data out of DB and renders it in the calendar like this:
$scope.temp = [];
$scope.academy = [];
$http.get(api.getUrl('academy', user.id)).success(function (response) {
$scope.temp = response;
for (var j = 0; j < response.length; j++) {
$scope.academy.push({
id: $scope.temp[j].id,
title: $scope.temp[j].name,
start: new Date($scope.temp[j].date).getTime(),
className: 'bg-info bg',
editable: true,
location: $scope.temp[j].location,
info: $scope.temp[j].description
})
if($scope.academy[j].start < $scope.time ) {
$scope.academy[j].className= 'bg-success bg'
}
if(0 < $scope.academy[j].start-$scope.time && $scope.academy[j].start-$scope.time < 172800000) {
$scope.academy[j].className= 'bg-danger bg'
alert('Remember '+$scope.academy[j].title);
}
$('.calendar').fullCalendar('renderEvent',{
id: $scope.academy[j].id,
title: $scope.academy[j].title,
start: $scope.academy[j].start,
className: $scope.academy[j].className,
editable: true,
location: $scope.academy[j].location,
info: $scope.academy[j].info
}, true)
}
});
I then have a onDrop function that is being activated whenever a drop happens. I can verify that with a simple alert().
/* alert on Drop */
$scope.alertOnDrop = function(){
alert($('.calendar').fullCalendar('clientEvents'));
};
This obviously returns an alert with all the objects on the calendar, and if I add a specific id I get that specific object as [object Object]. But I need to get the object and id of whatever object is being dropped on the calendar and I could really use some inputs on how I can achieve that?

alertOnDrop gives you the element as the first argument of your anon function.
$scope.alertOnDrop = function(e){
alert(e.id);
};

Related

Why can't I choose value from select2?

All data is shown and correct but I can't select any value from select2 dropdown.
What is wrong with my code?
jQuery(document).ready(function() {
jQuery('#basic').select2({
minimumInputLength: 0,
multiple: false,
query:function(options) {
var result = ymaps.suggest(options.term).then(function (items) {
var data = [];
var output = {
results : [],
more : null
};
for (var index = 0; index < items.length; ++index) {
console.log(items[index]);
data.push({
id: index,
text: items[index]['displayName'],
})
}
output.results = data;
output.more = true;
console.log(output);
options.callback(output);
});
}
});
jQuery('#basic').on('select2:select', function () {
console.log('on select: ' + jQuery(this).val());});
}
After doing R&D on select2 I found that query method is deprecated (See https://select2.org/configuration/options-api) so try to use ajax method.
Also there is one more issue when I opened the debugger I found that other select2 drop down (I mean select2 used on https://select2.org/) is adding options under drop down but in your case your select box is empty.
I would suggest try asking on their community https://forums.select2.org/

updating the array that is being passed to highcharts in meteor app

I'm using meteor to build a dashboard that uses highcharts to build the charts. Current set up is as follows. The page loads to show a drop down menu. When the user clicks the drop down menu, the client.js queries the database based on the selection, pushes the results to a few global arrays followed by a blaze.render of the template which has the chart. The chart uses the global variables as the series data and the xAxis categories. Problem is that when the user selects a different option from the drop down, the arrays should get updated and the chart re-rendered. But I noticed that the array does not get populated with new values. Instead new values get appended to the array.
Code below:
Template.districtDropdown.events({
'change #selectDistrict' : function(event, template){
// productValues2.length = 0;
// productUsage2.length = 0;
// productFidelity2.length = 0;
// productNames2.length = 0;
event.preventDefault();
var selectedValue = template.$("#selectDistrict").val();
console.log("You Selected " + selectedValue);
var filter = {
find: {
'School District' : selectedValue
}
};
$(filter).ready(function() {
Meteor.subscribe('aggByDistrict', filter, function() {
productUsage2 = [], productValues2 = [], productFidelity2 = [];
productNames2 = _.uniq(CombinedData.find().map( function(doc) { return doc.Product; }));
for(var i = 0; i < productNames2.length; i++) {
productValues2.push(CombinedData.find({'Product' : productNames2[i]}).count());
productUsage2.push(CombinedData.find({'Product' : productNames2[i], 'Usage' : {$gt:0}}).count());
productFidelity2.push(CombinedData.find({'Product' : productNames2[i], 'Fidelity' :1 }).count());
};
console.log(productNames2, productUsage2, productValues2, productFidelity2);
// Renders the highchart that shows the various aggs for selected district
Blaze.render(Template.LicensesDistributedByDistrict, $("#LicensesByDistrictCharts")[0]);
});
});
}
});
If I were to uncomment the productValues2.length = 0 then the chart gets empty arrays.
I know this is probably a a horrible implementation, but I'm trying to learn how to use meteor / highcharts.
It's appending the values because you're not clearing out its existing values.
// productValues2.length = 0;
// productUsage2.length = 0;
// productFidelity2.length = 0;
// productNames2.length = 0;
The code above clears the arrays
Okay, I think I figured out the answer. With the code posted by me earlier, the client side minimongo is populated by the subscribe command when the client makes the first choice from the drop down menu. When the client makes a second choice from the drop down, the server uses the new filter, and published the new documents to the already live collection on the client side minimongodb. To fix this, I modified the code by adding a .stop() at the end, after the chart has been rendered. This stops / clears the client side collection, and the whole process starts again when the client selects a second option from the drop down. Fixed code below:
//Handle the selection event from district dropdowns
Template.districtDropdown.events({
'change #selectDistrict' : function(event, template){
event.preventDefault();
var selectedValue = $(event.target).val();
var filter = {
find: {
'School District' : selectedValue
}
};
// console.log(filter);
$(filter).ready(function() {
var filteredCollection = Meteor.subscribe('aggByDistrict', filter, function() {
productNames2 = [], productUsage2 = [], productValues2 = [], productFidelity2 = [];
console.log(productNames2, productUsage2, productValues2, productFidelity2);
productNames2.length = 0, productUsage2.length = 0, productValues2.length = 0, productFidelity2 .length = 0;
productNames2 = _.uniq(CombinedData.find().map( function(doc) { return doc.Product; }));
for(var i = 0; i < productNames2.length; i++) {
// productValues2 = CombinedData.find({'Product' : productNames2[i]}).map()
productValues2.push(CombinedData.find({'Product' : productNames2[i]}).count());
productUsage2.push(CombinedData.find({'Product' : productNames2[i], 'Usage' : {$gt:0}}).count());
productFidelity2.push(CombinedData.find({'Product' : productNames2[i], 'Fidelity' :1 }).count());
};
console.log(productNames2, productUsage2, productValues2, productFidelity2);
// Renders the highchart that shows the various aggs for selected district
Blaze.render(Template.LicensesDistributedByDistrict, $("#LicensesByDistrictCharts")[0]);
filteredCollection.stop();
});
});
}
});

ComboBox typeAhead works but valueField is null under certain behavioral conditions

Requesting a sanity check here please...
ExtJS 4.2 comboBox Typeahead works but having issues retrieving the valueField under the following conditions:-
1) If a user types a value and then instead of hitting enter or clicking on the select combo list, they click elsewhere then the valueField is empty but the selected value is present.
2) Assuming that the combobox item was selected correctly, If I enter an additional character and then backspace that character, the combo box can no longer find the valueField..its almost like it has reset itself.
Fiddle example
https://fiddle.sencha.com/#fiddle/je1
How to reproduce
If you enter Maggie in the combo box, you will see the valueField ID in the console window, if you append a character and then backspace the character, the ID in the console window is null
(You will need to open the console window to see the output)
forceSelection does not resolve this issue as I have a template and it will not accept an entry in the combobox that is not part of the store, and I need to use sumID for my valueField as I need to retrieve and pass that value to the server.
Thank you everyone, awesome to have such a great community!!
I was able to get around this by using forceSelection and overriding the setValue thus allowing template items not in the store but in the combo to be selected via forceSelection. From playing around with the combobox, IMO, for a good look and feel, forceSelection is the way to go.
Here is my override, refer to statement //start of override
This was a quick fix, I will refine statement when I am back in the office, below I am pasting the solution from memory, you get the idea.
setValue: function(value, doSelect) {
var me = this,
valueNotFoundText = me.valueNotFoundText,
inputEl = me.inputEl,
i, len, record,
dataObj,
matchedRecords = [],
displayTplData = [],
processedValue = [];
if (me.store.loading) {
// Called while the Store is loading. Ensure it is processed by the onLoad method.
me.value = value;
me.setHiddenValue(me.value);
return me;
}
// This method processes multi-values, so ensure value is an array.
value = Ext.Array.from(value);
// Loop through values, matching each from the Store, and collecting matched records
for (i = 0, len = value.length; i < len; i++) {
record = value[i];
if (!record || !record.isModel) {
record = me.findRecordByValue(record);
}
// record found, select it.
if (record) {
matchedRecords.push(record);
displayTplData.push(record.data);
processedValue.push(record.get(me.valueField));
}
// record was not found, this could happen because
// store is not loaded or they set a value not in the store
else {
//start of override
// 'Select All Names' is the template item that was added // to the combo box, it looks like an entry from the store
// but it is not in the store
if (me.forceSelection && me.getDisplayValue() === 'Select All Names'){
processedValue.push(value[i]);
dataObj = {};
dataObj[me.displayField] = value[i];
displayTplData.push(dataObj);
}
//end of override
if (!me.forceSelection) {
processedValue.push(value[i]);
dataObj = {};
dataObj[me.displayField] = value[i];
displayTplData.push(dataObj);
// TODO: Add config to create new records on selection of a value that has no match in the Store
}
// Else, if valueNotFoundText is defined, display it, otherwise display nothing for this value
else if (Ext.isDefined(valueNotFoundText)) {
displayTplData.push(valueNotFoundText);
}
}
}
// Set the value of this field. If we are multiselecting, then that is an array.
me.setHiddenValue(processedValue);
me.value = me.multiSelect ? processedValue : processedValue[0];
if (!Ext.isDefined(me.value)) {
me.value = null;
}
me.displayTplData = displayTplData; //store for getDisplayValue method
me.lastSelection = me.valueModels = matchedRecords;
if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
inputEl.removeCls(me.emptyCls);
}
// Calculate raw value from the collection of Model data
me.setRawValue(me.getDisplayValue());
me.checkChange();
if (doSelect !== false) {
me.syncSelection();
}
me.applyEmptyText();
return me;
},
Look at the sources of Combobox and try override this method as follows
doLocalQuery: function(queryPlan) {
var me = this,
queryString = queryPlan.query;
if (!me.queryFilter) {
me.queryFilter = new Ext.util.Filter({
id: me.id + '-query-filter',
anyMatch: me.anyMatch,
caseSensitive: me.caseSensitive,
root: 'data',
property: me.displayField
});
me.store.addFilter(me.queryFilter, false);
}
if (queryString || !queryPlan.forceAll) {
me.queryFilter.disabled = false;
me.queryFilter.setValue(me.enableRegEx ? new RegExp(queryString) : queryString);
}
else {
me.queryFilter.disabled = true;
}
me.store.filter();
if (me.store.getCount()) {
if (me.rawValue === me.lastSelection[0].get(me.displayField)){
me.setValue(me.lastSelection);
} else {
if(me.store.getCount() === 1){
me.setValue(me.store.first());
}
me.expand();
}
} else {
me.collapse();
}
me.afterQuery(queryPlan);
},

How to serialize delete data with jqGrid, multiselection, and Spring?

Currently, I have an overridden delGridRow call that looks like this (credit to Krams and his Spring tutorial):
var row = $('#grid').jqGrid('getGridParam','selrow');
$('#grid').jqGrid( 'delGridRow', row,
{ url:'deleteRequirement.html',
recreateForm: true,
beforeShowForm: function(form) {
//Change title
$(".delmsg").replaceWith('<span style="white-space: pre;">' +
'Delete selected record?' + '</span>');
//hide arrows
$('#pData').hide();
$('#nData').hide();
},
reloadAfterSubmit:true,
closeAfterDelete: true,
serializeDelData: function (postdata) {
var rowdata = $('#grid').getRowData(postdata.id);
// append postdata with any information
return {id: postdata.id, oper: postdata.oper, reqID: rowdata.reqID};
},
afterSubmit : function(response, postdata)
{
var result = eval('(' + response.responseText + ')');
var errors = "";
if (result.success == false) {
for (var i = 0; i < result.message.length; i++) {
errors += result.message[i] + "<br/>";
}
} else {
$('#msgbox').text('Entry has been deleted successfully');
$('#msgbox').dialog(
{ title: 'Success',
modal: true,
buttons: {"Ok": function() {
$(this).dialog("close");
}
}
});
}
// only used for adding new records
var newId = null;
return [result.success, errors, newId];
}
});
else {
$('#msgbox').text('You must select a record first!');
$('#msgbox').dialog(
{ title: 'Error',
modal: true,
buttons: {"Ok": function() {
$(this).dialog("close");}
}
});
}
In order to add support for multiselection deletes, I changed the "selrow" first line to this:
var rowList = jQuery("#grid").getGridParam('selarrrow');
After this, things start getting sketchy fast. The spec says that the default delGridRow can accept an array of inputs records to delete. I made the following change to attempt to get the new 'rowList' variable to get used:
$('#grid').jqGrid( 'delGridRow', rowList, ...
I'm still hitting my deleteRequirement.html URL in my Spring controller, but only the last records appears to make it. I'm guessing the problem is in the postdata preparation in the serializeDelData section, but I haven't found the correct way to prepare this postdata with the list of records instead of the single record.
Any suggestions/insight would be appreciated.
Thanks all.
I don't use Spring myself, but some parts of your code seams be strange for me.
First of all the you can use two forms of the first parameter of delGridRow (row in your code). It can be either the comma-separated list of ids or an array of ids. If you use array of ids then jqGrid convert it to the comma-separated format by rowids = rowids.join();. As the result the format of postdata.id inside of serializeDelData can be also the comma-separated list of ids.
So if you need to support delete of multiple rows you should
modify the code of serializeDelData to send in reqID property also the list of the reqID. The corresponding code can be
serializeDelData: function (postdata) {
var ids = postdata.id.split(','), i, l = ids.length, reqIDList = [];
for (i = 0; i < l; i++) {
reqIDList.push($(this).jqGrid("getCell", ids[i], "reqID"));
}
return {id: postdata.id, oper: postdata.oper, reqID: reqIDList.join()};
}
modify your server code to support both id and reqID in comma-separated form.
Inside of afterSubmit callback you you the lines
// only used for adding new records
var newId = null;
return [result.success, errors, newId];
You can modify the lines to the following
return [result.success, errors];
because only the first two elements of the array returned by afterSubmit callback will be used.

Handling no results in jquery autocomplete

Hey I'm trying to return a message when there are no results for the users current query! i know i need to tap into the keyup event, but it looks like the plugin is using it
This question is really out of date, anyways I'm working with the new jQuery UI 1.8.16, autocomplete is now pretty different:http://jqueryui.com/demos/autocomplete/#default
Anyways if you're trying to the do the same thing as the question asks, there is no more parse function, as far as I know there is no function that is called with the search results.
The way I managed to pull this off is by overriding the autocomplete's filter function - Note: this will affect all your autocompletes
$.ui.autocomplete.filter = function(array, term) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
var aryMatches = $.grep( array, function(value) {
return matcher.test(value.label || value.value || value);
});
if (aryMatches.length == 0){
aryMatches.push({
label: '<span class="info" style="font-style: italic;">no match found</span>',
value: null
});
}
return aryMatches;
};
The function is slightly modified from the source, the grep call is the same, but if there are no results I add an object with a value of null, then I override the select calls to check for a null value.
This gives you an effect where if you keep typing and no matches are found you get the 'no matches found' item in the dropdown, which is pretty cool.
To override the select calls see jQuery UI Autocomplete disable Select & Close events
$(this).data('autocomplete').menu.options.selected = function(oEvent, ui){
if ($(ui.item).data('item.autocomplete').value != null){
//your code here - remember to call close on your autocomplete after
}
};
Since I use this on all my autocompletes on a page, make sure you check if value is null first! Before you try to reference keys that aren't there.
You could try supplying a parse option (function to handle data parsing) and do what you need when no results are returned to parse.
This example assumes you're getting back an array of JSON objects that contain FullName and Address attributes.
$('#search').autocomplete( {
dataType: "json",
parse: function(data) {
var array = new Array();
if (!data || data.length == 0) {
// handle no data case specially
}
else {
for (var i = 0; i < data.length; ++i) {
var datum = data[i];
array[array.length] = {
data: datum,
value: data.FullName + ' ' + data.Address,
result: data.DisplayName
};
}
}
return array;
}
});
I'm using the following code for the same purpose (the message is shown in the autocomplete list):
success: function(data, status, xhr){
if(!data.length){
var result = [
{
label: 'There are no matches for your query: ' + response.term,
value: response.term
}
];
response(result);
}
else{
// normal response
}
}
You can also utilize the "response" event to examine this. Simple but powerful. http://api.jqueryui.com/autocomplete/#event-response
response: function (event, ui) {
if (ui.content.length == 0) {
//Display an alert or something similar since there are no results
}
},

Categories

Resources