Adding HTML via JS to a specific child-Element - javascript

I have a very specific situation where I have ~50 child-divs which I cannot influence directly, that is, I cannot add classes or ids to one specific child-div nor alter the div via HTML because they are created automatically.
They appear in a simple grid/flexbox, two boxes next to each other. I already altered some of them with nth-child, but now I want to add individual headlines between f.ex. div 30 and 31.
Up until now, when I wanted some of the fields to be bigger, I addressed one of the child-divs directly via nth-child.
Here's the basic structure:
<div class="parent">
{$content} // basically <div>{$single-box-content}</div>
</div>
And the CSS I currently use:
.parent {
width: 800px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.parent:nth-child(10) {
width:800px;
}
That worked quite well. However, now that I want to have a headline above one of the divs (not inside), it doesn't work. When I try this:
.parent:nth-child(31):before {
content: "Headline";
display: block;
}
It appears inside the child-div, not above it. I cannot add a div to the HTML part, since all of them are created automatically in the backend (it's a form).
I wondered if it is possible to use JavaScript with some element.innerHTML, but I am at the very beginning of learning JS and I couldn't find anything (I could adapt) to address specific child-Elements in JS.
Is there a frontend solution to my problem?

With JS you can add classes, IDs, append HTML-elements to the DOM and so much more.
Below shows you how to both to insert an h2, but also how to add a class to an element of your choosing - I used :nth-child(3) for illustration purposes, but you can just swap that with :nth-child(31). The code is explained in comments in the snippet.
// finding the child element with nth-child selector
let selected = document.querySelector('.parent:nth-child(3)');
// giving it a class name
selected.classList.add('parentClass');
// creating a h2 element
let header = document.createElement("h2");
// the text inside the h2 element
let headerText = document.createTextNode("headline");
// appending the text to the h2 element
header.append(headerText);
// giving the child a class name
header.classList.add('childClass');
// appending the headline above/before the selected element
selected.parentNode.insertBefore(header, selected);
/* the class applied with JS */
.parentClass {
background-color: red;
}
.childClass {
background-color: limegreen;
}
<div class="parent">parent 1</div>
<div class="parent">parent 2</div>
<div class="parent">parent 3</div>

Related

Centering images and text in a div

I have been having some trouble centering some items on my website.
The items in question are in the passphrase generator (images and text elements in the dark box). I have tried the usual margin:auto, all the different display properties, text-align, align-self, align-content and align-items. None worked.
I was also wondering if anyone knew how we could get the text element under our images isntead of to the right, this is the code used for the generator.
All help is appreciated
A p tag is a block element, so the default width is 100%. This is why you have one element per line
#passphraseBilder {
text-align: center;
display: block;
}
#passphraseBilder p {
display: inline-block;
}
Turn the p tag into inline or inline-block, and it will work ;-)
Have a look to the difference between block and inline: https://www.w3schools.com/html/html_blocks.asp
Try this:
#passphraseBilder {
display:inline-block;
width:100%;
}
Note: I have just added the properties which you should add or overwrite. Existing properties has to be there.

Re-order Divs without access to html

I'm customising a wordpress theme and have come up against a frustrating blocker.
I would like to position the header (header.non-sticky-nav) after the fullscreen cover (.fullscreen-cover) and before the content (.content).
<header class="non-sticky-nav">
<div id="navbar"></div>
</header>
<div id="wrapper">
<div id="content">
<div class="fullscreen-cover"></div>
<div class="content"></div>
</div>
</div>
current-result_vs_desired-result
I tried repositioning the nav bar by using a "top: xpx" value but obviously that doesn't work as the .fullscreen-cover is not a fixed height.
Here is the test page I am using for the issue: http://samburrough.design/test/
The theme allows page specific or global css code injections, and as theme is regularly updated, I would like to try and stick to using this feature rather than delve into the theme files and have the changes overwritten every time I want to update.
Any help would be hugely appreciated!
Could you not create a child theme and modify the DOM that way?
At least this way the changes won't be over-written every time an update to the parent theme is released?
This would (should) actually be the preferred option.
Smashing Magazine; Create and Customise Wordpress Child Theme
Unfortunately, if the theme does not include block positioning, you need to edit the DOM. While you could probably use some wonky absolute positioning on the bar and the hero, positioning them absolutely is likely to cause you a cascade of problems - starting with the responsive nav.
There is a javascript function/method that lets nodes swap places in the dom.
you could try and look into that Node.replaceChild()
The example below is from the documentation and creates a new element but you can also select an existing node.
// create an empty element node
// without an ID, any attributes, or any content
var sp1 = document.createElement("span");
// give it an id attribute called 'newSpan'
sp1.id = "newSpan";
// create some content for the new element.
var sp1_content = document.createTextNode("new replacement span element.");
// apply that content to the new element
sp1.appendChild(sp1_content);
// build a reference to the existing node to be replaced
var sp2 = document.getElementById("childSpan");
var parentDiv = sp2.parentNode;
// replace existing node sp2 with the new span element sp1
parentDiv.replaceChild(sp1, sp2);
You could try using order with flexbox. For example:
.container {
display: flex;
flex-wrap: wrap;
}
.one,
.two {
width: 100%;
}
.one {
order: 2;
background: red;
}
.two {
order: 1;
background: blue;
}
<div class="container">
<div class="one">
1
</div>
<div class="two">
2
</div>
</div>
Might be a bit problematic, depending on what your markup looks like. And won't work on older browsers.

Linking ::after element on multiple slideshow items...only first one works

I have a slideshow and for each slideshow I have an ::after element like this:
.views-field.views-field-title .field-content:after {
content: url('../images/myimage.svg');
position: absolute;
margin-left: -21px;
margin-top: -30px;
}
I want to create a link for the element but only the first link works, it doesn't work on subsequent slideshow items.
$('.views-field.views-field-title .field-content').after().click(function () {
window.location.href = "http://www.example.com";
});
Do i need to iterate over this using foreach?
The after method is used for inserting content after the selected element(s).
$('h1').after('<p>Small text</p>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Big Text</h1>
You can't directly select pseudo elements since they aren't actual DOM elements. So you won't be able to make the :after content clickable, what you have "working" at the moment is you're inserting some dummy element and making it clickable.
In this case, you should replace the :after content with a proper DOM element (such as a <a> tag) and style that element accordingly.

How to check if 2 elements displayed on the same row?

Assuming I have 2 elements on a responsive design like this:
<div id="container">
<div class="first"></div>
<div class="second"></div>
</div>
both of them with style contains:
width: auto;
display: inline-block;
float: left;
And because I'm expecting different screen sizes to view page, so, according to screen size, sometimes they will be rendered/displayed on the same row, and sometimes they will not!, the second DIV will be moved to a separate row.
So, I'm wondering, how can I check if they are on the same line with JavaScript?
Thank you
"on the same line" would require inline elements or floating block elements of the exact same height. DIVs are block elements by default. So either use <span> tags instead of <div>, or add display: inline-block;to the CSS rule of those DIVs
ADDITION after EDIT OF QUESTION:
width: auto for a <div> means 100% of the parent element (in this case full width). As I wrote: If you have blocks, use display: inline-block; in their CSS. If you want them to have the same height, put them into a common container DIV (which you already have) and apply the following CSS:
#container {
display: table;
}
.first, .second {
display: table-cell;
width: 50%;
}
Aha (edited question), Javascript: Well, read out the DIV widths, add them and compare the result to the (read-out) container width.
You can use the element bounding boxes and check for overlap:
var rect1 = $('.first')[0].getBoundingClientRect();
var rect2 = $('.second')[0].getBoundingClientRect();
var overlaps = rect1.top <= rect2.bottom && rect2.top <= rect1.bottom;
This checks for any overlap which will probably be sufficient for your use. I used jQuery to get the elements but you can use pure js in the same way, it would just be a bit more verbose.
There is no concept of line on a page. You can check the x and y position of any element in the window and then decide if that meets whatever criteria you have for "on the same line".
By default, a div is the full width of a window so the two divs inside your container in this HTML:
<div id="container">
<div class="first"></div>
<div class="second"></div>
</div>
will be one above the other unless there is some other CSS you have not disclosed that controls the layout to allow them to be in the same row. If they are indeed width: auto and don't have any other layout rules affecting this, then they will each be full width and thus first will be above second in the layout stream. They would never be "on the same line" by any typical definition of that phrase.
Feel free to try it out here: https://jsfiddle.net/jfriend00/y0k7hLr8/ by resizing the right pane to any width you want. In all cases, the first will stay on top of the second.
If, on the other hand, you allow the div elements to have a different type of layout such as let them be display: inline-block and define a width for them, then the layout engine will fit as many on a given row as possible like here: https://jsfiddle.net/jfriend00/229rs97p/
Something tells me display: flex might help you in this. Read https://css-tricks.com/snippets/css/a-guide-to-flexbox/ for more info.

Div breaks jQuery accordion

I have a jQuery accordion that breaks when I need to place a div-tag in one of the sliding open areas.. How do I get around this? I need to put a div-tag since I cannot make a nice box out of a span-tag. Anyone knows a way around this??
Please see my demo here to see where it breaks :(
http://jsfiddle.net/zRqYM/
You should probably change this:
$(this).next("p").slideToggle("slow")
.siblings("p:visible").slideUp("slow");
to:
$(this).next("div").slideToggle("slow")
.siblings("div:visible").slideUp("slow");
and the CSS:
.accordion2 > div {
background: #f7f7f7;
/* etc... */
It makes more sense to use a DIV instead of P if you want to put other elements inside the expandable content: http://jsfiddle.net/zRqYM/13/
Or just use inline elements inside the P tag and style them to display:block;, but it doesn’t make semantic sense to me.
This seems a bit lame, but you can use a span and just set it to display: block. Then it's essentially a div: http://jsfiddle.net/zRqYM/5/
Why cant you put it in a span and style the span as a nice box with display block?
You can use a span-tag. All you need to do is add the following styling for your span-tag class in the css
.whatever {
border: 1px solid #000;
display: inline-block;
margin: 0 5px;
}
There is a different way to try your accordion without messing around with CSS
Get your HTML done as follows;
<div id='accordion'>
<h3>Title of the view</h3>
<div>
all the stuff you want to do here
</div>
<h3>Title of the view</h3>
<div>
all the stuff you want to do here
</div>
</div>
and make your script file as
$('#accordion').accordion({ active: 0 });
For more info: visit http://jqueryui.com/demos/accordion
I've updated your jsfiddle: http://jsfiddle.net/zRqYM/21/ and changed your p tags to div tags since it allows the most tag nesting.
As a general rule, a div tag cannot be inside of a p tag since it will cause the p tag to close itself.

Categories