Possible to make jqGrid stretch to 100%? - javascript

Is it possible to make it so that a jqGrid will have a width set to 100%? I understand that column widths must be an absolute pixel size, but I've yet to find anything for setting the width of the actual grid to a relative size. For instance, I want to set the width to 100%. Instead of 100% it seems to use an odd size of 450px. There is more horizontal room on the page, but with the columns width and such, it will make the container(of only the grid) horizontally scroll. Is there some way around this?

autowidth: true from 3.5 onwards

It works for me:
width: null,
shrinkToFit: false,

I'm using this to set the width of the grid to the width of the parent container.
function resizeGrid() {
var $grid = $("#list"),
newWidth = $grid.closest(".ui-jqgrid").parent().width();
$grid.jqGrid("setGridWidth", newWidth, true);
}

I ended up using the jqGrids.fluid extension to do this and it worked great.
UPDATE: That link seems to be dead, but the archived article can be viewed here.

You can try to fix the width of jqGrid with respect of a function which I described here Correctly calling setGridWidth on a jqGrid inside a jQueryUI Dialog

wonderful function for this i found here (stackoverflow) cannot remember the post. I have the height portion commented out keep that in mind (was not working for me) but the width is perfect. throw this anywhere in your php file.
$resize = <<<RESIZE
jQuery(window).resize(function(){
gridId = "grid";
gridParentWidth = $('#gbox_' + gridId).parent().width();
$('#' + gridId).jqGrid('setGridWidth',gridParentWidth);
// $('#' + gridId).jqGrid('setGridHeight', //Math.min(500,parseInt(jQuery(".ui-jqgrid-btable").css('height'))));
})
RESIZE;

Try to set width to "null". It works for me.
$(grid).jqGrid({
width: null,
});

It looks like this is not supported. According to the docs for setGridWidth:
Sets a new width to the grid dynamically. The parameters are:
new_width is the new width in pixels...
The docs for the width option also do not mention being able to set width as a percentage.
That being said, you can use the autowidth feature or a similar technique to give the grid the correct initial width. Then follow the methods discussed in resize-jqgrid-when-browser-is-resized to ensure the grid is properly resized when the browser window is resized, which will simulate the effect of having 100% width.

loadComplete : function () {
$("#gridId").jqGrid('setGridWidth', $(window).width(), true);
},

Simpler
$("#gridId").setGridWidth($(window).width() );

Try this,
Replace width: 1100 to autowidth: true,

You can't give width in percent, while if you want according to screen resolution then set as follows:
var w = screen.width
and then use this variable in width option of jqgrid.
Hope it will useful.

I have done this and working like charm.
$(document).ready(function () {
$("#jQGridDemo").setGridWidth(window.innerWidth - offset);
});
I have put offset of 50

I've noticed that only the combination of all 3 answers given, i.e. JohnJohn's answer,
Bhargav's answer and
Molson's answer helped me to achive a real automatic resize.
So I have created some code that takes advantage of all, see the snippet below. I've also improved it so you can either pass a single grid object or an array of grids to be resized.
If you try it out ensure that you
click on Run code snippet, and
then click on the "Full page" link button in the upper right corner.
Resize the window and watch how the grids changes their size and re-align automatically:
// see: https://free-jqgrid.github.io/getting-started/
// CDN used: https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid
$(function() {
// pass one single grid, or an array of grids
function resizeGrid(jqGridObj) {
var $gridArray = Array.isArray(jqGridObj) ? jqGridObj : [jqGridObj];
for(let i=0; i<$gridArray.length; i++) {
var $grid=$gridArray[i],
newWidth = $grid.closest(".ui-jqgrid").parent().width();
$grid.jqGrid("setGridWidth", newWidth, true);
}
};
// template for the 2 grids
function createGrid(gridName, gridData) {
var gridObj=$("#"+gridName); gridObj.jqGrid({
autowidth: true, height: 45,
colNames: ['First name', 'Last name', 'Updated?'],
colModel: [{name: "firstName"}, {name: "lastName"}, {name: "updated"}],
data: gridData,
loadComplete: function() {
// resize on load
resizeGrid(gridObj);
}
});
return gridObj;
}
// instantiate Grid1
var data1 = [
{ id: 10, firstName: "Jane", lastName: "Doe", updated: "no"},
{ id: 20, firstName: "Justin", lastName: "Time", updated: "no" }
];
var gridObj1=createGrid("grid1", data1);
// instantiate Grid2
var data2 = [
{ id: 10, firstName: "Jane", lastName: "Smith", updated: "no"},
{ id: 20, firstName: "Obi-Wan", lastName: "Kenobi", updated: "no" }
];
var gridObj2=createGrid("grid2", data2);
function debounce(fn, delay) {
delay || (delay = 200);
var timer = null;
return function () {
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
};
}
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 200);
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
// change size with window for both grids
jQuery(window).resize(throttle(function(){
resizeGrid([gridObj1, gridObj2]);
}));
});
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>Resizing jqGrid example</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/redmond/jquery-ui.min.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.2/css/ui.jqgrid.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.2/jquery.jqgrid.min.js"></script>
<table id="grid1"></table>
<br/>
<table id="grid2"></table>
Note: While this example is simple, if you have more complex jqGrids you will need throttling or debouncing (the 2 functions throttle and debounce are taken from there), otherwise the resize event could be really slow. Follow the link to read more about it. I prefer throttling in this case because it looks smoother, but I have included both functions so you can use them if needed in your code.
In my real code I needed throttling, otherwise resizing was getting far too slow. The code snippet already includes a throttled handler with a default threshold of 200ms. You can experiment with it, for example if you replace throttle by debounce in the code snippet, i.e.
jQuery(window).resize(debounce(function(){
resizeGrid([gridObj1, gridObj2]);
}));

Related

Add javascript to Wordpress loop with class selection

I would like to add category icons to a Wordpress page, each icon animated with snap.svg.
I added the div and inside an svg in the loop that prints the page (index.php). All divs are appearing with the right size of the svg, but blank.
The svg has a class that is targeted by the js file.
The js file is loaded and works fine by itself, but the animation appears only in the first div of that class, printed on each other as many times it is counted by the loop (how many posts there are on the actual page from that category).
I added "each()" and the beginning of the js, but is not allocating the animations on their proper places. I also tried to add double "each()" for the svg location and adding the snap object to svg too, but that was not working either.
I tried to add unique id to each svg with the post-id, but i could not pass the id from inside the loop to the js file. I went through many possible solutions I found here and else, but none were adaptable, because my php and js is too poor.
If you know how should I solve this, please answer me. Thank you!
// This is the js code (a little trimmed, because the path is long with many randoms, but everything else is there):
jQuery(document).ready(function(){
jQuery(".d-icon").each(function() {
var dicon = Snap(".d-icon");
var dfirepath = dicon.path("M250 377 C"+ ......+ z").attr({ id: "dfirepath", class: "dfire", fill: "none", });
function animpath(){ dfirepath.animate({ 'd':"M250 377 C"+(Math.floor(Math.random() * 20 + 271))+ .....+ z" }, 200, mina.linear);};
function setIntervalX(callback, delay, repetitions, complete) { var x = 0; var intervalID = window.setInterval(function () { callback(); if (++x === repetitions) { window.clearInterval(intervalID); complete();} }, delay); }
var dman = dicon.path("m136 ..... 0z").attr({ id: "dman", class:"dman", fill: "#222", transform: "r70", });
var dslip = dicon.path("m307 ..... 0z").attr({ id: "dslip", class:"dslip", fill: "#196ff1", transform:"s0 0"});
var dani1 = function() { dslip.animate({ transform: "s1 1"}, 500, dani2); }
var dani2 = function() { dman.animate({ transform: 'r0 ' + dman.getBBox().cx + ' ' + dman.getBBox(0).cy, opacity:"1" }, 500, dani3 ); }
var dani3 = function() { dslip.animate({ transform: "s0 0"}, 300); dman.animate({ transform: "s0 0"}, 300, dani4); }
var dani4 = function() { dfirepath.animate({fill: "#d62a2a"}, 30, dani5); }
var dani5 = function() { setIntervalX(animpath, 200, 10, dani6); }
var dani6 = function() { dfirepath.animate({fill: "#fff"}, 30); dman.animate({ transform: "s1 1"}, 100); }
dani1(); }); });
I guess your error is here:
var dicon = Snap(".d-icon");
You are passing a query selector to the Snap constructor, this means Snap always tries to get the first DOM element with that class, hence why you're getting the animations at the wrong place.
You can either correct that in two ways:
Declare width and height inside the constructor, for example var dicon = Snap(800, 600);
Since you are using jQuery you can access to the current element inside .each() with the $(this) keyword. Since you are using jQuery instead of the dollar you could use jQuery(this).
Please keep in mind this is a jQuery object and probably Snap will require a DOM object. In jQuery you can access the dom object by appending a [0] after the this keyword. If var dicon = Snap( jQuery(this) ); does not work you can try with var dicon = Snap( jQuery(this)[0] );
Additionally, you have several .attr({id : '...', in your code. I assume you are trying to associate to the paths an ID which are not unique. These should be relatively safe since they sit inside a SVG element and I don't see you are using those ID for future selection.
But if you have to select those at a later time I would suggest to append to these a numerical value so you wont have colliding ID names.

How to make the Chart.js animate when scrolled to that section?

I am trying to use the pie chart from Chart.js (http://www.chartjs.org/docs/#pieChart-exampleUsage). Everything works smooth, but the animation happens as soon as the page loads, but since the user has to scroll down to see the chart, they won't see the animation. Is there anyway I can make the animation to start only when scrolled to that position? Also if possible, is it possible to animate everytime when that chart becomes into view?
My code is as follows:
<canvas id="canvas" height="450" width="450"></canvas>
<script>
var pieData = [
{
value: 30,
color:"#F38630"
},
{
value : 50,
color : "#E0E4CC"
},
{
value : 100,
color : "#69D2E7"
}
];
var myPie = new Chart(document.getElementById("canvas").getContext("2d")).Pie(pieData);
</script>
You can combine the check for whether something is viewable with a flag to keep track of whether the graph has been drawn since it appeared in the viewport (though doing this with the plugin bitiou posted would be simpler):
http://jsfiddle.net/TSmDV/
var inView = false;
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemTop <= docViewBottom) && (elemBottom >= docViewTop));
}
$(window).scroll(function() {
if (isScrolledIntoView('#canvas')) {
if (inView) { return; }
inView = true;
new Chart(document.getElementById("canvas").getContext("2d")).Pie(data);
} else {
inView = false;
}
});
Best to use deferred plugin
https://chartjs-plugin-deferred.netlify.com/
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-deferred#1"></script>
new Chart(ctx, {
// ... data ...
options: {
// ... other options ...
plugins: {
deferred: {
xOffset: 150, // defer until 150px of the canvas width are inside the viewport
yOffset: '50%', // defer until 50% of the canvas height are inside the viewport
delay: 500 // delay of 500 ms after the canvas is considered inside the viewport
}
}
}
});
I don't know if you could do that, I had the same issue and resolved it without any plugin in this simple way, check out:
$(window).bind("scroll", function(){
$('.chartClass').each(function(i){
var dougData = [
{value: 100, color:"#6abd79"},
{value: 20, color:"#e6e6e6"}
];
var graphic = new Chart(document.getElementById("html-charts").getContext("2d")).Doughnut(dougData, options);
$(window).unbind(i);
});
});
I had the same problem with Chart.js and found a really great solution.
There is a package on GitHub that is called ChartNew.js by FVANCOP.
He expanded it and added several functions.
Look at the sample, the charts are drawn by scrolling down.
Responsible is the statement
dynamicDisplay : true
Using IntersectionObserver is the more modern approach, and gives you the ability to choose how much of the element must be visible before triggering an event.
A threshold of 0 means it will trigger if any part of the element is visible, while a threshold of 1 means the entire element must be visible.
It performs better than listening to scroll, and will only fire once when the element transitions from hidden to visible, even while you are continuously scrolling. And it also works if the page content changes due to other events, such as other content being hidden/shown, or window resize, etc.
This is how I made a radial chart that animates every time at least 20% of it appears into view:
const options = {
series: [75],
chart: {
type: 'radialBar',
},
};
const chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
const observer = new IntersectionObserver(function(entries) {
if (entries[0].isIntersecting === true) {
chart.updateSeries([0], false); // reset data to 0, then
chart.updateSeries([75], true); // set original data and animate
// you can disconnect the observer if you only want this to animate once
// observer.disconnect();
}
}, { threshold: [0.2] });
observer.observe(document.querySelector("#chart"));
This is what you want:
Check if element is visible after scrolling
Next time please check if there's already an answer ;)
Alternatively: jquery.appear

Retaining "height" declaration in jQuery after an Ajax call (dropdown selection loads product data, resets height on other page elements)

I have some jQuery setting a height on product descriptions, this can be seen here:
https://www.gabbyandlaird.com/product/truition-products/truition-healthy-weight-loss-pack
The code I'm using to achieve this is:
$(document).ready(function() {
var $dscr = $('.commerce-product-field-field-long-description'),
$switch = $('#toggle'),
$initHeight = 70; // Initial height
$dscr.each(function() {
$.data(this, "realHeight", $(this).height()); // Create new property realHeight
}).css({ overflow: "hidden", height: $initHeight + 'px' });
$switch.toggle(function() {
$dscr.animate({ height: $dscr.data("realHeight") }, 200);
$switch.html("- Read More").toggleClass('toggled');
}, function() {
$dscr.animate({ height: $initHeight}, 200);
$switch.html("+ Read More").toggleClass();
});
});
I am by no means a Javascript expert (or even an amateur for that matter). My knowledge of jQuery is fairly limited, so I'm not sure what needs to be changed above so that when the dropdown selection reloads the data on the page, I don't lose the height value on the "Read More" section of the product description. Any assistance is greatly appreciated. Thanks!
as per your code above it looks you are doing everything when the document is ready.
here is what you can do.
var initialHeight = function(){
// you height initialization code here
}
$(function () {
$(document).ready(initialHeight); // initializes the height on document ready
$("#yourSelectBox").change(initialHeight); // initializes the height on combobox selection change
});
hope this helps.

Is there a YUI 2.x equivalent to jQuery's scrollTo?

I want to create an animation to scroll the page smoothly when clicking on anchor links, just like jQuery.ScrollTo plugin (http://demos.flesler.com/jquery/scrollTo/) does it.
I tried making it using YUI 2.x Animation utility, by animating the value of the property document.activeElement.scrollTop. It works on webkit only :'( - on the other browser, nothing happens - not even an error is raised.
goToAnchor = function(e, id) {
var targetToGo = Dom.get(id),
scrollToTarget = new Animation(document.activeElement,
{
scrollTop:
{
from: document.activeElement.scrollTop,
to: targetToGo.offsetTop
}
}, 1, Easing.easeOut
)
Event.preventDefault(e);
scrollToTarget.animate();
}
What I'd like to know is if there's a plugin that does this for YUI 2.x or how to do a cross browser compatible code to do so.
Thanks!
You need to keep in mind that depending on browser you might need to scroll the html or the body element.
(practially, you need to scroll both to be sure)
Also at http://developer.yahoo.com/yui/animation/#scroll i see
var element = document.getElementById('test');
var myAnim = new YAHOO.util.Scroll(element, {
scroll: {
to: [ 500, test.scrollTop ]
}
});
myAnim.animate();
Maybe that is what you are looking for (still you will have to animate both html and body)
<script>
(function() {
var scrollingBody = document.body;
if (YAHOO.env.ua.gecko){
scrollingBody = document.documentElement;
}
(new YAHOO.util.Scroll(
scrollingBody,
{
scroll:
{
to: [0, 50]
}
},
0.7,
YAHOO.util.Easing.easeOut
)).animate();
})();
</script>

jqGrid - Dragging a row to sort it screws up cell widths

My problem: When I drag a row in jqGrid, and it completes a custom reload function, the cells of the grid, previously all of varying widths set when the grid is defined, are resized to all be the same width. This happens in Webkit browsers but not in Firefox.
Code:
I have dragging to sort enabled on a grid:
$mygrid.jqGrid(
'sortableRows', {
update: function(e, ui) {
sort_grid(e, ui);
}
}
);
As you can see I have a sorting function called on drag complete, sort_grid. Here it is:
function sort_grid(e, ui) {
var current_grid = $(ui.item[0]).closest('table').attr('id');
var $current_row, moved_id, next_id, next_priority;
var $moved_row = $('#' + current_grid + ' tr');
var cnt = 0;
this_id = ui.item[0].id;
$moved_row.each(function () {
if ($(this).attr('id') == this_id) {
$current_row = $moved_row.eq(cnt);
moved_id = $current_row.attr("id");
next_id = $current_row.next().attr("id");
next_priority = $current_row.next().children("td:first").attr("title");
}
cnt++;
});
if ( typeof moved_id !== 'undefined' ) {
if ( next_priority == 'undefined' ) {
next_priority = '999';
}
$.ajax({
url:my_url,
type:"POST",
data:"moved_id=" + moved_id + "&next_id=" + next_id + "&next_priority=" + next_priority,
success: function(data) {
$('.grid').setGridParam({loadonce:false, datatype:'json'}); // force grid refresh from server
$('#' + current_grid).trigger("reloadGrid");
$('.grid').setGridParam({loadonce:true}); // reset to use local values
}
})
}
}
Once I hit that reload trigger $('#' + current_grid).trigger("reloadGrid"); and reload finishes the grid now has incorrect widths on the cells in the grid (they go from being of various widths to all being the same width).
When the grid was originally created it had widths defined in the normal jqGrid fashion:
colModel:[
{name:'one', index:'one', sortable:true, width:45},
{name:'two', index:'two', sortable:true, width:180},
]
but after the grid reload the widths are reset all be the same width (I assume this is the total width of the grid being evenly divided over the total number of cells in the row). So, do I need to explicitly set these widths again, perhaps with something like the following called after the grid reloads?
$('.grid').setGridParam({
colModel:[
{name:'one', index:'one', sortable:true, width:45},
{name:'two', index:'two', sortable:true, width:180},
]
});
I tried the above fix, redefining the colModels after reload and explicitly setting the widths, but it had no effect. Weirder, if I go into the browser console and set the widths with javascript it also has no effect. That's got me stumped.
Unfortunately for me it looks like the jqGrid "Answer Man" (Oleg) is not around... lol.
I faced the same problem for Chrome. I recreated it here http://jsfiddle.net/gZSra/. Just drag the row and then sort any column.
But after few hard hours of debugging jqGrid sources I finally fixed this bug. The problem appears in emptyRows method of jqGrid.
emptyRows = function (scroll, locdata) {
var firstrow;
if (this.p.deepempty) {
$(this.rows).slice(1).remove();
} else {
firstrow = this.rows.length > 0 ? this.rows[0] : null;
$(this.firstChild).empty().append(firstrow); // bug "activation" line
}
if (scroll && this.p.scroll) {
$(this.grid.bDiv.firstChild).css({height: "auto"});
$(this.grid.bDiv.firstChild.firstChild).css({height: 0, display: "none"});
if (this.grid.bDiv.scrollTop !== 0) {
this.grid.bDiv.scrollTop = 0;
}
}
if(locdata === true && this.p.treeGrid) {
this.p.data = []; this.p._index = {};
}
},
*In recent jqGrid-4.4.4 this code begins from 1070 line of jqGrid.src.js
The problem connected removing and then appending firstrow. This row defines width of columns - one of it's cells in my jsFiddle example is
<td role="gridcell" style="height:0px;width:60px;"></td>
That is why problem seems to be connected with some Chrome's or Webkit's dynamic table behaviour.
FIX
Replace infected else scope with next line
$(this.firstChild).find('tr:not(:first)').remove();
It's not hard to see that instead of removing all lines and then appending first back, I just selecting and removing all except first row.
Result jsFiddle: http://jsfiddle.net/HJ3Q3/
Tested in Chrome, FF, IE 8 & 9.
Hope this fix will soon become part of jqGrid sources.
.trigger('reloadGrid');
is causing issues with sortablerows.
Below work around might help you (Unload & reload grid)
Create a function to configure grid, like below
jQuery().ready(ConfigureGrid);
function ConfigureGrid(){
jQuery("#grdCategory").jqGrid({
url: '/controller/action',
datatype: "xml",
colNames: ['Order', 'Name', 'Page Title', 'Is Active', 'Action'
],
colModel: [
{ name: 'col1', index: 'col1', width: 50, sortable: true, sorttype: 'int' }
, { name: 'col2', index: 'col2', width: 150, sortable: true }
],
rowNum: 10,
rowList: [10, 20, 30],
});
$("#list1").jqGrid('navGrid', '#pager1', { edit: false, add: false, del: false, search: true });
$("#list1").jqGrid('sortableRows', { update: function (event, ui) { updateOrder() } });
}
Create function to reload grid
function loadGrid() {
$('#grdCategory').jqGrid('GridUnload');
ConfigureGrid();
}
use loadGrid() function in ajax call back or to refresh grid
Have you tried to setup this property in your jQgrid options
width: 'auto',
If this doesnt work try reloading your grid after the update of the row
jQuery('.grid').trigger('reloadGrid');
The comment of PokatilovArt needs more attention : jqGrid - Dragging a row to sort it screws up cell widths .
It solves the problem in Chrome.
Here is the parameter to change in jqGrid :
deepempty : true
In jqGrid wiki, here is the definition of this option.
This option should be set to true if an event or a plugin is attached to the table cell. The option uses jQuery empty for the the row and all its children elements. This of course has speed overhead, but prevents memory leaks. This option should be set to true if a sortable rows and/or columns are activated.

Categories