How to retrieve Vector Tiles from Mapbox with d3.js and convert to geojson? - node.js

I am trying to replicate the example from Mike Bostock: https://observablehq.com/#d3/mapbox-vector-tiles
Since the language of Observable is not native Javascript, I am unable to get the example running.
Especially, the following two functions I am unable to get to work:
VectorTile = (await require("https://bundle.run/#mapbox/vector-tile#1")).VectorTile
Protobuf = require("pbf#3/dist/pbf.js")
require() is not a Javascript command. So, how can I get these two libraries?
What I tried:
Insert the libraries via <script></script> tags
Loading with await:
let VectorTile = await fetch('https://bundle.run/#mapbox/vector-tile#1.3.1');
let Protobuf = await fetch('https://unpkg.com/pbf#3.0.5/dist/pbf.js');
I am not sure if require() comes from node.js. So I played around with node.js but did not find a working solution either.
So, my question is: How can I get the example from Mike Bostock to work? Or in more general manner: How should I load vector tiles from Mapbox that I can convert them to geojson format as Mike is it doing in this example?

Regarding your first question, in order to get Mike Bostock's example to work you can keep in mind considerations:
Promises are something that Observable takes care of automatically, while node.js or JavaScript in browser does not, so you should take care of them
Add all the necessary libraries, while keeping in mind that the way you call them might be different from how Mike does so. As, for example, by default you should use Pbf, not Protobuf if you use pbf library (And yes require() comes from node.js)
For #mapbox/vector-tile library notice that it exports 3 objects, while you need VectorTile function (in node.js you could just use require().VectorTile). You can see how I've done it below for JavaScript in html
Finally you will need to insert generated svg code into html in order to display it, this is also something that Observable does automatically
I can't really tell how you 'should' load vector tiles, as I don't have much expertise in this particular aria. However, below I converted Mike Bostock's example to javascript, so you can see how it works outside of Observable.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
Map:
<div id='map'></div>
</div>
<script src="https://d3js.org/d3-array.v2.min.js"></script>
<script src="https://d3js.org/d3-geo.v2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-tile#1"></script>
<script src="https://d3js.org/d3-dsv.v2.min.js"></script>
<script src="https://d3js.org/d3-fetch.v2.min.js"></script>
<script src="https://unpkg.com/pbf#3.0.5/dist/pbf.js"></script>
<script src="https://bundle.run/#mapbox/vector-tile#1.3.1"></script>
<script>let VectorTile = _mapbox_vectorTile.VectorTile</script>
<script>
height = 600;
width = 954;
API_KEY = 'cfNfEQR1Qkaz-6mvWl8cpw';// Sign up for an API key: https://www.nextzen.org
projection = d3.geoMercator()
.center([-122.4183, 37.7750])
.scale(Math.pow(2, 21) / (2 * Math.PI))
.translate([width / 2, height / 2]).precision(0);
path = d3.geoPath(projection)
tile = d3.tile()
.size([width, height])
.scale(projection.scale() * 2 * Math.PI)
.translate(projection([0, 0]));
function filter({features}, test) {
return {type: "FeatureCollection", features: features.filter(test)};
};
function geojson([x, y, z], layer, filter = () => true) {
if (!layer) return;
const features = [];
for (let i = 0; i < layer.length; ++i) {
const f = layer.feature(i).toGeoJSON(x, y, z);
if (filter.call(null, f, i, features)) features.push(f);
}
return {type: "FeatureCollection", features};
}
tiles_pr = Promise.all(tile().map(async d => {
d.layers = new VectorTile(new Pbf(await d3.buffer(`https://tile.nextzen.org/tilezen/vector/v1/256/all/${d[2]}/${d[0]}/${d[1]}.mvt?api_key=${API_KEY}`))).layers;
return d;
}))
tiles_pr.then(
function(tiles){
//console.log(tiles)
map = `<svg viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">${tiles.map(d => `
<path fill="#eee" d="${path(geojson(d, d.layers.water, d => !d.properties.boundary))}"></path>
<path fill="none" stroke="#aaa" d="${path(geojson(d, d.layers.water, d => d.properties.boundary))}"></path>
<path fill="none" stroke="#000" stroke-width="0.75" d="${path(geojson(d, d.layers.roads))}"></path>
`)}
</svg>`
document.getElementById('map').innerHTML=map;
}
);
</script>
</body>
</html>

Related

How do I apply custom styling to custom google CAF receiver

documentation aint too clear on how to style custom CAF receiver(if at all possible). even when adding styling to head, styling is not applied. in chrome inspector, it is clear the styling is never applied.
const context = cast.framework.CastReceiverContext.getInstance()
const playerManager = context.getPlayerManager();
// unrelated code
// end
/***
* start player
* */
context.start()
body {
--playback-logo-image: url('res/logo.png');
}
cast-media-player {
--theme-hue: 180;
--progress-color: rgb(255, 255, 255);
--splash-image: url('res/background-2.png');
--splash-size: cover;
}
<html>
<head>
<script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js">
</script>
<link rel="stylesheet" href="css/receiver.css" media="screen" />
</head>
<body>
<cast-media-player id="player"></cast-media-player>
<script type="text/javascript"
src="js/receiver.js">
</script>
</body>
</html>
I am still new at this so someone please correct me if I am wrong.
I think the "styling" is used when modifying the basic receiver that is available. If you are creating a custom receiver you must do so from scratch.
Since you are using the cast-media-player element I feel like you are looking to customize the ui appearance of the basic receiver.
It appears (from looking at the documentation) that you are missing this code in the js file.
from: https://developers.google.com/cast/docs/caf_receiver/customize_ui
// Update style using javascript
let playerElement = document.getElementsByTagName("cast-media-player")[0];
playerElement.style.setProperty('--splash-image', 'url("http://some/other/image.png")');
Edit: Sorry after looking back at it that is for changing the style using Javascript as apposed to CSS.

Simple SVG project cause error on Internet Explorer 11

I am learning svg and would like to compare displaying svg items on different browsers. My code works fine on firefox, chrome, edge, safari etc, but cannot work on ie11. Unfortunately application I develop needs to support ie11 so I need to force my code to work correctly.
Here is fiddle: https://jsbin.com/hemawaboqa/1/edit?html,js,output
HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/#svgdotjs/svg.js"></script>
</head>
<body>
<div style="position:absolute;left:0px;top:0px;right:0px;bottom:0px;overflow:hidden;" id="svg-main-container">
<div style="position:absolute;left:0px;top:0px;bottom:0px;right:300px;border:1px solid #dadada;overflow:auto;" id="svg-canvas"></div>
</div>
</body>
</html>
JS
var draw = SVG().addTo('#svg-canvas').size(400, 400)
var rect = draw.rect(100, 100)
Why that code is not working on ie11?
I have created a sample using the SVG.js 3.0 version with your code, it will show the "Object doesn't support property or method 'from'" in IE11 browser, perhaps the issue is related to the svg.js version, and it is a plugin issue, you could feedback this issue to SVG.js forum.
Besides, I suggest you could refer to the following code, to use the old version of SVG.js:
<!DOCTYPE html>
<html lang=en-us>
<head>
<meta charset=utf-8>
<title>TEST</title>
</head>
<body>
<div style="position:absolute;left:0px;top:0px;right:0px;bottom:0px;overflow:hidden;" id="svg-main-container">
<div style="position:absolute;left:0px;top:0px;bottom:0px;right:300px;border:1px solid #dadada;overflow:auto;" id="drawing">
</div>
</div>
<script src=https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.6/svg.min.js></script>
<script>
(function () {
'use strict';
// Add title as first child of SVG element:
var createTitle = function (svgObject, text) {
var fragment = document.createDocumentFragment();
var titleElement = document.createElement('TITLE');
fragment.appendChild(titleElement);
titleElement.innerHTML = text;
svgObject.node.insertAdjacentElement('afterbegin', titleElement);
};
SVG.extend(SVG.Doc, {
namespace: function () {
return this
.attr({xmlns: 'http://www.w3.org/2000/svg', version: '1.1'})
.attr('xmlns:xlink', SVG.xlink, SVG.xmlns);
}
});
var draw = new SVG('drawing').size(300, 300);
var rect = draw.rect(100, 100).attr({fill: '#f06'});
// Add title to SVG element
createTitle(draw, 'Rectangle');
}());
</script>
</body>
</html>
The result as below:
The library you are using has ECMA 6 elements that are not understood in IE.
If you need your project to work in IE, you will have to use another library or find out how to change it so it allows for older browsers (as suggested here: https://svgjs.dev/docs/3.0/compatibility/)

snap svg try to rotate an object with center point but not work

I learn to use snap svg this library and want to rotate an object. However, I get a weird rotate effect and can't find what the problem is.
the following is the code snippet and you can have it a look.
var s = Snap("#container");
//lets draw 2 rects at position 100,100 and then reposition them
var r = s.rect(100,100,100,100).attr({fill: 'red' });
var g = s.group(r);
var bbox = g.getBBox();
s.text(20, 20, bbox.cx);
s.text(20, 40, bbox.cy);
g.animate({ transform: 'r180,'+ bbox.cx + ',' + bbox.cy }, 1000, mina.bounce );
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
</head>
<body>
<div style="width: 335px; height: 600px;">
<svg width='100%' height='100%' id='container'></svg>
</div>
</body>
</html>
Hope somebody can tell me :)
I think there's a bug in Snap 0.5/0.5.1 see here.
First thing I would do, is try Snap 0.4.1 eg here and see if that fixes it. I think it's fixed for 0.5.2, but not sure if that's available yet.
If it doesn't fix it, update the question to mention you have also tried 0.4.1.

Add material to mesh from node server

While I understand many of you may not have messed around with OWF (Ozone Widge Framework), it's merely wigetized html pages that communicate through a subscription service on the server.
Simple example I'm working with: http://blog.thematicmapping.org/2013/10/textural-terrains-with-threejs.html
I can successfully add a texture via THREE.ImageUtils.loadTexture() while navigating to the html page in Google Chrome. However, when I use OWF in Google Chrome and point my widget to the html page, I can only get it to load the mesh. If I attempt to load the texture, it's completely black. Therefore, it has nothing to do with (chrome --allow-file-access-from-files). I have verified this happens for the few examples I've tried from threejs.org. Obviously, it has something to do with the OWF implementation, but I was under the impression that these frameworks inherited the properties of the browser it was being run in (I could be completely wrong)... therefore, I assumed it would work.
EDIT: I made the poor mistake of assuming it was the widgetized framework causing the trouble. I linked one of the widgets directly to the node website and could not successfully render the terrain material. Then, I tried accessing it through a node.js server with no success.
Here's the code if anyone can tell me why it's black....
<!doctype html>
<html lang="en">
<head>
<title>three.js - Jotunheimen</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body { margin: 0; overflow: hidden; }
</style>
</head>
<body>
<div id="webgl"></div>
<script src="jsANDcss/3D/three.min.js"></script>
<script src="jsANDcss/3D/TrackballControls.js"></script>
<script src="jsANDcss/3D/TerrainLoader.js"></script>
<script>
window.addEventListener( 'resize', onWindowResize, false );
var width = window.innerWidth,
height = window.innerHeight;
var scene = new THREE.Scene();
/*scene.add(new THREE.AmbientLight(0xeeeeee));*/
var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
camera.position.set(0, -30, 30);
var controls = new THREE.TrackballControls(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
var material;
var texture;
var terrainLoader = new THREE.TerrainLoader();
terrainLoader.load('jsANDcss/3D/jotunheimen.bin', function(data) {
var geometry = new THREE.PlaneGeometry(60, 60, 199, 199);
for (var i = 0, l = geometry.vertices.length; i < l; i++) {
geometry.vertices[i].z = data[i] / 65535 * 5;
}
var texture = THREE.ImageUtils.loadTexture('jsANDcss/3D/jotunheimen-texture.jpg');
var material = new THREE.MeshPhongMaterial({
map: texture
/*wireframe: true*/
});
var plane = new THREE.Mesh(geometry, material);
material.needsUpdate = true;
scene.add(plane);
});
render();
document.getElementById('webgl').appendChild(renderer.domElement);
function render() {
controls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
}
</script>
</body>
</html>
If you use MeshPhongMaterial, you need to add a light to the scene. If you do not want to add a light, then use MeshBasicMaterial.
Also, do not set material.needsUpdate = true;. The loader does that for you. Loading is asynchronous, and the needsUpdate flag needs to be set at the right time.
Consider adding the plane to the scene in the loader callback, instead.
Also, if you are modifying the vertices, you need to recompute some things:
geometry.computeCentroids();
geometry.computeFaceNormals();
geometry.computeVertexNormals(); // required if you want your terrain "smooth"
three.js r.62

Prevent PDF file from downloading and printing

I am trying to find a way to prevent a PDF from being printed or downloaded when view from web. Also, it is prefered that user cannot print screen.
I am thinking about converting those PDF files to Flash. Any other ideas?
Okay, I take back what I commented earlier. Just talked to one of the senior guys in my shop and he said it is possible to lock it down hard. What you can do is convert the pdf to an image/flash/whatever and wrap it in an iFrame. Then, you create another image with 100% transparency and lay it over top the iFrame (not in it) and set it to have a higher Z-value than the iFrame.
What this will do is that if they right click on the 'image' to save it, they will be saving the transparent image instead. And since the image 'overrides' the iFrame, any attempt to use print screen should be shielded by the image, and they should only be able to snapshot the image that doesn't actually exist.
That leaves only one or two ways to get at the file...which requires digging straight into the source code to find the image file inside the iFrame. Still not totally secure, but protected from your average user.
Ultimately you will need to:
Create Images for each page
Present those to the user on the web via your own interface (html, flash etc)
Keep in mind flash wont work on Apple devices if that's required.
A print screen will allow someone to recreate the low res image you present, and in this case you could add a watermark to the image.
That is not possible. Reading is downloading. When a user is reading a file, browser is downloading that file to temp. So even if you disable the download button, the user can click "File -> Save As" or copy that file from temp folder.
There are a few things you can do:
Method 1
The following code will embed a PDF without any toolbars and hide the print/download icons
<embed src="{URL_TO_PDF.PDF}#toolbar=0&navpanes=0&scrollbar=0" width="425" height="425">
Method 02
Using Google Drive
Right click on pdf and goto Share(below image)
Then go to Advanced option in left bottom
Tick Both check boxes. After copy embed link and paste it to your src. No download and Save drive option is not allowed
If you encrypt the PDF you can control how printable and changeable it is.
Print settings:
None
Low res (150 dpi)
high res (max dpi)
You can also prevent folks from copying/pasting from your PDF, and even do that while allowing screen readers access (visually impaired folks can still read your PDFs).
You haven't mentioned what you're using to build the PDFs so the details are up to you.
Alternative: You can create annotations that are only visible when printing. Create a solid box over the entire page that only shows up when printed -> No useful printing.
You might be able to do the same thing with layers (Optional Content Groups) as well, not sure.
Creating a video with QuickTime's screen capture or anything similar kind of defeats all the effort to protect your document file from being copied.
if you want to provide a solution, well, there just isn't one. You would have to be able stop the user running a program that can access the buffers in the GPU to prevent them grabbing a screen shot. Anything displayed on the screen can be captured.
If you decide to send a file where the contents are not accessible online, then you need to rely on the security that the end product/application uses. This will also be completely breakable for an extremely determined pserson.
The last option is to send printed documents in the post. The old fashioned way using a good courier service. Costs go up, time delays are inevitble - but you get exactly what you are after. A solution is not without its costs.
Always happy to point out the obvious :)
I wish I had an answer but I only have Part of one. And I cannot take credit for it but the way to get it is below.
This is a more serious issue than it is being given credit for from the sound of the replies. Everyone is automatically assuming that the content that needs protection is for public consumption. This is not always the case. Sometimes there are legal or contractual reasons that require the site owner to take all possible measures to prevent downloading the file. The most obvious one I can think of has already brought up. The “Action Option Bar” presented by the browser to on almost any file you can left click.
Adobe DRM does nothing about that and worse, Adobe Acrobat cannot even have its own abilities to “Save” blocked as part of the “DRM” protection. This option comes up even in Reader no matter what other security selections you have chosen.
In our case, Adobe Acrobat was purchased solely to provide some degree of protection for their own format. It is hard to believe that Adobe will let you prevent printing, prevent editing, prevent even opening without a password or you can really go all out and use a certificate for your encryption. Yet they have no options to prevent saving at any point, anywhere. Instead offering the consolation of telling you “Don’t worry: The copy they download without your permission will also have the same DRM on it as well”. Unfortunately that was not the sole purpose of the purchase and half a solution is no “solution” at all.
There are probably 100 programs that are actually sold just to remove the DRM from Adobe documents and even if not, the point was that the client specified that no downloads be allowed even by users who had access to the private site. Therefore the need to prevent the download to start with is not so hard to understand. While conversion to FLASH may give you the download protection, you lose all the rest. Unless I can find a way to prevent opening, saving etc for a Flash File. Next, is it possible to password protect a Flash file from opening when clicked on?
The “partial fix” that I was finally able to get to work as needed still only disables all the “right click” functions but it does include a nice “Warning Box” where I can explain that the User has already agreed NOT to download, print, save and so on just to have access to the page. I am not sure if I could post the code here or whether it is acceptable to paste links either but a Google search for "Maximus right click" will take you to it. And it was one of several examples, it just happened to be the one I could implement the easiest and worked better than the others. Credit where credit is due.
Another option I was given by someone was a product called “Flipping Book”. And the user above suggestions for “Atalasoft” ( I had already found that and have sent a request for more information). Hopefully it will be “The Solution” and I can implement it in time to help. It seems to me that this is a place where there is an obvious need for a one-step packaged solution and usually "The Laws of Nature" take care of such an Imbalance in short order. Yet my research has taken me through many years of posters all asking for the same thing. Looks like someone would be able to make a nice living off a “simple” way to add a little more "protection" to “PDFs” (or other documents, images etc) for the people who obviously are in need of it. If I find it, and it works, I'm buying it. :>)
I wish I had skills as a programmer because I have some pretty good ideas of ways to implement such a product, unfortunately, I do not know how to put these ideas into practical use.
Although we should agree that ultimately you cannot prevent some form of document capture (specially through screen capture technology either through phone or computer), the goal is to prevent direct download of original document. Some suggest you turn it into images, but this is not necessary. There is clearly a way, as several cloud services allow you to share pdf files, removing the download option, without converting the PDF to images (a superior method because it retains important properties like word search). Personally, as a user of Outlook email, I use the cloud service it provides, OneDrive. I just want to share the HTML code produced by OneDrive to share PDF files without download and right-click support. I am no expert on HTMl so cannot tell you exactly how it is done, but it might still provide you some insights. Here is the code for one particular PDF I shared (without private information and other bits that seemed unnecessary to me):
<!DOCTYPE html>
<html lang="en-us" dir="ltr">
<head><meta name="GENERATOR" content="Microsoft SharePoint" /><meta http-equiv="Content-type" content="text/html; charset=utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta http-equiv="Expires" content="0" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" /><title>
OneDrive for Business
</title><link rel="shortcut icon" href="/_layouts/15/images/odbfavicon.ico?rev=47" type="image/vnd.microsoft.icon" id="favicon" /></head>
<body style="margin: 0; padding: 0;">
<script nonce= '55c3d852-fe79-49b0-927d-e793a0ba3192' >if(!spfxPerfMarks){var spfxPerfMarks = {};} var markPerfStage=function(key) {if(window.performance && typeof window.performance.now === 'function'){spfxPerfMarks[key]=window.performance.now();} else{spfxPerfMarks[key]=Date.now();} if (window.performance && typeof window.performance.mark === 'function') {window.performance.mark(key);}};</script><script type="text/javascript" id="SuiteNavShellCore" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192" crossorigin="anonymous" src="https://shellprod.msocdn.com/api/shellbootstrapper/business/oneshell">
</script><script type="text/javascript" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192">
window.document.getElementById('SuiteNavShellCore').addEventListener('error', function() {
var scriptElem = document.getElementById('SuiteNavShellCore');
scriptElem.parentNode.removeChild(scriptElem);
var newScript = document.createElement('script');
newScript.setAttribute('type', 'text/javascript');
newScript.setAttribute('id', 'SuiteNavShellCore');
newScript.setAttribute('src', 'https://shellprod.msocdn.com/api/shellbootstrapper/business/oneshell');
newScript.setAttribute('crossorigin', 'anonymous');
newScript.async = true;
newScript.addEventListener('load', function() { (typeof markPerfStage === 'function' && markPerfStage('suiteNavScriptAsyncEnd')); if (window.executeSuiteNavOnce) { window.executeSuiteNavOnce() } });
newScript.addEventListener('error', function() { window.o365ShellScriptLoadError = arguments[0]; (typeof markPerfStage === 'function' && markPerfStage('suiteNavScriptError')); if (window.executeSuiteNavOnce) { window.executeSuiteNavOnce() } });
document.head.appendChild(newScript); });
</script><script type="text/javascript" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192">
window.o365ShellLoadPromiseResolve = undefined; window.o365ShellLoadPromiseReject = undefined; window.o365ShellRenderPromiseResolve = undefined; window.o365ShellRenderPromiseReject = undefined; window.o365ShellPostRenderPromiseResolve = undefined; window.o365ShellPostRenderPromiseReject = undefined; window.o365ShellLoadPromise = new Promise(function (loadResolve, loadReject) { window.o365ShellLoadPromiseResolve = loadResolve, window.o365ShellLoadPromiseReject = loadReject }); window.o365ShellRenderPromise = new Promise(function (renderResolve, renderReject) { window.o365ShellRenderPromiseResolve = renderResolve, window.o365ShellRenderPromiseReject = renderReject }); window.o365ShellPostRenderPromise = new Promise(function (prResolve,prReject) { window.o365ShellPostRenderPromiseResolve = prResolve, window.o365ShellPostRenderPromiseReject = prReject });var executeSuiteNav = function () {var suiteNavPlaceholder = document.createElement('div');suiteNavPlaceholder.id = 'SuiteNavPlaceholder';suiteNavPlaceholder.style = "min-height: 50px";document.body.insertBefore(suiteNavPlaceholder, document.body.firstChild);if (window.o365ShellScriptLoadError) {o365ShellLoadPromiseReject(window.o365ShellScriptLoadError);o365ShellRenderPromiseReject(new Error('SuiteNavLoadError'));o365ShellPostRenderPromiseReject(new Error('SuiteNavLoadError'));return; }o365ShellLoadPromiseResolve();var themeData;try { themeData = JSON.parse(localStorage.getItem('odSuiteNavthemedata')).themeData; }catch(err) { themeData = {Primary:'#0078D4'}; }(typeof markPerfStage === 'function' && markPerfStage('suiteNavRenderAsyncStart'));O365Shell.RenderAsync({top: 'SuiteNavPlaceholder', layout: 'Mouse', enableSearchUX: true, initialSearchUXVisibility: true, initialSearchUXPlaceholderText: 'Search', initialSearchUXSearchText: "",enableDelayLoading: true, collapseO365Settings: true, disableDelayLoad: false, disableShellPlus: false, isThinHeader: false, enableLegacyResponsiveBehavior: false, expectSearchBoxSettings: true, shellDataOverrides: {}, supportShyHeaderMode: false, initialRenderData: { AppBrandTheme: themeData, Culture: 'en-US', CurrentMainLinkElementId: 'ShellDocuments', IsConsumer: false, UserDisplayName: 'JOHN DOE', UserID: '100320009e7b358d', WorkloadId: 'Sharepoint', ShellBootHost: 'https://shellprod.msocdn.com', EnableVanillaSearchBox: true }},function () {(typeof markPerfStage === 'function' && markPerfStage('suiteNavRenderAsyncEnd'));o365ShellRenderPromiseResolve();},function () {(typeof markPerfStage === 'function' && markPerfStage('suiteNavPostRender'));o365ShellPostRenderPromiseResolve();},function (error) {(typeof markPerfStage === 'function' && markPerfStage('suiteNavRenderAsyncErrorEnd'));o365ShellRenderPromiseReject(error); o365ShellPostRenderPromiseReject(error);});};
</script><script type="text/javascript" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192">
var params = window.location.search.substring(1).split('&') || [];
var shouldExecuteSuiteNav = true;
shouldExecuteSuiteNav &= params.indexOf('p=2') === -1;
shouldExecuteSuiteNav &= params.indexOf('cl=true') === -1;
shouldExecuteSuiteNav &= params.filter(function (x) { return x.indexOf('parent') === 0; }).length === 0;
try { shouldExecuteSuiteNav &= window.parent === window; } catch(err) { shouldExecuteSuiteNav = false; }
if (shouldExecuteSuiteNav) { executeSuiteNav(); }
</script>
</body>
<script type="text/javascript">
try {
(function() {
var a = navigator.userAgent.toLowerCase();
var i = a.indexOf("msie");
if (-1 !== i) {
var v = parseInt(a.substring(i + 5));
if (v <= 8 && Boolean(document.documentMode) && document.documentMode <= 8) {
var d = new Date(); d.setTime(d.getTime() + 31536000000);
document.cookie = "odbnu=0;expires=" + d.toUTCString() + ";path=/";
window.location.href = window.location.href.replace(/\/onedrive\.aspx/i, '/start.aspx#/Documents/Forms/All.aspx');
}
}
})();
} catch(e) {}
</script>
<script type="text/javascript" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192">
SOME PRIVATE STUFF HERE
</script><link rel="preconnect" href="https://spoprod-a.akamaihd.net" crossorigin /><script type="text/javascript">
!function(){if('PerformanceLongTaskTiming' in window){var g=window.__tti={e:[]};g.o=new PerformanceObserver(function(l){g.e=g.e.concat(l.getEntries())});g.o.observe({entryTypes:['longtask']})}}();
</script><script type="text/javascript">
var g_responseEnd = new Date().getTime();window['FabricConfig'] = { fontBaseUrl: ''};window['__odsp_culture'] = 'en-us';window['__odspSriHashes'] = {"listviewdataprefetch-mini-c82c051f.js":"sha256-GCNR9Rk+cuSJfvbszuhs5ZBaUs5tQ2RdzzJTteHOXGk=","reactandknockout-mini-584215d6.js":"sha256-ICjqvvD9qHiKbj5xYFNGC/JsgNcqNRRL1t3kW4RVioI=","aria-mini-2e5a74c4.js":"sha256-CbCwYga9yHE+t1OvB+NHHDdH2rxSfY6KJkCMiUpXQjw=","spectreviewer-mini-9c641fce.js":"sha256-tqmAhKxEONjZOpZuGrbo8VdnLx6kRH+Xfhjrcchv2+4=","babylonjs-mini-22e57381.js":"sha256-T6IgL4CdkolwNC0L4tG6d+G07Bhuc7bI1pSIShdrTUk=","sp-http_odb-mini-21a5eb98.js":"sha256-mTfdqB83ALG/d2z8krhrUugjXBzFQ/bzPfUIgcayACg=","onedriveappfontsplt-mini-ce0e18ec.js":"sha256-+ockQ4cjstrmVqBPVRH8C9Z9M0ZJbyQxHQ/cm/ukBOI=","onedriveappfontsdeferred-mini-3771cbb9.js":"sha256-qXZjhCWJDNPCbbXRIwDt1cqIyqzQKqROnwdASmSsoGw=","odbonedriveapp-mini-11081db7.js":"sha256-j/CkxuEVbtMOL5PRKZ05dZURZ/aNH9tk6vnMj6ei/lk=","en-us/
</script><script type="text/javascript">
window['moduleNameMapping']={"odsp-next/providers/operation/OperationProvider":"Rq"};
</script><script type="text/javascript" data-import-link="https://spoprod-a.akamaihd.net/files/odsp-common-library-prod_2019-02-15_20190219.002/require.js" id="requireJsString">
SOME VERY LONG FUNCTION CODE
</script><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/listviewdataprefetch-mini-c82c051f.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/reactandknockout-mini-584215d6.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/odbonedriveapp-mini-11081db7.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/en-us/odbonedriveapp-mini.resx-7f957d5c.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/odbonedrive-mini-5e8b1855.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/en-us/odbonedrive-mini.resx-374bb468.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/odbfiles-mini-9aaee23c.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/en-us/odbfiles-mini.resx-250da06d.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/odbitemsscope-mini-5070e33c.js" rel="preload" crossorigin="anonymous" as="script" /><link href="https://spoprod-a.akamaihd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/en-us/odbitemsscope-mini.resx-ff223e24.js" rel="preload" crossorigin="anonymous" as="script" /><script type="text/javascript" id="requireConfig">
!function(){
var backupBaseUrl = 'https://az741266.vo.msecnd.net/files/odsp-next-prod-amd_2020-06-12_20200612.001/';
window.__backupBaseUrl = backupBaseUrl;
var failOverState = window.__cdnFailOverState = {
baseUrlFailedOver: false,
modulesFalledBack: []
};
function processConfigToSupportFailOver(config) {
var paths = {};
for (var bundleId in config.bundles) {
var bundlePath = config.paths[bundleId];
var fallbackPaths = [bundlePath, backupBaseUrl + bundlePath];
for (var _i = 0, _a = config.bundles[bundleId]; _i < _a.length; _i++) {
var moduleName = _a[_i];
paths[moduleName] = fallbackPaths;
}
}
return {
paths: paths,
shim: config.shim,
deps: config.deps,
baseUrl: config.baseUrl,
waitSeconds: config.waitSeconds,
onNodeCreated: config.onNodeCreated,
enforceDefine: config.enforceDefine,
onPathFallback: function (options) {
var moduleId = options.moduleId;
var config = options.config;
if (moduleId && config && config.deps && config.deps.indexOf(moduleId) >= 0) {
var failedModules = failOverState.modulesFalledBack;
failedModules.push(moduleId);
if (!failOverState.baseUrlFailedOver && failedModules.length >= 2) {
require.config({
baseUrl: backupBaseUrl
});
failOverState.baseUrlFailedOver = true;
}
}
}
};
}
var config = {paths:{"listviewdataprefetch-mini":"listviewdataprefetch-mini-c82c051f","reactandknockout-mini":"reactandknockout-mini-584215d6","aria-mini":"aria-mini-2e5a74c4","spectreviewer-mini":"spectreviewer-mini-9c641fce","babylonjs-mini":"babylonjs-mini-22e57381","sp-http_odb-mini":"sp-http_odb-mini-21a5eb98","onedriveappfontsplt-mini":"onedriveappfontsplt-mini-ce0e18ec","onedriveappfontsdeferred-mini":"onedriveappfontsdeferred-mini-3771cbb9","odbonedriveapp-mini":"odbonedriveapp-mini-11081db7","odbonedriveapp-mini.resx":"en-us/odbonedriveapp-mini.resx-7f957d5c","odbonedrive-mini":"odbonedrive-mini-5e8b1855","odbonedrive-mini.resx":"en-us/odbonedrive-mini.resx-374bb468","odbbasepage-mini":"odbbasepage-mini-8d7dea71","odbfiles-mini":"odbfiles-mini-9aaee23c","odbfiles-mini.resx":"en-us/odbfiles-mini.resx-250da06d","odbuploadmanager-mini":"odbuploadmanager-mini-168f0ee8","odbuploadmanager-mini.resx":"en-us/odbuploadmanager-mini.resx-660b735c","odbreactcontrols-mini":"odbreactcontrols-mini-6f323ced","odbreactcontrols-mini.resx":"en-us/odbreactcontrols-mini.resx-c7ec26e2","odbdeferred-mini":"odbdeferred-mini-b9def3da","odbdeferred-mini.resx":"en-us/odbdeferred-mini.resx-d1f98f82","odblivepersonapicker-mini":"odblivepersonapicker-mini-414c6f81","odbdebugwindow-mini":"odbdebugwindow-mini-2f4ef22c","odbfilepicker-mini":"odbfilepicker-mini-2f5a2203","odbfilepicker-mini.resx":"en-us/odbfilepicker-mini.resx-3562db06","odbembed-mini":"odbembed-mini-8638d6c3","odboneup-mini":"odboneup-mini-3086899d","odboneup-mini.resx":"en-us/odboneup-mini.resx-a7d40d5e","odbpdf-mini":"odbpdf-mini-7d046eb1","odbpdf-mini.resx":"en-us/odbpdf-mini.resx-e5e07b77","odbwrs-mini":"odbwrs-mini-2c0b0a8b","odbsharepage-mini":"odbsharepage-mini-e62fc2f8","odbtextfileeditor-mini":"odbtextfileeditor-mini-000ede78","odbtextfileeditor-mini.resx":"en-us/odbtextfileeditor-mini.resx-259dbac3","odbfilerequestpage-mini":"odbfilerequestpage-mini-db0e14b3","odbfilerequestpage-mini.resx":"en-us/odbfilerequestpage-mini.resx-8e83db21","odbtiles-mini":"odbtiles-mini-a111ffa2","odbtiles-mini.resx":"en-us/odbtiles-mini.resx-4fae993b","odbsites-mini":"odbsites-mini-c5563389","odbsites-mini.resx":"en-us/odbsites-mini.resx-1b3b4aeb","odbitemvideoplayer-mini":"odbitemvideoplayer-mini-b7a61bf1","odbitemvideoplayer-mini.resx":"en-us/odbitemvideoplayer-mini.resx-983d47a8","odbexecutors-mini":"odbexecutors-mini-f93c0ada","odbexecutors-mini.resx":"en-us/odbexecutors-mini.resx-853081e6","odbdeferredcontrols-mini":"odbdeferredcontrols-mini-29643ad1","odbdeferredcontrols-mini.resx":"en-us/odbdeferredcontrols-mini.resx-d50ca5ed","odbnotifications-mini":"odbnotifications-mini-04da08b9","odbpushchannel-mini":"odbpushchannel-mini-38d90d10","odberror-mini":"odberror-mini-12596c1d","odberror-mini.resx":"en-us/odberror-mini.resx-cf31139d","odbrestore-mini":"odbrestore-mini-950ba62f","odbrestore-mini.resx":"en-us/odbrestore-mini.resx-3a5cbe8e","odbsettingsbasepage-mini":"odbsettingsbasepage-mini-d6c5acdd","odbsettingsbasepage-mini.resx":"en-us/odbsettingsbasepage-mini.resx-b5949852","odbsettings-mini":"odbsettings-mini-ddeab1d1","odbitemsscope-mini":"odbitemsscope-mini-5070e33c","odbitemsscope-mini.resx":"en-us/odbitemsscope-mini.resx-ff223e24","odbitemsscopedeferred-mini":"odbitemsscopedeferred-mini-f918897a","odbitemsscopedeferred-mini.resx":"en-us/odbitemsscopedeferred-mini.resx-af61a995","odbmobileappupsellbasepage-mini":"odbmobileappupsellbasepage-mini-723e546a","odbemptyfolderroot-mini":"odbemptyfolderroot-mini-f9f096eb","odbwinappcommunicator-mini":"odbwinappcommunicator-mini-60ab2c1a","odbcreatesite-mini":"odbcreatesite-mini-5400c9ec","odbcreatesite-mini.resx":"en-us/odbcreatesite-mini.resx-d9c236d6","odb-functional-tests-mini":"odb-functional-tests-mini-41e66bd6","odbhighcharts-mini":"odbhighcharts-mini-ce7056aa","odbclientform-mini":"odbclientform-mini-106b2b9f","odbclientform-mini.resx":"en-us/odbclientform-mini.resx-356af9e8","odbfloodgate-mini":"odbfloodgate-mini-061846b3","odbfloodgate-mini.resx":"en-us/odbfloodgate-mini.resx-610e7422","odbpowerapps-mini":"odbpowerapps-mini-c5977eac","msflowsdk":"msflowsdk-8689f64f","power-app":"power-app-86d2bb4d"},"directional-navigation":{}},deps:["bL3","f","bvB","a6o","buW","buZ","bfi"],baseUrl:"https:\u002f\u002fspoprod-a.akamaihd.net\u002ffiles\u002fodsp-next-prod-amd_2020-06-12_20200612.001\u002f",waitSeconds:0,onNodeCreated:function(n,c,m,u) {
n.setAttribute("crossorigin","anonymous");
var urlParts = u.split('/');
var fileName = urlParts[urlParts.length - 1];
var odspSriHashes = window.__odspSriHashes;
var integrity = odspSriHashes && (odspSriHashes[window.__odsp_culture + '/' + fileName] || odspSriHashes[fileName]);
if (integrity) {
n.setAttribute("integrity",integrity);
}
},enforceDefine:true};
var newConfig = processConfigToSupportFailOver(config);
require.config(newConfig);
}();
</script><script type="text/javascript">
window["_spModuleLink"]={"buildNumber":"odsp-next-prod-amd_2020-06-12_20200612.001","manifestName":"ODBOneDrive","scenarioName":"ODBOneDrive","usingRedirectCookie":false,"bugLinkFormat":null,"ulsLinkFormat":null};
</script>
</html>
<script type="text/javascript" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192">
var g_duration = 92;
var g_iisLatency = 2;
var g_cpuDuration = 72;
var g_queryCount = 6;
var g_queryDuration = 18;
var g_requireJSDone = new Date().getTime();
</script><script type="text/javascript">
var _spOneDrivePageDataCache = {"SPHomeWeb:sites/feed":{"cacheContext":{"ListItemId":3,"Hash":null,"MySiteUrl":null,"Time":"2020-05-28T15:24:51.0000000Z","Version":null},"cacheValue":null},"ODBWeb.sites/feed":{"cacheContext":{"ListItemId":4,"Hash":"7iItaPeKRTNyNthQTkF2/CvVyjcOTjNOkCsKnNsKarY=","MySiteUrl":null,"Time":"2020-05-28T15:25:03.0000000Z","Version":"1.0"},"cacheValue":"{\"Items\":[],\"Type\":\"ItemsList\"}"},"ODBWeb.substrate.recommended":{"cacheContext":{"ListItemId":5,"Hash":null,"MySiteUrl":null,"Time":"2020-05-28T15:24:51.0000000Z","Version":null},"cacheValue":null}};
</script>
<script type="text/javascript" nonce="55c3d852-fe79-49b0-927d-e793a0ba3192">
var g_deferDataLoadTime = new Date().getTime();var g_payload = {"parameters":{"__metadata":{"type":"SP.RenderListDataParameters"},"RenderOptions":1513223,"AllowMultipleValueFilterForTaxonomyFields":true, "AddRequiredFields":true}}; var g_listData = {"wpq":"","Templates":{},"ListData":{ "Row" :
[] OTHER SETTINGS WITH PRIVATE STUFF...
}};if (typeof DeferredListDataComplete != "undefined" && DeferredListDataComplete) { DeferredListDataComplete(); }
</script>
I suggest to modify pdf.js: remove the download button, convert pdf (at backend part) to some intermediate format of pdf.js and put watermark also at server side.
(disclaimer - I work for Atalasoft)
If you present your PDF documents with the Atalasoft web image viewer, you can prevent the PDF from being downloaded. You could also control printing from javascript on the client side.
In my opinion the other proposed solution is.
Convert your PDF book to HTML,
Show the html book in Iframe
This approach will prevent the users to download the file.
Convert pdf to image.
Use image tag to display the image.
Disable right click on the image.

Resources