Can I loop through fullcalendar events after loading calendar? - fullcalendar-scheduler

My fullcalendar object has events loaded from a URL as seen below. When an event on the calendar is clicked, I need to not only pass that event back to a function (which is built in), but I need to also find another event that is associated with the clicked event by a field called lesson_id). Is there a way to loop through the events to find the other event with the same lesson_id?
events: {
url: smurl + "&subCmd=sch",
error: function () {
$('#script-warning').show();
},
viewRender: function (view) {
try {
setTimeline(view);
} catch (err) { }
}
},

I believe I have found my answer. It appears that .fullCalendar( 'clientEvents' [, idOrFilter ] ) returns an array of event objects held in memory.

Related

How to prevent #change event when changing v-model value

I'm building an auto-complete menu in Vue.js backed by Firebase (using vue-fire). The aim is to start typing a user's display name and having match records show up in the list of divs below.
The template looks like this:
<b-form-input id="toUser"
type="text"
v-model="selectedTo"
#change="searcher">
</b-form-input>
<div v-on:click="selectToUser(user)" class="userSearchDropDownResult" v-for="user in searchResult" v-if="showSearcherDropdown">{{ user.name }}</div>
Upon clicking a potential match the intention is to set the value of the field and clear away the list of matches.
Here is the code portion of the component:
computed: {
/* method borrowed from Reddit user imGnarly: https://www.reddit.com/r/vuejs/comments/63w65c/client_side_autocomplete_search_with_vuejs/ */
searcher() {
let self = this;
let holder = [];
let rx = new RegExp(this.selectedTo, 'i');
this.users.forEach(function (val, key) {
if (rx.test(val.name) || rx.test(val.email)) {
let obj = {}
obj = val;
holder.push(obj);
} else {
self.searchResult = 'No matches found';
}
})
this.searchResult = holder;
return this.selectedTo;
},
showSearcherDropdown() {
if(this.searchResult == null) return false;
if(this.selectedTo === '') return false;
return true;
}
},
methods: {
selectToUser: function( user ) {
this.newMessage.to = user['.key'];
this.selectedTo = user.name;
this.searchResult = null;
}
}
Typeahead works well, on each change to the input field the searcher() function is called and populates the searchResult with the correct values. The v-for works and a list of divs is shown.
Upon clicking a div, I call selectToUser( user ). This correctly reports details from the user object to the console.
However, on first click I get an exception in the console and the divs don't clear away (I expect them to disappear because I'm setting searchResults to null).
[Vue warn]: Error in event handler for "change": "TypeError: fns.apply is not a function"
found in
---> <BFormInput>
<BFormGroup>
<BTab>
TypeError: fns.apply is not a function
at VueComponent.invoker (vue.esm.js?efeb:2004)
at VueComponent.Vue.$emit (vue.esm.js?efeb:2515)
at VueComponent.onChange (form-input.js?1465:138)
at boundFn (vue.esm.js?efeb:190)
at invoker (vue.esm.js?efeb:2004)
at HTMLInputElement.fn._withTask.fn._withTask (vue.esm.js?efeb:1802)
If I click the div a second time then there's no error, the input value is set and the divs disappear.
So I suspect that writing a value to this.selectedTo (which is also the v-model object for the element is triggering a #change event. On the second click the value of doesn't actually change because it's already set, so no call to searcher() and no error.
I've noticed this also happens if the element loses focus.
Question: how to prevent an #change event when changing v-model value via a method?
(other info: according to package.json I'm on vue 2.5.2)
On:
<b-form-input id="toUser"
type="text"
v-model="selectedTo"
#change="searcher">
The "searcher" should be a method. A method that will be called whenever that b-component issues a change event.
But looking at your code, it is not a method, but a computed:
computed: {
searcher() {
...
},
showSearcherDropdown() {
...
}
},
methods: {
selectToUser: function( user ) {
...
}
}
So when the change event happens, it tries to call something that is not a method (or, in other words, it tries to call a method that doesn't exist). That's why you get the error.
Now, since what you actually want is to update searcher whenever this.selectedTo changes, to get that, it is actually not needed to have that #change handler. This is due to the code of computed: { searcher() { already depending on this.selectedTo. Whenever this.selectedTo changes, Vue will calculate searcher again.
Solution: simply remove #change="searcher" from b-form. Everything else will work.
#acdcjunior, thanks for your answer.
Of course just removing the reference to searcher() just means no action is taken upon field value change so the field won’t work at all.
Moving the searcher() function into methods: {} instead of computed: {} means that it will be called on an input event and not a change even (another mystery but not one for today). A subtle difference that takes away the typeahead feature I’m aiming at.
However, it did make me remember that the result of computed: {} functions are cached and will be re-computed when any parameters change. In this case I realised that the searcher() function is dependent upon the this.selectedTo variable. So when the selectToUser() function sets this.selectedTo it triggers another call to searcher().
Fixed now. In case anyone has a similar problem in the future, I resolved this by turning to old fashioned semaphore by adding another variable.
var userMadeSelection: false
Now, searcher() begins with a check for this scenario:
computed: {
searcher() {
if(this.userMadeSelection) {
this.userMadeSelection = false;
return this.selectedTo;
}
…
and then in selectToUser():
this.userMadeSelection = true;

Mithriljs does not update DOM on change in data

I read somewhere, the DOM is updated every time an event occurs and there is changes in data which are bound to DOM. So I wished to learn more about it. I tried the code below but the DOM is not updated when data in textarea changes but its updated whenever I click or press tab key.
var app = {
controller: function () {
var self = this;
this.model = {};
this.model.errors = [];
this.break_data = function (value) {
self.model.errors = value.split(' ');
m.redraw();
}
},
view: function (ctrl) {
return m('.content', [
m('textarea', {onchange: m.withAttr('value', ctrl.break_data)}),
ctrl.model.errors.map(function (error) {
return m('.error', error);
})
]);
}
}
m.mount(document.getElementById('app'), app);
I even tried m.startComputaion(), m.stopComputation() and m.redraw() non of them works.
The redrawing timing is described here: https://stackoverflow.com/a/30728976/70894
As for your example, the problem is not Mithril but the event. You need to use oninput instead of onchange to look for immediate changes. As the Mozilla docs for the "change" event states:
The change event is fired for input, select, and textarea
elements when a change to the element's value is committed by the
user. Unlike the input event, the change event is not necessarily
fired for each change to an element's value.
Here's a fiddle with your code that uses oninput: http://jsfiddle.net/ciscoheat/LuLcra77/
Note that you don't need m.redraw in the event handler anymore now when the correct event is used, since Mithril redraws automatically after every event defined in a call to m().

How to catch opened event on a ComboBox with Dojo?

I want to know whether a combo box has been opened and call a function that displays an progress bar while it loads the data from a store. I've check the API but no I didn't find any suitable event for what I'm doing.
EDIT
What I want to do is start a progress bar while the combobox is populated from the store. I've created a widget with the combobox and the progress bar (a custom class) and "decorate" openDropDown function with aspect.before. This is the code I've written:
postCreate: function() {
this.inherited(arguments);
aspect.before(
this.comboBox, 'openDropDown',
lang.hitch(this, function(){
this.progressBar.increase();
})
);
on(
this.comboBox,
'search',
lang.hitch(this.progressBar, 'decrease')
);
}
But it seems is not using the right progressBar object.
It sounds like you are looking for something like an "onOpen" event. as of Dojo 1.10 The Dijit/Combobox widget does not support an event like the one you are describing, however it does support a number of other events that might meet your requirements.
I recommend looking into the api for a list of possible events: http://dojotoolkit.org/api/
However the following code will create a custom "onOpen" event like what you are describing. I've provided a jsfiddle which demos this new event
http://jsfiddle.net/kagant15/z4nvzy44/
var comboBox = new ComboBox({
id: "stateSelect",
name: "state",
value: "California",
store: stateStore,
searchAttr: "name"
}, "stateSelect")
// grab the existing openDropDown method
var openDropDownFunction = comboBox.openDropDown;
newFunction = function(){
topic.publish("openDropDown") // add the custom "openDropDown" event trigger
return openDropDownFunction.apply(this);
}
// replace the old comBox method will our new function
comboBox.openDropDown = newFunction;
// Subscribe to the custom openDropDown event and do something when it fires
topic.subscribe("openDropDown", function(){
console.log("Open Drop Down even trigger");
});

dojo make a widget react to a published event

Im trying to figure out how to close a pop up dialog based on a published event .. i.e when a person moves the mouse to another part of the page.(i only want it closed when i move to this part of the page) Is this possible
i have a topic published when the user moves off this area.
_hoverOffArea : function() {
topic.publish("messageRollOver/close");
},
how do i get my popup to subscribe to this topic and close itself ?
var tooltip = new TooltipDialog({
onMouseLeave : function() {
},
onBlur : function() {
}
});
messageTooltip.set("content", rollOver.domNode);
popup.open({
popup: tooltip,
around: e
});
You may be over thinking it. The dojo/topic module has a subscribe method which takes a topic name ("messageRollOver/close") and a function to fire when the message is published.
topic.subscribe('messageRollOver/close',function(args){
console.log('close tooltip');
});
You can pass arbitrary parameters to the publish message that are then passed to the subscribe:
topic.subscribe("messageRollOver/close",function(arg1){
console.log("arg1 = ",arg1);
});
var tooltip = new TooltipDialog(/*params*/);
topic.publish("messageRollOver/close",tooltip);
when the subscribe function is invoked, arg1 would be the second argument to the topic#publish function call.

In backbone.js how do I bind a keyup to the document

I've been following along with a Railscast tutorial of backbone.js and I wanted to extend the functionality to include keyboard control. I added the following to my show view:
class Raffler.Views.EntryShow extends Backbone.View
template: JST['entries/show']
events:
'click .back': 'showListing'
'keyup': 'goBack'
showListing: ->
Backbone.history.navigate("/", trigger: true)
goBack: (e) ->
console.log e.type, e.keyCode
render: ->
$(#el).html(#template(entry: #model))
this
On my show template I have the following:
Back
<%= #entry.get('name') %></td>
If I select the back link using the tab key, then start hitting random keys I get output in my javascript console. However if I load the page and do not select the link and just start hitting keys I get no output in my console.
How do I bind the event to the document so that it will listen to any keys pressed when loading the screen?
You will need to work around backbone's scope for views.
when you are doing something like this:
events:
'click .back': 'showListing'
'keyup': 'goBack'
you are binding your goBack function to the keyup event raised on your container element of your view. (by default the div in which the view is rendered)
instead of doing that, if you want to bind to something outside your view (which doesn't have it's own view!(*))
Raffler.Views.EntryShow = Backbone.View.extend({
template: JST['entries/show'],
events: {
'click .back': 'showListing'
},
initialize: function () {
$('body').keyup(this.goBack);
},
showListing: function () {
Backbone.history.navigate("/", trigger: true);
},
goBack: function (e) {
console.log e.type, e.keyCode;
},
render: function () {
$(this.el).html(this.template(entry: #model));
return this;
}
});
(*)remark as marked above, you best do this only when the item you want to bind to does not have it's own view, if you have a view for your full page (an app view or something like that) you could bind the keyup in there, and just raise an event App.trigger('keypressed', e); for example.
you can then in your EntryShow view, bind to that App's keypressed event.
App.bind('keypressed', goBack);
keep in mind that you should do something as a delayed event or grouping keypresses together in some situations, as firing every keypress that happens in the body, might be a big performance hit. especially on older browsers.
Your events will be scoped to your view element #el. To capture events on the document, you have to roll that yourself:
initialize: ->
$(document).on "keyup", #goBack
remove: ->
$(document).off "keyup", #goBack
Should do the trick.