Timers or timed events for backbone.js Views - events

I am trying to build an automatic carousel as a Backbone.js View so that it slides every so often. Ideally what I would like is a timer event. Something like
events{
"timer 5000" : "slide"
}
I don't see this happening. I tried firing the function from the outside.
window.setInterval(carouselView.slide, 5000);
That works. BUT, I can't access the instance of the view anymore. If i do a console.log(this); it gives me Window. I guess this is because the function is being called from Window and not from the view instance.
Any help would be much appreciated.

I realize this is an old question by now but you can do this without binding.
(function(view) {
window.setInterval(function() { view.slide(); }, 5000);
})(this);
If you stick that in your view's initialize it should work. What it does is basically creating a closure so that you still have access to the view inside your setInterval block.
I do agree that a timer event like "timer 5000" : "slide" would have been a nice feature for Backbone as I googled my way here looking for something exactly like that.

You have to bind the function to the context. I'm not 100% sure but I think this should work:
slide: _.bind(function(){ ... }, this)
See Backbone FAQ

Related

How to add an event listener to a Kendo UI view?

$('#my-view').on('show', showHandler)
Doesn't work. Using data-show is not an option either because the code that sets/unsets the event is within class that is instantiated later. Also creating the view programatically and passing in the event handler doesn't work because I need to set the event on/off at different times.
Is this not possible with kendoUI? If not, why? This seems like such an incredibly obvious feature to relay those events to the element themselves similar to what is possible with jquery ui widgets.
This works:
var view = $('#my-view');
var widget = kendo.widgetInstance(view);
widget.bind('show', showHandler);
Better answer, just delegate the events yourself so the code in the question actually works:
<div data-role="view" ... data-show="onShow">...</div>
and
function onShow () {
this.element.trigger('show');
}
Now the it works :). The problem I still has was that 'show' isn't triggered when a view is first shown if it is the first view shown. Er, so yeah I had to add some extra code for that too like this:
if ($('#my-view').is(':visible')) {
$('#my-view').trigger('show');
}
Lame but it works.

The view area of ckEditor sometimes shows empty at the start

I am using the following directive to create a ckEditor view. There are other lines to the directive to save the data but these are not included as saving always works for me.
app.directive('ckEditor', [function () {
return {
require: '?ngModel',
link: function ($scope, elm, attr, ngModel) {
var ck = ck = CKEDITOR.replace(elm[0]);
ngModel.$render = function (value) {
ck.setData(ngModel.$modelValue);
setTimeout(function () {
ck.setData(ngModel.$modelValue);
}, 1000);
}; }
};
}])
The window appears but almost always the first time around it is empty. Then after clicking the [SOURCE] button to show the source and clicking it again the window is populated with data.
I'm very sure that the ck.setData works as I tried a ck.getData and then logged the output to the console. However it seems like ck.setData does not make the data visible at the start.
Is there some way to force the view window contents to appear?
You can call render on the model at any time and it will simply do whatever you've told it to do. In your case, calling ngModel.$render() will grab the $modelValue and pass it to ck.setData(). Angular will automatically call $render whenever it needs to during its digest cycle (i.e. whenever it notices that the model has been updated). However, I have noticed that there are times when Angular doesn't update properly, especially in instances where the $modelValue is set prior to the directive being compiled.
So, you can simply call ngModel.$render() when your modal object is set. The only problem with that is you have to have access to the ngModel object to do that, which you don't have in your controller. My suggestion would be to do the following:
In your controller:
$scope.editRow = function (row, entityType) {
$scope.modal.data = row;
$scope.modal.visible = true;
...
...
// trigger event after $scope.modal is set
$scope.$emit('modalObjectSet', $scope.modal); //passing $scope.modal is optional
}
In your directive:
ngModel.$render = function (value) {
ck.setData(ngModel.$modelValue);
};
scope.$on('modalObjectSet', function(e, modalData){
// force a call to render
ngModel.$render();
});
Its not a particularly clean solution, but it should allow you to call $render whenever you need to. I hope that helps.
UPDATE: (after your update)
I wasn't aware that your controllers were nested. This can get really icky in Angular, but I'll try to provide a few possible solutions (given that I'm not able to see all your code and project layout). Scope events (as noted here) are specific to the nesting of the scope and only emit events to child scopes. Because of that, I would suggest trying one of the three following solutions (listed in order of my personal preference):
1) Reorganize your code to have a cleaner layout (less nesting of controllers) so that your scopes are direct decendants (rather than sibling controllers).
2) I'm going to assume that 1) wasn't possible. Next I would try to use the $scope.$broadcast() function. The specs for that are listed here as well. The difference between $emit and $broadcast is that $emit only sends event to child $scopes, while $broadcast will send events to both parent and child scopes.
3) Forget using $scope events in angular and just use generic javascript events (using a framework such as jQuery or even just roll your own as in the example here)
There's a fairly simple answer to the question. I checked the DOM and found out the data was getting loaded in fact all of the time. However it was not displaying in the Chrome browser. So the problem is more of a display issue with ckEditor. Strange solution seems to be to do a resize of the ckEditor window which then makes the text visible.
This is a strange issue with ckeditor when your ckeditor is hidden by default. Trying to show the editor has a 30% chance of the editor being uneditable and the editor data is cleared. If you are trying to hide/show your editor, use a css trick like position:absolute;left-9999px; to hide the editor and just return it back by css. This way, the ckeditor is not being removed in the DOM but is just positioned elsewhere.
Use this java script code that is very simple and effective.Note editor1 is my textarea id
<script>
$(function () {
CKEDITOR.timestamp= new Date();
CKEDITOR.replace('editor1');
});
</script>
Second way In controller ,when your query is fetch data from database then use th
is code after .success(function().
$http.get(url).success(function(){
CKEDITOR.replace('editor1');
});
I know, that this thread is dead for a year, but I got the same problem and I found another (still ugly) solution to this problem:
instance.setData(html, function(){
instance.setData(html);
});

How to use Backbone.EventBinder with views

Referring to this post on Backbone.EventBinder, I am lost on how to use EventBinder with Backbone views (which is the most popular use case). Is it still recommend to add a close() method to the Backbone.View prototype and a onClose() method to the view as suggested in this post? Also where does one store the binder object, so that binder.unbindAll() can be called on close? What is the recommended way to close child views (e.g. a parent view on a collection which has child views on the associated models). A working example would be a great addition to the Backbone.EventBinder project.
Yes, you should still add a close method to your views. The EventBinder does not negate any of what that Zombies post says. Rather, it helps to automate a lot of the process by making it easier to unbind all of your events within the view.
Take a look at the Marionette.View source code for an example of how it's used:
https://github.com/marionettejs/backbone.marionette/blob/master/src/marionette.view.js#L9
https://github.com/marionettejs/backbone.marionette/blob/master/src/marionette.view.js#L16
https://github.com/marionettejs/backbone.marionette/blob/master/src/marionette.view.js#L97
If you're using Marionette, you don't need to add the close method yourself, or add the event binder yourself. That's handled for you.
If you want to add this to your own views, it's easy:
MyView = Backbone.View.extend({
initialize: function(){
// add the event binder
this.eventBinder = new Backbone.EventBinder();
// bind some stuff
this.eventBinder.bindTo(this.model, "change:foo", this.doStuff, this);
},
close: function(){
// ... other stuff
this.eventBinder.unbindAll();
}
});

Attaching a Hover Effect

I'm using this tickertype jquery plugin:
http://www.hungry-media.com/code/jQuery/tickerType/
And I'm trying to attach a hover effect to a link, the website can be found here:
http://dougmolineux.com/json/
But it's simply not working, my hover code looks like this:
$(".mylink").hover(
function () {
alert("test");
console.log("is this working?");
//$("#test").html($(this).attr("id"));
//$(this).addClass("hover");
},
function () {
//$(this).removeClass("hover");
}
);
And my link looks like this:
"home": "example glossary",<br />
When I hover over the link nothing happens, is something wrong with my code? I have the js inside A document.ready function. I think that it may have something to do with the inclusion of the tickerType plugin, but its possible something maybe wrong with me code :)
Any advice would help!
Thanks
It is because the typewriter code serializes the HTML, therefore dropping any events attached to the elements.
It works with the effect off.
You can use the live() method to bind your events and it works. This works because it doesn't directly attach events, just lets events bubble to document where thier origin is checked and if it matches the selector, the event is fired.
jsFiddle.

Bind custom event handler after ajax load

Specifically I'm looking to bind lightbox to a specific element. Normally I would just do this: $('a.lightbox').lightBox(); but that isn't working since I'm doing some loading with AJAX. Looking at the jQuery API I found .bind() and .live() but I'm not getting anything when I do $('a.lightbox').bind('lightBox') after the AJAX .load() call.
What am I missing?
You need to add a callback function that handles that.
$("#div").load(url, {}, function(){ $('a.lightbox').lightBox(); });
Bind isn't going to help you, as the event isn't getting an event fired on it.
Another way would be to bind to an element higher up in the dom and check the target type. Such as:
$('#div').bind('click', function (event) {
target = $(event.target);
if (target.hasClass('lightbox')) {
// do stuff here
}
});
Just don't go too far up or you'll be catching way too many clicks.

Resources