I'm dynamically generating a div using JavaScript. When mouse is over certain elements in the page the new div appears. On mouseout it disappears. All that is working fine. But I want the div to be top-positioned according to the element the mouse was over of. So I record the position of the element with getBoundingClientReach:
function lopen(AbstId) { //called OnMouseOver
var rect = document.getElementById(AbstId).getBoundingClientRect();
var st3="px";
divtop = rect.top+st3 ;
alert ("Hello :" + divtop); //for checking purposes only
if (this.element == null) {
this.element = document.createElement('div');
this.element.id = "myPopup";
this.element.className = "myPopupBody";
this.element.onmouseover = 'prevent()'; //if mouse over new div, do not close
this.element.style["top"] = divtop; //HERE IS MY PROBLEM
}
document.body.appendChild(this.element);
popUpDetails();
}
function lclose () { //called OnMouseOut
document.getElementById("myPopup").innerHTML = " ";
document.body.removeChild(this.element);
}
The piece of code
this.element.style["top"] = divtop;
is getting the correct top value on first event, but do not actualize for further onmouseover events, even though divtop is actually refreshing (I check with the alert of 5th line).
Does anyone spot the problem?
Again, just for completeness. The problem was an incorrect assignment of style: top. Below the right code
function lopen(AbstId) { //called OnMouseOver
var rect = document.getElementById(AbstId).getBoundingClientRect();
var st3="px";
divtop = rect.top+st3 ;
//alert ("Hello :" + divtop); //for checking purposes only
if (this.element == null) {
this.element = document.createElement('div');
this.element.id = "myPopup";
this.element.className = "myPopupBody";
this.element.onmouseover = 'prevent()'; //if mouse over new div, do not close
//this.element.style["top"] = divtop; //here WAS my problem -deleted line
}
document.body.appendChild(this.element);
document.getElementById("myPopup").style["top"] = divtop; //here right code
popUpDetails();
}
Related
I have an event listener that is listening for a click event inside of a media query, if when the window is under 500px. Likewise I have one that is listening for a click event if the window is wider than 500px.
Once the buttons have been clicked within both states, the code works as I would like. However I have the following issue I would like to solve:
When the window is smaller than 500px and the button is clicked it displays the content as required, though when the window is dragged to be wider than 500px, the button then needs to be clicked again to show the content.
As I say this works fine once buttons have been clicked when the window is wider than 500px and then again under 500px, the correct content shows when the window is dragged back and forth.
What I would like to know is how to do the following:
When the button is clicked when the window is under 500px and then dragged out, the corresponding content is displayed without having to press the button again. I also want this to be the case when the window is wider than 500px and dragged to below this value.
Please see the JSFiddle here
Is there a way to somehow make an eventlistener for the element that has already been clicked and do it this way?
//Start listing variables for use in array.
var art1 = document.getElementById("article1");
var button1 = document.getElementById("btn1");
var art2 = document.getElementById("article2");
var button2 = document.getElementById("btn2");
var art3 = document.getElementById("article3");
var button3 = document.getElementById("btn3");
var articleArray = [art1, art2, art3];
var buttonArray = [button1, button2, button3];
function mediaQuery(x) {
//If window is under 500px in width.
if (x.matches) {
//Begin accordion code
var initAccordion = function(accordionElement) {
function handlePanelClick(event) {
showPanel(event.currentTarget);
}
function showPanel(panel) {
var expandedPanel = accordionElement.querySelector(".active");
if (expandedPanel) {
expandedPanel.classList.remove("active");
}
panel.classList.add("active");
}
var allPanelElements = accordionElement.querySelectorAll(".panel");
for (var y = 0; y < allPanelElements.length; y++) {
allPanelElements[y].addEventListener("click", handlePanelClick);
}
//showPanel(allPanelElements[0]);
}
initAccordion(document.getElementById("contentWrapper"));
} else { // If window if is over 500px in width.
//Begin button code.
var createfunc = function(i) {
return function() {
document.getElementById("fillMe").innerHTML = articleArray[i].innerHTML;
};
}
for (let i = 0; i < articleArray.length; i++) {
let button = buttonArray[i];
button.addEventListener("click", createfunc(i));
}
}
}
//Declare media query and add listener.
var x = window.matchMedia("(max-width: 500px)")
mediaQuery(x) // Call listener function at run time
x.addListener(mediaQuery) // Attach listener function on state changes
I have a list of news and I can modify the news. When I modify one she stay at her inital position (if she was at place 5 she stay here). But when I click "modify this new" a form pop to the bottom of the page and then when I submit the modifications I want to scroll to this modified new. To do that I would use something like
find position where label.text() == titleModified
then I could do
window.scrollTo(0,result of the line above);
For the moment I tried to do document.getElementById but it always bring me to the top of the page...
Thank you for helping me
PS: there is a link on Plunker to see the structure of news : https://plnkr.co/edit/mLCxPYaBR56KkEOLNF8F?p=preview
and this is my JS for the modification:
'submit .modifyArticle'(event) {
event.preventDefault();
const target = event.target;
const textModif = target.textModif.value;
const titreModif = target.titreModif.value;
const photoModif = target.photoModif.value;
const idModif = Session.get('idTemp');
//test if values from the from are not empty or whitespaced
if ((/\S/.test(textModif))||(/\S/.test(titreModif))) {
console.log("2ème étape: dans body.js -> submit .modifyArticle");
Meteor.call('articles.modify',idModif,textModif,titreModif,photoModif);
Session.set('wantModif',false);
//here my new is modified so I want to scroll to her
//var titreModified actually contains the title after the modification but only for the first new...
setTimeout(function(){
var titreModified = document.getElementById("titreArticle");
var position = titreModified.offsetTop;
console.log("Y: " + position);
console.log("var titreArticleModif: "+ titreModified.textContent);
}, 50)
[...]
EDIT (i'll put the solution here but the real hero is #alexr101): First I had to add a class to my label <label class="titreArticle">{{titre}}</label>
then this is the JS:
`setTimeout(function(){
$('.titreArticle').each(function(i, obj) {
if(obj.textContent.includes(titreModif)){
alert("le titre devrait être: " + obj.textContent);
var position = obj.offsetTop;
window.scrollTo(0,position);
return false;
}
});
}, 20)`
the timeout is here because it's not 100% real-time and I had to wait until the new title was put in the DOM.
Try getting the y position of the element like so:
//get modified element
var titleModified = document.getElementById("modifiedElement");
//get y position of element through offsetTop function
var yPosition = titleModified.offsetTop;
//Set scroll amount
window.scrollTo(0, yPosition );
Would that work?
JS only. On mouseover I'm calling a function I made that creates a div element with an image inside.
I pass (this) as a parameter to the function. The function works and onmouseover it creates a child element and I can click it. However, If I add on mouse out of the div to remove itself, it will only do so if I hovered over it. If I didn't, the div stays and on next hover it adds another one. If I add on mouse out of the parent element to remove the div, I cannot get to hover over the child div, cause as soon as I leave the parent, the child div is removed. The parent element is an (a href) inside a "TD" in a table. The code goes like this:
<script type="text/javascript">
function PopPanel(ownerElem) {
var myParent = ownerElem.parentNode;
var popanel = document.createElement("div");
popanel.className = "divPopPanel";
popanel.setAttribute("display", "block")
var phoneimg = document.createElement("img");
phoneimg.src = '/images/ImageAdditions/Phone.png';
phoneimg.className = "popupPhone";
popanel.appendChild(phoneimg);
phoneimg.onclick = function () {
try {
location.replace("Mylauncher:\\\\nas\\vol5\\SYSTEM\\ITR\\Scripts\\SomeProgram.exe" + " " + ownerElem.innerText);
}
catch (err) {
}
};
myParent.appendChild(popanel);
popanel.onmouseout = function (e) { this.parentNode.removeChild(this) }; //this removes itself on mouseout.
myParent.onmouseout = function (e) { popanel.parentNode.removeChild(popanel) }; // this removes the child element of the parent (which is the same element as above) on mouse out.
};
Well, after a long and miserable trial and error session, I've figured this out.
First I've modified the code that generates and populates the gridview with data, like this:
VB.net
dt.Columns.Add("InternalPhoneDialer", Type.GetType("System.String"))
Dim rn As New Random
Dim randNum As Integer = rn.Next(12, 428)
Dim internalphone As String = dr("InternalPhone").ToString
If internalphone.Contains(" ") Then
internalphone = internalphone.Substring(0, internalphone.IndexOf(" "))
internalphone = internalphone & randNum.ToString()
Else
internalphone = internalphone & randNum.ToString()
End If
//Substitute the current column with the newly created one above
dr("InternalPhoneDialer") = "<div id='popPanelWrapper" & internalphone & "' onmouseover='PopPanel(" & "popPanelWrapper" & internalphone & ");' onmouseleave='PopPanelClose(" & "popPanelWrapper" & internalphone & ");'> <a class='popPanelLink' href='javascript:void(0);' >" & dr("InternalPhone") & "</a> </div>"
I have made sure that I concatenate a unique id to each div in case the phone number is the same for another column (where I implement the same solution). So I added the column inner content + a random number and concatenated it to the DIV name.
Then, on client side I've modified my script like this:
JavaScript
<script type="text/javascript">
function PopPanel(ownerElem) {
var myParent = ownerElem;
var phoneimgexist = !!document.getElementById("popupPhone");
if (phoneimgexist) {
return
} else {
var phoneimg = document.createElement("img");
phoneimg.src = '/_layouts/15/images/ImageAdditions/Phone.png';
phoneimg.id = "popupPhone";
phoneimg.setAttribute("display", "block")
myParent.appendChild(phoneimg);
}
phoneimg.onclick = function () {
try {
location.replace("launcher:\\\\drive01\\vol1\\SYSTEM\\ITR\\Scripts\\Jabber.exe" + " " + ownerElem.innerText);
}
catch (err) {
}
};
};
function PopPanelClose(ownerElem) {
var myParent = ownerElem;
var phoneimg = document.getElementById("popupPhone");
var phoneimgexist = !!document.getElementById("popupPhone");
if (phoneimgexist) {
phoneimg.parentNode.removeChild(phoneimg);
} else {
return
}
};
Now, on mouse over a GridVew cell that contains a phone number I get an icon. By clicking it I can call the number.
In my opinion this solution is much better suited for the task, instead of creating a hidden div with image and data for every row in what could be thousands of entries in the GridView.
This no doubt saves a lot of resources.
I am trying to animate a dynamically created div with javascript, the id for the div is assigned when it is created, everything works fine until I attempt to animate one of the divs, I am trying this :
function start() // Called from a button click
{
var moveDiv= document.getElementById('Id0'); // Id0 is the Id of the div to move
animate(moveDiv); // Recursive animate
}
function animate(inDiv)
{
inDiv.style.left = parseInt(inDiv.style.left)+1+'px';
setTimeout(animate,20); // Recursive call
}
I know this is supposed to move the div infinitely to the left. However nothing happens at all and I cannot figure out why, I don't think its the fact that I dynamically create the divs as I have checked all the Id's and they all exist so I don't think its because it can't find Id0, but just incase here is a snippet of my div creation code :
for(var i=0; i<ca.length; i++)
{
var c = ca[i].trim();
var start = c.indexOf('"coursename":"') + 14;
var end = c.indexOf('","coursemark":"');
var CC = c.substring(start,end);
var start = c.indexOf('","coursemark":"') + 16;
var end = c.indexOf('%"')+1;
var CM = c.substring(start,end);
var idCount = i;
var div = document.createElement("div");
div.style.width = "180px";
div.style.height = "75px";
div.style.backgroundColor = "rgba(0,100,175,0.8)";
div.style.color = "white";
div.style.marginTop = "2%";
div.style.marginLeft = "50%";
div.id = "sortID"+idCount;
div.innerHTML = "Course Name : " + CC + " Course Mark : " + CM + " Id : " + div.id;
document.body.appendChild(div);
}
This code works fine however and creates the divs perfectly, I just can't get any div to move. Any help would be greatly appreciated.
Couple of problems...
function start() // Called from a button click
{
var moveDiv= document.getElementById('Id0'); // Id0 is the Id of the div to move
animate(moveDiv); // Recursive animate
}
There is no element with ID of Id0. All of your generated element IDs look like sortID...
And then...
function animate(inDiv)
{
inDiv.style.left = parseInt(inDiv.style.left)+1+'px';
setTimeout(animate,20); // Recursive call
}
inDiv.style.left has never been initiated
You're not passing inDiv through to your recursive animate call
So firstly check your element references. Then make sure you're setting the position of the div correctly, or handling scenarios where it isn't yet set. And finally make sure you pass inDiv through recursively.
I have this jsfiddle which works once.
function toggle_off(itemID){
alert(itemID+'->'+document.getElementById(itemID).getAttribute("style"));
document.getElementById(itemID).style.display = 'none';
}
function maskIt(x){
alert(x);
var mask = document.createElement('div');
mask.id = 'maskIt';
mask.setAttribute("class", "maskIt");
mask.onclick = function(){toggle_off('maskIt');}
mask.innerHTML = 'click to close mask';
document.body.appendChild(mask);
}
On click it opens a mask (layer), on mask click - closes it self - all fine up to here.
On second click, the mask opens again, but when you click on it the second time it won't close.
Any ideas?
Instead of hiding the div you should remove it as you are creating a new div each click
function toggle_off(itemID){
alert(itemID+'->'+document.getElementById(itemID).getAttribute("style"));
var mask = document.getElementById(itemID);
mask.parentNode.removeChild(mask);
}
DEMO
You are not destroying the first instance of "maskIt" when you close the overlay, so they build up in the background. If you inspect the page after the second click, you will see two maskIt divs, the first one hidden.
When you call getElementById('maskIt'), it will find the first, hidden, one in the document, and so not hide the second.
Why not reuse the first mask?
function toggle_off(itemID) {
alert(itemID + '->' + document.getElementById(itemID).getAttribute("style"));
document.getElementById(itemID).style.display = 'none';
}
function maskIt(x) {
alert(x);
var mask = document.getElementById('maskIt');
if (mask == null) {
mask = document.createElement('div');
mask.id = 'maskIt';
mask.setAttribute("class", "maskIt");
mask.onclick = function () {
toggle_off('maskIt');
}
mask.innerHTML = 'click to close mask';
document.body.appendChild(mask);
}
else
{
mask.style.display = "block";
}
}
http://jsfiddle.net/dFp6f/2/