I am using raphael to draw items on the screen. I have the container for the drawing object contained in a div and overflow: scroll. In all broswers except for IE 7/8 when the user is drawing it does not scroll. However, in IE 7/8 when the user is dragging (i.e. drawing a line) it scrolls automatically as the user nears the edges. I have found some help with jQuery and have tried overriding the onscroll event of the div but that didn't work.
I am not using jQuery and cannot add it.
Sometimes scrolling is caused by "selecting" text in the window (click and drag from top to bottom on this SO page to see what I mean). I can't tell from your description if this is the issue without seeing a jsFiddle example or sample code, but you might try disabling selection.
As you mentioned jQuery is not an option for you. If it were, you'd just use disableSelection().
For a vanilla Javascript solution, try:
function disableSelection(target) {
if (typeof target.onselectstart != "undefined") { //IE
target.onselectstart = function () {
return false;
};
} else if (typeof target.style.MozUserSelect != "undefined") { //Firefox
target.style.MozUserSelect = "none";
} else { //All other ie: Opera
target.onmousedown = function () {
return false;
};
}
target.style.cursor = "default";
}
window.onload = function () {
disableSelection(document.body);
};
Source (slightly modified for clarity): Disable selection on browser using Javascript
Related
I've been messing with the D3JS source code. What I want to achieve is only allow zooming with the Scrolling (Just like Google Maps), if CTRL is pressed too. I've been messing with the complete D3:
https://d3js.org/d3.v4.js
I was trying to achieve this around line 16556:
function wheeled() {
if (!filter.apply(this, arguments)) return;
if (event.ctrlKey == false) return; //This is the new line I added
.....
//else if ((t.k === k)) return; //I commented out this line
Everything else is intact. I downloaded this, and I've been experiencing with this sample:
https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172
In Chrome it's working perfectly. Everything is at it's supposed to be, however when I try to Ctrl+Scroll in Firefox, it just zooms the whole page. The Firefox sais that:
ReferenceError: event is not defined[Learn More] d3.v4.js:16558:1
wheeled http://127.0.0.1:8887/d3.v4.js:16558:1
contextListener/<
I stumbled upon the same problem, but don't wanted to alter the d3 source files. I solved it then by only conditionally calling the original wheel handler (I am using D3v4):
this.zoom = d3.zoom()[...]
var svg = d3.select(this.$refs.chart)
.call(this.zoom);
var wheeled = svg.on("wheel.zoom");
svg
.on("wheel.zoom", function () {
if (d3.event.ctrlKey) {
wheeled.call(this);
// prevent browser zooming at minimum zoom
d3.event.preventDefault();
d3.event.stopImmediatePropagation();
}
});
As I explained in my comment you don't need to mess with the source code, just add the conditional to your code. In your reply you said that it doesn't work on Firefox.
Well, that's the expected behaviour for Firefox (see my answer here).
Therefore, instead of:
if (event.ctrlKey == false) return;
You should do:
if (d3.event.sourceEvent.ctrlKey == false) return;
This will work on both Chrome and Firefox.
Here is the bl.ocks with that change: http://blockbuilder.org/anonymous/2a1c5fe3ed6948665f8d946a753adaef
Added this line:
if (d3.event.ctrlKey == false) return;
Into the source code of the d3.v4.js:
function wheeled() {
At the second line after it. Now it works. Thanks for the suggestion, it helped after all :)
Use a filter to require ctrlKey to start the zoom event. Disable scrolling when ctrlKey is pressed to prevent the browser's default action when scrolling passed the scale extent. Both things are hinted in zoom docs.
// ignore right button and require ctrl
zoom.filter(() => !d3.event.button && d3.event.ctrlKey)
// ignore default browser action when ctrlKey is pressed
selection
.call(zoom)
.on("wheel", () => { if (d3.event.ctrlKey) d3.event.preventDefault() })
Hi I have made a website using fullpage.js which is great and scrolls between sections (full pages) but on mobiles it can be difficult to navigate so I have made it continuos scrolling when the width is under 640px.
I have a menu which toggles down after the anchor changes from the main page and toggles back when the anchor is the main page. this is because there is a built in menu on the main page so it doesn't need a 2nd.
On mobiles after making it continuos scrolling this feature doesn't work but it still works on computer browsers. I don't know whether I am over looking something or if I could write a better script for the menu toggle.
Please look at www.themeltingpotkitchen.com to see what I mean.
Here is my menu js. I will point out that if your tap links via menus it will work but not by scrolling :s
// detect anchor change and hide or show menu
function locationHashChanged() {
var hash = location.hash;
var id = hash.replace(/^#/, '');
// logic
if (id == 'Home') {
$("#nav_hide").slideUp();
} else if (id == 'About') {
$("#nav_hide").slideDown();
} else if (id == 'Trailer') {
$("#nav_hide").slideDown();
} else if (id == 'Food') {
$("#nav_hide").slideDown();
} else if (id == 'Contact') {
$("#nav_hide").slideDown();
}
}
window.onhashchange = locationHashChanged;
// if loaded page is home hide menu
var hashVal = window.location.hash.split("#")[1];
var p = window.location.pathname.split("/");
var filename = p[p.length-1];
if(hashVal == 'Home', filename == 'index.html') {
$("#nav_hide").hide();
}
You should not be using the change in the URL to trigger any action. That's not the way to do it with fullPage.js.
You should be using the callbacks provided by the plugin such as onLeave or afterLoad.
Or you could even use the class added to the body element as suggested in this tutorial
The reason for it is because fullPage.js doesn't change the location hash but uses the HTML5 History API for mobile phones due to problems with the location hash behaviour in Mobile Chrome:
//Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
if (isTouchDevice || isTouch) {
history.replaceState(undefined, undefined, '#' + url);
} else {
var baseUrl = window.location.href.split('#')[0];
window.location.replace(baseUrl + '#' + url);
}
I am writing a web app in HTML and JavaScript for use on an iPhone. What I would like to achieve is preventing the app from elastic scrolling (scrolling past the pages extents and bouncing back). However, I need some of the longer elements of my app to be able to be scrolled (the app has a long canvas).
I have tried many answers to this found elsewhere on the internet, however, all of those solutions either used JQuery, disabled scrolling altogether, used Phonegap or just plain didn't work on IOS 7. How can I do this?
There is a way to achieve this without jQuery:
document.body.addEventListener('touchmove', function(event) {
event.preventDefault();
});
But this is not a proper solution. It's better to wrap your content in some div, and use css property on it:
-webkit-overflow-scrolling: touch;
Here is the example
Edit:
This will only prevent overscroll in webview, not in app. So you need to disable this feature in app config.
If you use phonegap:
<preference name="DisallowOverscroll" value="true" />
More description here
If you don't use phonegap, you can use this.
The above solution was insufficient in my case. It prohibits all scrolling. It is possible to build a solution here that prevents elastic scrolling in iOS, but that still allows scrolling on children. I this took the above solution and added a check that bubbles up the DOM to determine which scrollable element "owns" the scroll event, and if it's the root element of the page, I drop it:
function overflowIsHidden(node) {
var style = getComputedStyle(node);
return style.overflow === 'hidden' || style.overflowX === 'hidden' || style.overflowY === 'hidden';
}
function findNearestScrollableParent(firstNode) {
var node = firstNode;
var scrollable = null;
while(!scrollable && node) {
if (node.scrollWidth > node.clientWidth || node.scrollHeight > node.clientHeight) {
if (!overflowIsHidden(node)) {
scrollable = node;
}
}
node = node.parentNode;
}
return scrollable;
}
document.addEventListener('DOMContentLoaded', function() {
document.body.addEventListener('touchmove', function(event) {
var owner = findNearestScrollableParent(event.target);
if (!owner || owner === document.documentElement || owner === document.body) {
event.preventDefault();
}
});
}, false);
At this point, the body is no longer scrollable or elastically scrollable in iOS, but children elements are. You can then add -webkit-overflow-scrolling: touch; to those children so they are elastic but the document wont be. This will actually capture all scroll events even as you scroll to the bottom of the children, so the window's scroll position wont ever change erroneously. Alternatively you may also consider:
['resize', 'orientationchange', 'scroll'].forEach(function(event) {
window.addEventListener(event, function() {
window.scrollTo(0, 0);
});
});
which in addition to the first code block I shared, should really throw an axe at document scrolling in ios altogether.
So when you have scroll content in body & want to disable elastic scroll
use:
let scrollToTop = $(window).scrollTop();
if (scrollToTop < 0) {
// do something here
}
Because elastic scroll will always have negative value
Based on answer by #umidbek this is how it worked for me
document.getElementById('content-sections').
addEventListener('touchmove', function (event) {
event.preventDefault();
return false;
});
I have a Tapestry zone, inside which is an <iframe> element. I wanted to do run a simple JS function (just hiding and enabling some stuff, nothing fancy) when the iframe is done loading.
In chrome and firefox, it works just fine, but I'm having issues with IE 9.
function afterExportLoad() {
// hide throbber gif
// enable submit button
}
So, natually, I tried binding it to iframe like this (inline)
<iframe onload="afterExportLoad()" .../>
via PrototypeJS
exportFrame.observe('load', afterExportLoad);
via native JS
if (window.addEventListener) {
exportFrame.addEventListener("load", afterExportLoad, false);
} else if (window.attachEvent) {
exportFrame.attachEvent("onload", afterExportLoad);
} else {
exportFrame.onload = afterExportLoad;
}
Using any way above, it works in everything but IE, but in IE, after the iframe is loaded, the gif is "frozen" and the button is still disabled.
Is there a way to make it work in IE9 (and possibly any other IE versions)?
Thank you :)
So, I was fiddling around a bit and got to this solution:
Added browser checks in the function
function afterExportLoad() {
if (document.getElementsByName('downloadFrame').length > 0) {
var exportFrame = document.getElementsByName('downloadFrame')[0];
if ((Prototype.Browser.IE && exportFrame.readyState == "complete") || (!Prototype.Browser.IE)) {
// my stuff
}
}
}
Changed the event
<iframe onreadystatechange="afterExportLoad();" ...>
And in another function that listenes on zone update where iframe is
if (document.getElementsByName('downloadFrame').length > 0) {
var exportFrame = document.getElementsByName('downloadFrame')[0];
if (!Prototype.Browser.IE) {
exportFrame.stopObserving('readystatechange', exportLoad);
exportFrame.onload = exportLoad;
}
}
If any1 comes up with a better solution, let me know :)
I'm working on a project that's trying to implement some editing features using a contentEditable DIV. We're now trying to add support for IE9 (after initally providing Chrome/Safari support) and it's proving to be a challenge.
What we are able to do in Chrome is have <img> objects inside a content editable div, and allow those <img> elements to be dragged/dropped, but not resized. Additionally, pressing TAB in the contentEditable div should not select the <img>
In IE 9, I have found some methods for stopping the images from being resized (like Permitting moving only of <img>s within contentEditable <div>) but even that still shows those darn resize handles when clicking on an image. My big problem is that in IE 9, when I'm typing inside the contenteditable div, and I hit TAB, I want the browser to select the next item on the web page (in our application, it is another contentEditable div). This works in Chrome, but in IE, when I hit TAB, the <img> is selected (with the resize handles showing up)
Does anyone know if there is a way to disable the 'selection using tab' functionality in IE 9?
Here's a simple test case that disables the resizing, still allows drag-and-drop, but the <img> is still selected via TAB:
<html>
<head>
<title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
//This line below doesn't work in IE9
//document.execCommand("enableObjectResizing", false, false);
$('img', '#edit').each(function (i, item) {
item.attachEvent("onresizestart", function(e) {
e.returnValue = false;
}, false);
//I thought this below might work for disabling selection,
// but it doesn't...
item.attachEvent("onbeforeeditfocus", function(e) {
e.returnValue = false;
}, false);
});
});
</script>
</head>
<body>
<div id="edit" contenteditable="true">
Here is some text, and also an <img src="http://img841.imageshack.us/img841/1747/imagead.png" /> image
</div>
</body>
</html>
Here's a starting point for you. It's not ideal (particularly the heavy-handed mouse down/up detection) but it does basically detect when an image in a contenteditable element becomes selected with resize handles (a "control selection"; see MSDN for more details) via non-mouse means and moves the focus to another contenteditable element (hard-coded in the example). It works in IE 7; I haven't tested in IE 9 but I would expect it to work.
Live demo: http://jsfiddle.net/5BGxT/3/
Code:
if (document.selection && "onselectionchange" in document) {
// Ensure image can be resized when clicked on
var mouseDown = false;
document.getElementById("one").onmousedown = function() {
mouseDown = true;
};
document.getElementById("one").onmouseup = function() {
mouseDown = false;
};
document.onselectionchange = function() {
var sel = document.selection;
if (!mouseDown && sel.type == "Control" &&
sel.createRange().item(0).tagName == "IMG") {
var nextEditableEl = document.getElementById("two");
nextEditableEl.focus();
}
};
}
To prevent resizing of your images the onresizestart event handler should be set on the contenteditable container. It doesn't remove the handles but it does remove the possibility to resize the elements.
see: https://stackoverflow.com/a/11878624/1491212