I have a Cocoa webview, with a web application in it. The web application has a fixed toolbar itself, and with the elastic scrolling, and the toolbar coming below the top, it looks bad. Is there a way to disable the elastic/rubber-band scrolling, or at least keep the toolbar from moving with the rest of the content? I can modify the web app as much as neede.
If you're interested in doing it from the WebView and Cocoa perspective, you can also implement the finish load delegate, grab the scroll view, and disable elasticity:
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
NSScrollView *mainScrollView = sender.mainFrame.frameView.documentView.enclosingScrollView;
[mainScrollView setVerticalScrollElasticity:NSScrollElasticityNone];
[mainScrollView setHorizontalScrollElasticity:NSScrollElasticityNone];
}
Maybe this article would help you.
In short: disable overflow on HTML and BODY, add a wrapper with overflow:auto around all the page contents
I know this comment likely won't be accepted, since there's already an answer.
However, there's an actual method you can call on your NSView (docs here):
[[[webView mainFrame] frameView] setAllowsScrolling:NO];
Related
I'm developing a browser with touch screen support using Qt 5.4 and WebKit (I'm not using QML at the moment). Currently I'm implementing the touch scrolling and so far I managed to scroll the page's main frame. However, I'm having a hard time trying to figure out how to scroll its HTML sub-elements such as iframe, textarea, div, etc.
This is because I know how to scroll the main frame (I can call webView->page()->mainFrame()->setScrollPosition(QPoint(x, y));), but not how to scroll the web elements.
I imagine that with JavaScript injection it might be possible to check if an HTML element is scrollable and call a function that scrolls it, but this doesn't seem to be that elegant. Is there a way to this using only C++/Qt code?
I spent a lot of time grappling with this issue. Finally I just used a single line of Javascript and was done with it.
webView->page()->mainFrame()->evaluateJavaScript("window.scrollTo(0, document.body.scrollHeight);");
Plus, if Javascript is such a standard these days, why can't you rely on it inside a QWebView?
The Javscript to scroll a web element would be something like:
var textarea = document.getElementById('textarea_id');
textarea.scrollTop = textarea.scrollHeight;
Following up on How to rewrite URLs referenced by Javascript code? I'd like to overlay a button on top of someone else's website (e.g. overlay a Paypal button alongside Stackoverflow's bounty button) and have the two <iframe>s scroll together. The button would reside in the top layer. The website would reside in the bottom layer.
I understand that transparent <iframe>s were/are abused for clickjacking but the browser security mechanism seems to block legitimate use-cases. In my case the user is seeing the same button he/she is clicking. It's even possible that this is a browser bug.
Here is what I see under Chrome:
The top <iframe> intercepts all mouse clicks, even for areas that do not contain any components. Meaning, users cannot interact with the bottom layer at all.
If I style the top <iframe> with pointer-events: none the opposite problem occurs: users are able to see the top layer but all mouse clicks go to the bottom layer. Applying pointer-events: auto to child components does not help (clicks still pass through to the bottom layer).
If I size and position the top <iframe> so its area is equal precisely to the button I am trying to overlay, then mouse clicks go to the right layer but the top layer fails to scroll alongside the bottom layer. Meaning, the button always remains in the same absolute position as the bottom layer scrolls.
Is it possible for me to position a button in the top layer so that it always aligns with a certain position in the bottom layer? In the example where I position a Paypal button alongside the Stackoverflow bounty, I expect the Paypal button to scroll off the page as the user scrolls down the question.
https://stackoverflow.com/a/4087397/14731 leads me to believe this is not possible. Is there another way to implement this?
UPDATE: Here is a jsfiddle for you to play with. The test button is found to the right of "NEWS & VIEWS" in the middle of the page.
Update: New approach
Following discussion with Gili below, the requirement for the solution to work across multiple pages made me rethink my solution.
The new approach:
Doesn't require any code changes or specific features on the target site.
Works on every page while the user navigates (as long as they stay on the same domain)
Could be tweaked to inject any HTML/JS into any DOM element within any target page
My solution works as follows:
Send the person you want to demonstrate Widget X to an email with a link to your instructions page
That instructions page contains a bookmarklet which they add to their bookmarks bar
They visit their own site and click your bookmarklet
Your bookmarklet injects javascript into their page
That javascript creates a pop-up window with content that appears to belong to the target domain, since that domain generated the popup
That pop-up window then monitors the DOM on the target browser window (window.opener) and injects our arbitrary HTML whenever the current page doesn't contain our target node ID.
It seems to work well in my testing (perfect in Chrome, haven't tested across all browsers yet) and seems to work on every target site from StackOverflow to Twitter.
Live demo here: How to demo an web widget on a third party site without having access to their code
Sample code below, expanded for readability:
s = "<script type='text/javascript'>setInterval(function() { if(!window.opener.document.getElementById('gctrlPixelator')) {var i=document.createElement('IMG');i.src='//lorempixel.com/400/200/';i.id='gctrlPixelator';i.style.cssText='top:20;right:20;position:absolute;z-index: 9999;';window.opener.document.getElementsByTagName('body')[0].appendChild(i);}},500);</script>";
t = "<div style='text-align: center; font-family: Arial, Helvetica;'><h1 style='font-size: 18px;'>Demo running!</h1> Keep this window open and return to the main site window to continue the demo.</div>";
w = window.open('','name','height=200,width=400');
w.document.write(s);
w.document.write(t);
The above should be converted into a bookmarklet before deploying to an 'instructions' landing page for a potential client.
Original solution
First, sorry for posting this as an answer rather than as a comment. I've been thinking about this for half an hour, and only just realised I need 50 reputation to comment. So, apologies, but I wanted to share...
I agree that it's unlikely there is a cross browser way to do this double iframe trick. I read your other question about javascript URL rewriting and it lead me to an idea: Rather than trying to embed/hijack their site on another URL, how about creating a bookmarklet that allows you to inject your Javascript into their page?
It could work like this:
Direct them to your site where you host the custom bookmarklet link. Ask them to add it to their favorites.
Ask them to go to their own site, then click your bookmarklet in their bookmarks.
This would inject your JS into their page, allowing you to edit the DOM any way you wanted (e.g. changing styles, adding DOM elements, etc.)
Code something like this, converted to a bookmarklet (i.e. wrapped in a function with a javascript: at the start) could do the trick...
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", "http://www.example.com/file.js");
document.getElementsByTagName("head")[0].appendChild(script);
I've tested that in Chrome and it seems happy to load the JS cross-domain. The only rule seems to be that the protocols must match (http or https).
Not quite what you asked for, but a possible solution.
I want to showcase my company work to our future client.
The project which I am going to showcase is basically a FLASH-HTML5 conversion.
I want to use a switch on the page which will swap flash to HTML5 page and vice versa.
If I am on page3 of flash file and hit the switch button it should load page 3 from HTML5.
something similar to 'https://www.pixelplant.com/gallery/'
Can you guys help me out how to do it? What technology I should use?
There are multiple ways of achieving this. The example website uses iframe in a popup div, which could be done with jquery or any lightbox plugin based on jquery. You can also use inline hidden divs to fade-in/fade-out.
The switch binds with a function to call the relevant divs to display, that's it.
In my app I'm using a ScrollPane. I can load a DisplayObject into it, and it works fine. The thing is that when it's empty, i.e. I haven't loaded anything into it, there aren't any scrollbars on the pane. This makes sense, since there's no scrolling to do, but I'd like there to be "greyed out" scrollbars if possible.
It's not necessary or anything but most programs have it (open an empty .txt file in Notepad and you'll see what I mean), I'd just like to know if my app can do this.
If it helps at all, it's an AIR app made using FlashDevelop with the open-source Flex 4 SDK. I'm getting my components (ScrollPane, etc.) from a SWC.
Set the vertical or horizontal scroll policy according to what you want.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/containers/BaseScrollPane.html#verticalScrollPolicy
scrollPane.verticalScrollPolicy=ScrollPolicy.ON;
scrollPane.horizontalScrollPolicy=ScrollPolicy.ON;
HELP, this is a very unique problem and I can't for the life of me figure it out.
My flash content is overlapping the HTML above it.
This only happens if I've just launched IE after being restarted and goes away once I refresh the page. I even added a jQuery $(document).ready function that sets a margin between the html and the flash content to add 1px of space when the page is loaded. It's so hard to figure out, because once I refresh the page, it goes away.
Any input GREATLY appreciated.
Here is the site.
http://www.californiaremodels.com
(This only happens in IE)
here is a screen shot of the problem.
########### SOLVED ###################### SOLVED
I set the flash output as a javascript var (actually json_encoded PHP output) and on document load inserted the object into the "flashContent" div with the jQuery.(document).ready event.
Thank you to Andy Shellam!!
Have you tried loading your flash content using jQuery? I.e. set your div width/height in your HTML with a "this requires javascript/flash" placeholder, then have jQuery load the OBJECT into the div on page load. This way cures IE7's annoying "click here to activate this control" issue - may be a similar issue.
It may be due to the fact that you're floating that DIV that holds the flash content. It shouldn't matter, but sometimes IE gets hinky about such things. Try taking off the float and see if that cures the problem. If it does, create a non-floating workaround.
looks like it is the -4px of margin top you have that is creating the problem