getting around stopPropagation() - javascript

Once upon a time, a frond end dev had some menus he wanted to close when somebody clicked outside them anywhere on the page, so he used some ifs and the method mentioned to handle he job. Of course later this came back to bite him in the ass, because the clicks made inside the mentioned menus would not take effect. How do i get around that? Or how could i differently handle this? I am using bootstrap 3 if that is of some help
the HTML
<div class="shopbar pull-right">
<a data-toggle="collapse" href="#nav-shop" class="collapsed"> <i class="fa fa-lg fa-shopping-cart"></i> </a>
<a data-toggle="collapse" href="#search" class="collapsed"> <i class="fa fa-lg fa-search"></i> </a>
</div>
....
<div id="search" class="panel-collapse collapse">
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">Search In <span class="caret down"></span><span class="caret up"></span></button>
<ul class="dropdown-menu">
<li>Blog</li>
<li>Portfolio</li>
<li>Events</li>
<li>Shop</li>
<li>Pages</li>
</ul>
</div><!-- /btn-group -->
<input type="text" class="form-control">
<span class="input-group-btn">
<button class="btn btn-default fa fa-search" type="button"></button>
</span>
</div><!-- /input-group -->
</div>
</div>
</div>
</div>
the Jquery
$('html').click(function () {
$(".shopbar a").addClass("collapsed");
if ($("#nav-shop").hasClass("in")) {
$("#nav-shop").collapse('hide');
}
if ($("#search").hasClass("in")) {
$("#search").collapse('hide');
}
});
$("#nav-shop").click(function (event) {
event.stopPropagation();
return true;
});
$("#search").click(function (event) {
event.stopPropagation();
return true;
});

$('html').click(function (event) {
var target = $(event.target);
if(!target.is("#nav-shop") && !target.is("#search") ) {
$(".shopbar a").addClass("collapsed");
if ($("#nav-shop").hasClass("in")) {
$("#nav-shop").collapse('hide');
}
if ($("#search").hasClass("in")) {
$("#search").collapse('hide');
}
}
});
And no event.stopPropagation needed.

Related

AJAX+Laravel: after I successfully do process in AJAX, other functions are not working

Sorry my english not good :)
I have problem with AJAX success in Laravel, after I successfully do process in AJAX, other functions are not working. Like the picture below, I like status or comment, function of collapse button and favorite button does not work.
In AJAX success I use
$("#divwrap").load(" #divwrap");
div with an id of divwrap I use as a wrapper
Please help :)
Code
<div id="divwrap">
#foreach($singgah as $d)
<div class="box box2">
<div class="box-body box-body-custom">
<div class="post">
<div class="user-block">
<img class="img-circle" src="{{ asset('storage/' . $d->user->avatar ) }}" alt="user image">
<span class="username">
<?php $email = Crypt::encrypt($d->user->email) ?>
{{$d->user->name }}
<div class="btn-group pull-right custom-curret nav-right1">
<button type="button" class="btn btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fa fa-ellipsis-h"></span>
</button>
<ul class="dropdown-menu">
#if(Auth::user()->name ==$d->user->name )
<li><a onclick="editForm('{{$d->id }}')" class="pointer-jempol"> <i class="fa fa-pencil-square-o"></i> Edit Kiriman</a></li>
<li><a onclick="deleteData('{{$d->id }}')" class="pointer-jempol"> <i class="fa fa-times-circle"></i> Hapus Kiriman</a></li>
<li role="separator" class="divider"></li>
#endif
<li><i class="fa fa-exclamation-circle"></i> Laporkan Kiriman</li>
</ul>
</div>
</span>
<span class="description"><i class="fa fa-hashtag" title="Sebagai"></i> {{$d->category}} - <i class="fa fa-clock-o"></i> {{$d->created_at->diffForHumans()}}</span>
</div>
<p>
{{ $d->content }}
</p>
<div class="box box-default box-costum-collapse">
<div class="box-header with-border" style="padding:0px;">
<a class="label label-primary" title="Kota"><i class="fa fa-map-marker"></i> {{$d->lokasi }}</a>
<a class="label label-primary" title="Kontak"><i class="fa fa-phone-square"></i> {{$d->contact }}</a>
<table class="pull-right">
<tr>
<td class="mailbox-star" data-value="{{$d->id}}"><i class="fa fa-star-o text-red"></i> <a id="coba">{{ $d->singgahlike->count() }}</a></td>
<td class="btn-nopadding btn btn-box-tool" data-widget="collapse"> | <i class="fa fa-comment"></i> {{ $d->singgahcomment->count() }}</td>
</tr>
</table>
</div>
<div class="box-body" style="padding:0px;">
<div class="box-komentar">
#include('layouts.form.formComment')
<div id="box-komentar">
#foreach($d->singgahcomment as $c)
<div class="komentar-post">
<div class="user-block">
<img class="img-circle" src="{{ asset('storage/' . $c->user->avatar ) }}" alt="user image">
<span class="username usernamekoment">
{{$c->user->name }}
<div class="btn-group custom-curret nav-right-koment pull-right">
<button type="button" class="btn btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fa fa-ellipsis-h"></span>
</button>
<ul class="dropdown-menu">
#if(Auth::user()->name ==$c->user->name )
<li><a onclick="deleteComment('{{$c->id }}')" class="pointer-jempol"><i class="fa fa-times-circle"></i> Hapus Komentar</a></a></li>
<li role="separator" class="divider"></li>
#endif
<li><i class="fa fa-exclamation-circle"></i> Laporkan komentar</li>
</ul>
</div>
</span>
<span class="description descriptionkoment"><i class="fa fa-clock-o"></i> {{$c->created_at->diffForHumans()}}</span>
</div>
<p>{{ $c->comment }}</p>
</div>
#endforeach
</div>
</div>
</div>
</div>
</div>
</div>
</div>
#endforeach
</div>
and this is one ajax success process:
$(function () {
$(".mailbox-star").click(function (e) {
e.preventDefault();
var singgah_id = $(this).data('value');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{ url('singgah/like') }}",
type: "POST",
data: {singgah_id:singgah_id},
success: function (data) {
$("#divwrap").load(" #divwrap");
$('div.flash-message').html(data);
},
error: function () {
alert('Oops! error!');
}
});
//detect type
var $this = $(this).find("i");
var fa = $this.hasClass("fa");
if (fa) {
$this.toggleClass("fa-star");
$this.toggleClass("fa-star-o");
}
});
});
Below I show a button that works only once before the AJAX success button is working, but after the AJAX success button it becomes not working
It's because after jQuery changes and loads the elements of the DOM again, even if the id and class names are the same but the virtual id of the DOM elements are changed and javascript or jQuery assume this is different than previous ones.
In other words, jQuery attaches to elements on loading of DOM, so after done loading, it can't recognize the new elements. to do that you must get the elements from the document instead.
So your code will look like this:
$(document).on('click', ".mailbox-star", function (e) {
e.preventDefault();
var singgah_id = $(this).data('value');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{ url('singgah/like') }}",
type: "POST",
data: {singgah_id:singgah_id},
success: function (data) {
$("#divwrap").load(" #divwrap");
$('div.flash-message').html(data);
},
error: function () {
alert('Oops! error!');
}
});
//detect type
var $this = $(this).find("i");
var fa = $this.hasClass("fa");
if (fa) {
$this.toggleClass("fa-star");
$this.toggleClass("fa-star-o");
}
});
Notice this line:
$(document).on('click', ".mailbox-star", function (e) {
instead of this:
$(function () {
$(".mailbox-star").click(function (e) {
So if you want to events work after reloading part of DOM you must address the selector from the document. Note that the selecting of element works a little bit slower than the first one.

How to create dropdown menu in AngularJs 2 Javascript?

How to create dropdown menu in AngularJs 2 Javascript?
I have watched alot of tutorials but there is only available for Typescript. i need it in Javascript. Please help.
(function(app) {
app.HeaderComponent = ng.core
.Component({
selector: 'header',
template:
`<nav class="navbar navbar-default">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="" class=" navbar-brand">
<span class="brandname">Slant<sub> AngulatJS</sub></span>
</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="dashboarddiv">
Dashboard
</li>
<li></li>
<li>
<div [hidden]="submitted">
<form (ngSubmit)="onSubmit()" #Header="ngForm">
<button type="submit" [disabled]="!Header.form.valid"><span class="glyphicon glyphicon-envelope"></span></button>
</form>
</div>
<div [hidden]="!submitted">
<button (click)="submitted=false"><span class="glyphicon glyphicon-envelope"></span></button>
<h2>You submitted</h2>
<div class="row">
<div class="col-xs-3">Name</div>
<div class="col-xs-9 pull-left">rrr</div>
</div>
<div class="row">
<div class="col-xs-3">Alter Ego</div>
<div class="col-xs-9 pull-left">r</div>
</div>
<div class="row">
<div class="col-xs-3">Power</div>
<div class="col-xs-9 pull-left">r</div>
</div>
</div>
</li>
</ul>
</div>
</nav>`
})
.Class({
constructor: function() {
this.submitted = false;
},
onSubmit: function() {
this.submitted = true;
},
});
})(window.app || (window.app = {}));
I have tried this. but it creates div hide and show. I want dropdown menu in navigation bar.
This is the result of this code

jQuery find previous button by ID (which will have different names)

Hey all I am trying to get the previous button so that I can change its text to something else once someone selects a value from a select box.
<div class="input-group">
<div class="input-group-btn search-panel">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span id="search_concept">Type</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" id="dd1" role="menu">
<li>For Sale</li>
<li>Wanted</li>
</ul>
</div>
<div class="input-group-btn search-panel">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span id="search_concept">Location</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" id="dd2" role="menu">
<li>Somewhere</li>
<li>Elsewhere</li>
</ul>
</div>
<input type="text" class="form-control" name="x" placeholder="Search term...">
</div>
$('.search-panel #dd1, .search-panel #dd2').find('a').click(function(e) {
e.preventDefault();
var param = $(this).data("info");
$(this).prev().find('#search_concept').text($(this).text());
});
So the click event starts from THIS which is the a href="#" data-info="blah1">[value here]< /a> tag. So I am trying to go back to the < button> tag so that I can change the text Type to whatever was selected.
I've tried:
$(this).prev().find('#search_concept').text($(this).text());
and
$(this).prev().prev().find('#search_concept').text($(this).text());
and
$(this).prev().prev().children().find('#search_concept').text($(this).text());
and
$(this).prev().children().find('#search_concept').text($(this).text());
And I can't seem to find it....
fixed
$('.search-panel #dd1, .search-panel #dd2').find('a').click(function(e) {
e.preventDefault();
var param = $(this).data("info");
$(this).parents('.search-panel').find('button').html($(this).text() + ' <span class="caret"></span>');
});
The following snippet uses jQuery's .parents to locate a button.
$(this).parents(selector) will find any parent elements that have the specified selector.
Then .find(selector) will search that parent element for the specified selector.
Then you can assign that to a variable and use the element.
$('.search-panel #dd1').find('a').click(function(e) {
e.preventDefault();
var param = $(this).data("info");
var text = $(this).text();
// Assign element to variable for later manipulation
var $button = $(this).parents('.search-panel').find('button');
// eg: Replace button text (replaces all content including html)
// $button.text(text)
// eg: Find another element inside $button and replace the text
// $button.find('#search_concept').text(text)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="input-group">
<div class="input-group-btn search-panel">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span id="search_concept">Type</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" id="dd1" role="menu">
<li>For Sale</li>
<li>Wanted</li>
</ul>
</div>
<input type="text" class="form-control" name="x" placeholder="Search term...">
</div>
You simply can't have multiple SAME ids.
$(this).parents().find("button #search_concept").text($(this).text());
You have duplicated ids which can make things messy. I would change concept of relaying on id to some other selectors, e.g classes:
And so such way you can treat search-panel group as a widget, and javascript going to be rewritten as:
$('.search-panel').each(function() {
var search_concept = $(this).find(".search_concept");
$(this).find('a').click(function(e) {
e.preventDefault();
var param = $(this).data("info");
search_concept.text($(this).text());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="input-group">
<div class="input-group-btn search-panel">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="search_concept">Type</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" class="dd" role="menu">
<li>For Sale</li>
<li>Wanted</li>
</ul>
</div>
<div class="input-group-btn search-panel">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="search_concept">Location</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" class="dd" role="menu">
<li>Somewhere</li>
<li>Elsewhere</li>
</ul>
</div>
<input type="text" class="form-control" name="x" placeholder="Search term...">
</div>
This approach will arguably improve portability.

add CSS element using an angular directive

Im using angular and ng-repeat to populate a list of studies. This list is dynamic so you can toggle into child elements of each element. So basically I have a accordion style toggle list that can go three levels deep on each list item. I have a jQuery issue that I think should be solved with some angular directive or something. Basically I have an arrow (glyphicon) that should switch to up or down depending on if your looking at a child or a parent element in this list. I have this working with pure jQuery just adding and removing a css class from each list item. However, it only works on the first item in the list because ng-repeat creates multiple id’s but jQuery will only work on the first element with that id tag.
This is the HTML from the page.
<!-- User Studies List -->
<div ng-controller="StudiesController" id="before">
<h3 class="center"> User Studies </h3>
<div ng-repeat="study in studies" arrow>
<div class="panel-group" style="margin-bottom:0">
<div class="panel panel-default">
<div class="panel-heading" data-toggle="collapse" href="#collapse{{$index}}">
<h3 class="panel-title">{{ study.study }} <span class="glyphicon glyphicon-menu-down pull-right"></span></h3>
<p></p>
</div>
<div id="collapse{{$index}}" class="panel-collapse collapse">
<ul class="list-group">
<li class="list-group-item" data-toggle="collapse" href="#collapse{{study.id}}" style="margin-left:1%" id="sampleID{{$index}}">
<i>Sample: </i>{{ study.sample }}
<span id="glyph-switch" class="glyphicon glyphicon-menu-down pull-right"></span>
<span id="glyph-up" class="glyphicon glyphicon-menu-up pull-right"></span>
</li>
<div id="collapse{{study.id}}" class="panel-collapse collapse">
<ul class="list-group">
<li class="list-group-item" style="margin-left:3%"><i>Fastq: </i>{{ study.fastq }}
<div class="dropdown center pull-right">
<button class="btn-xs btn-default hvr-shadow" id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Action <span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dLabel">
<li id="list-item" data-toggle="modal" data-target="#more-metadata-modal" ng-click="showMore(study)">More Data</li>
<li id="list-item" data-toggle="modal" data-target="#edit-metadata-modal" ng-click="showMore(study)">Edit</li>
<li id="list-item" data-toggle="modal" data-target="#delete-metadata-modal" ng-click="showMore(study)">Delete</li>
</ul>
</div>
</li>
</ul>
</div>
</ul>
</div>
</div>
</div>
</div>
</div>
This is the Javascript
var count = 1;
$(document).on("click", "li[id*='sampleID']", function() {
console.log("clicked");
if(count > 0) {
$('#glyph-switch').css('visibility','hidden');
$('#glyph-up').css('visibility', 'visible');
count -= 1;
console.log("count", count);
} else {
$('#glyph-switch').css('visibility','visible');
$('#glyph-up').css('visibility', 'hidden');
count += 1;
console.log("count",count);
}
});
I would just use angular code (no jQuery at all).
Since you already have an object of studies, just handle an onClick="showGlyph($index)" passing the index and then in the code just set the a state for the up/down arrow $scope.GlyphUp = !$scope.GlyphUp.
In the template file have the up/down arrow object bind ng-show="GlyphUp"

How to toggle Element that is clicked and hide all other using bootstrap?

How to toggle Element that is clicked and hide all other using bootstrap V3.5?
this is my code:
<div id="buttons" style="padding: 50px;">
<a data-toggle="collapse" data-target="#item-01">
<button class="btn btn-default">
Item-01
</button>
</a>
<a data-toggle="collapse" data-target="#item-02">
<button class="btn btn-default">
Item-02
</button>
</a>
</div>
<div id="itens">
<div class="collapse" id="item-01">
<span>Item 01</span>
</div>
<div class="collapse" id="item-02">
<span>Item 02</span>
</div>
</div>
DEMO page.
You should probably put the data-target attribute on the buttons themselves, but your code as is... use the following in jQuery:
$("button").on("click", function(){
var alertMsg = $(this).parent().data("target");
alert(alertMsg); //First grab the data-target from the button's parent, or alternatively the button itself as I would recommend.
//Note, you have a typo which I moved forward with below.
/* var itemToShow = "#" + alertMsg;
alert(itemToShow); */
// I would recommend as well you don't use hashtags in your data-*
// elements. Rather as shown here, add the hashtag in with code.
$("#itens .collapse").hide(); //first hide all of the elements
$(alertMsg).show(); //then show the element related to your button click event data-target id.
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="buttons" style="padding: 50px;">
<a data-toggle="collapse" data-target="#item-01">
<button class="btn btn-default">
Item-01
</button>
</a>
<a data-toggle="collapse" data-target="#item-02">
<button class="btn btn-default">
Item-02
</button>
</a>
</div>
<div id="itens">
<div class="collapse" id="item-01">
<span>Item 01</span>
</div>
<div class="collapse" id="item-02">
<span>Item 02</span>
</div>
</div>

Categories

Resources