Call back from styled radio buttons - javascript

I am using the jQuery plugin radiosToSlider (http://rubentd.com/radios-to-slider/) and need to make sure that all radio button groups are checked and to give an alert when they are
I can do this if they are just radio buttons by checking the length but because the plugin changes the input buttons I am having difficulties
My fiddle is
http://jsfiddle.net/yFaAj/270/
$(document).ready(function () {
$(".radios").radiosToSlider();
});
$(":radio").change(function () {
var names = {};
$(':radio').each(function () {
names[$(this).attr('name')] = true;
});
var count = 0;
$.each(names, function () {
count++;
});
if ($(':radio:checked').length === count) {
alert("all answered");
}
}).change();
thanks

The problem isn't that the plugin changes your structure (although it does add some ins elements, which I don't agree with), it's that the plugin doesn't fire a change event for the converted radio controls, and setting the checked property interactively doesn't appear to do so either.
Since the plugin author doesn't publish an API for this use case, it's hard to know whether this is by design or oversight, but the source code definitely doesn't fire the event when the slider is clicked:
this.bearer.find('.slider-level').click( function(){
var radioId = $(this).attr('data-radio');
slider.bearer.find('#' + radioId).prop('checked', true);
slider.setSlider();
});
Your options, as I see them:
Contact the API author and ask for a bug fix, or the intended way to support this case
Downside: Time: dependent on the author to respond
Attach your "check" function to the click event of the .slider-level class, as the API does.
Downside: Brittle: future versions of the plugin may attach the behavior to different selectors
Attach your function to the click event of your radio group, and catch click events on the bubble
Downside: Inefficient: It will check for every click in the radio control
Here's a sample implementation of option 3. DEMO.
$(document).ready(function () {
$(".radios").radiosToSlider();
});
var makeIsRadioGroupChecked = function(selector) {
var $radioGroup = $(selector);
return function isRadioGroupChecked() {
return $radioGroup.find(':checked').length > 0;
};
};
var isOptionsChecked = makeIsRadioGroupChecked('#optionsRadioGroup');
var isSizeChecked = makeIsRadioGroupChecked('#sizeRadioGroup');
var areAllGroupsChecked = function() {
return isOptionsChecked() && isSizeChecked();
};
var alertIfAllGroupsChecked = function() {
if (areAllGroupsChecked()) {
alert("all answered");
}
};
$('.radios').on('click', alertIfAllGroupsChecked);

Related

Dynamically created buttons won't fire when clicked

I'm creating buttons based on what a user enters into an input box. However, the function i have linked to the dynamically created buttons won't fire when pressed.
function btnCreate() {
num++;
userBtn = $("<button>")
userBtn
.addClass("btn search-term-btn dynamicElement")
.appendTo($(".btn-holder"))
.text(topics)
.attr("data-name", topics);
usedTopics.push(topics + num);
topics = [];
console.log(num);
};
$(".search-term-btn").on("click", ".dynamicElement", function () {
// takes the name of the button
searchValue = $(".search-term").attr("data-name");
console.log(searchValue);
})
The class is correct, ive checked with the inspector. I just can't seem to figure out why it's unresponsive
Create the click event on DOM.
$(document).on("click", ".search-term-btn .dynamicElement", function () {
console.log(this)
});
while you are creating the buttons, you can add the onclick function there..
like userBtn = $("<button onlcikc="somefunction(this)">")
OR
you can use on function which is
$('body').on( "click",".dynamicElement", function() {
//your code
});

Kendo toolbar button not firing click event after being enabled

This is my logic, here I am trying to disable the save changes button and prevent click event on it if the user enters a duplicate value and enable it again if the user changes the values but after enabling it the update / save event does not occur am I doing something wrong? This is my code
function OnChange(data) {
//data.preventDefault();
$(".k-grid-save-changes")
.attr("role", "button")
.removeClass("k-state-disabled")
//.addClass("k-grid-save-changes")
.click(function () {
return true;
});
//console.log("data", data.items["0"].ProviderTypeName);
var name = data.items["0"].ProviderTypeName;
var Id = data.items["0"].Id;
var grid = $("#grid").data("kendoGrid");
//console.log("Grid ", grid);
grid.tbody.find('>tr').each(
function () {
$(this).css('background', 'white');
var dataItem = grid.dataItem(this);
//console.log(dataItem.ProviderTypeName)
if (dataItem.ProviderTypeName == name && dataItem.Id != Id) {
$(this).css('background', 'red');
$(".k-grid-save-changes")
//.removeClass("k-grid-save-changes")
.addClass("k-state-disabled")
//.removeAttr("role")
.click(function () {
return false;
});
}
});
}
This is where is call the on change event
.Events(events => events.RequestStart("OnRequestStart").Change("OnChange").RequestEnd("OnRequestEnd").Error("onError"))
If I remove the "return false;" it is working as expected but this allows duplicated values to be saved. So I have used this.
If I understand correctly in your code you do exactly what you mention as a problem. At every change you disable the save functionality with the return false. You don't enable it again at any point.
If you add an event handler to the button then you have to undo it at a later point. Since though I don't believe that the validation should occur at the change event but at the button click I would suggest to use the grid Save event where you could iterate dataSource.data() of your grid (much better) do your check and if anything happens return false.
One other way to go since you probably want the css effect with the background is to keep your code and discard the click event. Just set a flag that you could use in the save event. Something like this:
if(// your control){
$(this).css('background', 'red');
duplicatedValue = true;
}else{
.removeClass("k-grid-save-changes");
duplicatedValue = false;
}
And in the save event
function onSave(){
if(duplicatedValue){
return false;
}
}

Click events from two scripts on same element?

Edit: I think I got the solution! I want to try and fix this myself before I ask for further help = )
First script inhibits the second one from functioning as the click event from the first one overides the second one. Because the second one does not function it is impossible to open the drop down menu to select a list item to trigger the first scripts click.
What I tried was replacing all return false statements with event.stopPropagation(). Didnt work however. Tried re-ordering my scripts but that failed as well. I was thinking of making my second script target another parent div but that didnt work either.I also tried event.stopImmediatePropagation() and .bind methods.
Any idea?
First script that makes the drop down function. Contains click event.
function DropDown(el) {
this.f = el;
this.placeholder = this.f.children('span');
this.opts = this.f.find('ul.dropdown > li');
this.val = '';
this.index = -1;
this.initEvents();
}
DropDown.prototype = {
initEvents : function() {
var obj = this;
obj.f.on('click', function(event){
$(this).toggleClass('active');
return false;
});
obj.opts.on('click',function(){
var opt = $(this);
obj.val = opt.text();
obj.index = opt.index();
obj.placeholder.text(obj.val);
});
},
getValue : function() {
return this.val;
},
getIndex : function() {
return this.index;
}
}
$(function() {
var f = new DropDown( $('#f') );
$(document).click(function() {
// all dropdowns
$('.filter-buttons').removeClass('active');
});
});
Second script that does the filtering, also contains click event:
jQuery(document).ready(function(e) {
var t = $(".filter-container");
t.imagesLoaded(function() {
t.isotope({
itemSelector: "figure",
filter: "*",
resizable: false,
animationEngine: "jquery"
})
});
$(".filter-buttons a").click(function(evt) {
var n = $(this).parents(".filter-buttons");
n.find(".selected").removeClass("selected");
$(this).addClass("selected");
var r = $(this).attr("data-filter");
t.isotope({
filter: r
});
evt.preventDefault();
});
$(window).resize(function() {
var n = $(window).width();
t.isotope("reLayout")
}).trigger("resize")
});
html structure
<div id="f" class="filter-buttons" tabindex="1">
<span>Choose Genre</span>
<ul class="dropdown">
<li>All</li>
<li>Electronic</li>
<li>Popular</a></li>
</ul>
</div>
This doesn't really solve your problem but I was bored while drinking my coffee and felt like helping you write your dropdown plugin a little nicer
My comments below are inline with code. For uninterrupted code, see DropDown complete paste.
We start with your standard jQuery wrapper (function($){ ... })(jQuery)
(function($) {
// dropdown constructor
function DropDown($elem) {
First we'll make some private vars to store information. By using this.foo = ... we expose things (probably) unnecessarily. If you need access to these vars, you can always create functions to read them. This is much better encapsulation imo.
// private vars
var $placeholder = $elem.children("span");
var $opts = $elem.find("ul.dropdown > li")
var value = "";
var index = -1;
Now we'll define our event listeners and functions those event listeners might depend on. What's nice here is that these functions don't have to access everything via this.* or as you were writing obj.f.* etc.
// private functions
function onParentClick(event) {
$elem.toggleClass("active");
event.preventDefault();
}
function onChildClick(event) {
setValue($(this));
event.preventDefault();
}
function setValue($opt) {
value = $opt.text();
index = $opt.index();
$placeholder.text(value);
}
Here's some property descriptors to read the index and value
// properties for reading .index and .value
Object.defineProperty(this, "value", {
get: function() { return value; }
});
Object.defineProperty(this, "index", {
get: function() { return index; }
});
Lastly, let's track each instance of DropDown in an array so that the user doesn't have to define a special listener to deactivate each
// track each instance of
DropDown._instances.push(this);
}
This is the array we'll use to track instances
// store all instances in array
DropDown._instances = [];
This event listener deactivate each "registered" instance of DropDown
// deactivate all
DropDown.deactiveAll = function deactiveAll(event) {
$.each(DropDown._instances, function(idx, $elem) {
$elem.removeClass("active");
});
}
Here's the document listener defined right in the plugin! The user no longer has to set this up
// listener to deactiveAll dropdowns
$(document).click(DropDown.deactiveAll);
Might as well make it a jQuery plugin since everything in our DropDown constructor relies upon jQuery. This let's the user do var x = $("foo").dropdown();
// jQuery plugin
$.fn.dropdown = function dropdown() {
return new DropDown($(this));
};
Close the wrapper
})(jQuery);
Now here's how you use it
$(function() {
var x = $('#f').dropdown();
// get the value
f.value;
// get the index
f.index;
});
Anyway, yeah I know this doesn't really help you with your click listeners, but I hope this is still useful information to you. Off to the Post Office now!
I think you're going to need to simplify this to figure out what's going on. There's actually not enough information to see what elements the events are being attached to here.
For argument's sake, open the console and try the following:
$(document).on('click', function() { console.log('first'); return false; });
$(document).on('click', function() { console.log('second'); return false; });
Then click in the page. You'll see that both events are triggered. It might well be that your code is actually attaching the events to different elements (you don't say anywhere). If that's the case then you need to understand how event bubbling works in the DOM.
When you trigger an event, say a click on an element, that event will fire on that element, and then on it's parent, then grandparent etc all the way to the root node at the top.
You can change this behaviour by calling functions in the event itself. evt.stopPropagation tells the event to not bubble up to the ancestor nodes. evt.preventDefault tells the browser not to carry out the default behaviour for a node (eg, moving to the page specified in the href for an A tag).
In jQuery, return false from an event handler is a shortcut for, evt.preventDefault and evt.stopPropagation. So that will stop the event dead in its tracks.
I imagine you have something like:
<div event_two_on_here>
<a event_one_on_here>
</div>
If the thing that handles event_one_on_here calls stopPropagation then event_two_on_here will never even know it has happened. Calling stopPropagation explicitly, or implicitly (return false) will kill the event before it travels to the parent node/event handler.
UPDATE: In your case the issue is that the handler on .filter-buttons a is stopping the propagation (so #f doesn't get to run its handler).
$(".filter-buttons a").click(function(evt) {
// your code here...
// Don't do this - it stops the event from bubbling up to the #f div
// return false;
// instead, you'll probably just want to prevent the browser default
// behaviour so it doesn't jump to the top of the page ('url/#')
evt.preventDefault();
});

2 anchor with one click

So here is my code
prev
prev
How do I make it both click if I click any of it ?
If I click .slider-1-prev, at the same I click .slider-2-prev
If I click .slider-2-prev, at the same I click .slider-2-prev
How to make it by javascript ?
As well as triggering the event on the other link, you need to shield against infinite repeating (e.g. with a shield variable):
var inClick = false;
$(document).ready(function {
$('.slider-1-prev').on('click', function {
if (!inClick) {
inClick = true;
$('.slider-2-prev').trigger('click');
inClick = false;
}
});
$('.slider-2-prev').on('click', function {
if (!inClick) {
inClick = true;
$('.slider-1-prev').trigger('click');
inClick = false;
}
});
})
If you want a shorter version, you can listen for both on one handler and click "the other":
var inClick = false;
$(document).ready(function {
var $sliders = $('.slider-1-prev,.slider-2-prev');
$sliders.on('click', function {
if (!inClick) {
inClick = true;
// Click the one that was not clicked (not this)
$sliders.not(this).trigger('click');
inClick = false;
}
});
})
Another option is a bit more complicated as you need to turn the handler off and then on again. Stick with this simple one for now.
The on/off approach involves disabling the handling while executing it, so that it will not trigger again until you reconnect it. The downside is you need to reference a separate function so that it can effectively reference itself:
$(document).ready(function {
var $sliders = $('.slider-1-prev,.slider-2-prev');
// Define separate named function
var clickTheOtherOne = function(){
// Disable the click
$sliders.off('click');
// Click the one that was not clicked (not this)
$sliders.not(this).trigger('click');
// Reenable the click handler
$sliders.on('click', clickTheOtherOne);
}
// Initial enabling of the handler
$sliders.on('click', clickTheOtherOne);
});
If they're going to behave the same, why not define only one function for both?
$('.slider-1-prev, .slider-2-prev').click(function(){
//... mutual code
});
I can't figure why you need to do what you ask, but try this approach:
js code:
// this will work on all classes that start with 'slider-prev'
$('*[class^="slider-prev"]').on('click',function{
// do something
});
Of course you will need to alter your htm code to:
prev
prev
this should do the trick
$(document).ready(function{
$('.slider-1-prev').on('click',function{
$('.slider-2-prev').trigger('click');
});
$('.slider-2-prev').on('click',function{
$('.slider-1-prev').trigger('click');
});
})
Try this -
$('.slider-1-prev').click(function(){
$('.slider-2-prev').trigger('click');
});
// If you need the opposite, then do -
$('.slider-2-prev').click(function(){
$('.slider-1-prev').trigger('click');
});

By JQuery, how to specify on function as onClick handler for many radio buttons?

I have a function called handleOnClickRadio(i, j); and lots of radio buttons named as id="something-radio[i][j]". All these radio buttons are in a table called "bigtable".
How could I attach the function handleOnClickRadio() to all these radio buttons? And call it correct with handleOnClickRadio(i,j).
Thanks.
I would not attach the click handler to the buttons at all. You say you have lots of them. Attaching the same event handler to each of them is a waste of memory and could even be a performance problem.
Use event delegation instead:
$('#tableID').delegate('input[type=radio]', 'click', function() {
// code here
});
Then you could extract the i and j via regular expression (you could also consider to change the pattern so that you can use something simpler like split()):
var exp = new RegExp("\\[(.+?)\\]\\[(.+?)\\]", 'g');
var match = exp.exec(this.id);
var i = match[1];
var j = match[2];
You could put this together like so:
$('#tableID').delegate('input[type=radio]', 'click', function() {
var match = this.id.match(/\[(.+?)\]\[(.+?)\]/)
var i = match[1]; // use parseInt(match[1]) if you need an integer
var j = match[2];
handleOnClickRadio(i,j);
});
edit: Made code a bit simpler.
If i and j correspond to column and row indicies, see #Caspar Kleijne's answer for an alternative way to retrieve them.
For accessibility, you should consider binding the handler to the change event. Then changes via the keyboard will be recognized too.
wire up the event like this
$("#bigtable input[type='radio']").bind("click", OnClickRadio);
and use the handler like
var OnClickRadio = function () {
var col = $(this).parent("td").index();
var row = $(this).parent("td").parent("tr").index();
handleOnClickRadio(col, row)
});
You can attach an onClick method to a collection of radio buttons within a table with a simple bit of jQuery. When you say 'table called "bigtable"', I'm assuming that you mean that it has id="bigtable" in the following code.
$(document).ready(function() {
$("#bigtable input:radio").click(function() {
// Your on click code here
});
});
However, I would usually give each of the radio buttons a specific class using class="magicRadioButton" and then your jQuery code becomes a little clearer and doesn't rely on all of those radio buttons being within a table;
$(document).ready(function() {
$(".magicRadioButton").click(function() {
// Your on click code here
});
});
Now, if you need to then plug this information into your current handleOnClickRadio method, you can do so with the following.
$(document).ready(function() {
$("#bigtable input:radio").click(function() {
var button_id = $(this).attr("id");
var re = new RegExp("\\[(.*?)\\]\\[(.*)\\]");
var matches = re.exec(button_id);
var i = matches[1];
var j = matches[2];
handleOnClickRadio(i,j);
});
});
Give them class names in conjunction with $(this) in your click trigger
I suggest using delegate if you have lot of radios: that way, only one Event listener will be attached
see http://api.jquery.com/delegate/
$("#globalContainer").delegate("input", "click", function(){
//Perform a string test / regex to test if the id matches something-radio[i][j]
//With a regex with capturing groups you can retrieve [i] and [j] values at the same time
if ( test($(this).attr("id")) ) {
}
});
Ideally, you'd have a onclick assigned to the big table rather than each and every radio button. Events in JavaScript bubble up so the table (which is the eventual parent of all these radio buttons) will receiving the event.
So in jQuery you would have code like this
$('#bigtable').click(handleOnClickRadio);
The signature of your handleOnClickRadio function would be
function handleOnClickRadio(evt) {
var radio = evt.target;
var id = $(radio).attr('id');
}
evt.target will identify the actual radio button that was clicked/checked and you can access other attributes of the radio as well. such as
$(radio).attr('id)
Will give you the id of the radio button.
<input type="radio" class="many-radio-buttons" ....
jQuery:
$('.many-radio-buttons').click(function() {
//your_code;
});

Categories

Resources