I've got an application requiring a series of dropdowns. The functionality requires me to be able to switch between normal dropdown behavior and multi-select behavior.
I have made slight modifications to the ui.boostrap.dropdown from the Angular Directives for Bootstrap (see Dropdown). Everything works well, except for a gray bar after clicking (looks like the :hover css stays active after clicking) when in Multiselect mode.
When I toggle off then back on, the highlight goes away, as if the hover event has somehow completed.
Process:
Open the dropdown
Click Multiselect
Move the mouse and Multiselect stays highlighted, as if the ":focus" tag is not removed.
Visually:
The mouse is over 345 in this image, Multiselect should not be highlighted.
Angular HTML for dropdown:
<div ng-controller="DropdownCompanyController as vm">
<div class="btn-group u-front_dropdown-wide" dropdown is-open="vm.isopen">
<button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle>
{{ vm.selected }} <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" ng-click="vm.checkMultiSelect($event)">
<li ng-repeat="company in vm.companies"
ng-class="{ selected : company.selected }">
{{ company.name }}
</li>
<li class="divider"></li>
<li class="ng-scope" ng-class="{selected : vm.multi.select }">
<a href="#"
ng-click="vm.event.multiselect()"
ng-class="{ multi: vm.multi.select }">Multiselect</a>
<button
ng-hide="!vm.multi.select"
ng-class="{ multi_button: vm.multi.select }"
ng-click="vm.event.close_dropdown($event)">Close</button>
</li>
</ul>
</div>
</div>
Here's the event where the click on an element is handled:
vm.event = {};
vm.event.select = function(company) {
if (!vm.multi.select) {
clearCompanies(false);
company.selected = true;
vm.selected = company.name;
vm.isopen = false;
} else {
if (company.name !== vm.defaultCompany) {
company.selected = !company.selected;
vm.selected = vm.multi.title + countCompanies();
}
}
};
Link to Plunker.
I have had no luck tracking this down and my instinct is that the issue is in the CSS, but it's standard bootstrap CSS. Any assistance would be appreciated.
If you just dont want any item to have the highlight then in your own custom app.css file override the focus state with white:
.dropdown-menu > li > a:focus {
background-color: white;
}
Without doing a custom bootstrap build just add the hover following the focus to to keep the grey highlight:
.dropdown-menu > li > a:hover {
background-color: lightgray;
}
I have 2 scope variables like the following:
$scope.degrees =[{DegreeCategoryID:"1",DegreeCategory:"Accounting",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"2",DegreeCategory:"Advanced Manufacturing/Mechatronics Technology",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"3",DegreeCategory:"Air Conditioning and Refrigeration Technology",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"4",DegreeCategory:"Auto Body Technology",DegreeCategoryType:"Applied Sciences"},
{DegreeCategoryID:"78",DegreeCategory:"Associate in Sciences",DegreeCategoryType:"Academic"},
{DegreeCategoryID:"79",DegreeCategory:"Associate of Arts in Teaching",DegreeCategoryType:"Academic"},
{DegreeCategoryID:"80",DegreeCategory:"Emphasis",DegreeCategoryType:"Academic"},
{DegreeCategoryID:"81",DegreeCategory:"Field of Study",DegreeCategoryType:"Academic"}];
$scope.degreecategories=[{DegreeID:"1",DegreeCategoryID:"1",Degree:"Accounting AAS ",DegreeTypeID:"2",BHC:"1",CVC:"1",EFC:"1",ECC:"1",MVC:"1",NLC:"1",RLC:"1",Description:""},
{DegreeID:"2",DegreeCategoryID:"1",Degree:"Accounting Assistant Certificate ",DegreeTypeID:"1",BHC:"1",CVC:"1",EFC:"1",ECC:"1",MVC:"1",NLC:"1",RLC:"1",Description:""},
{DegreeID:"3",DegreeCategoryID:"1",Degree:"Accounting Clerk Certificate ",DegreeTypeID:"1",BHC:"1",CVC:"1",EFC:"1",ECC:"1",MVC:"1",NLC:"1",RLC:"1",Description:""},
{DegreeID:"4",DegreeCategoryID:"1",Degree:"Advanced Technical Certificate in Professional Accountancy",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"",ECC:"",MVC:"1",NLC:"",RLC:"",Description:""},
{DegreeID:"5",DegreeCategoryID:"2",Degree:"Advanced Manufacturing/Mechatronics Technology AAS ",DegreeTypeID:"2",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"6",DegreeCategoryID:"2",Degree:"Advanced Manufacturing/Mechatronics Technology Certificate ",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"1",NLC:"",RLC:"",Description:""},
{DegreeID:"7",DegreeCategoryID:"3",Degree:"Air Conditioning and Refrigeration Technology AAS ",DegreeTypeID:"2",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"8",DegreeCategoryID:"3",Degree:"Profit Center Manager Enhanced Skills Certificate ",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"9",DegreeCategoryID:"3",Degree:"Residential - Technician I Certificate ",DegreeTypeID:"1",BHC:"",CVC:"1",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"10",DegreeCategoryID:"3",Degree:"Residential - Technician III Level II Certificate ",DegreeTypeID:"1",BHC:"",CVC:"1",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"11",DegreeCategoryID:"3",Degree:"Residential AAS ",DegreeTypeID:"2",BHC:"",CVC:"1",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""},
{DegreeID:"12",DegreeCategoryID:"4",Degree:"Auto Body Metal Technician Certificate ",DegreeTypeID:"1",BHC:"",CVC:"",EFC:"1",ECC:"",MVC:"",NLC:"",RLC:"",Description:""}];
Both my above variables are present in the same controller. I am trying to display data in such a way that, when i click a button named 'Academic', it displays all the DegreeCategoryType:"Academic" variables from $scope.degrees using a filter.(until here it works fine)
Now i wanted to display another list following the previous list based on the selection i make from within the list ie. when i click one selection from the above made list, i wanted to to display the details from my $scope.degreecategories such that the it matches and filters based on the DegreeCategoryID. How do i approach this issue? i already posted this question but the message i tried to convey was not proper.
MARKUP Masterlist
<div ng-show="display.academic" class="col-lg-4 col-md-4 col-sm-4">
<div class="panel panel-info list-group list-unstyled" data-spy="scroll" data-target="#panelcategory" data-offset="0" style="max-height:300px;overflow:auto;position:relative;">
<div class="panel-heading">
<h3 class="panel-title">Academic</h3>
</div>
<a href='#' ng-repeat="degree in degrees | filter:{DegreeCategoryType:'Academic'}" class="list-group-item">
<li ng-click="showAcademic(degree)" >{{degree.DegreeCategory}}</li>
</a>
</div>
</div>
Markup sublist
<div ng-show="display.academiccourse" class="col-lg-9 col-md-9 col-sm-9">
<div class="panel panel-info list-group list-unstyled" data-spy="scroll" data-target="#panelcategory" data-offset="0" style="max-height:300px;overflow:auto;position:relative;">
<div class="panel-heading">
<h3 class="panel-title">{{DegreeCategory}}</h3>
</div>
<a href='#' ng-repeat="degree in degreecategories | filter:{DegreeCategoryID:filterSub}" class="list-group-item">
<li ng-click="display.appliedsciencescourse" >{{degree.Degree}}</li>
</a>
</div>
</div>
JS
$scope.showAcademic = function(degree){
$scope.DegreeCategory = degree.DegreeCategory;
$scope.filterSub = degree.DegreeCategoryID;
$scope.display.academiccourse = true;
};
<a href='#' ng-repeat="degree in degrees | filter:{DegreeCategoryType:'Applied Sciences'}" class="list-group-item">
<li ng-click="display.appliedsciencescourse" >{{degree.DegreeCategory}}</li>
</a>
I cant see that your ng-click actually does anything. If your ng-click calls a function, applying the element clicked on as a parameter, then you can set $scope.selectedCategory = yourcategory, on your second list, you can filter by selectedCategory, that will exist in the scope.
I have a listing of articles here, and I can't figure out how to execute the ng-click function calls on every new article inside the ng-repeat. Right now it works for existing articles, but when new articles are added dynamically (via AJAX), I need those to have the same functionality too.
For example: the ng-click function calls on the "+" sign to reveal social buttons seem to not work once new articles are inserted via AJAX (ie: delete articles, and let list be populated again with new elements)
Does AngularJS provide any tools to do that?
<div>
<div>
<input type="text" ng-model="search">
<span>{{filtered.length}} article(s)</span>
</div>
<div article-listing ng-repeat="article in filtered = (wikiArticles | filter:search)">
<!--Individual article begin-->
<span>
{{article.title}}
</span>
<div>
<a ng-click="articles.removeArticle($index)" title="Delete">
<span>✖</span>
</a>
<a ng-click="articles.toggleShare(article)">
<span class="plus-sign" title="Share">✖</span>
<div social-share ng-show="article.socialShare">
<div ng-click="socialShare = !socialShare" class="addthis_toolbox addthis_default_style addthis_32x32_style"
addthis:title="{{article.title}}" addthis:description="{{article.extract}}" addthis:url="{{article.url}}">
<a class="addthis_button_facebook"></a>
<a class="addthis_button_twitter"></a>
<a class="addthis_button_google_plusone_share"></a>
<a class="addthis_button_reddit"></a>
<a class="addthis_button_hackernews"></a>
</div>
</div>
</a>
</div>
<div>{{article.extract}}</div>
<!--Individual article end-->
</div>
</div>
Code for ng-click calls that don't seem to work for new article insertions
$scope.articles = (function() {
return {
shuffleArticles : function() {
$scope.wikiArticles.reverse();
},
removeArticle : function(index) {
$scope.wikiArticles.splice(index, 1);
$scope.fireAPICalls();
},
toggleShare : function(currArticle) {
var previousState = currArticle.socialShare;
angular.forEach($scope.wikiArticles, function(article) {
article.socialShare = false;
});
currArticle.socialShare = previousState ? false : true;
}
}
})();
Your ng-click calls are actually working- you can watch the ng-show toggle in the debugger.
The problem is that there is nothing to display on the new items you add.
The articles you initially add all have their icons populated with the .addthis classes, for instance here's your Facebook icon element:
<a class="addthis_button_facebook at300b" title="Facebook" href="#">
<span class=" at300bs at15nc at15t_facebook">
<span class="at_a11y">Share on facebook</span>
</span>
</a>
at300bs includes the following css which displays the image:
background: url(widget058_32x32.gif) no-repeat left!important;
However as you add new items, you aren't including the needed .addthis classes to them. Their elements look like this:
<a class="addthis_button_facebook"></a>
So ng-show has nothing to display (it shows a 0x0 div).
Add the .addthis classes to your new elements as you add them and you'll be all set.
OK, what I need may sounds rather complex, but here it is...
Let's say we have the HTML code below (it's still just an example, but it's still quite accurate) :
<div data-role="content" comp-id="jqm-content-6207" id="jqm-content-6207" class="" data-theme="" >
<!-- New Navigation Bar #1 -->
<div data-role="navbar" data-position="fixed" comp-id="jqm-navbar-4603" id="jqm-navbar-4603" class="" data-iconpos="top" >
<ul>
<!-- New Navigation Bar Item #1 -->
<li>
<a href="#" comp-id="jqm-navbar-item-6671" id="jqm-navbar-item-6671" class="" data-icon="home" data-theme="" >
One
</a>
</li>
<!-- / New Navigation Bar Item #1 -->
<!-- New Navigation Bar Item #2 -->
<li>
<a href="#" comp-id="jqm-navbar-item-4404" id="jqm-navbar-item-4404" class="" data-icon="gear" data-theme="" >
Two
</a>
</li>
<!-- / New Navigation Bar Item #2 -->
</ul>
</div>
<!-- / New Navigation Bar #1 -->
<!-- New Navigation Bar #2 -->
<div data-role="navbar" data-position="fixed" comp-id="jqm-navbar-4658" id="jqm-navbar-4658" class="" data-iconpos="top" >
<ul>
<!-- New Navigation Bar Item #2.1 -->
<li>
<a href="#" comp-id="jqm-navbar-item-5321" id="jqm-navbar-item-5321" class="" data-icon="home" data-theme="" >
One
</a>
</li>
<!-- / New Navigation Bar Item #2.1 -->
<!-- New Navigation Bar Item #2.2 -->
<li>
<a href="#" comp-id="jqm-navbar-item-2843" id="jqm-navbar-item-2843" class="" data-icon="gear" data-theme="" >
Two
</a>
</li>
<!-- / New Navigation Bar Item #2.2 -->
</ul>
</div>
</div>
First-off, the core idea is : when the user clicks an item with the comp-id attribute set, then add class msp-selected just to this specific element (and remove it from all other elements).
This is how I'm handling this specific part :
function removeAll()
{
$("*").each(function() {
if ($(this)!==undefined) {
$(this).removeClass("msp-selected");
}
});
}
$(document).ready( function() {
$('[comp-id]').bind('click', function(event) {
removeAll();
$(event.target).addClass('msp-selected');
});
});
So, as you may already have guessed it's like a way of "selecting" item (by clicking on them) from the HTML document.
Now, here's the catch :
How could I make it so that the "selection" is progressive?
What I mean...
When the user first clicks on the Navigation Bar :
Check if the first div with comp-id is selected (has the class msp-selected). If not, select it.
If the first div is already selected, then go one level deeper looking for comp-id, and select that one.
So, any ideas?
How would you do it?
P.S. When one clicks on the <a> of a navigation item, what specific item receives the event?
Is it the <div data-role=\"navbar\"> or the navigation bar item? No matter what, from all these items, I want to select the outermost - not being currently selected. Next time, when the user clicks again and e.g. the navigation bar is selected, then unselect it and select it's child (go deeper).
EDIT :
When trying :
$(document).ready( function() {
$('[comp-id]:not(.msp-selected)').on('click', function(e) {
removeAll();
$(this).addClass('msp-selected');
});
});
What I'm getting when clicking on navbar-item is :
Selected Div : jqm-navbar-item-8421
Selected Div : jqm-navbar-8598
Selected Div : jqm-content-2860
Selected Div : jqm-page-3363
So, basically it just "selects" the outermost container. Which is wrong... Next time the user clicks, the content should selected - then the navbar and then the navbar-item....
You may write a function like that (i am not sure if the syntax is correct)
function onclick(sender)
{
if(type of sender == null )
{
return;
}
if(sender.className=="selected")
{
onclick(sender.childElement[0]);
// OR If you need all children to be selected,
// for( var i =0; i<sender.childElement.count; i++)
// onclick(sender.childElement[i]);
}
else
{
sender.className="selected";
}
}