I have a Backbone view for a search form. The form includes several elements, including a slider implemented in jSlider. I want to capture all changes to the form, and update the results shown accordingly.
I can capture the click events fine, but I don't know how to capture the slide event on jSlider - I know how to bind custom events in Backbone, but jSlider seems not to have a way to bind it directly.
Here's my HTML:
<form id="searchform">
<input type="text" id="city" />
<input type="text" id="type" />
<input id="price-jslider" type="slider" name="price" value="1;500" />
</form>
And here's my Backbone code:
var SearchFormView = Backbone.View.extend({
el: $('#searchForm'),
events: {
"click input": "updateResults",
// how to capture slide event on jslider?
},
updateResults: function(e) {
// do stuff
}
});
Does anyone have any ideas on how to capture this sort of event?
You can pass an onstatechange function when initializing the jQuery slider:
var SearchFormView = Backbone.View.extend({
el: $('#searchForm'),
render: function() {
var self = this;
$("#price-jslider").slider({
onstatechange: function( value ) {
self.updateResults();
}
});
},
events: {
"click input": "updateResults"
},
updateResults: function(e) {
// do stuff
}
});
from jslider page
onstatechange function(value)
Function fires while slider change state.
callback function(value)
Function fires on "mouseup" event.
when you instantiate jslider, you define those function in option
$(whatever).jslider({
onstatechange : function(v) {
//set your input value to v
$('#searchForm').trigger('click')
}
})
Related
I'm trying to add an event dynamically but the event doesn't fire. jQuery is not available.
Backbone Code
var OptimizelyTeacherClick = Backbone.View.extend({
events: {
"click button.start-class-creation" : "optimizelyEvent"
},
optimizelyEvent: function(e){
e.preventDefault();
console.log('Optimizely Event');
alert('Optimizely Event');
}
});
var optimizelyTeacherClick = new OptimizelyTeacherClick({ el: $('.start-class-creation') }).render();
HTML
<form class="start-class-creation-form" action="http://site.dev/classes/online/new?type=online&via=teach&button=page_top" method="post">
<input value="My Class" name="title" class="initialized" type="hidden">
<button type="submit" class="btn submit-btn large primary start-class-creation">Get Started</button>
</form>
The root el element for the OptimizelyTeacherClick view is the button itself. So the event key string should just be click. Events are bound on the el.
var OptimizelyTeacherClick = Backbone.View.extend({
events: {
"click": "optimizelyEvent"
},
optimizelyEvent: function(e) {
e.preventDefault();
console.log('Optimizely Event');
}
});
You could also just instantiate the view with the selector string, Backbone will fetch it with jQuery.
var optimizelyTeacherClick = new OptimizelyTeacherClick({
el: '.start-class-creation'
}).render();
That being said, I don't feel like you're going in the right direction with this design, but I don't know enough on your project to help more.
I want to capture the user input in my webpage without having an input field.
The screen is used from a mobile device that can scan for barcode and RFID.
Currently I am capturing the input using an input field.
<input id="rfidContainer"/>
<div class="footer-btn confirm td-div">
<img src="img/done.png" /> F1 - Confirm
</div>
However, the user shouldn't be able to see the data that he scans because it has no added value to see the number. So I'm wondering how can I capture the input without an input field?
Not that relevant but my current code to process the input looks like this:
views.RFIDView = Backbone.View.extend({
events: {
"click .confirm": "doConfirmScan"
},
initialize: function() {
this.template = _.template(utils.templateLoader.get('rfid'));
},
render: function(eventName) {
$(this.el).html(this.template(this.model.toJSON()));
this.$("#rfidContainer").focus();
return this;
},
doConfirmScan : function(){
var rfid= this.$("#rfidContainer").val();
//the magic..
}
});
EDIT:
I need to clearify that making the input field invisible or type 'hidden' will not allow me to focus on it so the scanner will not dump it's value anywhere. So I am probably looking for a solution without an input field. Much like capturing key events on body.
Any help would be greatly appreceated.
Just add
JS:
views.RFIDView = Backbone.View.extend({
$('#results').addClass('hide');
events: {
"click .confirm": "doConfirmScan"
},
initialize: function() {
this.template = _.template(utils.templateLoader.get('rfid'));
},
render: function(eventName) {
$(this.el).html(this.template(this.model.toJSON()));
this.$("#rfidContainer").focus();
return this;
},
doConfirmScan : function(){
var rfid= this.$("#rfidContainer").val();
//the magic..
}
});
HTML:
<div id="results">
<input id="rfidContainer"/>
</div>
<div class="footer-btn confirm td-div">
<img src="img/done.png" /> F1 - Confirm
</div>
There are lots of examples of Rx.Observable.fromEvent(element, eventName) using a jquery selection as the element to capture events from. However is it possible for Rx listen to only events from a filtered event setup with jQuery?
//Bind the event on body but only respond to events that match the filter
$('body').on('click', '.aClass div .something', function () {...});
//Bind to 'body' but only respond to events from the binding above
Rx.Observable.fromEvent(/*something here?*/);
I have come up with something effectively similar but it seems like it would be much more costly than the jquery filter.
Rx.Observable.fromEvent($('body'), 'click')
.filter(function (e) {
return $(e.target).is('.aClass div .something');
})
.subscribe(function () {...});
Is there some way I could turn the jQuery binding into an emitter and use that event stream with Rx?
What's the best approach?
see http://jsfiddle.net/ktzk1bh3/2/
HTML:
<div class="aClass">
<div>
<a class="something">Click me</a>
</div>
</div>
Javascript:
//Bind to 'body' but only respond to events from the binding above
var source = Rx.Observable.create(function(o) {
$('body').on('click', '.aClass div .something', function(ev) {
o.onNext(ev);
})
});
var sub = source.subscribe(function(ev) { console.log("click", ev) });
You can use Rx.Observable.fromEventPattern.
Rx.Observable.fromEventPattern(
function add(handler) {
$('body').on('click', '.aClass div .something', handler);
},
function remove(handler) {
$('body').off('click', '.aClass div .something', handler);
}
);
This way it will automatically remove event handler on unsubscribe from observable subscription.
<div class='radios'>
<input type='radio' name='r' value='PM'>PM
<input type='radio' name='r' value='PCE'>PCE
<input type='radio' name='r' value='PCS'>PCS
</div>
<textarea class='textarea'>
</textarea>
Rx.Observable.fromEvent(document.querySelector('.radios'),'click')
.subscribe((e)=>console.log(e.target.value));
Need a little help with knockoutjs and binding a keypress event. I'm trying to hook up knockout so that I pick up on the enter keypress from within a text box. So I can perform the same action as clicking a button. Its a little tricky to explain but hopefully this JsFiddle will demonstrate what I'm trying to achieve.
http://jsfiddle.net/nbnML/8/
The problem I have is that observable value is not getting updated and I think its something to do with an observable not being updated until focus moves away from the textbox?
Any solutions to this problem.
Thanks!
One option is to use the valueUpdate additional binding to force an update on each keypress. For example, you would do:
<input type="text" data-bind="value: InputValue, valueUpdate: 'afterkeydown', event: { keypress: RunSomethingKey }" />
If that is not what you are after, then really you would want to fire the element's change event in your handler. For example with jQuery, you would do something like: $(event.target).change();.
It would be better though to move this into a custom binding. Maybe something like (probably should check if the result of valueAccessor() is a function):
ko.bindingHandlers.enterKey = {
init: function(element, valueAccessor, allBindings, vm) {
ko.utils.registerEventHandler(element, "keyup", function(event) {
if (event.keyCode === 13) {
ko.utils.triggerEvent(element, "change");
valueAccessor().call(vm, vm); //set "this" to the data and also pass it as first arg, in case function has "this" bound
}
return true;
});
}
};
Here is your sample updated: http://jsfiddle.net/rniemeyer/nbnML/9/
Don't discount submit bindings:
http://knockoutjs.com/documentation/submit-binding.html
This takes care of some IE 9/10 gotchas such as the return key not updating the observable. With this taken care of you don't need to intercept keycode 13
html:
<form data-bind="submit:RunSomething">
<input type="text" data-bind="value: InputValue" />
<input type="submit" value="test" />
<div data-bind="text: InputValue" />
</form>
code:
var ViewModel = function () {
var self = this;
self.InputValue = ko.observable('');
self.RunSomething = function (ev) {
window.alert(self.InputValue());
}
}
ko.applyBindings(new ViewModel());
See this here:
http://jsfiddle.net/jnewcomb/uw2WX/
I am learning backbone.js and am quite new. I have a view that acts as a button:
simpleButton = Backbone.View.extend({
template: "<button class='${classes}'>${text}</button>",
el: $("body"),
events: {
"click": "onClick",
"focus": "onFocus",
"blur": "onBlur"
},
initialize: function (args) {
_.bindAll(this, 'render');
this.rendered = false;
this.text = args.text || 'button';
this.classes = args.classes || [];
this.classes.push('ui-button');
//console.debug("Wh.views.simpleButton.initialize classes ",this.classes);
if (args.autoRender === true) this.render();
},
render: function () {
//console.debug("Wh.views.simpleButton.render classes ",this.classes);
if (this.rendered === false) {
$.tmpl(
this.template, {
classes: this.classes.join(' '),
text: this.text
}
).appendTo(this.el);
this.rendered = true;
}
},
//event handlers
onClick: function (ev) {
console.debug(this);
alert("click on ", ev, this);
},
onFocus: function (ev) {
////console.debug(ev);
},
onBlur: function (ev) {
}
});
My problem is that if I create two buttons, and click just one of them, I get the alert box two times, and the debug showing me "this" shows the first button first, and the second button next.
Am I missing something?
The events you define are bound to the "el" property of your view. In your case it is "body" so when you fire up click with 2 simpleButton views instantiated, you have 2 of them listening for the same event.
Each view you instantiate should represent one and only one DOM element defined by the el property. So if you want to create a button view (not sure this is 'best practice' in a real program) you could have :
SimpleButton = Backbone.View.extend({
template : "<button class='${classes}'>${text}</button>",
tagName : "div", // defines the html tag that will wrap your template
className: ".buttonbox",
...
});
mybtn = new SimpleButton();
mybtn.render().appendTo('body')
That way your click event will only concern the one div.buttonbox inside of which your button lives.
Notice : Backbone idea of the render function is creating an html string you'll use afterwards to append prepend or whatever in the DOM. That way if you create many you can do it so you only refresh the DOM once (refreshing the DOM is expensive)...
Use this in your View .it will unbind the click events
initialize : function() {
$(this.el).unbind("click");
}
Just a thought that creating a Backbone.View for each and every button in your app could be a performance overkill and you can't leverage the "delegate" feature in jQuery. I'd instead create a Backbone.View for the parent element of those buttons instead.
Of course, if you have a few special buttons with complicated logic then they probably do deserve their own View classes. :)
Give your buttons unique ids, for example <button id="button1"> and <button id="button2">, then in your events hash, you need to specify the click event and the id of the button you want to handle that event for, e.g:
events : {
"click #button1" : "onClick",
"click #button2" : "doSomethingElse"
}
Now this will call onClick() only when you click on the button with id=button1 and call doSomethingElse() when you click on the button with id=button2