I have a listview like the following:
<ul data-inset="true" data-filter="true" data-bind="foreach: growers" data-role="listview" id="ulGrowerList">
<li><a data-bind="click: $parent.setSelectedClassToGrowerList, attr: {id: growerId}"><span data-bind="text: growerName, attr: {id: growerId}, click: $parent.setSelectedClassToGrowerList" /></a></li>
</ul>
My setSelectedClassToGrowerList looks like this:
self.setSelectedClassToGrowerList = function (item, event) {
$(ulGrowerList).closest('ul').find('a').removeClass('highlight');
$(ulGrowerList).closest('ul').find('.selected').remove();
$(event.target).toggleClass("highlight");
if ($(event.target).hasClass("highlight")) {
$(event.target).append("<span class='selected'>Selected</span>");
//console.log(event.target.id);
replaceByValue('GrowerID', event.target.id);
postjson();
//update GrowerInfo
$.getJSON("Grower/GetGrower", function (allData) {
self.GrowerName(allData.Name);
self.GrowerCompany(allData.CompanyName);
self.GrowerAddress(allData.Address);
self.ShowGrowerCompany(allData.ShowCompany);
self.GrowerID(allData.ID);
});
} else {
$(event.target).find(".selected").remove();
}
As you see, I am binding setSelectedClassToGrowerList to both and tags because a click on the text (span) was not taking the required actions. Now, the problem is, when I click on the text itself, the "Selected" text is not displayed. The functionality I'm looking for is similar to this:
http://jsfiddle.net/czqXm/1/ except for ability to select multiple items which is already working.
The more I am working with knockout and jquery mobile, the more I am leaning towards the conclusion that they are not the best combination (sigh!).
OK. I think this is a duplicate-handler problem.
What's happening is that when you click the text, because it has a separate click handler on the SPAN, inside the click-handler for the then in actual fact TWO click events are being registered......
The first makes "Selected" appear, and the second makes it disappear again.
I think you can probably simplify your binding to this
<li><a data-bind="click: $parent.setSelectedClassToGrowerList,
attr: {id: growerId},
text: growerName"></a></li>
...But take a look at this fiddle
Related
I have a very small application in Angular JS. It's placed inside a bigger rails application, but I don't see too much interaction. The angular application, allows the user to interact with a group of categories. As easy as:
var angular_app = angular.module('angular_app', []);
angular_app.config(['$httpProvider', function($httpProvider, $cookieStore) {
//Protection
}]);
angular_app.controller('CategoriesController', function ($scope, $http) {
$scope.isEditing = false;
$scope.categoryName = '';
$http.get('/api/categories').success(function(data) {
//We use this to data-bind with the HTML placed below
$scope.categories = data;
});
$scope.addNewCategory = function() {
...
}
$scope.editCategory = function(index) {
if (!index)
return;
var selectedCategory = $scope.categories[index];
// With ng-show, we make visible the part of the UI
// that should be used for editing
$scope.isEditing = true;
}
$scope.cancelEditCategory = function() {
$scope.isEditing = false;
}
$scope.deleteCategory = function(index) {
...
}
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['angular_app']);
});
The idea is that the information is shown in a list, and we have an 'edit' button that allows the user to see other part of the UI that will let him perform changes.
<div ng-controller="CategoriesController">
<div ng-show='isEditing' class="popup_menu">
DIV FOR EDITING
</div>
<ul>
<li ng-repeat="category in categories">
<a href="#" ng-click='deleteCategory($index)'>[X]</a>
<a href="#" ng-click='editCategory($index)'>[E]</a>{{ category.name }}
</li>
</ul>
<input type="text" id="categoryTextBox" ng-model="categoryName"/>
<button id="submit" ng-click='addNewCategory()'>New category</button>
</div>
When I'm clicking the edit button, the corresponding part of the UI gets visible, but just after that, something happens, and the ul that should render the list, looses completely the binding, just showing something like:
[X] [E]{{ category.name }}
When it must be showing:
[X] [E]computer science
[X] [E]politics
[X] [E]news
(Which is what I have in the scope). It happens a few after the click (and works for a sec). No errors on the console, no interactions with other libraries (as far as I can see).
Thanks!
Turbolinks
I have no experience with Angular, but perhaps your problem could be to do with Turbolinks - this is a way of Rails loading the <body> tag of a page only - keeping the <head> intact.
Turbolinks is notorious for Javascript on Rails, as each time you reload your <body> without reloading the <head> part of your page, all your JS bindings are going to disappear. The solution to this, in normal JS, is to use JQuery / Javascript delegation, and delegate from the document object:
$(document).on("action", "delegated_object", function(){
...
});
Apologies if this does not work - it's a common issue for us, but as I have no experience with Angular, I don't know if it's going to help you or not.
It seems that I should have been more careful with the links:
<a href="#" ng-click='deleteCategory($index)'>[X]</a>
<a href="#" ng-click='editCategory($index)'>[E]</a>{{ category.name }}
Don't know exactly how this works, but seems that if the link has his href attribute, a GET request is made against 127.0.0.1, breaking in some way the angular code. If you put them like:
<a ng-click='deleteCategory($index)'>[X]</a>
<a ng-click='editCategory($index)'>[E]</a>{{ category.name }}
The problem will be solved. Thanks all for reading and helping!
I'm adding rows to a split listview with jQm, and I can only get the first row (not dynamically added) to trigger a click event. I assume there's a refresh function somewhere that I need to call, but I can't figure out what - I'm already refreshing the listview, which I expected to solve it...
Here's the fiddle:
http://jsfiddle.net/z36fy/1/
and here's the code:
<ul data-role="listview" data-split-icon="minus" id="list">
<li>
Item Description
remove
</li>
</ul>
Add item
JS:
var itemcount=1;
$('#addbtn').click(function() {
var addstr = '<li>Item Description '+itemcount+'remove</li></ul>';
$('#list').append(addstr);
$('#list').listview();
$('#list').listview('refresh');
itemcount++;
});
$('#list a.ui-li-link-alt').on("click",function() {
alert('delbtn clicked');
});
What am I missing?
Because you are dynamically adding DOM elements, you can't bind ahead of time. Instead use event delegation (https://learn.jquery.com/events/event-delegation/):
$('#list').on("click", ".delbtn", function() {
alert('delbtn clicked');
});
This says bind the click event to any items with class delbtn within the list even if they don't exist yet.
Updated FIDDLE
I'm trying to use, but to no luck
$("parent").on("click","child",function(){
//
}
My HTML sits this way
<ul id="carouselRoot">
<li id="container0"><div class="highcharts-container">.....</li>
<li>
<ul id="subCarousel">
<li id="container1"><div class="highcharts-container">.....</li>
<li id="container2"><div class="highcharts-container">.....</li>
<li id="container3"><div class="highcharts-container">.....</li>
</ul>
</li>
</ul>
I'm trying to capture the click event on each chart. So, $(".highcharts-container").click() works fine but I'm also adding charts dynamically to #subCarousel.
and doing
$("#subCarousel li").on("click",".highcharts-container",function(){});
simply does not invoke the call. How do I get around this?
PS: I've also tried using body as the parent.
Why don't you use Highchart API for capturing the click
$('#container').highcharts({
chart: {
events: {
click: function(event) {
alert ('clicked');
}
}
}
});
DEMO
Wrap your code within $(document).ready(function(){.....})
$(document).ready(function(){
$("#subCarousel li").on("click",".highcharts-container",function(){
alert('fgfg');
});
});
FIDDLE
Use highcharts built-in events. But for custom events, install highcharts-custom-events.
I have a functional dropdown:
<li data-dropdown="publish-dropdown-menu">
<a href="#" id="publish">
Publish
<img alt="" border="0" src="/assets/publish-arrow.jpg">
</a>
</li>
And the elements for this dropdown are(HAML):
.home-dropdown-menu.publish-dropdown-menu#publish-dropdown-menu
.top-arrow
%a.your-services{:href => new_service_path}
.icon-drop
%span
Your
%br>/
Service
%a.your-event{:href => new_event_path}
.icon-drop
%span
Your
%br>/
EVENT
But when this is replaced by AJAX this won't work anymore.
This is what I tried:
$('#publish').dropdown()
$('#publish').parent().dropdown()
But none of these worked.
Any advice on how to reset dropdown behaviour after page has been loaded.
Update
This is how I am replacing content:
$('#header').html('<%= escape_javascript(render 'layouts/header') %>')
Header has a lot of other content so is not easy for me to replace some parts.
The dropdown function or any events which were attached when DOM was loaded for the first time does not work for newly added elements. You need to reattach any events that were initially attached and re-call functions that you had called on those elements.
The reattachment of events can be achieved using jQuery on() method, but as dropdown is not an event and is a function we need to implement something like the following:
Trigger an event e.g. 'show' where you update the content of #header like follows:
$('#header').html("<%= escape_javascript(render 'layouts/header') %>").trigger('show');
Then call dropdown on the element in the show event handler in your javascript:
$(document).ready(function(){
$(document).on('show', '#header', function() {
$('#publish').dropdown();
});
});
I have a html list as the following:
<ul>
<li id="one">
<ul id="sub_ul">
<li>sth</li>
<li>sth2</li>
<li>sth3</li>
</ul>
</li>
</ul>
I observe a click event on "one" in order to SlideUp, SlideDown "sub_ul". The problem is that when the list is open, clicking on any of the sub-elements triggers the SlideUp action. I would naturally like to avoid this. Could anybody please tell me how I can do that?
Cheers,
Manojo
In your event handler first check if an item has been clicked.
$('one').observe('click', function(event)}{
if (event.findElement('li') != document) {
event.stop;
return;
}
// continue normal processing
});