show and hide a label depending on empty state - html

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";
};
};

Related

show/hide on multiple div without defining div element id

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.

angular ngModel style

Is it possible to style the value in the attribute ngModel of an input tag?
Example:
<input class="input" type="text" [(ngModel)] = "myService.text">
Let's say the value of text is '28 packages', can I put 28 in bold?
So if i understand correctly you want to have it bold whenever the value is 28 ?
yes its possible you can use a ng-class with a ternary expression like this
.bold{
font-weight:600;
}
<input type="text" ng-class="myService.text == '28 ? 'bold' : '''" class="input" ng-model="myService.text" />
This is not angular-related rather a CSS related question.
You cannot style only a part of an input in HTML/CSS so you won't be able to do it in angular.
Instead, you can use an input that is hidden behind a div. The idea is that when the user clicks the div, you actually focus the input. When the user types text, you capture the content of the input and fill the div with it, eventually adding <span class"highlight"> around the number of packages.
I prepared you a stackblitz in pure CSS/JS. You can adapt it in angular if you want.
Relevant pieces of code :
HTML :
<span id="hiddenSpan">This is the hidden div. Click it and start typing</span>
<div>
<label for="in">The real input</label>
<input id="in" type="text">
</div>
JS :
const input = document.getElementById('in')
const hiddenSpan = document.getElementById('hiddenSpan')
function onInputChanged() {
let text = input.value
const regex = new RegExp('(\\d+) packages')
let result = regex.exec(text)
if(result) {
hiddenSpan.innerHTML = '<span class="highlight">'+result[1]+'</span> packages'
} else {
hiddenSpan.innerHTML = text
}
}
// Capture keystrokes.
input.addEventListener('keyup', onInputChanged)
// Focus the input when the user clicks the pink div.
hiddenSpan.addEventListener('click', function() {
input.focus()
})
CSS :
#hiddenSpan {
background-color: pink;
}
.highlight {
font-weight: bold;
background-color: greenyellow;
}
Note : the downside is that the blinking caret is not visible anymore. You can take a look at this resource if you want to simulate one.
It is not possible to style certain parts of a text <input> field in bold. However, you can use a contenteditable div instead of a text <input> field. Inside the contenteditable div you can have other HTML tags like <strong> to style certain parts of the text however you like.
I created an Angular directive called contenteditableModel (check out the StackBlitz demo here) and you can use it to perform 2-way binding on a contenteditable element like this:
<div class="input" contenteditable [(contenteditableModel)]="myService.text"></div>
The directive uses regular expressions to automatically check for numbers in the inputted text, and surrounds them in a <strong> tag to make them bold. For example, if you input "28 packages", the innerHTML of the div will be formatted like this (to make "28" bolded):
<strong>28</strong> packages
This is the code used in the directive to perform the formatting:
var inputElement = this.elementRef.nativeElement;
inputElement.innerHTML = inputElement.textContent.replace(/(\d+)/g, "<strong>$1</strong>");
this.change.emit(inputElement.textContent);
You can change the <strong> tag to something else (e.g. <span style="text-decoration: underline"> if you want the text to be underlined instead of bolded).
When performing the formatting, there is an issue where the user's text cursor position will be unexpectedly reset back to the beginning of the contenteditable div. To fix this, I used 2 functions (getOriginalCaretPosition and restoreCaretPosition) to store the user's original cursor position and then restore the position back after the text formatting is performed. These 2 functions are kind of complex and they're not entirely relevant to the OP's question so I will not go into much detail about them here. You can PM me if you want to learn more about them.

div contentEditable but Readonly

I have a div with some text and I want when the cursor is hover this div to select the text. If I let this div as it is, when trying to select all (CTRL+A) then I select all page content, meaning all body text.
To get rid of this, I need to use contenteditable attribute for this div.
But I don't want to let people to change the text / copy / cut and so on
I try to use readonly for this div, but doesn't working.
Any advice please ?
PS1: This div has also other tags inside (html content), but I don't think that this is a problem.
PS2: An example is here: jsfiddle.net/msakamoto_sf/wfae8hzv/ - but with a problem. You can cut the text :(
Use event.metaKey in the keydown event to check if ctrl (or cmd on mac) keys are being pressed. You also have to disable the cut and paste events.
<div
contenteditable="true"
oncut="return false"
onpaste="return false"
onkeydown="if(event.metaKey) return true; return false;">
content goes here
</div>
You can prevent the user from cutting by handling the "cut" event and calling its preventDefault() method. This will prevent cut with any user input (including the browser's context menu or edit menu), not just via a particular key combination.
This example uses jQuery because your jsFiddle uses it:
$("#editablediv").on("cut", function(e) {
e.preventDefault();
});
set contenteditable to false and it should work !! that simple.
use contenteditable attribute for div to make it editable or not
and use readonly attr for form input elements.
<element contenteditable="true|false">
<input readonly="readonly" />
Here's an example in React, but it would work with basic HTML and JavaScript as well because I'm just leveraging the default events.
// import CSS
import './DefaultSettings.css';
// import packages
import React, { Component } from 'react';
// import components
const noop = (e) => {
e.preventDefault();
return false;
};
class DefaultSettings extends Component {
render() {
return (
<div className="DefaultSettings"
contentEditable={true}
onCut={noop}
onCopy={noop}
onPaste={noop}
onKeyDown={noop}>
</div>
);
}
}
export default DefaultSettings;
To prevent ctrl + x (Cut) from div you need to use following JQuery :
if (event.ctrlKey && event.keyCode === 88)
{
return false;
}
It will prevent to cut text from div.
Check Fiddle Here.
on user id condition set contentEditable="false"
for JavaScript,
document.getElementById(divid).contentEditable = "false";
this will work

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.