jQuery.styledSelect plugin - opening the select from another element in the dom - javascript

I'm using this plugin - http://plugins.jquery.com/project/styledSelect to style a Select box on my page. Demo page here - http://liepins.org/files/jQuery.styledSelect-1.0/examples.html
I've trying to figure out a way to open and close the select box from another element on the page, something like -
$('#show-lists').styledSelect(); //apply the plugin on page load
$("#another-button").toggle(
function () {
$('#show-lists').clickSelect() //open the dropdown
},
function () {
$('#show-lists').closedSelect() //close it
},
);
The above code doesn't work, it's just there to illustrate. Any idea how I can access these methods externally? Or can anyone suggest an alternative?
Thanks in advance.

You could modify the plugin to expose them as events bound to the control, e.g.
closedSelect();
s.change(closedSelect);
currentZIndex -= 3;
// New lines
s.bind('openSelect', clickSelect);
s.bind('closeSelect', closedSelect);
});
and then trigger the events from your code:
$("#another-button").toggle(
function () {
$('#show-lists').trigger('openSelect');
},
function () {
$('#show-lists').trigger('closeSelect');
},
);
although as you can see closedselect is already bound to the .change() event, so you could just call $('#show-lists').change(); instead for the close case - but I think I'd stick to the separate event myself for clarity.

Related

Rebind .toggle() event after unrelated event?

I have a filter for a grid that is being shown/hidden with toggle like so:
$("#btnFilter").toggle(function () {
// show filter
}, function () {
// hide filter
});
The grid is interactive and double-clicking it will overlay the existing grid with new dynamic HTML. I do not want my filter to be shown when interacting with the grid, so in my grids onClick() event I am putting the appropriate // hide filter code which is the same as in the toggle function.
The only issue is, since I am bypassing the .toggle() event, I'll need to click on #btnFilter twice when attempting to hide it manually (which is what I do not want).
Any thoughts would be great!
I appreciate the answers but the logic isn't really what concerns me, any idea why toggle has been removed? Possibly related to my issue?
Toggle is removed you can use a boolean variable or just ask jQuery if it's visible
$('#btnFilter').on('click', function () {
if ($("#filterDiv").is(":visible")) {
$("#filterDiv").hide();
} else {
$("#filterDiv").show();
}
});
toggle(function,function...) is removed, create a bool and use an if statement
var toggle = false;
$('#btnFilter').on('click', function () {
toggle = !toggle;
if (toggle) {} else {}
});
toggle(function,function...) remove because:
This is the "click an element to run the specified functions"
signature of .toggle(). It should not be confused with the "change the
visibility of an element" of .toggle() which is not deprecated. The
former is being removed to reduce confusion and improve the potential
for modularity in the library. The jQuery Migrate plugin can be used
to restore the functionality.

How to set the focus for a particular field in a Bootstrap modal, once it appears

I've seen a couple of questions in regards to bootstrap modals, but none exactly like this, so I'll go ahead.
I have a modal that I call onclick like so...
$(".modal-link").click(function(event){
$("#modal-content").modal('show');
});
This works fine, but when I show the modal I want to focus on the first input element... In may case the first input element has an id of #photo_name.
So I tried
$(".modal-link").click(function(event){
$("#modal-content").modal('show');
$("input#photo_name").focus();
});
But this was to no avail. Lastly, I tried binding to the 'show' event but even so, the input won't focus. Lastly just for testing, as I had a suspiscion this is about the js loading order, I put in a setTimeout just to see if I delay a second, will the focus work, and yes, it works! But this method is obviously crap. Is there some way to have the same effect as below without using a setTimeout?
$("#modal-content").on('show', function(event){
window.setTimeout(function(){
$(event.currentTarget).find('input#photo_name').first().focus()
}, 0500);
});
Try this
Here is the old DEMO:
EDIT:
(Here is a working DEMO with Bootstrap 3 and jQuery 1.8.3)
$(document).ready(function() {
$('#modal-content').modal('show');
$('#modal-content').on('shown', function() {
$("#txtname").focus();
})
});
Starting bootstrap 3 need to use shown.bs.modal event:
$('#modal-content').on('shown.bs.modal', function() {
$("#txtname").focus();
})
Just wanted to say that Bootstrap 3 handles this a bit differently. The event name is "shown.bs.modal".
$('#themodal').on('shown.bs.modal', function () {
$("#txtname").focus();
});
or put the focus on the first visible input like this:
.modal('show').on('shown.bs.modal', function ()
{
$('input:visible:first').focus();
})
http://getbootstrap.com/javascript/#modals
I am using this in my layout to capture all modals and focus on the first input
$('.modal').on('shown', function() {
$(this).find('input').focus();
});
I had the same problem with bootstrap 3, focus when i click the link, but not when trigger the event with javascript.
The solution:
$('#myModal').on('shown.bs.modal', function () {
setTimeout(function(){
$('#inputId').focus();
}, 100);
});
Probably it´s something about the animation!
I had problem to catch "shown.bs.modal" event.. And this is my solution which works perfect..
Instead simple on():
$('#modal').on 'shown.bs.modal', ->
Use on() with delegated element:
$('body').on 'shown.bs.modal', '#modal', ->
Seems it is because modal animation is enabled (fade in class of the dialog), after calling .modal('show'), the dialog is not immediately visible, so it can't get focus at this time.
I can think of two ways to solve this problem:
Remove fade from class, so the dialog is immediately visible after calling .modal('show'). You can see http://codebins.com/bin/4ldqp7x/4 for demo. (Sorry #keyur, I mistakenly edited and saved as new version of your example)
Call focus() in shown event like what #keyur wrote.
I've created a dynamic way to call each event automatically. It perfect to focus a field, because it call the event just once, removing it after use.
function modalEvents() {
var modal = $('#modal');
var events = ['show', 'shown', 'hide', 'hidden'];
$(events).each(function (index, event) {
modal.on(event + '.bs.modal', function (e) {
var callback = modal.data(event + '-callback');
if (typeof callback != 'undefined') {
callback.call();
modal.removeData(event + '-callback');
}
});
});
}
You just need to call modalEvents() on document ready.
Use:
$('#modal').data('show-callback', function() {
$("input#photo_name").focus();
});
So, you can use the same modal to load what you want without worry about remove events every time.
I had the same problem with the bootstrap 3 and solved like this:
$('#myModal').on('shown.bs.modal', function (e) {
$(this).find('input[type=text]:visible:first').focus();
})
$('#myModal').modal('show').trigger('shown');
Bootstrap has added a loaded event.
https://getbootstrap.com/docs/3.3/javascript/#modals
capture the 'loaded.bs.modal' event on the modal
$('#mymodal').on('loaded.bs.modal', function(e) {
// do cool stuff here all day… no need to change bootstrap
})
Bootstrap modal show event
$('#modal-content').on('show.bs.modal', function() {
$("#txtname").focus();
})
A little cleaner and more modular solution might be:
$(document).ready(function(){
$('.modal').success(function() {
$('input:text:visible:first').focus();
});
});
Or using your ID as an example instead:
$(document).ready(function(){
$('#modal-content').modal('show').success(function() {
$('input:text:visible:first').focus();
});
});
Hope that helps..

jQuery: Get reference to click event and trigger it later?

I want to wrap an existing click event in some extra code.
Basically I have a multi part form in an accordion and I want to trigger validation on the accordion header click. The accordion code is used elsewhere and I don't want to change it.
Here's what I've tried:
//Take the click events off the accordion elements and wrap them to trigger validation
$('.accordion h1').each(function (index, value) {
var currentAccordion = $(value);
//Get reference to original click
var originalClick = currentAccordion.click;
//unbind original click
currentAccordion.unbind('click');
//bind new event
currentAccordion.click(function () {
//Trigger validation
if ($('#aspnetForm').valid()) {
current = parseInt($(this).next().find('.calculate-step').attr('data-step'));
//Call original click.
originalClick();
}
});
});
jQuery throws an error because it's trying to do this.trigger inside the originalClick function and I don't think this is what jQuery expects it to be.
EDIT: Updated code. This works but it is a bit ugly!
//Take the click events off the accordion elements and wrap them to trigger validation
$('.accordion h1').each(function (index, value) {
var currentAccordion = $(value);
var originalClick = currentAccordion.data("events")['click'][0].handler;
currentAccordion.unbind('click');
currentAccordion.click(function (e) {
if ($('#aspnetForm').valid()) {
current = parseInt($(this).next().find('.calculate-step').attr('data-step'));
$.proxy(originalClick, currentAccordion)(e);
}
});
});
I think this:
var originalClick = currentAccordion.click;
Isn't actually doing what you think it is - you're capturing a reference to the jQuery click function, rather than event handler you added, so when you call originalClick() it's equivalent to: $(value).click()
I finally came up with something reliable:
$(".remove").each(function(){
// get all our click events and store them
var x = $._data($(this)[0], "events");
var y = {}
for(i in x.click)
{
if(x.click[i].handler)
{
y[i] = x.click[i].handler;
}
}
// stop our click event from running
$(this).off("click")
// re-add our click event with a confirmation
$(this).click(function(){
if(confirm("Are you sure?"))
{
// if they click yes, run click events!
for(i in y)
{
y[i]()
}
return true;
}
// if they click cancel, return false
return false;
})
})
This may seem a bit weird (why do we store the click events in the variable "y"?)
Originally I tried to run the handlers in x.click, but they seem to be destroyed when we call .off("click"). Creating a copy of the handlers in a separate variable "y" worked. Sorry I don't have an in depth explanation, but I believe the .off("click") method removes the click event from our document, along with the handlers.
http://www.frankforte.ca/blog/32/unbind-a-click-event-store-it-and-re-add-the-event-later-with-jquery/
I'm not a jQuery user, but in Javascript, you can set the context of the this keyword.
In jQuery, you use the $.proxy() method to do this.
$.proxy(originalClick, value);
originalClick();
Personally, I'd look at creating callback hooks in your Accordion, or making use of existing callbacks (if they exist) that trigger when opening or closing an accordion pane.
Hope that helps :)
currentAccordion.click is a jQuery function, not the actual event.
Starting with a brute-force approach, what you'd need to do is:
Save references to all the currently bound handlers
Unbind them
Add your own handler, and fire the saved ones when needed
Make sure new handlers bound to click are catched too
This looks like a job for an event filter plugin, but I couldn't find one. If the last point is not required in your application, then it's a bit simpler.
Edit: After some research, the bindIf function shown here looks to be what you'd need (or at least give a general direction)

jqModal only works after element's been inserted on the page

I'm using the jqModal plugin to attach a dialog box to a button click. I'm trying to attach the following box to the page:
suqBoxInner = document.createElement("div");
suqBoxInner.id = "suq_box_inner";
$(suqBoxInner).jqDrag('.jqDrag').jqResize('.jqResize').jqm({
trigger: '#suq_button',
overlay: 0,
onShow: function(h) {
return h.w.css('opacity', 0.92).slideDown();
},
onHide: function(h) {
return h.w.slideUp("slow", function() {
if (h.o) {
return h.o.remove();
}
});
}
});
However this only works if I run this binding code after the div's been inserted into the page. That is I have to use something like $("#div_on_page").after(suqBoxInner) before running the jqDrag code. What are my options for binding it before it's inserted into the page? I could use $.live() but that has to bind to a mouse event and the jqModal plug in uses bind on the trigger listed inside the function call.
It appears that this plugin requires the div (suqBoxInner) to be on the page. So short of modifying the plugin, I'm not sure you have many options as-is. Perhaps you may want to rethink how you are implementing the plugin? How is suqBoxInner being placed on the page? Is it after a specific event, or action?
One solution I can think of off the top of my head is to fire an event after suqBoxInner is placed on the page. The event would then initialize jqModal.
Just a thought. Good luck.

Listen for change events in forms: JQuery

I have a form with an id of "wizard" - I only have select elements in this form. This form is in a lightbox using the JQuery plugin fancybox:
I want to know when any of these have been changed using JQuery. How can I do this? I currently have:
$('form#wizard select[name=servers], form#wizard select[name=cores]').change(function() {
var channels = parseInt($('form#wizard select[name=servers]').val(), 10) * parseInt($('form#wizard select[name=cores]').val(), 10);
$('#yellow').val(channels);
});
EDIT - I have the above wrapped in $(document).ready(function() {...}
However, it does not work, it does not even get run. I have put alerts in there and they never show up. The above only works when the above is a div that I have removed the display:none from, strange! So I am looking for a different implementation to get around this as I need that lightbox as it is.
I really need help on this.
Thanks all
The jQuery change function only binds those elements that are present when the domready event fires. If the lightbox plugin you are using is dynamically creating elements, you should be using jQuery's live function to "bind your handler to all current - and future matched elements".
Change this:
$('your selector').change(function() { /* code ... */ });
with this:
$('your selector').live('change', function() { /* code ... */ });

Categories

Resources