Force links to open in a new window - javascript

In our web site we have embedded PDFs, and we would like to make sure that when the user clicks a link inside the PDF, it opens in a new tab or window. We have no control over the PDFs so we cannot do anything with the links themselves.
Is it possible to intercept the request in some way, for example with onbeforeunload, and force the new page to open in a separate window?

No sorry, there is no way of doing this.
This is by design.
If it was possible it would be a major security breach.

You can manipulate the links inside the PDF document to run a javascript to open links in a new window/tab. Heres how I did it with C# and iTextSharp
public static MemoryStream OpenLinksInNewWindow(MemoryStream mySource)
{
PdfReader myReader = new PdfReader(mySource);
int intPageCount = myReader.NumberOfPages;
PdfDictionary myPageDictionary = default(PdfDictionary);
PdfArray myLinks = default(PdfArray);
//Loop through each page
for (int i = 1; i <= intPageCount; i++)
{
//Get the current page
myPageDictionary = myReader.GetPageN(i);
//Get all of the annotations for the current page
myLinks = myPageDictionary.GetAsArray(PdfName.ANNOTS);
//Make sure we have something
if ((myLinks == null) || (myLinks.Length == 0))
continue;
//Loop through each annotation
foreach (PdfObject myLink in myLinks.ArrayList)
{
//Convert the itext-specific object as a generic PDF object
PdfDictionary myLinkDictionary = (PdfDictionary)PdfReader.GetPdfObject(myLink);
//Make sure this annotation has a link
if (!myLinkDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.LINK))
continue;
//Make sure this annotation has an ACTION
if (myLinkDictionary.Get(PdfName.A) == null)
continue;
//Get the ACTION for the current annotation
PdfDictionary myLinkAction = (PdfDictionary)myLinkDictionary.Get(PdfName.A);
//Test if it is a URI action
if (myLinkAction.Get(PdfName.S).Equals(PdfName.URI))
{
//Replace the link to run a javascript function instead
myLinkAction.Remove(PdfName.F);
myLinkAction.Remove(PdfName.WIN);
myLinkAction.Put(PdfName.S, PdfName.JAVASCRIPT);
myLinkAction.Put(PdfName.JS, new PdfString(String.Format("OpenLink('{0}');", myLinkAction.Get(PdfName.URI))));
}
}
}
//Next we create a new document add import each page from the reader above
MemoryStream myMemoryStream = new MemoryStream();
using (Document myDocument = new Document())
{
using (PdfCopy myWriter = new PdfCopy(myDocument, myMemoryStream))
{
myDocument.Open();
for (int i = 1; i <= myReader.NumberOfPages; i++)
{
myWriter.AddPage(myWriter.GetImportedPage(myReader, i));
}
// Insert JavaScript function to open link
string jsText = "function OpenLink(uri) { app.launchURL(uri, true); }";
PdfAction js = PdfAction.JavaScript(jsText, myWriter);
myWriter.AddJavaScript(js);
myDocument.Close();
}
}
return new MemoryStream(myMemoryStream.GetBuffer());
}
I got most code from this answer: https://stackoverflow.com/a/8141831/596758

According to Aaron Digulla's answer, you can't actually do this without modifying the PDF reader. Sorry!
I think you can't do this without changing Acrobat Reader... I suggest ... some other PDF reader which doesn't use a "single document" UI. [Foxit Reader] uses tabs and can display several PDF documents.

Could this be of interest: JS to open pdf's in new window? I'm assuming that you can at least add JavaScript to the page. You shouldn't have to modify the PDF's themselves in order to open them in a new window, and even though you might not be able to modify the url's themselves you should be free to open those links in any fashion you want on your page. Or am I completely misunderstanding your question? :)

Related

Create a temporary file and open it in a new tab?

Let say I have a database with several products. I'm making a page to create printable export of that database. On the page the user can setup the export depending on his needs. For example, choosing what categories of products he want to exclude from it, how he want it to be sorted and so on.
He then click on a button making an ajax call with the chosen settings to a php script making the sql request and everything.
From there I would like to generate a temporary html page to visualize the result and open it in a new tab to be printed. But once it is done, I don't need it anymore. I could write the html file from my php script and make my ajax call to open the new file on another tab but that would create a new file everytime and take a lot of space.
What is the best way to achieve that ? The main problem is that my php script result in a very long string that can't be send in the url. tmpfile() don't allow me to open the created file in a new tab as it is deleted at the end of the script.
I tried using tempnam() like this :
$tmpfname = tempnam("../tmp/",$_SESSION['loggedUser']);
$handle = fopen($tmpfname, "w");
fwrite($handle, "long string being my html code");
fclose($handle);
$success = true;
$return_arr = array($success,$tmpfname);
And my ajax call :
$.post('../php/export_script.php',{:settings},function(data){
response = JSON.parse(data);
if (response[0] == true) {
var win = window.open('../landing.php?file='+response[1], '_blank');
if (win) {
win.focus();
} else {
alert("Browser blocked the opening of the file.");
}
}else{
alert(response[1]);
}
});
So that open the landing.php page that is like so :
<div id="content">
<?php
$handle = $_GET['handle'];
$fileData = #file_get_contents($handle);
echo $fileData
?>
</div>
But that open the new tab with the clear path of the file in the url like this
"https://mywebsite.com/landing.php?file=/home/myserver/myproject/tmp/userV4rIkE"
That looks unsafe to me, showing some clear server infos to the user. Is there a better way to achieve this ? I though about just creating a normal file in my tmp folder generating a random name with timestamp + user session code and setting up a way for my server to empty that folder every once in a while.
In the parent page, you can use javascript to create a new page, which gives you a way to write data into that new page - so just write the HTML from the parent into the new page. It does not need any URL at all (about:blank) should work fine.
const handle = window.open();
if (handle) {
// write HTML to child.
}

To get all the static hyperlinks from another view

Currently, I am able to get all the hyperlinks from the loaded page in the application. I have added the below code to the shared _Layout page in javascipt.
'''
var links = document.getElementByTagName("a");
var urls=[];
for (var i = 0;i<links.length;i++)
{
var datalink = new Object();
datalink.label=links[i].text;
datalink.value=links[i].getAttribute("href");
if (datalink.value.startswith("https://")) {
urls.push(datalink);
}
}
'''
What I want is that I should also be able to fetch the hyperlinks or the content from the other views (for example /Accounts/Index.cshtml) of the MVC application at the startup.
Any suggestions?

Is there a way to get the page count of a word doc?

Preferably I would like to do this in the browser with javascript. I am already able to unzip the doc file and read the xml files but can't seem to find a way to get a page count. I am hoping the property exist in the xml files I just need to find it.
edit: I wouldn't say it is a duplicate of Is there a way to count doc, docx, pdf pages with only js (without Node.js)? My question is specific to word doc/docx files and that question was never resolved.
Found a way to do this with docx4js
Here is a small sample parsing file from input elem
import docx4js from 'docx4js';
docx4js.load(file).then(doc => {
const propsAppRaw = doc.parts['docProps/app.xml']._data.getContent();
const propsApp = new TextDecoder('utf-8').decode(propsAppRaw);
const match = propsApp.match(/<Pages>(\d+)<\/Pages>/);
if (match && match[1]) {
const count = Number(match[1]);
console.log(count);
}
});
In theory, the following property can return that information from the Word Open XML file, using the Open XML SDK:
int pageCount = (int) document.ExtendedFilePropertiesPart.Properties.Pages.Text;
In practice, however, this isn't reliable. It might work, but then again, it might not - it all depends on 1) What Word managed to save in the file before it was closed and 2) what kind of editing may have been done on the closed file.
The only sure way to get a page number or a page count is to open a document in the Word application interface. Page count and number of pages is calculated dynamically, during editing, by Word. When a document is closed, this information is static and not necessarily what it will be when the document is open or printed.
See also https://github.com/OfficeDev/Open-XML-SDK/issues/22 for confirmation.
When you say "do this in the browser" I assume that you have a running webserver with LAMP or the equivalent. In PHP, there is a pretty useful option for .docx files. An example php function would be:
function number_pages_docx($filename)
{
$docx = new docxArchive();
if($docx->open($filename) === true)
{
if(($index = $docx->locateName('docProps/app.xml')) !== false)
{
$data = $docx->getFromIndex($index);
$docx->close();
$xml = new SimpleXMLElement($data);
return $xml->Pages;
}
$docx->close();
}
return false;
}

Bookmarklet/JavaScript to rotate URL

I want to create a Bookmarklet which will load one link out of a list of ten links, order doesn't matter, but weight-age does.
I tried http://www.htmlbasix.com/textrotator.shtml but it's for rotating a link on a webpage, how to make a Bookmarklet which will open a random URL from the list? Kind of URL rotator script within a bookmark.
Any efficient way to do that?
Thanks in advance.
You can't setup bookmarklet to run automatically. Consider writing browser extension or just use curl.
Not automatically.
Then it varies.
First, if you're 100% that pages don't redirect you anywhere you can try to use window.location inside you bookmarklet in next way:
var next = urls.indexOf(window.location.href) + 1;
next = next < urls.length ? next : 0;
window.location = urls[next];
If one of pages redirects or messes with url then you can use localStorage on your own domain and postMessage to store any data between bookmarklet calls.
I have found the solution after few tries
javascript: (function randomlinks() {
var myrandom = Math.round(Math.random() * 9);
var links = new Array();
links[0] = "http://www.javascriptkit.com";
links[1] = "http://www.dynamicdrive.com";
links[2] = "http://www.cssdrive.com";
links[3] = "http://www.codingforums.com";
links[4] = "http://www.news.com";
links[5] = "http://www.gamespot.com";
links[6] = "http://www.msnbc.com";
links[7] = "http://www.cnn.com";
links[8] = "http://news.bbc.co.uk";
links[9] = "http://www.news.com.au";
window.location = links[myrandom];
})()

Open link in new browser?

I have the following code below in a javascript file and need to have the link that is being generated open in a new window.
if (currentSearchType === 'extSearch') {
extSearchSearchValue = extSearchSearchInput.val();
window.location.href = replaceByObject(global.uhg.data['general'].body.extSearchSearchUrl, {
q: extSearchSearchValue
});
Normally with javascript I believe you'd use a window.open type of function, but not sure how to incorporate that with this type of code.
However you do it, opening a new browser window with javascript will most probably be blocked by popup blockers, so perhaps you should rethink your approach to the user himself clicking a regular link, then you can use target="...".
Just use a var to hold the URL and then pass it to window.open()...
if (currentSearchType === 'extSearch') {
extSearchSearchValue = extSearchSearchInput.val();
var url = replaceByObject(global.uhg.data['general'].body.extSearchSearchUrl, {
q: extSearchSearchValue
});
window.open(url, 'searchWindow');
}

Categories