I have a panel with 3 items in it. A panel then a horizontal splitter then a panel. This layout works fine and the user can easily drag the splitter up and down to resize the adjoining panels.
But how do I set the position of the splitter programmatically? Ideally I'd like to animate the splitter to its new position.
The splitter has a method setPosition, which also takes an animate argument. But this method simply moves the splitter without changing the heights of either panel. So the splitter is now floating over the top of one of the panels. In the afteranimate listener I've tried all manner of doLayout, updateLayout, panel.setHeight, etc... but nothing seems to affect the panel sizes. According to the console the code is run, it just doesn't appear to do anything.
So what is the method for changing the position of a horizontal position between two panels?
This is using Ext 4.1.1a.
splitter.setPosition(0,30,{
listeners:{
beforeanimate: function(){
console.log('animate');
},
afteranimate: function(){
console.log('finished');
bottomPanel.setHeight(500); //Does nothing
splitter.updateLayout(); //Does nothing
rightColumn.doLayout(); // Puts splitter bar back to the original position
}
}
});
I have solved a very similar problem with ExtJS 4.1.3. I have two panels separated by a vertical splitter and I wanted the splitter position to persist across page refreshes.
After trying for some time trying to hook into the splitter itself, I abandoned the idea. The way I have been able to set the splitter position programmatically starts by listening to the resize event of one of the panels.
I store the width of the sidebar with the ExtJS state manager. If the new width parameter is undefined, then this is a page reload situation and I grab the last saved sidebar panel width from the state manager. I set the width of the sidebar to the saved value, then set the splitter position to 20 pixels more than the width (to account I assume for the scrollbar.)
Inside the sidebar panel:
resize: function (sidebar, newWidth, newHeight, oldWidth, oldHeight) {
var sidebarWidth = newWidth;
if (oldWidth === undefined) {
// page reload. restore width from state manager
savedWidth = Ext.state.Manager.get('sidebar_width');
sidebarWidth = savedWidth === undefined ? sidebarWidth : savedWidth;
}
sidebar.splitter.setPosition(sidebarWidth + 20);
sidebar.setWidth(sidebarWidth);
Ext.state.Manager.set('sidebar_width', sidebarWidth);
}
I had avoided setting a listener inside a panel because I didn't know how to get a handle to the splitter object. The breakthrough came when I discovered that the context parameter sent into the resize event (named sidebar in the example code provided) holds a reference to the splitter object.
This solution worked for me and hopefully it will be helpful to others with this question.
Related
In my angularjs application I have approximately 23 tabs. So 90% of the width I have given for tabs with overflow : hidden, and 10% width Prev and Next icons. Each Tab has 36px width. So by default on the page 5 tabs are getting visible. Now when I click Next, I just want to scroll 5 tabs to left, like this continue till the last tab visible. So in my Next icon click event I am trying to do this some thing like the following, in my controller, to get the max scroll left and then use it but in my code maxScrollLeft is returning NaN.
_self.getNextTabs = function () {
var maxScrollLeft = $element.scrollWidth - $element.clientWidth;
alert(maxScrollLeft);
angular.element(document.querySelector('.main_tabSet .nav-tabs')).scrollLeft(600);
}
Here I have hard coded .scrollLeft(600); for testing purpose, so when I click Next, the tabs are scrolling left. But I want to make this scrolling to work correctly based on the max scroll left and the number of tabs that are being occupied. can any one help me in fixing it.
Not sure if _self.getNextTabs is in a directive, a controller or some other location, but the name $element indicates (to me) that it may be inside a directive?
If so, then I think $element may be a jquery object. AND - if that's the case, then you would need to use the syntax $element[0].scrollWidth et al...
_self.getNextTabs = function () {
var maxScrollLeft = $element[0].scrollWidth - $element[0].clientWidth;
angular.element(document.querySelector('.main_tabSet .nav-tabs')).scrollLeft(600);
}
I am trying to create an 'application' contained in a div on a web page. This can't be any larger than certain dimensions (lets say: 550px by 280px). I have a menu with at least 1-3 sub menus for each item. The problem is, while I know the submenu is no larger than 280px high, the submenus often extend beyond the parent div's bounds (except for the last one which always grows upward not down).
Is there any way to make the menus grow up or down depending on whether it will extend beyond the div's bounds?
Here is a JSFiddle: http://jsfiddle.net/3FqcG/
Notice how the "Salzburg" submenu grows down beyond the bounds of the black DIV? I want that to grow up if it is too long and down if there is enough room.
Currently, I am just using the basic initialization: $( "#menu" ).menu();
Thanks!
I don't believe you can do this in CSS.
This leaves us with javascript. The basic idea is to:
calculate the baseline of the menu
if this lies outside the boundary
move the menu upwards to correct the position
live almost happily ever after
But, we have one major issue:
Though we capture the focus of an element, we don't know when its submenu is displayed & positioned. So although your problem is technically solved, it is by far not a desirable solution.
UPDATE
The best workaround I could come up with was to:
Turn off the animation (to avoid ugly glitches)
Add a watcher that would constantly monitor the element that is about to be opened
If opened, apply the position correction
Anyway, if you consider coming this far, you might as well override the default positioning of the jquery ui component, with the note that you will not be able to easily update the library. Update: or try Rudy Garcia's version if it works
Demo
Code of the demo:
var BASE_OFFSET = $('#menuContainer').offset().top;
var MAX_OFFSET = $('#menuContainer').height(); // get the offset of the container
var whenVisible = function($el, callback){ //executes callback when $el is visible
if($el.is(':visible')){ // if visible
callback(); // execute callback
}else{ // otherwise
setTimeout(function(){whenVisible($el, callback);},10); // do the same check in 10 ms
}
};
var fixPosition = function($menu){ // correct the position of the menu in respect to #menuContainer
var h = $menu.outerHeight(true); // take the height of the menu
var menuBottom = $menu.offset().top + h - BASE_OFFSET; // the baseline of the menu (taking into consideration the BASE_OFFSET)
if(menuBottom > MAX_OFFSET){ // if this is outside the MAX height
var diff = MAX_OFFSET - menuBottom; // calculate the difference
var newTop = $menu.position().top + diff; // modify current positioning with the calculated diff value
$menu.css('top', newTop + 'px'); // apply it to top (which is also used by jquery to position submenus
}
$.fx.off = false; // switch animations back on
};
$( "#menu" ).menu().on('menufocus', function(ev, ui){ // on the event menufocus
var $ui = $(ui.item); //take the focused element
var $menu = $ui.children('ul'); // take its related submenu
if($menu.length === 0){ // if there is none
return; // just terminate
}
$.fx.off = true; // switch off jQuery effects (otherwise you'll have glitches)
whenVisible($menu, function(){fixPosition($menu);}); // execute fixPosition when $menu is visible
});
You could also look at the API for this widget:
http://api.jqueryui.com/menu/
You can use the position option to position the elements how you want.
This will change the position so that they are within the box, however you will want to dynamically access the last to give it the position you want as the code below will change all menu items to move up 50.
$( "#menu" ).menu({ position: { my: "left top", at: "right+5 top-50" } });
A complete list of positioning options are also found here: http://api.jqueryui.com/position/
Apparently jquery UI has accounted for this and has given the option "within" to make sure your element stays within another element of your choice.
Therefore Your solution should be this:
$( "#menu" ).menu({ position: {within: '#menuContainer' } });
How do I go about getting what the height of an element on a page would be if it ignored the 'height' css property applied to it?
The site I'm working on is http://www.wncba.co.uk/results and the actual script I've got so far is:
jQuery(document).ready(function($) {
document.origContentHeight = $("#auto-resize").outerHeight(true);
refreshContentSize(); //run initially
$(window).resize(function() { //run whenever window size changes
refreshContentSize();
});
});
function refreshContentSize()
{
var startPos = $("#auto-resize").position();
var topHeight = startPos.top;
var footerHeight = $("#footer").outerHeight(true);
var viewportHeight = $(window).height();
var spaceForContent = viewportHeight - footerHeight - topHeight;
if (spaceForContent <= document.origContentHeight)
{
var newHeight = document.origContentHeight;
}
else
{
var newHeight = spaceForContent;
}
$("#auto-resize").css('height', newHeight);
return;
}
[ http://www.wncba.co.uk/results/javascript/fill-page.js ]
What I'm trying to do is get the main page content to stretch to fill the window so that the green lines always flow all the way down the page and the 'Valid HTML5' and 'Designed By' messages are never above the bottom of the window. I don't want the footer to stick to the bottom. I just want it to stay there instead of moving up the page if there's not enough content to fill above to fill it. It also must adapt itself accordingly if the browser window size changes.
The script I've got so far works but there's a small issue that I want to fix with it. At the moment if the content on the page changes dynamically (resulting in the page becoming longer or shorter) the script won't detect this. The variable document.origContentHeight will remain set as the old height.
Is there a way of detecting the height of an element (e.g. #auto-resize in the example) and whether or not it has changed ignoring the height that has been set for it in css? I would then use this to update the variable document.origContentHeight and re-run the script.
Thanks.
I don't think there is a way to detect when an element size changed except using a plugin,
$(element).resize(function() //only works when element = window
but why don't you call refreshContentSize function on page changes dynamically?
Look at this jsFiddle DEMO, you will understand what I mean.
Or you can use Jquery-resize-plugin.
I've got it working. I had to rethink it a bit. The solution is on the live site.
The one think I'd like to change if possible is the
setInterval('refreshContentSize()', 500); // in case content size changes
Is there a way of detecting that the table row has changed size without chacking every 500ms. I tried (#content).resize(function() but couldn't to get it to work.
I am writing a simple script that displays a dialog box when a user hovers over a profile picture. It dynamically determines the profile pics location on the page and then places itself to the left of it and about 100px above it. This part is working fine.
My issue arises when a profile pic is at the top of the screen and a user mouses over it. The dialog will appear but the top portion of it will be above the fold (i.e. not in the current browser window). Naturally this is not good usability and I would like it to appear on the screen.
My question is how do I know when a dialog will be off screen so I can recalculate its position on the page?
I saw this question which seems like the same as mine but unfortunately no actual solution was provided other then to link to a jQuery plugin. I am using Prototype.
Prototype already provides positions with Element.viewportOffset().
Edit, as Mathew points out document.viewport gives the rest of the information. For example,
var dialogtop = dialog.viewportOffset().top;
if (dialogtop < 0) {
// above top of screen
}
elseif (dialogtop + dialog.getHeight > document.viewport.getHeight()) {
// below bottom of screen
}
You'll want to find the profile pic's position relative to the document (here's a good article on how, though I suspect Prototype's Element.Offset already handles this), then compare it to the body's scrollTop property to see if it's close enough to the top that it needs to have its dialog repositioned.
I am familiar with this problem, however, last time I was able to use a library (Seadragon) to get the screen dimensions and mouse position. I was also working with a fixed size overlay so no code to share with you other than general approach.
For my pop up box I decided to use the event mouse position rather than location of the div on the page. I then compared the mouse position to the known screen size, which I determined on start or resize.
From How do I get the size of the browser window using Prototype.js?
var viewport = document.viewport.getDimensions(); // Gets the viewport as an object literal
var width = viewport.width; // Usable window width
var height = viewport.height; // Usable window height
In Prototype you can also get the mouse coordinates:
function getcords(e){
mouseX = Event.pointerX(e);
mouseY = Event.pointerY(e);
//for testing put the mouse cords in a div for testing purposes
$('debug').innerHTML = 'mouseX:' + mouseX + '-- mouseY:' + mouseY;
}
Source : http://remorse.nl/2008/06/mouse_coordinates_with_prototype/
I am developing a modal dialog as a part of a web application. There is one thing that's been of a puzzle to me. Please watch a movie clip that I just uploded at http://inter.freetzi.com/example/. I feel strongly that I have to accompany my question with a video because this is the case when it's better to see once, than to hear 100 times.
(It could be vertical scrolling, or both vertical and horizontal at the same time. But I am using horizontal scrolling in my example, so watch for it.)
Here's about my question:
Width of the transparent mask affects the width of the page itself. But in Opera, for exemple, every time the window gets resized, the page gets width that is at most close to 'true'. While in IE, once the transparent mask has affected the width, afterwards the page remembers it and stays with it. What is the problem and how to settle it? How to make IE behave the way Opera does?
In my project, I do the following:
//curViewpointW and curViewpointH are current width and height of the viewpoint (current is meant to be the moment of the resize event)
oMask.style.width = curViewpointW + 'px';
oMask.style.height = curViewpointH + 'px';
var pageWH = getPageWH(); //getPageWH() is a function that gets current width and height of the page (with scrolling if there is any)
var curPageW = pageWH[0];
var curPageH = pageWH[1];
if (curPageW > curViewpointW) {
oMask.style.width = curPageW + 'px';
}
if (curPageH > curViewpointH) {
oMask.style.height = curPageH + 'px';
}
But IE ignores that somehow...
P.S. It's jQuery in my example, so many of you may have used its dialog before.
Have you looked into setting an onresize event handler that will adjust your mask dimensions when the window is resized? If you are using Prototype, you can set up such a handler unobtrusively like this:
Event.observe(document.onresize ? document : window, "resize", function() {//dostuff});
courtesy of the Roberto Cosenza blog