show/hide on multiple div without defining div element id - html

first am sorry for bad English / grammar
am creating something where you show and hide.
but my problem is that when I click show/hide it only brings input box 1 on both buttons. and I want it to show/hide each box.
my problem is that. I don't want to use the id to define show/hide Element
because if I have more than 10 div with input boxes I have to define them all by getElementById I don't want that.
I want when I click on the show/hide it brings input box without getElementById
so that even if I have more then 10 input box to show I only click and show/hide without defining its id
function myFunction(event) {
var x = document.getElementById("mydv");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
x.parentNode.insertBefore(x, event.target.nextSibling);
}
document.addEventListener('click', function(event){
if(event.target.className.includes("dv1")){
myFunction(event);
}
});
<!DOCTYPE html>
<html>
<head>
<title> SHOW / Hide </title>
</head>
<body>
<ul>
<li>
<div id="mydv" style="display:none;">
<p>input box 1
<input type="text" name="textfield">
</p>
</div>
<button class="dv1">SHOW/HIDE</button>
</li>
<li><div id="mydv" style="display:none;">
<p>input box 2
<input type="text" name="textfield">
</p>
</div>
<button class="dv1">SHOW/HIDE</button></li>
</ul>
</body>
</html>

If you want to specify an element on a page, that can be similar in every way to other elements except perhaps text content or something else, realistically you need an id, as this is how JavaScript defines a unique element.
But what you can do, is change your HTML button, to contain a rel, which is an attribute, and then get that attribute and use that to specify which element id you're looking for.
You can then call a function and simply pass "this" as an argument.
HTML :
<button onclick="hideShow(this)" rel="mydv">Show/Hide</button>
JavaScript :
<script>
function hideShow(elem){
var ele = document.getElementById(elem.getAttribute("rel"));
if(ele.style.display == "none"){
ele.style.display = "block";
}
else{
ele.style.display = "none";
}
}
</script>
If you are absolutely abhorrent to using ID's, you can use child nodes and specify which child by number, but this means if ever you change anything, you will break your code, which is foolish. I recommend using unique ID's and simply changing your code in the above ways.

Short and lazy answer to your problems - if you are going to keep your current hierarchy, you can simply find DIV tag inside your LI parentNode (since its the only DIV tag).
Basically it goes like this - button press -> change focus from button to parentNode LI -> finds DIV.
in short - in function myFunction(event) change
var x = document.getElementById("mydv");
to
var x = event.target.parentNode.getElementsByTagName("DIV")[0];
Working example:
https://jsfiddle.net/w2a9zg46/1/

The problem is that getElementById refers to the first element with that id. It simply ignores everything else. Using the same id for more than one element is a bad practice. An id should be a unique reference to that element, use class instead.

Related

Jquery change css class from variable

For my site, I code a button allowing to change the css of a class present in a div card. My button is located in the card-footer. Having several cards, I can't / don't think to retrieve the element with an id (as there will be X times the same ID)
In order to circumvent this system, I therefore use a parentElement which goes up to the div card
<div class="card">
<div class="card-body">
<p class="change">Change one</p>
<p class="change">Change two</p>
<p class="change">Change three</p>
</div>
<div class="card-footer">
<i id="updateData">change</i>
</div>
</div>
jQuery($ => {
$('#updateData').click(e => {
var element = e.target.parentElement.parentElement;
$('.change').css('display','none');
});
});
I would like to indicate that only the class "changes" present in my element variable and not all the classes in the page.
I don't know how to add a variable to my ".css" command, do you know how ?
Thanks in advance !
First of all since you will have multiple elements with same id that means that you should not use ID and use class instead. Id is meant to be unique. So yours id="updateData" should become class="updateData". Now you can grab all of those buttons and assign event to all of them instead of just first like you were by using id selector.
$('.updateData').click(e=> {});
Next in order to be able to use clicked element in jQuery way convert from arrow function to regular anonymous function since arrow function overrides this keyword. And now you can use jQuery to hide like
$('.updateData').click(function() {
element = $(this).parent().parent();
element.hide();
});
If you want more precise selection to hide only .change elements use
$('.updateData').click(function() {
element = $(this).parent().parent();
element.find(".change").hide();
});
Not bad, but more efficient, when you have multiple click targets, is delegation:
$(document).on("click", ".updateData", function() { ... });
Also .hide() is convenient, but rather then "change the css of a class" add a class "hidden" or something! In best case the class further describes what the element is. CSS is just on top.

show and hide a label depending on empty state

I am appending several buttons into an html span tag every time I type on different inputs.
<span id="pill_filters>
<button id="filterCreated">Filter name here</button>
<button id="filterCreated2">Filter name here</button>
</span>
I also wanna show a label whenever there are buttons inside of this span tag and if they aren't, I wanna hide said label.
<label id="label_sc">Search Criteria:</label>
So far my jquery is
function showSCLabel(){
if ($("#pill_filters").html.is(':empty')){
$("#label_sc").addClass("d-none");
}else{
$("#label_sc").removeClass("d-none");
}
}
But it doesnt seem to work. The label already has "d-none" class since the beginning and even with that, it is still showing. What am I doing wrong? is this not how the :empty state works? what can I use instead? I'll appreciate a lot your help!
if statement is missing ()
.html.is is invalid jQuery
Use:
if ( $("#pill_filters").is(':empty') ) {
Answer without jQuery:
//span
const span=document.getElementById("pill_filters");
//label
const label=document.getElementById("label-sc");
span.addEventListener('DOMSubtreeModified',function(){
//if innerHTML is not ""
if(span.innerHTML){
//show label
label.style.display="block";
}else{
//hide label
label.style.display="none";
};
};

Apply style to grandparent of the grandchild with specific value [duplicate]

This question already has answers here:
Is there a CSS parent selector?
(33 answers)
Closed 8 years ago.
I have the following code:
<div class="photos-wrapper" id="detailPhoto">
<div class="pseudo">
fixedTEXT
</div>
<div class="image-wrapper">
</div>
<div class="activites">
</div>
<div class="commentaire">
</div>
</div>
I want to include my own CSS style to this first and main <div class="photos-wrapper" id="detailPhoto"> but the only way to do this is by identify the grandchild selector i.e <a href="#/123456/"> because there are multiple occurrences of the same code.
Maybe it will be a bit more clear when I show what I tried:
a[href*="123456"] > div.pseudo > div.photos-wrapper[id^="detailPhoto"] {
display: none !important;
}
div.photos-wrapper[id^="detailPhoto"] < div.pseudo < a[href*="123456"] {
display: none !important;
}
That's the way I tried to do so but it obviously is not working.
The thing I am probably trying to do here is called a parent selector but I'm not quite sure.
#edit
Let's take a look on this code, it's actually more detailed:
http://jsfiddle.net/60ezqtL7/
The goal is to hide by display: none; style whole divs that are containing exactly the same values i.e. PHOTO 1
There's no need to use jQuery in this case (or many other cases).
detailPhoto.classList.toggle('hide', detailPhoto.querySelector('[href=#/123456]'))
As I mentioned in my comment to your answer, there is not parent or ancestor selecor. The easiest and most efficient way to to it via jQuery is the has() method.
$('#detailPhoto').has('a[href*="123456"]').hide(); // or use .addClass() instead
Use Google to host jquery for you.
Demo : I've used the class selector in the demo as id should be unique.
addClass Demo
UPDATE
Given your update and assuming you want to display 1 and only 1 of each photo, additional wrappers with photos with the same href will be hidden.
/*Loop through each link in div with cass psudo
in a div with class photos-wrapper*/
var found = {};
$(".photos-wrapper .pseudo a").each(function(){
var $this = $(this);
var href = $this.attr("href");
//if the href has been enountered before, hide the .photos-wrapper ancestor
if(found[href]){
$this.closest(".photos-wrapper").hide();
/*Other options:
Use Css direct
$this.closest(".photos-wrapper").css("display", "none");
Assign a duplicate class, then style that class ass appropriate
$this.closest(".photos-wrapper").addClass("duplicate");
*/
}else{
//otherwise add it to the array of what has been found
found[href] = true;
}
});
Demo
If you're not familiar with jquery, make sure to read up on how it is implemented and the purpose of $(document).ready();
Update 2
To hide all containers with replicated href use:
//Loop through each a tag
$(".photos-wrapper .pseudo a").each(function () {
var $this = $(this);
//Get the href
var href = $this.attr("href");
//Check if more than one exists
if ($('.photos-wrapper .pseudo a[href="' + href + '"]').size() > 1) {
//Hide all .photo-wrapper containers that have the replicated href
$('.photos-wrapper .pseudo a[href="' + href + '"]').closest(".photos-wrapper").hide();
}
});
Another Demo
I still suggest removing duplicates server-side if at all possible.
On a complete side note, the <center> tag was depreciated back at HTML4 and should no longer be used. Use CSS instead. There are pleanty of examples out there on how to center content using CSS.
At this time there is not a way to do this with only CSS, but you can do it easily with JQuery. This will search the descendants of #detailPhoto and hide the href (set it to display: none;).
<script>
$(function() {
$('#detailPhoto').find('a[href$="#/123456/"]').hide();
});
</script>
To search parents, you'd use this.
<script>
$(function() {
$('a[href$="#/123456/"]').closest('#detailPhoto').hide();
});
</script>
To use this you will also need the JQuery library added to the head of your document.
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

AngularJs - how to support a textbox with hyperlinks

I'm new to Angular but I'm trying to implement a textbox that allows users to enter in links. I only want to support links, and otherwise I want to block all html from being presented as such. I could theoretically use something other than a textarea, but my requirements are that it must be bound to a variable in my scope (right now with ng-model) and I cannot accept html tags other than '< a >'
Here is my example plnkr
In the example, I would like the second seeded item to display as a link, blue and underlined. However, the third item should display as it is currently shown (without interpreting it as html).
HTML:
<textarea maxlength="160" ng-model="val.text"></textarea>
<div class="btn" ng-click="submit()">Submit</div>
<br><br>
<div ng-repeat="item in items">
{{display(item)}}
</div>
JS:
$scope.submit = function() {
if (!$scope.val.text) return
$scope.items.push($scope.val.text);
}
$scope.display = function(txt) {
return txt;
// something here? if txt contains <a> and </a> indicate
// that we should display as html
}

Ideas for multicolored textbox?

In my site, I would like to implement a textbox where people can input a set of strings separated by a separator character.
For example the tags textbox at the bottom of this page: tags(strings) delimited by space(separator).
To make it more clear to the user, it would make a lot of sence to give each string a different background color or other visual hint.
I don't think this is possible with a regular input[text] control.
Do you deem it possible to create something like that with javascript? Has somebody done this before me already? Do you have any other suggestions?
Basic Steps
Put a textbox in a div and style it too hide it.
Make the div look like a text box.
In the onClick handler of the div, set the input focus to the hidden text box.
Handle the onKeyUp event of the hidden text box to capture text, format as necessary and alter the innerHtml of the div.
Tis quite straightforward. I'll leave you to write your formatter but basically you'd just splitString on separator as per the Semi-Working-Example.
Simple Outline
<html>
<head>
<script language="javascript" type="text/javascript">
function focusHiddenInput()
{
var txt = document.getElementById("txtHidden");
txt.focus();
}
function formatInputAndDumpToDiv()
{
alert('Up to you how to format');
}
</script>
</head>
<body>
<div onclick="focusHiddenInput();">
Some label here followed by a divved textbox:
<input id="txtHidden" style="width:0px;" onKeyPress="formatInputAndDumpToDiv()" type="text">
</div>
</body>
</html>
Semi-Working Example
You still need to extend the click handlers to account for tag deletion/editing/backspacing/etc via keyboard.... or you could just use a click event to pop up another context menu div. But with tags and spacer ids identified in the code below that should be pretty easy:
<html>
<head>
<script language="javascript" type="text/javascript">
var myTags=null;
function init()
{
document.getElementById("txtHidden").onkeyup= runFormatter;
}
function focusHiddenInput()
{
document.getElementById("txtHidden").focus();
}
function runFormatter()
{
var txt = document.getElementById("txtHidden");
var txtdiv = document.getElementById("txtBoxDiv");
txtdiv.innerHTML = "";
formatText(txt.value, txtdiv);
}
function formatText(tagText, divTextBox)
{
var tagString="";
var newTag;
var newSpace;
myTags = tagText.split(' ');
for(i=0;i<myTags.length;i++) {
newTag = document.createElement("span");
newTag.setAttribute("id", "tagId_" + i);
newTag.setAttribute("title", myTags[i]);
newTag.setAttribute("innerText", myTags[i]);
if ((i % 2)==0) {
newTag.style.backgroundColor='#eee999';
}
else
{
newTag.style.backgroundColor='#ccceee';
}
divTextBox.appendChild(newTag);
newTag.onclick = function(){tagClickedHandler(this);}
newSpace = document.createElement("span");
newSpace.setAttribute("id", "spId_" + i);
newSpace.setAttribute("innerText", " ");
divTextBox.appendChild(newSpace);
newSpace.onclick = function(){spaceClickedHandler(this);}
}
}
function tagClickedHandler(tag)
{
alert('You clicked a tag:' + tag.title);
}
function spaceClickedHandler(spacer)
{
alert('You clicked a spacer');
}
window.onload=init;
</script>
</head>
<body>
<div id="txtBoxDivContainer">
Enter tags below (Click and Type):<div id="txtBoxDiv" style="border: solid 1px #cccccc; height:20px;width:400px;" onclick="focusHiddenInput();"></div>
<input id="txtHidden" style="width:0px;" type="text">
</div>
</body>
</html>
Cursor
You could CSS the cursor using blink (check support) or otherwise just advance and hide as necessary an animated gif.
This is quite interesting. The short answer to your question is no. Not with the basic input element.
The real answer is: Maybe with some trickery with javascript.
Apparently Facebook does something close to this. When you write a new message to multiple persons in Facebook, you can type their names this sort of way. Each recognized new name is added a bit like an tag here and has an small cross next to it for removing it.
What they seem to do, is fake the input area size by drawing an input-looking box and removing all styling from the actual input with css. Then they have plenty of logic done with javascript so that if you have added an friend as a tag and start backspacing, it will remove the whole friends name at once. etc.
So, yes, it's doable, but takes plenty of effort and adds accessibility problems.
You can look how they do that at scripts like TinyMCE, which add such features to textareas. In textareas you can use HTML to colorize text.
You can use multiple textboxes
textbox1 <space> textbox2 <space> textbox3 ....
and so on... You can then apply the background-color style to each textbox.