Slickgrid - Move rows with arrow links - slickgrid

I am trying to create a function, that when an arrow link (up or down) is clicked on a certain row, the row will move up or down.
Is there a way to dynamically move rows in the data this way?
(I know there is the RowMoveManager but the requirements request arrow links instead of drag-able)

I found a way to do it, although it might not be the most efficient way. I have a column in my data, rank and I added an onClick function on an arrow moveOneUp(index);
function moveOneUp(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = parseInt(_grid.dataView.getItem(rowIndex).rank)-1 ;
_grid.dataView.getItem(rowIndex-1).rank = parseInt(_grid.dataView.getItem(rowIndex-1).rank)+1;
_grid.dataView.fastSort('rank');
}
If anyone needs the rest of the arrow functions:
function moveOneDown(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = parseInt(_grid.dataView.getItem(rowIndex).rank)+1 ;
_grid.dataView.getItem(rowIndex+1).rank = parseInt(_grid.dataView.getItem(rowIndex+1).rank)-1;
_grid.dataView.fastSort('rank');
}
function moveTop(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = 0 ;
_grid.dataView.fastSort('rank');
}
function moveBottom(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = parseInt(_grid.dataView.getLength())+1;
_grid.dataView.fastSort('rank');
}

function moveOneUp(rowIndex) {
dataViewReorder.beginUpdate();
rowIndex = rowIndex - 1;
dataViewReorder.getItem(rowIndex).intOrd0 = parseInt(dataViewReorder.getItem(rowIndex).intOrd0) - 1;
dataViewReorder.getItem(rowIndex - 1).intOrd0= parseInt(dataViewReorder.getItem(rowIndex - 1).intOrd0) + 1;
dataViewReorder.fastSort('intOrd0');
dataViewReorder.setItems(dataReorder);
dataViewReorder.endUpdate();
gridReorder.setData(dataViewReorder);
gridReorder.render();
}
function moveOneDown(rowIndex) {
dataViewReorder.beginUpdate();
rowIndex = rowIndex - 1;
dataViewReorder.getItem(rowIndex).intOrd0= parseInt(dataViewReorder.getItem(rowIndex).intOrd0) + 1;
dataViewReorder.getItem(rowIndex + 1).intOrd0= parseInt(dataViewReorder.getItem(rowIndex + 1).intOrd0) - 1;
dataViewReorder.fastSort('intOrd0');
dataViewReorder.setItems(dataReorder);
dataViewReorder.endUpdate();
gridReorder.setData(dataViewReorder);
gridReorder.render();
}

Related

Google script pushing data from one tab to another while retaining data validation

I have the following google apps script. It functions to look in my PENDING-IP tab and check the status (column G). If the status is "Screened - Ready for Review," then it moves the entire row of data to the SCREENED - READY FOR REVIEW tab.
My problem is this - the data in columns L, M, and N of the PENDING tab is a checkbox, but when it pushes it to the SCREENED tab, it changes it to TRUE or FALSE. Is there a way to modify my script to push the data with validation to retain the checkboxes? Thank you!
function screened() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('PENDING-IP'); //source sheet
var testrange = sheet.getRange('G:G'); //range to check
var testvalue = (testrange.getValues());
var csh = ss.getSheetByName('SCREENED - READY FOR REVIEW'); //destination sheet
var data = [];
var j =[];
//Condition check in G:G; If true copy the same row to data array
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] == 'Screened - Ready for Review') {
data.push.apply(data,sheet.getRange(i+1,1,1,25).getValues());
//Copy matched ROW numbers to j
j.push(i);
}
}
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
//Delete matched rows in the source sheet
for (i=0;i<j.length;i++){
var k = j[i]+1;
sheet.deleteRow(k);
//Alter j to account for deleted rows
if (!(i == j.length-1)) {
j[i+1] = j[i+1]-i-1;
}
}
}
Try this
I haven't actually tested this except in a simpler situation
function screened() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getSheetByName('PENDING-IP');
var testrange=sheet.getRange(1,7,sheet.getLastRow(),1);
var testvalue=testrange.getValues();
var valids=testrange.getDataValidations();
var csh = ss.getSheetByName('SCREENED - READY FOR REVIEW'); //destination sheet
var data = [];
var valid = [];
var j =[];
var d=0;
for (var i=0;i<testvalue.length;i++) {
if (testvalue[i][0] == 'Screened - Ready for Review') {
data.push(sheet.getRange(i+1-d,1,1,25).getValues());//I am not sure but I could see having to put [0] at the end here
valid.push(sheet.getRange(i+1-d,1,1,sh.getLastColumn()).getDataValidations());//I am not sure but I could see having to put [0] at the end here
sheet.deleteRow(i+1-d++);//this should delete matching rows
}
}
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(valid);
}
What I've found is that you can treat the validations the same way you treat the data by replacing getValues() with getDataValidations() and setValues() with setValidations();

Kendo NumericTextBox with step and rounding

I want to setup kendoNumericTextBox to allow user input any integer number and set step to 1000. But when user enters any value and use spinner, it should update to next multiple of step.
For example:
enter 123, press spin up, value will be 1000
enter 1234, press spin up, value vill be 2000
Is it possible or only way is to handle spin event and modify value from there?
UPDATE:
Ok, guys, thnx for help.
I have this spin handler now and it seems to be working as expected.
function onSpin(e)
{
var currentvalue = kendo.parseInt(this.value());
if (currentvalue > 0)
{
this.value(Math.floor(currentvalue / this.step()) * this.step());
}
if (currentvalue < 0)
{
this.value(Math.ceil(currentvalue / this.step()) * this.step());
}
}
I have provided a dojo below with a potential solution for you:
https://dojo.telerik.com/UQohUjaP/2
I have created a function that will work on the spin and on change value so that it will step the value up/down on the value that you set e.g. 1000
the function is fairly simple and for brevity I have taken out the log statements here:
function onChange() {
var currentvalue = kendo.parseInt(this.value());
if (currentvalue > 0) {
currentvalue = Math.ceil(currentvalue / this.step()) * this.step();
} else if (currentvalue < 0) {
currentvalue = Math.floor(currentvalue / this.step()) * this.step();
} else {
currentvalue = 0;
}
this.value(currentvalue);
}
Unfortunately there doesn't seem to be a simple way of figuring out if the value has gone up or down so I am basically checking to see if the value is greater than 1 or less than 1 and then calculating the ceiling or the floor for the value and then stepping it in the right direction. in order to cater for zero we have a special condition which just sets the value to 0 assuming that is a valid value in your scenario
As you say, it's possible by listening to the spin event:
$("#numerictextbox").kendoNumericTextBox({
min: 0,
spin: function(e) {
var isUp = e.sender._key === 38,
isDown = e.sender._key === 40;
var m = Math.trunc(this.value()/1000),
value = isUp ? m + 1 : m;
this.value(value * 1000);
}
});
I doubt there's something out of the box, because your needs seem somewhat unusual.

Progress when assigning datasource to XtraTreeList

I have a XtraTreeList and I assign a huge datasource (with millions of items) to it
xtraTree.TreeViewData = dataSource;
This operation takes 80 seconds to complete, which is totally fine given the amount of nodes.
I'd just like to display a somewhat reliable progress bar to the user, indicating how many nodes have been processed.
I have tried:
looking in the event list, but I only found PrintExportProgress
googling for the topic, hoping I would find something on the DevExpress support pages
I'm using the WinForms variant, version 15.2 if that matters.
This is not about displaying progress while I build the datasource. There are 2 steps:
build the datasource (read from file) - this also takes 60 seconds, but I do that myself and I have no problem here
assign the datasource to the XtraTreeList - works, but I don't get progress information and it needs to be done on the UI thread, which is blocking
This is also not about cross-thread updating of the progress bar. I know how to do that.
Hey I did the same thing in a project that I built using WinForms ... except I only had 4500 items - these items were files that I had to extract data from. What I did is at each file that I processed (at the bottom of my foreach loop) I called a method to update my progress bar on my form:
Form1.UpdateProgressbar();
Inside my Form1.cs, I did this:
public void UpdateProgressbar()
{
progressBar2.Increment(1);
label7.Text = "Processed: " + Convert.ToString(progressBar2.Value) + " out of " + Globals.totalartistcount + " Artists";
label8.Text = "Processed: " + Globals.songcounter + " Songs. Processing: " + Globals.artist;
label9.Text = "Total Number of Songs to process: " + Globals.totalsongcount;
progressBar2.Update();
Application.DoEvents();
}
If I remember right the
Application.DoEvents();
was critical to actually see the progress bar move and the labels update their text. I initialized my progress bar this way:
/* ------ progress bar ------------------------------------------ */
public void InitializeProgressBar(DirectoryInfo di)
{
int songcount = 0;
int artistcount = 0;
int index = 0;
//Get Total number of folders
foreach (var sf in di.GetDirectories())
{
//find index of artist to process
//this is just an array of artist names and if true or false to process
for (int i = 0; i <= Globals.artists.GetUpperBound(0); i++)
{
if (sf.Name == Globals.artists[i, 0])
{
index = i;
break;
}
}
if (Globals.artists[index, 1] != "false")
{
// Get a total number of files to process (MAX)
foreach (var fi in sf.GetFiles("*.mp3"))
{
songcount++;
}
artistcount++;
}
}
Globals.totalartistcount = artistcount;
Globals.totalsongcount = songcount;
progressBar2.Minimum = 0;
progressBar2.Maximum = artistcount - 1;
progressBar2.Value = 0;
Application.DoEvents();
}
There, I hope that helps.

How to get the XPath of a grid cell using Firebug?

I am working on a UI. My job is to automate it. I came across the following grid.
When you click on any cell under the Rule column, a browse button appears.
I am supposed to automate this scenario. So, using Firebug I am trying to extract the XPath of that cell.
I used Firebug's inspector to locate that particular cell, so that I can write the XPath for it, but I am unable to locate that cell. Instead, the entire row is getting selected, as shown in next images.
How should I approach this problem?
below code might help you to verify the grid values,
public void verifyTableValues(String expectedValue
) {
try {
//List of Fields values which you want to verify
List<String> expectedValues = Arrays.asList(expectedValue.split("#"));
// you will get the number of rows in Table Select the xpath to /tr
String tableRow = driver.findElements(By.xpath(//table row constant));
int tableRwCnt = getCount(tableRow);
// you will get the number of Columns in Table Select the xpath to /td
String tableColumn = driver.findElements(By.xpath(//table Column constant));
int tableColumnCnt = getCount(tableColumn);
for (int cnt = 1; cnt <= tableRwCnt; cnt++) {
for (int listCount = 1; listCount <= tableColumnCnt; listCount++) {
String actualVal = findElement(By.xpath(tableColumn + "[" + cnt + "]/td["
+ expectedValues.get(listCount) + "]").getText();
String expectdVal = expectedValues.get(listCount);
Assert.assertEquals("Value from table doent Match", expectdVal, actualVal);
}
}
} catch (Exception e) {
// code for exception
}
}
Parameter: expectedValue = test1#test2#test4#test4 (Grid values)

jQuery Isotope 2.1 Pagination

I'm trying to paginate items using jQuery Isotope 2.1. I have a set of items which can be filtered. I'd like to be able to limit the displayed items using a range. If I want to display 10 items per page, I'd tell it show all items between 11 and 20 in the filtered set for page 2, for example.
To make matters more complex, items can be sorted as well.
Is there any way to do this?
I thought about toggling a "active" class on the filtered items, then using JS and CSS I would only show items with the "active" class that are within the current range. Not sure if that's the most efficient approach.
Thanks,
Howie
I was able to solve the problem by prototyping the _filter method.
Firstly, I call the _sort method before attempting to filter the items since sorting will affect which items are displayed on each page.
Then I added a few parameters to the options object, such as page and items_per_page. Using these two values, I can calculate the first and last item for the intended page. Even though it's not necessary for pagination, I also added a parameter called activeClass which defaults to active and is added to all matching items. In addition I added and odd-item and an even-item class to each item so that in a list view, for example, I can alternate the row colors.
Lastly, I set a property on the this object called all_matches to the entire set of filtered items. This way I can calculate the total number of pages for my pager. Then I return only the filtered items for the current page.
On the layoutComplete event, I use the page and items_per_page values from the options object in order to calculate the first and last item and update my pager.
I happen to be using Bootstrap along with a customized version of the Bootpag pager which accepts itemsPerPage and totalItems.
You can check out the codepen here. Hope it helps.
Isotope.prototype._filter = function (items)
{
//console.log('FILTER ' + arguments.callee.caller.toString());
var filter = this.options.filter;
filter = filter || '*';
var matches = [];
var all_matches = [];
var hiddenMatched = [];
var visibleUnmatched = [];
var start, end;
//console.log('page: ' + this.options.page + ' items per page: ' +
this.options.items_per_page);
start = (this.options.page - 1) * this.options.items_per_page;
end = this.options.page * this.options.items_per_page;
//console.log('start: ' + start + ' end: ' + end + ' page: ' +
this.options.page);
// we want to set the current value of filteredItems to all items
before we sort
// we must sort first becuase we need to make sure we are showing
// the correct results for each page in the correct order
this.filteredItems = items;
this._sort();
if (this.options.activeClass === undefined ||this.options.activeClass === '')
{
this.options.activeClass = 'active';
}
var test = this._getFilterTest(filter);
// test each item
for (var i = 0, len = items.length; i < len; i++)
{
//console.log('item: ' + i, $(items[i].element).find('.grid-item-title .asset-link').text(), items[i]);
var item = items[i];
if (item.isIgnored)
{
continue;
}
// add item to either matched or unmatched group
var isMatched = test(item);
// add to matches if its a match
if (isMatched)
{
all_matches.push(item);
// before we add it to the matched set, let's make sure if falls within range
// it needs to be part of the current page set otherwise we filter it out
if (all_matches.length > start && all_matches.length <= end)
{
matches.push(item);
var odd_even = (matches.length % 2 === 0) ? 'even-item' : 'odd-item';
$(item.element).addClass(this.options.activeClass + ' ' + odd_even);
} else
{
// we need to reset isMatched if we're not using it on the current page
isMatched = false;
$(item.element).removeClass(this.options.activeClass + ' odd-item even-item');
}
}
// add to additional group if item needs to be hidden or revealed
if (isMatched && item.isHidden)
{
// reveal these items
hiddenMatched.push(item);
} else if (!isMatched && !item.isHidden)
{
// hide these items
visibleUnmatched.push(item);
}
}
var _this = this;
function hideReveal()
{
_this.reveal(hiddenMatched);
_this.hide(visibleUnmatched);
}
if (this._isInstant)
{
this._noTransition(hideReveal);
} else {
hideReveal();
}
// set all matches as a property on 'this' since we'll need it later to build the pager
this.all_matches = all_matches;
return matches;
};
H

Resources