How can I write a function that relies on dynamic selectors? - javascript

I am writing a function to dynamically load jQuery UI accordian leaves with content. I know (think) the AJAX part works as I lifted it from another working AJAX loader I have, but the function as a whole does not work.
The code:
function load_leaf(link){
var link = link;
$.ajax({
cache : false,
type : 'POST',
async: false,
url : 'includes/'+ link +'.php?'+ new Date().getTime(),
dataType : 'text',
data: {
owner : '$user_id'
},
success: function(msg){
$("#" + link).html(msg);
console.log('Can\'t see me in Chrome, but ok in firefox !')
},
error: function() {
console.log($.makeArray(arguments));
},
complete: function() {
console.log($.makeArray(arguments));
}
});
};
$(function(){
$('.accordian').click(function(){
var link = this.getAttribute("link");
load_leaf(link);
});
});
For whatever reason this does not work. The break point seems to be this line
$("#" + link).html(msg);
Specifically the selector, as a hard coded selector works perfectly. The link variable is correctly filled i know this as i can alert the value correctly. The link is not the problem as i replaced the whole ajax function with a simple add class and it a still did not work, it also broke at the selector.
EDIT:
This is the div as printed by php:
<h3 class="accordian" id="'.$tab_id.'" link="'.$tab_link.'" >
'.$tab_name.'
</h3>
<div id="'.$tab_link.'"><p>Hi</p></div>
The html for the first one is:
<h3 class="accordian" id="accordian_manage.php" link="accordian_manage.php" >Manage Images</h3><div id="accordian_manage.php"><p>Hi</p></div>

Your ID has a period . in it, which jQuery interprets as a chained class selector.
You can either change your link/IDs, or use this hack:
$("[id='" + link + "']");
Live demo

I guess your problem is with Jquery is not finding the div to load the msg..Post the accordion div so that i could give you the proper selector

Related

Refer to ID (as selector) that is already inside HTML link tags

I have a link that is generated by a core module (meaning I can't modify the code) as such:
<a id="my-unique-id-1" class="my-link-class" href="/switch off">Switch off</a>
Problem is, the ID and class are within the <a> tag and I do not have any useable elements wrapped around the link that I can use.
When clicked, it goes and do what it has to do server side (see code following), and then returns this:
<a id="my-unique-id-1" class="my-link-class it-is-off" href="/switch on">Switch on</a>
I want to replace or amend the complete first link.
First the jQuery script:
$(".my-link-class").click(function() {
var current_id = $(this).attr('id');
var link = $(this).attr('href');
$.ajax({url: link, success: function (result) {
//All works fine up to here. The changes are made in server side and returns the new link as the result.
//Following is my problem:
if(result){
$(current_id).replaceWith(result); //the selector is wrong, I know.
}
}
}
My problem is that the id (current_id) is already within a <a> tag.
How can I refer to the selector in the tag.
I tried:
$(current_id).replaceWith(result); //nothing happens
$('#' + current_id).replaceWith(result);
$('a#' + current_id).replaceWith(result);
But I get with the last two TypeError: Argument 1 of Node.appendChild does not implement interface Node.
(I know I can do other things than replaceWith such as changing text and href in link, but the problem here is to find the selector first).
You can just use $(this).replaceWith():
$(document).on('click', '.my-link-class', function() {
var html = '<a id="my-unique-id-1" class="my-link-class it-is-off" href="/switch on">Switch on</a>';
$(this).replaceWith(html);
return false;
});
.it-is-off {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="my-unique-id-1" class="my-link-class" href="/switch off">Switch off</a>
I think there are two things happening here.
You are trying to use an ID to replace an element, when it would be easier to just keep a reference to the DOM element you want to replace rather than finding it twice.
You are binding an event to an anchor tag that you are then trying to replace. Once you replace it, the event will go away. The way to avoid this issue is bind your event to something that won't be changing. That can be the element right above the one you are going to replace, or it can be a much higher up element like the body element.
Here's a possible solution that fixes both problems. I've written a function called simulatedAjax to give an idea of what I think you're saying the backend code is doing. It follows the same idea as the jQuery $.get using the configurationObject, callback(result) signature.
function simulatedAjax(config, done){
var onOffText = (config.url === "on" ? "off" : "on");
done('Switch '+ onOffText +'');
}
And now your client code
$(function(){
// Bind the click to the body element, but with a delegate to your link class .custom-link
$('body').on('click', '.custom-link', function(e){
// Store a reference to the A tag, name is irrelevant but self is easy to understand
var self = this;
// Keep the page from actually navigating to the href
e.preventDefault();
//Replace with real jQuery $.get or $.ajax with configuration
simulatedAjax({
url: $(this).attr('href')
}, function(resultHTML){
// Since we stored a reference to the original in the self variable, we can just replace it here. Note that if we tried to use `this` here, it wouldn't refer to the right `this`
$(self).replaceWith(resultHTML);
});
});
});
You can see this code sample working in this JSFiddle http://jsfiddle.net/x83vfmuw/
Hope this helps!

Tooltipster not working properly in the beginning

I am using the tooltipster plugin tool where I got gantt chart drawn with some td given id.
So, which ever id is defined and the mouse over it will get ajax data and show accordingly.
Below is snippet of my codes. Issue here is that the tool tip only appear after few times I mouse the td. Thereafter, it works fine.
I can see, in my debug window, that ajax page is called and following error:
Tooltipster: one or more tooltips are already attached to this element: ignoring. Use the "multiple" option to attach more tooltips. jquery.tooltipster.min.js:1
$(document).ready(function () {
$('td[id]').tooltipster({
// content: 'Loading...',
functionBefore: function(origin, continueTooltip) {
// We'll make this function asynchronous and allow the tooltip to go ahead and show the loading notification while fetching our data
continueTooltip();
var idval=0;
// Next, we want to check if our data has already been cached
//if (origin.data('ajax') !== 'cached') {
$.ajax({
type: 'GET',
url: 'getDetails.php',
data:idval,
success: function(data) {
// Update our tooltip content with our returned data and cache it
//alert("Data is : "+data);
var finalData = 'Total Data : 300 <br> Total Completed : 200';
//alert("DATA");
//origin.tooltipster: $('<span>testst<strong>This text is in bold case !</strong></span>')
origin.tooltipster({
content: finalData,
multiple: true,
contentAsHTML: true
});
//origin.tooltipster({content: data,contentAsHTML: true}).data('ajax', 'cached');
}
});
//}
}
});
});
The Tooltipster plugin really should be initialised before all of this. Using the mouseenter enter to trigger it's initialisation every time a user hover's over a <td> element is not great practice and is the root problem to your issue. Ideally you would want to break it down into the following:
Find your <td> elements with id's defined.
Apply tooltipster to these elements.
Let tooltipster handle everything from there.
1. Finding your <td> elements
With the magic of jQuery you can fetch these with a clever use of selectors rather than querying a larger set with your initial implementation, gathered from the answers within the StackOverflow thread here, jquery get only all html elements with ids, we get:
$('td[id]')
This will fetch you all <td> elements with an id defined, be warned this could be a bit slow if you have an extensive table. Alternatively you can select, then apply a filter to narrow down your set:
$('td').filter(function(){
return $(this).attr('id') !== undefined;
});
Both will essentially do the same!
2. Applying tooltipster to these elements
I've not done much here since you had a lot of commented out code, so I've kept it the same, with some minor tweaks, here is my version of the "working code":
$('td[id]').tooltipster({
// content: 'Loading...',
functionBefore: function(origin, continueTooltip) {
// We'll make this function asynchronous and allow the tooltip to go ahead and show the loading notification while fetching our data
continueTooltip();
// Next, we want to check if our data has already been cached
//if (origin.data('ajax') !== 'cached') {
$.ajax({
type: 'GET',
url: 'getDetails.php',
data: $(this).attr('id'),
success: function(data) {
// Update our tooltip content with our returned data and cache it
//alert("Data is : "+data);
var finalData = 'Total Data : 300 <br> Total Completed : 200';
//alert("DATA");
//origin.tooltipster: $('<span>testst<strong>This text is in bold case !</strong></span>')
origin.tooltipster({
content: finalData,
multiple: true,
contentAsHTML: true
});
//origin.tooltipster({content: data,contentAsHTML: true}).data('ajax', 'cached');
}
});
//}
}
});
3. Letting tooltipster handle everything from here
Tooltipster (when intialised) is triggered by default when hovering over an element, this means your functionBefore will be run before this "hover" event, causing your AJAX request to be run each time, there is no need to do anything more thereafter :D
I hope this helps! :)
You can use this code :
var tooltipInstance;
$("body").on('mouseover', 'td[id]:not(.tooltipstered)', function(){
tooltipInstance = $(this).tooltipster({
//your code ...
});
tooltipInstance.tooltipster('open');
});

jQuery click event with class selector only fires once

I'm using classed links to change FlowPlayer content. Here is a working version: http://jsfiddle.net/r9fAj/
In my actual page using the same code the first link clicked works fine. The second one does not fire the click function at all. Even if I comment out everything but the console.log()...
$('.playerLink').click( function() {
audioPlayer.unload();
initAudioPlayer();
$('#player').css('display', 'block');
$('#player').animate({"height":"50px"}, 1000);
var newClip = {'url':$(this).attr('ajax-data'),'autoplay':true};
audioPlayer.play(newClip);
console.log('playing ' + $(this).attr('ajax-data'));
});
HTML like so
Listen
Listen
<a id="flowplayer" href="/audio/episodes/09_27_2013_Happy_Hour_88509726.mp3"></a>
And the player initialized like so:
var audioPlayer;
var initAudioPlayer = function () {
$f("flowplayer", "/player/flowplayer-3.2.16.swf", {
plugins: {
controls: {
fullscreen: false,
autoHide: false,
}
},
clip: {
autoPlay: false,
url: "",
}
});
audioPlayer = $f();
};
initAudioPlayer();
Since the jsFiddle works over and over I assume something else in my page is preventing the second click() from working but the console has no errors for me.
So my question is, short of posting the whole site's code how do I pursue debugging this?
So it sounds like your .click() event handler is only being fired for the first link you click and not for additional clicks. For general debugging, you could take your page that is not working and gradually comment out / remove other part of the JS and HTML until you are able to make it work correctly. Or start with the minimal amount that is working (the fiddle) and gradually add in the rest to see when it stops working.
So this is the first site I have done where content is delivered via AJAX and internal links are caught by
$("a:not([href^='http://'])").click( function(e) {
var url = $(this).attr("href");
var title = ($(this).attr("title")) ? ': ' + $(this).attr("title") : '';
e.preventDefault();
if(url!=window.location){
window.history.pushState({path:url},title,url);
$('#contentMain').load(url);
document.title = "It's New Orleans" + title;
}
});
For some reason it does work once to click a link with the class but the second time gets preventDefault()ed.
Listen
The fix was adding [href^='#'] to not() e.g.
$("a:not([href^='http://'],[href^='#'])").click( function(e) {

Comment Box is not hiding after posting

Comment box is not hiding after posting any thing.
currently using AJAX to post data. Just want to hide input area just after submitting it.
here is fully
working example
I also this code to open the comment box.
$(document).ready(function() {
$(".comment_button").click(function() {
var element = $(this);
var I = element.attr("id");
$("#slidepanel" + I).slideToggle(300);
$(this).toggleClass("active");
return false;
});
});
suggesting you check the example Here
Add the following to the success callback:
$("#slidepanel" + Id).hide();
Or, to match the fade in:
$("#slidepanel" + Id).slideToggle(300);
See here for updated jsFiddle. Note the success callback will not be called in jsFiddle, since the php page does not exist at http://fiddle.jshell.net/DkAMN/1/show/insertajax.php.

loading content into a div with jquery

Hey All - I am having a bit of trouble with a jquery function. I have a nav bar and I want when a user clicks on the nav bar to have the page load into a div (#content)
The code I have works for the first click, but when I try to click on another item it shows the loading image, but does not put the new content in the div (it leaves the old content). Any thoughts?
$(document).ready(function() {
$('.cat').live("click",function() {
var section = $(this).attr("id");
$.ajax({
type: "POST",
url: "../soccer/nav/" + section + ".php",
beforeSend: function() {
$('div#content').hide();
$('div#loading').show();
},
success: function(html){
$('div#loading').hide();
$("div#content").replacewith(html);
}
});
return false;
});
});
Any help would be greatly appreciated!
The problem is the .replacewith() method. You are actually replacing the #content div with the new content. Just use .html() instead.
You don't need $("div#content"). You can just do $("#content")
$("#content") means find the node with the id "content".
Try with:
$.post("../soccer/nav/" + section + ".php", null, function(data)
{
$('#loading').hide();
$("#content").html(data);
});
Try to use jQuery.Load event to make use of ajax and html populating at the same time.

Categories