I've got a notifications button in a rails app that lists friends' recent activity. It has a count badge that appears over the button. Once a user views those notifications I want to clear the current badge so the count can restart with new notifications. Any suggestions?
var renderActivities = function() {
var source = $('#activities-template').html();
var template = Handlebars.compile(source);
var html = template({
activities: window.loadedActivities,
count: window.loadedActivities.length
});
I was trying something like this:
$('#notifications-button').click(function(event) {
count: = 0;
});
Source code (outside of body):
<script id="activities-template" type="text/x-handlebars-template">
<button class="btn btn-default" class="dropdown-toggle notifications-button" data-toggle="dropdown"><i class="fa fa-bell-o fa-2x"><span class="badge notifications-count">{{count}}</span></i></button>
<ul class="dropdown-menu pull-right notifications-menu">
{{#each activities}}
{{activityLink}}
{{/each}}
<li class="divider"></li>
<li>See All</li>
</ul>
</script>
I'm really not all that familiar with Javascript but really need this feature to work.
You're going to want to grab the selector that contains the count and set the text to 0. Something like so...
$('#notifications-button').on('click', function() {
$('.notifications-count').text('0');
});
Related
Is it possible to return something to a function from appended HTML?
In my case, something that determines what button was pressed in that HTML.
Scenario
I am making a file menu system for web storage. You have other storage, bitmapr web storage, and then local disk. I want to be able to create a file selection system using jQuery. (e.g: I click select on bitmapr web storage, and then the function that called that returns that I clicked bitmapr web storage. (or an rational value that means that.)
Problem
I'm not sure how to tackle this scenario. I've tried using onclick returns, that doesn't work, and jquery append doesn't return what happens on onclick.
Is there a way to solve the scenario posted above?
Program code
Modal display function
var advancedModal = function(html, title, msg, color) {
$("body").append(`
<div class="w3-modal-content w3-animate-opacity w3-display-middle modal">
<header class="w3-container w3-${color}">
<span onclick="$(this).parent().parent().remove()" class="w3-button w3-display-topright">×</span>
<h2>${title}</h2>
<small>${msg}</small>
</header>
${html}
<footer class="w3-container w3-${color}">
<p>bitmapr</p>
</footer>
</div>
</div>`);
return (something determining what button was pressed)
};
advancedModal call
advancedModal(`
<div class="w3-container w3-animate-opacity">
<ul class="w3-ul">
<li class="w3-light-grey w3-animate-opacity" onclick="$('ul', this).toggle();">
<i class="fa fa-question"> </i><i class="fa fa-chevron-right"></i> Web Storage
<button class="w3-button w3-red" onclick="resetStorage()">Delete All</button>
<ul class="w3-ul">
${otherStorageHTML}
</ul>
</li>
<li class="w3-blue blueGradient w3-animate-opacity" onclick="$('ul', this).toggle();">
<i class="fa fa-images"> </i><i class="fa fa-chevron-right"></i> <b>bitmapr</b> Web Storage
<button class="w3-button w3-teal" onclick="return 'clicked me'">Select</button>
<ul class="w3-ul">
${bitmaprHTML}
</ul>
</li>
<li class="w3-blue w3-deep-purple w3-animate-opacity" onclick="$('ul', this).toggle();">
<i class="fa fa-archive"> </i><i class="fa fa-chevron-right"></i> Local Disk Storage
<button class="w3-button w3-teal" onclick="">Select</button>
<ul class="w3-ul">
Not Available Now
</ul>
</li>
</ul>
</div>
`, "Open", spaceLeft + "MB remaining in virtual storage", "blue"));
Notice: All of the ${} variables are defined correctly.
Text diagram
var value = advancedModal(...)
advancedModal(html, title, etc...) {
prints out html, but on click of a button, return a value corresponding to the button
}
Visual diagram
Extra thing
Before flagging/closing, please post in comments what your questions are or what you want cleared up. I tried hard to explain it all here but there may be something I am missing. Thanks.
Instead of returning a value, you can pass a callback. This can be a new parameter.
var advancedModal = function(html, title, msg, color,callback) {};
Now you can use a delegated method to call on when a button is clicked.
var advancedModal = function(html, title, msg, color,callback) {
... appending ...
$('.w3-container').on("click","button",callback);
};
This will call the callback function on any button that is clicked. Here is an example:
advancedModal(html, title, msg, color,function(){
console.log(this); // <-- this is the button
});
It will be a good idea to give the button tag an attribute that allows you to identify it.
Working Example: JsFiddle
Ultimately I'm wanting the user to click on the Landing Page next to an image on either Print or Mug. Then on the Order Page have the button for Print/Mug be active and then the image that's associated be marked as well.
So I have in Landing Page the following code:
<ul class="dropdown-menu">
<li>
Print
</li>
<li>
Mug
</li>
</ul>
Then in the Order Page the following code:
<div class="img-container1 image-container" image_var="main_image.jpg">
<%= image_tag('main_image.jpg') %>
<div class="wk-after">
<div class="centered-wk">
<span class="fa fa-check-circle check-circle"></span>
</div>
<div class="centered-wk wk-select">
SELECTED
</div>
</div>
</div>
My thought process was to then grab from the Order Page the image_var attribute and make it active.
So far I've been using:
<script>
function toggleActive() {
var activeElements = document.querySelectorAll('image_var');
activeElements.forEach(function (el) {
el.classList.remove('active');
});
btn.classList.add('active');
}
</script>
This isn't working. I don't know what the best way to grab the image_var or a url parameter. What am I missing?
I've also tried:
<script>
function toggleActive() {
var activeElements = document.querySelectorAll('[image-var]');
activeElements.forEach(function (el) {
el.classList.remove('active');
});
btn.classList.add('active');
}
</script>
With an update to the div on the container to be image-var to match. Still not touching the image.
I feel like this should be working with jQuery:
<script>
$(function(){
$.url.attr('image')
$.url.attr('type')
});
</script>
Wouldn't this be pulling out the main_image.jpg and then the print from type?
I have durandal and knockout web application.
I have a html as follows:
<ul id="header">
</ul>
In .js function I am adding li dynamically as:
$("#header).append('<li id="btn"> <span class="name">Test</span></li>')
ko.applyBindingsToNode(ul);
I am aware of the fact that I am binding the li after applyBindings has been called. To add it dynamically I am using
ko.applyBindingsToNode(ul); , but still no luck.
Can anyone please tell me whats the syntax/alternative solution for this?
// begins a JavaScript comment. This means that everything after <a href="javascript: is commented out, and the resulting code will look something like this:
$("#header).append('<li id="btn"><a href="javascript:
ko.applyBindingsToNode(ul);
Furthermore, the ko.applyBindingsToNode call will be part of the ' string opened just after the opening brackets on the append call.
To resolve this, you need to escape those comments by placing backslashes before them:
href="javascript:\/\/"
Refer to the demo here.
Please find the code below:
HTML:
<ul id="header">
</ul>
JS:
$(function() {
$("#header").append('<li id="btn">' + ' <span class="name">Test</span></li>');
//ko.applyBindingsToNode(ul);
});
using foreach:
var DemoPage = (function() {
function DemoPage() {
var _this = this;
_this.buttons = ko.observableArray([]);
_this.debug = ko.observable('');
_this.testmethod = function(data, event) {
_this.debug('Clicked LI: ' + data.buttonId);
}
_this.addHeadingRow = function() {
_this.buttons.push({
buttonId: Math.floor(Math.random() * 100)
});
}
}
return DemoPage;
})();
var demoApp = new DemoPage();
ko.applyBindings(demoApp);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul id="header" data-bind="foreach: buttons">
<li id="btn">
<a data-bind="click: $root.testmethod">
<span class="name">Test</span>
</a>
</li>
</ul>
<button data-bind="click: addHeadingRow">add heading row</button>
<p data-bind="text: debug"></p>
I would like to answer my own question.
The solution is very simple .
In the .js file define an observable array
self.arraysample = ko.observableArray([]);
In a method populate the array with data
self.arraysample.push(data)
In the html page , we can do this:
<ul id="head" data-bind:"foeach:arraysample">
<li>
<a id="btn">
<span data-bind="text:$data.arrayelement"></span>
</a>
</li>
</ul>
Thats it whenevr the data in the "self.arraysample" changes, automatic updating will take place because of knockout js properties.
I hope it helps someone because ,I have seen so many examples in the web advising to use ko.applyBindings() once again which doesnt work at all.
I have three buttons on a page and depending on which on you click a different set of tabs is shown. Once you make a selection a reset button is available to clear your choice. In these tabs a user is able to make a selection and is then taken to a results page. What currently happens is, if a user clicks back via the browser the default view is the three original buttons but what I would like is the default view to be the last tab they were in before sending off for results. Is there a clever angular way to handle this?
Example:
http://plnkr.co/edit/2WZ12TKcHGXWmLhgD1vj
Buttons:
<div class="btn-group btn-group-justified" role="group" aria-label="Qualifications">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="tab = 1; showSelectorTabs=true; showSelectorButtons=true">Button 1</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="tab = 2; showSelectorTabs=true; showSelectorButtons=true">Button 2</button>
</div>
<div class="btn-group" role="group">
<button disabled="true" type="button" class="btn btn-default" ng-click="tab = 3; showSelectorTabs=true; showSelectorButtons=true">Button 3</button>
</div>
</div>
Tabs:
<tabset ng-show="tab == 1">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Home
</li>
<li role="presentation">Profile
</li>
<li role="presentation">Messages
</li>
</ul>
</tabset>
<tabset ng-show="tab == 2">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Home
</li>
<li role="presentation">Profile
</li>
<li role="presentation">Messages
</li>
</ul>
</tabset>
<tabset ng-show="tab == 3">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Home
</li>
<li role="presentation">Profile
</li>
<li role="presentation">Messages
</li>
</ul>
</tabset>
</div>
Nicholas is right, but I did something like this recently without using ngRoute so I wanted a simpler way to accomplish it. In addition to your original issue, you might want to consider using ng-repeat because (based on your example), that would save you a lot of code. Like so:
<div class='btn-group' role='group' ng-repeat='button in buttons'>
<button type='button' class='btn btn-default' ng-click='buttonSelected(button)'>Button {{ button }}</button>
</div>
<tabset ng-repeat='tabset in tabsets' ng-show='tabset.name == selectedTabset'>
<ul>
<li ng-repeat='tab in tabset.tabs' ng-class='{active: tab.active}'><a href='#{{ tabset.name }}_{{ tab.name }}'>{{ tab.name }}</a></li>
</ul>
</tabset>
Like MichaelOryl mentioned, I'd also suggest moving some of that logic out of the view and into the controller. I added the scope objects called above in ng-repeat in case you're not already familiar with that.
$scope.buttons = ['One','Two','Three'];
$scope.tabsets = [
{ name: 'One',
active: false,
tabs: [
{name: 'Home', active: true, content: ''},
{name: 'Profile', active: false, content: ''},
{name: 'Messages', active: false, content: ''}]
},{ // two more, same structure as first tabset }]
$scope.showSelectorButtons = true;
$scope.showSelectorTabs = false;
$scope.selectedTabset = 'None';
$scope.buttonSelected = function(selected){
$scope.showSelectorButtons = false;
$scope.showSelectorTabs = true;
$selectedTabset = selected;
}
And finally, here's my take on the location. You'll notice I added unique identifiers to the hrefs in the view, then I use those to select the proper tab on page load. This is also off the cuff, so no promises but it would look something like this:
$scope.deepLink(url){
if(url.indexOf('#') > -1){
var hash = url.split('#')[1];
var tabsetId = hash.split('_')[0];
var tabId = hash.split('_')[1];
var hashTabset = $filter('filter')($scope.tabsets, {name: tabsetId}, true);
var hashTab = $filter('filter')(hashTabset, {name: tabId}, true);
angular.forEach($scope.tabsets, function(tabset){
tabset.active = false;
angular.forEach(tabset.tabs, function(tab){ tab.active = false; });
});
hashTabset.active = true;
hashTab.active = true;
}
}
var url = $location.url();
$scope.deepLink(url);
Hope this is helpful, if you have any questions let me know.
You might want to consider saving the current selected tab in either a cookie or in browser local storage. You would only erase the value when appropriate (such as when the reset button is hit). I believe this would cause the currently selected view to be the default, more or less, when the user comes back in due to hitting page refresh or the back button.
I've use LocalStorageModule with good success for app defaults and general settings.
Otherwise you might want to just use the generic ngCookies module.
You should probably change your ngClicks to call functions inside your controller, though:
ng-click="setTab(3)"
You'd then have something like this as a controller, calling in the localStorageService, for example. This is off-the-cuff code - it probably won't run. I'm just trying to show you what I mean.
app.controller('SecretCtrl', function ($scope, localStorageService) {
$scope.tab = localStorageService('defaultTab');
if ($scope.tab == null) { $scope.tab = 0; }
$scope.setTab = function(tabNumber) {
$scope.tab = tabNumber;
$scope.showSelectorTabs=true;
$scope.showSelectorButtons=true
localStorageService.add('defaultTab', tabNumber);
}
};
This will work if you're using ngRoute or something similar and actually triggering URL changes in your app.
Push the state of $scope.tab into the URL with $location.search(), and when your page first loads read the state of it back off the URL to initialize which tab is active.
Change your buttons to call a function on your controller:
<button type="button" class="btn btn-default" ng-click="showTab(1)">Button 1</button>
Function on your controller does the logic you previously had in the HTML, in addition it updates the URL to contain the current selected tab number:
function showTab(tabNumber) {
$scope.tab = tabNumber;
$scope.showSelectorTabs=true;
$scope.showSelectorButtons=true;
$location.search({tab: tabNumber});
}
When your page is first loaded, initialize the tab from the value in the URL if it's available, otherwise default to tab 1 or whatever you like:
$scope.tab = $location.search().tab != null ? $location.search().tab : 1;
Basically, I'm trying to create a dynamic list, that allows the user to add list/remove list items.
The problem is for some reason
1) 'createTextNode' in this variable doesn't work.
2)
document.getElementById("myList").appendChild(list ).appendChild(inList);
works, while
var listContainer = document.getElementById("myList").appendChild(list ).appendChild(inList);
listCotnainer.appendChild(list).appendChild(inList);
DOES NOT!!
Any help would be appreciated. Thanks!!
Also, would appreciate if you could direct me to a readily written code for the dynamic list, it'll save me a great deal of time. Thanks!
function addItem(txt) {
var list = document.createElement("li");
var listAtr = list.setAttribute("class", "list-group-item");
listAtr.createTextNode(txt);
var inList = document.createElement("button");
var inListAtr = inList.setAttribute("class", "btn btn-default glyphicon glyphicon-minus");
document.getElementById("myList").appendChild(list ).appendChild(inList);
//listCotnainer.appendChild(listAtr);
}
function removeItems() {
}
function removeItem() {
}
<section>
<div ng-controller="addElements">
<h3>{{subtitle}}</h3>
<button class="btn btn-default glyphicon glyphicon-plus" onclick="addItem('This is a test text')"></button>
<button class="btn btn-default glyphicon glyphicon-minus" onclick="removeItems()"></button>
<ul class="list-group" id="myList">
<!-- dynamically generate list items here -->
</ul>
</div>
</section>
Your variable listContainer is wrong. It should be:
var listContainer = document.getElementById("myList");
listCotnainer.appendChild(list).appendChild(inList);