Making JEditable work on new elements (.live) - javascript

I'm using the JEditable plugin for in-place editing.
I have a "setup" function which calls .editable() on all the relevant classes. The problem is, I have newly appended elements which I'd like to make editable as well. Obviously, being newly added, .editable() never gets called on them.
In other words, I'm looking to get the effect that jquery's live() function does, but for the editable() function.
My current workaround seems kinda ugly to me (redscribe_button is the button that needs to be clicked to edit the text):
$(".redescribe_button").live("click", function(click_event) {
click_event.preventDefault();
$(".editable", $(this).parent().parent()).editable("/temp/", {
event: "make_editable",
indicator : 'Saving...',
tooltip : 'Click to edit...'
});
$(".editable", $(this).parent().parent()).trigger('make_editable');
});
In other words, I'm just calling .editable every time the edit button is clicked.
Any ideas for a better solution?

I just came to this question as well and solved it in a more elegant way (IMHO).
$('.jqEdit').live('click',function(event) {
event.preventDefault();
$(this).editable('save.php')
});

Calling editable more than once on an element has no adverse side effects, right? So why not just re-do the setup each time anything changes.

Related

Best way to slim down my code on onclicks

I am not great at javascript/jquery for the most part but I know how to get some software to work. But my issue is that I have a whole bunch of
$("body").on("click", "button#thisid", function(event) {
//do stuff here
});
There are alot of the on clicks that use jquery post and get functions but they all have tiny and simple differences that i need to have get sent through. I dont want every single button to have an onclick event but I am not sure how to bind the event to a large list of items that need to have it attached to.
I have been trying to come up with some way to slim all these down but I want to have the best approach instead a whole bunch of crash and fails. So I am reaching out to people who know more than me in order to lead me in the correct path.
Please help
Considering your elements are dynamically injected, you will need to apply the click handler to an element that always exist on page load:
$(document).ready(function() {
$(document).on("click", "button.target", function() {
console.log($(this)[0].id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="1" class="target">One</button>
<button id="2" class="target">Two</button>
In the above example, the click handler is applied to document, and triggers whenever a button element with the class of target is clicked, running the code inside the function.
To combine the .get() and .post() functions, you'll have to find synonymous data. Keep in mind that you have access to $(this), so you can extract the relevant ID if need be :)
Hope this helps!
I dont exactly get what you want to do...
But the $("body") is the jquery selector which defines on which elements your listener will be bound to.
So if you want to create a listener for more different elements the probably easiest solution is creating a class like "listenedElement" which you give to every element you want the listener to react to and write write the selector like this
$('.listenedElement').on( "click", function() {});
If you just look for click listeners this one looks pretty nice as well:
https://api.jquery.com/click/
A nice way I find is having a one line for each button like so:
$('#model').on('click', openModel());
$('#openDropdown').on('click', openDropdown());
$('#shoppingCart').on('click', shoppingCart());
And then defining each of these functions:
function openModel() {
// Stuff here
}
function openDropdown() {
// Stuff here
}
function shoppingCart() {
// Stuff here
}
So instead of writing the function as a parameter, I find it neater to just do it separately and call it like above.

Wrote alternative to jQuery Accordion, it spazzed. Why?

I wrote an alternative to the jQuery Accordion, as that didn't offer multiple open section support (any idea why they opted to not include support for that? What's the history there?). I did some research on StackOverflow, as well on Google to see what other options others came up. I needed something that could be used on the fly on multiple elements.
After seeing several solutions and experimenting with them, in the end, I wrote my own version (based on Kevin's solution from http://forum.jquery.com/topic/accordion-multiple-sections-open-at-once , but heavily modified).
jsFiddle can be found here: http://jsfiddle.net/3jacu/1/
Inline Code:
$(document).ready(function(){
$.fn.togglepanels = function(){
return this.each(function(){
h4handler = $(this).find("h4");
$(h4handler).prepend('<div class="accordionarrow">▼</div>');
$(h4handler).click(function() {
$(h4handler).toggle(
function() {
barclicked = $(this);
$(barclicked).find(".accordionarrow").html('►');
$(barclicked).next().slideUp('slow');
window.console && console.log('Closed.');
return false;
},
function() {
barclicked = $(this);
$(barclicked).find(".accordionarrow").html('▼');
$(barclicked).next().slideDown('slow');
window.console && console.log('Open.');
return false;
}
);
});
});
};
$("#grouplist").togglepanels(); }
Oddly, the accordion arrow at the right side stopped working once I pasted it in jsFiddle, while it works in my local copy.
In any case, the issue is that toggling isn't working as expected, and when it does, it fires duplicate toggle events which result in it closing, opening, then ultimately closing the section and it won't open from that point on (it toggles open then closes back). That's assuming it works! At first, it won't work as it doesn't respond. I think there's a logic error somewhere I'm missing.
From what I wrote/see in the code, it searches the given handle for the corresponding tag (in this case, h4), pops the handle into a variable. It then adds the arrow to the h4 tag while applying the accordionarrow class (which floats it to the right). It then adds a click event to it, which will toggle (using jQuery's toggle function) between two functions when h4 is clicked.
I suspect the problem here is that I may be mistakenly assuming jQuery's toggle function will work fine for toggling between two functions, that I'll have to implement my own toggle code. Correct me if I'm wrong though!
I'm trying to write the code so it'll be as efficient as possible, so feedback on that also would be appreciated.
Thanks in advance for your time, assistance, and consideration!
You have the toggle binding (which is deprecated by the way) inside of the click binding, so a new event handler is getting attached every time you click the header.
As a random aside you should also fire events within the plugin (where you have the console lines would make sense) so that external code can react to state changes.
I believe your issue is the $(h4handler).click(function() { you have wrapped around the toggle listener. Essentially what this was doing was making so every click of the tab was adding the toggle listener, which was then also firing an event. Removing the click listener will have the behaviour you expect.
You forgot to paste the trailing characters ); to close the function call to jQuery function ready. Fixed: http://jsfiddle.net/LeZuse/3jacu/2/
UPDATE: I've just realised I did not really answer your question.
You are duplicating the .toggle functionality with binding another .click handler.
The doc about .toggle says:
Description: Bind two or more handlers to the matched elements, to be executed on alternate clicks.
Which means the click event is already built in.
NOTE: You should use local variables instead of global, so your plugin won't pollute the window object. Use the var keyword for this:
var h4handler = $(this).find("h4");

Sharing an event across two scripts or using change is visibility state as an event trigger

OK I am lost here. I have read numerous postings here and else where on the topic of how to check for the state of a given element in particular whether it is visible or hidden and make the change of state trigger an event. But I cannot make any of the suggested solutions work.
Firstly, as every one seems to leap on this point first, the need to do this has arisen as I have one jQuery script which deals with displaying an svg icon in a clickable state. And another which already has functions to perform relevant actions when the form is made visible by clicking the icon and obviously I want to reuse these.
What I have tried:
Initially I tried have both the scripts acting on a single click event (this remains the ideal solution)....
Script 1:
$(".booked").on("click", function() {
$("#cancellation_Form_Wrapper").css("visibility","visible");
}).svg({loadURL: '../_public/_icons/booked.svg'});
Script 2:
$(".booked").on("click", function() {
// do stuff
});
This did not work so I tried to research sharing an event across two scripts but couldn't make any head way on this subject so I tried triggering another event for the second script to pick up....
Script 1:
$(".booked").on("click", function() {
$("#cancellation_Form_Wrapper").css("visibility","visible");
$("#cancellation_Form_Wrapper").trigger("change");
}).svg({loadURL: '../_public/_icons/booked.svg'});
Script 2
$("#cancellation_Form_Wrapper").on("change", function(event){
// do stuff
});
This did not work again I am unclear why this didn't have the desired effect.
Then I tried is(:visible) ....
Script 1
$(".booked").on("click", function() {
$("#cancellation_Form_Wrapper").css("visibility","visible");
}).svg({loadURL: '../_public/_icons/booked.svg'});
Script 2
$("#cancellation_Form_Wrapper").is(":visible", function(){
// do stuff
});
So I am a bit lost. The ideal would be to return to the first notion. I do not understand why the click event on the svg cannot be handled by both scripts. I assume that this has something to do with event handlers but I am not sure how I could modify the script so they both picked up the same event.
Failing that I could use the fact the visibility state changes to trigger the action.
Any guidance welcomed.
Edit Ok I have just resolved the issue with script 2 picking up the triggered event from script 1. Sad to say this was a basic error on my part ... the form was preventing the display of the alert. However I still cannot get the is(:visible) to work.
Your syntax may be off:
$("#cancellation_Form_Wrapper").is(":visible", function(){
// do stuff
});
should be:
if($("#cancellation_Form_Wrapper").is(":visible")){
// do stuff
});
EDIT: If you want something to happen after a div is made visible, you may want to use the show() callback rather than toggling visibility:
$('#cancellation_Form_Wrapper').show(timeInMilliseconds, function(){
// do something
});
However, this needs to take place in the same function, which I don't think improves your position.
The problem is probably that your second on() script is firing at the same time as your first, meaning the wrapper is not yet visible. You could try wrapping the second on() in a short timeout:
$(".booked").on("click", function() {
setTimeout(function(){
if($("#cancellation_Form_Wrapper").is(":visible")){
// do stuff
});
}, 100);
});
That should introduce enough of a delay to make sure the wrapper has been shown before trying to execute the second statement.

JQuery if statement for .is(':visible') not working

I have a div that when the page is loaded is set to display:none;. I can open it up using this simple code:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'block'});
});
Once it's opened, I'd like the user to be able to close it so I tried using the .is(':visible') function and then wrapping my original code in an if statment but this time using display:none;
if($('.field-group-format-wrapper').is(':visible')){
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'none'});
});
}
This does not seem to work though and I am not getting any syntax errors that I know of.
I also tried this:
if ($('.field-group-format-wrapper').is(':visible'))
$(".field-group-format-toggler").click(function () {
$(".field-group-format-wrapper").css({'display':'none'});
});
... but that did not work either.
You can just use the toggle function:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").toggle();
});
This will show the '.field-group-format-wrapper' elements if they are currently hidden and hide them if they're currently visible.
FYI the reason your code snippet in your question wasn't working is because you're only checking the visibility of the elements on dom ready, rather than on each click - so the event handler to show the elements will never be attached.
I guess your function is only being called on page load at which time all divs are hidden.
Why not check the visibility in the click event handler?
$('.field-group-format-toggler').click(function(){
var $wrapper = $('.field-group-format-wrapper'); //Maybe $(this).parent()?
if($wrapper.is(':visible'))
$wrapper.hide();
else
$wrapper.show();
As already mentioned, you can use the toggle function to achieve what you want.
To add a bit of extra information, when attaching events like you're doing, you're actually using a subscription model.
Registering an event puts it in a queue of events subscribed to that handler. In this case, when you add the second event to change the CSS, you're adding an event, not overwriting the first one.
Whilst thing isn't actually causing your problem, it's worth being aware of.

jQuery toggle running twice

It seems that this code:
$(function(){
$('.show_hide_login').toggle(
function (){
alert('show');
$("div#fullpage").show();
$("div#loginbox").show();
},
function (){
alert('hide');
$("div#loginbox").hide();
$("div#fullpage").hide();
}
); });
Any idea on why it would be running twice when I click on either link (two, one is a div and one is an anchor)?
How many elements do you have with the .show_hide_login class? I'll guess you have two of those. In which case, $('.show_hide_login') result contains two elements, and toggle() is executed for each of them.
This isn't an answer to your question, but you could clean up your code a bit like so:
$(function() {
$('.show_hide_login').toggle(
function() {
alert('show');
$("#loginbox,#fullpage").show();
}, function() {
alert('hide');
$("#loginbox,#fullpage").hide();
});
});
As to your actual problem, I suspect Nick's guessed the culprit. Check out this demo to see the result of binding the same event twice: http://jsfiddle.net/9jPLv/
In addition to adding an alert prior to the binding of the toggle event, you could add in an unbind() and see if that solves the problem, like so:
$('.show_hide_login').unbind().toggle(
If that solves it, the toggle binding is definitely being run twice, so you'd just have to figure out why.
my answer is just a kind of checkpoint,i had the same issue but for different reason. I did include the script file in base page as well as child page. this resulted in toggle running twice if you have this problem check that the script is added only once.
It might be the same issue i was having.
so if you got an element with a script tag in it - then you move that containing element or wrap it with another tag in jquery - then the ready function in jquery is executed again - thus binding a second toggle function to your element.
as suggested $('.show_hide_login').unbind().toggle( is a workaround that does work, but better to try moving your javascript code to the head or bottom of the page.

Categories

Resources