In HTML, I have a button list. If user clicks a button,
doCommand function will be called.
The code is following,
<ul>
<li class="button1" onclick="doCommand('bold');" id="bold-button" title="bold">B</li>
<li class="button2" onclick="doCommand('bold');" id="italic-button" title="bold">I</li>
<li class="button3" onclick="doCommand('bold');" id="underline-button" title="bold">U</li>
<li class="button4" onclick="doCommand('bold');" id="strikethrough-button" title="bold">S</li>
</ul>
This is plain expression, normal web programmer will code like that.
But, I want to hide onclick event and its function for security reason.
So the HTML code will be like this,
<ul>
<li class="button1" id="bold-button" title="bold">B</li>
<li class="button2" id="italic-button" title="bold">I</li>
<li class="button3" id="underline-button" title="bold">U</li>
<li class="button4" id="strikethrough-button" title="bold">S</li>
</ul>
Is there any efficient way to do this?
Hiding onclick property but do the same work.
I am using jQuery.
if you set the same class for the btns, you could easily do:
markup:
<ul>
<li class="button1 clickable" id="bold-button" title="bold">B</li>
<li class="button2 clickable" id="italic-button" title="bold">I</li>
<li class="button3 clickable" id="underline-button" title="bold">U</li>
<li class="button4 clickable" id="strikethrough-button" title="bold">S</li>
</ul>
js:
$('.clickable').click(function(){/* doCommand('bold') or whatever */})
Edit: if you want on click to directly transform the text to bold, you could use the this (that refers to the element you clicked, and you need to wrap it inside jQuery $) keyword inside the function i.e.
$('.clickable').click(function(){$(this).css('font-weight','bold')})
The class should be the same at all buttons, like this:
<li class="button button1"...
<li class="button button2"...
Then, you can do like this in javascript.
$("li.button").click(function() {
doCommand('bold');
});
Without changing your markup and using vanilla JS you can do it the following way.
const list = document.querySelector('ul');
list.addEventListener('click', e => {
if (e.target.classList.contains('button1')) {
console.log('bold');
};
if (e.target.classList.contains('button2')) {
console.log('italics');
};
if (e.target.classList.contains('button3')) {
console.log('underline');
};
if (e.target.classList.contains('button4')) {
console.log('strikethrough');
};
})
<ul>
<li class="button1" id="bold-button" title="bold">B</li>
<li class="button2" id="italic-button" title="bold">I</li>
<li class="button3" id="underline-button" title="bold">U</li>
<li class="button4" id="strikethrough-button" title="bold">S</li>
</ul>
I assign the event to the parent list, and check the class of the target allowing to do whatever action needed.
You can use jquery's document ready event to wire up the events:
$(function()
{
$("#bold-button").click(function(){doCommand('bold');});
}
);
Related
i am in a bit of a pickle.
I am trying to get a button to delete its parent when clicked.
But when i run the code it won't respond. in fact , it doesn't delete anything at all.
I have specified that IF() event.target === deleteButton{ remove parent}
but it either doesn't recognise the event, or it fails to find the parent.
a bit of help would be greatly apreciated!
I
const todoListElement = document.getElementById('ordered-todo-list');
const form = document.getElementById('todo-form');
const deleteButton = document.querySelector('.delete');
todoListElement?.addEventListener("click", todoListEraser)
function todoListEraser( event:MouseEvent) {
console.log(event.target)
if (event.target === deleteButton ){
(event.target as HTMLElement).closest('li')?.remove();
}
else {
return console.log('did not work, try again');
}
}
<template id="list-item-template">
<li class="list-item">
<input type="checkbox" class="status-toggle" name="form-checkbox">
<p class="task-text"></p>
<button class="delete" >X</button>
</li>
</template>
<ol id="ordered-todo-list">
</ol>
am working in typescript.
My answer might be completely wrong for what you need, but this doesn't seem to be your complete code so I had to take some guesses.
There are two ways I can see this being done. If the <li> elements in your template are added to the list before this JavaScript executes, you can use the first method (commented out). If the <li> elements from your template are added after this JavaScript executes, the second method should work just fine.
/*
// Method 1
document.querySelectorAll(".delete").forEach(el => {
el.addEventListener("click", e => {
e.target.parentElement.remove();
});
});
*/
// Method 2
document.querySelector("#ordered-todo-list").addEventListener("click", e=> {
if(e.target.className.includes("delete")) {
e.target.parentElement.remove();
}
});
<ol id="ordered-todo-list">
<li class="list-item">
<input type="checkbox" class="status-toggle" name="form-checkbox">
<p class="task-text"></p>
<button class="delete" >X</button>
</li>
<li class="list-item">
<input type="checkbox" class="status-toggle" name="form-checkbox">
<p class="task-text"></p>
<button class="delete" >X</button>
</li>
<li class="list-item">
<input type="checkbox" class="status-toggle" name="form-checkbox">
<p class="task-text"></p>
<button class="delete" >X</button>
</li>
</ol>
Method 1 adds event listeners to the delete buttons themselves. Then it simply removes the parentElement.
Method 2 adds the event listener to the <ol> element and checks to see if the element clicked (e.target) is a delete button by checking the className attribute.
I need to loop through the DOM with JQuery, and add a click handler to multiple parent elements that contain a child that will also be given a slideToggle(). I have the logic working fine when I add the click handlers manually, but now I need to be able to dynamically do this to multiple parent elements.
Here is my HTML:
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
Basically, you click on .sub-menu-link to slideToggle() .sub-menu-list.
Here is the JS that I have working so far. It targets the id's manually currently, which feels gross:
$('#sub-menu-link-1').click(function() {
$('#sub-menu-list-1').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
$('#sub-menu-link-2').click(function() {
$('#sub-menu-list-2').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
My apologies if this is something very apparent to do in JQuery. I am not at all familiar with it, and it just so happens to be a requirement of this project.
you could simply use below code.
select all list items with class name and add listener. click will be attached to all elements
$('.sub-menu-link').click(function() {
$(this).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
You already have classes, so just use them instead of the ids: use this to refer to the clicked element, .next() to get the next sibling (the li.sub-menu), and .find('.sub-menu-list') to get to the ul you want to toggle:
$('.sub-menu-link').click(function() {
const $subMenuList = $(this).next().find('.sub-menu-list');
console.log($subMenuList.text().trim());
$subMenuList.slideToggle(100);
$(this).toggleClass('active-menu-link');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
You can use jQuery's .next() like so:
$(".sub-menu-link").click(function() {
$(this).next(".sub-menu-link").slideToggle(100);
$(this).toggleClass("active-menu-link");
})
Or you can chain them and use ES6 arrow syntax to make it more concise:
$(".sub-menu-link").click(() => $(this).toggleClass("active-menu-link").next(".sub-menu-link").slideToggle(100));
You should try this if your list and link ids have similiar pattern as in the code you have shown
$('#sub-menu-link').click(function() {
var id = $(this).attr("id").replace("sub-menu-link", "")
$('#sub-menu-list-'+ id).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
When I put onClick event in button element inside li element like below to make AJAX:
<ul>
<li><button value="orange" onClick="qCat(value)">Orange</button></li>
<li><button value="apple" onClick="qCat(value)">Apple</button></li>
</ul>
It works nicely.
But if I take away button to apply event directly to li element like below make AJAX:
<ul>
<li value="orange" onClick="qCat(value)">Orange</li>
<li value="apple" onClick="qCat(value)">Apple</li>
</ul>
It won't work. Anything wrong with my code? Pls advice. Thanks.
The value attribute of an li element is supposed to be a number. Furthermore it is only supported for Ordered Lists (ol).
The values can even be auto-incrementing by setting the first value to e.g. 100 and then the rest will follow.
If I test your code then the function qCat() receives a 0 (zero) parameter which is consistent with the above.
For additional info see here: https://www.w3schools.com/tags/att_li_value.asp
You just need to change the argument passed to your function (thanks to #epascarello for pointing that out). See the code below.
function qCat(val) {
console.log(val.getAttribute('value'));
}
<ul>
<li value="orange" onClick="qCat(this)">Orange</li>
<li value="apple" onClick="qCat(this)">Apple</li>
</ul>
function First(){
alert('it is the first option');
}
function Second(){
alert('it is the second option');
}
function General(){
alert('it is a shared option');
}
<ul>
<li><a href="#" onclick=First();>First option</a></li>
<li><a href="#"onclick=Second();>Second option</a></li>
<li><a href="#"onclick=General();>Third option</a></li>
<li><a href="#"onclick=General();>Forth option</a></li>
</ul>
Please have a look into this updated code.
function qCat(event){
debugger;
console.log($(event.target).attr('value'));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li value="orange" onClick="qCat(event)">Orange</li>
<li value="apple" onClick="qCat(event)">Apple</li>
</ul>
The value attribute sets the value of a list item. The following list items will increment from that number.
The value must be a number and can only be used in ordered lists
In order to get the expected result use data-* (a HTML global attribute)
qCat = function(elm){
val = elm.getAttribute('data-value');
alert(val);
}
<ul>
<li data-value="orange" onClick="qCat(this)">Orange</li>
<li data-value="apple" onClick="qCat(this)">Apple</li>
</ul>
I have three <ul>s that expand when their buttons are clicked. Not all three <ul>s will show up - only when there is a notification to show. I hard-coded the values for now, but I can instantiate them on an as-needed basis.
Right now, they cover each other when they expand. I would like the others to move when a list is expanded so they don't cover each other. I was thinking of getting the index of the one whose button is clicked and then resetting the bottom style of the others. I need to get the index of the <ul> parent of the button that was clicked, probably using jQuery but straight JavaScript is fine as well. Can anyone help?
Here is my code:
<div id="NotificationDiv">
<ul id="noticeLead" class="notification_base notification_Lead"><button id="notification_button">Lead Notice</button>
<div>
<li id="urlLead" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Lead #1</a>
</li>
<li id="urlLead" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Lead #2</a>
</li>
</div>
</ul>
<ul id="noticeTask" class="notification_base notification_Task"><button id="notification_button">Task Notice</button>
<div>
<li id="urlTask" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Task #5</a>
</li>
<li id="urlTask" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Task #6</a>
</li>
<div>
</ul>
<ul id="noticePolicy" class="notification_base notification_Policy"><button id="notification_button">Policy Notice</button>
<div>
<li id="urlPolicy" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Policy #3</a>
</li>
<li id="urlPolicy" class="notification_urlNotice notification_notice">
<a target="_blank" >Check Policy #4</a>
</li>
</div>
</ul>
</div>
And in the $(document).ready, I have:
$('.notification_base').on('click', 'button', function(){
$(this).closest('.notification_base').find('.notification_urlNotice').slideToggle();
});
Try this:
var myParentId; //Here you'll store the id of the clicked element
$('.notification_base').on('click', 'button', function(){
$(this).closest('.notification_base').find('.notification_urlNotice').slideToggle();
myParentId = $(this).attr("id");
});
Thank you everyone for your input. I changed my structure to a table assigning .parent class to the header row and .child class to the data row and put this code in the jQuery ready function and it works great.
function getChildren($row) {
var children = [];
while($row.next().hasClass('child')) {
children.push($row.next());
$row = $row.next();
}
return children;
}
$('.parent').on('click', function() {
var children = getChildren($(this));
$.each(children, function() {
$(this).toggle();
})
});
My DOM is as follows
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
</ul>
</li>
</ul>
My jQuery in a in the bottom of the page is:
$("#Browse").click(function() {
$("#browse-one").html('<div class="ui-widget">Loading...</div>');
$("#browse-one").load('../api/browse.php?do=getFirst');
});
This script goes into the database and spits out raw LIs. After this runs the DOM is modified as follows
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
<li id="one-1" data-id="1">SOMETHING</li>
<li id="one-2" data-id="2">SOMETHING</li>
<li id="one-3" data-id="3">SOMETHING</li>
<li id="one-4" data-id="4">SOMETHING</li>
.
.
.
<li id="one-N" data-id="N">SOMETHING</li>
</ul>
</li>
</ul>
What is the proper jqueryish way to track clicks on these LIs. I want to extract the data-id of the clicked element and make a second API call to construct part two of the tree. For example if data-id="1"'s LI is clicked the DOM should be:
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
<li id="one-1" data-id="1">SOMETHING
<ul id="Something Here">
<li id="two-1" data-id="1">HMM</li>
<li id="two-2" data-id="2">HMM</li>
<li id="two-3" data-id="3">HMM</li>
.
.
.
<li id="two-M" data-id="M">HMM</li>
</ul>
</li>
<li id="one-2" data-id="2">SOMETHING</li>
<li id="one-3" data-id="3">SOMETHING</li>
<li id="one-4" data-id="4">SOMETHING</li>
.
.
.
<li id="one-N" data-id="N">SOMETHING</li>
</ul>
</li>
</ul>
Im having trouble thinking of how i'de keep each of the inner UL's IDs unique. Sure I can do the "LEVEL-ID" as in "two-1" but I feel this is hackish and not the proper jquery way.
EDIT:
But now how do I track the children's clicks?? This doesn't seem valid but I hope you understand wht I'm trying to do
$("#Browse").click(function() {
$("#locations-browse").html('<div class="ui-widget">Loading...</div>');
$("#locations-browse").load('../api/browse.php?do=getFirst');
//Child is tracked
$("#locations-browse").delegate("li","click",function(evt){
var inner = $(this).append("<ul></ul>");
inner.html('<div class="ui-widget">Loading...</div>');
inner.load('../api/browse.php?do=getSecond');
$(this).delegate("li","click", function(evt) {
alert("Child ". $(this).data("id") . " is clicked";
});
});
});
EDIT 2:
Hmm this still is not working:
$("#Browse").click(function() {
$("#locations-browse").html('<div class="ui-widget">Loading...</div>');
$("#locations-browse").load('../api/browse.php?do=getFirst');
//Child is tracked
$("#locations-browse").delegate("li","click",function(evt){
$(this).append("<ul></ul>");
$(this).children("ul").load('../api/browse.php?do=getSecond?location-id='.$(this).data("id"));
$(this).delegate("li","click", function(evt) {
alert($(this).data("id"));
});
});
});
Delegate the event via li#Browse and reference the data-id attribute relative to the event's contextual element.
$('#Browse').on('click', 'li', function(evt) {
alert($(this).data('id'));
});
Incidentally, there's several out-of-the-box plugins that do what you need, just in case you didn't want to build you own, e.g. YUI Treeview or the one I wrote.