I wish to have a link which opens popup when clicked however I wish it to open a page in a new window if the user doesn't have JS enabled.
The following doesn't seem to work,
<a id="tac-link" target="_blank" href="tac.html">terms and conditions</a>
function popUp(URL) {
day = new Date();
id = day.getTime();
eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=550,height=600,left = 445,top = 150');");
}
$('tac-link').click(function() {
popUp('tac.html');
return false;
});
I think you just have the id selector wrong. Try changing $('tac-link') to $('#tac-link').
Another approach:
$('a[target="_blank"]').click(function(e) {
window.open( this.href );
e.preventDefault();
});
In order to make this functionality more browser-compatible, you need to pass the event object to the click handler, then call e.preventDefault();.
example:
$( '#button' ).click( function( e ) {
//... your code...
e.preventDefault();
return false;
} );
Also note that event.preventDefault is not present in all browsers and will cause an error in things like IE7 (if memory serves.) To avoid that, use a general if-statement:
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;
This will prevent the error from being thrown. I believe jQuery uses this approach as well.
You simply missed the # indicating it's an id and not a node name.
$('#tac-link')
PS - I wouldn't recommend using eval, why not just store all the page variables in an object?
var pages = {};
function popUp( url ) {
var id = +new Date;
pages[id] = window.open( url );
}
Related
I'm creating a Chrome Browser Extension that clicks some buttons automatically whenever they appear. I'm using arrive.js for the watching, which uses a query Selector to watch for the html elements to click on.
var buttonA = 'a[data-test="begin-session-button"]'
var buttonB = 'a[data-test="skill-header-practice-button"]'
document.arrive(buttonA, function () {
document.querySelector(buttonA).click();
});
document.arrive(buttonB, function () {
document.querySelector(buttonB).click();
});
The Problem I have is some sites have both buttons buttonA and buttonB. As of now both buttons would be clicked and it is a matter of luck which one gets clicked last.
Whenever there is a site with buttonA and buttonB, only click buttonA. So I'm looking to alter the query for buttonB like:
document.arrive(buttonB + ' :not:' + buttonA, function () {
document.querySelector(buttonB).click();
});
As a query in the Chrome Browser Console this would look like:
document.querySelector(
'a[data-test="skill-header-practice-button] ' +
':not:a[data-test="begin-session-button"]'
)
This is bad syntax and not working in the chrome brower console. How would the Correct Syntax look like?
Could you not do something like this
document.arrive(buttonA, function () {
document.querySelector(buttonA).click();
});
document.arrive(buttonB, function () {
if(document.querySelector(buttonA) == null){
document.querySelector(buttonB).click();
}
});
I can't say that I have used the arrive library before though so I could be completely wrong
i guess this is simpler to do it "programatically" than with complex selectors, something like (works with your code because buttonA is global, be careful that this var must be accessible to the function):
var buttonA = 'a[data-test="begin-session-button"]'
var buttonB = 'a[data-test="skill-header-practice-button"]'
document.arrive(buttonA, function () {
document.querySelector(buttonA).click();
});
document.arrive(buttonB, function () {
var buttA = document.querySelector(buttonA);
if(buttA === null){
document.querySelector(buttonB).click();
}
});
I have a link where I want to get the top level domain name of the domain clicked.
In my example I have
click on this link
When I click on it I want an alert saying
www.example.com
I know window.location.host does this for the actual location of the site but am not sure how to get this for the individual href
I have tried the below but it returns
jQuery(document).on("click", "a", function (event) {
event.preventDefault();
var id = jQuery(this).attr('href') || 'nohref';
alert(window.location.host);
alert(id);
});
http://www.example.com/this/that
rather than
www.example.com
What is the best way to achieve this?
It's pretty straightforward actually, no need for regular expression:
jQuery(document).on("click", "a[href]", function (event) {
event.preventDefault();
alert(this.hostname);
});
See MDN - HTMLAnchorElement.
I'm not sure if it works in Internet Explorer though.
Try
jQuery(document).on("click", "a", function (event) {
event.preventDefault();
var id = jQuery(this).attr('href') || 'nohref';
var domain = id.match(/http[s]?\:\/\/(.*?)[\/$]/)[1]
alert(domain);
});
var domain = jQuery(this).attr('href').match(/^https?:\/\/([^\/]+)/);
if (domain != null && typeof domain[1]!='undefined')
domain = domain[1];
else
domain = '';
You could take a stab at using document.domain, although it's not as widely supported as window.location.host.
I'm trying to open the href onMouseOver after 3000ms. But it just popups a blank window. What am I missing?
HTML:
My Rec
JavaScript:
var Popup = null;
function openwindow()
{
var win = window.open()
}
(OK, first off, you need to supply a URL to window.open(), otherwise it doesn't know what page to open to. Aside from that:)
When you do a setTimeout() the value of this is reset in the delayed code.
A quick fix is to extract the URL immediately, and then pass a function into setTimeout() that can use the variable.
<a href="../cc2b/myrec.html"
onMouseOver="var popupUrl = this.href; Popup = setTimeout(function(){openwindow(popupUrl)}), 3000);"
onMouseOut="clearInterval(Popup)">
My Rec
</a>
However, a cleaner solution would be to minimise the code in onMouseOver by setting a timeout in the openhoverpopup function:
<a href="../cc2b/myrec.html"
onMouseOver="openhoverpopup(this.href)"
onMouseOut="clearhoverpopup()">
My Rec
</a>
<script>
var popupTimeout = null;
function openhoverpopup(url) {
popupTimeout = setTimeout(function () {
window.open(url);
}, 3000);
}
function clearhoverpopup() {
clearTimeout(popupTimeout);
}
</script>
You can grab the URL from the element that triggered the mouseover event with either event.target or event.srcElement for older IE browsers.
http://jsfiddle.net/b42pr/1
HTML
Hover
JavaScript
function popURL() {
var url = event.target.href || event.srcElement.href;
console.log("Open URL: " + url);
setTimeout(function(){
window.open(url);
}, 3000)
}
this.href is undefined, I think you're looking for window.location.href:
> this.href
undefined
> window.location.href
"http://stackoverflow.com/questions/18981172/settimeout-window-open-cant-take-this-href"
Also, your function
function openwindow()
{
var win = window.open()
}
Takes no parameters and opens nothing. Change it to
function openwindow(target)
{
var win = window.open(target)
}
Be careful though, most pop-up blockers will block this kind of window.
Try specifying the href outside of the string:
My Rec
Could someone please share experience / code how we can detect the browser back button click (for any type of browsers)?
We need to cater all browser that doesn't support HTML5
The 'popstate' event only works when you push something before. So you have to do something like this:
jQuery(document).ready(function($) {
if (window.history && window.history.pushState) {
window.history.pushState('forward', null, './#forward');
$(window).on('popstate', function() {
alert('Back button was pressed.');
});
}
});
For browser backward compatibility I recommend: history.js
In javascript, navigation type 2 means browser's back or forward button clicked and the browser is actually taking content from cache.
if(performance.navigation.type == 2) {
//Do your code here
}
there are a lot of ways how you can detect if user has clicked on the Back button. But everything depends on what your needs. Try to explore links below, they should help you.
Detect if user pressed "Back" button on current page:
Is there a way using Jquery to detect the back button being pressed cross browsers
detect back button click in browser
Detect if current page is visited after pressing "Back" button on previous("Forward") page:
Is there a cross-browser onload event when clicking the back button?
trigger event on browser back button click
Found this to work well cross browser and mobile back_button_override.js .
(Added a timer for safari 5.0)
// managage back button click (and backspace)
var count = 0; // needed for safari
window.onload = function () {
if (typeof history.pushState === "function") {
history.pushState("back", null, null);
window.onpopstate = function () {
history.pushState('back', null, null);
if(count == 1){window.location = 'your url';}
};
}
}
setTimeout(function(){count = 1;},200);
In case of HTML5 this will do the trick
window.onpopstate = function() {
alert("clicked back button");
}; history.pushState({}, '');
You can use this awesome plugin
https://github.com/ianrogren/jquery-backDetect
All you need to do is to write this code
$(window).load(function(){
$('body').backDetect(function(){
// Callback function
alert("Look forward to the future, not the past!");
});
});
Best
In my case I am using jQuery .load() to update DIVs in a SPA (single page [web] app) .
Being new to working with $(window).on('hashchange', ..) event listener , this one proved challenging and took a bit to hack on. Thanks to reading a lot of answers and trying different variations, finally figured out how to make it work in the following manner. Far as I can tell, it is looking stable so far.
In summary - there is the variable globalCurrentHash that should be set each time you load a view.
Then when $(window).on('hashchange', ..) event listener runs, it checks the following:
If location.hash has the same value, it means Going Forward
If location.hash has different value, it means Going Back
I realize using global vars isn't the most elegant solution, but doing things OO in JS seems tricky to me so far. Suggestions for improvement/refinement certainly appreciated
Set Up:
Define a global var :
var globalCurrentHash = null;
When calling .load() to update the DIV, update the global var as well :
function loadMenuSelection(hrefVal) {
$('#layout_main').load(nextView);
globalCurrentHash = hrefVal;
}
On page ready, set up the listener to check the global var to see if Back Button is being pressed:
$(document).ready(function(){
$(window).on('hashchange', function(){
console.log( 'location.hash: ' + location.hash );
console.log( 'globalCurrentHash: ' + globalCurrentHash );
if (location.hash == globalCurrentHash) {
console.log( 'Going fwd' );
}
else {
console.log( 'Going Back' );
loadMenuSelection(location.hash);
}
});
});
It's available in the HTML5 History API. The event is called 'popstate'
Disable the url button by following function
window.onload = function () {
if (typeof history.pushState === "function") {
history.pushState("jibberish", null, null);
window.onpopstate = function () {
history.pushState('newjibberish', null, null);
// Handle the back (or forward) buttons here
// Will NOT handle refresh, use onbeforeunload for this.
};
}
else {
var ignoreHashChange = true;
window.onhashchange = function () {
if (!ignoreHashChange) {
ignoreHashChange = true;
window.location.hash = Math.random();
// Detect and redirect change here
// Works in older FF and IE9
// * it does mess with your hash symbol (anchor?) pound sign
// delimiter on the end of the URL
}
else {
ignoreHashChange = false;
}
};
}
};
Hasan Badshah's answer worked for me, but the method is slated to be deprecated and may be problematic for others going forward. Following the MDN web docs on alternative methods, I landed here: PerformanceNavigationTiming.type
if (performance.getEntriesByType("navigation")[0].type === 'back_forward') {
// back or forward button functionality
}
This doesn't directly solve for back button over the forward button, but was good enough for what I needed. In the docs they detail the available event data that may be helpful with solving your specific needs:
function print_nav_timing_data() {
// Use getEntriesByType() to just get the "navigation" events
var perfEntries = performance.getEntriesByType("navigation");
for (var i=0; i < perfEntries.length; i++) {
console.log("= Navigation entry[" + i + "]");
var p = perfEntries[i];
// dom Properties
console.log("DOM content loaded = " + (p.domContentLoadedEventEnd -
p.domContentLoadedEventStart));
console.log("DOM complete = " + p.domComplete);
console.log("DOM interactive = " + p.interactive);
// document load and unload time
console.log("document load = " + (p.loadEventEnd - p.loadEventStart));
console.log("document unload = " + (p.unloadEventEnd -
p.unloadEventStart));
// other properties
console.log("type = " + p.type);
console.log("redirectCount = " + p.redirectCount);
}
}
According to the Docs at the time of this post it is still in a working draft state and is not supported in IE or Safari, but that may change by the time it is finished. Check the Docs for updates.
suppose you have a button:
<button onclick="backBtn();">Back...</button>
Here the code of the backBtn method:
function backBtn(){
parent.history.back();
return false;
}
How do I test to see if links are external or internal? Please note:
I cannot hard code the local domain.
I cannot test for "http". I could just as easily be linking to my own site with an http absolute link.
I want to use jQuery / javascript, not css.
I suspect the answer lies somewhere in location.href, but the solution evades me.
Thanks!
I know this post is old but it still shows at the top of results so I wanted to offer another approach. I see all the regex checks on an anchor element, but why not just use window.location.host and check against the element's host property?
function link_is_external(link_element) {
return (link_element.host !== window.location.host);
}
With jQuery:
$('a').each(function() {
if (link_is_external(this)) {
// External
}
});
and with plain javascript:
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
if (link_is_external(links[i])) {
// External
}
}
var comp = new RegExp(location.host);
$('a').each(function(){
if(comp.test($(this).attr('href'))){
// a link that contains the current host
$(this).addClass('local');
}
else{
// a link that does not contain the current host
$(this).addClass('external');
}
});
Note: this is just a quick & dirty example. It would match all href="#anchor" links
as external too. It might be improved by doing some extra RegExp checking.
Update 2016-11-17
This question still got a lot of traffic and I was told by a ton of people that this accepted solution will fail on several occasions. As I stated, this was a very quick and dirty answer to show the principal way how to solve this problem. A more sophisticated solution is to use the properties which are accessible on a <a> (anchor) element. Like #Daved already pointed out in this answer, the key is to compare the hostname with the current window.location.hostname. I would prefer to compare the hostname properties, because they never include the port which is included to the host property if it differs from 80.
So here we go:
$( 'a' ).each(function() {
if( location.hostname === this.hostname || !this.hostname.length ) {
$(this).addClass('local');
} else {
$(this).addClass('external');
}
});
State of the art:
Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
a.classList.add( location.hostname === a.hostname || !a.hostname.length ? 'local' : 'external' );
});
And the no-jQuery way
var nodes = document.getElementsByTagName("a"), i = nodes.length;
var regExp = new RegExp("//" + location.host + "($|/)");
while(i--){
var href = nodes[i].href;
var isLocal = (href.substring(0,4) === "http") ? regExp.test(href) : true;
alert(href + " is " + (isLocal ? "local" : "not local"));
}
All hrefs not beginning with http (http://, https://) are automatically treated as local
var external = RegExp('^((f|ht)tps?:)?//(?!' + location.host + ')');
Usage:
external.test('some url'); // => true or false
Here's a jQuery selector for only external links:
$('a[href^="(http:|https:)?//"])')
A jQuery selector only for internal links (not including hash links within the same page) needs to be a bit more complicated:
$('a:not([href^="(http:|https:)?//"],[href^="#"],[href^="mailto:"])')
Additional filters can be placed inside the :not() condition and separated by additional commas as needed.
http://jsfiddle.net/mblase75/Pavg2/
Alternatively, we can filter internal links using the vanilla JavaScript href property, which is always an absolute URL:
$('a').filter( function(i,el) {
return el.href.indexOf(location.protocol+'//'+location.hostname)===0;
})
http://jsfiddle.net/mblase75/7z6EV/
You forgot one, what if you use a relative path.
forexample: /test
hostname = new RegExp(location.host);
// Act on each link
$('a').each(function(){
// Store current link's url
var url = $(this).attr("href");
// Test if current host (domain) is in it
if(hostname.test(url)){
// If it's local...
$(this).addClass('local');
}
else if(url.slice(0, 1) == "/"){
$(this).addClass('local');
}
else if(url.slice(0, 1) == "#"){
// It's an anchor link
$(this).addClass('anchor');
}
else {
// a link that does not contain the current host
$(this).addClass('external');
}
});
There are also the issue of file downloads .zip (local en external) which could use the classes "local download" or "external download". But didn't found a solution for it yet.
const isExternalLink = (url) => {
const tmp = document.createElement('a');
tmp.href = url;
return tmp.host !== window.location.host;
};
// output: true
console.log(isExternalLink('https://foobar.com'));
console.log(isExternalLink('//foobar.com'));
// output: false
console.log(isExternalLink('https://www.stackoverflow.com'));
console.log(isExternalLink('//www.stackoverflow.com'));
console.log(isExternalLink('/foobar'));
console.log(isExternalLink('#foobar'));
The benefit of using this approach is that:
It would automatically resolve the hostname for relative paths and fragments;
It works with protocol-relative URLs
To demonstrate this, let's look at the following examples:
const lnk = document.createElement('a');
lnk.href = '/foobar';
console.log(lnk.host); // output: 'www.stackoverflow.com'
const lnk = document.createElement('a');
lnk.href = '#foobar';
console.log(lnk.host); // output: 'www.stackoverflow.com'
const lnk = document.createElement('a');
lnk.href = '//www.stackoverflow.com';
console.log(lnk.host); // output: 'www.stackoverflow.com'
With jQuery
jQuery('a').each(function() {
if (this.host !== window.location.host) {
console.log(jQuery(this).attr('href'));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You can use is-url-external module.
var isExternal = require('is-url-external');
isExternal('http://stackoverflow.com/questions/2910946'); // true | false
/**
* All DOM url
* [links description]
* #type {[type]}
*/
var links = document.querySelectorAll('a');
/**
* Home Page Url
* [HomeUrl description]
* #type {[type]}
*/
var HomeUrl = 'https://stackoverflow.com/'; // Current Page url by-> window.location.href
links.forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
// Make lowercase of urls
var url = link.href.toLowerCase();
var isExternalLink = !url.includes(HomeUrl);
// Check if external or internal
if (isExternalLink) {
if (confirm('it\'s an external link. Are you sure to go?')) {
window.location = link.href;
}
} else {
window.location = link.href;
}
})
})
Internal Link
External Link
This should work for any kind of link on every browser except IE.
// check if link points outside of app - not working in IE
try {
const href = $linkElement.attr('href'),
link = new URL(href, window.location);
if (window.location.host === link.host) {
// same app
} else {
// points outside
}
} catch (e) { // in case IE happens}
Yes, I believe you can retrieve the current domain name with location.href. Another possibility is to create a link element, set the src to / and then retrieving the canonical URL (this will retrieve the base URL if you use one, and not necessarily the domain name).
Also see this post: Get the full URI from the href property of a link
For those interested, I did a ternary version of the if block with a check to see what classes the element has and what class gets attached.
$(document).ready(function () {
$("a").click(function (e) {
var hostname = new RegExp(location.host);
var url = $(this).attr("href");
hostname.test(url) ?
$(this).addClass('local') :
url.slice(0, 1) == "/" && url.slice(-1) == "/" ?
$(this).addClass('localpage') :
url.slice(0, 1) == "#" ?
$(this).addClass('anchor') :
$(this).addClass('external');
var classes = $(this).attr("class");
console.log("Link classes: " + classes);
$(this).hasClass("external") ? googleAnalytics(url) :
$(this).hasClass("anchor") ? console.log("Handle anchor") : console.log("Handle local");
});
});
The google analytics bit can be ignored but this is where you'd probably like to do something with the url now that you know what type of link it is. Just add code inside the ternary block.
If you only want to check 1 type of link then replace the ternaries with an if statement instead.
Edited to add in an issue I came across. Some of my hrefs were "/Courses/" like so. I did a check for a localpage which checks if there is a slash at the start and end of the href. Although just checking for a '/' at the start is probably sufficient.
I use this function for jQuery:
$.fn.isExternal = function() {
var host = window.location.host;
var link = $('<a>', {
href: this.attr('href')
})[0].hostname;
return (link !== host);
};
Usage is: $('a').isExternal();
Example: https://codepen.io/allurewebsolutions/pen/ygJPgV
This doesn't exactly meet the "cannot hardcode my domain" prerequisite of the question, but I found this post searching for a similar solution, and in my case I could hard code my url. My concern was alerting users that they are leaving the site, but not if they are staying on site, including subdomains (example: blog.mysite.com, which would fail in most of these other answers). So here is my solution, which takes some bits from the top voted answers above:
Array.from( document.querySelectorAll( 'a' ) ).forEach( a => {
a.classList.add( a.hostname.includes("mywebsite.com") ? 'local' : 'external' );
});
$("a").on("click", function(event) {
if ($(this).hasClass('local')) {
return;
} else if ($(this).hasClass('external')) {
if (!confirm("You are about leave the <My Website> website.")) {
event.preventDefault();
}
}
});
this works for me:
function strip_scheme( url ) {
return url.replace(/^(?:(?:f|ht)tp(?:s)?\:)?\/\/(www\.)?/g, '');
}
function is_link_external( elem ) {
let domain = strip_scheme( elem.attr('href') );
let host = strip_scheme( window.location.host );
return ! domain.indexOf(host) == 0;
}