Fire dialog box when user clicks on external links - javascript

There goal is to prevent users from redirect on accidental clicks on external links, when user fills up the form.
Problem: the whole code has to be abstract. I don't know which links user clicks, I don't know whether the form is fully or partly filled.
If the form is empty, then redirect user without dialog/confirmation box.
Here's code:
function exit_confirm(event) {
let url;
if (event.target.nodeName === "a") {
url = event.target.getAttribute('href');
}
if (window.confirm('Do you want to leave the site?')) {
window.location.href = url;
}
}
function getAllElementsWithDataAttribute() {
return document.querySelectorAll('*[data-]');
}
function registerOnClickChangeKeydownEventsOfElementsWith() {
let elementsWithDataAttribute = getAllElementsWithDataAttribute();
['click', 'change', 'keydown'].forEach(evt => {
elementsWithDataAttribute.addEventListener(evt, exit_confirm, false);
});
}
The code is not a final version.
I have to get url from a clicked link and pass it to window.location.href
I also need to check a clicked link if it is an external link.
*[data-] - here has to be smthing that defines the link

Related

ServiceWorker Notification Click - How can I refresh a page AND jump to an anchor link?

Basically, on my 'notificationclick' event, I am trying to open the notifications URL. It works perfectly for normal URLs. But if the URL has an anchor tag (#), it will then just try to jump to the specified anchor (which doesn't exist yet.)
I can easily cut out the anchor part of the url, and that works for the base page, it will then refresh the page successfully, but it wont jump to the comment.
So i tried doing this:
if (cleanedClientUrl === cleanedUrl && 'focus' in client) {
//focus and reload the window that has this page open
client.focus();
//if the url had a # in it, first navigate to the cleaned url (otherwise it wont refresh)
if (url.indexOf('#'))
client.navigate(cleanedUrl);
client.navigate(url);
return;
}
Which I was hoping would first redirect it to the URL without the cleanedUrl (without the anchor), and then navigate to the original url, which include the anchor, to make it jump down. But it seems the second client.navigate cancels the first one.
Is there any way to wait until the first one is loaded, or tell the page to reload even if there's an anchor specified in the URL?
Here is my full code:
//user clicked / tapped a push notification
self.addEventListener('notificationclick', function(event) {
const clickedNotification = event.notification;
clickedNotification.close();
//exit if the url could not be found
if (!event.notification.data || !event.notification.data.url) return;
//get url from event
var url = event.notification.data.url;
//if the url contains a #, remove it and everything after it
var cleanedUrl = url.indexOf('#') ? url.substring(0, url.indexOf('#')) :url;
event.waitUntil(
self.clients.matchAll({type: 'window', includeUncontrolled: true}).then( windowClients => {
console.log('opening window', windowClients.length, 'windows')
// Check if there is already a window/tab open with the target URL
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
//if the page url contains a #, remove it and everything after it
var cleanedClientUrl;
if (client.url.indexOf('#') !== -1)
cleanedClientUrl = client.url.substring(0, client.url.indexOf('#'));
else cleanedClientUrl = client.url;
// if the cleaned URLs match
if (cleanedClientUrl === cleanedUrl && 'focus' in client) {
//focus and reload the window that has this page open
client.focus();
//if the url had a # in it, first navigate to the cleaned url (otherwise it wont refresh)
if (url.indexOf('#'))
client.navigate(cleanedUrl);
client.navigate(url);
return;
}
}
// If not, then open the target URL in a new window/tab.
if (self.clients.openWindow) {
return self.clients.openWindow(url);
}
})
);
});
Could you quickly jump to the anchor and then immediately reload the page?
main JS thread
window.location = '#my-anchor-value';
window.location.reload();
ServiceWorker
if you need to chain navigation in a SW, you'll need to await the promise completion of the first navigate()
if (url.indexOf('#')) {
return client.navigate(cleanedUrl)
.then(() => client.navigate(url));
} else {
return client.navigate(url);
}

how to refresh the page with original URL when URL has been changed via history.pushState()

I have used history.pushState() and now if the user refreshes the page then it is refreshing current URL which is not an original URL.
I tried detecting refresh page with a cookie, hidden filed but it is not working.
window.onload = function() {
document.cookie="PR=0";
var read_cookies = document.cookie;
var s = read_cookies;
s = s.substring(0, s.indexOf(';'));
if( s.includes("1"))
{
window.location.href = "https://www.google.com";
}
else{
document.cookie="PR=1";
}
loadURL();
};
function loadURL()
{
document.cookie="PR=1";
document.getElementById("visited").value="1";
var str="abc/b cd";
str=str.replace(/ /g, "-");
history.pushState({},"",str);
}
when user is refreshing the page I need original URL on that time.
This might be helpful. But you need control over the pushed url.
// this goes to your 'original' url
window.addEventListener('beforeunload', function (event) {
sessionStorage.setItem('lastPage', window.location.href)
}
// page with your pushed url
if (sessionStorage.getItem('lastPage') === 'PAGE_YOU_DONT_WANT_TO_BE_REACHABLE_DIRECTLY') {
window.location = 'PAGE_YOU_WANT'
}
I'm interested what the use case for this is. As far as my knowledge goes you can't suppress the refresh event completely.

twitter share button quirk

Link to my in codepen: codepen.io/neel111/pen/dRBQNY?editors=1010
When the tweet button is clicked then it redirect to the page to tweet in the twitter, with a preselected text to tweet.
The JavaScript code used there is given below just for a quick look:
//-------------quotes--------
(function(){
window.addEventListener("load", makeRequest);
function makeRequest(mk){
document.getElementsByClassName("buttonQ")[0].addEventListener("click", makeRequest);
function reqListener(rl) {
if(httpR.readyState === XMLHttpRequest.DONE) {
var quote;
if(httpR.status === 200) {
quote = JSON.parse(httpR.responseText);
document.getElementsByClassName("quote")[0].innerHTML = quote[0].body;
} else {
alert("There was a problem with the request!")
}
}
}
var httpR;
httpR = new XMLHttpRequest();
httpR.onreadystatechange = reqListener
httpR.open("GET", "https://quote-api.glitch.me/pull/1", true);
httpR.send();
}
//----------------------tweet-------------------
window.addEventListener("load", function() {
document.getElementsByClassName("buttonT")[0].addEventListener("click", tweetEvent);
})
function tweetEvent(twt) {
//twt.preventDefault();
document.getElementsByClassName("quote")[0].normalize();
var tweetBody = document.getElementsByClassName("quote")[0].childNodes[0].nodeValue;
var URLBase = document.getElementsByClassName("twitter-share-button")[0].getAttribute("href");
var URLExtended = URLBase + "?hashtags=quotes&text=" + encodeURIComponent(tweetBody);
document.getElementsByClassName("twitter-share-button")[0].setAttribute("href", URLExtended);
}
})();
Quirk:
when the tweet button is clicked for the first time after the page is loaded/refreshed then the preselected text in the redirected page to tweet is
Preselected_text(quote)_from_the_main_page #tweet
But after the first click, everytime the tweet button is click the preselected text in the redirected page to tweet is
Preselected_text(quote)_from_the_main_page?hashtags=quotes #quotes
Where i am doing wrong?
So I think the problem is that you are modifying the href of the anchor tag and inserting the modified href into the dom. What I would do instead is to get rid of the in the button and build the url like you are but instead of modifying something in the dom just call window.open(extendedUrl);
Something like this should get you started:
window.addEventListener("load", function() {
document.getElementsByClassName("buttonT")[0].addEventListener("click", tweetEvent);
})
function tweetEvent(twt) {
//twt.preventDefault();
document.getElementsByClassName("quote")[0].normalize();
var tweetBody = document.getElementsByClassName("quote")[0].childNodes[0].nodeValue;
var url = "https://twitter.com/intent/tweet?hashtags=quote&text="+encodeURIComponent(tweetBody);
return window.open(url);
}
})
As you can see I have simplified the url building and then passed the resulting url to window.open which will open the url in a new window/tab (depending on user preference in their browser... find more on that here).

Open URL from JavaScript after user has entered details

I need to prevent a user from downloading a file (PDF) until they have entered some simple details into a form. We need to capture the details so that we can see who is downloading the file.
See a jsFiddle here http://jsfiddle.net/ctn7N/1/
The steps I need it to follow are:
User opens page. If they have already filled out the capture form, store that state in a variable.
They click a download link. Store the link so that it can be used later.
If they've already entered details, i.e. check the variable, open the link in a new tab as normal (default behaviour).
If they haven't entered details, show the capture form.
Once they click submit on the form, show the downloads section again, store the state and open the original download that they clicked on in a new tab.
On subsequent loads of the page they should not have to enter their details again and downloads should just open.
The current code I'm using fails at the last part of step 5, when it tries to open the download link in a new tab. Although it works in the fiddle, it breaks in Chrome v35.0 because the link is blocked by a popup blocker.
Is there any way around this that would allow it to open in all browsers?
Thanks for looking,
Adam
Code to accompany fiddle:
HTML Code
<div id="capture-section" class="hide">
<form id="capture-form">
<label for="name">Enter your name to download the file:</label>
<input id="name" name="name" type="text" />
<button id="submit-btn" type="submit">Submit</button>
</form>
</div>
<div id="download-section">
<!-- Download links replaced with placeholder links for jsFiddle, would normally be PDFs -->
<a target="_blank" class="js-download" href="http://example.com">Document 1</a>
<a target="_blank" class="js-download" href="http://www.google.com">Document 2</a>
<a target="_blank" class="js-download" href="http://www.bing.com">Document 3</a>
</div>
JavaScript
$(document).ready(function() {
var detailsEntered = '',
downloadLink = '';
// Would normally access localStorage on load of page to see if user has already entered details
// Removed to allow multiple jsFiddle runs for a user
//
// detailsEntered = accessStorage('retrieve', 'detailsEntered');
$('.js-download').click(function(event) {
var self = $(this);
downloadLink = self.attr('href'); // Store clicked download link
if (detailsEntered != 'true') {
// If the user hasn't entered details yet, show the form
$('#download-section').addClass('hide');
$('#capture-section').removeClass('hide');
event.preventDefault();
return false;
} // Otherwise allow standard link behviour
});
$("#submit-btn").click(function(event) {
var name = $('input[name=name]').val(),
proceed = true;
if(name==""){
$('input[name=name]').addClass("error");
proceed = false;
}
if(proceed) {
// If form validates, show downloads again and store value for return visits
$('#capture-form input').val('');
$('#capture-section').addClass('hide');
$('#download-section').removeClass('hide');
detailsEntered = 'true';
accessStorage('store', 'detailsEntered', 'true');
// Now open previously clicked download link in new tab
// DOES NOT WORK - Blocked by popup blocker
window.open(downloadLink, '_blank');
}
event.preventDefault();
return false;
});
//reset previously set border colors and hide all message on .keyup()
$("input, textarea").keyup(function() {
$(this).removeClass("error");
});
function accessStorage(action, dataKey, dataValue) {
if(typeof(Storage) === "undefined") {
// No support for localStorage/sessionStorage.
return false;
}
if (action == 'store') {
localStorage.setItem(dataKey, dataValue);
} else if (action == 'retrieve') {
return localStorage.getItem(dataKey);
}
}
});
A solution, if you don't need to open a new page, would be to simply change the location of the current page (means no popup issue) :
if(proceed) {
// If form validates, show downloads again and store value for return visits
$('#capture-form input').val('');
$('#capture-section').addClass('hide');
$('#download-section').removeClass('hide');
detailsEntered = 'true';
accessStorage('store', 'detailsEntered', 'true');
// Now open previously clicked download link in new tab
window.location.href = window.location.protocol + "//" + window.location.host + downloadLink; // if downloadLink is a relative URI
// window.location.href = downloadLink; // if downloadLink is an absolute URI
}

FormNavigate with confirm box yes no button

When a user leaves a JSP page, I need to display a confirmation with yes no button "You have unsaved changes. Do you want to leave it without saving?". If the user presses "ok", then the user goes to the page s/he is navigating to. Otherwise, if "no" is pressed, the user stays on the page. My code is here:
var formdata_original=false;
jQuery(".outConfirmPlugin").click(function () {
if (formdata_original == false) {
con();
}
return formdata_original;
});
function con() {
$.confirm({
'title':'',
'message':settings.jsMessage,
'buttons':{
'Yes':{
'class':'blue',
'action':function () {
formdata_original = true;
}
},
'No':{
'class':'gray',
'action':function () {
}
}
}
});
};
I know my error is: function "con" and "return formdata_original;" - they are not synchronized. How can i do this?
try return simple value from you function, i mean
action':function () {
return true;
}
and when you call 'con' function you will be able to write
formdata_original = con();
In this case you can not worry about sinhronize
The second option is creation global object that belongs ot window or $. So try
window["formdata_original"] = false
and in your code inside confirm dialog
window["formdata_original"]=true.

Categories