Define attach-point programmatically - javascript

I would like to define custom widget, create a Dijit/form/Button inside and add attach point to it. But for some reason the attach-point remains invisible..
postCreate: function() {
require(["dijit/form/Button", "dojo/dom", "dojo/domReady!"], function(Button, dom){
// Create a button programmatically:
var myButton = new Button({
label: "Click me!",
"data-dojo-attach-point": "myButton"
}, "progButtonNode").startup();
});
console.debug(this.myButton); // returns undefined
}

technically you can do it. But dojo indexes all the attach-points on parse. so if you are going to add a button dynamically then you'll have to parse the dom too.

Related

How to detect the changes from textarea by dojo

require(["dijit/form/Button", "dojo/dom", "dojo/domReady!"], function(Button, dom){
// Create a button programmatically:
var myButton = new Button({
disabled:true,
label: "Click me!",
onClick: function(){
// Do something:
dom.byId("result1").innerHTML += "Thank you! ";
}
}, "progButtonNode").startup();
});
require(["dijit/form/Textarea","dijit/registry","dojo/dom" ,"dojo/on","dojo/domReady!"], function(Textarea,registry,dom,on){
var textarea = new Textarea({
name: "myarea",
value: "This is the text area...\n\n\n\n\n\n",
style: "width:200px;"
}, "myarea").startup();
//disalbe the button...
//registry.byId("progButtonNode").set("disabled",true);
//test
dom.byId("result1").innerHTML += "Good!";
//add onchange event...
//var button = registry.byId("progButtonNode");
alert('hi');
on(textarea,"change",function(){
alert('3');
registry.byId("progButtonNode").set("disabled",false);
});
});
The above is my code.
My requirement is detect the changes once it was made from textarea, and then set the button enable. (the button was disable by default)
I am getting error:
Uncaught TypeError: Cannot read property 'on' of undefined
Thanks a lot!
To detect changes on widget Textarea, use onChange when initializing it.
Use registry.byId() to get you Button widged ans set is property disabled to false using method .set();
Working example: https://jsfiddle.net/41epfsdd/
Please note I have used intermediateChanges: true this allow onChange to fire on each keystroke which changes value within the widget Textarea.
If you omit it or use intermediateChanges: false instead, onChange event will only fires when the field is blurred.
require(["dijit/form/Button", "dijit/form/Textarea", "dijit/registry", "dojo/dom", "dojo/on", "dojo/domReady!"], function(Button, Textarea, registry, dom, on) {
var myButton = new Button({
disabled: true,
label: "Click me!"
}, "progButtonNode").startup();
var textarea = new Textarea({
name: "myarea",
value: "This is the text area...\n\n\n\n\n\n",
intermediateChanges: true,
onChange: function() {
var progButtonNode = registry.byId('progButtonNode');
progButtonNode.set('disabled', false);
}
}, "myarea").startup();
});
Edit:
Regarding your comment on how to apply an event handler on an already generate Textarea widget. You can use dojo/on example:
require(["dojo/on"], function(on){
on(target, "event", function(e){
// handle the event
});
});
Example based on your comment:
on(this.lastCommentTextArea, 'change', function(event){
// handle the event
})

Avoid clicking twice to begin editing boolean (checkbox) cell in Backgrid

We are using Backgrid and have discovered that to begin editing a "boolean" (checkbox) cell in Backgrid, you must click twice: the first click is ignored and does not toggle the state of the checkbox. Ideally we would get to the root of what is causing this behavior (e.g. is preventDefault being called) and solve it there, but I at first I tried a different approach with the following extension of BooleanCell's enterEditMode method which seemed like a logical place since it was upon entering edit mode that the checkbox click was being ignored.
Problem is my attempt also toggles the state of the previously edited checkbox. Here is the code.
var BooleanCell = Backgrid.BooleanCell.extend({
/*
* see https://github.com/wyuenho/backgrid/issues/557
*/
enterEditMode: function () {
Backgrid.BooleanCell.prototype.enterEditMode.apply(this, arguments);
var checkbox = this.$('input');
checkbox.prop('checked', !checkbox.prop('checked'));
}
});
The following seems to work:
var BooleanCell = Backgrid.BooleanCell.extend({
editor: Backgrid.BooleanCellEditor.extend({
render: function () {
var model = this.model;
var columnName = this.column.get("name");
var val = this.formatter.fromRaw(model.get(columnName), model);
/*
* Toggle checked property since a click is what triggered enterEditMode
*/
this.$el.prop("checked", !val);
model.set(columnName, !val);
return this;
}
})
});
This is because the render method gets called by Backgrid.BooleanCell's enterEditMode method on click, and said method destroys and re-creates the checkbox as follows but in so doing loses the checked state (after the click) of the original "non-edit-mode" checkbox
this.$el.empty();
this.$el.append(this.currentEditor.$el);
this.currentEditor.render();
A simpler approach:
var OneClickBooleanCell = Backgrid.BooleanCell.extend({
events: {
'change input': function(e) {
this.model.set(this.column.get('name'), e.target.checked);
},
},
});
This bypasses the CellEditor mechanism entirely and just reacts to the input event on the checkbox by updating the model.

Backbone Event Map Doesn't Recognize Classes

Stack.
I'm using Backbone's event map in my View.
JS:
events: {
"click .edit-info-button": "pullEdits"
},
pullEdits: function(e){
// Get the value of the button clicked
e.preventDefault();
$(".edit-info-button").click(function(){parseEdits(this.value);});
}
HTML:
<button class="button edit-info-button" value="edit address">EDIT</button>
When edit-info-button is a class, the event listener does not work. pullEdits() never fires.
When I change edit-info-button into an id ("click #edit-info-button", "button id='edit-info-button', etc.) pullEdit() and all functions after it run successfully.
The issue is, the page I'm working on needs multiple edit buttons and I'd like to give them the same class and pull the value instead of giving them all unique ids.
Am I missing something? Thanks.
Try this instead.
...
events: {
"click .edit-info-button": "pullEdits"
},
pullEdits: function(e){
var val = $(e.target).attr('value')
return parseEdits( val );
}
...

Backbone: Toggle methods on some event

I want one button to toggle two methods in backbone but I'm having issues. I'm pretty much new to JS in general.
If you click on a button:
I want to show a hidden div
change the text of the button clicked
Then, if you click the button again (which has the new text and the hidden div is shown)
Change the text
Hide the shown div
The second method of .hide is not being fired? I'm wondering if this is because .hide is not in the DOM initially, because it's being added on the show method. Just a guess and maybe there's a better way to toggle methods on one class?
Here's my JS
'touchstart .share-btn' : 'show',
'touchstart .hide' : 'hide'
'show' : function (e) {
var view = this;
$(e.currentTarget).closest('.tile').find('.share-tools').fadeIn('fast');
$(e.currentTarget).addClass('hide');
if ($(e.currentTarget).hasClass('hide')){
$(e.currentTarget).find('.button-copy').closest('.button-copy').html('close');
}
},
'hide' : function (e) {
var view = this;
if($(e.currentTarget).hasClass('hide')) {
$('.share-tools').fadeOut('fast');
$(e.currentTarget).removeClass('hide');
$(e.currentTarget).find('.button-copy').closest('.button-copy').html('share');
}
},
Maybe reworking your code a bit will help. I've created a working jsfiddle based on what I think you're trying to accomplish.
Here is the relevant view code:
var View = Backbone.View.extend({
...
// Make it clear that these are the same element.
// Ensure they will not both fire by making them exclusive.
events: {
'mousedown .share-btn:not(.hide)' : 'show',
'mousedown .share-btn.hide' : 'hide'
},
'show' : function (e) {
console.log('show');
var $e = $(e.currentTarget);
$e.closest('.tile').find('.share-tools').fadeIn('fast', function () {
$e.addClass('hide');
});
$e.find('.button-copy').closest('.button-copy').html('close');
},
'hide' : function (e) {
console.log('hide');
var $e = $(e.currentTarget);
$e.closest('.tile').find('.share-tools').fadeOut('fast', function () {
$e.removeClass('hide');
});
$e.find('.button-copy').closest('.button-copy').html('share');
}
});
You can find the working jsfiddle here: http://jsfiddle.net/somethingkindawierd/7rfs9/
Try to return false in your event listener to prevent call both methods on first click.

backbone.js: different output for same process

Working through the setElement part of Addy Osmani's backbone.js tutorial.
He presents this example:
// We create two DOM elements representing buttons
// which could easily be containers or something else
var button1 = $('<button></button>');
var button2 = $('<button></button>');
// Define a new view
var View = Backbone.View.extend({
events: {
click: function(e) {
console.log(view.el === e.target);
}
}
});
// Create a new instance of the view, applying it
// to button1
var view = new View({el: button1});
// Apply the view to button2 using setElement
view.setElement(button2);
button1.trigger('click');
button2.trigger('click');
However, he doesn't explain why there is different output for button1.trigger('click'); vs. button2.trigger('click'); -- possibly a dumb question, and I know that these are different ways of attaching the view to the button elements, but why does button2.trigger('click'); also return true?
button1.trigger('click'); shouldn't produce any output at all from that code.
setElement is fairly simple:
setElement view.setElement(element)
If you'd like to apply a Backbone view to a different DOM element, use setElement, which will also create the cached $el reference and move the view's delegated events from the old element to the new one.
So view.setElement(e) does four things:
Unbinds the view's events from view.el.
Sets view.el = e.
Sets view.$el = Backbone.$(e).
Binds the view's events to the new view.el.
The result is that nothing will be left listening to events from button1 and view will be listening to events from button2.
A more thorough example might help so let us attach some more click event handlers:
var button1 = $('<button id="button1"></button>').click(function() {
console.log('button1 jQuery', this);
});
var button2 = $('<button id="button2"></button>').click(function() {
console.log('button2 jQuery', this);
});
var View = Backbone.View.extend({
events: {
click: function(e) {
console.log('Backbone ', view.el, view.el === e.target);
}
}
});
var view = new View({el: button1});
view.setElement(button2);
button1.trigger('click');
button2.trigger('click');
Demo: http://jsfiddle.net/ambiguous/S7A9z/
That should give you something like this in the console:
button1 jQuery <button id=​"button1">​</button>​
button2 jQuery <button id=​"button2">​</button>​
Backbone <button id=​"button2">​</button>​ true
Both raw jQuery event handlers will be triggered as expected but we'll only get the button2 event through Backbone because the setElement call happened before the trigger calls.
So why is view.el === e.target true? Well, you're clicking on button2 so e.target will be button2 and the view.setElement(button2) call replaces view.el so this.el inside the Backbone click handler will also be button2.

Categories

Resources