first post so go easy on my noobness!
I have a script that opens a popup window when some linked text is clicked, but now I want to get rid of the text and just use an empty span with background img as the link. Needless to say the script will not work with just the span and I'd appreciate some pointers on how to modify it to work (or suggest any workarounds if it ain't gonna work on an empty span).
Current link structure (which uses the text link to trigger the js window containing thelink.com):
<a href="http://thelink.com" class="pop">
<span class="icon_bg"><!-- empty span with image as background --></span>
some text here
</a>
Desired link structure (no text, just empty span with bg img):
<a href="http://thelink.com" class="pop">
<span class="icon_bg"><!-- empty span with image as background --></span>
</a>
Current script:
function popWin() {
function addEvent(element, eventName, callback) {
if (element.addEventListener) {
element.addEventListener(eventName, callback, false);
} else {
element.attachEvent("on" + eventName, callback);
}
}
function init() {
var links = document.querySelectorAll('a.pop');
for (var i = 0; i < links.length; i++) {
popWin.addEvent(links[i], 'click', popWin.popup)
}
}
function openPopup(e) {
var top = (screen.availHeight - 500) / 2;
var left = (screen.availWidth - 500) / 2;
var e = (e ? e : window.event);
var target = (e.target ? e.target : e.srcElement);
var popup = window.open(
target.href,
'social',
'width=550,height=420,left='+ left +',top='+ top +',location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1'
);
if(popup) {
popup.focus();
e.preventDefault();
return false;
}
return true;
}
return {
init: init,
popup: openPopup,
addEvent: addEvent
}}
var popWin = new popWin();
popWin.addEvent(window, 'load', popWin.init)
My hunch is to somehow define the span tag as the target using .nodeName. All help appreciated.
You can use the <span> </span> to simulate invisible text and thus will cause the span to get width.
Your span is empty currently. Add some content to it, then it would work for you.
<span>Content</span>
Now the event would trigger for you.
Background image won't be visible until you have some width and height for the span. I would refer you to use
span {
/* change the display property of span; default is inline */
display: inline-block;
/* because width and height can be applied to only block level elements */
width: 100px;
height: 100px;
}
Now try it again. Have my fiddle, it makes a good use of your example, and it enables click on the textless span.
Also, you're not having any click handler in your code.
<span onclick="popWin()">
This would enable the click event.
http://jsfiddle.net/afzaal_ahmad_zeeshan/FdjZy/
OK, I think I've worked out the solution, but am curious if this is gonna be bombproof (seems to work in the few browsers I've tried so far).
Changed the line:
var target = (e.target ? e.target : e.srcElement)
To:
var target = (e.target ? e.target : e.srcElement).parentNode;
Now the span tag is triggering the script without the need for any text anywhere within the a tags.
Related
I have some data in a table where clicking it will navigate you elsewhere, but people are requesting the ability to highlight the text to be able to copy/paste it elsewhere. Since they are links, the default behavior in HTML is to drag the link... I don't know why or how that is useful, but I want to disable that on certain links.
TL;DR: I want to be able to highlight the text of a link and not drag it.
The gif below should help explain my issue.
The following methods are NOT what I want:
I have seen examples that prevent both highlighting & dragging using something like this
<a draggable="false" href="#">
or this
.no-drag {
user-drag: none;
}
Or this
myElement.ondragstart = function () {
return false;
};
But obviously that is not what I need here.Is what I want possible to do?
In Google Chrome this works
user-select: none;
-webkit-user-drag: none;
#Julien Grégoire's answer above put me on the right track for this, but the below code is the basics of what I ended up using.
var clickedEl = document.getElementById("test");
var limit = 5;
var mouseMoved = false;
function resetEvents() {
clickedEl.onmousemove = null;
clickedEl.ondragstart = null;
clickedEl.onmouseleave = null;
mouseMoved = false;
}
clickedEl.onmousedown = function (downEvent) {
if (clickedEl.attributes.href) {
clickedEl.onclick = function (clickEvent) {
if (mouseMoved) {
clickEvent.preventDefault();
}
resetEvents();
};
}
clickedEl.onmouseleave = function () {
resetEvents();
};
clickedEl.onmousemove = function (moveEvent) {
// This prevents the text selection being dragged
clickedEl.ondragstart = function (dragEvent) {
dragEvent.preventDefault();
};
if (Math.abs(moveEvent.x - downEvent.x) >= limit || Math.abs(moveEvent.y - downEvent.y) >= limit) {
// If user clicks then moves the mouse within a certain limit, select the text inside
window.getSelection().selectAllChildren(clickedEl);
mouseMoved = true;
}
};
};
<a id="test" href="http://stackoverflow.com">Click or select</a>
I'm super late to answer but I'm just gonna leave it here:
Just put draggable="false" inside <a> tag,
<a draggable="false" href="./"></a>
then in CSS you put:
body {
-webkit-user-drag: none;
}
You could detect if user moves the mouse after the click and if so manage selection using window.getSelection. Something like this for example:
var linkEl = document.getElementById('test')
linkEl.onmousedown = function(downEvent) {
var clickedEl = downEvent.target;
var mouseMoved = false;
clickedEl.onmousemove = function() {
// If user clicks then moves, select the whole link
window.getSelection().selectAllChildren(clickedEl);
// Set a flag to prevent opening the link
mouseMoved = true;
// Reset mousemove, else it'll run constantly
clickedEl.onmousemove = null;
// This is only to prevent having the text selection being dragged
clickedEl.ondragstart = function(dragEvent) {
dragEvent.preventDefault();
}
}
if (mouseMoved) {
// If mouse has moved, prevent default
downEvent.preventDefault();
}
}
<a draggable="false" id="test" href="http://stackoverflow.com">Click or select</a>
This is the simplest solution that worked for me. You can change '*' to 'a'.
*, *::after, *::before {
-webkit-user-select: none;
-webkit-user-drag: none;
-webkit-app-region: no-drag;
}
Is there a way to get elements which is:
Inside a div with overflow: scroll
Is in viewport
Just like the following picture, where active div (5,6,7,8,9) is orange, and the others is green (1-4 and >10) :
I just want the mousewheel event to add "active" class to div 5,6,7,8,9 (currently in viewport). View my JSFiddle
$('.wrapper').bind('mousewheel', function (e) {
//addClass 'active' here
});
You could do something like this. I would have re-factored it, but only to show the concept.
Firstly I would attach this to scroll event and not mousewheel. There are those among us that likes to use keyboard for scrolling, and you also have the case of dragging the scrollbar. ;) You also have the case of touch devices.
Note that with this I have set overflow:auto; on wrapper, thus no bottom scroll-bar.
With bottom scrollbar you would either have to live with it becoming tagged as in-view a tad to early, or tumble into the world of doing a cross-browser calculating of IE's clientHeight. But the code should hopefully be OK as a starter.
»»Fiddle««
function isView(wrp, elm)
{
var wrpH = $(wrp).height(),
elmH = $(elm).height(),
elmT = $(elm).offset().top;
return elmT >= 0 &&
elmT + elmH < wrpH;
}
$('.wrapper').bind('scroll', function (e) {
$('div.box').each(function(i, e) {
if (isView(".wrapper", this)) {
$(this).addClass('active');
} else {
$(this).removeClass('active');
}
});
});
Note that you should likely refactor in such a way that .wrapper height is only retrieved once per invocation, or if it is static, at page load etc.
Update; a modified version of isView(). Taking position of container into account. This time looking at dolphins in the pool.
»»Fiddle««
function isView(pool, dolphin) {
var poolT = pool.offset().top,
poolH = pool.height(),
dolpH = dolphin.height(),
dolpT = dolphin.offset().top - poolT;
return dolpT >= 0 && dolpT + dolpH <= poolH;
}
I made a menu on html (on the side and 100% heigth, expandeable as in android holo)
<div id="menu">
<button class="menubutton"></button>
<button class="menubutton"></button>
</div>
The menu normally remains transparent and with a short width:
#menu {
background-color: transparent;
width: 8%;
}
The idea was to expand and color it on hover. It was easy:
#menu:hover {
background-color: blue;
width: 90%;
}
There is no problem untill here. I need the same effect on focus. There is no way in css to change parent css on child focus (neither hover by the way, but it is not needed, cuase i can use the entire menu hover).
So i used a script:
var menubuttonfocus = document.getElementsByClassName("menubutton");
for (i=0; i<menubuttonfocus.length; i++) {
menubuttonfocus[i].addEventListener("focus", function() {
menu.style.backgroundColor = "blue";
menu.style.width = "90%";
});
menubuttonfocus[i].addEventListener("blur", function() {
menu.style.backgroundColor = "transparent";
menu.style.width = "8%";
});
}
The script works just fine, the problem is that when you trigger those events by focusing a button, the css of #menu:hover changes somehow and #menu does not change when hovering. I tried to solve this by doing something similar but with hover instead of focus:
menu.addEventListener("mouseenter", function(){
menu.style.backgroundColor = "blue";
menu.style.width = "90%";
});
menu.addEventListener("mouseout", function(){
menu.style.backgroundColor = "transparent";
menu.style.width = "8%";
});
This works somehow, but it is REALLY buggy.
I tried also to select "#menu:hover,#menu:focus", but it doesn't work because the focus is on the button elements and not in #menu.
Please avoid jquery if posible, and i know it's asking for too much but a pure css solution would be awesome.
Probably helpful info: html element are created dinamically with javascript.
I can show more code or screenshot, you can even download it (it is a chrome app) if needed: chrome webstore page
Thanks.
SOLVED: I did what #GCyrillus told me, changing #menu class on focus via javascript eventListener. .buttonbeingfocused contains the same css as "#menu:hover". Here is the script:
var menubuttonfocus = document.getElementsByClassName("menubutton");
for (i=0; i<menubuttonfocus.length; i++) {
menubuttonfocus[i].addEventListener("focus", function() {
menu.classList.add("buttonbeingfocused");
});
menubuttonfocus[i].addEventListener("blur", function() {
menu.classList.remove("buttonbeingfocused");
});
}
if the problem is what I think it is - you forgetting about one thing:
When you focusing / mouseentering the .menubutton - you are mouseleaving #menu and vice-versa - so your menu behaviour is unpredictible because you want to show your menu and hide it at the same time.
solution is usually setting some timeout before running "hiding" part of the script, and clearing this timeout (if exist) when running "showing" part.
it will be something like this:
var menuTimeout;
function showMenu() {
if (menuTimeout) clearTimeout(menuTimeout);
menu.style.backgroundColor = "blue";
menu.style.width = "90%";
}
function hideMenu() {
menuTimeout = setTimeout( function() {
menu.style.backgroundColor = "transparent";
menu.style.width = "8%";
}, 800);
}
//then add your listeners like you did - but put these functions as a handlers - like this:
menu.addEventListener("mouseenter", showMenu);
...
//in addition you need also "mouseenter" and "mouseleave" events handled on .menubuttons
I am working on some jQuery/JavaScript that makes it possible to drag a div around and simultaneously be able to manipulate other divs (specifically images) on the page. The movable div is basically a transparent rectangle that is meant to simulate a lens. The problem I am having is that I cannot figure out how to pass clicks through to the images below the movable div. I have read up on the pointer-events CSS property and tried setting that to none for the movable div, but that makes the movable div no longer movable. Is there a way for me to pass clicks through this movable div while keeping it movable?
EDIT: To all those asking for my current code, here is the JavaScript that I have so far:
<script>
$(document).ready(function(){
$('img').click(function(e) {
$(document).unbind('keypress');
$(document).keypress(function(event) {
if ( event.which == 115) {
$(e.target).css('width', '+=25').css('height', '+=25');
};
if ( event.which == 97) {
$(e.target).css('width', '-=25').css('height', '-=25');
};
});
});
//code to drag the lens around with the mouse
$("#draggableLens").mousemove(function(e){
var lensPositionX = e.pageX - 75;
var lensPositionY = e.pageY - 75;
$('.lens').css({top: lensPositionY, left: lensPositionX});
});
});
</script>
I created a demo that is proof of concept using document.elementFromPoint to locate the nearest image the moveable element is over. I used jQueryUI draggable to simplify event handling.
The trick with using document.elementFromPoint is you must hide the element you are dragging just long enough to look for other elements, or the draggging element is itself the closest element.
Adding an active class to the closest element allows clicking on the viewer to access the active element
Demo code uses LI tags instead of IMG
var $images = $('#list li');
timer = false;
$('#viewer').draggable({
drag: function(event, ui) {
if (!timer) {
timer = true;
var $self = $(this);
/* use a timeout to throttle checking for the closest*/
setTimeout(function() {
/* must hide the viewer so it isn't returned as "elementFromPoint"*/
$self.hide()
var el = $(document.elementFromPoint(event.pageX, event.pageY));
$('.active').removeClass('active');
if ($el.is('li')) {
$el.addClass('active')
}
$self.show()
timer = false;
}, 100);
}
}
}).click(function() {
if ($('.active').length) {
msg = 'Clicked on: ' + $('.active').text();
} else {
msg = 'Click - No active image';
}
$('#log').html(msg + '<br>');
})
DEMO: http://jsfiddle.net/nfjjV/4/
document.elementFromPoint is not be supported in older browsers. You could also use jQuery position or offset methods to compare coordinates of elements with the current position of the viewer for full browser compatibility
I have a vertically-scrolling div within a page that also scrolls vertically.
When the child div is scrolled with the mouse wheel and reaches the top or bottom of the scroll bar, the page (body) begins to scroll. While the mouse is over the child div, I'd like the page (body) scroll to be locked.
This SO post (scroll down to the selected answer) demonstrates the problem well.
This SO question is essentially the same as mine, but the selected answer causes my page contents to noticeably shift horizontally as the scrollbar disappears and reappears.
I thought there might be a solution that leverages event.stopPropagation(), but couldn't get anything to work. In ActionScript, this kind of thing would be solved by placing a mousewheel handler on the child div that calls stopPropagation() on the event before it reaches the body element. Since JS and AS are both ECMAScript languages, I thought the concept might translate, but it didn't seem to work.
Is there a solution that keeps my page contents from shifting around? Most likely using stopPropagation rather than a CSS fix? JQuery answers are welcome as is pure JS.
here's what i ended up with. very similar to #mrtsherman's answer here, only pure JS events instead of jQuery. i still used jQuery for selecting and moving the child div around, though.
// earlier, i have code that references my child div, as childDiv
function disableWindowScroll () {
if (window.addEventListener) {
window.addEventListener("DOMMouseScroll", onChildMouseWheel, false);
}
window.onmousewheel = document.onmousewheel = onChildMouseWheel;
}
function enableWindowScroll () {
if (window.removeEventListener) {
window.removeEventListener("DOMMouseScroll", onArticleMouseWheel, false);
}
window.onmousewheel = document.onmousewheel = null;
}
function onChildMouseWheel (event) {
var scrollTgt = 0;
event = window.event || event;
if (event.detail) {
scrollTgt = -40 * event.detail;
} else {
scrollTgt = event.wheelDeltaY;
}
if (scrollTgt) {
preventDefault(event);
$(childDiv).scrollTop($(childDiv).scrollTop() - scrollTgt);
}
}
function preventDefault (event) {
event = event || window.event;
if (event.preventDefault) {
event.preventDefault();
}
event.returnValue = false;
}
i've noticed the scrolling doesn't match normal scrolling exactly; it seems to scroll a bit faster than without this code. i assume i can fix by knocking down wheelDeltaY a bit, but it's odd that it would be reported differently by javascript than it's actually implemented by the browser...
I usually do it with a small hack listening to the scroll event on the document: it resets the scroll height back to the original one - effectively freezing the document from scrolling but any inner element with overflow: auto will still scroll nicely:
var scrollTop = $(document).scrollTop();
$(document).on('scroll.scrollLock', function() {
$(document).scrollTop(scrollTop);
});
and then when I'm done with the inner scroll lock:
$(document).off('scroll.scrollLock');
the .scrollLock event namespace makes sure I'm not messing with any other event listeners on scroll.
Although this is an old question, here is how I do it with jQuery. This allows you to scroll a list within an outer list, or you can change the outer list to the document to do what the OP asked.
window.scrollLockHolder = null;
function lockScroll(id){
if (window.scrollLockHolder == null){
window.scrollLockHolder = $('#' + id).scrollTop();
}
$('#' + id).on('scroll', function(){
$('#' + id).scrollTop(window.scrollLockHolder);
});
}
function unlockScroll(id){
$('#' + id).off('scroll');
window.scrollLockHolder = null;
}
And you can use it like this:
<ul onmousemove="lockScroll('outer-scroller-id')" onmouseout="unlockScroll('outer-scroller-id')">
<li>...</li>
<li>...</li>
</ul>
what about this:
div.onmousemove = function() { // may be onmouseover also works fine
document.body.style.overflow = "hidden";
document.documentElement.style.overflow = "hidden";
};
div.onmouseout = function() {
document.body.style.overflow = "auto";
document.documentElement.style.overflow = "auto";
};