Jquery event quits firing after 3 hits - javascript

I'm working with a small mvc view and I want to be able to toggle the data source(ajax call to controller) between either 1 of 2 locations or both. It all works great, until I've clicked the toggles 3 different times, then all three toggles become unresponsive. I've tried click and change events, same results.
The only other items are on the page is a left navigation view that still works after the toggles go idle.
If I navigate away from the view with the toggles and then back to it they remain broken. If I hard refresh the page they work for another 3 clicks.
I'm at a loss on this and need some help. Any thoughts?
my toggles
<div class="btn-group"id="divToggle" data-toggle="buttons">
<label class="btn blue">
<input type="radio" value="1" class="toggle DashToggle"> US06
</label>
<label class="btn blue active">
<input type="radio" value="0" class="toggle DashToggle"> BOTH
</label>
<label class="btn blue">
<input type="radio" value="2" class="toggle DashToggle"> US05
</label>
</div>
And my view consist of 5 div blocks like the following
<div class="col-lg-2 col-md-4 col-sm-6 col-xs-12">
<div class="dashboard-stat blue-soft">
<div class="visual">
<i class="fa fa-car"></i>
</div>
<div class="details">
<div class="number stat_ActiveJits">
1349
</div>
<div class="desc">
Active JITS
</div>
</div>
<a class="more" href="javascript:;">
View Details <i class="m-icon-swapright m-icon-white"></i>
</a>
</div>
</div>
I have tried all of the following examples for the Jquery side and they all quit working after 3 clicks...
$(document).ready(function () {
$('#divToggle input[type=radio]').change(function () {
BuildDashBoard(this.value)
});
});
$('#divToggle input[type=radio]').live().change(function () {
BuildDashBoard(this.value)
});
$('.divToggle').on('change', '.DashToggle', (function () {
BuildDashBoard(this.value)
}));
And yes the toggle classes were changed to match these.
$(".US06_DashToggle").change(function () {
BuildDashBoard(1)
})
$(".US05_DashToggle").change(function () {
BuildDashBoard(2)
})
$(".DYNA_DashToggle").change(function () {
BuildDashBoard(0)
})
And finally my ajax call which works fine.
function BuildDashBoard(plantid)
{
var uri = 'http://' + host + '/DashBoard/DashStats';
$.ajax({
type: 'POST',
url: uri,
data: { PlantId: plantid },
success: function (d) {
$('.stat_ActiveJits').text(d.ActiveJits.toString());
$('.stat_PastDueJits').text(d.PastDueJits.toString());
$('.stat_ActiveExpedites').text(d.ActiveExpedites.toString());
$('.stat_PastDueExpedites').text(d.PastDueExpedites.toString());
$('.stat_ActiveProductionOrders').text(d.ActiveProductionOrders.toString());
//$.notific8('Application Options Updated', { theme: 'teal', life: 2000, verticalEdge: 'right', horizontalEdge: 'bottom' });
}
});
}

Well after a couple hours of fighting with this a comment Kevin B made about the radio buttons needing names made me rethink my css. My css was not correctly doing the grouping so once i clicked a button, it was checked and never unchecked. The reason it did not work as buttons, I have no clue and I'm done messing with it.

Related

ui not reflecting proper class upon toggle click

I have a toggle button and after wiring it up i noticed that when i click on it - the style doesn't change unless i refresh the page.
Here is my Html:
<div (click)="onValueChange(item)">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-toggle-switch" [ngClass]="{'active': item.isActive}">
<input type="checkbox">
<span class="status-on">on</span>
<span class="status-off">off</span>
</label>
</div>
</div>
What do i have to do to ensure that upon click the active class is added or removed properly without having to refresh?
Here is my on click function:
private onValueChange(item: ItemType) {
item.isActive = !item.isActive;
this.save(item);
}

How to disable buttons in button-group (Bootstrap)?

I have a button-group like the one on the picture:
and the code like this:
<span class="btn-group" data-toggle="buttons">
<span class="btn btn-default active">
<input type="radio" value="false"><label >No</label>
</span>
<span class="btn btn-default">
<input type="radio" value="true"><label >Yes</label>
</span>
</span>
How do I disable this control completely? When I added bootstrap class .disabled and/or attribute disabled to any or all of these elements I still could click on the buttons and they were affected even though bootstrap was showing the crossed circle icon.
I found here a workaround that stops events propagation, however it works only to prevent adding active class to the buttons but not focus.
$('.btn-group .btn.disabled').click(function(event) {
event.stopPropagation();
});
$('.btn-group .btn.disabled').click(function(event) {
return false;
});

Retain scroll position when a button is toggled

I am working on an angularJS application which has a page where I display around 30 items using ng-repeat. In front of each item, there is a toggle button (enabled/disabled). With the current code that I have, I can toggle these items. But the problem is if I scroll down and toggle lets say item 25, then automatically it scrolls to the top of the page. If I now scroll down, I can see that the toggle actually took place.
So the requirement now is to make sure that the scroll position is retained after the toggle button is clicked.
Please see below the code that I have.
HTML
<div id="eventTypes" class="panel-body">
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
<div ng-if="spinner" class="spinner">
<div class="spinner-container container1">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container2">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container3">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
</div>
</div>
JS
(function () {
'use strict';
angular.module('myApp').controller('itemsController', function ($scope, itemsService) {
var serviceError = function (errorMsg) {
console.log(errorMsg);
$scope.turnOffSpinner();
};
$scope.items = [];
$scope.item = {};
$scope.spinner = true;
$scope.toggleEnabled = function (item) {
$scope.turnOnSpinner();
itemsService.toggleEnabled(item)
.then(function () {
$scope.loaditems();
});
};
$scope.loaditems = function () {
itemsService.getitems().then(function (response) {
$scope.items = response.data;
}, serviceError);
$scope.turnOffSpinner();
};
$scope.turnOnSpinner = function () {
$scope.spinner = true;
};
$scope.turnOffSpinner = function () {
$scope.spinner = false;
};
$scope.loaditems();
});
}());
How this works right now is, once I click the toggle button, a spinner is enabled. Meanwhile the controller will call the itemService.toggleEnabled() method which does an ajax call to the server to just change the status of the item(enabled to disabled or vice-versa) in the backend. On successful change of the status and when the ajax call returns, the $scope.loadItems() method is called in the controller. This method will then do another ajax call to fetch the items (now with the updated status of the item that was toggled). The spinner is disabled and the data is then displayed on the UI.
When all of this is done, the page is scrolled to the top. This is annoying when I want to toggle an item which is way down in the list.
I want the page to be present at the same position when I clicked the toggle button of the corresponding item and not scrolling up to the top.
I am new to AngularJS and any help in this regard would be really helpful.
It looks like your spinner scheme is what's causing you problems:
...
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
...
<div ng-if="spinner" class="spinner">
...
Whenever you click your button, you are removing every single element in your ng-repeat from the DOM when you $scope.turnOnSpinner(). That's why it appears to jump to the top. It's not really jumping, there just aren't enough DOM elements to fill up the page, making the page so short that the scrollbar disappears (even if it's only for a second). Then when the spinner is done, your ng-repeat fills up the page with DOM elements again, resulting in your scroll position being lost.
So basically what you are trying to fix is a symptom of a less than ideal loading spinner implementation.
ng-if is a "brutal" way of hiding things in Angular. It's mostly meant to hide things for a longer period of time than "softer" directives like ng-show/ng-hide. One solution to your problem is to use ng-disabled on each one of your buttons to prevent the user from interacting with it while the spinner is active, rather than doing a hard removal of each element:
Before:
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
After:
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
ng-disabled="spinner"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
Another solution, which I really like and use myself is this Angular module: https://github.com/darthwade/angular-loading
You can attach it to any element in the page and it will put a loading spinner over it and prevent you from interacting with it until your ajax or whatever is done.
If you don't like either of those, try putting your ng-repeat into a container that you can use to prevent interaction with your elements when the spinner is up:
<div class="container" ng-class="{'you-cant-touch-this': spinner}">
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
</div>
Now you can style it in some way to prevent interaction without having to remove all those items from the DOM:
.you-cant-touch-this {
pointer-events: none;
}

Get html button/drop down text from c# code

I am wondering how I can grab the text from my HTML button/dropdown menu in c#? With the asp.net dropdownlist I was able to do string text = dropdownlist.Value; But it doesnt seem to be as simple, or maybe it is, with a different type of dropdown. I couldnt use the asp drop down list because it didnt act as a button and a drop down menu. The functions below are for changing the text from the default "Advanced" to the selected item text by the user. After the user changes the buttons text, I want to grab that text and use it as a condition for a sqlbuild.where clause. Also the text of the updated button should remain after the search button is clicked. With the asp drop down list the value remained after the refresh but for some reason when I search when the updated drop down menu, the change is wiped after selecting submit
Something like this is what i had in mind to do:
// get advancedsearch value
string selectedTxt = AdvancedSearch.value;
//filter on selected value
if (selectedTxt == "item1")
{
sqlbuilder.where = ("input1#");
}
else if (selectedTxt == "item2")
{
sqlbuild.where = ("input2#");
etc
// container for button/dropdown menu
<div class="container">
<div class="row buffer">
<div class="col-xs-2 col-sm-2 col-md-2 col-lg-2 ">
<div class="input-group" role="group" >
<div class="input-group-btn" role="group">
<asp:Button runat="server" class="btn btn-secondary dropdown-toggle" id="AdvancedSearch" data-toggle="dropdown" OnClientClick="AdvancedSubmit();" style="background-color:#718CA1;color:#FFF;" Text="Advanced:" />
<ul class="dropdown-menu" runat="server" id="dropdown" style="background-color:#718CA1;color:#FFF;">
<li><a class="dropdown-item" href="#" data-value="asset">item1</a></li>
<li><a class="dropdown-item" href="#" data-value="building">item2</a></li>
<li><a class="dropdown-item" href="#" data-value="astmgrbems">item3</a></li>
</ul>
</div>
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 text-center">
<div class="input-group" role="group">
<input type="text" id="InquiryInput2" onblur="javascript:removeSpaces()" style="display:none" runat="server" class="form-control" Width="280px" />
</div>
</div>
</div>
</div>
EDIT - Realize I forgot to add functions if that helps
function AdvancedSubmit() {
var obj = document.getElementById('<%=InquiryInput2.ClientID%>');
if (obj.style.display == 'none') {
obj.style.display = 'block';
}
};
$(function () {
$(".dropdown-menu li a").click(function () {
var selText = $(this).text();
/* $(".btn btn-secondary").html(selText);*/
alert(selText);
document.getElementById('<%=AdvancedSearch.ClientID%>').value = selText;
})
});
Just add an ASP hidden field. Then in the javascript set that field's value as well as the button's value. That way it'll be posted back to the server when the form is submitted.

Dynamically adding items to HTML list

I'm currently building a wizard in asp.net MVC 5 application using knockout. On one of the steps, I need to add items to an html list. that is, text is enter into a textbox and you click the added button, the text is added to the list.
My template:
<script type="text/html" id="addProduct">
<li class="dd-item bordered-inverse animated fadeInDown">
<div class="dd-handle dd-nodrag">
<div class="checkbox">
<label>
<a data-bind="attr: { 'href': '#' }" class='btn btn-xs icon-only success'><i class="fa fa-trash-o"></i></a>
<label data-bind="text: Name, uniqueName: true"></label>
</label>
</div>
</div>
</li>
</script>
<div class="row">
<div class="col-md-6">
<div id="newProduct" class="dd">
<ol class="dd-list" data-bind="template: { name: 'addProduct', foreach: Model.Step1.ProductServices }"></ol>
</div>
</div>
</div>
input textbox:
#Html.TextBoxFor(model => model.Step1.ProductService, new { data_bind = "value: Model.Step1.ProductService")
<button type="button" id="addservice" data-bind="event:{ click: AddProduct }">Add Service/Product</button>
knockout add event:
self.AddProduct = function () {
self.Model.CurrentStep().ProductServices.push({ name: self.Model.CurrentStep().ProductService });
}
self.Model.CurrentStep().ProductServices is a List Product as just one property name.
The code above add an item to the html list and updates the UI, but self.Model.CurrentStep().ProductServices.length is always zero, meaning nothing was added to the Model itself.
Please how can I force it to update the self.Model.CurrentStep().ProductServices?
length is not a property of an observableArray. Check ProductServices().length instead.

Categories