How do I click on a link without id - javascript

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();
}
}

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.

jQuery - how to determine which link was clicked

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();
});
});

Function to find string on page and click link next to it?

I'm wondering whether it is possible to devise a script which will search a webpage for a certain string of text, and then click the link in the element id directly to its right.
Is this possible. Maybe javascript, php?
Please help, and thanks to all that do. :)
#Four_lo
Thanks for your reply. I'm sorry, maybe it's because I'm pretty new to javascript, but I can't really understand anything on the page you suggested.
I put together some javascript which will search the page for an element id and click the link within there.
<html>
<head>
<script type="text/javascript">
function init(){
var linkPage = document.getElementById('linkid').href;
window.location.href = linkPage;
}
onload=init;
</script>
</head>
<body>
GO HERE
I WANT TO CLICK HERE!
</body>
</html>
So basically, I need to search the page for GO HERE. Then, once this is found, I need to click the link in id="thisone", if that makes sense.
The above code works, and clicks the link within the id specified. However, I'd like to find certain text within that id, then move onto the next id, and click the link within that id.
It is possible. It will probably take some finesse but here is where you should start to access String you need. I believe regular expressions will be a must as well.
http://dom.spec.whatwg.org/#processinginstruction
http://domparsing.spec.whatwg.org/
Slightly more complicated than it needs to be:
function performAfterLinkWithText(text, perform) {
// get all the links
var $links = document.getElementsByTagName('a');
// scan them for your text
for(var i in $links) {
if($links[i].innerHTML === text) {
var $next = $links[i] // ready for loop
, terminateAfter = 20 // don't repeat forever
;
// keep checking the adjacent element
// because newlines show up as #text
do {
$next = $next.nextSibling;
} while( !$next.href && terminateAfter-- > 0 );
// do your thing
perform($next.href, $next); // window.location.href = $next.href;
}
}
}
// test -- performAfterLinkWithText('GO HERE', function(url, link) { console.log(url, link); });
performAfterLinkWithText('GO HERE', function(url) { window.location.href = $next.href; });
Or with jQuery:
window.location.href = $('a:contains("GO HERE")').next().attr('href')

Selecting elements to show and hide, traversal issue! (jQuery)

I have been trying every combination under the sun of parent()/children()/find() and selector syntax to .show() an element of my webpage that i hid on document ready, but I just can't get it to work! I'd really appreciate it if someone could take a look..
If you go to the portfolio section you can see it live here -> http://holly.im/ .
In any case the html looks something like this:
<div id="portfolio">
<h1>Heading</h1>
<div class ="little_column">
<div class="project">
click
</div>
</div>
<div id="c++_games_engine_construction" class="big_column">
<?php include "projects/C++_game_engine_construction.php"; ?>
</div>
</div>
And the relevant jquery:
$(document).ready(function() {
//hide all the big_columns /
// project details within the portfolio page
$('#portfolio').find('.big_column').hide(); //This seems to be working
});
$(function(){
$('.project').click(function () {
var selectedProject =
$(this).children('a.projlink').attr('href');
$(this).parent().parent().find(selectedProject).show(); //My most recent attempt, I though maybe i needed to go up the heirachy then back down? But whatever i try it doesn't show.
return false;
});
});
That's it really, thanks!
Having the character + in the ID of an element causes jQuery to become confused because the + character is reserved for the Next Adjacent Selector.
If you remove those characters from your code, it works just fine. As was mentioned in one of the comments to this answer, since the href is essentially the ID of the item to be shown, you can select it directly.
HTML
<div id="portfolio" class="section">
<h1>Heading</h1>
<div class="little_column">
<div class="project"> click
</div>
</div>
<div id="c_games_engine_construction" class="big_column">
I'm hidden at first!
</div>
</div>
JS
$(document).ready(function () {
//hide all the big_columns /
// project details within the portfolio page
$('#portfolio').find('.big_column').hide(); //This seems to be working
});
$(function () {
$('.project').click(function () {
var selectedProject = $(this).children('a.projlink').attr('href');
$(selectedProject).show(); //My most recent attempt, I though maybe i needed to go up the heirachy then back down? But whatever i try it doesn't show.
return false;
});
});
jsfiddle
The issue is with the + in the selector. It needs to be escaped because it has special meaning in the Selectors API (and is invalid for an ID).
If you removed the ++ from the href and the id, it works.
Alternately, you can do .replace(/\+/g, "\\+")
var selectedProject = $(this).children('a.projlink').attr('href').replace(/\+/g, "\\+")
Off topic: You don't need two .ready() calls, which is what you have, but using different syntax.
As others have mentioned, your problem are the + characters mistreated by jQuery. So the simple solution is: do not use jQuery - or at least, not for the selector thing. Since every target you have is an id selector, we can easily change it to
$(document).ready(function() {
$('#portfolio').find('.big_column').hide();
$('.project').click(function () {
var selectedProject = $(this).find('a').attr('href'); // a littebit simplified
var el = document.getElementById(selectedProject.slice(1));
$(el).show();
return false;
});
});

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