How to detect scroll event from pdf.js - pdf

I'm essentially using the default web/viewer.html and its associated files that comes with it. I have it loaded in an iframe. How can I add an event listener to when the pdf is scrolled? Thanks for any help.

I dug around and tested some things more and figured it out, which is pretty simple but if you're in the same bind:
var viewerContainer = window.document.getELementById('somePdfIframe').contentDocument.getElementById('viewerContainer') will contain the element whose scrollTop will change.
So if
viewerContainer.scrollTop + $(viewerContainer).height() == viewerContainer.scrollHeight
then the user has reached the bottom of the pdf iFrame.
You can also viewerContainer.addEventListener('scroll', function() {...}) to listen for scrolls in the pdf iframe.
One little thing that was tricky for me is that you should make sure the pdf iframe was fully loaded before calling this code.

Related

Parse Element ID within iframe using Webview in VB.net

I have a webpage that loads caller data when a caller calls. I am trying to parse the element ids but they are loaded in an iframe. How would i go about doint this?
The iframe is and the elements are on default.html <iframe onload="UserFrameLoaded();" name="cmUserFrame" id="view_cmUserFrame" style="display: block; overflow: scroll;" marginheight="0" width="100%" height="1415px" frameborder="0" marginwidth="0" src="./CallManager_files/default.html"></iframe>
the code im using is
Dim firstNameText As String = Await WebView21.ExecuteScriptAsync("document.getElementById('m.first_name').textContent")
i tried
Dim firstNameText As String = Await WebView21.ExecuteScriptAsync("document.getElementById('view_cmUserFrame').contentWindow.document.getElementById('m.first_name').textContent")
Im not sure if the iframes source is on another domain. Im hoping not...
I can probably just save the webpage locally and then load default.html directly but i am not sure how to save the webpage with webview either.
You pretty much are asking a Javascript question, however, things might be easier for you if you understand a little more about Webview2 and how you can access those frames.
First option is FrameCreated Event which will fire when the cmUserFrame is created in the top document. From this you get a frame and you can then use ExecuteScriptAsync from that frame object.
Next up you have AddScriptToExecuteOnDocumentCreatedAsync with this it will inject your script into each document that is created. In this case you could have Javascript that checks the name of the document/Frame and then if it is the right frame continues with your javascript.
With respect to you actual Javascript, without knowing the actual page it is difficult to know. open the Dev tools of either Chrome or edge and then the console and copy past your javascript into there to see if it works there first. If it works there then you have a timing issue. If it does not work then you need to work on what is not being found.
Updated From Comments
To help you understand the Webview2 frame events here is an Issue from Github
One more link from Webview2 GitHub issues.
Specifically to answer your questions.
Implement FrameCreated
Wait for the frame with the name you want
Wait for DomContentCompleted event
Call ExecuteScriptAsync ONE THE FRAME you get from 2
Code would then be assuming that that frame's document is as you have in your js
Dim firstNameText As String = Await WebView21FRAME.ExecuteScriptAsync("document.getElementById('m.first_name').textContent")

Cycle.js/xstream click event streamed once, but fired twice

There's a single button element on the page and the following click stream:
let submitClick$ = sources.DOM.select(buttonSel)
.events("click")
.mapTo(true)
.debug(console.log)
Once I click on the button, true is logged, which is correct.
However, when I map the stream, the code inside runs twice:
let submitDeal$ = submitClick$.map(() => {
console.log("Clicked")
// ...
})
No other event handlers should be attached to the button, and the element itself sits inside a div:
button(".btn--add", "Submit")
The usual event.preventDefault() and event.stopPropagation() doesn't make a difference, and inspecting the event does show that it is fired from the same element button.btn--add.
Not really sure what's going on, any ideas are appreciated! Thanks!
Versions:
"#cycle/dom": "^12.2.5"
"#cycle/http": "^11.0.1"
"#cycle/xstream-run": "^3.1.0"
"xstream": "^6.4.0"
Update 1: I triple checked and no JS files are loaded twice. I'm using Webpack that bundles a single app.js file that's loaded on the page (Elixir/Phoenix app). Also when inspecting the button in the Event Listeners tab in Chrome's Developer Tools, it seems that only 1 event handled is attached.
Update 2: Gist with the code
Too little information is given to resolve this problem. However some things come to mind:
You shouldn't use .debug(console.log) but .debug(x => console.log(x)) instead. In fact .debug() is enough, it will use console.log internally.
Then, is the button inside a <form>? That may be affecting the events. In general this question needs more details.
Turns out this was due to a bug in xstream, which was fixed in xstream#7.0.0.

iOS10 Safari Keyboard Popup

I have a single page web app. The keyboard pops-up everytime I click on the screen.
There are no text input boxes in the DOM at all.
How can I debug why the keyboard is popping up.
You can see examples of this strange behaviour at https://blight.ironhelmet.com and https://np.ironhelmet.com
update with a clue: A user is now reporting that rather than the keyboard, a dropdown selection spiner is popping up all the time, long after that dropdown has been removed from the DOM.
For React users:
I had the same thing happen in a React single-page app with React-Router. I didn't write code to remove elements from the DOM, but of course React does that for you.
On my site, there are React components that contain one to four input fields. After any such component appears, and then is hidden (unmounted / not rendered anymore), then any time the user taps a link, the keyboard pops up. This makes the site unusable. The only way to make it stop was to reload the page.
The workaround: calling document.activeElement.blur() in componentWillUnmount for the wrapper component around my <input> fields did the trick.
componentWillUnmount()
{
if (document && document.activeElement)
{
document.activeElement.blur();
}
}
Note that calling window.activeElement.blur() did not seem to do anything.
There's a thread in the Apple support forums about this issue:
https://discussions.apple.com/thread/7692319
Looks like the keyboard was holding a reference to input after I had removed them from the DOM.
I added a test when removing element to see if it was the current activeElement, then, if so, calling document.activeElement.blur() before removing it. Seems to have solved the problem so far.

optimize drag and drop with svg library & javascript

Currently most of the SVG framework provides drag and dropping. I have used RaphaelJs , Extjs Drawing , and SVG.js(http://www.svgjs.com/). All of the framework provides the event handling method by binding it with the element itself. For example:
dragStart: function(event){
//'this' refers to the element itself
this.doSomething();
this.moveTo(event.x,event.y);
};
However the consequences of this is that browser performance is greatly degraded, when there are more than hundred of elements and some logic processing aside. My elements will be composite elements, meaning maybe some text or path in a rect but the rect should be the target (or this) of the event when dragged. The elements will have other event to listen to , for example onclick, onDblClick, onHover & etc.
My question is, is there any way to optimize this ? The user experience is bad after the application is showing a lot of the composite elements I mentioned above.
UPDATE:
I have built an application using the mean that i spoke of above. Binding the event handler to each of the objects. The result is not very user friendly when the element is listening to onhover and onmousedown events. I am thinking to optimize the application but not sure how. The effect is more obvious in FF, chrome is better.
Are you sure you need SVG? Fabric.js is an awesome API for scaling, rotating, drag-drop, and grouping, based on the Canvas element.

Lazy Load - refresh / update when combined with javascript filtering

I am now trying to implement lazyload onto my website.
I have successfully got lazy load working on pages that have a static gallery.
The main portfolio of the website has a large list of images that can be filtered using the javascript library Isotope.
The lazy load works fine when filtering is not in used, however, if the page loads and I don't scroll, but filtering is used, the items which are brought into view don't resolve. I found that occasional images worked, but most don't.
Any suggestions on how to fix this?
Presumably i need to be able to do something that will re-trigger lazy load to refresh or recheck itself?
Here is the gallery I am trying to get working, where you can see the issues I am having: http://www.imageworkshop.com/lazyload-portfolio/
Anyone able to help?
call this code on filtered item is clicked: $(window).trigger('scroll');
I found this answer from acarabott - https://stackoverflow.com/a/13919010/735369
I have implemented this and this has worked.
The only issue is that the refresh doesn't happen until a scroll action takes place.
If you want to use isotope's sorting/filtering functions, you will need to set the failure_limit of lazyload and trigger the event with isotope's onLayout callback.
jQuery(document).ready(function($) {
var $win = $(window),
$con = $('#container'),
$imgs = $("img.lazy");
$con.isotope({
onLayout: function() {
$win.trigger("scroll");
}
});
$imgs.lazyload({
failure_limit: Math.max($imgs.length - 1, 0)
});
Explanation
According to the docs ( http://www.appelsiini.net/projects/lazyload )
After scrolling page Lazy Load loops though unloaded images. In loop it checks if image has become visible. By default loop is stopped when first image below the fold (not visible) is found. This is based on following assumption. Order of images on page is same as order of images in HTML code. With some layouts assumption this might be wrong.
With an isotope sorted/filtered list, the page order is certainly different from the HTML so we need to adjust our failure_limit.
As you can see we store the jQuery object so that we can use its length-1 as our failure_limit. If you're curious as to why it is length-1, it's because of the following check in lazyload's update method.
if (++counter > settings.failure_limit) {
return false;
}
Lazy load on other events
If you are not triggering your lazyloads on scroll, you will need to swap the "scroll" trigger for whichever event you are using.
Demo
http://jsfiddle.net/arthurc/ZnEhn/