pdf.js downloading as document.pdf instead of filename - javascript

I am using pdf.js library in my application.
It has integrated really well except for when i am trying to download the document. Everytime i download a specific file it gets downloaded as document.pdf
I have quite a lot of files to download and this is creating a bit of confusion.
My code goes as below:
<iframe src="pdf_viewer/web/viewer.html?file=/docs/resumes/1b763820-e262-4f76-8502-8872a3cb52e8&filename=sample.pdf"></iframe>
my first parameter is the file id and the second parameter is the name with which the document should be downloaded as.
Below code is the one present in the pdf viewer viewer.js file
function getPDFFileNameFromURL(url) {
var defaultFilename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'document.pdf';
console.log(url);
console.log(defaultFilename);
if (isDataSchema(url)) {
console.warn('getPDFFileNameFromURL: ' + 'ignoring "data:" URL for performance reasons.');
return defaultFilename;
}
var reURI = /^(?:(?:[^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
var splitURI = reURI.exec(url);
var suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
if (suggestedFilename.indexOf('%') !== -1) {
try {
suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
} catch (ex) {}
}
}
return suggestedFilename || defaultFilename;
}
From my understanding of the code, what i am doing regarding the input is right. Where could i be going wrong ?

i figured out the solution
<iframe src="pdf_viewer/web/viewer.html?file=/docs/resumes/1b763820-e262-4f76-8502-8872a3cb52e8?sample.pdf"></iframe>
This takes the input in the url, now i can extract filename from the url

Related

If else does not works properly

I have a Function (with help of other user of stackoverflow), but only the first if statement works, the second not. I want to take advantage of this code to get both: http and https followed or not by www
function formatURL() {
var url = document.getElementsByName("URL")[0];
var formattedURL = document.getElementsByName("formattedURL")[0];
url = url.value;
if (url.substr(0, 0) === "") // with our without www
{
formattedURL.value = "https://" + url;
return;
} else
{
formattedURL.value = "http://" + url;
return;
}
}
formattedURL.value = url;
}
You're running into this issue because url.substr(0,0) will always be an empty string "" for any string value of url (your if statement is always true).
Not sure what exactly you're trying to compare url.substr against because we don't have all the possible inputs you give to your <URL/> elements. Otherwise, I could have an actual fix for you.

D365 Error when calling function from another JS

I am having an issue calling JS function from another JS file.
Main JS where the function is defined.
var Common = Common || {};
Common.BaseAction = Common.BaseAction || {};
Common.BaseAction.SetNotification = function (message, level, uniqueId)
{
Xrm.Page.ui.setFormNotification(message, level, uniqueId);
}
Common.BaseAction.clearNotification = function (uniqueId) {
Xrm.Page.ui.clearFormNotification(uniqueId);
}
JS from where I am calling the function
var apItem = apItem || {};
apItem.BaseForm = apItem.BaseForm || {};
apItem.BaseForm.SetName = function ()
{
var bookName = Xrm.Page.getAttribute("ap_bookid").getValue()[0].name;
var condition = Xrm.Page.getAttribute("ap_condition").getText();
if (bookName !== null && condition !== null) {
Xrm.Page.getAttribute("ap_name").setValue(bookName + " - " + condition);
}
}
apItem.BaseForm.CountOverDueBy = function() {
var rentedTill = Xrm.Page.getAttribute("ap_rented_till").getValue();
var nowD = Date.now();
if (rentedTill !== null) {
var overdueBy = parseInt((Date.now() - rentedTill) / 86400000);
if (overdueBy > 0) {
Xrm.Page.getAttribute("ap_overdue_by").setValue(overdueBy);
Common.BaseAction.SetNotification("Book is Overdue by " + overdueBy
+ " Days.", "WARNING", "OverDueWarning");
}
else {
Xrm.Page.getAttribute("ap_overdue_by").setValue(null);
Common.BaseAction.clearNotification("OverDueWarning");
}
}
}
In the entity's form, I have added both above files with common.js being at the top and from the event handler I am calling function apItem.BaseForm.CountOverDueBy
Save + Published and Ctrl + F5 gives following error
ReferenceError: Common is not defined
at Object.apItem.BaseForm.CountOverDueBy (https://<domain>/%7B636651014350000438%7D/WebResources/ap_ItemFormBase.js?ver=2091450722:24:13)
at eval (eval at RunHandlerInternal (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:153:1), <anonymous>:1:17)
at RunHandlerInternal (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:159:1)
at RunHandlers (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:118:1)
at OnScriptTagLoaded (https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:233:1)
at https://<domain>/form/ClientApiWrapper.aspx?ver=2091450722:202:1
I have tried everything but nothing seems to be working.
The way you register the JS files in form, starting from common.js on top & then ap_ItemFormBase.js should work. But product team made few performance improvements around script files like lazy script loading/parallel script loading. This is little tricky & modern scripting is messy between different clients like UUI & web.
Like explained in blog post, if you set the pre-requisite js as dependency, it will load before you consume it in dependent files.
Open the ap_ItemFormBase.js web resource from solution (not from Form Properties), go to Dependencies tab & add the common.js. This will make sure file is ready before reference is used.

url with % doesn't get to api

Hi trying to get a signUrl from S3, for some reason making the call with % isn't parse correctly by my code. I get a 404 not found.
This is the ajax request:
https://stage.musicmarkers.com/website/api/admin/get-signed-url/thumbnail/magazine%2F2BE.gif/image%2Fgif
My API:
app.get('/website/api/admin/get-signed-url/thumbnail/:key/:type', auth.getMember, directives.noCache, getThumbnailSingedUrl);
My function:
function getThumbnailSingedUrl(req, res) {
if (!isAdmin(req, res)) {
return;
}
var key = req.params.key || '';
var type = req.params.type || '';
ThumbnailBucketFacade.getSignedUrl(
'putObject',
key,
type,
function onGotSignedUrl(error, result) {
if (error) {
RestResponse.serverError(res, error);
} else {
RestResponse.ok(res, result);
}
}
);
}
Making the call in a dev environment works.
Making the call without % environment works.
Same code exactly in a different project works.
Any ideas?
I believe what you have is encoded URI. So you need to decode it before using it:
const key = req.params.key && decodeURIComponent(req.params.key) || '';
const type = req.params.type && decodeURIComponent(req.params.type) || '';
More on decoreURIComponent here.
This is also backward compatible, so you don't have to worry that a plain string will get mangled.
So eventually it was a configuration issue at 'nginx', the 'nginx' router
was configured to add '/' at the end of the site name. That made all the
other slashes scrambled and ultimately to the call not to be recognise.
Thank's for those helping.

Implementation of a client-side 'require' function compatible with node.js

Having decided to implement all of my Javascript libraries as modules compatible with node.js, I've now put together a simple 'require' function to be used on the client side of things. I do realize that there are already plenty of very good implementations out there of this, but most seem fairly heavy-handed so I'm just opting to go with the "roll-your-own" approach.
Here's my 'require.js' file:
/*
A client-side script loading class designed to be compatible with node.js
*/
function require(filename)
{
try
{
var
script = null,
ajax = new XMLHttpRequest(),
index = filename.toLowerCase().indexOf('.js');
if(index <= 0 || index != filename.length - 3)
filename += '.js';
ajax.onload = function()
{
script = this.responseText;
};
ajax.open('GET', filename, false);
ajax.send();
return _isolate_script_(script);
}
catch(error)
{
return null;
}
}
function _isolate_script_(_script_)
{
return (new Function
(
'var exports = {}, module = {exports : null}; '
+ _script_ +
'; return module.exports || exports;'
)).call();
}
Example module ('example.js'):
/*
Example of a multiple-class export file
*/
exports.metallic = function(value)
{
return (Math.sqrt(4 + value * value) + value) / 2;
}
exports.inverse_metallic = function(value)
{
return exports.metallic(-value);
}
Example of a module consumer ('main.js'):
function main()
{
var
example = require('example');
if(example != null)
{
var
value = Math.floor(Math.random() * 100) + 1;
alert
(
'example.metallic(' + value + ') = ' + example.metallic(value)
+ '\n' +
'example.inverse_metallic(' + value + ') = ' + example.inverse_metallic(value)
);
}
else
alert('Error: cannot load "example"');
}
Finally, a basic HTML file that invokes our page logic:
<!DOCTYPE html>
<html>
<head>
<script src = 'require.js'></script>
<script src = 'main.js'></script>
</head>
<body onload = "main()"></body>
</html>
So my specific question is simply whether or not I've implemented everything correctly, and moreover if the framework and use-cases seem kosher enough?
It seems that you are trying to reimplement Browserify:
Browsers don't have the require method defined, but Node.js does. With Browserify you can write code that uses require in the same way that you would use it in Node.
If you want to implement a similar thing yourself then take a look at the Browserify source code.
See: https://github.com/substack/node-browserify
I'm just going to answer this myself.
The main issue is that older browsers sometimes freeze-up with synchronous ajax requests. Simply launching the entire 'main' function in it's own thread seems to be a good solution for that. That is, if some unforeseen issue arises with loading scripts then the page itself may not be responsive, but the browser should at least be unaffected. In other words, something along the lines of this:
<!DOCTYPE html>
<html>
<head>
<script src = 'require.js'></script>
<script src = 'main.js'></script>
</head>
<body onload = "setInterval(main)"></body>
</html>
As to concerns about throughput, I've now tested this with huge amounts of data (~100 MB) and it appears to make little difference on performance as to whether the code was loaded with a script tag or via the ajax call. All major browsers on two different operating systems and the results were pretty much the same. So unless I see convincing evidence to the contrary I'm just going to assume this to be the rule rather than the exception.
All that said, I'm certainly still open to any comments or criticisms that may be.
If you want module caching as well try this:
let parent = "";
let cache = {};
/**
* Load a JavaScript text synchronously.
*
* #param url The url.
*/
function cludge(url) {
/* resolve and check */
if (parent !== "")
url = new URL(url, parent).href;
let map = cache[url];
if (map !== undefined)
return map;
map = {};
cache[url] = map;
/* load and execute */
let back = parent;
try {
parent = url;
let request = new XMLHttpRequest();
request.open('GET', url, false);
request.send();
let fun = new Function("exports", "require", request.responseText);
fun(map, cludge);
} finally {
parent = back;
}
return map;
}
But the name resolution is not as elaborate as in nodejs.

Why does el.style.backgroundImage not work in this functional context?

I wrote an answer for this question: New background according to url, the code I posted in my answer was to check a URL for the presence of a particular string and, if it was there, change the background-image of a given element.
So! Me being me, I thought I'd try and avoid jQuery and go for a more traditional vanilla JavaScript approach with the following:
var images = {
'halloween' : '/images/newbackground.jpg',
'christmas' : '/images/xmasbackground.jpg'
};
var url = document.location.href,
elem = document.getElementById('elementThatYouWantToStyle');
for (var keyword in images){
if (images.hasOwnProperty(keyword) && url.indexOf(keyword) !== -1) {
elem.style.backgroundImage = images[keyword];
}
}
Source.
Which I then thought I'd convert to a functional approach, so it became this:
var images = {
'halloween': 'http://davidrhysthomas.co.uk/img/dexter.png',
'christmas': 'http://davidrhysthomas.co.uk/img/mandark.png'
};
function setBG(el, map, url) {
if (!el || !map) {
return false;
}
else {
var url = url || document.location.href,
el = el.nodeType == 1 ? el : document.getElementById(el);
for (var keyword in map) {
if (map.hasOwnProperty(keyword) && url.indexOf(keyword) !== -1) {
el.style.backgroundImage = encodeURIComponent(map[keyword]);
}
}
}
}
setBG('one', images, 'http://some.domain.com/with/halloween.jpg');
setBG(document.getElementById('two'), images, 'http://some.domain.com/with/christmas.jpg');
JS Fiddle demo.
Now, if I add a console.log() to the if assessment within the for...in loop it shows that we're getting into the loop, and the console suggests that I have an accurate reference to the DOM node, the images object, the URL (as passed into the function) and am getting the correct value from the object.
The following line, however, in which I attempt to set the el.style.backgroundImage property, does not work (this is true whether or not I wrap the map[keyword] in the encodeURIComponent() or not albeit I've linked only to the attempt in which I did. So: what's the obvious flaw in my logic? Why is el.style.backgroundImage not being set?
(Incidentally JS Lint, at JS Fiddle, seems happy with it (other than the redefinition of existing variables (url and el) done in order to have a fall-back/default).
You are declaring a local variable url with var url that already defined as an argument url and you also need to use the form url(http:/xxxx).
Change to this (removed var in front of url and added the url() around the url):
function setBG(el, map, url) {
if (!el || !map) {
return false;
}
else {
url = url || document.location.href;
el = el.nodeType == 1 ? el : document.getElementById(el);
for (var keyword in map) {
if (map.hasOwnProperty(keyword) && url.indexOf(keyword) !== -1) {
el.style.backgroundImage = 'url(' + map[keyword] + ')';
}
}
}
}
An URL is not a valid backgroundImage value unless you wrap it in a url().
el.style.backgroundImage = 'url(' + map[keyword] + ')';
Fiddle
Also, you should not encodeURIcomponent the whole URL, otherwise it will encode even the protocol's : and the /'s, resulting in a 404 as (due to the now lack of protocol) being interpreted as a relative URL:
GET http://fiddle.jshell.net/_display/http%3A%2F%2Fdavidrhysthomas.co.uk%2Fimg%2Fdexter.png 404 (Not Found)
Instead, to more safely encode a full URI you can use encodeURI:
el.style.backgroundImage = 'url("' + encodeURI(map[keyword]) + '")';
Fiddle
Note: MDN mentions that encodeURI may not work as expected in different browsers with GET requests, that is, URLs including query strings. I couldn't reproduce that problem though.
Also as noted by #jfriend00, the var keyword before url is unnecessary, as it already belongs to the function scope due to being declared as a formal parameter. Read more: JavaScript Scoping and Hoisting

Categories