Click event not firing with Backbone & jQuery - backbone.js

I'm using Backbone in an app & running into an situation where events are not firing.
My View, maps to a dialog interface containing several controls (a text area, a couple radio buttons, etc.) and a save button. I'm defining the following events:
events: {
'input': 'onchange',
'change': 'onchange',
'click .save': 'save',
'click .cancel': 'cancel',
},
Each time any form element in the dialog changes, I fire onchange, which performs some validation and either enables or disables the save button.
In the 'normal' flow, everything works properly. I fill out the textarea, click an option on the radio button, and then click save. My work is saved properly.
In an alternative flow, I try to click save while my cursor is still in the text area, and nothing happens. Then, if I click on the save button a second time, the form saves correctly. I've tried setting a breakpoint at the very beginning of the save method, and confirmed that it is not called during the first button click, and is then called correctly with the second button click.
I've tried to make a minimal example as a jsFiddle to demonstrate the issue, but I can't isolate the buggy behavior.
What could be preventing the click event and save function the first time I click the button? Do you have any tips or recommendations for helping debug an issue like this?
Update: Using a Javascript Profiler
I went back and used a profiler to dig in on what's happening. Here was my process:
Set up page for test, with everything filled in except the primary textarea
Start profiler
Type a letter into the textarea and wait for onchange handlers to fire, which is evidenced by Save button becoming enabled
Wait several seconds
Click Save - nothing happens
Stop profiler
And here's my profile:
What's interesting is that there's a clear flurry of activity when the onchange handlers fire, seen as a visible spike in the flame chart. However, when I click save the first time, there is no javascript execution captured at all! Very curious...

Related

In an Angular application, how to integrate the Ace editor with a toolbar?

I wish to write an Angular application which integrates the Ace editor with a toolbar for saving + undo/redo. I've created a basic plunk for working out this app.
As you should be able to tell from the plunk there is a 'toolbar' directive responsible for rendering the toolbar (with three buttons: Save, Undo and Redo) and an 'ace' directive responsible for rendering the Ace editor. Both directives reside in 'directives.coffee'.
The toolbar should behave the way you would expect from a text editor toolbar, i.e.:
The save button should be enabled iff the document has changed since it was last saved
When clicking the save button, the document state should change to pristine (i.e., not dirty) and the save button should go back to the disabled state
The undo button should be enabled iff there is at least one operation that can be undone
When clicking the undo button, the editor should be told to undo the last operation and the undo button should be updated as per the above point
The redo button should be enabled iff there is at least one operation that can be redone
When clicking the redo button, the editor should be told to redo the last operation and the redo button should be updated as per the above point
So my question is, how can I devise an Angular binding between the Ace editor and the application toolbar so that the above specification is met?
I am not sure what do you need to do on angular side, but ace provides methods for all of this
var undoManager = editor.session.getUndoManager()
undoManager.isClean()
undoManager.markClean()
undoManager.hasUndo()
undoManager.hasRedo()
Note that isClean is based on undo stack not on document value, so writing and deleting a letter will enable save button even though value isn't changed.
Also it is better to use editor.on("input", function(){}) instead of 'change' since input event is fired asynchronously.

Drag finger from one button to another - want to un-trigger old button and trigger new button - Windows Store

I am working on a windows store application and I want to be able to drag between buttons so that the originally pressed button becomes deactivated and the newly "dragged onto" button becomes activated but I can't seem to get this to work.
I have 2 Buttons inside a StackPanel and the events I have on them are:
PointerPressed
PointerEntered
PointerReleased
PointerExited
PointerCanceled
PointerCaptureLost
PointerPressed and PointerEntered share the same event handler and the rest (the "deactivation" events) share the same event handler.
If I press one button my "activated" event handler is triggered and if I drag off it my "deactivated" event handler is triggered but if I then drag onto the second button the "activated" event handler isn't triggered again.
Strangely, if I start by dragging from off the StackPanel onto one of the buttons the "activated" event handler is triggered. I assume that it is something to do with the internal pointer management stuff but can't seem to find a workaround.
Does anyone know why this is happening and how I can get it to work how I want?
Thanks for your time.
Edit
Okay I've been researching some stuff and I've come across CapturePointer() and ReleasePointerCapture() but this seems to be broken - If I capture the pointer, when I take my finger off the screen, PointerReleased doesn't even get hit.
I've also realized why the "dragging from off the SP onto one of the buttons causes it to 'activate'" - this is because when a button is pressed it doesn't route its event but fires a Click event - meaning the same pointer cannot fire a PointerEntered event of another button, but if it starts outside a Button it will trigger PointerEntered.
This doesn't get me much further but it is a little extra info :)
The concept of Button is a bit unique in regard to mouse capture and how dragging away from it happens. In your scenario I'm not sure if the event model around Button will work correctly for you. On Button, when a pointer is depressed (mouse) it has capture until it is released. This is not the same for touch where a press and drag away is different because in touch there isn't any explicit capture unless you create it.
So what you are hitting is going to be a slight conflict between mouse/touch interactions anyway using Button -- using some other UI element (not sure if you have a styled button) should get you what you want.

Autosaving on blur + "Undo" button

I am writing directive, that will act like this:
allow editing of some text (using content editable)
on loosing focus it should save its value to model (lately watched and saved to DB)
there should be button "Undo" which revert changes.
My implementation is: http://plnkr.co/edit/DsWEYQV4j51i4GO6KjSe?p=preview
The only problem I have is when I press "undo" button, DIV lose focus (so 'focusout' event is fired) and value is saved in model, so "undo" button can't revert its value.
( I click "undo" -> focusout event (autosave) -> click event (??? can't revert) )
Possible workarounds I see:
set timeout on blur and cancel it if 'undo' button was pressed. But it is ugly as user can enter value and navigate to other part of app, so timeouted saving won't run any $watch listeners.
save value on focusin and restore it when 'undo' button is saved. This cause another problem: $watch listeners would run with changed value and then run again with previous value (so there would be 2 writes to DB instead of one)
Do anybody have solution for such behaviour (autosave on blur + undobutton)?
How about using underscore.js debounce function or similar to cause a delay on autosave, where it will check for a undo flag and cancel? Not sure what the $watch listeners are doing. Of course it will still not work if the user completely goes out of the app or refreshes the page etc.

Backbone.ModelBinder: why do I have to hit submit twice?

I am using Backbone and Backbone.ModelBinder.
I have a bunch of text fields that are bound via BackboneModelBinder. Everything works as expected however when I make a change to a text field and I don't unfocus the field first (click off the input field) before hitting the SAVE button, I have to hit the Save button twice -- once to unfocus the fields, and then a second time to actually fire the save button handler (which should have fired the first time)
(Save is a standard html button with a backbone event bound to it).
Does anyone have any knowledge of why this might be?
I hope this made sense :|
Thanks for any help or direction
-Kirk
That's because ModelBinder by default set the new value to the model's attributes on "blur" or "change" events (it dependes on the input's type). You can modify this behavior by changing the source code, adding keyup as binding event in those two methods:
_bindViewToModel:function () {
$(this._rootEl).delegate('', 'change keyup', this._onElChanged);
// The change event doesn't work properly for contenteditable elements - but blur does
$(this._rootEl).delegate('[contenteditable]', 'blur keyup', this._onElChanged);
},
_unbindViewToModel: function(){
if(this._rootEl){
$(this._rootEl).undelegate('', 'change keyup', this._onElChanged);
$(this._rootEl).undelegate('[contenteditable]', 'blur keyup', this._onElChanged);
}
},

Silverlight click event registered a second time before first event completed

I have a button which launches a "modal dialog" - it just creates a transparent grid covering everything, with the "dialog" created on top of that.
However I have a strange issue - if I double/triple click the button really fast (or add some delay in the event code), the button click event is executed multiple times, creating multiple overlapping modal dialogs. If the first action in my event is to disable the button (IsEnabled=false) it seems to prevent this.
My guess is that Silverlight is being multithreaded with input - it is not only recording the second click in another thread (while the button's click event is running), but it is jumping the gun by evaluating which control should be the target before the previous event has finished executing. Even though that event alters what control is at those mouse coordinates, it doesn't matter.
Does anyone know anything about this behavoir, or a way around it? If I have something like a save window, where the user clicks a save button, a blocking grid ("Saving...") is placed up while it saves, and then the whole "window" is closed, I'd like to avoid the user being able to queue up multiple save event clicks (this could lead to unpredictable program behavoir).
If you've ever worked with WinForms or WPF, this is expected behavior. Your button is broadcasting its Click event until your modal dialog covers it up. Unfortunately, there is some amount of time between your first click and when the modal dialog covers the button which allows multiple clicks to the original button.
You have two solution choices:
Disable the button after the first click and then re-enable after the modal dialog returns. You've already mentioned that this works.
Write code in the Event Handler of the button to determine if a modal dialog is already being displayed. This way, you're putting the responsibility in one location rather than splitting it up (disabling and re-enabling the button). This would be my preferred solution.
I think what you're seeing is the behaviour of Silverlight's routed events.
You can set the Handled property of the event arguments to true to prevent the event from bubbling.

Resources