When the user clicks the drop down menu, I want to show emojis. But the problem is the only way I know how to do that is to input an emoji one by one.
My question is how do I show all the emojis? I want to when the user clicks the drop down menu and when they click the emoji, add it to the text area.
home.php:
<textarea id="textf2" rows="3" maxlength="3000" placeholder="Enter text" cols="35">
</textarea>
<button id="bt6" type="submit" name="search">Post status</button>
<div class="dropdown" id="div1">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content">
</div>
</div>
<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
Okay, I think this is what you want:
After looking here and tinkering with the code for an hour, I got this:
emojis = document.getElementById("myDropdown").getElementsByTagName("li")
for (var i = 0; i < emojis.length; i++) {
emojis[i].addEventListener("click", function() {
var smiley = this.innerHTML;
ins2pos(smiley, 'textf2');
});
}
function ins2pos(str, id) {
var TextArea = document.getElementById(id);
var val = TextArea.value;
var before = val.substring(0, TextArea.selectionStart);
var after = val.substring(TextArea.selectionEnd, val.length);
TextArea.value = before + str + after;
setCursor(TextArea, before.length + str.length);
}
function setCursor(elem, pos) {
if (elem.setSelectionRange) {
elem.focus();
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn') && !event.target.matches('#myDropdown li')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
#myDropdown {
display: none
}
#myDropdown.show {
display: block;
}
<textarea id="textf2" rows="3" maxlength="3000" placeholder="Enter text" cols="35">
</textarea>
<button id="bt6" type="submit" name="search">Post status</button>
<div class="dropdown" id="div1">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<ul id="myDropdown" class="dropdown-content">
<li>😁</li>
<li>😃</li>
<li>😅</li>
</ul>
</div>
JSfiddle and more emojis here
Hope that helps!
Update: To include images, you got to use <div id="textf2" contentEditable="true"></div> instead of the text area and use the code noted here
emojis = document.getElementById("myDropdown").getElementsByTagName("li")
for (var i = 0; i < emojis.length; i++) {
emojis[i].addEventListener("click", function() {
var smiley = this.innerHTML;
pasteHtmlAtCaret(smiley + " ");
});
}
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// only relatively recently standardized and is not supported in
// some browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn') && !event.target.matches('#myDropdown img')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
#myDropdown {
display: none
}
#myDropdown.show {
display: block;
}
#text_wrapper {
margin: 40px;
border: 1px solid #ccc;
}
#textf2 {
outline: none;
margin: 10px;
min-height: 100px;
}
img {
width: 50px;
height: auto;
}
<div id="text_wrapper">
<div id="textf2" contentEditable="true">
</div>
</div>
<button id="bt6" type="submit" name="search">Post status</button>
<div class="dropdown" id="div1">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<ul id="myDropdown" class="dropdown-content">
<li><img src="https://upload.wikimedia.org/wikipedia/commons/e/ec/Happy_smiley_face.png" /></li>
<li><img src="http://res.freestockphotos.biz/pictures/15/15550-illustration-of-a-yellow-smiley-face-pv.png" /></li>
<li><img src="http://res.freestockphotos.biz/pictures/15/15564-illustration-of-a-yellow-smiley-face-pv.png" /></li>
</ul>
</div>
EDIT: I misread the question, so I'll add in how I would do it:
I would create an array of Emoji characters. I would then loop over this array of emojis. For each emoji in the array you want to perform a 'map' operation so you get an HTML element. Then you want to append these elements to the dropdown-content element as children.
For example:
var emojis = ['😍','😀','🤑']; // put all emojis in here
emojis.map((character) => {
var a = document.createElement('a');
a.src='#';
a.textContent = character;
a.addEventListener(
'click',
function() { /* append character to the textarea. this will probably something simple like 'textareaElement.value += character */}
);
return a;
});
emojis.forEach((el) => dropDownContentElement.appendChild(el));
Related
I made this favImages array and added some image objects to it. Then I am trying to append a paragraph element(removeButton) to each of them which will be triggered by clicking the images.
var favImages = new Object();
for (var i = 0; i < 5; i++) {
favImages[i] = document.getElementById("fav" + (i + 1));
}
var removeButton = document.createElement("p");
removeButton.id = "removebutton";
removeButton.innerHTML = "Remove Image";
for (var i = 0; i < 5; i++) {
var newImage = document.getElementById(favImages[i].id);
newImage.addEventListener("click", function() {
newImage.appendChild(removeButton)
}, false);
}
Don't use a loop. Use an event listener on the container and test what was clicked using event.target. You cannot add a child to an image
You COULD use a div, put the image as a background and the span to click as content
Anyway here are some examples
document.getElementById("container").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("remove")) tgt.closest("div").remove()
})
#container div {
width: 200px
}
.remove {
float: right
}
<div id="container">
<div>
<span class="remove">X</span>
<img src="https://via.placeholder.com/150/0000FF/000888?text=image1" />
</div>
<div>
<span class="remove">X</span>
<img src="https://via.placeholder.com/150/FF00FF/000888?text=image2" />
</div>
<div>
<span class="remove">X</span>
<img src="https://via.placeholder.com/150/FF0000/000888?text=image3" />
</div>
</div>
From an array:
const images = [
"https://via.placeholder.com/150/0000FF/000888?text=image1",
"https://via.placeholder.com/150/FF00FF/000888?text=image2",
"https://via.placeholder.com/150/FF0000/000888?text=image3"
];
const container = document.getElementById("container");
container.innerHTML = images.map(img => `<div><span class="remove">X</span>
<img src="${img}" /></div>`).join("");
container.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("remove")) tgt.closest("div").remove()
})
#container div {
width: 200px
}
.remove {
float: right
}
<div id="container">
</div>
Okay, so I'm getting a weird problem with my onClick elements.
I'm using PHP to echo some code, and here it is:
<div class = \"dropdown\">
<i id = \"elipses_$id\" onClick = \"dropDown_$id()\" style = \"color:#777\" class=\"fas fa-ellipsis-v\"></i>
<div id = \"dropdown_$id\" class = \"dropdown-content\">
[html code here isn't relevant]
</div>
</div>
When I open inspect element, and I click the button, it outputs the function name:
And when I type the function name into the console, the dropdown opens like it should. So why doesn't it do it when I click?
Not sure if it is needed, but here is the script I am using to open/close the dropdown.
function dropDown_$id() {
document.getElementById(\"dropdown_$id\").classList.toggle(\"show\");
}
window.onclick = function(event) {
console.log(event.target);
if (!event.target.matches('#dropdown_$id') && !event.target.matches('#elipses_$id')) {
var dropdown = document.getElementById(\"#dropdowm_$id\");
var c;
if(dropdown != null){
for (c = 0; c < dropdown.length; c++) {
var openDropdowns = dropdown[c];
if (openDropdowns.classList.contains('show')) {
openDropdowns.classList.remove('show');
}
}
}
}
}
EDIT: This is the raw HTML of the dropdown that is spat out after PHP is run:
<div id="dropdown_26" class="dropdown-content">
<div id="names" style="border-bottom: thin solid #BDBDBD;">
<h2 class="dropdown-contenth2">Francois van Kempen</h2>
<p style="color:grey;margin-top:-20px; margin-left: 16px;">#Bork_Bork</p>
</div>
div id="settings" style="border-bottom: thin solid #BDBDBD;">
<a id="a1" class="dropdown-contenta" href="settings.php">Accout Settings</a>
<form id="dark_mode_form" action="nightmode.php" method="POST" style="padding: 10px; display:flex;justify-content:flex-start;align-content:center">
<label style="" class="switch">
<input onchange="this.form.submit()" type="checkbox" name="darkmode" value="checked">
<span class="slider round"></span>
</label>
<p class="dropdown-contentp" style="margin:0;padding:0; margin-left:5px;margin-top:5px;">Night mode</p>
</form>
</div>
<a id="a2" class="dropdown-contenta" href="logout.php">Log out #Bork_Bork</a>
<a id="a3" class="dropdown-contenta" href="reset-password.php">Reset password #Bork_Bork</a>
</div>
EDIT 2: Added the raw script:
<script id="dropdown-settings" type="text/javascript">
function dropDown() {
document.getElementById("dropdown").classList.toggle("show");
}
function dropDown_26() {
document.getElementById("dropdown_26").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
console.log(event.target);
if (!event.target.closest('#dropdown') && !event.target.closest('#navPFP')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
if (!event.target.matches('#dropdown_26') && !event.target.matches('#elipses_26')) {
var dropdown = document.getElementById("#dropdowm_26");
var c;
if(dropdown != null){
for (c = 0; c < dropdown.length; c++) {
var openDropdowns = dropdown[c];
if (openDropdowns.classList.contains('show')) {
openDropdowns.classList.remove('show');
}
}
}
}
}
</script>
I am unable to move "close" to the right side.
I have tried float:right, right:0, align-content:right in css but nothing seems to work.
index.html
<head>
<style>
.close{
right:0;
}
</style>
</head>
<body>
<div>
<input type = "text" size = "35" id="work" placeholder = "Enter your list here">
<input type="submit" onClick="appendToDoList()" value="Add to List">
</div>
<ul id="workUl">
<li>Work out</li>
</ul>
<script>
//include a close button for list
var getList= document.getElementsByTagName("LI");
var i;
for(i=0; i<getList.length; i++){
var span = document.createElement("SPAN");
var closebtn = document.createTextNode("\u00D7");
span.appendChild(closebtn);
getList[i].appendChild(span);
}
//add to the list
function appendToDoList(){
var ListN = document.createElement("li");
var N = document.getElementById("work").value;
var t = document.createTextNode(N);
ListN.appendChild(t);
if (N === '') {
alert("You must write something!");
} else {
document.getElementById("workUl").appendChild(ListN);
}
document.getElementById("work").value = "";
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(txt);
var i;
for(i=0; i<close.length;i++){
}
ListN.appendChild(span);
}
The close button should be align to the right side. Could you please suggest something. I also went through the similar post in past, however it does not seem to work for me.
Try to write a well structured code. I have create a fiddle with 2-3 minor corrections and the close "button" seems to be on the right side (https://jsfiddle.net/x1kf8mz6/)
HTML:
<!DOCTYPE html>
<html>
<body>
<div>
<input type = "text" size = "35" id="work" placeholder = "Enter your list here">
<input type="submit" onClick="appendToDoList()" value="Add to List">
</div>
<ul id="workUl">
<li>Work out</li>
</ul>
</body>
</html>
JS:
//add to the list
function appendToDoList(){
var ListN = document.createElement("li");
var N = document.getElementById("work").value;
var t = document.createTextNode(N);
ListN.appendChild(t);
if (N === '') {
alert("You must write something!");
} else {
document.getElementById("workUl").appendChild(ListN);
}
document.getElementById("work").value = "";
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(txt);
var i;
for(i=0; i<close.length;i++){
}
ListN.appendChild(span);
}
and finally CSS:
.close{
right:0;
}
Make sure that you set the "position" absolute for span tag and position "relative" for li tag. Then it will definitely work.
Try add this in CSS (for me it worked, if i understood your question)
ul li {
position: relative;
padding: 5px 5px 5px 5px;
}
.close {
position: absolute;
right: 0; //you can change the icon distance (**for example:**just add like 5em, the *close* icon will come closer)//
top: 0;
}
This question already has answers here:
How to call multiple JavaScript functions in onclick event?
(14 answers)
Closed 5 years ago.
I have two JS functions:
function myFunctionMenu() {
document.getElementById("main-menu").classList.toggle("shows");
}
and
function expandFunction() {
document.getElementById("menu-button").classList.toggle("expand");
}
Both of which toggle classes. Those classes have styles:
.shows {
margin-right: auto;
margin-left: auto;
display: block;
transition: all 2s ease;
}
and
.expand {
padding: 1% 20%;
background-color: #8c8c8c;
}
I then have two more functions, one for each of those original functions, which removes that class when clicking outside of the button that initiates both functions:
window.onclick = function(event) {
if (!event.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("house-menu");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('shows')) {
openDropdown.classList.remove('shows');
}
}
}
}
and
window.onclick = function(event) {
if (!event.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("dropbtn");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('expand')) {
openDropdown.classList.remove('expand');
}
}
}
}
The HTML follows, just in case:
<!doctype html>
<head>
<title>Site Photos</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="Styles/new-menu.css">
<script type="text/javascript" src="script/menu-scripts.js"></script>
</head>
<body>
<br>
<h1>
Name <br>
</h1>
<h2>
Site Photos
</h2>
<!--Menu-->
<div class="menu-container" div style="margin-left:auto; margin right:auto; margin-top:5%; margin-bottom:auto; width:40%;">
<!-- Main Menu Button -->
<div id="main-button-container" style="text-align:center; margin-top:-8%;">
<button onclick="myFunctionMenu();expandFunction()" class="dropbtn" id="menu-button"> Menu </button>
</div>
<hr>
<!-- Main Menu Container -->
<div id="main-menu" class="house-menu">
Main House <hr>
Car Barn <hr>
Utility Building <hr>
Central Plant <hr>
Exteriors<hr>
</div>
<hr>
</div>
</body>
</html>
The problem I am having is that I can only run one of the two "remove when click outside the button" functions at a time.
Can anyone explain to me why?
Thank you.
Because the first window.onclick will get overridden by the second one. Just like writing var a = 1; and later var a = 2;. You should use document.addEventListener for this purpose:
document.addEventListener("click", function(e){
if (!e.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("house-menu");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('shows')) {
openDropdown.classList.remove('shows');
}
}
}
});
and
document.addEventListener("click", function(e){
if (!e.target.matches('#menu-button')) {
var dropdowns = document.getElementsByClassName("dropbtn");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('expand')) {
openDropdown.classList.remove('expand');
}
}
}
});
I am trying to filter the div element based on user input i already done with table element but now i need to do the same in div element.
User Input
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for Teacher.." title="Type in a name"><br/>
Table data
<div style="border:1px solid gray">
<table id="myTable" >
<c:forEach var="tr" items="${teachersList}">
<tr><td><a href="teacher_view_adm?tcrId=${tr.id}" >${tr.fname} ${tr.lname}</a><br/>Last Seen</td>
</tr>
</c:forEach>
</table>
</div>
Table script
<script>
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
if(filter==""){
}
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
above code works fine for table elements but how can i change to div elements. bellow i specify the structure of div element data.
Div element
<div style="border:1px solid gray" id="myDiv">
<c:forEach var="tr" items="${teachersList}">
<div>
<p><a href="teacher_view_adm?tcrId=${tr.id}" >${tr.fname} ${tr.lname}</a><br/>Last Seen</p>
</div>
</c:forEach>
</div>
I need to change the above table script to div element script can any one help me to do this?
If I understand correctly, you need something like this.
var input = document.getElementById("myInput");
input.addEventListener("input", myFunction);
function myFunction(e) {
var filter = e.target.value.toUpperCase();
var list = document.getElementById("list");
var divs = list.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
var a = divs[i].getElementsByTagName("a")[0];
if (a) {
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
divs[i].style.display = "";
} else {
divs[i].style.display = "none";
}
}
}
}
<input type="text" id="myInput" placeholder="Search for Teacher.." title="Type in a name"><br/>
<div id="list">
<div>
<p>test data 1<br/>Last Seen</p>
</div>
<div>
<p>test data 2<br/>Last Seen</p>
</div>
<div>
<p>new test data 3<br/>Last Seen</p>
</div>
</div>
https://jsfiddle.net/npx0gv9n/
You can try something like this:
Idea
Get the parent div and check if it has divs inside it.
If yes, use recursion to validate them.
If not, validate them directly.
To validate, accept searchQuery and div's text and parse them to lowercase. This will allow you to do case insensitive search.
Them just check for existence of searchQuery in this text. If yes, add a class (hide). If no, remove it.
function searchMyValue(container) {
var search = document.getElementById('txtQuery').value.toLowerCase();
var text = container.textContent.toLowerCase();
var childDivs = container.querySelectorAll('div');
if (childDivs.length) {
Array.prototype.slice.call(childDivs).forEach(x => searchMyValue(x));
} else if (search.trim() && text.indexOf(search) < 0) {
container.classList.add('hide')
} else {
container.classList.remove('hide')
}
}
var btn = document.getElementById('btnSearch')
btn.addEventListener("click", searchMyValue.bind(btn, document.querySelector('.container')))
function createDivs(array, element) {
var divs = [];
for (var i = 0; i < array.length; i++) {
(function(i) {
var d = document.createElement('div');
var p = document.createElement('p');
var a = document.createElement('a');
a.textContent = array[i];
p.append(a);
d.append(p);
divs.push(d);
})(i)
}
element.append.apply(element, divs)
}
createDivs(["foo", "bar", "Hello World", "test"], document.querySelector('.content'));
createDivs(["Sachin", "Rahul", "Trend", "Virat"], document.querySelector('.content2'));
.hide {
display: none
}
<div class="filter">
<input type="text" id="txtQuery">
<button id="btnSearch">Search</button>
</div>
<div class="container">
<div class="content"></div>
<div class="content2"></div>
</div>