I have to make some table-cells blink based on their values, and apparently IE8 is still a thing, so I'm working on the fix for that..
Here's my function for adding the blink-effect:
function blinkForIE(element) {
setInterval(function () {
if (element.hasClass('IEBlink')) {
element.removeClass('IEBlink');
}
else {
element.addClass('IEBlink');
}
}, 100);
}
the class:
.IEBlink
{
background-color:red;
}
This works for 4 of my 5 cells that should be blinking. I've debugged and checked taht the correct elements are getting passed to the blinkForIE-method and it adds the setInterval-thing for the first 4 elements but not the 5th..
Anyone knows why this might be happening? (I'm not sure what info might be needed, so if you need something else please comment and I'll add it when I can.)
EDIT: still not sure what you guys need to see, but here's all the jquery
var threshold = 100; //---THIS can be changed to what ever our threshold-difference should be.
$(document).ready(function () {
var itemsIndex;
var locationIndex;
var locations = [""];
$('#<%= gvKeying.ClientID %> tbody tr.GridHeader th').each(function () {
if ($(this).html() === 'Items') {
itemsIndex = $(this).index() + 1; //Find the column index of the Items column (+1 for nth-child usage)
}
else if ($(this).html() === 'KeyingLocation') {
locationIndex = $(this).index() + 1; //And the same for KeyingLocation-column.
}
});
$('#<%= gvKeying.ClientID %> tbody tr td:nth-child(' + locationIndex + ')').each(function () {
if ($(this).html() === ' ') {
//Do nothing.
}
else {
locations.push($(this).html()); //Add all locations to an array
}
});
locations = unique(locations); //Make them unique
locations.shift(); //This just removes the first empty element.
for (var i = 0; i < locations.length; i++) { //Loop through all locations
var values = [];
var valuesToBlink = [];
$('#<%= gvKeying.ClientID %> tbody tr').each(function () {
if ($(this).find('td:nth-child(' + locationIndex + ')').html() === locations[i]) {
values.push($(this).find('td:nth-child(' + itemsIndex + ')').html()); //Make an array with all the values.
}
});
values = getTop5(values); //We just want the top 5 highest values.
var firstBlinkVal = -1;
for (var j = 0; j < values.length - 1; j++) { //Loop through the values.
if (firstBlinkVal > -1 && compare(values[j], values[j + 1]) > -1) {
firstBlinkVal = Math.min(firstBlinkVal, compare(values[j], values[j + 1]));
}
else if(compare(values[j], values[j + 1]) > -1){
firstBlinkVal = compare(values[j], values[j + 1]);
}
}
if (firstBlinkVal > -1) {
for (var j = 0; j < values.length; j++) {
if (values[j] >= firstBlinkVal) {
valuesToBlink.push(values[j]);
}
}
}
$('#<%= gvKeying.ClientID %> tbody tr').each(function () { //Loop through all rows.
if ($(this).find('td:nth-child(' + locationIndex + ')').html() === locations[i]) { //If this row is the current location,
var temp = $(this).find('td:nth-child(' + itemsIndex + ')').html(); //get the value for this row.
if (jQuery.inArray(temp, valuesToBlink) > -1) { //if we want this to blink,
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0) {
blinkForIE($(this).find('td:nth-child(' + itemsIndex + ')')); //make it blink for IE
}
else {
$(this).find('td:nth-child(' + itemsIndex + ')').addClass('blink_me'); //make it blink for everything else.
}
}
}
});
}
});
function blinkForIE(element) {
var x = element.html();
console.log(x);
setInterval(function () {
if (element.hasClass('IEBlink')) {
element.removeClass('IEBlink');
}
else {
element.addClass('IEBlink');
}
}, 100);
}
//This just compares two values and returns true if the diff is over our threshold.
function compare(val1, val2) {
if (Math.abs(val1 - val2) > threshold) {
return Math.max(val1, val2);
}
return -1;
}
//Returns a sorted array of the top5 highest values in the input-array.
function getTop5(values) {
values.sort(function (a, b) { return b - a });
while (values.length > 5) {
values.pop();
}
values.sort(function (a, b) { return a - b });
return values;
}
//Makes the values of the input unique.
function unique(list) {
var result = [];
$.each(list, function (i, e) {
if ($.inArray(e, result) == -1) result.push(e);
});
return result;
}
You should call only 1 setInterval function, passing all cells to be animated.
function blinkForIE(elements) {
setInterval(function(){
elements.forEach(function(e){$(e).toggleClass('IEBlink')})
}, 100);
}
resp.
function blinkForIE($elements) {
setInterval(function(){
$elements.toggleClass('IEBlink')
}, 100);
}
(elements is Array, $elements is jQuery object)
The problem is, that setInterval must not execute the callback function, if there is no idle time slot at the execution time. It happens, when there are many executions within a small time interval.
You can troubleshoot this also using different offsets:
setTimeout(function(){setInterval(callback, 100)}, i*15)
Related
I'm struggling in how to make this simple code work: i only want to check the values of every column and see if they are sequential (like 0 to 7 for example), and if so, highlight that column (class = "snaked" ).
So i marked every cell which belongs to the first row (class = "vstarter") and i tried out this :
function is_colsnake() {
ognicella.filter(".vstarter").each(
function() {
var cella = $(this);
var pos = cella.index();
var colonna = ognicella.filter(":nth-child(" + (pos + 1) + ")")
var col = [];
var issnake = false;
colonna.each(
function() {
col.push(parseInt($(this).text()));
});
col.each(
function() {
var start = parseInt($(this).text()) ;
var next = parseInt($(this).next().text()) ;
var prev = parseInt($(this).prev().text()) ;
var ix = $(this).index() ;
if (ix == 0) {
if (next == start + 1) {
issnake = true;
} else {
issnake = false;
}
} else if (start != prev + 1) {
issnake = false;
}
});
if (issnake) {
colonna.each(function() {
$(this).addClass("snaked");
})
} else {
colonna.each(function() {
$(this).removeClass("snaked");
})
}
})
};
However it isn't working. Would you please help?
I have a function to select a random number from 0 to 45 and then I show the div with the specific ID. It's working fine but it repeats a number.
Can anyone advise so it won't repeat numbers?
I call the function onclick like this
$(".skip").click(function () {
scared++;
$("#counter").html("My current count is: " + dared);
var d = 50;
/*$(".question").addClass("hideMe");
$(this).parents("div").next("div").removeClass("hideMe");*/
var r = Math.round(Math.random() * 44) + 1;
var newquestion = "q" + r;
$('.active').removeClass("active");
$("#" + newquestion).addClass("active");
if (scared > 44) {
$('.main').fadeOut('fast');
$('.logo').switchClass("logo", "share");
$('.progress').css("display", "none");
$('.share-game').css("display", "block");
$('.hero').css("right", "-240px");
$('#score-total').html(score + '');
} else {
}
$('.red-line').append('<div id="children' + (d++) + '" class="red"></div>');
return false;
});
You can see what i did.
var usedNumbers = [];
var randomNumbers = [];
$(function() {
//Getting 20 random numbers
for (i = 0; i < 20; i++) {
randomNumbers.push(getRandomNumber());
}
console.log(randomNumbers);
function getRandomNumber() {
var hasInArray = true;
do {
var r = Math.round(Math.random() * 44) + 1;
if (usedNumbers.indexOf(r) === -1) {
usedNumbers.push(r);
hasInArray = false;
return r;
}
} while (hasInArray === true);
}
});
Warning to not set the numbers of randomnumbers more then what you want to get, because that will cause an infinite loop!
Use an array to capture the used numbers and then check that array on each click, generating a new number if that one is found. It resets back to an empty array when it is full.
var savedNumbers = [];
function getRandom() {
if (savedNumbers.length === 45) {
savedNumbers = [];
}
var r = Math.round(Math.random() * 44) + 1;
if (savedNumbers.indexOf(r) > -1) {
getRandom();
} else {
savedNumbers.push(r);
return r;
}
}
DEMO
I have two grids that I allow the user to copy rows between. For small sets, no problem, but for large datasets (5-10 thousand) I notice JQGrid is very slow. This is what I have now:
$('#imgRightArrow').click(function ()
{
var fromGrid = $('#fromGrid');
var toGrid = $('#toGrid');
var rowKeys = fromGrid.getGridParam('selarrrow');
var j = rowKeys.length - 1;
if (j >= 0) $('body').addClass('loading');
(function ()
{
for (; j >= 0; j--) // - high to low to avoid id reordering
{
var row = fromGrid.jqGrid('getRowData', rowKeys[j]);
toGrid.addRowData('gtp_' + rowKeys[j], row); // - add prefix to keep rowid's unique between grids
fromGrid.delRowData(rowKeys[j]);
if (j % 100 === 0)
{
$('#fromGridHeader').text(fromGrid.jqGrid('getGridParam', 'records') + ' Cards on this Order');
$('#toGridHeader').text(toGrid.jqGrid('getGridParam', 'records') + ' Cards to be Dispatched');
if (j === 0) // - done
$('body').removeClass('loading');
else
{
j--;
window.setTimeout(arguments.callee); // - set a timer for the next iteration
break;
}
}
}
})();
});
It's so slow that I have to use a kludge to prevent the browser from timing out.
I've tried something like this:
$('#imgRightArrow').click(function ()
{
var fromGrid = $('#fromGrid');
var toGrid = $('#toGrid');
var copyData = toGrid.jqGrid('getRowData'); // - existing data
var rowKeys = fromGrid.getGridParam('selarrrow');
var j = rowKeys.length - 1;
if (j >= 0) $('body').addClass('loading');
(function ()
{
for (; j >= 0; j--)
{
copyData.push(fromGrid.jqGrid('getRowData', rowKeys[j]));
fromGrid.jqGrid('delRowData', rowKeys[j]);
if (j % 100 === 0)
{
if (j === 0)
{
fromGrid[0].refreshIndex();
toGrid.jqGrid('clearGridData', true);
toGrid.setGridParam({ data: copyData });
toGrid[0].refreshIndex();
toGrid.trigger('reloadGrid');
$('#fromGridHeader').text(fromGrid.jqGrid('getGridParam', 'records') + ' Cards on this Order');
$('#toGridHeader').text(toGrid.jqGrid('getGridParam', 'records') + ' Cards to be Dispatched');
$('body').removeClass('loading');
}
else
{
j--; // - manually decrement since we break
window.setTimeout(arguments.callee); // - set a timer for the next iteration
break;
}
}
}
})();
});
...it seems faster, but deleting the rows from the fromGrid still uses delRowData, which is very slow.
Any ideas on how to accomplish this efficiently for large sets of data?
Any client-side operation is going to be very slow when you have thousands of rows involved. The best way to speed it up would be to do the operations server-side. For example, you could pass the ID's to the server as part of an AJAX request and then refresh the grids when the server response is received.
Alternatively, is the user really selecting five thousand rows to copy, or are they just trying to do a bulk operation such as "copy all"? Maybe you can implement such a feature to improve the overall experience, and eliminate the need to pass any ID's to the AJAX request.
Does that help?
By pressing ctrl+c we can copy and paste the selected row using the following methods,
$(document).ready(function () {
$('#gvMygrid').keyup(function (e) {
var crtlpressed = false;
var celValue = "";
var celValue1 = "";
var celValue2 = "";
if (e.keyCode == 17) {
crtlpressed = true;
}
if (e.keyCode == 67 && e.ctrlKey == true) {
var myGrid = $('#gvMygrid');
var my_array = new Array;
my_array = $("#gvMygrid").getGridParam('selarrrow');
for (var i = 0; i < my_array.length; i++) {
var rowInfo = $("#gvMygrid").getRowData(my_array[i]);
if (rowInfo != null)
var data = JSON.stringify(rowInfo);
var splitData = data.split('","');
for (var j = 1; j < splitData.length; j++) {
celValue1 = celValue1 + splitData[j].split(":")[1] + " ";
}
celValue1 = celValue1 + '\r\n';
}
celValue2 = celValue1.replace(/"/g, '');
celValue = celValue2.replace(/}/g, '');
crtlpressed = false;
copyToClipboard(celValue);
}
function copyToClipboard(s) {
if (window.clipboardData && clipboardData.setData) {
window.clipboardData.clearData("Text");
clipboardData.setData("Text", s);
}
}
}); });
We are splitting the data with a four spaces in the for loop so that we can get each cells data with four spaces.
I am attempting to create a table that will only display one row at a time and also randomize on each refresh. Here is my code:
<script>
var maxRows = 1; //displays one row at a time
$('#song-list').each(function() {
var cTable = $(this);
var cRows = cTable.find('tr:gt(0)');
var cRowCount = cRows.size();
if (cRowCount < maxRows) {
return;
}
/* hide all rows above the max initially */
cRows.filter(':gt(' + (maxRows - 1) + ')').hide();
var cPrev = cTable.siblings('.prev');
var cNext = cTable.siblings('.next');
/* start with previous disabled */
cPrev.addClass('disabled');
cPrev.click(function() {
var cFirstVisible = cRows.index(cRows.filter(':visible'));
if (cPrev.hasClass('disabled')) {
return false;
}
cRows.hide();
if (cFirstVisible - maxRows - 1 > 0) {
cRows.filter(':lt(' + cFirstVisible + '):gt(' + (cFirstVisible - maxRows - 1) + ')').show();
} else {
cRows.filter(':lt(' + cFirstVisible + ')').show();
}
if (cFirstVisible - maxRows <= 0) {
cPrev.addClass('disabled');
}
cNext.removeClass('disabled');
return false;
});
cNext.click(function() {
var cFirstVisible = cRows.index(cRows.filter(':visible'));
if (cNext.hasClass('disabled')) {
return false;
}
cRows.hide();
cRows.filter(':lt(' + (cFirstVisible +2 * maxRows) + '):gt(' + (cFirstVisible + maxRows - 1) + ')').show();
if (cFirstVisible + 2 * maxRows >= cRows.size()) {
cNext.addClass('disabled');
}
cPrev.removeClass('disabled');
return false;
});
});
</script>
Second piece of code:
<script>
Array.prototype.shuffle = function() {
for (var i = 0; i < this.length; i++) {
// Random item in this array.
var r = parseInt(Math.random() * this.length);
var obj = this[r];
// Swap.
this[r] = this[i];
this[i] = obj;
}
}
function randomize(tableID) {
var myTable = document.getElementById(tableID);
var myRows = new Array();
for (i=myTable.rows.length-1; i>=0; i--) {
var theRow = myTable.rows[i];
myRows.push(theRow);
theRow.parentNode.removeChild(theRow);
}
myRows.shuffle();
for (j=0; j<myRows.length; j++) {
myTable.appendChild(myRows[j]);
}
}
window.onload = function() {
randomize("song-list");
}
//-->
</script>
Both pieces work fine on their own but when I try to combine them the randomize function supersedes the other code and I get a long list of tr that randomize after refresh.
I know there is something I can do to make these codes agree with one another.
Have any suggestions?
put the whole 1st block of code into a function:
function showOneRow() {
...
}
and call it after randomize:
window.onload = function() {
randomize("song-list");
showOneRow();
}
When I have a currently selected row in my jqgrid, and I have buttons that say "Next" and "Previous", how do I programmatically do that? Upon initial investigation, I'll need to get the ids of the rows but is there a way to do this by just using the index of the current selected row in the grid?
The ids in my rows are not sequential and are of random values.
Thanks
$('#btnNext').click(function () {
var grid = $("#grid").jqGrid({...});
var selectedRow = grid.getGridParam('selrow');
if (selectedRow == null) return;
var ids = grid.getDataIDs();
var index = grid.getInd(selectedRow);
if (ids.length < 2) return;
index++;
if (index > ids.length)
index = 1;
grid.setSelection(ids[index - 1], true);
});
According to http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events, there's row index property but it doesn't get passed in to onSelectRow event. Perhaps you could get to the row object via its ID and check whether it has a row index, possibly called iRow. From there you'll just have to find the next row by row index iRow+1.
var rowId;
var previousRecord = false;
var array;
function initGrid() {
array = $(ProspectsGrid).jqGrid('getDataIDs');
var i = 0;
if (previousRecord == true)
i = array.length-1;
$(ProspectsGrid).setSelection(array[i]);
rowId = array[i];
}
function GetNextRecord() {
previousRecord = false;
if (rowId != array[array.length - 1]) {
var i = 0;
while (rowId != array[i]) {
i++;
}
i++;
$(ProspectsGrid).setSelection(array[i]);
rowId = array[i];
}
else {
var currentPage = ProspectsGrid.getGridParam("page");
if (currentPage < ProspectsGrid.getGridParam("lastpage")) {
ProspectsGrid.setGridParam({
page: currentPage + 1
});
ProspectsGrid.trigger("reloadGrid");
}
}
}
function GetPreviousRecord() {
previousRecord = true;
if (rowId != array[0]) {
var i = 0;
while (rowId != array[i]) {
i++;
}
i--;
$(ProspectsGrid).setSelection(array[i]);
rowId = array[i];
}
else {
var currentPage = ProspectsGrid.getGridParam("page");
if (currentPage > 1) {
ProspectsGrid.setGridParam({
page: currentPage - 1
});
ProspectsGrid.trigger("reloadGrid");
}
}
}