My plunker
In this plunker based on orderby in ng-repeat it is working fine but when the rowId exceeds 9 number in parent + button, the rowid becomes 10.
The parent rowid 10 is displaying as a child of 1.
Here I am separating parent and child with -.
If the rowid is child then I am adding - before child record.
Finally what I want to achieve is I want to display 10 as parent, 1-10 as child.
var newRow = {
"rowId": "1",
"componentIdentification": "",
"componentName": "",
"codigo": "",
"componentType": "",
"componentState": "",
"actionId": "",
"actionPerform": ""
}
$scope.componentList = [];
$scope.componentList.push(angular.copy(newRow));
$scope.addParentRow = function(rowId) {
var newGridRow = angular.copy(newRow);
var lastChar = getListOfSameLevel(rowId, true); //isParentRow
var parentId = rowId.length > 1 ? rowId.slice(0, rowId.length - 1) : "";
newGridRow.rowId = parentId + getNextChar(lastChar);
$scope.componentList.push(newGridRow);
}
$scope.addChildRow = function(rowId) {
var newGridRow = angular.copy(newRow);
var lastChar = getListOfSameLevel(rowId, false);
if (rowId.length === lastChar.length) {
newGridRow.rowId = rowId + "-1";
} else {
var parentId = lastChar.length > 1 ? lastChar.slice(0, lastChar.length - 1) : "";
newGridRow.rowId = parentId + getNextChar(getLastChar(lastChar));
}
$scope.componentList.push(newGridRow);
};
var getNextChar = function(inputChar) {
return parseFloat(inputChar) + 1;
};
var getLastChar = function(fullStr) {
return fullStr.slice(-1);
};
var getListOfSameLevel = function(rowId, isParentRow) {
var compIdLength = rowId.length;
var matchedArray = [];
var sortedMatchedArray = [];
var latestCompId = "";
if (compIdLength > 1) {
var parentId = isParentRow ? rowId.slice(0, rowId.length - 1) : rowId;
if (!isParentRow) {
matchedArray = _.filter($scope.componentList, function(row) {
return ((row.rowId.length >= compIdLength) && row.rowId.startsWith(parentId));
});
} else {
matchedArray = _.filter($scope.componentList, function(row) {
return ((row.rowId.length === compIdLength) && row.rowId.startsWith(parentId));
});
}
sortedMatchedArray = matchedArray.sort();
latestCompId = sortedMatchedArray[sortedMatchedArray.length - 1].rowId;
return isParentRow ? getLastChar(latestCompId) : latestCompId;
} else {
matchedArray = _.filter($scope.componentList, function(row) {
return (row.rowId.length === compIdLength || (!isParentRow && row.rowId.startsWith(rowId)));
});
sortedMatchedArray = matchedArray.sort();
latestCompId = sortedMatchedArray[sortedMatchedArray.length - 1].rowId;
return latestCompId;
}
};
The problem is a result of you sorting on rowID as a string, instead of rowID as a number.
I've added a function to return the integer value of rowID and then sort on that. It places the 10th row at the correct place in the list (after 9, not after 1), but stops incrementing at 10, so you've got other issues there you'll have to figure out.
Basically you add this function:
$scope.rowIdAsNumber = function() {
return parseInt(rowId.to);
};
And then change your repeat to orderBy that function
<tr data-node="treetable-1" id="basetr10" name="0" ng-repeat="rowData in componentList | orderBy:'rowIdAsNumber'">
I've forked your plnkr here:
https://plnkr.co/edit/Q4aQTU5CzVJ7EPUuEY4s?p=preview
Related
var allUsers = [{id:1},{id:2},{id:3},{id:4},{id:5}]
var selectedUsers = [{id:1},{id:4}]
How would I return this?
var remainingUsers = [{id:1},{id:2},{id:3},{id:4}]
Hope this will work for you
var allUsers = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]
var selectedUsers = [{ id: 4 }, { id: 1 }]
function compare(a, b) {
let comparison = 0;
if (a.id > b.id) {
comparison = 1;
} else if (a.id < b.id) {
comparison = -1;
}
return comparison;
}
selectedUsers = selectedUsers.sort(compare)
var remainingUsers = allUsers.slice(allUsers.findIndex(x => x.id == selectedUsers[0]['id']), allUsers.findIndex(x => x.id == selectedUsers[1]['id']) + 1)
console.log(remainingUsers);
You could use this approach
var allUsers = [{id:1},{id:2},{id:3},{id:4},{id:5}]
var selectedUsers = [{id:1},{id:4}]
function getRemaining(allUsers, selectedUsers){
var rem = [];
var start = false;
var stop = false;
allUsers.map((x)=>{
if(x.id == selectedUsers[0].id){ start = true; rem.push(x) }
if(x.id == selectedUsers[1].id){ stop = true; rem.push(x) }
if(start && !stop){
rem.push(x)
}
})
return rem
}
getRemaining(allUsers, selectedUsers)
I tried to make an example on your given values. please have a look.
var alluser = [{id:1},{id:2},{id:3},{id:4},{id:5}];
var selected = [{id:1},{id:4}];
var left_users = new Array();
function check_matchuser(ref_id){
var count = 0;
$(selected).each(function(key, value){
if(value.id==ref_id){
count++;
}
});
if(count>0){
return false;
}else{
return true;
}
}//end of check
$(alluser).each(function(key, usersvalue){
var check_status = check_matchuser(usersvalue.id);
if(check_status){
var temp_data = {'id' : usersvalue.id};
left_users.push(temp_data);
}
});
console.log(left_users);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
var remainingUsers = allUsers.slice(allUsers.findIndex(x=>x.id == selectedUsers[0].id),allUsers.findIndex(x=>x.id == selectedUsers[1].id)+1)
You can use slice.
var allUsers = [{id:1},{id:2},{id:3},{id:4},{id:5}]
var selectedUsers = [{id:1},{id:4}]
var remainingUsers = allUsers.slice(allUsers.findIndex(x=>x.id == selectedUsers[0].id),allUsers.findIndex(x=>x.id == selectedUsers[1].id)+1)
console.log(remainingUsers);
I'm sorry my English is not very good,Maybe you can gets the start and end subscripts and then USES the splice() method.
var allUsers = [{id:1},{id:2},{id:3},{id:4},{id:5}]
var selectedUsers = [{id:1},{id:4}]
function getBetweens(allUsers,selectedUsers){
var start = allUsers.findIndex((item)=>{
return JSON.stringify(item)==JSON.stringify(selectedUsers[0])
})
var end = allUsers.findIndex((item)=>{
return JSON.stringify(item)==JSON.stringify(selectedUsers[1])
})
betweenArray = allUsers.splice(start,end+1)
return betweenArray
}
console.log(getBetweens(allUsers,selectedUsers),'gets')
I've done some searching around the web and nothing seems to solve my problem. I have the following jQuery code:
function youtube_data_parser(data) {
//---> parse video data - start
var qsToJson = function(qs) {
var res = {};
var pars = qs.split('&');
var kv, k, v;
for (i in pars) {
kv = pars[i].split('=');
k = kv[0];
v = kv[1];
res[k] = decodeURIComponent(v);
}
return res;
}
//---> parse video data - end
var get_video_info = qsToJson(data);
if (get_video_info.status == 'fail') {
return {
status: "error",
code: "invalid_url",
msg: "check your url or video id"
};
} else {
// remapping urls into an array of objects
//--->parse > url_encoded_fmt_stream_map > start
//will get the video urls
var tmp = get_video_info["url_encoded_fmt_stream_map"];
if (tmp) {
tmp = tmp.split(',');
for (i in tmp) {
tmp[i] = qsToJson(tmp[i]);
}
get_video_info["url_encoded_fmt_stream_map"] = tmp;
}
//--->parse > url_encoded_fmt_stream_map > end
//--->parse > player_response > start
var tmp1 = get_video_info["player_response"];
if (tmp1) {
get_video_info["player_response"] = JSON.parse(tmp1);
}
//--->parse > player_response > end
//--->parse > keywords > start
var keywords = get_video_info["keywords"];
if (keywords) {
key_words = keywords.replace(/\+/g, ' ').split(',');
for (i in key_words) {
keywords[i] = qsToJson(key_words[i]);
}
get_video_info["keywords"] = {
all: keywords.replace(/\+/g, ' '),
arr: key_words
};
}
//--->parse > keywords > end
//return data
return {
status: 'success',
raw_data: qsToJson(data),
video_info: get_video_info
};
}
}
function getVideoInfo() {
var get_video_url = $('#ytdlUrl').val();
var get_video_id = getUrlVars(get_video_url)['v'];
var video_arr_final = [];
var ajax_url = "video_info.php?id=" + get_video_id;
$.get(ajax_url, function(d1) {
var data = youtube_data_parser(d1);
var video_data = data.video_info;
var player_info = data.video_info.player_response;
var video_title = player_info.videoDetails.title.replace(/\+/g, ' ');
var fmt_list = video_data.fmt_list.split(',');
var video_thumbnail_url = video_data.thumbnail_url;
var video_arr = video_data.url_encoded_fmt_stream_map;
//create video file array
$.each(video_arr, function(i1, v1) {
var valueToPush = {};
valueToPush.video_url = v1.url;
valueToPush.video_thumbnail_url = video_thumbnail_url;
valueToPush.video_title = video_title;
$.each(fmt_list, function(i2, v2) {
var fmt = v2.split('/');
var fmt_id = fmt[0];
var fmt_quality = fmt[1];
if (fmt_id == v1.itag) {
valueToPush.fmt_id = fmt_id;
valueToPush.fmt_quality = fmt_quality;
}
});
video_arr_final.push(valueToPush);
});
});
return video_arr_final;
}
function getUrlVars(url) {
var vars = {};
var parts = url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {
vars[key] = value;
});
return vars;
}
function fillInOptions(ytOptions) {
//console.log(ytOptions);
//alert(ytOptions[0]);
var ytFill = ytOptions;
console.log(ytFill);
//ytFill.forEach(function(i,v) {
var ytdlOptions = $('#ytdlOptions');
ytFill.forEach(function(i,v) {
console.log(i);
ytdlOptions.append(new Option(v.fmt_quality, v.fmt_id));
});
return true;
}
function showYTDLLoader() {
$('#ytdlInput').fadeOut(1000, function() {
$('#ytdlLoader').fadeIn(500);
});
var options = getVideoInfo();
//console.log(options);
if (fillInOptions(options) == true) {
//do rest
}
}
function showYTDLOptions() {
return true;
}
function startDownload() {
showYTDLLoader();
}
function hideYTDLLoader() {
$('#ytdlLoader').fadeOut(500);
}
function animateCSS(element, animationName, callback) {
const node = $(element);
node.addClass(animationName);
function handleAnimationEnd() {
node.removeClass(animationName);
node.animationend = null;
if (typeof callback === 'function') callback();
}
node.animationend = handleAnimationEnd();
}
When my button is clicked, I call showYTDLLoader() which gets an array of objects from the YouTube API that looks like this:
[
{
"video_url": "https://r7---sn-uxanug5-cox6.googlevideo.com/videoplayback?expire=1572496003&ei=Iw66Xa24H8PL3LUPiN25mAs&ip=2001%3A8003%3A749b%3Aa01%3A5cd8%3Ac610%3A6402%3Ad0fe&id=o-ADsVnoOoBQ6-SWzYZU7gHES06s7xQptJG6hn9WcakITY&itag=22&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-uxanug5-cox6%2Csn-ntqe6n7r&ms=au%2Crdu&mv=m&mvi=6&pl=39&initcwndbps=1655000&mime=video%2Fmp4&ratebypass=yes&dur=917.768&lmt=1572418007364260&mt=1572474311&fvip=4&fexp=23842630&c=WEB&txp=5535432&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRgIhAIp-4gyUTLoXFetbY0ha_YnR7DJqsp_MNjjIxqDdfPZJAiEA_WPd21jgX9broBcigf8rcSEVoJb2_NX7t3XZQqytsSM%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgacvP3zjEq-rVEZFrX7a_hC6TR-Zab7Ii-Fbaupjs_PcCIHdZht4l4ioYL3ERz7WNiSbnOnhm5iYxEECaQXPP2hUp",
"video_title": "Arnold Schwarzenegger on Son-in-law Chris Pratt, Pranking Sylvester Stallone & Terminator’s Return",
"fmt_id": "22",
"fmt_quality": "1280x720"
},
{
"video_url": "https://r7---sn-uxanug5-cox6.googlevideo.com/videoplayback?expire=1572496003&ei=Iw66Xa24H8PL3LUPiN25mAs&ip=2001%3A8003%3A749b%3Aa01%3A5cd8%3Ac610%3A6402%3Ad0fe&id=o-ADsVnoOoBQ6-SWzYZU7gHES06s7xQptJG6hn9WcakITY&itag=18&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-uxanug5-cox6%2Csn-ntqe6n7r&ms=au%2Crdu&mv=m&mvi=6&pl=39&initcwndbps=1655000&mime=video%2Fmp4&gir=yes&clen=44248820&ratebypass=yes&dur=917.768&lmt=1572416976690256&mt=1572474311&fvip=4&fexp=23842630&c=WEB&txp=5531432&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRQIhANTZJlBHFWQWCnfK11yvLiPUV26c6NzvqIMKjDwmsByMAiBUSy0ZJMo4GdHSiRU4xBDDLxLtzwKZAqAKCiB-1aViDQ%3D%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgacvP3zjEq-rVEZFrX7a_hC6TR-Zab7Ii-Fbaupjs_PcCIHdZht4l4ioYL3ERz7WNiSbnOnhm5iYxEECaQXPP2hUp",
"video_title": "Arnold Schwarzenegger on Son-in-law Chris Pratt, Pranking Sylvester Stallone & Terminator’s Return",
"fmt_id": "18",
"fmt_quality": "640x360"
}
]
But when I try and loop through each entry with fillInOptions(), my loop is never completed because the length is apparently zero. However, when I dump the array using console.log() it tells me the length is 2, and displays the above. I need to be able to add each option to my dropdown.
Thankyou!
UPDATE: Added full code, sorry!
It looks like your .forEach() is the root of the problem. The parameters of a forEach are currentValue, index like this: array.forEach(function(currentValue, index) {}); but it looks like you're using them in the opposite way
Try rewriting that iteration to this:
ytFill.forEach(function(v, i) {
console.log(i);
ytdlOptions.append(new Option(v.fmt_quality, v.fmt_id));
});
Notice the difference in the order of v and i in the parameters.
I have an array of objects and want to create another array of objects based on.
I want to check if an object is repeated just want to show the count, otherwise show the object itself with count = 1.
<!-- I have an array-->
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
// I want to create another array based on "arr" like the one below
var test =[{name:"coke",price:20,count:3},{name:"kabab",price:20,count:1}];
//Any hint please
This may help you. This answer considers name or some identifier will be unique for each object.
counter = {}
var arr = [{
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "kabab",
price: 250
}];
var obj = {};
var counter = {}
for (var i = 0, len = arr.length; i < len; i++) {
obj[arr[i]['name']] = arr[i];
counter[arr[i]['name']] = (counter[arr[i]['name']] || 0) + 1
}
newArr = new Array();
for (var key in obj){
newArr.push(extend( obj[key], {count:counter[key]}));
}
function extend(a, b){
for(var key in b)
if(b.hasOwnProperty(key))
a[key] = b[key];
return a;
}
console.log(newArr)
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var countNameMapping = {}, finalArr = [];
var arrLength = arr.length;
for(i=0; i<arrLength; i++){
var tempObj = {name:arr[i], price:arr[i].price, occurance:1};
var productName = arr[i].name;
if(countNameMapping[productName] === undefined){
countNameMapping[productName] = tempObj;
}else{
countNameMapping[productName].occurance += 1;
}
}
for(var k in countNameMapping){
finalArr.push(countNameMapping[k])
}
console.log(finalArr );
You can try this one:
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var result = [];
arr.map(function(arrObject) {
if (result.length > 0) {
result.map(function(resultObject) {
if (resultObject.name != arrObject.name) {
arrObject.count = 1;
result.push(arrObject);
} else {
resultObject.count++;
}
})
} else {
arrObject.count = 1;
result.push(arrObject);
}
})
console.log(result);
This will provide the result you are looking for:
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var map = arr.reduce((accum, item) => {
var obj = accum.get(item.name) || Object.assign({}, item, {count:0});
obj.count++;
return accum.set(item.name, obj);
}, new Map());
var res = [...map.values()];
More or less...
var arr = [{
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "kabab",
price: 250
}];
// I want to create another array based on "arr" like the one below
// var test =[{name:"coke",price:20,count:3},{name:"kabab",price:20,count:1}];
var count = {};
var test = [];
for (var i = 0, len = arr.length; i < len; i++) {
var id = JSON.stringify(arr[i]);
if (count.hasOwnProperty(id)) {
count[id].count++;
} else {
test.push(arr[i]); // Data contamination. Too lazy to copy object
count[id] = test[test.length - 1]; // Could be better.
count[id].count = 1;
}
}
console.log(test);
This is probably what are you looking for:
How does it work?
First, your array arr will use a forEach loop to find each object and if if new you will add it to the results array. The method isNew() will return true if the object is new.
For each new object founded you will count the number of occurrences using findOccurrences() To reduce the number of "loops" you will slice the array according to the index. So you don't need to search again over the already processed data.
So now you can build an new object, using the name, price and count.
Finally, you can push() the new object to the results array.
var arr =[{name:"coke",price:20},{price:20,name:"coke"},{name:"coke",price:20},{name:"kabab",price:250}];
var results = [];
var index = 0;
var originalDiv = document.getElementById('original');
var resultsDiv = document.getElementById('results');
arr.forEach(function(obj) {
if (isNew(obj)) {
var counter = findOccurrences(obj, arr.slice(index, arr.length));
var newObj = {
name: obj.name,
price: obj.price,
count: counter
}
results.push(newObj);
}
index++;
});
printArray(arr, originalDiv);
printArray(results, resultsDiv);
function isNew(newObj) {
var wasFound = true;
if (typeof results != "undefined" && results != null && results.length > 0) {
results.forEach(function(obj) {
if (newObj.name === obj.name && newObj.price === obj.price) {
return false;
} else {
wasFound = false;
}
});
return !wasFound;
} else {
return true;
}
}
function findOccurrences(newObj, objects) {
var count = 0;
if (typeof objects != "undefined" && objects != null && objects.length > 0) {
objects.forEach(function(obj) {
if (newObj.name === obj.name && newObj.price === obj.price) {
count++;
}
});
}
return count;
}
function printArray(objects, div) {
var count = 0;
if (typeof objects != "undefined" && objects != null && objects.length > 0) {
objects.forEach(function(obj) {
var newElement = document.createElement('p');
newElement.innerHTML = 'item ' + count + ': ';
Object.keys(obj).forEach(function(key) {
newElement.innerHTML += key + ': ' + obj[key] + ', ';
});
newElement.innerHTML = newElement.innerHTML.slice(0, -2);
div.appendChild(newElement);
count++;
});
}
}
<div id="original"><p>Original Array</p></div>
<div id="results"><p>Results Array</p></div>
Update:
More optimization.
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var accumulator = {};
var results = [];
var index = 0;
var originalDiv = document.getElementById('original');
var resultsDiv = document.getElementById('results');
String.prototype.hashCode = function() {
var hash = 0;
if (this.length == 0) return hash;
for (i = 0; i < this.length; i++) {
var char = this.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash |= 0; // Convert to 32bit integer
}
var c = (hash & 0x0FFFFFFF)
.toString(16)
.toUpperCase();
return '0000000'.substring(0, 7 - c.length) + c;
};
arr.forEach(function(obj) {
var id = JSON.stringify(obj).hashCode();
console.log(id);
if (accumulator.hasOwnProperty(id)) {
accumulator[id].count++;
} else {
results.push(obj);
accumulator[id] = results[results.length - 1];
accumulator[id].count = 1;
}
});
printArray(arr, originalDiv);
printArray(results, resultsDiv);
function printArray(objects, div) {
var count = 0;
if (typeof objects != "undefined" && objects != null && objects.length > 0) {
objects.forEach(function(obj) {
var newElement = document.createElement('p');
newElement.innerHTML = 'item ' + count + ': ';
Object.keys(obj).forEach(function(key) {
newElement.innerHTML += key + ': ' + obj[key] + ', ';
});
newElement.innerHTML = newElement.innerHTML.slice(0, -2);
div.appendChild(newElement);
count++;
});
}
}
<div id="original">
<p>Original Array</p>
</div>
<div id="results">
<p>Results Array</p>
</div>
I try to apply this example with another way. When I try it on console.log it seems run without error but when I do it on function(){}, it turns error all grid method is undefined such:
Uncaught TypeError: Cannot call method 'getView' of undefine.
The function:
onTextFieldChange = function () {
var grid = Ext.getCmp('grid'),
value = Ext.getCmp('gridfield'),
view = grid.getView(),
columns = grid.getColumns();
view.refresh();
grid.searchValue = value.getValue();
grid.matches = [];
grid.currentIndex = null;
if (grid.searchValue !== null) {
grid.store.each(function (record, index) {
var node = view.getNode(record),
count = 0;
if (node) {
Ext.Array.forEach(columns, function (column) {
var cell = Ext.fly(node).down(column.getCellInnerSelector(), true),
matches,
cellHTML,
seen;
if (cell) {
matches = cell.innerHTML.match(grid.tagsRe);
cellHTML = cell.innerHTML.replace(grid.tagsRe, grid.tagsProtect);
cellHTML = cellHTML.replace(grid.searchRegExp, function (m) {
++count;
if (!seen) {
grid.matches.push({
record: record,
column: column
});
seen = true;
}
return '<span class="' + grid.matchCls + '" style="font-weight: bold;background-color: yellow;">' + m + '</span>';
}, grid);
Ext.each(matches, function (match) {
cellHTML = cellHTML.replace(grid.tagsProtect, match);
});
// update cell html
cell.innerHTML = cellHTML;
}
});
}
});
}
};
The event:
xtype: 'textfield',
name: 'searchField',
id: 'txtfield',
hideLabel: true,
width: 200,
change: onTextFieldChange()
Any suggestions?
I answer my own question if there is none, this is onTextFieldChange() method
onTextFieldChange = function () {
var me = Ext.getCmp('grid'),
count = 0;
me.view.refresh();
me.searchValue = getSearchValue();
me.indexes = [];
me.currentIndex = null;
if (me.searchValue !== null) {
me.searchRegExp = new RegExp(me.searchValue, 'g' + (me.caseSensitive ? '' : 'i'));
me.store.each(function (record, idx) {
var td = Ext.fly(me.view.getNode(idx)).down('td'),
cell, matches, cellHTML;
while (td) {
cell = td.down('.x-grid-cell-inner');
matches = cell.dom.innerHTML.match(me.tagsRe);
cellHTML = cell.dom.innerHTML.replace(me.tagsRe, me.tagsProtect);
// populate indexes array, set currentIndex, and replace wrap matched string in a span
cellHTML = cellHTML.replace(me.searchRegExp, function (m) {
count += 1;
if (Ext.Array.indexOf(me.indexes, idx) === -1) {
me.indexes.push(idx);
}
if (me.currentIndex === null) {
me.currentIndex = idx;
}
return '<span class="' + me.matchCls + '">' + m + '</span>';
});
// restore protected tags
Ext.each(matches, function (match) {
cellHTML = cellHTML.replace(me.tagsProtect, match);
});
// update cell html
cell.dom.innerHTML = cellHTML;
td = td.next();
if (me.currentIndex !== null) {
me.getSelectionModel().select(me.currentIndex);
}
}
}, me);
}
// no results found
if (me.currentIndex === null) {
me.getSelectionModel().deselectAll();
}
};
I am currently working with example 5: http://mleibman.github.io/SlickGrid/examples/example5-collapsing.html so that I can implement collapsing in my own slickgrid. However I am having trouble doing this and was wondering if there is some tutorial I can look at or if someone has done this and can give me a few pointers. The following is some test code that I have been working with to get this to work, without a lot of luck
<script>
var grid;
var data = [];
//this does the indenting, and adds the expanding and collapsing bit - has to go before creating colums for the grid
var TaskNameFormatter = function (row, cell, value, columnDef, dataContext) {
value = value.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
var spacer = "<span style='display:inline-block;height:1px;width:" + (15 * dataContext["indent"]) + "px'></span>";
var idx = dataView.getIdxById(dataContext.id);
if (data[idx + 1] && data[idx + 1].indent > data[idx].indent) {
if (dataContext._collapsed) {
return spacer + " <span class='toggle expand'></span> " + value;
} else {
return spacer + " <span class='toggle collapse'></span> " + value;
}
} else {
return spacer + " <span class='toggle'></span> " + value;
}
};
var columns = [
{id: "title", name: "title", field: "title", width: 150, formatter: TaskNameFormatter},
{id: "duration", name: "Duration", field: "duration"},
{id: "start", name: "Start", field: "start"},
{id: "finish", name: "Finish", field: "finish"}
];
var options = {
enableColumnReorder: false
};
var searchString = "";
function myFilter(item) {
if (searchString != "" && item["title"].indexOf(searchString) == -1) {
return false;
}
if (item.parent != null) {
var parent = data[item.parent];
while (parent) {
if (parent._collapsed || (searchString != "" && parent["title"].indexOf(searchString) == -1)) {
return false;
}
parent = data[parent.parent];
}
}
return true;
}
$(function () {
var indent = 0;
var parents = [];
for (var i = 0; i < 3; i++) {
var d = (data[i] = {});
var parent;
d["id"] = "id_" + i;
if (i===0){
d["title"] = "1st Schedule";
}else if(i===1){
d["title"] = "1st Schedule Late";
}else {
d["title"] = "1st Schedule Early Leave";
}
if (i===0){
parent =null;
}
if (i===1){
parent = parents[parents.length - 1];
indent++;
}
if (i===2){
indent++;
parents.push(1);
}
if (parents.length > 0) {
parent = parents[parents.length - 1];
} else {
parent = null;
}
d["indent"] = indent;
d["parent"] = parent;
d["duration"] = "5 days";
d["start"] = "01/01/2013";
d["finish"] = "01/01/2013";
}
/* **************Adding DataView for testing ******************/
dataView = new Slick.Data.DataView();
dataView.setItems(data);
dataView.setFilter(myFilter); //filter is needed to collapse
/* ************** DataView code end ************************* */
grid = new Slick.Grid("#myGrid", dataView, columns, options);
//this toggles the collapse and expand buttons
grid.onClick.subscribe(function (e, args) {
if ($(e.target).hasClass("toggle")) {
var item = dataView.getItem(args.row);
if (item) {
if (!item._collapsed) {
item._collapsed = true;
} else {
item._collapsed = false;
}
dataView.updateItem(item.id, item);
}
e.stopImmediatePropagation();
}
});
//this is needed for collapsing to avoid some bugs of similar names
dataView.onRowsChanged.subscribe(function (e, args) {
grid.invalidateRows(args.rows);
grid.render();
});
})
</script>
I strongly suggest you to look into the grouping example instead, it's also with collapsing but is made for grouping, which is 90% of what people want and since couple months can also do multi-column grouping. You can see here the SlickGrid Example Grouping then click on these buttons (1)50k rows (2)group by duration then effort-driven (3)collapse all groups...then open first group and you'll see :)
As for your code sample, I replaced the example with your code and it works just as the example is...so?