How to update Model value when trigger controller function? - javascript

controller:
onSelectRow :
function(id){
setTimeout(function () {$scope.getSelectedRow(); }, 0);
},};
$scope.getSelectedRow = function(){
var grid = $("#patientgrid");
var rowKey = grid.jqGrid('getGridParam',"selrow");
var kelr = grid.jqGrid('getCell', rowKey, 'PostTopic');
if (rowKey)
{
$scope.lastsel=kelr;
}
else
alert("No rows are selected");}
Html:
<h1>Topic:{{lastsel}}</h1>
Problem is ...
when I choose the new row, "lastsel" doesn't change.

I use $apply and it works!!
$scope.getSelectedRow = function(){
var grid = $("#patientgrid");
var rowKey = grid.jqGrid('getGridParam',"selrow");
var kelr = grid.jqGrid('getCell', rowKey, 'PostTopic');
if (rowKey)
{
$scope.lastsel;
$scope.$apply(function()
{
$scope.lastsel=kelr;
},1);
}
else alert("No rows are selected");
}

Related

clearing all elements from Javascript knockout observableArray. Items remain causing duplicates

I am trying to create an observableArray of "Board" objects to populate a view.
I can currently add new Board objects to the array after each timed page refresh. But instead of clearing the array and then adding new boards from the foreach loop, it just adds to the existing ones causing duplicates.
$(document).ready(function() {
refreshPage();
});
function refreshPage() {
getGames();
setTimeout(refreshPage, 10000);
console.log("Page refreshed");
};
function Board(data) {
this.gameChannel = ko.observable(data.GameChannel);
this.HomeTeamImage = ko.observable(data.HomeTeamImage);
this.HomeTeamName = ko.observable(data.HomeTeamName);
this.HomeBeerPrice = ko.observable(data.HomeBeerPrice);
this.HomeTeamArrow = ko.observable(data.HomeTeamArrow);
this.HomeBeer = ko.observable(data.HomeBeer);
this.HomeBeerAdjustedPrice = ko.observable(data.HomeBeerAdjustedPrice);
this.AwayTeamArrow = ko.observable(data.AwayTeamArrow);
this.AwayBeerPrice = ko.observable(data.AwayBeerPrice);
this.AwayTeamName = ko.observable(data.AwayTeamName);
this.AwayBeerAdjustedPrice = ko.observable(data.AwayBeerAdjustedPrice);
this.AwayBeer = ko.observable(data.AwayBeer);
this.awayTeamImage = ko.observable(data.AwayTeamImage);
this.FullScore = ko.computed(function() {
return data.HomeTeamScore + " | " + data.AwayTeamScore;
}, this);
}
function vm() {
var self = this;
self.gameCollection = ko.observableArray([]);
}
getGames = function() {
var _vm = new vm();
$.ajax({
type: "GET",
dataType: "json",
url: "/Dashboard/PopulateMonitor/",
error: errorFunc,
success: function(data) {
_vm.gameCollection = [];
$.each(data, function() {
_vm.gameCollection.push(new Board(this));
});
}
});
function errorFunc() {
alert("Error, could not load gameboards");
}
ko.applyBindings(_vm);
}
The issue appears within the getGames() function on or around the line
_vm.gameCollection = [];
I appreciate any help available. Not very well versed with Knockout.js
Every time you're calling getGames you're creating a new '_vm':
getGames = function () {
var _vm = new vm();
Move var _vm = new vm(); to
$(document).ready(function () {
var _vm = new vm(); // <-- HERE
refreshPage();
});
Some lines have to be moved too, see the snippet :
$(document).ready(function() {
_vm = new vm();
refreshPage();
});
function refreshPage() {
getGames();
setTimeout(refreshPage, 10000);
console.log("Page refreshed");
};
function Board(data) {
this.gameChannel = ko.observable(data.GameChannel);
this.HomeTeamImage = ko.observable(data.HomeTeamImage);
this.HomeTeamName = ko.observable(data.HomeTeamName);
this.HomeBeerPrice = ko.observable(data.HomeBeerPrice);
this.HomeTeamArrow = ko.observable(data.HomeTeamArrow);
this.HomeBeer = ko.observable(data.HomeBeer);
this.HomeBeerAdjustedPrice = ko.observable(data.HomeBeerAdjustedPrice);
this.AwayTeamArrow = ko.observable(data.AwayTeamArrow);
this.AwayBeerPrice = ko.observable(data.AwayBeerPrice);
this.AwayTeamName = ko.observable(data.AwayTeamName);
this.AwayBeerAdjustedPrice = ko.observable(data.AwayBeerAdjustedPrice);
this.AwayBeer = ko.observable(data.AwayBeer);
this.awayTeamImage = ko.observable(data.AwayTeamImage);
this.FullScore = ko.computed(function() {
return data.HomeTeamScore + " | " + data.AwayTeamScore;
}, this);
}
function vm() {
var self = this;
self.gameCollection = ko.observableArray([]);
ko.applyBindings(this);
}
getGames = function() {
$.ajax({
type: "GET",
dataType: "json",
// placeholder:
url: 'data:application/json;utf8,[]',
//url: "/Dashboard/PopulateMonitor/",
error: errorFunc,
success: function(data) {
_vm.gameCollection.removeAll();
$.each(data, function() {
_vm.gameCollection.push(new Board(this));
});
}
});
function errorFunc() {
alert("Error, could not load gameboards");
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
Couple of things:
You shouldn't call applyBindings more than once. So, move it outside of your setTimeout.
_vm.gameCollection = [] won't work. To clear your observableArray, use removeAll. You can also set it to an empty array like this: _vm.gameCollection([])
Also, if you want to call the same function after an interval of time, you can make use of setInterval.
Here's a minimal version of your code. Click on Run code snippet to test it out. I have created a counter variable which updates gameCollection with new data every second.
let counter = 0;
function refreshPage() {
getGames();
console.log("Page refreshed");
};
function Board(data) {
this.gameChannel = ko.observable(data.GameChannel);
}
function vm() {
var self = this;
self.gameCollection = ko.observableArray([]);
}
getGames = function() {
let data = [
{
GameChannel: `GameChannel ${++counter}`
},
{
GameChannel: `GameChannel ${++counter}`
}];
_vm.gameCollection.removeAll(); // <- Change here
data.forEach(function(item) {
_vm.gameCollection.push(new Board(item));
});
}
var _vm = new vm();
ko.applyBindings(_vm); // this needs to be only called once per page (or element)
setInterval(refreshPage, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- ko foreach: gameCollection -->
<span data-bind="text: gameChannel"></span><br>
<!-- /ko -->

Data not binding as it should be after calling ajax with knockoutjs

I have this grid that i am creating using knockoutjs, it works perfectly at first, now i am using a window.location.hash to run another query, it works too and query returns the correct amount of data however when i insert it within the observableArray (which gets inserted correctly as well), the grid doesn't update the data and shows the old data... I'm using removeAll() function on the observableArray as well before inserting new set of data but it wont update my grid, i suspect there is something wrong with the DOM?
I should mention when i reload the page (since the page's url keeps the hash for query) my grid shows the data and works perfectly. for some reason it needs to reload the page and doesn't work without,
Here is my JS:
if (!ilia) var ilia = {};
ilia.models = function () {
var self = this;
this.pageCount = ko.observable(0);
//this is the observableArray that i am talking about ++++++++
this.items = ko.observableArray();
var $pagination = null;
var paginationConfig = {
startPage: 1,
totalPages: 20,
onPageClick: function (evt, page) {
self.generateHash({ pageNum: page });
self.getData();
}
}
var hashDefault = {
pageNum: 1,
pageSize: 20,
catId: null,
search: ""
}
this.dataModel = function (_id, _name, _desc, _thumb, _ext) {
var that = this;
this.Id = ko.observable(_id);
this.Name = ko.observable(_name);
this.Desc = ko.observable(_desc);
this.Url = '/site/ModelDetail?id=' + _id;
var b64 = "data:image/" + _ext + ";base64, ";
this.thumb = ko.observable(b64 + _thumb);
}
this.generateHash = function (opt) {
//debugger;
var props = $.extend(hashDefault, opt);
var jso = JSON.stringify(props);
var hash = window.location.hash;
var newHash = window.location.href.replace(hash, "") + "#" + jso;
window.location.href = newHash;
return jso;
}
this.parseHash = function () {
var hash = window.location.hash.replace("#", "");
var data = JSON.parse(hash);
if (data)
data = $.extend(hashDefault, data);
else
data = hashDefault;
return data;
}
var _cntrl = function () {
var _hdnCatName = null;
this.hdnCatName = function () {
if (_hdnCatName == null)
_hdnCatName = $("hdnCatName");
return _hdnCatName();
};
var _grid = null;
this.grid = function () {
if (_grid == null || !_grid)
_grid = $("#grid");
return _grid;
}
this.rowTemplate = function () {
return $($("#rowTemplate").html());
}
}
this.createPagnation = function (pageCount, pageNum) {
$pagination = $('#pagination-models');
if ($pagination && $pagination.length > 0)
if (paginationConfig.totalPages == pageCount) return;
var currentPage = $pagination.twbsPagination('getCurrentPage');
var opts = $.extend(paginationConfig, {
startPage: pageNum > pageCount ? pageCount : pageNum,
totalPages: pageCount,
onPageClick: self.pageChange
});
$pagination.twbsPagination('destroy');
$pagination.twbsPagination(opts);
}
this.pageChange = function (evt, page) {
var hash = self.parseHash();
if (hash.pageNum != page) {
self.generateHash({ pageNum: page });
self.getData();
}
}
this.getData = function () {
var _hash = self.parseHash();
inputObj = {
pageNum: _hash.pageNum,
pageSize: _hash.pageSize,
categoryId: _hash.catId
}
//debugger;
//console.log(_hash);
if (inputObj.categoryId == null) {
ilia.business.models.getAll(inputObj, function (d) {
//debugger;
if (d && d.IsSuccessfull) {
self.pageCount(d.PageCount);
self.items.removeAll();
_.each(d.Result, function (item) {
self.items.push(new self.dataModel(item.ID, item.Name, item.Description, item.Thumb, item.Extention));
});
if (self.pageCount() > 0)
self.createPagnation(self.pageCount(), inputObj.pageNum);
}
});
}
else {
ilia.business.models.getAllByCatId(inputObj, function (d) {
if (d && d.IsSuccessfull) {
self.pageCount(d.PageCount);
self.items.removeAll();
console.log(self.items());
_.each(d.Result, function (item) {
self.items.push(new self.dataModel(item.ID, item.Name, item.Description, item.Thumb, item.Extention));
});
// initializing the paginator
if (self.pageCount() > 0)
self.createPagnation(self.pageCount(), inputObj.pageNum);
//console.log(d.Result);
}
});
}
}
this.cntrl = new _cntrl();
};
And Initialize:
ilia.models.inst = new ilia.models();
$(document).ready(function () {
if (!window.location.hash) {
ilia.models.inst.generateHash();
$(window).on('hashchange', function () {
ilia.models.inst.getData();
});
}
else {
var obj = ilia.models.inst.parseHash();
ilia.models.inst.generateHash(obj);
$(window).on('hashchange', function () {
ilia.models.inst.getData();
});
}
ko.applyBindings(ilia.models.inst, document.getElementById("grid_area"));
//ilia.models.inst.getData();
});
Would perhaps be useful to see the HTML binding here as well.
Are there any console errors? Are you sure the new data received isn't the old data, due to some server-side caching etc?
Anyhow, if not any of those:
Are you using deferred updates? If the array size doesn't change, I've seen KO not being able to track the properties of a nested viewmodel, meaning that if the array size haven't changed then it may very well be that it ignores notifying subscribers. You could solve that with
self.items.removeAll();
ko.tasks.runEarly();
//here's the loop
If the solution above doesn't work, could perhaps observable.valueHasMutated() be of use? https://forums.asp.net/t/2056128.aspx?What+is+the+use+of+valueHasMutated+in+Knockout+js

Nothing happend on click - jQuery

I have this code:
jQuery.fn.extend({
SelectBox: function(options) {
return this.each(function() {
new jQuery.SelectBox(this, options);
});
}
});
jQuery.SelectBox = function(selectobj, options) {
var opt = options || {};
opt.inputClass = opt.inputClass || "inputClass";
opt.containerClass = opt.containerClass || "containerClass";
var inFocus = false;
var $select = $(selectobj);
var $container = setupContainer(opt);
var $input = setupInput(opt);
$select.hide();
hideMe();
$input
.click(function(){
if (!inFocus) {
showMe();
} else {
hideMe();
}
})
.keydown(function(event) {
switch(event.keyCode) {
case 27:
hideMe();
break;
}
})
.blur(function() {
if ($container.not(':visible')) {
hideMe();
}
});
function showMe() {
$container.show();
inFocus = true;
}
function hideMe() {
$container.hide();
inFocus = false;
}
function setupContainer(options){
$container = $("." + options.containerClass);
$input = $("." + options.inputClass);
var first = false;
var li = "";
$select.find('option').each(function(){
if($(this).is(':selected')){
$input.find('span').text($(this).text());
first = true;
}
//var $li = $container.find('ul').append('<li>' + $(this).text() + '</li>');
var li = document.createElement('li');
li.innerHTML = $(this).text();
$container.find('ul').append(li);
$(li).click(function(event){
$(li).remove();
});
});
return $container;
}
function setupInput(options){
$input = $("." + options.inputClass);
$input.attr('tabindex', '0');
return $input;
}
};
In this code, the "select" i choose hidden, and replaced by a list.
Now, i want click on some "li", and "li" removed.
But, i click on the "li" i have created, and nothing happened.
Why? how can i remove or do anything else when i click on the "li"?
There is no need to add event to each individual element. Use event delegation.
$(document).ready(function() {
$(commonParentSelector).on('click', 'li', function() {
// ^^^^^^^^^^^^^^^^^^^^
$(this).remove();
});
});
Update commonParentSelector according to your needs and it should work.
Docs: https://api.jquery.com/on
use var $li = $("<li>").text($(this).text()).appendTo($container.find('ul'));

How can i use factory function for different AngularJS controllers?

I have a factory function that i want to use in three different controllers, I want to use if factory code block inside if condition of controller and else factory code block i want to use in else condition of controller. How to achieve this task using factory any help will be appreciated.
So far tried code below...
Factory.js
angular.module("App").factory('geoTreeFactory', function() {
return {
getTreeCheck: function (geoLocation) {
if (geoLocation.id === 5657){
$.each(geoLocation.parent(),function(index,location) {
if (location.id !== geoLocation.id) {
$.each(location._childrenOptions.data.items,function(index,child){
var disableChildId = 'disabled' + child.id;
var model = $parse(disableChildId);
model.assign($scope, true);
})
var disableItemId = 'disabled' + location.id;
var model = $parse(disableItemId);
model.assign($scope, true);
}
});
}
// If a child is checked Disable the parents
try {
var parent = geoLocation.parent().parent();
var disableParentId = 'disabled' + parent.id;
var parentModel = $parse(disableParentId);
parentModel.assign($scope, true);
} catch (err) {
// Ignore since this happens when a node is selected which has no children
}
//Expand and collapse tree on parent check so childrens can be disabled.
$scope.riskInPrcsgeoLocationTree.expand($scope.riskInPrcsgeoLocationTree.findByText(geoLocation.text));
$scope.riskInPrcsgeoLocationTree.collapse($scope.riskInPrcsgeoLocationTree.findByText(geoLocation.text));
//If the parent item is checked, disable all the children
if(geoLocation.items) {
$.each(geoLocation.items,function(index,location) {
var disableItemId = 'disabled' + location.id;
var model = $parse(disableItemId);
model.assign($scope, true);
});
}
},
//Else block function if ocnditions are false
getTreeUncheck: function(geoLocation) {
if (geoLocation.id === 5657){
var getParent = geoLocation.parent();
$.each(geoLocation.parent(),function(index,location) {
if (location.id !== geoLocation.id) {
$.each(location._childrenOptions.data.items,function(index,child){
var disableChildId = 'disabled' + child.id;
var model = $parse(disableChildId);
model.assign($scope, false);
})
var disableItemId = 'disabled' + location.id;
var model = $parse(disableItemId);
model.assign($scope, false);
}
});
}
// If child is unchecked Enable the parent
try {
var parent = geoLocation.parent().parent();
var checkedChildrens = [];
for (var i=0; i<selectedRiskGeoLocations.length; i++){
var checkNodes = selectedRiskGeoLocations[i];
checkedChildrens.push(checkNodes);
}
if (checkedChildrens.length === 0){
var disableParentId = 'disabled' + parent.id;
var parentModel = $parse(disableParentId);
parentModel.assign($scope, false);
};
}
catch (err) {
// Ignore since this happens when a node is selected which has no children
}
//If the parent item is unchecked, enable the childrens
if(geoLocation.items){
$.each(geoLocation.items,function(index,location){
var disableItemId = 'disabled' + location.id;
var model = $parse(disableItemId);
model.assign($scope, false);
});
}
}
};
Controller.js
var selectedCtlGeoLocations = [];
var selectedCtlGeoLocationIds = [];
$scope.populateControlInPrcsGeoLoction = function(geoLocation) {
var pos = $.inArray(geoLocation.text,selectedCtlGeoLocations);
if (pos < 0) {
selectedCtlGeoLocations.push(geoLocation.text);
selectedCtlGeoLocationIds.push(geoLocation.id);
// If the parent item is checked, disable all the
// children
geoTreeFactory.getTreeIfBlock();
} else {
selectedCtlGeoLocations.splice(pos, 1);
selectedCtlGeoLocationIds.splice($.inArray(
geoLocation.id, selectedCtlGeoLocationIds),
1);
// If the parent item is unchecked, enable the
// children
geoTreeFactory.getTreeElseBlock();
}
};
Alright, I could be way off here, but is this what you're trying to do?
app.factory('myservice', function(){
return {
ifBlock: function(){
// code to run if condition is true
},
elseBlock: function(){
// code to run if condition is false
}
}
});
app.controller('main', function(myservice){
$scope.myevent = function(geoLocation){
if(condition){
myservice.ifBlock(geoLocation);
} else {
myservice.elseBlock(geoLocation);
}
}
});
You could also solve this problem like this (and if I understand your problem correctly, this is probably the preferred method):
app.service('myservice', function(){
return {
go: function(geoLocation){
if(condition){
// code to run if condition is true
} else {
// code to run if condition is false
}
}
}
});
app.controller('main', function(myservice){
$scope.myevent = function(geoLocation){
myservice.go(goeLocation);
}
});

Issue with Double clicks on a element

I have running script which moves the tr elements from one container to another on double click. But i have below mentioned issues:
1) If we do are very quick double-click on elements than it moves but its values doesn't come, it shows empty tags.
2) I want to change the background color on double click and it color should remove when we click outside or another elements.
<script>
$(function () {
function initTabelMgmt() {
selectInvitees();
moveSelectedInvitees();
deleteInvitees();
//scrollOpen();
}
var tmContainer = $("div.cv-tm-body");
var toggleAssignBtn = tmContainer.find('.cv-move-items button');
/*
function scrollOpen() {
var position = $('div.cv-item li.open').first().position();
var offsetTop = $('div.cv-tm-col-r .cv-helper-grid-overflow').scrollTop();
var unitHeight = $('div.cv-item li.open').first().height();
var containerHeight = $('div.cv-tm-col-r .cv-helper-grid-overflow').height();
var scrollAmount = offsetTop + position.top;
if ((offsetTop - position.top) <= 0 && (offsetTop - position.top) >= (-containerHeight + unitHeight)) {
//do nothing
} else {
$('div.cv-tm-col-r .cv-helper-grid-overflow').animate({
scrollTop: scrollAmount
});
}
};
*/
// scrollOpen end
function selectInvitees() {
//select items from invitee list
var startIndex, endIndex;
var dbclick = false;
tmContainer.find("table.cv-invitees").on('click', 'tr', function (e) {
var row = $(this);
setTimeout(function () {
//singleclick functionality start.
if (dbclick == false) {
if (!row.is('.assigned')) {
toggleAssignBtn.removeClass('is-disabled');
if (e.shiftKey) {
row.parents('.cv-invitees').find('tr').removeClass('selected');
endIndex = row.parents('.cv-invitees').find('tr').index(this);
var range = row.closest('table').find('tr').slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex) + 1).not('.assigned');
range.addClass('selected');
} else if (e.ctrlKey) {
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.toggleClass('selected');
} else {
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.parents('.cv-invitees').find('tr').not(this).removeClass('selected');
row.toggleClass('selected');
}
}
}
}, 200)
})
.dblclick(function () {
dbclick = true
//doubleclick functionality start.
toggleAssignBtn.addClass('is-disabled');
function moveSelectedInviteesDBClick() {
var row = tmContainer.find("table.cv-invitees tr.selected");
if (!row.is('.assigned')) {
var allOpenSeat = $('.cv-item .open');
var numberOpen = allOpenSeat.length;
var name = row.find("td").eq(0).text();;
var company = row.find("td").eq(1).text();
var addedInvitees = [];
allOpenSeat.each(function (index) {
if (index < 1) {
var openSeat = $(this);
openSeat.find('.name').text(name);
if (company != '') {
openSeat.find('.company').addClass('show').text(company);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
openSeat.removeClass('open');
}
row.remove();
});
}
} // moveSelectedInviteesDBClick
moveSelectedInviteesDBClick();
setTimeout(function () {
dbclick = false
}, 300)
});
} // selectInvitees end
function moveSelectedInvitees() {
//move invitees from left to right
tmContainer.find('button.cvf-moveright').click(function () {
var selectedItem = $('.cv-invitees .selected');
var allOpenSeat = $('.cv-item .open');
var numberSelected = selectedItem.length;
var numberOpen = allOpenSeat.length;
var errorMsg = tmContainer.prev('.cv-alert-error');
if (numberSelected > numberOpen) {
errorMsg.removeClass('is-hidden');
} else {
var name;
var company;
var invitee = [];
var selectedInvitees = [];
var count = 0;
selectedItem.each(function () {
var $this = $(this);
name = $this.find("td").eq(0).text();
company = $this.find("td").eq(1).text();
invitee = [name, company];
selectedInvitees.push(invitee);
count = count + 1;
i = 0;
$this.remove();
});
var addedInvitees = [];
var items = $('div.cv-item li');
var seatItems = $('div.cv-order li');
allOpenSeat.each(function (index) {
if (index < count) {
var openSeat = $(this);
openSeat.find('.name').text(selectedInvitees[index][0]);
if (selectedInvitees[index][1] != '') {
openSeat.find('.company').addClass('show').text(selectedInvitees[index][1]);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
//selectedInvitees.shift();
openSeat.removeClass('open');
}
});
selectedInvitees = [];
}
toggleAssignBtn.addClass('is-disabled');
});
} // moveSelectedInvitees end
function deleteInvitees() {
//move invitees from left to right
tmContainer.find('div.cv-tm-col-r .cv-icon-remove').click(function () {
//delete seat assignment
var icon = $(this);
var idx = $('.ui-sortable li').index(icon.parent());
icon.parent().fadeTo(0, 0).addClass('open').find('.name').text('Open').end().fadeTo(750, 1);
icon.parent().find('.company').removeClass('show').text('');
// icon.parent().find('.entitystub').text('00000000-0000-0000-0000-000000000000');
// icon.parent().find('.entitytype').text('0');
// icon.parent().find('.pipe').remove();
// icon.hide();
// var testSeat = $('.seat-numbers li').get(idx);
//var seatStub = j$.trim(j$(testSeat).find('.seatstub').text());
//var input = { 'seatStub': seatStub };
//AssignSeats(input, "/Subscribers/WS/SeatAssignmentService.asmx/DeleteRegistrant");
});
}
initTabelMgmt();
}); // document.ready end
</script>
Your code looks pretty nice. You should also use in order to register from jQuery a single click event the native method .click(...). So please change the following line
tmContainer.find("table.cv-invitees").on('click', 'tr', function (e) {
To:
tmContainer.find("table.cv-invitees").click(function (e) {
and everything should work fine. For some strange reasons the function
$("#someelement").on("click", ...);
does not work always, only sometimes. JQuery officially recommends you to use the native functions for predefined events (such as onclick, onkeyup, onchange etc.) because of this strange behavior.
Edit:
If dblick does not work now, then make 2 lines please, like this:
tmContainer.find("table.cv-invitees").click(function (e) {
// [...]
;
tmContainer.find("table.cv-invitees").dbclick(function (e) {
// [...]
Edit2:
If it does not work, too, then please remove the single click event listener when you are in the .click() closure. Because if this happens, jQuery´s behavior is to treat it always as a single click. So, in other words dblick() will never be triggered, because .click() will always happens before. And then jQuery won´t count up to 2 fast clicks. Expect the unexpected^^
Edit3: This is the full code, which should hopefully work now as it is:
$(function ()
{
function initTabelMgmt()
{
selectInvitees();
moveSelectedInvitees();
deleteInvitees();
//scrollOpen();
}
var tmContainer = $("div.cv-tm-body");
var toggleAssignBtn = tmContainer.find('.cv-move-items button');
var iClickCounter = 0;
var dtFirstClick, dtSecondClick;
/*
function scrollOpen() {
var position = $('div.cv-item li.open').first().position();
var offsetTop = $('div.cv-tm-col-r .cv-helper-grid-overflow').scrollTop();
var unitHeight = $('div.cv-item li.open').first().height();
var containerHeight = $('div.cv-tm-col-r .cv-helper-grid-overflow').height();
var scrollAmount = offsetTop + position.top;
if ((offsetTop - position.top) <= 0 && (offsetTop - position.top) >= (-containerHeight + unitHeight)) {
//do nothing
} else {
$('div.cv-tm-col-r .cv-helper-grid-overflow').animate({
scrollTop: scrollAmount
});
}
};
*/
// scrollOpen end
function selectInvitees()
{
//select items from invitee list
var startIndex, endIndex;
var dbclick = false;
tmContainer.find("table.cv-invitees").click(function(e)
{
iClickCounter++;
if (iClickCounter === 1)
{
dtFirstClick = new Date();
var row = $(this);
window.setTimeout(function ()
{
//singleclick functionality start.
if (dbclick == false)
{
if (!row.is('.assigned'))
{
toggleAssignBtn.removeClass('is-disabled');
if (e.shiftKey)
{
row.parents('.cv-invitees').find('tr').removeClass('selected');
endIndex = row.parents('.cv-invitees').find('tr').index(this);
var range = row.closest('table').find('tr').slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex) + 1).not('.assigned');
range.addClass('selected');
}
else if (e.ctrlKey)
{
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.toggleClass('selected');
}
else
{
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.parents('.cv-invitees').find('tr').not(this).removeClass('selected');
row.toggleClass('selected');
}
}
}
},
200);
}
else if (iClickCounter === 2)
{
dtSecondClick = new Date();
}
else if (iClickCounter === 3)
{
if (dtSecondClick.getTime() - dtFirstClick.getTime() < 1000)
{
return;
}
iClickCounter = 0;
dbclick = true
//doubleclick functionality start.
toggleAssignBtn.addClass('is-disabled');
function moveSelectedInviteesDBClick()
{
var row = tmContainer.find("table.cv-invitees tr.selected");
if (!row.is('.assigned'))
{
var allOpenSeat = $('.cv-item .open');
var numberOpen = allOpenSeat.length;
var name = row.find("td").eq(0).text();;
var company = row.find("td").eq(1).text();
var addedInvitees = [];
allOpenSeat.each(function (index)
{
if (index < 1)
{
var openSeat = $(this);
openSeat.find('.name').text(name);
if (company != '') {
openSeat.find('.company').addClass('show').text(company);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
openSeat.removeClass('open');
}
row.remove();
}
);
}
}
// moveSelectedInviteesDBClick
moveSelectedInviteesDBClick();
window.setTimeout(function ()
{
dbclick = false
}, 300);
}
}
);
} // selectInvitees end
function moveSelectedInvitees()
{
//move invitees from left to right
tmContainer.find('button.cvf-moveright').click(function ()
{
var selectedItem = $('.cv-invitees .selected');
var allOpenSeat = $('.cv-item .open');
var numberSelected = selectedItem.length;
var numberOpen = allOpenSeat.length;
var errorMsg = tmContainer.prev('.cv-alert-error');
if (numberSelected > numberOpen) {
errorMsg.removeClass('is-hidden');
}
else
{
var name;
var company;
var invitee = [];
var selectedInvitees = [];
var count = 0;
selectedItem.each(function () {
var $this = $(this);
name = $this.find("td").eq(0).text();
company = $this.find("td").eq(1).text();
invitee = [name, company];
selectedInvitees.push(invitee);
count = count + 1;
i = 0;
$this.remove();
});
var addedInvitees = [];
var items = $('div.cv-item li');
var seatItems = $('div.cv-order li');
allOpenSeat.each(function (index)
{
if (index < count)
{
var openSeat = $(this);
openSeat.find('.name').text(selectedInvitees[index][0]);
if (selectedInvitees[index][1] != '')
{
openSeat.find('.company').addClass('show').text(selectedInvitees[index][1]);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
//selectedInvitees.shift();
openSeat.removeClass('open');
}
}
);
selectedInvitees = [];
}
toggleAssignBtn.addClass('is-disabled');
}
);
} // moveSelectedInvitees end
function deleteInvitees()
{
//move invitees from left to right
tmContainer.find('div.cv-tm-col-r .cv-icon-remove').click(function ()
{
//delete seat assignment
var icon = $(this);
var idx = $('.ui-sortable li').index(icon.parent());
icon.parent().fadeTo(0, 0).addClass('open').find('.name').text('Open').end().fadeTo(750, 1);
icon.parent().find('.company').removeClass('show').text('');
// icon.parent().find('.entitystub').text('00000000-0000-0000-0000-000000000000');
// icon.parent().find('.entitytype').text('0');
// icon.parent().find('.pipe').remove();
// icon.hide();
// var testSeat = $('.seat-numbers li').get(idx);
//var seatStub = j$.trim(j$(testSeat).find('.seatstub').text());
//var input = { 'seatStub': seatStub };
//AssignSeats(input, "/Subscribers/WS/SeatAssignmentService.asmx/DeleteRegistrant");
}
);
}
initTabelMgmt();
}
); // document.ready end
I guess that you interpret in your special case a double click as 3 times clicked at the same table entry. And if a user do so and if the time difference between first and second click is longer than one second, a double click will be fired. I think should be the solution to deal with this special case.
Edit 4: Please test, if it is possible to click on 3 different table column and get also double click fired. I think this is an disadvantage on how my code handles the double click. So, you need to know from which table column you have already 1 to 3 clicks set. How can we do this? Basically, there are 3 possibilities to do this:
(HTML5 only:) Make data attribute on each tr and the value for this data attribute
should be the clicks already clicke on this tr.
Define a global object key/value pair object, which holds the
event-ID (but I don´t know how to get this back by jQuery driven
events) as the key and the amount of clicks already done as the
value. And then if you are on the next click, you can decide what is
to do now for this tr. This is my favorite alternative!
Last but not least: Only register the click event on every tr and
make for each click-registering an own global area, so that we just
avoid the actual problem. You can do this e. g. by making an JS
Object which hold a member variable as the iclickCounter and you
make a new object of this class, each time a new click event is
registered. But this alternative need a lot more code and is main-memory-hungry.
All of thes possible options need a wrap around your click event, e. g. a loop, that iterates over all tr elements in the given table. You did this already partially by calling the jQuery-function .find(..). This executes the closure on every found html element. So, in your case on all tr elements in the searched table. But what you need to do is to make the workaround of one of my options given above.

Categories