I have the following JavaScript which lies on a page within an iframe, and grabs the parent pages css to make the page have a seamless look to the rest of the page. I'm having an issue with it picking up the wrong styling however. How can I target specific tags(such as h1, h3`, etc to use on the page within the iframe?
var getFontFamily = function(){
for(var i = 0; i < document.styleSheets.length; i++){
for(var j = 0; j < document.styleSheets[i].rules.length; j++){
if(document.styleSheets[i].rules[j].style.fontFamily){
return document.styleSheets[i].rules[j].style.fontFamily;
}
}
}
return 'not-found';
};
window.addEventListener('load', function(){
var data = getFontFamily();
window.frames[0].postMessage(data, 'http://localhost:3000');
console.log('Message sent -->');
});
Current version: jsfiddle
This is the HTML that the css of the parent page needs to be applied to:
<div class="info">
<div class="lead">Message Lead</div>
<h2>Title</h2>
<div class="ticker">
<div class="ticker__also">Also</div>
<ul class="ticker__list">
<li>sub headline</li>
<li>sub headline</li>
<li>sub headline</li>
</ul>
</div>
</div>
<div class="extras">
<div class="title">Extra info</div>
<a class="link" href="http://www.url.tv" target="_blank">Link</a>
<div class="share">
<a class="twitter">Twitter</a>
<a class="facebook">Facebook</a>
<a class="email">E-mail</a>
</div>
</div>
You can get styles from elements directly via the style attribute and the window.getComputedStyle method. This is more accurate than just taking the first result that appears in the list of CSS rules (where you also just find selectors, not actual elements the style is applied to).
The MDN page about the style attribute has some easy examples, for your purpose, it could be look like this.
var getFontFamily = function() {
var el = document.getElementById(id);
var cs = window.getComputedStyle(el, null);
return cs.fontFamily || '';
}
Related
I want to remove the rel attribute of the a inside other class without removing the one inside myclass.
document.getElementsByClassName('other class').document.getElementsByTagName("a").element.removeAttribute("rel");
<div class="myclass">
<a rel="nofollow noopener noreferre">MEC</a>
</div>
<div class="other class">
<a = rel "nofollow noopener noreferrer">MEC</a>
</div>
I also tried using jQuery:
document.getElementsByClassName('other class').child;
for (var i = 0; i < activeLis.length; i++) {
var allLinks = document.getElementsByTagName("a");
for (i = 0; i < allLinks.length; i++) {
allLinks[i].removeAttribute("rel");
}
};
Either use :
$('.other').children('a').attr("rel","");
Or
$('.other').children('a').removeAttr("rel");
The main issue with your code is that getElementsByClassName and getElementsByTagName return node lists. As such you need to iterate through them, which is easier done with querySelectorAll(), calling removeAttribute() on the individual nodes. Try this:
document.querySelectorAll('.other.class').forEach(function(el) {
el.querySelectorAll("a").forEach(function(a) {
a.removeAttribute("rel");
});
});
<div class="myclass">
<a rel="nofollow noopener noreferre">MEC</a>
</div>
<div class="other class">
<a rel="nofollow noopener noreferrer">MEC</a>
</div>
The jQuery equivalent of this is:
$('.other.class > a').removeAttr("rel");
This is obviously assuming that you are selecting the div using two classes. If it's just a single class then use .otherclass
In javascript I want to tell post-container that when I click on it, take the href located at link and go to page X.
There are multiple post-container
My code is this:
<div class="post-container">
<a class="link" href="X">
<h2 class="post-title">Hello, world!</h2>
</a>
<div class="date-posts">...</div>
</div>
I want to be able to click outside the Hello, world! title of my post in any area of post-container and go to page X
Any idea how to do this?
I hope I'm interpreting your question correctly, but you can just rearrange where you're writing your a href tag. Instead, wrap your div inside of it. This will make the entire div element a link.
<a class="link" href="google.com">
<div class="post-container">
<h2 class="post-title">Hello, World!</h2>
<div class="date-posts"></div>
</div>
</a>
This will work.Add Event listener to the parent element (Event Delegation).You can take the href property of the child element and then use window.location.href.You might need to add preventDefault() to avoid default behaviour of a tag
If you have multiple tags with same class name.You have to use querySelectorAll .Either way if you have single elements or multiple elements with same class name use querySelctorAll.
// if you have one tag
let ele = document.querySelectorAll(".post-container")
ele.forEach(element => {
element.addEventListener("click", function(e) {
e.preventDefault();
let href = element.children[0].getAttribute("href")
window.location.href = href;
})
})
.post-container {
background-color: green;
}
<div class="post-container">
<a class="link" href="X">
<h2 class="post-title">Hello, world!</h2>
</a>
<div class="date-posts">...</div>
</div>
Assuming you have multiple .post-containers you would need to iterate over each of them and add an event listener to handle click events. On click, find the a get its href and set the window.location (I just console log it in this demo)
(function(){
let elems = document.querySelectorAll(".post-container");
for (i = 0; i < elems.length; ++i) {
let el = elems[i];
el.addEventListener("click", function(e) {
e.preventDefault();
let href = el.querySelector("a").getAttribute("href");
console.log("href",href);
//window.location.href = href;
})
}
})();
<div class="post-container">
<a class="link" href="X">
<h2 class="post-title">Hello, world!</h2>
</a>
<div class="date-posts">...</div>
</div>
<div class="post-container">
<a class="link" href="Y">
<h2 class="post-title">Goodbye world!</h2>
</a>
<div class="date-posts">...</div>
</div>
Javascript:
var elements = document.getElementsByClassName('post-container');
var loadLink = function() {
var link = this.getElementsByTagName("a")[0].href;
window.location.href = link;
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', loadLink, false);
}
Check working demo
document.getElementsByClassName('post-container')[0].onclick = function(e){
location.href = this.children[0].href;
}
I need it to be a javascript solution only please. Please refer to this demo.
The goal is to hover the dots on the right bottom corner and swap the images accordingly. But what it does now is showing a blank page when hovering, and the whole ul becomes vertical and goes to top left corner. What did I do wrong here???
HTML:
<div id="wrapper">
<section id="contentWrapper">
<div id="resistorContent" class="content">
<section id="resistorDetail1"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic1.jpg"></section>
<section id="resistorDetail2"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic2.jpg"></section>
<section id="resistorDetail3"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic3.jpg"></section>
<section id="resistorDetail4"><img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic4.jpg"></section>
<ul>
<li onMouseOver="showDetail(resistorDetail1)"></li>
<li onMouseOver="showDetail(resistorDetail2)"></li>
<li onMouseOver="showDetail(resistorDetail3)"></li>
<li onMouseOver="showDetail(resistorDetail4)"></li>
</ul>
</div>
</section>
</div>
JAVASCRIPT:
<script type="text/javascript">
var children = document.querySelectorAll('.content > section[id]')
function showDetail(target){
for (var i = 0, child; child = children[i]; i++) {
child.style.display = 'none';
}
document.getElementById(target).style.display = 'block';
}
</script>
POSSIBLE COLLIDING CSS ?:
.content section:not(:first-child) {
display: none;
}
Thank you in advance!!
TL;DR
Here is the working fiddle: https://jsfiddle.net/2qz2srqs/3/
Reason
Your code was very close, but it had a few minor issues.
The first was a copy-paste error, you had two elements with the id of resistorDetail3.
Second, your syntax for the onmouseover event was incorrect. Prefix any javascript with javascript: and ensure it has proper syntax.
Third, your showDetail method expected a string id of the element to show. In your onmouseover declaration you had showDetail(resistorDetail1) instead of showDetail('resistorDetail1').
Finally, when you javascript is referenced in the HTML, you need to make sure you load the javascript first. Just by taking a look at the developer's console you could see that it through an error "showDetail is not defined.. I switched it to No wrap - in <body> and it worked fine.
BUT I highly recommend against directly referencing javascript from your HTML. Instead, load the HTML first and then use the DOM ready event of javascript to bind your events. That will increase your load time and make it easier to switch to something like jQuery/Zepto if needed.
Full Code
HTML
<section id="contentWrapper">
<div id="resistorContent" class="content">
<section id="resistorDetail1">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic1.jpg" />
</section>
<section id="resistorDetail2">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic2.jpg" />
</section>
<section id="resistorDetail3">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic3.jpg" />
</section>
<section id="resistorDetail4">
<img src="http://d3d71ba2asa5oz.cloudfront.net/40000483/images/pic4.jpg" />
</section>
<ul>
<li onmouseover="javascript: showDetail('resistorDetail1')"></li>
<li onmouseover="javascript: showDetail('resistorDetail2')"></li>
<li onmouseover="javascript: showDetail('resistorDetail3')"></li>
<li onmouseover="javascript: showDetail('resistorDetail4')"></li>
</ul>
</div>
</section>
JS
var children = document.querySelectorAll('.content > section[id]');
function showDetail(target) {
for (var i = 0, child; child = children[i]; i++) {
child.style.display = 'none';
}
document.getElementById(target).style.display = 'block';
}
CSS
(unchanged)
Here's another working fiddle.
https://jsfiddle.net/2qz2srqs/4/
The issue was a couple things.
You were passing undefined vars into your onmouseover attributes. You wanted strings (I quoted them)
In JSFiddle, you don't automatically get the window scope, so you have to assign a function as a property of a window if you want to be able to hit it with an event attribute.
There is an i button in the middle of my website. I'd ask you to click it—you would see a button—contact.
When the user clicks on it, I want the content of the div above to be changed.
This is the code:
<section id="about" class="wrapper about accelerate hide">
<div class="cell accelerate">
<div class="cables center accelerate">
<div class="panel accelerate">
<header>
<h1>gog<em>sem</em>cel</h1>
</header>
<p><strong>gogsemcel </strong>is a trademark of <i font-family="Trebuchet MS">Company</i>.</p>
<p>This project is a collaboration between<br>Company name & gogsemcels.</p>
<ul class="links">
<li><a class="download" href="info/info.html">More Info</a></li>
<li><a class="github" target="_blank" href="contact.html">Contact</a></li>
</ul>
</div>
</div>
</div>
</section>
The button's class is github.
Any suggestions?
Gigantic thanks.
I see you have jQuery on your page so you could use this:
$('#about a.github').on('click', function(e){
e.preventDefault();
var content = $(this).closest('.panel').find('p');
content[0].innerHTML = 'This is a new text!'
content[1].innerHTML = 'This is the second line!'
});
Example
I am not a fan of disabling right-click. Just FYI I can see the whole content anyway...
If you want to do it with vanilla JS you can use this (credits do Chris's nice function):
function collectionHas(a, b) { //helper function (see below)
for (var i = 0, len = a.length; i < len; i++) {
if (a[i] == b) return true;
}
return false;
}
function findParentBySelector(elm, selector) {
var all = document.querySelectorAll(selector);
var cur = elm.parentNode;
while (cur && !collectionHas(all, cur)) { //keep going up until you find a match
cur = cur.parentNode; //go up
}
return cur; //will return null if not found
}
var git = document.querySelector('#about a.github');
git.addEventListener('click', function (e) {
e.preventDefault();
var content = findParentBySelector(git, '.panel').querySelectorAll('p');
content[0].innerHTML = 'This is a new text!'
content[1].innerHTML = 'This is the second line!'
});
Example
You should add href attribute to Contact link.
<a class="github" target="_blank" href="#contact">Contact</a>
Then, add id attribute to 2 p elements for easily selecting.
<section id="about" class="wrapper about accelerate hide">
<div class="cell accelerate">
<div class="cables center accelerate">
<div class="panel accelerate">
<header>
<h1>viva<em>stem</em>cell</h1>
</header>
<p id="abc"><strong>vivastemcell </strong>is a trademark of <i font-family="Trebuchet MS">Tsovn Tsirani Company</i>.</p>
<p id="def">This project is a collaboration between<br>Tsovn Tsirani & vivastemcells.</p>
<ul class="links">
<li><a class="download" href="info/info.html">More Info</a></li>
<li><a class="github" target="_blank" href="contact.html">Contact</a></li>
</ul>
</div>
</div>
</div>
</section>
Now, in onload event of your page, add following code. This use pure Javascript that you want.
// You can use document.querySelector -> returns the first element found.
var gh = document.querySelectorAll('#about .github')[0];
if (gh) {
gh.addEventListener('click', function (e) {
e.preventDefault();
document.getElementById('abc').textContent = new Date().getTime();
document.getElementById('def').textContent = new Date().getTime();
})
}
In the following javascript script, I use the following code to empty an <ul> list of countries and refill it (with a little animation using the hide() function of jquery).
It works in chrome and safari, but in IE, the new <li> elements of the <ul> are appearing behind the place of the previously showed <li>'s . Is there a workaround for this ?
$('#country_list').hide(300,function(){
var i;
$(".country_list").empty();
$(".country_list").height(0);
$(".country_link").remove();
$("#content").append('<div id="country_list_div" class="grid_3 "><ul id="country_list"></ul></div>');
var country_list= country_dict[letter];
var country_count = country_list.length;
for (i=0;i<country_count;i++)
{
$("#country_list").append('<li><a class="country_link" href="" id="'+country_list[i][0]+'" na="'+country_list[i][1]+'">'+country_list[i][1]+"</a></li>");
}
$('#country_list').show(300);
return false;
});
Here is the corresponding html, as asked (You can see the whole thing at http://populationpyramid.net too)
<div id="content" class="container_12">
<div id="canvas_container_div" class="grid_7 " >
<div id="canvas_container" ></div>
</div>
<div id="year_list_div" class="grid_1 " style="display: table-cell; vertical-align: middle;">
<ul id="year_list">
</ul>
</div>
<div id="alpha_list_div" class="grid_1 ">
<div style="margin-left:11px;">
<ul id="alpha_list">
</ul>
</div>
</div>
<div id="country_list_div" class="grid_3 ">
<ul id="country_list">
</ul>
</div>
</div>
why remove the original ul? also you are removing ".country_list" not "#country_list"
Maybe...
$"#country_list").hide(300, function(){
var cl = $(this); //get a variable handle
cl.empty();
var items = country_dict[letter];
for (var i=0 i<items.length; i++) {
cl.append(([
'<li>'
,'<a class="country_link" href="javascript:void(0);"'
,' id="' + items[i][0] +'"'
,' na="' + items[i][1] + '"'
,'>'
,items[i][1]
,'</a>'
,'</li>'
]).join(''));
}
cl.show(300);
});
Make sure you specify the size (height or width) of the container, IE tends to flow its content opposed to overwrite positions. I always like to clip my containers to make sure they never flow out.