Why i am getting multiple element appended while clicking the button? - javascript

I just adding a span as parent of text selection. i do 2 ways one using clicking on button another on by pop-up button (on select will appear)
When i click the pop-up button multiple times, i am getting appended as much of (multiple times) spans as parent of my selection.
how to fix this? any one help me?
myjs:
function selHTML() {
var nNd = document.createElement("span");
var w = getSelection().getRangeAt(0);
w.surroundContents(nNd);
$(nNd).addClass('highlight');
}
$("#addText").on('click', function(event) {
event.preventDefault();
$(selHTML());
});
$("div.content").mouseup(function(event) {
var range = window.getSelection().getRangeAt(0);
if (!range.collapsed) {
var bounds = range.getBoundingClientRect();
var x = bounds.left + ((bounds.right - bounds.left - $(".savetooltipAll").outerWidth()) / 2);
var y = bounds.top - $(".savetooltipAll").outerHeight() + $(window).scrollTop();
$(".savetooltipAll").css("top", (y+(bounds.top)) + 'px');
$(".savetooltipAll").css("left",x + 'px');
$(".savetooltipAll").show();
$("button").click(function(){
$(selHTML()); //it calls multiple times...
});
} else {
$(".savetooltipAll").hide();
}
});
$("div.content").mousedown(function(event) {
var range = window.getSelection();
console.log(range.type);
});
Live Demo

You're (re)registering the .click handler every time the .mouseup handler is invoked.
Just do it once, outside of the handler.
Aldo, don't write $() around the call to selHTML() - it's invoking jQuery but will have no effect has you're discarding the result.

$("button").on('click', function(){
selHTML(); //it won't call multiple times... :)
});
$("div.content").mouseup(function(event) {
var range = window.getSelection().getRangeAt(0);
if (!range.collapsed) {
var bounds = range.getBoundingClientRect();
var x = bounds.left + ((bounds.right - bounds.left - $(".savetooltipAll").outerWidth()) / 2);
var y = bounds.top - $(".savetooltipAll").outerHeight() + $(window).scrollTop();
$(".savetooltipAll").css("top", (y+(bounds.top)) + 'px');
$(".savetooltipAll").css("left",x + 'px');
$(".savetooltipAll").show();
} else {
$(".savetooltipAll").hide();
}
});

Related

Javascript event handler with parameter

I'm trying to set the onmousemove event for an svg element. The code below works in chrome, but in firefox it is not setting the onmousemove property correctly every time. After the 2nd change it gets messed up.
mysvg.setAttribute('onmousemove','window.updateXY(evt,' + that.chartNumber + ')');
mysvg is still the correct svg element according to firebug: svg#chart0
the svg property onmousemove says function(e) instead of onmousemove(evt) when it gets messed up, but no error is reported in firebug
Edited to show more code:
var YAxis = function(mysvg,chartNumber){
this.chartNumber = chartNumber;
var that = this;
var g = document.createElementNS(xmlns, "g");
this.id = 'YAxis' + chartNumber;
g.id = this.id;
mysvg.appendChild(g);
var shift = false;
this.selected = false;
this.yScale = function(e){
e.stopPropagation();
that.origY = e.pageY;
that.shift = e.ctrlKey;
mysvg.onmousemove = that.dragY;
mysvg.onmouseup = that.dropY;
}
this.dragY = function(e) {
var chart = charts[that.chartNumber];
if(chart.log)
displayXYText.innerHTML = 'range: ' + Math.round(Math.pow(10,chart.max*(1 + (e.pageY - that.origY)/(chart.height)))*100)/100 + '-' + Math.round(Math.pow(10,chart.min*(1 - (e.pageY - that.origY)/(chart.height)))*100)/100;
else
displayXYText.innerHTML = 'range: ' + Math.round(chart.max*(1 + (e.pageY - that.origY)/(chart.height))*100)/100 + '-' + Math.round(chart.min*(1 - (e.pageY - that.origY)/(chart.height))*100)/100;
}
this.dropY = function(e) {
var chart = charts[that.chartNumber];
if(that.shift){
var range = (chart.max - chart.min)*Math.round((e.pageY - that.origY)/(chart.height)*1000)/1000;
chart.max += range;
chart.min += range;
}else{
var range = chart.max - chart.min;
chart.max *= 1 + Math.round((e.pageY - that.origY)/(chart.height)*1000)/1000;
chart.min *= 1 - Math.round((e.pageY - that.origY)/(chart.height)*1000)/1000;
if(chart.max <= chart.min){
chart.max = chart.min + range;
}
}
mysvg.setAttribute('onmousemove','window.updateXY(event,' + that.chartNumber + ')');
//mysvg.onmousemove = updateXY(e,that.chartNumber);//function() { updateXY(e,that.chartNumber)}; //set back to orig function
//mysvg.setAttribute('onmousemove','updateXY(evt,' + that.chartNumber + ')');
//console.debug(mysvg.onmousemove.textContent);
mysvg.setAttribute('onmouseup','window.mouseUp(event)');
//console.debug("got here onmousemove");
chart.redraw();
}
}
I tried all the methods above but none worked properly in firefox. The solution was to not pass any parameters other than event to the updateXY function. When the other parameters were undefined, run separate logic to determine what the parameters should be in that case. Once the code is in the window frame, you can use setAttribute like you normally do. #FirefoxOOPfail

the drop event is not triggering

am working on a project using jquery,where we have to drag one div and drop on to the map. it is working but 1st wee have to click somewhere in the page then the div is got selected else it will not select and unable to drop..
render: function(){
var leftMatrixTemplate = _.template(Application.Template.Maps.LeftMatrix, {});
$("#left-navigation").html(leftMatrixTemplate).removeClass("hidden");
var detailedViewTemplate = _.template(Application.Template.Maps.DetailedView, {});
$(this.el).html(detailedViewTemplate).removeClass("hidden");
$('div[id^="cu-"]').on('dragstart',function(e){
e.originalEvent.dataTransfer.setData("Text",e.currentTarget.id);
});
$('div[id^="lum-"]').on('dragstart',function(e){
e.originalEvent.dataTransfer.setData("Text",e.currentTarget.id);
});
$('#MapView').on('drop',function(e){
var x = e.originalEvent.clientX + $(this).scrollLeft() - this.offsetLeft;
var y = e.originalEvent.clientY + $(this).scrollTop() - this.offsetTop;
e.originalEvent.stopPropagation();
e.originalEvent.preventDefault();
var data = e.originalEvent.dataTransfer.getData("Text");
var did = 'd'+data;
if (data.match("^cu")){
$(this).append('<div class="dropped cuImg" id="'+did+'"></div>');
}else{
$(this).append('<div class="dropped luminaryImg" id="'+did+'"></div>');
}
$('#'+did).css('left',x).css('top',y);
}).on('dragover', function (e) {
e.preventDefault();
});
}
please help me to come out from this,, thankq

how to check if the scrollbar has reached at the end of div?

function yHandler () {
var show = document.getElementById('show');
var contentHeight = show.offsetHeight;
var yOffset = show.pageYOffset;
var y = yOffset + show.innerHeight;
if(y >= contentHeight) {
alert("ok")
}
}
show.onscroll = yHandler;
how to check if the scrollbar has reached the end of div?
Some code for you to work on:
var scroll = document.getElementById('scroll');
var content = document.getElementById('content');
scroll.onscroll = function(){
var total = scroll.scrollTop + scroll.clientHeight;
if(total == content.clientHeight)
alert('Reached bottom!');
}
http://jsfiddle.net/EY6qP/
Thor's method works perfectly well (+1), but you could also rely on scrollHeight.
(function(scroll){
scroll.onscroll = function(){
if (scroll.scrollTop + scroll.clientHeight == scroll.scrollHeight) {
console.log('hither!');
}
}
})(document.getElementById('scroll'));
Use scrollHeight, scrollTop and clientHeight attributes to detect the scroll bar reached bottom end or not.
function handleScroll() {
var div = document.getElementById("div-id");
if(Math.abs(Math.round(div.scrollHeight - div.scrollTop) - div.clientHeight) > 3) {
console.log("Scroll bar reached bottom end");
return true;
}
return false;
};

scroll other scrollbars with scrollbar

i have 3 divs with scrollbars.
If i scroll in div 1 i want to scroll div 2 and 3 in the opposite direction.
The distance scrolled should be half the distance of div 1.
This is what i have now (small part, rest is in jsfiddle), which works for 1 div.
$("#textBox1").scroll(function () {
console.log("scroll 1");
var offset = $("#textBox1").scrollTop() - scrollPosTBox1;
var half_offset = offset/2.0;
disable1 = true;
if(disable2 == false) {
$("#textBox2").scrollTop(scrollPosTBox2 - half_offset);
}
if(disable3 == false) {
$("#textBox3").scrollTop(scrollPosTBox3 - half_offset);
}
disable1 = false;
});
However, if i try to get the same for the other 2 divs then i can't scroll anything anymore.
This is because div 1 triggers div 2 and div 2 triggers back to div 1 for example.
I tried to fix this with the disable code but it doesn't help.
Can someone help me?
http://jsfiddle.net/XmYh5/1/
No disrespect to #EmreErkan and #Simon for their effort. Here's a no-click version of this.
var $boxes = $("#textBox1,#textBox2,#textBox3"),
active;
$boxes.scrollTop(150);
// set initial scrollTop values
updateScrollPos();
// bind mouseenter:
// 1) find which panel is active
// 2) update scrollTop values
$boxes.mouseenter(function () {
active = this.id;
updateScrollPos();
});
// bind scroll for all boxes
$boxes.scroll(function (e) {
$this = $(this);
// check to see if we are dealing with the active box
// if true then set scrolltop of other boxes relative to the active box
if(this.id == active){
var $others = $boxes.not($this),
offset = $this.scrollTop()-$this.data("scroll"),
half_offset = offset / 2;
$others.each(function(){
$this = $(this);
$this.scrollTop($this.data("scroll") - half_offset);
});
}
});
// utility function:
// assign scrollTop values element's data attributes (data-scroll)
function updateScrollPos() {
$boxes.each(function(){
$this = $(this);
$this.data("scroll",$this.scrollTop());
});
}
Fiddle
You can use a variable to determine active textbox with .mousedown() and do the trick if it's active;
var activeScroll = '';
$("#textBox1").on('mousedown focus mouseenter', function () {
activeScroll = 'scroll1';
}).scroll(function () {
if (activeScroll == 'scroll1') {
console.log("scroll 1");
var offset = $("#textBox1").scrollTop() - scrollPosTBox1;
var half_offset = offset / 2.0;
$("#textBox2").scrollTop(scrollPosTBox2 - half_offset);
$("#textBox3").scrollTop(scrollPosTBox3 - half_offset);
}
});
You can check your updated jsFiddle here.
Finally got a dynamic solution for this, was more complex than I thought but I think I got it:
http://jsfiddle.net/XmYh5/14/
var initialTop = 150,
factor = 2;
$(".textBox")
.addClass('disabled')
.scrollTop(initialTop)
.on('scroll', function () {
var $this = $(this);
if(!$this.is('.disabled')) {
this.lastOffset = this.lastOffset || initialTop;
var offset = $this.scrollTop(),
step = (offset - this.lastOffset) / factor;
$this.siblings().each( function() {
var $this = $(this),
offset = $this.scrollTop() - step;
$this.scrollTop(offset);
this.lastOffset = offset;
});
this.lastOffset = offset;
}
})
.on('mouseenter', function() {
$(this).removeClass('disabled').siblings().addClass('disabled');
});

How to get a list of all elements that resides at the clicked point?

On user click I would like to get a list of all elements that resides at the clicked point.
For example, if user clicks on Hello here:
<div><span>Hello<span></div>
I would like to get the following list:
<span> element
<div> element
<body> element
<html> element
What would be the easiest method to get these elements ?
EDIT: Based on clarification, I think this is what you mean:
EDIT: As pointed out by #Misha, outerWidth() and outerHeight() should be used in lieu of width() and height() in order to get an accurate range.
Also, if there's nothing to prevent event bubbling on the page, then the click should be placed on the document as it will be much more efficient. Even if some other click handler prevents bubbling, you should still have the click on the document, and just handle it separately from those handler that prevent bubbling.
Example: http://jsfiddle.net/57bVR/3/
$(document).click(function(e) {
var clickX = e.pageX
,clickY = e.pageY
,list
,$list
,offset
,range
,$body = $('body').parents().andSelf();
$list = $('body *').filter(function() {
offset = $(this).offset();
range = {
x: [ offset.left,
offset.left + $(this).outerWidth() ],
y: [ offset.top,
offset.top + $(this).outerHeight() ]
};
return (clickX >= range.x[0] && clickX <= range.x[1]) && (clickY >= range.y[0] && clickY <= range.y[1])
});
$list = $list.add($body);
list = $list.map(function() {
return this.nodeName + ' ' + this.className
}).get();
alert(list);
return false;
});​
Original answer:
This will give you an Array of the tag names including the span. Couldn't quite tell if this is what you wanted.
It uses .parents() along with .andSelf() to get the elements, then uses .map() with .get() to create the Array.
Example: http://jsfiddle.net/9cFTG/
var list;
$('span').click(function() {
list = $(this).parents().andSelf().map(function() {
return this.nodeName;
}).get();
alert(list);
});​
If you just wanted the elements, not the tag names, get rid of .map() and .get().
Or if you wanted to join the Array into a String using some sort of separator, just add .join(" ") after .get(), placing your separator inside the quotes.
In the near future this should be possible:
$(document).click(function(e) {
var family = this.elementsFromPoint(e.pageX, e.pageY);
$(family).each( function () {
console.log(child);
});
});
Update 2019
Currently in editors draft:
Elements from point
use parent method to get parent of the current tag recursively or in cycle:
var parentTag = $(this).parent().get(0).tagName;
The jQuery parents() function can do this for you.
To attach a click event to all span tags, for example:
$("span").click(function() {
var parents = "";
$(this).parents().map(function () {
parents = parents + " " + this.tagName;
})
alert(parents);
});
Try something like this
$('span').click(function() {
var parents = $(this).parents();
for(var i = 0; i < parents.length; i++){
console.log($(parents[i]).get(0).tagName)
}
});
check the live demo
http://jsfiddle.net/sdA44/1/
Just javascript implementation:
window.addEventListener('click', function(e){
console.log(document.elementFromPoint(e.pageX, e.pageY))
}, false)
Worked for me in firefox and chrome as of 3-29-2017
Found this:
https://gist.github.com/osartun/4154204
Had to change elements.get(i) to elements[i] to fix it...
I have updated the demo http://jsfiddle.net/57bVR/3/, adding to the code the logic to manage also (if present):
The scrolling of the page
The zoom level html tag (in the project I work it gives to me several troubles)
$(document).click(function (e) {
var htmlZoom = window.getComputedStyle(document.getElementsByTagName('html')[0]).getPropertyValue('zoom');
var clickX = e.pageX,
clickY = e.pageY,
list,
$list,
offset,
range,
$body = $('body').parents().andSelf();
$list = $('body *').filter(function () {
offset = $(this).offset();
marginLeft = offset.left * htmlZoom - $(document).scrollLeft();
marginTop = offset.top * htmlZoom - $(document).scrollTop();
outerWidth = $(this).outerWidth() * htmlZoom;
outerHeight = $(this).outerHeight() * htmlZoom;
range = {
x : [marginLeft,
marginLeft + outerWidth],
y : [marginTop,
marginTop + outerHeight]
};
return (clickX >= range.x[0] && clickX <= range.x[1]) && (clickY >= range.y[0] && clickY <= range.y[1])
});
$list = $list.add($body);
list = $list.map(function () {
return this.nodeName + ' ' + this.className
}).get();
alert(list);
return false;
});

Categories