I have a grid with a good amount of data which the user can filter or show/hide groups of columns by using combo boxes. Some of the column switches take a long time to load and I want to call setLoading(true,true) on the grid or the combobox to show the user that the browser is working.
I have a listener function that is called when the user makes a selection on the combo box. I call combo.setLoading(true,true) before starting any of the code that takes a while to execute. Then I call combo.setLoading(false,false) at the very bottom of the function.
The loading only shows up for a split second after the code between the two setLoading calls has executed. If I take out the call to remove the loading icon, the icon still only shows up after the code is executed.
Anyone have an idea what is happening? This seems very odd to me.
categorycomboselect: function(combo, records){
combo.setLoading(true,true);
var panel = combo.up('panel');
console.log(panel);
var category = records[0].data.name;
var grid = Ext.ComponentQuery.query('grid')[1];
Ext.suspendLayouts();
grid.suspendedLayout=true;
var columns = grid.columns;//.getView().getGridColumns();
//slow code that shows/hides columns
grid.suspendedLayout=false;
Ext.resumeLayouts(true);
combo.setLoading(false,false);
},
UPDATE
Here is my code with Trimboli's suggestion, it still isn't working. I'm showing/hiding the columns based on a string in their ID. I did it this way because the categories I want to show/hide the columns on are dynamic and the columns are dynamic.
categorycomboselect: function(combo, records){
combo.setLoading(true,true);
setTimeout( function(){
var panel = combo.up('panel');
var category = records[0].data.name;
var grid = Ext.ComponentQuery.query('grid')[1];
Ext.suspendLayouts();
grid.suspendedLayout=true;
var columns = grid.columns;
if(category=='All grade items'){
for(var i = 0; i< columns.length; i++){
columns[i].setVisible(true);
}
}else{
for(var i = 0; i< columns.length; i++){
columns[i].hide();//setVisible(false);
if(!(typeof columns[i].itemId ==='undefined')){
if((columns[i].itemId).indexOf(category)>=0){
columns[i].show();
}
}
}
}
grid.suspendedLayout=false;
Ext.resumeLayouts(true);
combo.setLoading(false,false);
},1);
},
Also, I wasnt sure if
Ext.suspendLayouts();
grid.suspendedLayout=true;
do the same thing or not. And if not, which is better.
What you're essentially doing is this:
showMask();
for (i = 0; i < 10000000; ++i) {
// busy loop
}
hideMask();
If you show/hide a mask without giving the browser a "break" for it to update the DOM, you won't see anything because it all gets flushed out at the end once you relinquish control back to the browser.
If you wanted to let the mask actually show, you need to give a slight delay before continuing on with your busy loop:
showMask();
setTimeout(function() {
// Busy stuff
hideMask();
}, 1);
Related
Using Google Apps Script, I generate G-Slides based on a template (first slide top left) as shown below...
...from a Google Sheet where each row has a set of attributes corresponding to its respective slide:
Furthermore, a trigger has been set to execute the Google Apps script 'On Open' (i.e. upon refreshing the document) in G-Sheet.
The script currently duplicates the first slide (the template) per rows with complete information, and feeds the variables from G-Sheet as designated in the {{brackets}} onto the template slide (i.e. the template_value matches the template_field).
function fillTemplateV3() {
// Id of the slides template
var PRESENTATION_ID = "PRESENTATION ID HERE";
// Open the presentation
var presentation = SlidesApp.openById(PRESENTATION_ID);
// Read data from the spreadsheet
var values = SpreadsheetApp.getActive().getDataRange().getValues();
// Replace template variables in the presentation with values
let hdr = values.shift()
values.forEach(row =>{
let templateSlide = presentation.getSlides()[0].duplicate()
for ( var i = 0 ; i < 4; i++){
let templateField = hdr[i]
let templateValue = row[i]
let logo = row[4]
console.log(logo)
templateSlide.replaceAllText(templateField, templateValue)
templateSlide.getShapes().forEach(s => {
if (s.getText().asString().trim() == "{{logo}}") s.replaceWithImage(logo);
});
}
}
);
}
The issue I'm having is that the script is additive, i.e. each time the script is executed it keeps on adding slides on top of those already created. I am not convinced that adding a function to delete the Slides before executing the for loop is efficient to address this issue.
How do I execute the script so that the number of slides in G-Slides correspond to the number of rows in G-Sheets? I.e. if I have 3 rows filled with information in G-Sheet, I should only have 4 slides total (counting the template slide). Right now, every-time the script executes, slides are added to the G-Slide document, so that if I add a fourth row, execute the script, and the script ran once before, I end up with 8 slides total. Instead I want to generate 4 slides, not counting the template slide.
Edited to clarify the code's objective.
I was overthinking this by a lot. I simply had to execute a for loop through my slides first, before executing the for loop to fill my G-Slide template from G-Sheets, in order to delete all slides besides the first one, which serves as my template slide:
function fillTemplate() {
// Id of the slides template
// Remember to replace this with the Id of your presentation
var PRESENTATION_ID = "YOUR PRESENTATION ID HERE";
// Open the presentation
var presentation = SlidesApp.openById(PRESENTATION_ID);
// Read data from the spreadsheet
var values = SpreadsheetApp.getActive().getDataRange().getValues();
// Replace template variables in the presentation with values
let hdr = values.shift()
var slides = presentation.getSlides();
//change i to any other index if desired
for (var i = 1; i < slides.length; i++) {
slides[i].remove()
}
values.forEach(row => {
let templateSlide = presentation.getSlides()[0].duplicate()
for (var i = 1; i < 6; i++) {
let templateField = hdr[i]
let templateValue = row[i]
let logo = row[6]
console.log(logo)
templateSlide.replaceAllText(templateField, templateValue)
templateSlide.getShapes().forEach(s => {
if (s.getText().asString().trim() == "{{logo_url}}") s.replaceWithImage(logo);
});
}
});
}
Credit to the answer of this post for helping me find a solution: How to delete slides programmatically after the nth one in google slides?
I have these sections on this side scrolling site. And want to add a class which will change styling depending if you're on a certain section.
I'm working on this function. The top is what determines the section of the side scroller you are viewing.
The let variables and below is where it stops working. I'm trying to have it so if a nonHome ID section is clicked, for example "slide-1", then add the class 'nav-visibilty'. If they are a match "slide-2" and "slide-2" then remove said class. Am I close?
https://codepen.io/mikayp-the-styleful/pen/NWPxoXR?editors=1111
setTimeout(function(){
for (i=0; i < nonHome.length; i++ ){
if (nonHome[i].id != nonHomeID){
nonHome[i].classList.add("nav-visibility");
console.log('add')
} else{
nonHomeID.classList.remove("nav-visibility");
console.log('rem')
}
}
I am still not totally clear on the behavior that you want, but there are two errors in the code that can be fixed:
It seems like you are always using 'slide-2' instead of the slideId in your event handler.
As mentioned in a comment, nonHomeID is being used incorrectly in your comparison (it is either a string or an element, but you are using it as if it was a string in the if condition, and as the element in the else branch.) Here I have kept it as an element and renamed it for clarity.
Fixing these errors results in code that applies the nav-visibility class to all slides except the one selected by the button. Is that the desired behavior?
let nonHome = document.querySelectorAll(".slide-container section");
let nonHomeSelected = document.getElementById(slideId);
var i;
setTimeout(function() {
for (i = 0; i < nonHome.length; i++) {
if (nonHome[i] != nonHomeSelected) {
nonHome[i].classList.add("nav-visibility");
console.log("add");
} else {
nonHome[i].classList.remove("nav-visibility");
console.log("rem");
}
}
}, 1000);
Edit to add: If the goal is to add nav-visibility to all only the specific slideId, you should not be adding in a loop, i.e. you need to pull your check for whether the slide is Home outside the loop. There are conceptually two steps here: remove the class from all elements that are no longer to have it, then add the class to the element that needs it.
let slideToAddVisibilityTo = document.getElementById(slideId)
let homeSlide = document.getElementById('slide-2')
let allSlides = document.querySelectorAll(".slide-container section")
for (let i = 0; i < allSlides.length; ++i)
allSlides[i].classList.remove('nav-visiblity')
if (slideToAddVisibilityTo != homeSlide)
slideToAddVisibilityTo.classList.add('nav-visibility')
Just hide them all, then show the clicked one:
function showSection(id) {
var sections = document.getElementsByTagName("section");
for(var i=0; i<sections.length; i++) sections[i].classList.remove("nav-visibility");
var current = document.getElementById(id);
current.classList.add("nav-visibility");
}
Example: showSection("foo") will remove nav-visibility from all sections, then add it to the section with id foo.
so I am trying to create a etch-a-sketch and I need to generate multiple divs (i.e. little squares) based on the users input. So for instance the option is how many pixels do you want the grid size to be from 1 - 50 and based on the answer (say 30) I need to make a grid with that many squares on each side. The issue is that I can only get that many squares as a row at the top and not as a grid. Linked is my code and also shown is my javascript code which is the one giving me issues. The HTML/CSS are mostly just styling, but they are shown in the link. I am not sure what I am doing wrong because I am using someone else's code as reference and it seems to work for them, but not for me.
https://codepen.io/faar23/pen/qjZgQY
$(document).ready(function(){
/*for (var i = 0; i < 24; i ++) {
$('#workspace').append('<div class = "row"></div>');
$('.row').height(27);
};*/
/*for now i am going to leave the above code commented out but what it
does is instantly creates 24 boxes on the workspace
and without this, the space is empty. I am commenting it out to see if the
.height function will wor down below...doesnt seem to*/
/*the above loop generates 24 divs dynamically without having to copy paste
in html. the .height sets the height of the divs.
the width is set in the css under myId. this was done using this tutorial
https://www.youtube.com/watch?v=dtgx_twX-a4 + inspecting
the elements on this project https://beachfern.github.io/sketchpad/*/
$('#mainButton').mouseenter(function(){
$('#mainButton').addClass('highlight');
});
$('#mainButton').mouseleave(function(){
$('#mainButton').removeClass('highlight');
});
/*the above code makes the main start button change color when the mouse
enters it*/
$('.buttonhide').hide();
$('#mainButton').click(function(){
$('.buttonhide').show();
});
/*the above code hides the rest of the buttons until the main button is
clicked, then all the buttons show themselves*/
$('#mainButton').on('click', function(){
var workspaceSize = prompt("How many boxes should make up the canvas? (1
to 50)", "24");
/*i am going to use this user's way and see if that works better for me
https://stackoverflow.com/questions/25518243/creating-div-grid-with-
jquery-for-loop*/
if(workspaceSize > 0 && workspaceSize <= 50){
$('#workspace').empty();
for (var i = 0; i < workspaceSize; i++){
$('#workspace').append('<div class = "row"></div>');
};
for (var x = 0; x < workspaceSize; x++){
$('.row').append('<div class = "column"></div>');
};
$('.row').height(700 / workspaceSize);
$('.column').height(700 / workspaceSize);
$('.column').width(700 / workspaceSize);
}; /*very imp closing bracket. shit doesnt work without it*/
});
});
You need to nest the two for loops, so that for each row it creates the columns.
This might work, or lead you in the right direction:
for(var i = 0; i < workspaceSize; i++){
$('#workspace').append('<div class="row" id=row'+i+'></div>');
for(var j = 0; j < workspaceSize; j++){
$('#row'+i).append('<div class="column"></div>')
}
}
I am trying to get a value of a cell in a html table within JavaScript. I can do this when the row is clicked twice or when I click on a row and then another row but I need to get the cell value on first click
This is my code so far
var table = document.getElementById('ContentPlaceHolder1_htmltable');
if (table != null) {
for (var i = 0; i < table.rows.length; i++) {
for (var j = 0; j < table.rows[i].cells.length; j++)
table.rows[i].cells[j].onclick = function () {
cellvalue = this.innerHTML;
};
}
}
This runs on an onclick event on the ASPxListBox object from devexpress I am using.
Note: I can't use third party libraries like jQuery for this.
Thanks
The jsfiddle code posted by arcade Gandalf above does work, however, to fix my problem of getting the cell value on first click, the code needs to run when the page load is complete
window.onload = getCellValueOfTable;
function getCellValueOfTable {
jsFiddle code or my code posted above...
}
Then in the onclick event for the listbox or a table as I described in the question, just call the above function and that is all.
I have large tables being generated and each row has a checkbox, class "chcktbl".
In the table header, there is a Select All checkbox, class "chckHead".
The select/deselect all function works fine, as does the count of selected charts I have displayed in the table heading.
The function to enable shift+click capability to select a range of checkboxes also works, but in its current format, only selects 10 checkboxes before generating an error message in a popup window:
"Stop running this script? A script on this page is causing your web browser to run slowly. If it continues to run, your computer might become unresponsive."
<script type=text/javascript>
//select all button
$('#chckHead').click(function() {
if (this.checked === false) {
$('.chcktbl:checked').attr('checked', false);
}
else {
$('.chcktbl:not(:checked)').attr('checked', true);
}
countSelected();
});
//count number of boxes checked
function countSelected() {
var numCharts = $('input.chcktbl:checked').length;
$('#numCharts').html(numCharts);
}
//SHIFT+Click to select a range of checkboxes:
// this variable stores the most recently clicked checkbox
// it is used for shift-clicks
var lastClickedBox = 0;
// the checkbox functionality is default to the browser
$('.chcktbl').click(function(event) {
var clickedBox = $('.chcktbl').index(event.target);
if(event.shiftKey) {
setCheckboxes(lastClickedBox, clickedBox);
};
lastClickedBox = clickedBox;
countSelected();
});
// sets all the checkboxes between the specified indices to true
function setCheckboxes(end, start) {
if(start > end) {
var temp = start;
start = end;
end = temp;
};
for(var i = start; i < end; i++) {
$('.chcktbl').eq(i).prop('checked', true);
};
countSelected();
};
</script>
This is a really common feature for selecting a range of items with one click, but I can't find an efficient way to do it. If anyone knows a better way of approaching this or can spot some inefficiency in the code then please let me know.
How about using jquery nextUntil?
I didn't actually test this but this should give you the basic idea and it removes the for loop. I created similar functionality to this before using nextUntil/prevUntil and never got an unresponsive page.
function setCheckboxes(end, start) {
if(start > end) {
var temp = start;
start = end;
end = temp;
};
$('.chcktbl').eq(start).nextUntil(':eq('+(end+1)+')').add().prop('checked', true);
countSelected();
};
I tried you code and it worked well for me. You might want to try this jquery plugin
https://gist.github.com/DelvarWorld/3784055