I am using jQuery to open a PDF in a new window or tab. For the most part, it works. I can click the link, and the PDF opens in a new tab.
The problem occurs when I open another PDF.
The new PDF will open, along with the previous PDF. By the time I get to the 5th PDF, there will be 4 additional tabs from the PDFs that I previously opened.
I am working with datatables. I click a link that contains data-attributes, which then opens a modal. From inside the modal is where I'll have another click event that will then open the PDF:
$('#resultsTable').on('click', 'tr > td > a.uploadDocs', function(e)
{
e.preventDefault();
$('#editForm input, select').val(''); // <- clear previous values
var editbooking = $(this).attr('data-editbooking');
var editpartnercode = $(this).attr('data-editpartnercode');
// open PDF click event
// takes vars editbooking and editpartner to build path and filename
$('#downloadPDF').on('click', function()
{
var pdf = '../PartnerUploads/' + editpartnercode + '/' + editbooking + ".pdf";
$.get(pdf)
.done(function()
{
window.open(pdf);
}).fail(function(textStatus)
{
if(textStatus.status == 404)
{
return false;
}
});
// *** edit ***
$('#downloadPDF').off('click');
});
});
All of the above works as far as navigating to the directory, and then opening the file. But it should not open all of the files that were previously opened.
How can I find why additional tabs are being opened when opening a PDF?
As mentioned in comments, you have nested event binding.
Every time you will click on #resultsTable, you will create a new event for #downloadPDF every single time, resulting in exponentially growing the number of tabs you open.
Use $('#downloadPDF').off('click') after window.open(pdf); and one inside fail(function(textStatus).
Solution:
$('#resultsTable').on('click', 'tr > td > a.uploadDocs', function(e)
{
e.preventDefault();
$('#editForm input, select').val(''); // <- clear previous values
var editbooking = $(this).attr('data-editbooking');
var editpartnercode = $(this).attr('data-editpartnercode');
// open PDF click event
// takes vars editbooking and editpartner to build path and filename
$('#downloadPDF').on('click', function()
{
var pdf = '../PartnerUploads/' + editpartnercode + '/' + editbooking + ".pdf";
$.get(pdf)
.done(function()
{
window.open(pdf);
$('#downloadPDF').off('click');
}).fail(function(textStatus)
{
if(textStatus.status == 404)
{
return false;
}
$('#downloadPDF').off('click');
});
});
});
Related
Hash anchor links fail to find/target ID DOM element target (and therefore fail to trigger JS UI tab change)
Hi visit https://eurosurveillance.org/content/10.2807/1560-7917.ES.2019.24.40.1900157 and scroll down the HTML fulltext (shown in this tab) and try clicking on the link marked 'Supplement 1' or 'Supplement 2' note nothing happens.
There is nothing clever about the links they are normal html hash links....
Supplement 1
Now if you visit the same page but this time do a hard reload with the following URL in the browser address bar https://eurosurveillance.org/content/10.2807/1560-7917.ES.2019.24.40.1900157#html_fulltext (notice the only change is the hash in the URL). Now try following the same instructions as before and you will notice that for some reason the anchor link is now followed and the anchor tab JS is triggered this is behaviour that I am expecting
Please advise. thanks in advance.
Hi many thanks the issue was resolved by refactoring the responsive-tabs.js code:
$(document).ready(function() {
//responsive tabs API code.
var Tabs = {
init: function() {
this.bindUIfunctions();
this.pageLoadCorrectTab();
},
bindUIfunctions: function() {
// Delegation
$(document)
.on("click", ".js-transformer-tabs a[href^='#']:not('.active, .disabled')", function(event) {
Tabs.changeTab(this.hash);
event.preventDefault();
})
.on("click", ".js-transformer-tabs a.active, .js-transformer-tabs a.disabled", function(event) {
Tabs.toggleMobileMenu(event, this);
event.preventDefault();
})
.on("click", ".js-textoptionsFulltext a.html:not('.disabled')", function(event) {
//console.log("tab?" + this.hash);
event.preventBubble=true;
var anchorTab = Tabs.changeTab(this.hash);
anchorTab.trigger("click"); //trigger click event in this case it will be html fulltext.
//event.preventDefault();
});
//We also need to handle the back state by telling the browser to trigger the tab behaviour!
$(window).on('popstate', function(e) {
anchor = $('[href="' + document.location.hash + '"]');
if (anchor.length > 0) {
Tabs.displayTab(anchor);
} else {
var defaultAnchor = $('.js-transformer-tabs li.active a');
if (defaultAnchor) {
Tabs.displayTab(defaultAnchor)
}
}
});
},
changeTab: function(hash) {
var anchor = $(".js-transformer-tabs a[href='" + hash + "']");
var activeTab = anchor.find('span strong');
Tabs.displayTab(anchor);
$(".js-dropdown li").hide();
$(".js-mobile-tab").text($(activeTab).text());
// update history stack adding additional history entries.
// pushState is supported!
history.pushState(null, null, hash);
// Close menu, in case mobile
return anchor; // make property available outside the function
},
pageLoadCorrectTab: function() {
//console.log("document.location.hash: " + document.location.hash);
if (document.location.hash.length > 0) {
// If the page has a hash on load, go to that tab
var anchor = $(".js-transformer-tabs a[href='" + document.location.hash + "']");
if (!anchor.hasClass("disabled")) {
var anchorTab = this.changeTab(document.location.hash);
// this is a further amendment to allow the fulltext and
//(any future event if its attached) to load when bookmarking a page with a particular tab.
anchorTab.trigger("click");
}
} else if ($(".js-transformer-tabs .active.tabIcon .active").length > 0) {
// go to which ever tab is defined as active in the JSP page and trigger a click on it
// but, only when no hash in the url
var activeTab = $(".js-transformer-tabs .active.tabIcon .active");
activeTab.trigger("click"); //trigger click
}
},
toggleMobileMenu: function(event, el) {
$(el).closest("ul").toggleClass("open");
},
displayTab: function(anchortab) {
var url = anchortab.attr("href");
//console.log("url" + url);
var divtabContent = $(url);
// activate correct anchor (visually)
anchortab.addClass("active").parent().siblings().find("a").removeClass("active");
// activate correct div (visually)
divtabContent.addClass("active").siblings().removeClass("active");
}
}
Modernizr.load([{
//test
test : Modernizr.history,
//if yes then do nothing as nothing extra needs loading....
//if no then we need to load the history API via AJAX
nope : ['/js/' + ingentaCMSApp.instanceprefix + '/vendor/history.min.js'],
complete : function() {
var location = window.history.location || window.location;
Tabs.init();
}
}])
});
//end of responsive tabs API code.
$(".js-select").click(function(){
$(".js-dropdown li").slideToggle();
});
I am doing one feature about showing alert on external link(apart from current domain) click. For that, I have written below code. All is working fine except below scenario.
$('a').each(function() {
var $a = jQuery(this);
if ($a.get(0).hostname && getDomain($a.get(0).hostname) != currentDomain) {
$a.click(function(event) {
//console.log($a.get(0));
//var myClasses = this.classList;
//console.log(myClasses.length + " " + myClasses['0']);
$("#redirectconfirm-modal").removeClass('hide');
if (!confirmed) {
event.preventDefault();
event.stopPropagation();
$modal.on('show', function() {
$modal.find('.btn-continue').click(function() {
confirmed = true;
$a.get(0).click();
$modal.modal('hide');
location.reload();
});
});
$modal.on('hide', function() {
$a.get(0).removeClass("selected");
confirmed = false;
});
$modal.modal('show');
}
});
}
});
Scenario which produces this issue:
Click on any external link from the site, it open a modal popup for redirection confirmation with continue & return button.
If I click on "Return" button it closes the modal popup.
Now, I am clicking on external link from my site, it open the modal again but this time I am clicking on "Continue" button & guess what, it open that external link in 3 different tabs
Actually on each anchor tag click, it saves whole anchor tag value. I think, if remove all these anchor tag values on modal close code i.e. $modal.on('hide', function() { }) it will resolve problem. I had tried with many different ways but still facing this issue.
Can you please provide solution/suggestion on that?
Problem is when you have 3 external links (as you probably have), than you set 3 times this part of code:
$modal.on('show', function() { ... });
$modal.on('hide', function() { ... });
which is wrong. Those events listeners should be set only once.
Some simplified code would look like this:
var $modal = $("#redirectconfirm-modal");
var currentDomain = 'blabla';
$modal.on('click', '.btn-continue', function(e) {
window.location = $modal.data('redirectTo');
});
$('a').each(function() {
var $a = jQuery(this);
if( $a.get(0).hostname && getDomain($a.get(0).hostname)!=currentDomain ) {
$a.click(function(e) {
$modal.data('redirectTo', $a.attr('href'));
$modal.modal('show');
});
};
});
Don't inline your events, you may try something like this:
$('a').each(function() { //add a class to all external links
var $a = jQuery(this);
if ($a.get(0).hostname && getDomain($a.get(0).hostname) != currentDomain) {
$a.addClass('modalOpen');
}
});
$('.modalOpen').not(".selected").click(function(event) { //open the modal if you click on a external link
event.preventDefault();
$('.modalOpen').addClass('selected'); //add class selected to it
$modal.modal('show');
});
$modal.on('hide', function() {
$('.selected').removeClass("selected");//remove the class if you close the modal
});
$('.btn-continue').click(function() {
$('.selected').click();//if the users clicks on continue open the external link and hide the modal
$modal.modal('hide');
});
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).
I'm still trying to master jQuery, AJAX, and JSON.
On my application, I have the following dropdown select menu:
<select id="serviceload" name="serviceload"></select>
I auto populate the OPTIONS with another function which I don't think is necessary to display here. Just know that the above SELECT has 1 or more OPTION values.
This is followed by the content section:
<div class="row" id="completeProfile">
// series of DIVS and TABLES
</div>
Initially, the content section is hidden, so the user will only see the dropdown menu:
$('#completeProfile').hide();
And now, the jQuery: this next piece of code is what I use when the user chooses a selection from the dropdown menu. Every time they pick a new selection, queries rerun, and new content is displayed to the screen, unless they select a blank OPTION.
$('#serviceload').change(function () {
var page = $('#serviceload').val();
if (page == "") {
$('#completeProfile').hide();
} else {
$.post('api/profileSearch.php', {
page: page
}, function (data) {
var obj = JSON.parse(data);
$('#portBody').empty();
var htmlToInsert = obj.map(function (item) {
return '<tr><td>' + item.PORT + '</td><td>' + item.NAME + '</tr>';
});
$('#portBody').html(htmlToInsert);
});
// I do several more $.post to return data into specific tables
// Take note of this next $.post
$.post('api/vesselSearch.php', {
page: page
}, function (data) {
var obj = JSON.parse(data);
$('#vesselinfo').empty();
var htmlToInsert = obj.map(function (item) {
return '<tr><td>Edit</td><td>' + item.VESSEL_NAME + '</td></tr>';
});
});
// after all the queries are ran, and the data is returned, now we show the content
$('#completeProfile').show();
}
});
In the vesselInfo portion above, there is section that prints a hyperlink with which you can click, and it opens a modal window. This is for editing purpose. This functions properly.
Here is where the issue lies.
Back in the content section, there is another hyperlink that opens a modal window to add a new vessel.
<h3>Vessels</h3> / Add New
This opens an Add New Vessel modal. In that modal there is a FORM with a button that reads like this:
<button type="button" id="addVesselSubmit">Add</button>
When this button is clicked, it sends the values entered by the user to a PHP script which updates a table.
$('#addVesselSubmit').click(function () {
var addservice = $('#addservice').val();
var addvessel = $('#addvessel').val();
$.post('api/addInfo.php', {
addservice: addservice,
addvessel: addvessel
}, function (data) {
// here is where my problem lies
if (data == 0) {
alert("Vessel was not saved");
} else {
alert("Vessel was saved");
// At this point, I need to rerun the main function above so that it shows the vessel that was added immediately to the content section without a page refresh
}
});
});
So in the code directly above, if the new record was successfully saved to the table, the whole content section should rerun without a page refresh, with the new record automatically showing in the vesselInfo section.
I think the code that is used to display the content needs to be turned into a main function that can be called when the addVesselSubmit is successful, but I am not sure how to proceed with that.
To reiterate my question: I need to be able to save a new record, and print the new record to the page without a page refresh.
$.post('api/addInfo.php', {
addservice: addservice,
addvessel: addvessel
}, function (data) {
// here is where my problem lies
if (data == 0) {
alert("Vessel was not saved");
} else {
alert("Vessel was saved");
// At this point, I need to rerun the main function above so that it shows the vessel that was added immediately to the content section without a page refresh
//Trigger a change on element
$('#serviceload').trigger('change');
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
}
});
I want to be able to focus the original page after opening a new window/tab, the same way as it's done on this website: http://www.vouchercodes.co.uk/laredoute.co.uk
Its when you click on the green button 'Get code and open site'.
the code is all there for you to see. I used firebug to find the <a> object that had the click event bound to the code that did the popup behind the main browser window. I scrolled down to look inside the global.js file and found this:
Basically the .blur() on the named popup window will pass focus back to the main window for browsers that support it and return false; will ensure the link doesn't open in the current window which is the default behaviour. Scroll down the code below and you'll see it towards the bottom.
// -- VoucherClick --
// This baby does the funky stuff when the user clicks to reveal the voucher code
(function($) {
$.fn.extend({
voucherClick: function(config) {
return this.each(function() {
// What is the objects parent?
var theObject = $(this);
if ($(this).hasClass('the-image')) {
var theParent = theObject.parent().parent();
} else {
var theParent = theObject.parent().parent().parent();
}
theObject.click(function() {
// Revealed codes have a light yellow background
// First we remove the background of any currently selected vouchers
$('.selected-voucher').css('backgroundColor','#fff').removeClass('selected-voucher');
// Now we add the yellow background. We have to check what was clicked as it affects
// how far up the DOM tree the voucher DIV starts
// We also must check if we are on an indiviual page with an expired voucher,
// because the yellow background can overlap the left hand edge of the voucher
if (theParent.parent().hasClass('individual-expired')) {
} else {
theParent.css('backgroundColor','#ffffee').addClass('selected-voucher');
}
// Check to see if the voucher has alread been revealed - we only want to run this
// if it hasn't yet been clicked
if (!theParent.data('voucherRevealed')) {
// Make a note that this voucher has been clicked
theParent.data('voucherRevealed', true)
// Make a note of the voucher code and create the revealed code module
var thisCode = theParent.find('strong').html();
// If the code is over 18 characters, we need to reduce the font size
if (thisCode.length > 8) {
thisCode = '<span class="revealedVoucherCode small">' + thisCode + '</span>';
} else {
thisCode = '<span class="revealedVoucherCode">' + thisCode + '</span>';
}
// Fade out the initial module and fade in the revealed voucher module
theParent.find('.code-wrapper').fadeOut('normal', function() {
// If it's an individual page there is no H3
if (theParent.find('h3').length == 0){
// So we add the revealed module after the dates
theParent.find('.dates').after('<div class="revealedVoucher">' + thisCode + '</div>');
} else {
theParent.find('h3').after('<div class="revealedVoucher">' + thisCode + '</div>');
}
theParent.find('.revealedVoucher').fadeIn();
})
}
// Open the merchant link in a new window
var mer_window = window.open(theObject.attr('href'), '_blank', 'toolbar=1,location=1,directories=1,scrollbars=1,resizable=1,status=1,menubar=1');
// Where browsers support it, let's pop this new window BEHIND the current window
if (typeof mer_window === "object") {
mer_window.blur();
}
// Reveal the What Just Happened Text, which was set up in the VoucherInit function
theParent.find('.what-just-happened').slideDown();
// Don't open the link in this current window
return false;
}); // end theObject click function
}) // end this.each function
} // end function(config)
}) // end $.fn.extend
}) (jQuery);
based on the above example, I've put together the following code, however click event doesn't work...
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script type="text/javascript">
(function($) {
$.fn.extend({
myClick: function(config) {
return this.each(function() {
var theObject = $(this);
theObject.click(function() {
var new_window = window.open(theObject.attr('href'), '_blank', 'toolbar=1,location=1,directories=1,scrollbars=1,resizable=1,status=1,menubar=1');
if (typeof new_window === "object") {
new_window.blur();
}
return false;
});
})
}
})
}) (jQuery);
$('.fade').myClick();
</script>
</head>
<body>
Google<br />
</body>
</html>