jQuery - how to determine which link was clicked - javascript

I have a simple piece of PHP which generates n copies of the following code:
<p class="ShowSDB_L2" class="center" onClick="FSD_L2('<?php print dbG;?>','<?php print $sLID;?>')">Click Here to See Data</p>
<div class="divSDB_L2">
</div>
It is generated using PHP, so the number of copies is unknown up front.
On another page I have the following Javascript (using jQuery)
function FSD_L2(dbG,SlID)
{
$(".divSDB_L2").load("test15.php?dbG="+dbG+"&SlID="+SlID).css('display','block');
}
When the text above (Click Here to See Data) is clicked, it should add the contents of test15.php between the the two DIV tags.
#Test15.php
<?php
$dbG = $_GET['dbG'];
$SlID = $_GET['SlID'];
print $dbG . " & " . $SlID;
?>
The problem I have is how to determine which of the links was clicked? At present, if I have three copies, and click one, all three copies are activated.
I hope I have made this clear enough. I'm sure there must be a simple way, but I'm quite new to Javascript/jQuery.

Like Brian said, you could just put the same class on all of your links and use the $(this) keyword in jQuery inside of a click function to find out which link was clicked.
Here's a basic example of changing link colors on a nav using this technique: http://jsfiddle.net/9E7WW/
HTML:
<a class="nav">Test</a>
<a class="nav">Test2</a>
<a class="nav">Test3</a>
<a class="nav">Test4</a>
Javascript:
$(document).ready(function(){
$('.nav').click(function(){
// change all to black, then change the one I clicked to red
$('.nav').css('color', 'black');
$(this).css('color', 'red');
});
});

Am not sure I fully understand what it is you are having difficulty with, but the following is how I would do it.
<p class="ShowSDB_L2" class="center" data-dbg="<?php print dbG;?>" data-slid="<?php print $sLID;?>">Click Here to See Data</p>
<div class="divSDB_L2"></div>
$(document).ready(function() {
$(document).on('click', 'p.ShowSDB_L2', function(evt) {
var $p = $(evt.currentTarget),
dbG = $p.data('dbg'),
slid = $p.data('slid'),
$div = $p.next();
FSD_L2(dbG, slid, $div);
});
});
function FSD_L2(dbG, SlID, $div)
{
$div.load("test15.php?dbG="+dbG+"&SlID="+SlID).css('display','block');
}
The click handler is not hardcoded to each p tag. Instead with each p tag we store the required data, ie dbg & slid.
The click handler is then attached once at document ready. jQuery abstracts over the various browsers and passes to its handlers the event object as its first parameter. This object can then be used to find the element on which the event occurred. Refer: http://api.jquery.com/on/
Finally, we fetch the required data from the clicked element, find the div that needs to be updated and then call your custom function.

Here is a cross-browser way to find the element (target) that triggered the event (e):
function getTarget(e){
// non-ie or ie?
e=e||window.event;
return (e.target||e.srcElement);
};

Add the complete URL to your link (or p in this case) using a data attribute:
<p class="ShowSDB_L2" class="center" data-loadurl="test15.php?dbG=<?php echo $dbG; ?>&SlID=<?php echo $SlID; ?>">Click Here to See Data</p>
<div class="divSDB_L2"></div>
Then do all the binding directly in your jQuery so you have direct access to the link that was clicked:
$(document).ready(function() {
$('.ShowSDB_L2').on('click', function(e) {
e.preventDefault();
$('.divSDB_L2').empty().load($(this).data('loadurl')).show();
});
});

Related

Moving inline javascript function to external file and convert to jQuery

I am trying to optimize my "spoiler" bbcode on phpBB3.
Right now, I have a working solution, but the inline javascript is injected by phpBB every time the "spoiler" bbcode tag is used. I want to call a common function instead of adding it inline every time the bbcode is used.
Here is that working inline javascript:
<div class="spoiler">
<div class="spoiler-title">
<span onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.parentNode.getElementsByTagName('a')[0].innerText = 'hide'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.parentNode.getElementsByTagName('a')[0].innerText = 'show'; }">
<strong>{TEXT1}</strong> (show)
</span>
</div>
<div class="spoiler-text">
<div style="display: none;">
{TEXT2}
</div>
</div>
</div>
For ease of reading, the inline onclick function is repeated here:
if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') {
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = '';
this.parentNode.getElementsByTagName('a')[0].innerText = 'hide';
} else {
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none';
this.parentNode.getElementsByTagName('a')[0].innerText = 'show';
}
Clicking the anchor with the class of "spoiler-btn" has a preventDefaults on it, to prevent the click from taking you to the top of the page:
$(document).ready(function(){
$(".spoiler-btn").click(
function(e) {
e.preventDefault();
}
);
});
I was trying to replace the span onclick inline javascript with a function call that passes 'this' to an external javascript file. I couldn't seem to get that working, so I tried using jQuery to capture 'this' to traverse up the DOM to find the "div" contained within the "spoiler-text" div and manipulate the display:none. There can be multiple of these spoiler tags on the page, so I cannot give the div inside of the "spoiler-text" div an id.
Here I changed the onclick of the span to the external function:
onclick="spoilerToggle(this);"
I then have the following in my external file:
var spoilerToggle = function(param) {
if ($(this).parent('div').parent('div').hasClass('spoiler-text').css('style') == 'none') {
($(this).parent('div').parent('div').hasClass('spoiler-text').removeAttr('style'));
($(this).parent('div').$('a').text('hide'));
} else {
($(this).parent('div').parent('div').hasClass('spoiler-text').css('display', 'none'));
($(this).parent('div').$('a').text('show'));
}
}
The console then gives the following error:
bbcode.js:22 Uncaught TypeError: $(...).parent(...).parent(...).hasClass(...).css is not a function
Line 22 is the line with the "if" check.
jQuery is loaded on the site, and I've made sure to call my external javascript file right before the close of the body tag.
I feel like I've gone down the rabbit hole and cannot see the light. I'm sure this is much easier than I am making it out to be.
Any help is greatly appreciated. Thank you!
.hasClass() returns a boolean, so you can't chain other methods after it. That's why you get the error you quote.
I would implement it a different way though:
$(document).on("click", ".spoiler-title", function(e) {
e.preventDefault();
var container = $(this).closest(".spoiler");
container.find(".spoiler-btn").text(function(i, currentText) {
return currentText === "show" ? "hide" : "show"
});
container.find(".spoiler-text div").toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="spoiler">
<div class="spoiler-title">
<span>
<strong>{TEXT1}</strong> (show)
</span>
</div>
<div class="spoiler-text">
<div style="display: none;">
{TEXT2}
</div>
</div>
</div>
The above uses a single, delegated click handler bound to the document to handle clicks on all spoiler elements on the page (you could instead bind it to a lower-level container element, at whatever the lowest level is that contains all the spoilers).
Within the handler, this will refer to the clicked element, so with DOM navigation methods such as .closest() and .find() you can go up to the containing div and then down to the elements you want to manipulate. .closest() is more flexible than trying to chain .parent().parent(), because it will automatically go up until it finds an element matching the specified selector, so if you later change your HTML structure the JS probably won't need to change.
If the .text() call looks confusing, what happens there is jQuery calls the function I passed to .text() as an argument, passing it the current value of the element's text and then whatever value is returned becomes the new text.

Issues while Displaying/Reading data through jquery

I'm trying to do is - Before application is ready, it reads some data from one of the external file, make a new dyanamic "li" based on the file content and then it renders that li on html.
Just to add some explanation - There are two "li" in code
1) Dynamic li - that generates after reading a line from file
2) Static li - that display static li
So, whenever i try to click on "Static link" it calls click event and display me result which works fine.However, when i click on dynamic link, it doesn't trigger the click event
Another thing i noticed, When application is ready it display "its now generating static link first" alert first then it displays "its now generating dynamic link". Potentially, it should display the "dynamically link" alert first and the static link alert afterwards.
HTML
<body>
<div class="ui-page ui-page-active" id="main">
<header>Open Fulfillment Order</header>
<div id="ordersList" style="text-align: left">
<ul id="dynamicList" style="text-align: left;padding-left: 70px;padding-top: 30px">
</ul>
</div>
</div>
</body>
File.txt
Order1, 3/15/2017, 2
Order2, 3/10/2017, 3
Order3, 3/30/2017, 4
order4, 3/20/2017, 2
Javascript file
$(document).ready(function() {
$.get('file/data.txt', function(data) {
alert("its now generating dynamic link");
var lines = data.split("\n");
for (var prop in lines) {
var orderData = lines[prop];
var splittedData = orderData.split(",");
// Dynamic link hard coded string will be repalced with actual order name
$("#ordersList ul").append('<li><span class="tab">Dynamic Link</span></li>');
}
});
alert("its now generating static link first");
$("#ordersList ul").append('<li><span class="tab">Static Link</span></li>');
});
$(document).ready(function() { //dom is now loaded in.
$('#dynamicList li').click(function() {
alert($(this).find('a').attr('data-value')); // this will alert data-value value.
});
});
Any idea why click event is not being called on Dynamic Link?
the issue could be that when you use
$('#dynamicList li').click(function() {
alert($(this).find('a').attr('data-value')); // this will alert data-value value.
});
jQuery only creates bindings for the li elements that currently exist on the page. If lis are added later, try using this instead
$(document).on('click', '#dynamicList li', function() {
alert($(this).find('a').attr('data-value')); // this will alert data-value value.
});

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!

How do I click on a link without id

I'm not experienced in javascript. I'm trying to write a function in CasperJS, which uses javascript.
I'm trying to click on a link from a search result page. The <a href> tag does not have an id to it, but it is enclosed in a <h3 />, which is enclosed in a <div id="some_id"/>.
Essentially the code looks like this:
<div id="result_0">
<div />
<div />
<h3 class="...">
<a href="some_link">
.
.
</a>
</h3>
.
.
</div>
I want to know how to click that link in javascript.
I tried doing it like this:
document.getElementById('result_0').getElementsByTagName('div')[2].getElementsByTagName('a')[1].click();
But this doesn't seem to work. Can you guys help ?
Edit: Here is the link to my entire script: https://github.com/ctrl-shift-esc/randomamazonshopper/blob/master/myscript.js
You need a CSS selector and the thenClick method here. Something like this should work:
casper.thenClick('#result_0 h3:first-child a');
The following works for the html structure shown in the question (if you change the div's id from some_id to result_0):
document.getElementById('result_0').getElementsByTagName('h3')[0]
.getElementsByTagName('a')[0].click();
Demo (open the browser's JS console): http://jsfiddle.net/kyLXT/1/
Perhaps your code had the wrong indices in the square brackets?
Or you can do this to click the first link in the first h3 within the element with that id:
document.querySelector('#result_0 h3 a').click();
Or if you're concerned that there might not be a matching element:
var el = document.querySelector('#result_0 h3 a');
if (el)
el.click();
// optionally add an else here
Note that either way the code would need to be in a script block that appears after the elements in question and/or in a DOM ready or window onload event handler (the jsfiddle demo above put the code in an onload handler via the fiddle options on the left).
You can use the ID of the div holding the <h3>:
var oParentDiv = document.getElementById("some_id");
var arrHeaders = oParentDiv.getElementsByTagName("h3");
if (arrHeaders.length !== 1) {
alert("no header or more than one");
} else {
var oHeader = arrHeaders[0];
var arrLinks = oHeader.getElementsByTagName("a");
if (arrLinks .length !== 1) {
alert("no link or more than one");
} else {
var oLink = arrLinks[0];
oLink.click();
}
}

find ID of parent DIV and fade DIV out

Im trying to fade out a DIV when clicking a link within the DIV itself. Here is my code:
$(".hideinfo").click(function () {
var parentLink = $(this).parent().parent();
$(parentLink).fadeTo("slow", 0);
});
The reason I'm not specifying the ID directly is because I want to use this to fade out multiple DIVs with different ID's.
The above code was returning the ID when I setup an alert but not fading the DIV out or anything else I tried to so... any help here would be appreciated. The HTML is:
<div id="First-Block" class="item">
<p>text here</p>
<p>Back</p>
</div>
Thank you!
You should use fadeOut("slow") instead.
Try changing your code to:
$(".hideinfo").click(function () {
var parentLink = $(this).parent().parent();
$(parentLink).fadeOut("slow");
});
To improve this even further you can shorten your code to:
$(".hideinfo").click(function() {
$(this).closest(".item").fadeOut("slow");
});
Just to mention as well that by clicking on an anchor it will jump to the top of the page using #. I would take a look at .preventDefault()
You can also check out the API here -> http://api.jquery.com/fadeOut/
Use fadeOut() instead since your primary goal is to affect the overall visibiltity not a given opacity.
jsBin demo
$(".hideinfo").click(function( e ){
e.preventDefault(); // prevent default anchor link behavior
$(this).closest('.item').fadeTo(400, 0);
});
Additionally try to wrap the above into a document ready :
$(function(){
// code here.
});

Categories