FullCalendar eventDragStart ui is empty - jquery-ui

I set up a fullcalendar with a eventStartDrag. When I do a log of the UI variable in the event, it seems to be empty. Is there any reason why ? All the other variables that are passed are ok.
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#calendar').fullCalendar({
header: {
left: 'prev,next',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'agendaWeek',
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function (date) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
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;
$('#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();
}
},
eventResize: function (event, delta, revertFunc) {
event.isChanged = true;
},
eventDrop: function (event, delta, revertFunc) {
event.isChanged = true;
},
eventDragStart: function (event, jsEvent, ui, view) {
console.log(event);
console.log(jsEvent);
console.log(ui);
console.log(view);
var dragged = [ui.helper[0], event];
},
events: [
{% for timeEntry in timeEntries %}
{
id: {{ timeEntry.id }},
title: '{{ timeEntry.task.description }}',
taskId: '{{ timeEntry.task.id }}',
start: '{{ timeEntry.startTime|date("Y-m-d\\TH:i:s") }}',
{% if timeEntry.stopTime is not null %}
end: '{{ timeEntry.stopTime|date("Y-m-d\\TH:i:s") }}',
{% else %}
end: null,
{% endif %}
isNew: false,
isChanged: false
},
{% endfor %}
]
});

As of version 2.1.1, jQueryUI is no longer a dependency (see release notes).
As the method signature kept the same, you will see in the source code that it always passes an empty object:
//(... fullCalendar 2.1.1 source code ...)
// line 4544
dragStart: function(ev) {
_this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
_this.isDraggingSeg = true;
view.hideEvent(event); // hide all event segments. our mouseFollower will take over
view.trigger('eventDragStart', el[0], event, ev, {}); // last argument is jqui dummy
},
When the eventDragStart is triggered the last argument is jqui dummy

Related

Turbolink - Fullcalendar only showing on reload

I have fullcalendar calendar that does not show unless I use turbolinks. But I would like not to use turbolink. Is there another way of loading the calendar.
My calendar.js looks like:
var initialize_calendar;
initialize_calendar = function() {
$('.calendar').each(function(){
var calendar = $(this);
calendar.fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
lang: "en",
selectable: true,
selectHelper: true,
editable: true,
eventLimit: true,
events: '/events.json',
select: function(start, end) {
$.getScript('/events/new', function() {
$('#event_date_range').val(moment(start).format("MM/DD/YYYY HH:mm") + ' - ' + moment(end).format("MM/DD/YYYY HH:mm"));
date_range_picker();
$('.start_hidden').val(moment(start).format('YYYY-MM-DD HH:mm'));
$('.end_hidden').val(moment(end).format('YYYY-MM-DD HH:mm'));
});
calendar.fullCalendar('unselect');
},
eventDrop: function(event, delta, revertFunc) {
event_data = {
event: {
id: event.id,
start: event.start.format(),
end: event.end.format()
}
};
// noinspection Annotator
$.ajax({
url: event.update_url,
data: event_data,
type: 'PATCH'
});
},
eventClick: function(event, jsEvent, view) {
// noinspection Annotator
$.getScript(event.show_url, function() {
$('#event_date_range').val(moment(event.start).format("MM/DD/YYYY HH:mm") + ' - ' + moment(event.end).format("MM/DD/YYYY HH:mm"));
date_range_picker();
$('.start_hidden').val(moment(event.start).format('YYYY-MM-DD HH:mm'));
$('.end_hidden').val(moment(event.end).format('YYYY-MM-DD HH:mm'));
});
}
});
})
};
(I remove the following at the bottom because i am removing turbolinks from the app: $(document).on('turbolinks:load', initialize_calendar);
)
In my index.html.erb, i have :
<div class="homepage_box_top_dashboard">
<div class='calendar' id="calendar"></div>
</div>
Any help please?
You still need to have something trigger your initialize_calendar() function to fire.
This was getting triggered by TurboLinks. Now you need something else to trigger it.
In plain speak:
$(document).on('turbolinks:load', initialize_calendar);
means: "when the turbolinks:load event fires, call initialize_calendar"
Right now you are just telling the browser that initialize_calendar exists, but you're never turning it on.
You should be able to use this:
// Jquery
$(document).on('ready', initialize_calendar());
-or-
// JQuery shorthand
$(document).ready(initialize_calendar());
which means "when the document:ready event fires, call initialize_calendar"
-or-
// pure Javascript
document.addEventListener('DOMContentLoaded', function() {
initialize_calendar();
});
which means "when the DOMContentLoaded event fires, call initialize_calendar"
You always have to tell JavaScript when to do something. It doesn't have to be when the page loads.
For example, you could assign this action to a button:
$('#initialize_calendar_button').on('click', initialize_calendar);
Hope that helps.

kendo ui Clickable row

I created a Kendo UI Grid view and it displays data correctly , now what I am trying to achieve is that ; When i Click on a row I want to get the primary key of that row and use it elsewhere I tried many solution in net but I did not work. does anyone knows how to achieve this.
here is my code :
function FondsGrid() {
var sharedDataSource = new kendo.data.DataSource({
transport: {
read: {
url:
"http://localhost:...........",
dataType: "json"
}
},
pageSize: 20
});
var accountGrid = $("#grid-fonds").kendoGrid({
dataSource: sharedDataSource,
sortable: true,
pageable: false,
columns: [
{
field: "CodIsin",
title: " ",
template: '<span class="categ #= CodIsin #"></span>',
attributes: {
class: "text-center"
},
headerattributes: {
style: "text-align:center"
},
width: 35
},
{
field: "LIBELLEPDT",
title: "Nom du fonds",
template: '<div id="#: IdProduitSP #" class="title-fonds #:
IdProduitSP #" data-toggle="popover" ><span class="desc-
fonds">#: LibClassificationNiv2 #</span>#: LIBELLEPDT #
.
.
.
dataBound: function () {
var widthGrid = $('.k-grid-content').width();
$(".k-grid-header").width(widthGrid);
$(".title-fonds").popover({
trigger: 'hover',
html: true,
template: '<div class="popover HalfBaked" role="tooltip">
<div class="arrow"></div><h3 class="popover-header"></h3><div
class="popover-body"></div></div>',
content: function () {
return $('#popover-content').html();
}
});
}
}).getKendoGrid();
/* Initialisation */
$(document).ready(function ($) {
FondsGrid();
});
Your own answer is perfectly valid and is a good example of how you can use jquery to directly target the dom elements that kendo generates. This approach is always valuable when kendo does not offer the functionality you need.
However in this case, the grid widget offers the change event. You can set the grid to be 'selectable' and subscribe to the 'change' event which fires when one or more rows are selected:
selectable: "multiple, row",
change: function(e) {
var selectedRows = this.select();
var selectedDataItems = [];
for (var i = 0; i < selectedRows.length; i++) {
var dataItem = this.dataItem(selectedRows[i]);
selectedDataItems.push(dataItem);
}
// selectedDataItems contains all selected data items
}
Within the handler function, 'this' refers to the grid widget instance and calling the select() function on it returns the selected rows. From those rows, you can then retrieve the datasource items that are bound to them giving you access to the id and any other properties.
See here for more details: https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/events/change
This how I fixed It.
$("#grid-fonds").on("click", "td", function (e) {
var row = $(this).closest("tr");
var value = row.find("td:first").text();
console.log(value);
});

JqGrid searchoptions with select2 existing value

I'm trying to integrate select2 for JqGrid filter form. I'm using JqGrid min 4.6 & Select2 min 4.0.1. The filter works fine but I'm unable to retrieve the value that has been set through select2 once the filter form is closed and reopened. i.e. dataInit e1 does not return the existing value of the select input. I must be doing something wrong?
JqGrid Column Model:
{
name: 'CurrencyID', hidden: true, search: true, stype: 'select', searchtype: 'number', searchoptions: {
searchhidden: true,
sopt: ['eq', 'ne'],
dataInit: function (el) {
intiGridFilterSelecr2Field(el, paramFromView.CurrencyOptions);
}
},
searchrules: { required: true }
},
Parameters:
#section scripts{
<script>
var paramFromView = {
CurrencyOptions: {
searchURL: '#Url.Action("GetCurrency", "Controller")',
detailURL: '#Url.Action("CurrencyDetailsJson", "Controller")',
idField: 'CurrencyID',
txtField: 'Description'
}
};
</script>
}
Select2 Helper:
function intiGridFilterSelecr2Field(element, options) {
var comboPageSize = 15;
var quietMillis = 200;
var placeHolderText = 'Choose...'
var defaults = {
searchURL: '',
detailURL: '',
idField: '',
txtField: ''
};
var options = $.extend({}, defaults, options);
var select2Element = $(element);
select2Element.select2({
width: 'element',
minimumInputLength: 1,
placeholder: placeHolderText,
ajax: {
url: options.searchURL,
dataType: 'json',
quietMillis: quietMillis,
cache: false,
data: function (params) {
return {
name: params.term,
page: params.page,
pageSize: comboPageSize
};
},
processResults: function (data) {
var more = (data.page * comboPageSize) < data.total;
var resultsArr = [];
for (var i = 0; i < data.result.length; i++) {
resultsArr.push({ id: data.result[i][options.idField], text: data.result[i][options.txtField] });
}
return { results: resultsArr, more: more };
}
},
}).each(function (index, element) {
var idCombo = $(this);
// The problem is that idCombo.val() is always empty.
// element:select2-hidden-accessible
if (idCombo.val() != null && idCombo.val().length > 0) {
$.ajax(options.detailURL, {
data: {
id: idCombo.val()
},
dataType: 'json',
cache: false
}).done(function (data) {
var optselected = select2Element.find('option').filter(function () { return this.value == data[idField] && this.text == data[txtField] && this.selected })
if (optselected == undefined || optselected.length == 0) {
var $optionContact = $("<option selected></option>").val(data[idField].toString()).text(data[txtField]);
var toBeRemoved = select2Element.find('option').filter(function () { return this.value == data[idField] });
if (toBeRemoved != undefined) {
toBeRemoved.remove();
}
select2Element.append($optionContact).trigger('change.select2');
}
});
}
});
}
When the filter is being set...
When Loading the existing filter. How do I pass this CurrencyID = 1 to select2 helper?
Update:
With Oleg's answer, I updated my code as below.
{
name: 'CurrencyID', hidden: true, searchtype: 'number', search: true,
stype: "select", searchoptions: {
searchhidden: true,
sopt: ["eq", "ne"],
dataUrl: paramFromView.CurrencyOptions.searchURL,
buildSelect: function (data) {
var obj = jQuery.parseJSON(data);
var i, options = [];
for (i = 0; i < obj.result.length; i++) {
options.push("<option value='" + obj.result[i][paramFromView.CurrencyOptions.idField] + "'>" +
obj.result[i][paramFromView.CurrencyOptions.txtField] + "</option>");
}
return "<select>" + options.join("") + "</select>";
},
noFilterText: "Any",
selectFilled: function (options) {
setTimeout(function () {
$(options.elem).select2({
width: 'element',
});
}, 0);
}
},
searchrules: { required: true }
},
I'm almost there with what I wanted to achieve. However I'm still facing some difficulties.
When the filter is initially loaded, value is selected on the dropdown but query value is empty. i.e. if the user clicks on the find button soon after the filter form is loaded, no filter will be set.
I still cannot get select2 styles working.
I can demonstrate how to use select2 with free jqGrid fork of jqGrid, which I develop. I get the demo from the README of the old version 4.14.1 (the current released version is 4.15.3) and modified it to demonstrate the usage of select2.
The main part of the code could be
stype: "select",
searchoptions: {
sopt: ["eq", "ne"],
...
selectFilled: function (options) {
setTimeout(function () {
$(options.elem).select2({
width: "100%"
});
}, 0);
}
}
See https://jsfiddle.net/Lae6kee7/2/. You can try to choose an option in the filter toolbar in "Shipped via" column and the open the search dialog. You will see that the select2 will have the same option selected.
If you would load the data via Ajax request posted by select2 than your code will be much more complex as it could be. It's important to understand that such way is really required only for really large set of possible value. I means the number of items larger as 100000 items for example. On the other side, the most use cases required less as 1000 options. In the case it would be more effective to load all the data as options of select and then convert the select to select2. select2, which uses local select works much more quickly from the users point of view.
The code will be easier in my opinion if you will use dataUrl instead of ajax option of select2. You can use dataUrl to return from the server all different values, which can be used in select2 and to use buildSelect to build <select> from JSON data returned from the server. The demo https://jsfiddle.net/Lae6kee7/23/ demonstrates that. I made the demo for JSFiddle, which supports Echo service (see here), which allows to simulate server responses. Your real code should contains mostly only dataUrl, buildSelect and the code of selectFilled, which I included above.
Additionally, I'd recommend you to consider to use <datalist> (see here for example), which could be good alternative to select2. All modern web browsers contains native support of <datalist> and thus <datalist> works very quickly. Try to search in the first Client column of my demos. You will see control, which will be very close to select2. Additional advantage of <datalist>: one will be able not search for only exact predefined values like test10, test11 or test12, but for substrings like 1. Compare
with
or
with

Jquery UI drag and drop - dragged item dissapears when dropped only on mobile

I am trying to get drag and drop working properly and on desktop of laptop pc it is fine. However, on a mobile device, when I drag and drop, when dropped, the dragged item dissapears underneath (i think) everything else and I really am unable to work out why.
I have uploaded a page showing the problem to http://mailandthings.co.uk/dam1/
I have tried setting the zindex in the draggable code and that makes no difference
var $dragContainer = $("div.drag-container");
var $dragItem = $("div.drag-item");
$dragItem.draggable({
cursor: "move",
snap: "div.drag-container",
snapMode: "inner",
snapTolerance: 10,
helper: "clone",
handle: "i",
zIndex: 10000
});
$dragContainer.droppable({
drop: function (event, ui) {
var $elem = $(event.toElement);
var obj = {
posX: event.pageX - $dragContainer.offset().left - event.offsetX,
posY: event.pageY - $dragContainer.offset().top - event.offsetY,
data: $elem.data(),
html: $elem.html()
};
addElement(obj);
masterPos.push(obj);
}
});
function addElement(obj) {
var $child = $("<div>");
$child.html("<i>" + obj.html + "</i>").addClass("drop-item drop-item-mobile");
$child.attr("data-type", obj.data.type);
$child.css({
top: obj.posY,
left: obj.posX
});
$dragContainer.append($child);
}
If it using jQuery UI Touch Punch 0.2.3
Does anyone have any ideas?
There was sort of a logistical issue that I found. Based on your code, I could identify the following state / logic:
User drags an item (A, B, C) to the car image to indicate a Dent, Scratch, or Heavy Damage
The Drop Point indicates where the Type of damage is located
When the dragged item is dropped, a new object should be created that indicates the Type and stores the location on the car map
This new object replaces the dragged item and is appended to the container
To expand on this, you have the following code that is the dragged element, for example:
<div class="drag-item ui-draggable" style="">
<i data-type="A" class="ui-draggable-handle">A</i>Dent
</div>
This is important when creating the new object. In your current code, you're requesting data from an object that does not have any data attributes, $elem.data(). Remember that this is the <div> that contains the <i> that has the attribute. So data is null or undefined. You will want to capture the data from the child element: $elem.find("i").data().
Also, since you append all the HTML to your new object, you make a double wrapped element. $child will look like:
<div class="drop-item drop-item-mobile">
<i>
<div class="drag-item ui-draggable" style="">
<i data-type="A" class="ui-draggable-handle">A</i>Dent
</div>
</i>
</div>
I do not think this was your intention. I suspect your intention was to create:
<div class="drop-item drop-item-mobile">
<i>A</i>
</div>
Here is an example of all this: https://jsfiddle.net/Twisty/g6ojp4ro/40/
JavaScript
$(function() {
var theForm = document.forms.form1;
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
var masterPos = [];
$("#hidpos").val('');
var $dragContainer = $("div.drag-container");
var $dragItem = $("div.drag-item");
$dragItem.draggable({
cursor: "move",
snap: "div.drag-container",
snapMode: "inner",
snapTolerance: 10,
helper: "clone",
handle: "i",
zIndex: 10000
});
$dragContainer.droppable({
drop: function(event, ui) {
var $elem = ui.helper;
var type = ui.helper.find("i").data("type");
var $child = $("<div>", {
class: "drop-item drop-item-mobile"
}).data("type", type);
$("<i>").html(type).appendTo($child);
$child.appendTo($dragContainer).position({
of: event
});
var obj = {
posX: $child.offset().top,
posY: $child.offset().left,
data: $child.data(),
html: $child.prop("outerHTML")
};
masterPos.push(obj);
}
});
$("map").imageMapResize();
// Save button click
$('#form1').submit(function(e) { //$("#btnsave").click(function () {
if (masterPos.length == 0) {
$("#spnintro").html("Oops!");
$("#spninfo").html("No position data was entered");
$("#dvinfo").fadeTo(5000, 500).slideUp(500, function() {});
} else {
$("#hidpos").val(JSON.stringify(masterPos));
$.ajax({
url: '/handlers/savepositions.ashx',
type: 'POST',
data: new FormData(this),
processData: false,
contentType: false,
success: function(data) {
$("#spnintro").html("Success!");
$("#spninfo").html("Position data has been saved");
$("#dvinfo").fadeTo(5000, 500).slideUp(500, function() {});
}
});
}
e.preventDefault();
});
});
Tested with Mobile client at: https://jsfiddle.net/Twisty/g6ojp4ro/40/show/ and is working as expected.
Hope that helps.

Synchronized HighChart: Uncaught TypeError: $(...).appendTo(...).highcharts is not a function

I have developed one webpage to show multiple charts. It is based on drop down menu selection. For example, if I select line then Line chart should appear in the container, if I select dual axis chart, it should appear in the same container. But while creating synchronized chart. I am facing one problem. It seems that the charts are being created, but they are not getting appended to container. Please help me out.
My code is as follows:
SynchronizedChart.js:
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, { trigger: 'syncExtremes' });
}
}
});
}
}
function drawSyncChart(Takennumber) {
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
/*$('#displayPanel').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.highlight(e);
}
}
});*/
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
Highcharts.Point.prototype.highlight = function (event) {
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
var output = { "xData": [], "datasets": [] };
//**********************************************
// DATA MANIPULATION AS PER HIGHCHART CONVENTION
//**********************************************
//console.log(JSON.stringify(output));
$.each(output.datasets, function (i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function (val, j) {
return [output.xData[j], val];
});
$('<div class="tmp">')
.appendTo('#displayPanel')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
type: 'datetime',
labels: {
formatter: function () {
return Highcharts.dateFormat('%a %d %b %H:%M:%S', this.value);
}
},
crosshair: true,
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
}]
});
// Append the chart
//div.appendTo("#displayPanel");
});
I am loading JS in following order:
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="../highcharts/highcharts.js"></script>
<script src="../highcharts/modules/exporting.js"></script>
<script src="../highcharts/themes/dark-unica.js"></script>
<script src="../PageJS/Admin/SynchronizedChart.js"></script>
And I am getting the error as follows:
SynchronizedChart.js:94 Uncaught TypeError: $(...).appendTo(...).highcharts is not a function
at Object.<anonymous> (SynchronizedChart.js:94)
at Function.each (datatables.min.js:14)
at drawSyncChart (SynchronizedChart.js:81)
at drawColumnChart (Chart.js:9)
at HTMLSelectElement.<anonymous> (ChemicalAnalysisChart.js:45)
at HTMLSelectElement.dispatch (datatables.min.js:16)
at HTMLSelectElement.r.handle (datatables.min.js:16)
(anonymous) # SynchronizedChart.js:94
each # datatables.min.js:14
drawSyncChart # SynchronizedChart.js:81
drawColumnChart # Chart.js:9
(anonymous) # ChemicalAnalysisChart.js:45
dispatch # datatables.min.js:16
r.handle # datatables.min.js:16
I solved the problem by separating creation of HighCharts and appending to the existing container. Please refer below code for reference:
$('<div id="chart' + i + '" class="col-md-20">').appendTo('#displayPanel');
var chart = new Highcharts.Chart({....... });
Also cleared the container before appending the Charts.
$(".highcharts-container").remove();

Resources