I have a parent div gal1, inside which there can be further divs and content, but only one img element without an id as you can see below. Now I want to use only Javascript (no jQuery) to change the style of this image, using gal1 as argument (because the rest of the structure inside this div may vary, only this one image will always be there somewhere). I couldn't find any other stackoverflow question that addresses exactly my situation.
<div class="gallery-preview" id="gal1">
<div class="gallery-preview-img" id="gal-img1">
<img src="galleries/kevin-carls/Monks.jpg">
</div>
<div class="gallery-preview-text" id="gal-text1">
<span class="gallery-name" href="">Road to India</span><br/>
<span class="artist-name" href="">Kevin Carls</span>
</div>
</div>
Than you can make use of method called getElementsByTagName('img') than you should get image and update it.
document.getElementById(gal1).getElementsByTagName('img');
get the content by using id, and then query images by using getElementsByTagName
function getImages(contentId) {
var content = document.getElementById(contentId);
// only one image, just return an item; or you can return an array
if (content) return document.getElementsByTagName('img')[0];
}
You can insert CSS which may be more efficient if you have to do this in more than this single case.
http://jsfiddle.net/65Ggv/
var style_rules = [];
style_rules.push("#gal1 img { border: 3px solid green; } ");
var style = style_rules.join("\n");
var el=document.createElement("style");
el.appendChild(document.createTextNode(style));
el.type="text/css";
document.head.appendChild(el);
Unless you absolutely need to pick the colors or border sizes dynamically, which I doubt because you are an admitted beginner, stuffing stylesheets in with Javascript is a Rube Goldberg device. It seems nifty to be able to do this, but if your application is important to you, you will regret it. (You might as well use innerHTML to stuff in a stylesheet in that case -- at least it will be faster than making DOM calls.)
Pranay Rana's answer to use getElementsByTagName is the best option if your constraints are actually stable (only one img). Obtain an element reference el, to gal1, using getElementById, then var myimg = el.getElementsByTagName("img") and you are almost done.
If you insist upon funking with the style nodes, you can stuff whatever properties you want into the style property of myimg. It becomes inline style.
Even so, you almost certainly do not need to stuff in novel rules, and changing inline style is often avoidable. It is more predictable and stable to modify the class attribute on myimg, and use a predefined set of style classes for the cases you need to handle. This will give a nice clean separation of the style from the script, and avoid both the in-lining of the style rules and run-time mutilation of the style tree by code injection.
Related
We have a very large website that is quite old and has a lot of 'b' tags. My boss wants to change them to 'strong' tags but this will require a lot of time to change manually so she was hoping we could change it with some code.
I had a nice bit of JQuery code that worked (intermittently), but I couldn't get it to work on the site as it uses JQuery 1.9.1 and cannot be upgraded.
I then found this piece of Javascript which does what I need but only works on the first 'b' tag on the page and all others stay as 'b' tags. I don't know enough about Javascript selectors to change the firstChild selector.
<script>
function replaceElement(source, newType) {
// Create the document fragment
const frag = document.createDocumentFragment();
// Fill it with what's in the source element
while (source.firstChild) {
frag.appendChild(source.firstChild);
}
// Create the new element
const newElem = document.createElement(newType);
// Empty the document fragment into it
newElem.appendChild(frag);
// Replace the source element with the new element on the page
source.parentNode.replaceChild(newElem, source);
}
// Replace the <b> with a <div>
replaceElement(document.querySelector('b'), 'strong');
</script>
You might use querySelectorAll:
Array.from(document.querySelectorAll('b')).forEach(e=>{
replaceElement(e, 'strong');
});
But this is really a xy question. You really should do the change server side, for example by using some search/replace (learn to use your code editor). You're adding to the code debt here.
Note also that there's no obvious reason to prefer strong over b in HTML5.
Use getElementsByTagName(). It's more efficient than querySelectorAll because it doesn't have to parse selectors, and it describes better what you are really trying to do - get elements by tag name.
var elements = document.getElementsByTagName("b");
replaceElement(elements[0], "strong");
replaceElement(elements[1], "strong");
replaceElement(elements[2], "strong");
You can also iterate over this collection by using Array.from().
You would be better off finding the source of the <b> tags and changing them there as Denys has mentioned.
Updating the DOM would have little benefit and would cause performance issues when there are many tags on a page.
Does this system use a CMS or database to store the content? I would look to use something like these 2 SQL queries to replace them across the site:
update content_table set content_column = replace(content_column, '<b>','<strong>');
update content_table set content_column = replace(content_column, '</b>','</strong>');
Can some one show how I can change the InnerHTML of the titles class to be the same as the alt attribute. For the actual website jarretonions.co.za
Thanks
$(document).ready(function() {
$(".pic").on("click", function() {
$(".modal").show();
var srclong = $(this).attr("src");
var srcshort = srclong.split("_");
var srcextension= srclong.split(".");
$(".modal img").attr("src", srcshort[0]+'.'+srcextension[1]);
************is it something like this********
var title = $(this).attr("alt");
$(".modal span").InnerHTML= title;
OR
document.getElementByClassName('titles').innerHTML = title;
})
+
echo
"<div class='art'>
<img class='pic' src='img/".$row["name"]."_tnail.jpg'
alt='".$row["name"]." • ".$row["year"]." • ".$row["type"]."'
height='auto' width='100%'/>
<div class='modal'>
<img class='big'/>
<span class='titles'></span>
</div>
</div>"
;
Since you're using JQuery, you can select those elements using $(".title") and change them directly. Something like so:
$(document).ready(function() {
$(".pic").on("click", function() {
$(".title").text( $(this).attr("alt") );
})});
Here's a fiddle: https://jsfiddle.net/wmjtfLja/1/
Note that if you have more than one element of class .title, they will all change. So you may want to select the title element by id or by relative path from the clicked image.
Realizing in advance, the danger of providing an answer that is not (superficially) fully aligned with the question, I was struck by the comment from melpomene, whom I initially thought was refering to things not existing in jquery.
melpomene is 100% correct, since getElementByClassName does not exist.
The correct syntax is getElementsByClassName.
Having said that, helloworld is also correct (syntax errors aside), since loading jquery for every little task is really redundent, and one can manipulate by class with little more half a dozen lines of pure javascript.
But, getting elements by class has dangers, since the return is a 'live' array.
For example, with dylan's original question, getting by class is only useful to return the first instance (the array length is just a guide of how many elemnts it applies to). Therefore, for dylan to make changes as he proposed, each requires its own button. (which also means, michael that I believe you are incorrect when you say it will affect all elements with same class name - oth, you are fully correct in noting that one should inpsect for other values (or change the class name) when running loops on the attribute).
Consider the following (on the fly class change);
function otf_cls_change(cls_original,cls_replace){
var a=document.getElementsByClassName(cls_original);
l=a.length;
if (l==0){return 0;}
do {
a[0].setAttribute('class',cls_replace);
a=document.getElementsByClassName(cls_original);
l=a.length;
} while (l>0);
}
This is effective for changing class names on the fly.
But, if we modify the code and
//change this a[0].setAttribute('class',cls_replace); // to
a[0].innerHTML='this_html';
It will cause the browser to hit an endless loop.
Why? because the live array returned by ElementByClass will only process the first item (even if you try to loop the array).
Therefore, while changing the class on the fly is fun and very do-able, I'd strongly suggest that using it to change any attrib that is not specific to the class id is a bad idea.
Changing the class attrib in conjunction with another attrib is fine.
For example,
a[0].innerHTML='this_html'; //do this first
a[0].setAttribute('class',cls_replace); //then this
The above will work to loop class defined elements.
On a point of massive personal hypocrisy, I do get annoyed when people ask for pure javascript solutions, and then some wing nut chimes in with jquery. I guess I'm doing the opposite here, since evidently, the question was jquery related, and here I am throwing out pure javascript. Sorry bout that.
btw, dylan, good luck with it. glad you bit back on the negative comment. Too many people here are terrified of offending, and wind up get bullied.
hth,
Gary
I am making a chrome extension, and I want to find all occurrences of a certain word, and put them inside a new div class so I can change them with CSS.
Right now my content.js file looks like this:
(function() {
function change() {
var words = new Array("color");
var html = document.body.innerHTML;
for(var i = 0; i < words.length; i++) {
var reg = new RegExp(words[i], 'ig');
var html = html.replace(reg, '<div class="colorClass">'+words[i]+'</div>');
}
document.body.innerHTML = html;
}
change();
})();
But when I do that, entire web pages get messed up and become unrecognizable (for example, the "Color" wikipedia page).
When I try something simpler like:
var html = html.replace(reg, '<i>'+words[i]+'</i>');
It works just fine. Why is this whole page getting messed up when I try to add divs?
How can I fix this?
One reason the styles are messed up are because the native web page's CSS is overriding the styles loaded from your content script.
The second reason is that you need to be very careful when modifying HTML. You need be careful only to modify text. The current method you are using - you are possibly modifying html classes, ids, etc.
I've actually built an extension (Source code for reference) that does something very similar. I'll share my learnings:
JS
I had used NodeIterator which is fairly unknown. I discovered this API a year ago from another extension: https://code.google.com/p/chrome-type-ahead/
NodeIterator will help you filter out the true text elements that you want to add styles to. This will help you avoid modifying any valid html(classes, ids, etc.) that matches your regex.
CSS
I would suggest adding a class to the html tag in addition to the html you are inserting. The reason for this is that you'll need to be very specific in your styles.
You want to avoid at all cost any chance of a collision with a selector of an existing page.
In addition you need to make sure to add your own css resets that are not only namespaced but also have !important on each attribute.
You CANNOT assume anything about the html tag that you are inserting. Sites can have very generic selectors that will completely mess up your styles. And also the sites can have very specific selectors (using id) that are more specific than you're styles (hence the need for important)
html.very-specific-class .very-specific-color-class {
/*
padding, margin, border, etc.
difficult to add all properties but add all the common ones at the very least
*/
padding: 0px !important;
margin: 0px !important;
border: 0px !important;
...
}
This is happening because a <div> is a block-level element, and it pushes other elements to a new line.
<i> however, is an inline element, so it will not change the page layout at all.
I would recommend using a <span>,instead of a <div>, as span's have no default styling in browsers.
Because divs are block elements. You can use spans, which are inline elements:
var html = html.replace(reg, '<span class="colorClass">'+words[i]+'</span>');
If you want use div,you can add some css styles,like this:
.colorClass{display:inline-block;}
We've got a little tool that I built where you can edit a jQuery template in one field and JSON data in another and then hit a button to see the results immediately within the browser.
I really need to expand this though so the designer can edit a full CSS stylesheet within another field and when we render the template, it will have the CSS applied to it. The idea being that once we've got good results we can take the contents of these three fields, put them in files and use them in our project.
I found the jQuery.cssRule plugin but it looks like it's basically abandoned (all the links go nowhere and there's been no development in three years). Is there something better or is it the only game in town?
Note: We're looking for something where someone types traditional CSS stylesheet data in here and that is used immediately for rendering within the page and that can be edited and changed at will with the old rules going away and new ones used in their stead. I'm not looking for something where the designer has to learn jQuery syntax and enter in individual .css("attribute", "value") type calls to jQuery.
Sure, just append a style tag to the head:
$("head").append("<style>p { color: blue; }</style>");
See it in action here.
You can replace the text in a dynamically added style tag using something like this:
$("head").append("<style id='dynamicStylesheet'></style>");
$("#dynamicStylesheet").text(newStyleTextGoesHere);
See this in action here.
The cleanest way to achieve this is by sandboxing your user-generated content into an <iframe>. This way, changes to the CSS won't affect the editor. (For example, input { display:none; } can't break your page.)
Just render out your HTML (including the CSS in the document's <head>, and write it into the <iframe>.
Example:
<iframe id="preview" src="about:blank">
var i = $('#preview')[0];
var doc = i.contentWindow || i.contentDocument;
if (doc.document) doc = doc.document;
doc.open('text/html',true);
doc.write('<!DOCTYPE html><html>...</html>');
doc.close();
If the user should be able to edit a whole stylesheet, not only single style attributes, then you can store the entered stylesheet in a temporary file and load it into your html document using
$('head').append('<link rel="stylesheet" href="temp.css" type="text/css" />');
sounds like you want to write an interpreter for the css? if it is entered by hand in text, then using it later would be as simple as copy and pasting it into a css file.
so if you have a textarea on your page to type in css and want to apply those rules when you press the button, you could use something like this (only pseudocode, needs work):
//for each css id in the text area
$.each($('textarea[name=cssTextArea]').html().split('#'), function({
//now get each property
$.each($(this).split(';'), function(){
$(elem).css({property:value});
});
});
then you could write something to go through each element that your designer typed in, and get the current css rules for it (including those that you applied using some code like the snippet above) and create a css string from that which could then be output or saved in a db. It's a pain and much faffing around with substrings but unfortunately I don't know of a faster or more efficient way.
Hope this atleast gives you some ideas
I am learning about JavaScript, and in the text it says you must us locally defined styles for animation. i.e. A HTML style tag. Does this make sense, and if so, why is this necessary? Thanks in advance.
No, this is not necessary.
You can do it in two basic ways.
Dynamically change the style:
<p id="myElement">Here is some text to animate</p>
<script>
var pixels = 10; // e.g., if this were a dynamically changing variable
document.getElementById('myElement').style.width = pixels+'px';
</script>
Dynamically change the class:
<style>
.tiny {width:10px}
</style>
<p id="myElement">Here is some text to animate</p>
<script>
document.getElementById('myElement').className = 'tiny';
</script>
The latter approach is probably a better practice because it gives control to the designer to control everything from CSS, while letting the JavaScript programmer focus on functionality only.
However, in the case of transitions, where you wish to change values dynamically (e.g., incrementing the width by 1 every second), it is not practical to define a class for each possible width along the way. However, it is possible for you to query the stylesheet itself to get this info. CSS Variables will make this easier if they are implemented, but currently you can use something like the function getCSSPropertyValue at https://gist.github.com/990313 to get the begin and end values from classes defined in the stylesheet, while handling the style transitions with the style property.
var beginWidth = parseInt(getCSSPropertyValue('.small', 'width'));
var endWidth = parseInt(getCSSPropertyValue('.large', 'width'));
var itvl = setInterval(function () {
if (beginWidth++ > endWidth) {
clearInterval(itvl);
}
document.getElementById('myElement').style.width = beginWidth + 'px';
}, 10);
They may be referring to changing the style locally in javascript. In order to do that you utilize the style attribute of each element.
element.style.width = "100px";
would change the style to a width of 100px. This is how you change the appearance of elements with javascript.
Perhaps what the text means is that when you do something like call the jQuery animate() function, for instance, passing in CSS properties, those properties are set via the style attribute of the HTML element. This makes sense because you'll want these rules to override any pre-defined rules from your stylesheets.
Example: http://jsfiddle.net/jRKJx/
If you inspect the <div> after the animation runs, you'll see that jQuery set the style attribute on the element.