Previous post which lead to this issue: Fullcalendar using resources as a function with select menu
Based on my previous post, I have an issue using fullcalendar 4. When I am using resources as a function, my all-day blocks do not line up with my scheduler time slots. You can see it in the picture.
Here's my resources function:
resources: function(fetchInfo, successCallback, failureCallback) {
// Filter resources by whether their id is in visibleResourceIds.
var filteredResources = [];
filteredResources = resourceData.filter(function(x) {
return visibleResourceIds.indexOf(x.id) !== -1;
});
successCallback(filteredResources);
},
Here's my toggleresource function:
// menu button/dropdown will trigger this function. Feed it resourceId.
function toggleResource(resourceId) {
visibleResourceIds = [];
//if select all... see if undefined from loading on initial load = true
if ((resourceId == '') || (resourceId === undefined)) {
$.map( resourceData, function( value, index ) {
visibleResourceIds.push(value.id);
});
}
var index = visibleResourceIds.indexOf(resourceId);
if (index !== -1) {
visibleResourceIds.splice(index, 1);
} else {
visibleResourceIds.push(resourceId);
}
calendar.refetchResources();
Other related code (when the menu changes, the resources of the selected menu item show only in fullcalendar):
var resourceData = [];
var visibleResourceIds = [];
$.getJSON('ajax_get_json.php?what=schedule_providers_at_location',
function(data) {
$.each(data, function(index) {
resourceData.push({
id: data[index].value,
title: data[index].text
});
});
});
$('#toggle_providers_calendar').change(function() {
toggleResource($('#toggle_providers_calendar').val());
});
The resources show/hide just fine based on the selected menu resource, but look at the allday blocks - they don't line up after the resources are refetched for some reason. They correct themselves as the user navigates the scheduler though!
UPDATE BELOW
After looking around it looks like when refetchevents is called, the class .fc-week loses the following css:
style="border-right-width: 1px; margin-right: 20px;"
Here's a full pic of the calendar on initial load:
After I click a one of the navigation arrow, the all-day lines meet up with the rest of the calendar times because that style is applied to .fc-week.
I don't have any special css applied to the calendar and I am not using any themes that would get rid of this: at least not that I see now.
Here's the html that houses the calendar:
<div class="portlet-body">
<div class='loader'></div>
<div class="row">
<div id="calendar_full" style="padding-left: 10px; padding-right: 15px;"></div>
</div>
</div>
In order to fix this, I can add this following line after the resources are refetched in my toggleResources function:
$('#calendar_full .fc-week').css('border-right-width', '1px').css('margin-right', '20px');
I am going to keep looking as to why this css disappears after the resources are refetched. I wonder if it could be a glitch?
Related
I got an error and strange behavior inside template.onDestoyed;
I have code for infinite scroll subscribtion (it stored in special subscribtion-template) It work fine, until i switch to another route, and create a new instance of subscriber-template.
Code:
Template.subscriber.onCreated(function() {
var template = this;
var skipCount = 0;
template.autorun(function(c) {
template.subscribe(template.data.name, skipCount, template.data.user);
var block = true;
$(window).scroll(function() {
if (($(window).scrollTop() + $(window).height()) >= ($(document).height()) && block) {
block = false;
skipCount = skipCount + template.data.count;
console.log(template.data);
console.log("skip_count is "+skipCount);
template.subscribe(template.data.name, skipCount, template.data.user, {
onReady: function() {
block = true;
},
onStop: function() {
console.log('route switched, subscribtion stopped');
}
});
}
});
})
});
When i "scroll down" on a page, subscriber work fine, when i go in another page and "scroll down" first i get a data from old subscriber template (what must be destroyed in theory) in first time. In second time (scroll down again) new instance of subscriber starts works normally.
PIRNT SCREEN CONSOLE
What i doing wrong?
Owch!
The good guy from meteor forums helped me.
Actually the problem is in jquery.scroll event. It not cleaned up when template is destroyed. (Is it a bug? Or it is normal behavior?). I just needed to unbind the scroll event in onDestroyed section.
While using the Scheduler's Resource view the user found it hard to understand the hovering time.
Adding this below $('#calendar').fullCalendar( ... );
$(".fc-slats tr").each(function () {
$(this).addClass("timerow");
});
and CSS
.timerow:hover {background: lightblue;}
PROBLEM: When user pressed next or prev buttons the calendar rendered again the table and the .hover did not work.
adding the code also in the viewRender in Calendar's properties solved it.
viewRender: function (view, element) {
$(".fc-slats tr").each(function () {
$(this).addClass("timerow"); });
},
The final result is shown in the image below:
resource1
resource2
When I try to use this.findAll on a template where the selector is in a sub-template, findAll returns nothing.
Here's the HTML:
<template name="products">
{{#each productList}}
{{> product }}
{{/each}}
</template>
<template name="product">
<div class="box">{{name}}</div>
</template>
Here's the JS:
Template.products.helpers({
productList: function() {
var all = Products.find({}).fetch();
return all;
}
});
Template.products.rendered = function(){
var boxes = this.findAll('.box');
console.log(boxes.length);
}
Output of boxes.length is 0. Any ideas how I could get the "box" elements?
According to the docs for findAll:
Only elements inside the template and its sub-templates can match parts of the selector.
So it should work for sub-templates. I tried this with a fixed array of products and it worked, which implies that you are just seeing a delay between the call to rendered and the products being fetched. For example if you do:
Template.products.events({
'click .box': function (e, t) {
var boxes = t.findAll('.box');
console.log(boxes.length);
}
});
Then if you click on one of the boxes, you should see the correct number logged to the console. In short, I think the test may just be invalid. If you are using iron-router, you could try adding a waitOn for the products - that may ensure they arrive before the rendered call.
Here's what I did to run a script after all products have been loaded.
I've added last_product property in all the products.
Template.products.helpers({
productList: function() {
var all = Products.find({}).fetch();
var total = all.length;
var ctr = 0;
all.forEach(function(doc){
doc.last_product = false;
ctr++;
if(ctr == total)
{
doc.last_product = true;
}
return doc;
});
return all;
}
});
Then instead of "Template.products", I used "Template.product" to detect if the last product is rendered. When the last product is rendered, run the script.
Template.product.rendered = function(){
if(this.data.last_product){
var boxes = $('.pbox');
console.log(boxes.length);
}
}
boxes.length now has the correct length.
Thanks to David for the idea!
Here's the correct answer. I've added this to my iron-router route:
action : function () {
if (this.ready()) {
this.render();
}
}
Found the answer from https://stackoverflow.com/a/23576039/130237 while I was trying to solve a different problem.
I am trying to select events on fullcalendar, based on user selection.
Example: if user selects class A, then all classes with the same ID should turn green (using applied className).
I am having trouble applying classes to the other events that I can successfully select by ID. I guess my issue is combining the event objects with jQuery objects.
sample code:
eventClick: function(event) {
$(this).addClass("reg_selected"); //this works fine on selected event
var selectedID = event.id
alert(selectedID); //get event.ID, and use it to find similar ones.
var similarEvents = $("#calendar").fullCalendar('clientEvents',selectedID).addClass("reg_selected");
the error I get is:
addClass is not a function
I also tried this method of looping, and got the same error:
for (var i = 0; similarEvents.length > i ; i++){
alert(similarEvents[i].title);
similarEvents[i].className("reg_selected");
}
the alert() worked, but the className() generated the same error as above
This answer for a very similar situation, but when event classes are selected with round-trip to the event source for possible persistence in the db or checks.
Class name can be specified in the event object in the source as follows (start and end given for the context only):
[{
...
"className": "selected-event",
"start": '2017-05-01T08:30:00.0',
"ends": '2017-05-01T09:00:00.0',
...
}, ...]
The idea is that user clicks the event; ajax call to select events goes to backend; onsuccess, frontend javascript does$calendar.fullCalendar('rerenderEvents'); and receives the event source with events' classes. The immediate child of .fc-event-container gets the specified class, in the example above - selected-event.
As a result, the selection can be persisted on the backend.
clientEvents returns an array of matching objects. You need to iterate through the array (in your case similarEvents) and call addClass for each item
Update:
There is also issues using an id to update multiple events, using a filter function instead is a better way to go.
eventClick: function(event) {
var similarEvents = $("#calendar").fullCalendar('clientEvents', function(e) { return e.test === event.test });
for (var i = 0; similarEvents.length > i ; i++){
similarEvents[i].className = 'reg_selected';
$('#calendar').fullCalendar('updateEvent', similarEvents[i]);
}
},
See jsfiddle
For fullcalendar add event class, id and title see this.
if($('#eventTitle').val() == "Avilable") {
eventClass = "avilable";
}else {
eventClass = "unavilable";
}
$myCalendar.fullCalendar('renderEvent', {
id:response,
title: title.val(),
start: start.val(),
end: end.val(),
allDay: true,
className: eventClass,
color: color
}, true
);
I was able to get it working with the following code:
eventRender: function (eventObj, $el) {
$el.addClass(eventObj.ClassName);
},
eventObj.ClassName = "calendar-priority-warning"
I am working on a little project with knockout where i have to simulate the answer to asome questions.
I dynamically build 3 buttons and when i click one i compare the text on it with the correct answer and if it's correct it should become green.., if it's not correct it should become red and the right one should become green..
I was trying to use the binding to css property of knockout, but it seems that the property is not correctly refreshed, even if the computed associated with the css changes
The html:
<ul data-bind="foreach: chosenQuestionAnswers">
<li>
<button data-bind="text: answerText, css: $root.answerStatus(), click: $root.selectButton"></button>
</li>
</ul>
The ko part:
selectedAnswer: ko.observable(),
isAnswerCorrect: ko.observable(),
selectButton: function (value) { my.AppViewModel.isAnswerCorrect(my.AppViewModel.checkIfCorrectAnswer(value.answerText));
},
checkIfCorrectAnswer: function (value) {
return (value == my.AppViewModel.chosenQuestionCorrectAnswer());
},
my.AppViewModel.answerStatus = ko.computed(function () {
var exit = this.isAnswerCorrect() == true ? "highlightRight" : "highlightWrong";
console.log(this.isAnswerCorrect());
console.log(exit);
return exit;
}, my.AppViewModel);
The console.log shows the correct value of the var exit... but the css of the button does not change...
Any idea why?..
Thanks.... I.
you're referencing an old version of KO (2.1), the latest as of today is version is 2.2.1. Your fiddle works when referencing the new version # http://knockoutjs.com/downloads/knockout-2.2.1.js. Here's a fork: http://jsfiddle.net/drdamour/xe2M5/
The dynamic css binding (how you're using it) was only added in 2.2 see http://blog.stevensanderson.com/2012/10/29/knockout-2-2-0-released/
stack won't let me submit without some code so...here some worthless code:
var x = {a:1}
css classes are part of the view, try to keep them out of the ViewModel, it should focus on business logic.
I would do something like
http://jsfiddle.net/hLXbq/
HTML
<button data-bind="css: { valid: valid, invalid: invalid }, click: toggle">Toggle</button>
JS
ViewModel = function () {
this.valid = ko.observable(false);
this.invalid = ko.computed(function () {
return !this.valid();
}, this);
};