How to write custom layout in ExtJs 4 or 3 - javascript

I want to write my own layout.. (like vbox, border and so one)... What i want to do is to create layout that will place it's content in the middle (verticall - middle, horisontal - middle)..
Is there some one who could show me how this control will look like in extJs or can provide some links that may be usefull?
I have this example from
http://dev.sencha.com/deploy/dev/examples/layout-browser/layout-browser.html
Ext.ux.layout.CenterLayout = Ext.extend(Ext.layout.FitLayout, {
// private
setItemSize : function(item, size){
this.container.addClass('ux-layout-center');
item.addClass('ux-layout-center-item');
if(item && size.height > 0){
if(item.width){
size.width = item.width;
}
item.setSize(size);
}
}
});
Ext.Container.LAYOUTS['ux.center'] = Ext.ux.layout.CenterLayout;
But it gives me more questions than answers.. What is setItemSize How it works? When? Why? ect. What is item.setSize called for? How it works? When? Why? ect.

check the examples of ExtJS 3, there is an Ext.ux.Layout.CenterLayout under custom layouts there already, maybe a good point to start?
http://dev.sencha.com/deploy/dev/examples/layout-browser/layout-browser.html
Edit: Try this layout user extension, it centers an item in the horizontal and vertical center of it's container
Ext.ns('Ext.ux.layout');
Ext.ux.layout.CenterLayout = Ext.extend(Ext.layout.ContainerLayout, {
monitorResize:true,
type: 'ux.center',
getLayoutTargetSize : function() {
var target = this.container.getLayoutTarget();
if (!target) {
return {};
}
return target.getStyleSize();
},
onLayout : function(ct, target){
Ext.ux.layout.CenterLayout.superclass.onLayout.call(this, ct, target);
if(!ct.collapsed){
this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
}
},
setItemSize : function(item, size){
var left = (size.width - item.getWidth()) / 2;
var top = (size.height - item.getHeight()) / 2;
var pos = Ext.apply(item.getEl().getPositioning(), {
position : 'absolute',
left : left,
top : top
});
item.getEl().setPositioning(pos);
}
});
Ext.Container.LAYOUTS['ux.center'] = Ext.ux.layout.CenterLayout;

Ext.layout.ContainerLayout (the base class for layouts) has a doLayout method that triggers your container rendering.
In the case of FitLayout, its overriden and it calls a custom setItemSize function who calls the native setSize for the first container item (or the selected item if any), to fit the container size (maximize i guess).
Check also these custom layouts : http://layoutscroll.demo.revolunet.com/

Ext.create('Ext.container.Viewport', {
layout: {
type: 'hbox',
pack: 'center',
align: 'middle'
},
items: [
{
html: 'Hello World'
}
]
});

Related

AE Scripting : How to create a button in ExtendScript that stretches along with the width of panel in real time?

As we cant set the width in percentage in ExtendScript.
I am finding a way where my button can be stretch/resize in realtime while resizing the panel size.
I tried setting the fill value -
Button.preferredSize.width = 200;
Button.preferredSize.height = 80;
saveButton.alignment = ['fill', 'fill'];
Didn't worked. Tried matching button width to panel width
Button.preferredSize.width = panel.width;
Didn't worked.
Just set it's alignment to fill horizontally.
You can also specify it's size/ preferredSize and change it's default height.
Also, in order the UI to resize you need to add "onResizing/ onResize" event listeners and tell the layout to resize with resize().
Here's an example:
function myPanel (thisObj)
{
var win = {};
win.pal = thisObj instanceof Panel ? thisObj : new Window('palette', '', undefined, {resizeable: true});
if (win.pal === null) return win.pal;
var res = "Group {orientation: 'column', alignment: ['fill', 'fill'], preferredSize: [128, 64], \
myButton: Button {text: 'My Button Name', alignment: ['fill', 'center']}\
}";
win.ui = win.pal.add(res);
win.ui.myButton.minimumSize = [128, 32];
win.pal.layout.layout(true);
win.pal.onResizing = win.pal.onResize = function ()
{
this.layout.resize();
};
if (win.pal !== null && win.pal instanceof Window)
{
win.pal.show();
}
return win;
}
myPanel(this);
EDIT: You can set the button's width in percentage too, by taking it's container size. E.g.: win.ui.myButton.size = [ 0.9 * win.ui.size[0], 32];

Hide scrollbar in SAPUI5 page

I have a problem.
I have a list of tweets to show in a page. For mobile devices I don't want to show the right vertical scrollbar.
I've build the page, with its slider and its tweets list. Then I put this page in a scroll container.
Then I return the scroll container.
The code is this:
sap.ui.jsview("ttest.initView", {
/** Specifies the Controller belonging to this View.
* In the case that it is not implemented, or that "null" is returned, this View does not have a Controller.
* #memberOf ttest.initView
*/
getControllerName : function() {
return "ttest.initView";
},
/** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed.
* Since the Controller is given to this method, its event handlers can be attached right away.
* #memberOf ttest.initView
*/
createContent : function(oController) {
var oTweetList = new sap.m.List("items", {
threshold: 2,
inset : false,
showUnread : true,
scrollToLoad : true,
columns : [
new sap.m.Column({
styleClass : "data",
hAlign : "Left",
})
]
});
var oSlider = new sap.m.Slider({
id: "tweetSlider",
width: '100%',
min: 0,
change : function(oEvent){
//Update tweet list
var startIndex = 0;
var endIndex = this.getValue();
oController.updateTweetList("update", startIndex, endIndex);
}
});
var oPage = new sap.m.Page({
title: "Tweet list for #matteorenzi",
enableScrolling : false,
headerContent: [
new sap.m.Button({
icon: "sap-icon://refresh",
press : function(oEvent){
//Update tweet list with all tweets
oController.updateTweetList("first", "", "");
}
})
],
content: [
oSlider,
oTweetList
]
});
var oScroller = new sap.m.ScrollContainer({
vertical : true,
horizontal : false,
content : [
oPage
]
});
oEventBus.subscribe("it.besolution.PopulateList", "Go", function(chId, evId, data){
var template = new sap.m.ColumnListItem({
type : "Navigation",
cells : [
new it.besolution.Tweet({
user : "{user/name}",
username : "{user/screen_name}",
tweet : "{text}",
press : function(oEvent){
var path = this.getBindingContext().getPath();
sap.ui.getCore().byId("iduserDetails").setModel(oGlobalModel).bindElement(path);
app.to("iduserDetails");
}
})
]
});
oSlider.setMax(oGlobalModel.getProperty("/size") - 1);
oTweetList.setModel(oGlobalModel);
oTweetList.bindAggregation("items", "/tweets/", template);
});
return oScroller;
}
});
The page didn't load. I don't know how to do. Why the list is invisible?
Obviously, if I remove the scroll container and I return the oPage element, the list is visible.
Why? How I have to write my code to show the list without the scrollbar?
If you don't want to show the right vertical scrollbar. There is a property called enableScrolling.And you really want to use ScrollContainer, put it as Page content, not the other way around.
enableScrolling default: true
Whether the Page takes special measures to make page content scrollable and keep headers fixed. If set to false, there will be no scrolling at all; for performance reasons this is highly recommended when scrolling is not needed. The Page only allows vertical scrolling because horizontal scrolling is discouraged in general for full-page content. If it still needs to be achieved, disable the Page scrolling and use a ScrollContainer as full-page content of the Page. This allows you to freely configure scrolling. It can also be used to create horizontally-scrolling sub-areas of (vertically-scrolling) Pages.

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

Dynamically change height of rows of Kendo Grid on container Kendo window resize

I have two issues. I have a grid on a page which is contained within a Kendo window. I need the size of the grid rows to increase/decrease to ensure it fills the whole height of the window. I also have a grid on a different page which is just inside a Div that needs to be resized to fit the height of its container on the document window resize.
I have the following code given to me by Kendo support, but it doesn't do what I need it to do. It only sets the grid to be 100% of its container. But this leaves white space underneath the rows. I want to have no white space and for the rows to dynamically change their height so they all fit within the space together for one of them, and dynamically change the pageSize after calculating how many rows would fit in the size of the window for the other.
One of the grids is a top ten grid and the other is a list of all employees grid.
$(window).resize(function() {
var gridElement = $("#grid"),
newHeight = gridElement.innerHeight(),
otherElements = gridElement.children().not(".k-grid-content"),
otherElementsHeight = 0;
otherElements.each(function(){
otherElementsHeight += $(this).outerHeight();
});
gridElement.children(".k-grid-content").height(newHeight - otherElementsHeight);
});
Apologies for the amount of text but I've been stuck on this for days and wanted to give you as much info as possible.
EDIT: horizontal resizing works as intended out of the box. Why is the height any different? :S
EDIT2: Here is the code im using for my grid, this resides in the kendo window's content section
#(Html.Kendo().Grid<DataModels.UI.OperatorPickRatesChartModel>()
.Name("topTenPickersChart")
.Columns(columns =>
{
columns.Bound(b => b.operatorId).Title("Operator Id");
columns.Bound(b => b.averagePicksLastThirty).Title(" Average Picks Last Thirty");
})
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Field(b => b.operatorId).Editable(false);
model.Field(b => b.averagePicksLastThirty).Editable(false);
})
.Read("operatorTopTenPickRates", "DashBoard")
.Events(events => events.Error("error"))
.PageSize(10)
)
.Filterable()
)
For the following solution you need to have the table inside an HTML element that uses 100% of the area (width and height). For getting it what I do is define the HTML as:
<div id="container">
<div id="grid"></div>
</div>
and the following CSS style:
#container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
Not, once the window is resized we need to do some maths...
$(window).resize(function () {
// Get container height
var containerH = $("#container").height();
// Get Grid height
var tableH = grid.element.height();
// Get Grid body height (the remaining is header and footer)
var bodyH = grid.table.height();
// The new height of the body is:
grid.table.height(containerH - tableH + bodyH - 1);
});
JSFiddle showing it here: http://jsfiddle.net/OnaBai/dB5CF/
EDIT: If your grid is inside a kendo window, then you have to:
You don't need the CSS definition.
You are not resizing $(window) but kendoWindow so I will put that code inside Kendo Window resize event handler.
You need to set an initial width for Kendo Window.
So your code should be something like:
$("#container").kendoWindow({
width : 400,
resize: function (e) {
console.log("resize", e);
var containerH = $("#container").height();
var tableH = grid.element.height();
var bodyH = grid.table.height();
grid.table.height(containerH - tableH + bodyH - 1);
}
});
var grid = $("#grid").kendoGrid({
dataSource: {
data : createRandomData(100),
pageSize: 10,
schema : {
model: {
fields: {
Id : { type: 'number' },
FirstName: { type: 'string' },
LastName : { type: 'string' },
City : { type: 'string' }
}
}
}
},
editable : false,
pageable : true,
columns : [
{ field: "FirstName", width: 90, title: "First Name" },
{ field: "LastName", width: 90, title: "Last Name" },
{ field: "City", width: 100 }
]
}).data("kendoGrid");
And the modified JS Fiddle here: http://jsfiddle.net/OnaBai/dB5CF/2/

Possible to make jqGrid stretch to 100%?

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]);
}));

Categories