Links not working inside div element that appears on mouse over - javascript

I'm creating a JavaScript function which will parse data (which will be retrieved from a database, but its just static here for testing) and format it into links and place it into a div element (popup) that will show up when the mouse is hovered onto the icon. However, I cannot figure out why the links are not clickable. I can right click it and open it in a new tab, but I cannot directly click and open them. Also, it works on Firefox, but not Chrome, or Safari!
EDITED:
Here is the code in JSFiddle:
https://jsfiddle.net/kvdju2ju/2/
HTML
<table>
<tr>
<td>
<div id="p1" class="parent">
<img src="http://www.free-icons-download.net/images/blue-square-icon-47147.png" style="border-width:0px;"/>
<div id="p1data" class="data" style="display:none">
Website1#http://www.google.com#Website2#http://www.Link2.com#Website3#http://www.Link3.com"
</div>
<div id="p1popup" class="popup" style="display: none">
</div>
</div>
</td>
</tr>
</table>
CSS
.parent {
position: relative;
}
.parent .popup {
display: block;
position:absolute;
top: 0px;
left:20px;
background-color: #FFFFFF;
padding: 5px;
outline: black solid 1px;
}
.parent:hover .popup {
display: block;
position:absolute;
top: 0px;
left:20px;
background-color: #FFFFFF;
z-index: 100;
outline: black solid 1px;
}
.popup a:link { color: #003300; text-decoration: none;}
.popup a:visited { color: #003300; }
.popup a:hover { color: #006600; }
.popup a:active { color: #006600; }

You can add the nodes like this (It works on Chrome):
function parseWebsites() {
var text = document.getElementById('p1data').innerHTML;
var lines = text.split("#");
var string = "";
var myNode = document.getElementById("p1data");
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
for (var i = 0; i < lines.length - 1; i = i + 2) {
var webtitle = lines[i];
var website = lines[i + 1];
//string = string + "<a href='" + website + "' target='_blank'>" + webtitle + "</a> <br> ";
var node = document.createElement("a"); // Create a <a> node
var textnode = document.createTextNode(webtitle); // Create a text node
node.appendChild(textnode); // Append the text to <a>
node.href = website;
node.target = "_blank";
document.getElementById("p1popup").appendChild(node); // Append <a> to <div> with id="p1popup"
var br = document.createElement("br"); // Create a <br> node
document.getElementById("p1popup").appendChild(br);
}
//document.getElementById("p1popup").innerHTML = string;
}
https://jsfiddle.net/s8st79w0/1/

Does this only have to work on desktop if so, you're fine but I don't know if it would work on mobile.
If you want some cleaner code and cut out the JS which I think is adding some complexity and requires some extra loading on the browser part, I would try a CSS only approach with :hover. You can achieve the same affect. An example is below. Also, I think linkedin uses this approach for there nav. I think bettycrocker.com and pillsbury.com uses this as well.
http://www.w3schools.com/howto/howto_css_dropdown.asp

You don't have an anchor and you don't have href
you have missing href
try adding one
<a id="p1" class="parent" href='https://www.google.com'>
<div>
<img src="http://www.free-icons-download.net/images/blue-square-icon-47147.png" style="border-width:0px;" />
<div id="p1data" class="data" style="display:none">
website1#http://www.google.com#Website2#http://www.Link2.com#Website3#http://www.Link3.com"
</div>
</div>
</a>

Related

Clone div based on content of span

There are random number of div's as show below, I am trying to clone these div on click. when cloning I want to change the content to actual content + no of clones it has (based on content of span , not the id or classes of "clone-this")
eg.
If I click the first "chrome" div, since the body already have "chrome (1) and chrome (2)" , div with content "chrome (3)" Should appear .
If I click the 2nd div ie. "Mozilla Firefox", since there is no cloned version, a div with content "Mozilla Firefox (1)" should appear.
and so on.
I tried to make this, but when i clone the count is based on class , not the content . so clicking on "chrome" div will clone "chrome (5)" not "chrome (3)" .
Also in my implementation when i click the "chrome (1)" div, it will clone as "chrome (1)(5)" . I want this to be like "chrome (3)"
how can i achieve this?
note that there will be any number of divs at first. 5 is just for and example.
jsfiddle here
$(document).on('click', '.clone-this', function(){
var CloneContainer = $(this).clone();
var no = $('.clone-this').size();
CloneContainer.html(CloneContainer.html() + " (" + no + ")");
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
To accomplish that, you should check "content" of each item and count the number of elements which have same text. But, there is one problem here; each element (for example Chrome, Chrome (1), Chrome (2)) has different content. So, you may split the text using parenthesis or you may use RegEx (recommended).
$(document).on('click', '.clone-this', function(){
var CloneContainer = $(this).clone();
var content = CloneContainer.find('span').html().split(' (')[0];
var no = $(".clone-this:contains('"+content+"')").size();
CloneContainer.html( CloneContainer.html() .split(' (')[0] + " (" + no + ")" );
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
On the snippet above, you may see basic version of it. But you MUST consider the "similar content" issue like following.
Chrome
Chrome Mobile
Firefox
Firefox Mobile
Here is another way to get you going. I "trim" the clicked div to its base name and then loop through the divs and get the length of all which contain the same base name.
After that I modify the cloned element to fill in the right count of the cloned element appropriately:
var regExp = /\([0-9]+\)/;
$('.clone-this').click(function(e){
var target = e.target.textContent;
var matches = regExp.exec(target);
var elements = $('.clone-this');
var count = elements.length;
var index = 0;
if (null != matches) {
target = matches.input.substr(0, matches.input.lastIndexOf(" "));
}
for(var i = 0; i < count; i++){
index += (elements[i].textContent.indexOf(target) > -1) ? 1: 0;
}
var CloneContainer = $(this).clone();
CloneContainer.html(CloneContainer.html().split('(')[0] + "(" + index + ")" );
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>

javascript - remove element from div when button inside is pressed

I have a div that looks like this:
<div id="contact-segments">
<div class="contact-segment-item doesnt-include">
<div class="segment-content pull-left" style="width: 80%">
<p>LOL</p>
</div>
<div class="pull-right">
<a href="your link here">
<i class="white-segment-icon fa fa-times"></i>
</a>
</div>
</div>
</div>
Whenever someone presses an add button, I add another contact-segment-item div to the contact-segments div through JavaScript with this function:
function createUserSegment(tags) {
var div = document.createElement("div");
div.className = 'contact-segment-item includes'
div.innerHTML = "<div class='segment-content pull-left' style='width: 80%''> <p>" + tags + "</p> </div> <div class='pull-right'> <a href='your link here'> <i class='white-segment-icon fa fa-times'></i></a> </div>";
document.getElementById("contact-segments").appendChild(div);
}
As you can see, the divs that are getting added through JavaScript have an a tag that shows a button with an "x".
How can I remove the contact-segment-item when the "x" is pressed inside of it?
Here's how each of them look so it's easier to picture.
I can link the "x" button click to javascript but how do I know which child of contact-segments to delete and also how do I get the p of it before it's deleted.
When the user presses the "x" on this div, I want to get the p or in this case Woop! so I can do something with it but then also delete that contact-segment-item
Thanks
Instead of using .innerHTML we nest nodes with appendChild. Finally for our close i button we add onClick event handler. We pass there our div node, and use remove() method to remove the node.
EDIT:
Added css.
Do not use a if your anchors only needs to delete your segments. For example use only i without wrapping a and add a cursor: pointer style to it.
See working example:
function createUserSegment(tags){
var div = document.createElement("div");
div.className = 'contact-segment-item includes';
var tagInfo = document.createElement("div");
tagInfo.className = 'contact-segment-item__text';
tagInfo.innerHTML = tags;
var closeButton = document.createElement("i");
closeButton.className = 'contact-segment-item__closeButton white-segment-icon fa fa-times';
closeButton.onclick = function() {
div.remove();
};
div.appendChild(tagInfo);
div.appendChild(closeButton);
document.getElementById("contact-segments").appendChild(div);
}
#contact-segments {
max-width:350px;
width: 100%;
}
.contact-segment-item {
display: block;
position: relative;
width: 100%;
background: #00B792;
border-radius: 8px;
line-height: 40px;
clear: both;
padding: 20px 30px;
margin-bottom: 10px;
}
.contact-segment-item__anchor::after {
clear: both;
}
.contact-segment-item__text {
display: inline-block;
color: #fff;
}
.contact-segment-item__closeButton {
display: inline-block;
cursor: pointer;
color: #fff;
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<button id="add-new" onClick="createUserSegment('new one')">Add new segment</button>
<br/>
<div id="contact-segments">
</div>

display a div below a selected input field? No JQuery

how to display a div everytime a user focus on a input field. there is already a div and it is hidden. the position of the div will change depending on the position of the selected field and it will be display below
this is my code
formFieldListWrapper.style.top = ((((formSelectedFieldInput.offsetTop > (formWrapper.offsetHeight/2))?((formSelectedFieldInput.offsetTop-(formWrapper.offsetHeight/2))-(formSelectedFieldInput.offsetHeight+formWrapper.offsetHeight*0.02)):(formSelectedFieldInput.offsetTop))/formWrapper.offsetHeight)*100) + "%";
formFieldListWrapper.style.left = ((formSelectedFieldInput.offsetLeft/formWrapper.offsetWidth)*100) + "%";
Why use javascript? This could be chieved by using CSS only
HTML
<div class="holder">
<input type="text" />
<div class="dropdown">
<p>Testing</p>
<p>Css ONLY</p>
<p>Dropdown</p>
</div>
</div>
CSS
.holder {
position: relative;
}
.dropdown {
position: absolute;
border: 1px solid red;
display: none;
}
input:focus + .dropdown {
display: block;
}
UPDATE
little bit misred the question, if You need to position div dynamically like in this fiddle, You cloud use:
HTML
<div class="holder">
<input type="text" />
</div>
<div class="holder" style="margin-top: 30px;">
<input type="text" />
</div>
<div class="dropdown">
<p>Testing</p>
<p>Css ONLY</p>
<p>Dropdown</p>
</div>
CSS
.holder {
position: relative;
}
.dropdown {
position: absolute;
border: 1px solid red;
display: none;
z-index: 1;
background: white;
}
input:focus + .dropdown {
display: block;
}
Javascript to position dropdown div
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('focus', function(){
this.parentNode.appendChild(document.querySelector('.dropdown'));
});
}
Try the following:
formSelectedFieldInput.addEventListener("focus", setDivToInput, false);
function setDivToInput(e)
{
var inputElement = e.target; //e.target refers to the element that fired the event.
formFieldListWrapper.style.top = inputElement.offsetTop + formFieldListWrapper.offsetHeight + "px";
formFieldListWrapper.style.left= inputElement.offsetLeft + "px";
formFieldListWrapper.style.display = "block";
}
The first line adds a focus event to the input. This sets the div to the input based upon it's position on the page. This is very basic and doesn't behave well when the div runs of the screen. You need to add logic for that.
Now for multiple inputs in a form
var nodes = form.querySelectorAll("input"); //replace with your form element
for (var i = 0; i < nodes.length; ++i)
{
nodes[i].addEventListener("focus", setDivToInput, false);
}
function setDivToInput(e)
{
var node = e.target;
formFieldListWrapper.style.top = node.offsetTop + formFieldListWrapper.offsetHeight + "px";
formFieldListWrapper.style.left= node.offsetLeft + "px";
formFieldListWrapper.style.display = "block";
}
This code sets the focus event to all inputs in the form.

Fault reading of background color

I have css file with property: "background:#f9f9f9;". The div has the right background color but when I read it the result is empty (""). The function then changes the background color and when I read it again it shows me: "background: none repeat scroll 0% 0% rgb(249, 249, 249)". The new color is right but it was shown only after I changed the color using js.
Why does it happens? Is there any way to fix it?
(I know I can initialize it manually using js with the right color, and I'm going to do it until I find the right solution).
Edit: inserted code.
.cLiftsDiv {
float:left;
display: table-cell;
text-align: center;
vertical-align: middle;
width: 15%;
border:1px solid #111111;
background:#f9f9f9;
border-radius: 5px;
height: 80%;
cursor: default;
/* to be unselectable */
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
margin: 2% 2%;
position:relative;
}
JS functions:
var items = new Array("Lifts");
var elem = document.getElementById("mainMonitor");
for (var i = 0; i < items.length; ++i)
{
var tempDiv = document.createElement("div");
tempDiv.id = items[i] + "Div";
tempDiv.className = "c" + items[i] + "Div";
var tempInnerDiv = document.createElement("div");
tempInnerDiv.innerHTML = items[i];
tempDiv.appendChild(tempInnerDiv);
tempDiv.onmouseover = hoverDiv;
elem.appendChild(tempDiv);
}
function hoverDiv()
{
var elem = document.getElementById(this.id);
alert("background: " + elem.style.background);
if (elem.style.background != "#aaaaaa")
{
//elem.style.background = "#cccccc";
}
}
I use firefox (and it doesn't work too in chrome).
We need more code to help here but is background color which works fine:
<!DOCTYPE html>
<html>
<head>
<style>
span.highlight
{
background-color:yellow;
}
</style>
</head>
<body>
<p>
<span class="highlight">This is a text.</span> This is a text. This is a text. This is a text. This is a text. This is a text. This is a text. This is a text. This is a text. <span class="highlight">This is a text.</span>
</p>
</body>
</html>
Working with JavaScript alerting the color: JS Fiddle
You should try this instead:
//On page ready
var color = "#fff";
$("item selctor").css("background-color",color);

CSS fix for webgrid's pager method using Razor and MVC3

I am using MVC3 with Razor, for display a grid I am using a WebGrid, and for paging for this very grid I am using the following code.
My problem : The paging-buttons should keep the same size both when they are selected/clicked and when they are not selected/clicked.
I am having some css problems, I have used CSS and javascript to achieve a design which my client wanted I have replicated it at this fiddle link http://fiddle.jshell.net/Z5L4g/
Razor Code
#grid.Pager(mode: WebGridPagerModes.All, numericLinksCount: 15, firstText: "<<", lastText: ">>", previousText: "<", nextText: ">")
My CSS Code
body {
font-family: Calibri;
background-color:
#D8D8D8;
margin-top: 0px;
text-decoration:none;
}
#footer:not([href]) {
letter-spacing: 0px;
}
#footer {
text-align: center;
margin-top: 10px;
}
.pagingCss {
font-size: 13px;
}
.whiteBox {
background-color:
white;
color:
black;
padding-right: 7px;
padding-left: 7px;
padding-top: 4px;
padding-bottom: 4px;
text-decoration: none;
margin-top: 10px;
letter-spacing: 0px;
}
.blackBox {
background-color:
black;
color:
white;
padding-right: 7px;
padding-left: 7px;
padding-top: 4px;
padding-bottom: 4px;
text-decoration: none;
margin-top: 10px;
letter-spacing: 0px;
}
.pagingCss a {
font-size: 13px;
color: white;
text-decoration:none;
}
Javascript Code I have used
var keywords = ['>>', '<<', '<', '>'];
function linklabels() {
var footerDiv = document.getElementById('footer');
var oldLinks = footerDiv.getElementsByTagName('A');
var oldLinksCount = oldLinks.length;
var keywordsCount = keywords.length;
for (var i = 0; i < oldLinks.length; i++) {
if (oldLinks[i].firstChild.nodeValue == '>>' || oldLinks[i].firstChild.nodeValue == '<<' || oldLinks[i].firstChild.nodeValue == '>' || oldLinks[i].firstChild.nodeValue == '<') {
var my_div = null;
var newDiv = null;
var newDiv = document.createElement("span");
var newContent = document.createTextNode(oldLinks[i].firstChild.nodeValue);
newDiv.appendChild(newContent);
newDiv.className = "whiteBox";
oldLinks[i].firstChild.nodeValue = "";
oldLinks[i].appendChild(newDiv);
}
else {
var my_div = null;
var newDiv = null;
var newDiv = document.createElement("span");
var newContent = document.createTextNode(oldLinks[i].firstChild.nodeValue);
newDiv.appendChild(newContent);
newDiv.className = "blackBox";
oldLinks[i].firstChild.nodeValue = "";
oldLinks[i].appendChild(newDiv);
}
} // end of for
// footer
}
window.onload = linklabels;
Here is how my HTML is render after using the above code
and the code is rendered as html is below
<div id="footer" class="pagingCss">
<a href="/CompanySearch/Home/Results?page=1">
<span class="whiteBox"><<</span>
</a>
<a href="/CompanySearch/Home/Results?page=5">
<span class="whiteBox"><</span>
</a>
<a href="/CompanySearch/Home/Results?page=1">
<span class="blackBox">1</span>
</a>
<a href="/CompanySearch/Home/Results?page=2">
<span class="blackBox">2</span>
</a>
<a href="/CompanySearch/Home/Results?page=3">
<span class="blackBox">3</span>
</a>
<a href="/CompanySearch/Home/Results?page=4">
<span class="blackBox">4</span>
</a>
<a href="/CompanySearch/Home/Results?page=5">
<span class="blackBox">5</span>
</a>
6 <a href="/CompanySearch/Home/Results?page=7">
<span class="blackBox">7</span>
</a>
<a href="/CompanySearch/Home/Results?page=8">
<span class="blackBox">8</span>
</a>
<a href="/CompanySearch/Home/Results?page=9">
<span class="blackBox">9</span>
</a>
<a href="/CompanySearch/Home/Results?page=10">
<span class="blackBox">10</span>
</a>
<a href="/CompanySearch/Home/Results?page=7">
<span class="whiteBox">></span>
</a>
<a href="/CompanySearch/Home/Results?page=10">
<span class="whiteBox">>></span>
</a>
</div>​
I know there has to be really easy some way or trick to do this, which I just cannot find... please help me out on this.
As I said in the comments,
don't try to heal the symptoms. In your case a CSS fix won't do the trick because there is no selector for text nodes.
a quick jquery fix would to the trick though:
$(function() {
$("#footer").contents().filter(function() {
var $this = $(this);
return $this.children().length == 0 && $.trim($this.text()).length > 0;
}).wrap("<span class='selectedBox' />");
});
This will wrap your lone text element with a span with class selectedBox for which you have to add some css.
You can see it in action here.
UPDATE
here is a complete solution
This also replaces your linklabels javascript code:
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
$(function() {
$("#footer a").contents().wrap("<span class='blackBox' />");
$("#footer").find("a span").each(function(){
var val = $.trim($(this).text());
if (!isNumber(val))
$(this).attr('class', 'whiteBox');
});
$("#footer").contents().filter(function() {
var $this = $(this);
return $this.children().length == 0 && $.trim($this.text()).length > 0;
}).wrap("<span class='whiteBox' />");
});
The selected number is displayed without a wrapping element, so it´s rendered inline.
Try wrapping it in a span tag like this: http://jsfiddle.net/Z5L4g/2/
I have wrapped the selected number in a span with class selected, which shares the same rules as the blackbox class, except having transparent background and black text color.
I wouldn't say it´s a CSS problem, but a markup problem. The selected page indicator doesn't get any width or height and can't be styled as it is just text.
Suggestion: either change the markup, or split the innerHTML of the #footer with javascript and work from there. I would go with the first option.

Categories