Moving $.get method to its own function to avoid repeating - javascript

I have the following function for pulling data from a php json_encode for use in FullCalendar.
eventDrop: function(info) {
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
editable = rawdata.find(x => x.id === info.event.id).editable;
start= info.event.start.toISOString();
start = moment(info.event.start).format('Y-MM-DD HH:mm:ss');
end= info.event.end.toISOString();
end = moment(info.event.end).format('Y-MM-DD HH:mm:ss');
title = info.event.title;
id = info.event.id;
});
}
I will use very similar code for the eventResize function within fullcalendar, so I would like to extract this part
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
into it's own function (not 100% sure I'm using the right terminology here?) I seen this answer jQuery - Passing variable within a function to another function about how to pass variables in the global scope, so I tried to move my above code out of eventDrop like so
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
});
eventDrop: function(info) {
But this gives me an error
Uncaught SyntaxError: Unexpected token '.'
Ideally I would like to do the json extract using the $.get only one time throughout my page, and then reference the rawdata global variable to read the information, is this possible?
My full solution at current is
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var today = moment().day();
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
defaultDate: today,
editable: true,
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
});
eventDrop: function(info) {
editable = rawdata.find(x => x.id === info.event.id).editable;
start= info.event.start.toISOString();
start = moment(info.event.start).format('Y-MM-DD HH:mm:ss');
end= info.event.end.toISOString();
end = moment(info.event.end).format('Y-MM-DD HH:mm:ss');
title = info.event.title;
id = info.event.id;
if (!confirm("Confirm you want to change " + info.event.title + " to " + info.event.start)) {
info.revert();
}
else{
if(editable === 'Y'){
$.ajax({
url: 'php/calendarupdate.php',
data: 'title=' + info.event.title + '&start='+ start +'&end=' + end + '&id=' + info.event.id ,
type: "POST"
});
}
else{
alert("Can only modify this calendar event if you created it. Please ask the event creator to modify.");
calendar.refetchEvents();
}
}
},
navLinks: true, // can click day/week names to navigate views
dayMaxEvents: true, // allow "more" link when too many events
events: {
url: '/php/get-events.php',
failure: function() {
document.getElementById('script-warning').style.display = 'block'
}
},
loading: function(bool) {
document.getElementById('loading').style.display =
bool ? 'block' : 'none';
}
});
calendar.render();
});
</script>

Problem solved, thanks to #Patrick Evans for the suggestion, I was adding the get call to the middle of my code, where I had to add it at the end, after the ";" to end the line. I can now reference "rawdata" variable within EventDrop.
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var today = moment().day();
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
defaultDate: today,
editable: true,
eventDrop: function(info) {
editable = rawdata.find(x => x.id === info.event.id).editable;
start= info.event.start.toISOString();
start = moment(info.event.start).format('Y-MM-DD HH:mm:ss');
end= info.event.end.toISOString();
end = moment(info.event.end).format('Y-MM-DD HH:mm:ss');
title = info.event.title;
id = info.event.id;
if (!confirm("Confirm you want to change " + info.event.title + " to " + info.event.start)) {
info.revert();
}
else{
if(editable === 'Y'){
$.ajax({
url: 'php/calendarupdate.php',
data: 'title=' + info.event.title + '&start='+ start +'&end=' + end + '&id=' + info.event.id ,
type: "POST"
});
}
else{
alert("Can only modify this calendar event if you created it. Please ask the event creator to modify.");
calendar.refetchEvents();
}
}
},
navLinks: true, // can click day/week names to navigate views
dayMaxEvents: true, // allow "more" link when too many events
events: {
url: '/php/get-events.php',
failure: function() {
document.getElementById('script-warning').style.display = 'block'
}
},
loading: function(bool) {
document.getElementById('loading').style.display =
bool ? 'block' : 'none';
}
});
$.get( "php/get-events.php", function( data ) {
// data is your result
// Find the value for editable where the event id = the event you are trying to move
rawdata = JSON.parse(data);
});
calendar.render();
});
</script>

Related

How to update start Time(!) in fullcalendar.js

Is there a way to change the start time of an Event, wich I draged into the calendar.
The Event comes from an external Source like this:
//initialize the external events
$('#external-events .fc-event').each(function() {
/* // store data so the calendar knows to render an event upon drop
$(this).data('event', {
title: $.trim($(this).text()), // use the element's text as the event title
stick: true // maintain when user navigates (see docs on the renderEvent method)
});
*/
var eventObject = {
title: $.trim($(this).text()), // use the element's text as the event title
id: $(this).data('id')
};
// 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
});
});
I want to change/update the start Time and Title - if necessary - of the Event in a modal Dialog. It seems to work fine, but everytime I add another Event by dragging and want to change it, it changes all other dragged Events, too.
eventClick: function(calEvent, jsEvent, view) {
//Sending data to modal:
$('#modal').modal('show');
$("#input_title").val(calEvent.title);
var my_time = moment(calEvent.start).format('LT');
$("#input_time").val(my_time);
var my_date = moment(calEvent.start).format("YYYY-MM-DD");
$("#input_date").val(my_date);
// waiting for button 'save' click:
$('.btn-primary').on('click', function (myEvent) {
calEvent.title = $("#input_title").val();
var my_input_time = $("#input_time").val();
var momentTimeObj = moment(my_input_time, 'HH:mm:ss');
var momentTimeString = momentTimeObj.format('HH:mm:ss');
var my_input_date = $("#input_date").val();
var momentDateObj = moment(my_input_date, 'YYYY-MM-DD');
var momentDateString = momentDateObj.format('YYYY-MM-DD');
calEvent.start = moment(momentDateString + ' ' + momentTimeString, "YYYY-MM-DD HH:mm");
$('#calendar').fullCalendar('updateEvent', calEvent);
$('#calendar').fullCalendar('unselect');
$('#modal').modal('hide');
});
}
What I am doing wrong?
I finally figured out, how to do this. In my example I'm able to change the event end-time by calculating the duration between start and end and diplay it as HH:mm. So the User can change the duration like 01:00 (hour). Also I add some additional fields like "information" and "color". After the changes in a modal (bootstrap) are made, I write it back to the calendar. Maybe there are better solutions for this, but for me it works fine.
// initialize the external events
$('#external-events .fc-event').each(function() {
// Start Time: String to Date
var my_start_time = new Date (new Date().toDateString() + ' ' + $(this).data('start'));
var start_time = moment(my_start_time).toDate();
// End Time: String to Date -> Date to Decimal
var my_dur_time = new Date (new Date().toDateString() + ' ' + $(this).data('duration'));
var dur_time = moment(my_dur_time).format('HH:mm');
dur_time = moment.duration(dur_time).asHours();
//Add Decimal End Time to Start Time
var end_time = moment(start_time).add(dur_time, 'hours');
// store data so the calendar knows to render an event upon drop
$(this).data('event', {
start: $(this).data('start'),
end: end_time,
title: $.trim($(this).text()), // use the element's text as the event title
stick: true, // maintain when user navigates (see docs on the renderEvent method)
});
// 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
});
});
$('#calendar').fullCalendar({
//Other calendar settings here ...
eventClick: function(event, element) {
curr_event = event;
var inp_start_time = moment(event.start).format();
var inp_end_time = moment(event.end).format();
var diff_time = moment(moment(inp_end_time),'mm').diff(moment(inp_start_time),'mm');
diff_time = moment.duration(diff_time, "milliseconds");
diff_time = moment.utc(moment.duration(diff_time).asMilliseconds()).format("HH:mm");
var my_time = moment(event.start).format('HH:mm');
var my_date = moment(event.start).format('DD.MM.YYYY');
var my_hidden_date = moment(event.start).format('YYYY-MM-DD');
$("#inp_time").val(my_time);
$("#inp_date").val(my_date);
$("#inp_hidden_date").val(my_hidden_date);
$("#inp_title").val(event.title);
$("#inp_duration").val(diff_time);
$("#inp_information").val(event.information);
$("#inp_color").val(event.color);
$('#modal').modal('show');
}
});
$("#button_ok").click(function (myevent) {
var my_input_time = $("#inp_time").val();
var momentTimeObj = moment(my_input_time, 'HH:mm:ss');
var momentTimeString = momentTimeObj.format('HH:mm:ss');
var my_input_date = $("#inp_hidden_date").val();
var momentDateObj = moment(my_input_date, 'YYYY-MM-DD');
var momentDateString = momentDateObj.format('YYYY-MM-DD');
var datetime = moment(momentDateString + ' ' + momentTimeString, "YYYY-MM-DD HH:mm");
var my_title = $("#inp_title").val();
var my_duration = $("#inp_duration").val();
var new_dur_time = moment.duration(my_duration).asHours();
//Add Decimal End Time to Start Time
var new_end_time = moment(datetime).add(new_dur_time, 'hours');
var new_information = $("#inp_information").val();
var new_color = $("#inp_color").val();
$.extend(curr_event, {
title: my_title,
start: datetime,
end: new_end_time,
information: new_information,
color: new_color
});
$("#calendar").fullCalendar('updateEvent', curr_event);
});
});
Hope this helps.
Greetings.

selectize.js questions about a no result plugin and allowing default behaviour on link

I am using selectize for an auto suggest field, and i have used one of the no_results plugins to show a link when there is no result, and this works great for the most part, but i have a few dramas i am just not sure how to get around
I have two things i need to get help with
1st most important - How to pass variables to the plugin
I have multiple instances of selectize on the several pages, so i need to pass the vars hr_link and hr_label to the plugin so i don't have to recreate the plugin 30 times with just the those vars different
2nd - Allow link to be clicked, bypassing default behaviour
To get the links to be clickable i have used the onmousedown() and touchstart() but is there a better way to re-enable the default click on just this link in the results box.
I have spent a lot of time researching these items, so I don't think it is a duplicate
// The Plugin
Selectize.define('header_no_results', function( options ) {
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var ignoreKeys = [KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN];
var self = this;
var hr_link = 'http://link_to_info.com';
var hr_label = 'country';
options = $.extend({
message: ' No results found: click here to add a'+hr_label,
html: function(data) {
return '<div class="selectize-dropdown-content">' + data.message + '</div>';
}
}, options );
self.on('type', function() {
var message = 'Not Found: click here Add a '+hr_label;
if (!self.hasOptions) {
self.$empty_results_container.html(message).show();
} else {
self.$empty_results_container.hide();
}
});
self.onKeyUp = (function() {
var original = self.onKeyUp;
return function ( e ) {
if (ignoreKeys.indexOf(e.keyCode) > -1) return;
self.isOpen = false;
original.apply( self, arguments );
}
})();
self.onBlur = (function () {
var original = self.onBlur;
return function () {
original.apply( self, arguments );
self.$empty_results_container.hide();
};
})();
self.setup = (function() {
var original = self.setup;
return function() {
original.apply( self, arguments);
self.$empty_results_container = $(
options.html($.extend({
classNames: self.$input.attr( 'class' )
}, options))
);
self.$empty_results_container.hide();
self.$dropdown.append(self.$empty_results_container);
};
})();
});
// the function calling the plugin
$('#companyLinks').selectize({
valueField: 'id',
labelField: 'display',
searchField: 'display',
maxItems: 1,
options: [],
create: false,
onItemAdd: function(value){
window.location.href = 'http://my_link.com/'+value;
},
load: function(query, callback) {
if (!query.length) return callback();
$.ajax({
url: 'http://link.com/get/list',
type: 'GET',
dataType: 'json',
data: {
q: query
},
error: function() {
callback();
},
success: function(res) {
callback(res);
//window.open($(res).val(), '_self');
}
});
},
plugins: ['header_no_results']
});
The solution to pass the var was not all that hard after all just had to look in the right place, and there is further info here
In the function we need to change out
plugins: ['header_no_results']
with
plugins: { "header_no_results": {
link : "page/location",
} }
then we can retrieve link and declare the var we needed in the plugin by
var hr_link = options.link;

Angular ui-calendar events function called twice

I am developing a project with AngularJS and using Angular-UI UI-Calendar. In my code I initialize eventSources model for ui-calendar to empty array ([]) and set ui-config "events parameter" to a custom function. That function makes an $http request and then calls the callback function given to the events function.
However, I found out that when I load the page or change the month viewed by left or right buttons, events function called twice. How can I solve that?
Here is my code:
function CalendarCtrl($scope, Data){
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
// Stores all events
var events = [];
/* config object */
$scope.uiConfig = {
calendar:{
height: 450,
editable: true,
header: {
left: 'prev,next',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
buttonText: {
month: "Ay",
week: "Hafta",
day: "Gün",
list: "Ajanda"
},
allDayText: "Tüm gün",
eventLimitText: "daha fazla",
firstDay: 1,
timeFormat: 'H:mm',
axisFormat: 'H:mm',
lazyFetching: true,
// Here listen for calendar change events
events: getEvents
}
};
// For angular ui-calendar element
$scope.eventSources = [];
// Calendar event handlers
function getEvents(from, to, callback){
console.log(from); // For test purposes
// Request for data from server and when it comes, call callback to update calendar
Data.calendar.get(moment(from).unix(), moment(to).unix()).then(function(events){
angular.forEach(events, function(event){
event.start = moment.unix(event.start);
if(event.end){
event.end = moment.unix(event.end);
}
else{
delete event.end;
}
var d = event.start;
if(d.hour() == 0 && d.minute() == 0 && d.second() == 0){
event.allDay = true;
}
if(event.important){
event.className = "important-event";
}
event.editable = true;
});
callback(events);
});
}
I have the solution.
Instead of registering an event handler to $scope.uiConfig.calendar.events, register that same function to $scope.eventSources array. Like that:
$scope.eventSources = [getEvents];
Whenever view changes and calendar needs data it will look at the $scope.eventSources elements. And if an element is a function it will be called and results will be shown in calendar.
We ran into a similar problem in a project and our solution was also in the eventSource initialization putting an empty object inside the array.
$scope.eventSources = [{}];

Click function doesn't work after ajax call in dynamic element (Backbone)

I've create dynamic popup in my Backbone.view by clicking button:
var Section = Backbone.View.extend({
className: 'sqs-frontend-overlay-editor-widget-section',
events:{
'click .sqs--section--control__edit': 'Section_control'
},
initialize: function(){
},
render: function(){
this.$el.append(_.template(_section).apply(this.options));
return this.$el;
},
Section_control: function(){
var me = this;
require(['View/Popup/Section_control'], function(_Section_control){
var sec = new _Section_control({popup: popup, sec: me.options.section});
var popup = new Popup({content: sec.render()});
});
}
});
return Section;
in the created dynamic popup i have button with trigger:
events:{
'click .module-invert-mode': 'invert'
},
invert: function(e){
console.log('hello');
if(this.options.sec.hasClass('.module-invert')) {
console.log('yse');
}
this.options.sec.toggleClass('module-invert');
this.options.sec.trigger('invertChange');
},
and button invertChange trigger:
el.on("invertChange", function(e){
var section = el.parents('section');
var index = section.index();
var model = collection.at(index);
model.set(Helper.sectionToObj(section),{doReload: true})
});
take a look at the {doReload: true} function that i call in invertChange:
change: function(model, options){
me = this;
if( model._changing && options.doReload ) {
$.ajax({
url: 'wp-admin/admin-ajax.php',
type: 'post',
data: {
action: 'getShortcode',
shortcode: model.attributes.shortcode
},
success: function (data) {
//var section = $(data);
me.$el.find('section:eq(' + model.collection.indexOf(model) + ')').replaceWith(data);
me.add( model, model.collection );
//me.collection.add({shortcode: model.attributes.shortcode}, {at: section.index()});
}
});
}
},
the problem is when I create dynamic popup and click on the button with invertChange trigger, ajax works only once, when I click on button in popup again, ajax doesn't works ( next ajax request works only if close and create dynamic popup again). How I can call ajax without constantly closing and opening my dynamic popup?
The problem that you have code which overrides child views
me.$el.find('section:eq(' + model.collection.indexOf(model) + ')').replaceWith(data);
And this listener is not able to handle event
el.on("invertChange", function(e){
because your code
this.options.sec.trigger('invertChange');
doesn't trigger event on correct view, it has lost the reference to this view after replaceWith()
As a solution you need parse your data object and apply each changes locally to elements
something like this
$(data).find("* [attr]").each(function(i, el) {
var $el = $(el),
attr = $el.attr("attr"),
$parent = me.$el.find('section:eq(' + model.collection.indexOf(model) + ')');
if ($el.is("div, span")) {
$parent.find('[attr=' + attr + ']').html($el.html());
} else if ($el.is("img")) {
$parent.find('[attr=' + attr + ']').attr("src", $el.attr("src"));
} else if ($el.is("a")) {
$parent.find('[attr=' + attr + ']').attr("href", $el.attr("href"));
} else if (attr == "image_back_one") {
$parent.find('[attr=' + attr + ']').attr("style", $el.attr("style"));
} else {
console.log($el);
}
});

Passing value to a form input field inside a jquery dialogbox?

I have a map on my index page. I want to click on the map and place a marker on the position. The click event has a function where i want to open up a modal (jquery dialog box) and load a form from another child html page with the position now filled in the right form-field.
My problem is passing the value (the marker position) to the input field in the form. My function seems to work if i put the input field somewhere on the index page but not in the child template in the dialogbox.
I'm trying with this $('#test_input').val(lng + ',' + lat); But it only show the value for millisecond then disappears. Do you have any ideas why this isn't working? Or how to reconstruct this? Thanks!
function onMapClick(e) {
var lat = e.latlng.lat;
var lng = e.latlng.lng;
if (typeof marker != 'undefined') {
map.removeLayer(marker);
marker = L.marker([lat, lng], {icon: redMarker}).addTo(map);
}
else {
marker = L.marker([lat, lng], {icon: redMarker}).addTo(map);
}
$('#upload-modal').load('upload/ #myform');
$('#test_input').val(lng + ',' + lat); //This is what I'm trying<----------
$('#upload-modal').dialog({
height: 550,
width: 500,
modal: false,
buttons: {
Upload: function() {
var dialog = $(this),
form = $('#myform'),
data = form.serialize();
$('.off').remove();
$.ajax({
url: 'upload/',
data: data,
type: 'post',
success: function(response) {
res = $.parseJSON(response);
if (res['status'] == 'OK') {
alert('Thank you! Form has been submitted');
dialog.dialog('close');
}
else if (res['status'] == 'bad') {
delete res['status']
var errors = res;
$.each(errors, function(key, value) {
var err = $('<span></span>', {
'class': 'off',
'text': value
}),
br = $('<br></br>', {
'class': 'off',
}),
input = $('#id_'+key).parent();
br.appendTo(input);
err.appendTo(input);
err.css('color', 'red').css('font-size', '10px');
});
}
}
});
}
}
});
}
It seems #test_input is in your form so you have to wait until the other form is completely loaded, use a callback like this:
$('#upload-modal').load('upload/ #myform', function(){
$('#test_input').val(lng + ',' + lat);
});

Categories

Resources