click function does not working with ng-if - javascript

If i use like following,I got what i need.. Here is the code.
<style>
.moreMenu {
position: absolute;
right: 0px;
z-index: 10;
padding: 10px;
color: #666;
border-radius: 0 0 0 4px;
background: #FFF;
display: none;
border-top: 1px solid #DDD;
}
</style>
<i class="fa fa-ellipsis-v tbButton otherOptions rightSide" aria-hidden="true"></i>
<div class="moreMenu">
heloo
</div>
<script>
$(".otherOptions").click(function () {
$(".moreMenu").slideToggle("fast");
});
</script>
But if i use ng-if condition,
<i class="fa fa-ellipsis-v tbButton otherOptions rightSide" aria-hidden="true" ng-if="member==''"></i>
click function is not working.

I solved the issue..
<i class="fa fa-ellipsis-v tbButton otherOptions rightSide" aria-hidden="true" ng-if=members==''" ng-click="mymore()"></i>
// controller
$scope.mymore = function(){
$(".moreMenu").slideToggle("fast");
}
Thanks all for the informations...

It would be better to use ng-click but if you need to use jQuery's click event, you can add a filtered click event to the body:
$('body').on('click', '.otherOptions', function() {
$('.moreMenu').slideToggle('fast');
});
this will add an event handler on the body but will only trigger if the event bubbles up from the otherOptions element. This is an approach to handling dynamic content with jQuery events

#athi is your answer is a proper answer. But as per the question I have answered here use ng-show instead of ng-if.
angular.module("a",[]).controller("ac",function($scope){
});
.otherOptions
{
color: #666;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="a" ng-controller="ac">
<input class="otherOptions" type="button" value="hello" ng-click="mymore()" ng-show=true>
<div class="moreMenu">
heloodfg
</div>
</div>
<script>
$(".otherOptions").click(function () {
$(".moreMenu").slideToggle("fast");
});
</script>

Related

How to Update getElementsByClassName after doing something?

if (document.querySelector(".delete-filter") !== null) {
let dltbtn = document.getElementsByClassName("delete-filter");
let contbtn = document.getElementsByClassName("filter-solid");
for (let i = 0; i < dltbtn.length; i++) {
dltbtn[i].onclick = function() {
contbtn[i].remove();
}
}
}
.filter-solid {
display: inline-block;
border: 1px solid #faa938;
border-radius: 2vw;
font-size: 13px;
padding: 5px 8px;
color: #525666;
margin: 4px 0;
}
.filter-solid button {
border: none;
background: none;
color: #525666;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha512-SfTiTlX6kk+qitfevl/7LibUOeJWlt9rbyDn92a1DqWOw9vWG2MFoays0sgObmWazO5BQPiFucnnEAjpAB+/Sw==" crossorigin="anonymous" referrerpolicy="no-referrer">
<div>
<span class="filter-solid"><span> فقط کالاهای تخفیف دار </span> <button class="delete-filter"><i class="fa fa-times"></i></button></span>
<span class="filter-solid"><span> از <span>200,000</span> تا <span>1,200,000</span> تومان </span> <button class="delete-filter"><i class="fa fa-times"></i></button></span>
<span class="filter-solid"><span> رنگ آبی </span> <button class="delete-filter"><i class="fa fa-times"></i></button></span>
</div>
In above code I want to remove an element after click, but the problem is when I delete elements (from left) the count of dltbtn and contbtn is not updating. I mean when I have 4 elements there is [0, 1, 2, 3] array, so when I delete first element the array should be [0, 1, 2] in order, but it will not be updated. how should I fix this?
If you use .addEventListener() instead of .onclick, and DOM traversal to find the container of the clicked button, you don't need dltbtn, contbtn or an index.
this in the event handler assigned with .addEventListener() is the clicked element -> the button.
With .closest(".filter-solid") we travel the DOM up to the first element that matches the selector ".filter-solid" (in this case .parentNode) would do the same -> the container that should be removed.
document.querySelectorAll(".delete-filter")
.forEach(function(btn) {
btn.addEventListener("click", function() {
const container = this.closest(".filter-solid");
if (container) {
container.remove();
}
});
})
.filter-solid {
display: inline-block;
border: 1px solid #faa938;
padding: 5px 8px;
margin: 4px 0;
}
<div>
<span class="filter-solid"><span> فقط کالاهای تخفیف دار </span> <button class="delete-filter"><i class="fa fa-times">X</i></button></span>
<span class="filter-solid"><span> از <span>200,000</span> تا <span>1,200,000</span> تومان </span> <button class="delete-filter"><i class="fa fa-times">X</i></button></span>
<span class="filter-solid"><span> رنگ آبی </span> <button class="delete-filter"><i class="fa fa-times">X</i></button></span>
</div>
The main issue is that getElementsByClassName() returns a live collection. To quote the MDN page:
Warning: This is a live HTMLCollection. Changes in the DOM will reflect in the array as the changes occur. If an element selected by this array no longer qualifies for the selector, it will automatically be removed. Be aware of this for iteration purposes.
Meaning that contbtn[i].remove() will implicitly remove the current element from the array (because it is removed from the DOM), shifting all elements that come after it.
An easy change would be swapping from getElementsByClassName() to querySelectorAll() which does not not return a live collection.
let dltbtn = document.querySelectorAll(".delete-filter");
let contbtn = document.querySelectorAll(".filter-solid");
With this change elements in the resulting collection won't shift when contbtn[i].remove() is called.
Another good solution in this scenario would be to use event delegation. This means adding an event listener to the wrapping <div> which checks if the .delete-filter is clicked and removes the associated .filter-solid.
This also simplifies adding new elements, since you no longer need to add event listeners on those new elements.
const containers = document.querySelectorAll(".filter-solid-container");
for (const container of containers) {
container.addEventListener("click", function ({ target }) {
// only search within the container by addeding the container selector
const dlt = target.closest(".filter-solid-container, .delete-filter");
// return if not clicked on .delete-filter
// (`dlt` will be set to the container)
if (dlt == container) return;
// I assume that .filter-solid is always present around a .delete-filter
// find and remove it
dlt.closest(".filter-solid").remove();
});
}
// demo: adding a new filter without fumbling with event handlers
const addFilter = document.querySelector("#add-filter");
addFilter.addEventListener("click", function () {
containers[0].innerHTML += `
<span class="filter-solid">
<span>test</span>
<button class="delete-filter"><i class="fa fa-times"></i></button>
</span>
`;
});
.filter-solid {
display: inline-block;
border: 1px solid #faa938;
border-radius: 2vw;
font-size: 13px;
padding: 5px 8px;
color: #525666;
margin: 4px 0;
}
.filter-solid button {
border: none;
background: none;
color: #525666;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha512-SfTiTlX6kk+qitfevl/7LibUOeJWlt9rbyDn92a1DqWOw9vWG2MFoays0sgObmWazO5BQPiFucnnEAjpAB+/Sw==" crossorigin="anonymous" referrerpolicy="no-referrer">
<div class="filter-solid-container">
<span class="filter-solid"><span> فقط کالاهای تخفیف دار </span> <button class="delete-filter"><i class="fa fa-times"></i></button></span>
<span class="filter-solid"><span> از <span>200,000</span> تا <span>1,200,000</span> تومان </span> <button class="delete-filter"><i class="fa fa-times"></i></button></span>
<span class="filter-solid"><span> رنگ آبی </span> <button class="delete-filter"><i class="fa fa-times"></i></button></span>
</div>
<button id="add-filter" type="button">add filter</button>

Toggle <span> text which contains inner HTML element

On the button click, I want to toggle its text from 'View More' to 'View Less'. However, the span element contains another element inside of it (Font Awesome icon). When I toggle text of a span element, the element inside of it disappears. You can see it in the snippet below.
I also tried this solution:
$('.button span').text(($('.button span').text()=='View More<i class="fas fa-angle-down"></i>') ? 'View Less<i class="fas fa-angle-up"></i>' : 'View More<i class="fas fa-angle-down"></i>');
But it inserts the i element as a span text, instead as an element.
NOTE: I can't keep the i element outside of the span element because I have certain animations in CSS.
$('.button').click(function() {
$('.button i').toggleClass('fa-angle-up fa-angle-down');
$('.button span').text(($('.button span').text()=='View More') ? 'View Less' : 'View More');
});
.button {
width: 250px;
padding: 12px 0;
text-transform: uppercase;
cursor: pointer;
}
.button i {
margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>
<button type="button" name="button" value="" class="button">
<span>View More<i class="fas fa-angle-down"></i></span>
</button>
$('.button').click(function() {
$('.button span').html(($('.button span').text()=='View More') ? 'View Less<i class="fas fa-angle-up">' : 'View More<i class="fas fa-angle-down">');
});
.button {
width: 250px;
padding: 12px 0;
text-transform: uppercase;
cursor: pointer;
}
.button i {
margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>
<button type="button" name="button" value="" class="button">
<span>View More<i class="fas fa-angle-down"></i></span>
</button>
This can be fixed using the html() function of JQuery. That will have the same functionality as the text() function, but adds the option to set html elements.
This link provides you with the JQuery documentation.
what about to wrap the text which you want to change into an own span with an id? then you could change the text without touching the fontawesome icon
I would simply add a data attribute to the texts and toggle only that portion instead of trying to complicate things, like this:
$('.button').click(function() {
$('.button i').toggleClass('fa-angle-up fa-angle-down');
const currentText = $('[data-view-more]').text();
const updatedText = currentText === 'View More' ? 'View Less' : 'View More';
$('[data-view-more]').text(updatedText);
});
.button {
width: 250px;
padding: 12px 0;
text-transform: uppercase;
cursor: pointer;
}
.button i {
margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>
<button type="button" name="button" value="" class="button">
<span>
<span data-view-more>View More</span>
<i class="fas fa-angle-down"></i>
</span>
</button>
As you can see I now target data-view-more text when toggling the text and then I target the icon to toggle that.
Just for fun and for the idea: no jquery, use event delegation and a data-attribute to toggle text and icon
document.addEventListener("click", handle);
function handle(evt) {
const bttn = evt.target.closest("[data-view]");
return bttn
? toggleBttn(bttn, bttn.dataset.view === "more")
: true;
}
function toggleBttn(bttn, isClosed) {
let classes = ["fa-angle-down", "fa-angle-up"];
classes = isClosed ? classes : classes.reverse();
bttn.querySelector("i").classList.replace(...classes);
bttn.dataset.view = isClosed ? "less" : "more";
}
.button {
width: 250px;
padding: 12px 0;
text-transform: uppercase;
cursor: pointer;
}
[data-view]:before {
content: 'view 'attr(data-view);
margin-right: 10px;
}
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>
<button type="button" data-view="more" class="button">
<i class="fas fa-angle-down"></i>
</button>
When you keep the icon out of the span, it works like you expect it:
<button type="button" name="button" value="" class="button">
<span>View More></span>
<i class="fas fa-angle-down"></i
</button>

mouse up callback not working after dragsort

I am trying to update the inputbox's value after picture dragged.
Below is the fiddle and code.
I need to manual click picture after dragsort to update $('#pic').val() How can I skip the manual click? or is it a way to auto click "li" ?
I have tried ul.children('li').first().click() but it's not working either.
fiddle
html
<div class="mediaset" data-param="{filter: 'image', batch: 1}">
<input type="hidden" name="media" data-param="{type: 'media'}">
<div class="topside">
<button type="button" class="btn icon-image green label" onclick="getElementById('inputfile_pic').click();">UPLOAD</button>
<input type="file" class="imagesUpload" data-value="pic" multiple="" id="inputfile_pic" style="height:0;width:0;z-index: -1; position: absolute;left: 10px;top: 5px;">
<input type="hidden" name="pic" id="pic" value="book.png,a1.png,1804161714530.jpg,">
</div>
<ul class="items sortablelist" id="v_pic" data-listidx="0">
<li id="book" style="border: 1px solid rgb(219, 224, 226); width: 150px; text-align: center; list-style-type: none; cursor: pointer;" data-itemidx="0">
<h5>book.png</h5>
<img src="../timthumb.php?src=e30001/data2/pic/book.png&h=120&w=120" title="book.png" alt="book.png" id="book_img" onclick="openBigPic('/e30001/data2/pic/book.png')">
<div style="text-align:center;">
<i class="fa fa-times"></i>
<i class="fa fa-search-plus"></i>
</div>
</li>
<li id="a1" style="border: 1px solid rgb(219, 224, 226); width: 150px; text-align: center; list-style-type: none; cursor: pointer;" data-itemidx="1">
<h5>a1.png</h5>
<img src="../timthumb.php?src=e30001/data2/pic/a1.png&h=120&w=120" title="a1.png" alt="a1.png" id="a1_img" onclick="openBigPic('/e30001/data2/pic/a1.png')" style="cursor: move;">
<div style="text-align:center;">
<i class="fa fa-times"></i>
<i class="fa fa-search-plus"></i>
</div>
</li>
<li id="1804161714530" style="border: 1px solid rgb(219, 224, 226); width: 150px; text-align: center; list-style-type: none; cursor: pointer;" data-itemidx="2">
<h5>1804161714530.jpg</h5>
<img src="../timthumb.php?src=e30001/data2/pic/1804161714530.jpg&h=120&w=120" title="1804161714530.jpg" alt="1804161714530.jpg" id="1804161714530_img" onclick="openBigPic('/e30001/data2/pic/1804161714530.jpg')">
<div style="text-align:center;">
<i class="fa fa-times"></i>
<i class="fa fa-search-plus"></i>
</div>
</li>
</ul>
</div>
js
$(document).ready(function(){
$('.sortablelist').dragsort({
dragSelectorExclude: 'input, textarea, a[href] , i , em',
dragBetween: true,
placeHolderTemplate: '<li style="font-size:18px;"><div style="padding-top:50px;">moving...</div></li>'
});
$('.sortablelist li').mouseup(function(){
ul = $(this).parent();
switched_input_value = '';
ul.find('li').each(function(){
picValue = $(this).children('h5').html();
if(!!picValue) {
switched_input_value += picValue+',';
}
}).promise().done(function(){
//ul.children('li').first().click();//not working either
input_id = ul.attr('id').replace('v_','');
$('#'+input_id).val(switched_input_value);
console.log(switched_input_value);
});
});
});
May be something you are looking for. You no need to trigger click and no need to bind click event to $('.sortablelist li'), just use dragEnd event
$('.sortablelist').dragsort({
dragSelectorExclude: 'input, textarea, a[href] , i , em',
dragBetween: true,
placeHolderTemplate: '<li style="font-size:18px;"><div style="padding-top:50px;">moving...</div></li>',
dragEnd: function() {
getData();
}
});
function getData() {
var listName = [];
$('.sortablelist').find('li').each(function() {
console.log($(this).find('h5').html());
listName.push($(this).find('h5').html());
});
$('#pic').val(listName.join(','));
}
See the fiddle https://jsfiddle.net/3a5q4mhy/50/

Unable to make button show or hide depending on whether another element has content

So this is probably a simple question. But I have to ask because it's not doing what I want.
Here is the button JavaScript:
$(document).ready(function(){
if ($(".saved-items").html().length > 0) {
$('.btn-01').show();
}
});
The button is shown if there is content in the div. But I would like it to hide again if the div has no content.
I tried:
$(document).ready(function(){
if ($(".saved-items").html().length > 0) {
$('.btn-01').show();
}
if ($(".saved-items").html().length < 0) {
$('.btn-01').hide();
}
});
Here is the HTML when an item is added:
<div class="col-sm-2">
<div class="saved-items"><h4>Items:</h4>
<ul>
<li><i class="fa fa-anchor" aria-hidden="true" style="color:#f60;margin-right:10px;"></i>RAW</li>
</ul>
<script>
$(document).ready(function(){
$('.btn-01').toggle($(".saved-items").html().trim().length > 0);
});
</script>
</div>
</div>
<div class="col-sm-2">
<a class="fancybox my-subject" href="#contact-formulier" value="Item X"><div style="display: block;" class="btn-01">Check Out</div></a>
</div>
</div>
And this is the HTML without any items saved:
<div class="col-sm-2">
<div class="saved-items">
<h4>Items:</h4>
</div>
</div>
<div class="col-sm-2">
<a class="fancybox my-subject" href="#contact-formulier" value="Item X"><div class="btn-01">Check Out</div></a>
</div>
But no go. Here is the CSS of btn-01:
.btn-01 {
background: #f60;
color: #fff;
border-radius: 2px !important;
padding: 5px;
text-align: center;
margin: 40px auto 0px auto;
width: 90%;
display: none;
border:none;
}
You can use toggle() to achieve this:
$('.btn-01').toggle($(".saved-items").html().trim().length > 0);
Working example
length of string is zero or greater than zero..can't be less than zero.
$(document).ready(function(){
if ($(".saved-items").html().length > 0) {
$('.btn-01').show();
}else{
$('.btn-01').hide();
}
});
please check https://jsfiddle.net/Shilpi/uhfruo1a/2/

Bootstrap Jquery/Ajax Inline Edit when clicking Edit button

Can some one suggest me an inline edit were when I click on the edit button my label content should be replaced with an input text and I would be able to update it in my mysql db.
My code:
<label style="display:block;">mylabel</label>
<input type="text" style="display:none;">myinput</input>
<button>edit</button>
Any help would be appreciated Thanks!!
I would probably just use contentEditable, if possible.
document.addEventListener('DOMContentLoaded', function(){
var btn = document.getElementById("editButton");
btn.addEventListener("click", function(){
var editLabel = document.getElementById("editLabel");
editLabel.contentEditable = true;
editLabel.className = "editActive";
});
});
#editLabel{
margin-bottom: 25px;
display: inline-block;
padding: 5px;
box-sizing: border-box;
}
#editButton{
display: block;
}
.editActive{
border: 1px inset #e3e3e3;
cursor: text;
}
<label id="editLabel">Hello World</label>
<button id="editButton">Edit Label</button>
I wouldn't recommend doing it inline. As you can see the result will not be clean. This will work though.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<label style="display:block;">mylabel</label>
<input type="text" style="display:none;" value="myInput">
<button onclick="$('label').text($('input').val())">edit</button>

Categories