kendoDropDownList loading bar not showing - kendo-ui

I am using a dropDownList to show some values in order to filter results on a grid.
I have use the 'change' event to see when the grid must be updated
$('#view-mode-selector').kendoDropDownList({
change: onMChange
});
in the method onMChange I am trying to show the progress bar with
kendo.ui.progress($("#grid), true);
and at the end of the method when all is done I have
kendo.ui.progress($("#grid), false);
But the data loads and I do not see the progress bar.
If I remove the last statement (the 'false' one) I can see the progress bar, but it never disappears.
If I debug, It appears and disappears when the data is ready.
It is not an issue of the data loading too fast, sometimes the data takes 5 seconds to be ready.
The data is already in the browser, I am just showing or hiding columns.
Kendo version v2016.2.714
Thanks
EDIT
on onMChange I have some ifs where I populate an array (columnsToShow) with the name of the columns I want to show (everything else will be hidden) then I call a function with this code:
showHideColumn: function(columnsToShow) {
var grid = $(this.gridId).data("kendoGrid");
var show = false;
for (var i = 0; i < grid.columns.length; i++) {
show = false;
if (columnsToShow.length > 0) {
for (var j = 0; j < columnsToShow.length; j++) {
if (columnsToShow[j] == grid.columns[i].field) {
grid.showColumn(i);
columnsToShow.splice(j, 1);
show = true;
break;
}
}
}
if (!show) {
grid.hideColumn(i);
}
}
}
That code seems to be very inefficient at hiding/showing columns, all activity stops for few seconds when I want to show all columns (after having hidden some), I have around 30 columns and 30 rows.

Your question is a little misleading. Is the #grid element you are having difficulty displaying the loading icon for a grid control (as per the name of the element) or a drop down control (as per the title of the question)?
If grid
In order to show the loading icon I used:
kendo.ui.progress($("#grid").data("kendoGrid").element, true);
And to hide:
kendo.ui.progress($("#grid").data("kendoGrid").element, false);
If drop down
I haven't had to force display loading icons for dropdowns however there is an example here, noting the comment specifying:
The element must have a position:relative style applied
Additionally further down, it is noted that the element cannot have child elements.

Related

HandsonTable not rendering all rows

HandsonTable is not rendering all rows - it loads only part of all rows. But when I do Ctrl+A and paste into Excel I see all the rows. Why is Handsontable not displaying all the rows?
<hot-table col-headers="true" row-headers="true" datarows="data" context-menu width="1080">
<hot-column ng-repeat="column in columns" data="{{column.data}}"></hot-column>
</hot-table>
To render all rows, just set renderAllRows: true
The current answer does not answer the original question.
Handsontable does not render all cells at once because it is designed to be efficient for very large data sets. It does this using virtual rendering, dynamically modifying the DOM to include only the cells at the scroll position.
The rows virtual rendering can be disabled by setting renderAllRows: true, as described in the docs: "If typed true then virtual rendering mechanism for handsontable will be disabled." Although it will then not be as efficient for large data sets.
You can also change the number of pre-rendered rows and columns instead of rendering them all. From the performance tips,
You can explicitly specify the number of rows and columns to be rendered outside of the visible part of the table. In some cases you can achieve better results by setting a lower number (as less elements get rendered), but sometimes setting a larger number may also work well (as less operations are being made on each scroll event). Tweaking these settings and finding the sweet spot may improve the feeling of your Handsontable implementation.
This is done by setting viewportRowRenderingOffset and viewportColumnRenderingOffset in the handsontable options. These are by default set to auto which lets handsontable try to find the best value, but may be provided an integer value (e.g. viewportRowRenderingOffset: 70, viewportColumnRenderingOffset: 70).
I had the same problem (using HandsOnTable 6.2.1 and the old AngularJS) and customers would start complaining about not being sure if they were at the end of the table or not.
I was able to create two buttons linked to the functions 'scrollToBeginning' and 'scrollToEnd'. This way the user is sure to be at the last line. Three things specific about my answer:
I expose the functions to the DOM using $scope;
I have an object 'goToLine' holding 3 properties (scrollingToEnd: boolean, row: number, col: number), it is used in other functions not posted here;
I have a list of ID referencing HandsOnTable objects stored in $scope.hots.
Here is my raw solution, feel free to adapt / enhance:
$scope.stopScrollingToEnd = function () {
$scope.goToLine.scrollingToEnd = false;
};
$scope.scrollToBeginning = function (goToLine) {
$scope.stopScrollingToEnd();
const hot = $scope.hots[goToLine.id];
hot.scrollViewportTo(0, 0);
};
/**
* Scroll to the end of the List Element.
* We need this functionality because of a bug in HandsOnTable related to its Virtualization process.
* In some cases (complex table), when manually scrolling, the max row is wrong, hence causing major confusion for the user.
* #param {*} goToLine
* #returns
*/
$scope.scrollToEnd = function (goToLine) {
// We scroll to the first line before going to the last to avoid the bug and being sure we get to the last line
$scope.scrollToBeginning(goToLine);
const hot = $scope.hots[goToLine.id];
var numberOfRows = hot.countRows();
// This variable is used to repeat the scrollViewportTo command.
// It is built using the length of `numberOfRows`.
var repeat = numberOfRows ? 1 * Math.ceil(Math.log10(numberOfRows + 1)) : 1;
// Used in other goTo function to avoid conflict.
$scope.goToLine.scrollingToEnd = true;
// FIXME : not supposed to call scrollViewportTo several times... => fixed in recent versions of HandsOnTable ?
for (let n = 0; n < repeat; n++) {
if (!$scope.goToLine.scrollingToEnd) {
return;
}
setTimeout(function () {
if (!$scope.goToLine.scrollingToEnd) {
return;
}
hot.scrollViewportTo(numberOfRows - 1, 0);
}, 500);
}
};

How to indent the first line of a paragraph in CKEditor

I'm using CKEditor and I want to indent just the first line of the paragraph. What I've done before is click "Source" and edit the <p> style to include text-indent:12.7mm;, but when I click "Source" again to go back to the normal editor, my changes are gone and I have no idea why.
My preference would be to create a custom toolbar button, but I'm not sure how to do so or where to edit so that clicking a custom button would edit the <p> with the style attribute I want it to have.
Depending on which version of CKE you use, your changes most likely disappear because ether the style attribute or the text-indent style is not allowed in the content. This is due to the Allowed Content Filter feature of CKEditor, read more here: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
Like Ervald said in the comments, you can also use CSS to do this without adding the code manually - however, your targeting options are limited. Either you have to target all paragraphs or add an id or class property to your paragraph(s) and target that. Or if you use a selector like :first-child you are restricted to always having the first element indented only (which might be what you want, I don't know :D).
To use CSS like that, you have to add the relevant code to contents.css, which is the CSS file used in the Editor contents and also you have to include it wherever you output the Editor contents.
In my opinion the best solution would indeed be making a plugin that places an icon on the toolbar and that button, when clicked, would add or remove a class like "indentMePlease" to the currently active paragraph. Developing said plugin is quite simple and well documented, see the excellent example at http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1 - if you need more info or have questions about that, ask in the comments :)
If you do do that, you again need to add the "indentMePlease" style implementation in contents.css and the output page.
I've got a way to indent the first line without using style, because I'm using iReport to generate automatic reports. Jasper does not understand styles. So I assign by jQuery an onkeydown method to the main iframe of CKEditor 4.6 and I check the TAB and Shift key to do and undo the first line indentation.
// TAB
$(document).ready(function(){
startTab();
});
function startTab() {
setTimeout(function(){
var $iframe_document;
var $iframe;
$iframe_document = $('.cke_wysiwyg_frame').contents();
$iframe = $iframe_document.find('body');
$iframe.keydown(function(e){
event_onkeydown(e);
});
},300);
}
function event_onkeydown(event){
if(event.keyCode===9) { // key tab
event.preventDefault();
setTimeout(function(){
var editor = CKEDITOR.instances['editor1'], //get your CKEDITOR instance here
range = editor.getSelection().getRanges()[0],
startNode = range.startContainer,
element = startNode.$,
parent;
if(element.parentNode.tagName != 'BODY') // If you take an inner element of the paragraph, get the parentNode (P)
parent = element.parentNode;
else // If it takes BODY as parentNode, it updates the inner element
parent = element;
if(event.shiftKey) { // reverse tab
var res = parent.innerHTML.toString().split(' ');
var aux = [];
var count_space = 0;
for(var i=0;i<res.length;i++) {
// console.log(res[i]);
if(res[i] == "")
count_space++;
if(count_space > 8 || res[i] != "") {
if(!count_space > 8)
count_space = 9;
aux.push(res[i]);
}
}
parent.innerHTML = aux.join(' ');
}
else { // tab
var spaces = " ";
parent.innerHTML = spaces + parent.innerHTML;
}
},200);
}
}

Programatically updating underlying data in Slickgrid

I have 6 textboxes at the top of the screen that update an entire column(one textbox per column) based on any changes. I was selecting the columns based on their class (.l#). Here is the code (issues to follow):
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = [".l1", ".l7", ".l8", ".l9"];
var fields = $(bound[id]);
for (var i = 0; i < fields.length; i++)
{
fields[i].innerHTML = $(ctrl).val();
}
};
which is bound to the keyup event for the text areas. Issues are:
1) initially fields.length was -1 as I didn't want to put data in the "add new
row" section at the bottom. However, when running it, I noticed the
final "real" record wasn't being populated. Also, when stepping through, I
noticed that the "new row" field was before the "last row" field.
2) when doing it this way, it is purely superficial: if I double click the field,
the real data hasn't been changed.
so in the grand scheme of things, I know that I was doing it wrong. I'm assuming it involves updating the data and then forcing a render, but I'm not certain.
Figured out how to do it. Modified the original code this way:
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = ['title1', 'title2', 'title3', 'title4'];
var field = bound[id];
for (var i = 0; i < dataView.getLength(); i++)
{
var item = dataView.getItem(i);
item[field] = $(ctrl).val();
dataView.updateItem(i, item);
}
grid.invalidate();
};
I have 6 textboxes (item1-item6) that "bind" to fields in the sense that if I change data in a textbox, it updates all of the rows and any new rows added also have this data.
Parts where the two issues can be explained this way:
1) to work around that, though still it would be a presentational fix and not a real updating of the underlying data, one could force it to ignore if it had the active class attached. Extra work, and not in the "real" direction one is going for (masking the field).
2) It was pretty obvious with the original implementation (though it was all I could figure out via Chrome Dev Tools that I could modify at the time) that it was merely updating a div's content and not actually interacting with the data underneath. Would look nice, and perhaps one could just pull data from the item1-item6 boxes in place of the column if it is submitted, but if someone attempts to modify the cell, they'll be looking at the real data again.

How to dynamically load carousel items in Sencha

I have a problem with my product view. I want to display product data. each product is a "box" with an image and text. I want to display six products on a panel. As of the fact that i have many products i want to have a "carousel like view". My idea was the following: Place 6 products on a panel. Load 3 panels and place each panel as a carousel item so that i can swipe to get to another "page".
To save performance I tried to always have only 3 items in the carousel. The active "page" and the page before, and the page after, so that I can swipe to left/right and the next page can be loaded.
I tried to put my logic in the "onActiveItemChange"-Listener of the carousel, but I had massive problems with adding/removing carousel items. So my Question is is it possible to do what i want to accomplish?
Is there a better alternative? Of course my data is in a store, but I don't want that standard list view.
Another Question: Because my first attempt with the carousel failed i tried to build a Ext.Container (card layout) with the panels on it. But how can I listen to a swipe event on a Panel???
thanks for help ;-)
Even I am doing the same, using carousel & a store. Every page of carousel is a view(panel) which would have 4/6 child views(panels). On store load I am creating those children and then divide them into pages and add those pages to carousel.
This is working fine for me and on activeItemChange I am loading more pages:
activeitemchange: function(container, value, oldValue, eOpts) {
var activeItemIndex = container.getActiveIndex();
var galleryTotal = container.getInnerItems() ? container.getInnerItems().length : 0;
if ((activeItemIndex + 1 == galleryTotal)) {
console.log("At last page, time to load");
var store = this.config.store;
store.nextPage({ addRecords: true });
}
}
I think I understand your issue. Assuming you've got 3 items and you're always viewing the middle one (as you move forward, item 0 gets destroyed and one item gets created). And assuming that each item has an id associated with its location in the list.
var current_item = Ext.getCmp('carousel_name').getActiveItem().getId();
current_item = Number(current_item.replace('item', ''));
//Objects to create
var next_item = current_item + 1;
var previous_item = current_item - 1;
//Objects to destroy
var next2_item = current_item + 2;
var previous2_item = current_item - 2;
//Create items
var createItem = function(item_location, type){
var carousel_item = create_content(item_location);
if(type == 'next'){
Ext.getCmp('carousel_name').add(carousel_item);
}else if(type == 'previous'){
Ext.getCmp('carousel_name').insert(0, carousel_item);
Ext.getCmp('carousel_name').setActiveItem(1);
}
}
createItem(next_item,'next');
createItem(previous_item,'previous');
//Destroy items
if(Ext.getCmp('item'+previous2_item)){
Ext.getCmp('carousel_name').getItems().items[0].destroy();//This is a hack, for some reason with the above commented out line, the item was getting destroyed but wasn't being removed from carousel_name
}
if(Ext.getCmp('item'+next2_item)){
Ext.getCmp('carousel_name').getItems().items[Ext.getCmp('carousel_name').getMaxItemIndex()].destroy();//This is a hack, consistency with previous destroy (above)
}

Restyling dynamically styled SlickGrid cells after Sort

Ok, let me explain my scenario more clearly:
When a cell is edited, it becomes 'dirty' and I style it a certain way by adding a CSS class to the cell via javascript.
Then, if the user Sorts the grid, the styling is lost (I believe because all the rows are recreated) and I need a way to restore the styling to the appropriate cell/row after a Sort.
What I attempted to do is add an entry into data[] called 'status' and onCellChange I loop through data[] and match the args.item.Id to appropriate entry in data[].
grid.onCellChange.subscribe(function (e, args) {
var done = false;
for (var i = 0; i < data.length && !done; i++) {
if (data[i].id == args.item.id) {
data[i].status = "dirty";
done = true;
}
}
}
However, onSort I'm not sure how to match the sorted rows to the data array. (Since I have no args.item) I've attempted to do selector statements:
$(".slick-row")
to restyle the correct cells, but I have no way to associate the rows with their entry in data[].
1) There is no need to search for the item in your onCellChange handler - it is available at "args.item".
2) Sorting the "data" array will not wipe out your change to the item in #1.
3) You mention dynamically styling cells. I see no code for that. If your custom formatter is the piece of code that looks at "item.status" and renders it differently if it is dirty, then you don't have to do anything extra. Sorting the data and telling the grid to re-render will preserve the "dirty" cell styles.

Resources