I'm curently working on some extension to the gnome-shell. I added a new Popup menu into aggregate menu in status area, but can't move it to the desired position. Tried menu.moveMenuItem(item, position), but it moves only the "main" item, not the entire dropdown (How it looks - my PopupSubMenuMenuItem is named ThermalManagement, and submenu menu items starts from Optimized). What I need to do to move an entire submenu into specific position?
Code sample:
enable() {
this._item = new PopupMenu.PopupSubMenuMenuItem('Thermal Management', true);
this._item.icon.icon_name = 'applications-system-symbolic';
let position = this._findMenuItemPosition(Main.panel.statusArea.aggregateMenu._power.menu) + 1;
this._optimizedOption = this._createOptimizedOption();
this._item.menu.addMenuItem(this._optimizedOption);
this._quietOption = this._createQuietOption();
this._item.menu.addMenuItem(this._quietOption);
this._coolOption = this._createCoolOption();
this._item.menu.addMenuItem(this._coolOption);
this._ultraPerformanceOption = this._createUltraPerformanceOption();
this._item.menu.addMenuItem(this._ultraPerformanceOption);
Main.panel.statusArea.aggregateMenu.menu.addMenuItem(this._item);
Main.panel.statusArea.aggregateMenu.menu.moveMenuItem(this._item, position);
}
Related
My problem is simple: I have a div container, with a property of overflow:auto, in mobile I see the scroll bar because my elements are out of the container, I can scroll to the right or left. I want that when I click an item in the top right, it gets placed in the head of the list (unshift), and the container goes back to its default position where the scrollLeft is 0. What I am doing is :
myElement.scrollLeft = 0;
But it is not working. This is the whole code I have:
function showDetails(i) {
// Important
cdiscountHeaderOptions.scrollLeft = 0;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
let updatedData = data.filter(function (item) {
return item.id - 1 !== i;
});
let selectedItem = data.filter(function (item) {
return item.id - 1 === i;
})[0];
updatedData.unshift(selectedItem);
renderData(updatedData);
}
detailsContainers.style.display = 'flex';
}
I tried also:
myElement.scrollTo(0,0);
But I got an error: scrollTo is not a function.
Any help would be much appreciated.
What I would do is place an empty div at the top <div id="scrollToTop"></div> of your HTML page and then in your js code, you can simply say document.getElementById("scrollToTop").scrollIntoView();
UPDATED ANSWER
Try putting a div where you want to scroll, make it position absolute so it's at a specific position, then you can use the .scrollIntoView(); function
UPDATED ANSWER
window.scrollTo(0,0)
I'm looking to have two separate links for two vertical slide-out nav bars be set off from a javascript function separately after clickon.
I've tried using the same togglebutton function with two classes which correspond to the two slide-out nav bars to no avail.
$(document).ready(function() {
var $toggleButton = $('.toggle-button-work'),
$menuWrap = $('.menu-wrap-work'),
$toggleButton = $('.toggle-button-about'),
$menuWrap = $('.menu-wrap-about');
// Slide-out Nav - LEFT - MY WORK
$toggleButton.on('click', function() {
$(this).toggleClass('button-open-work');
$menuWrap.toggleClass('menu-show');
});
// Slide-out Nav - RIGHT - ABOUT
$toggleButton.on('click', function() {
$(this).toggleClass('button-open-about');
$menuWrap.toggleClass('menu-about');
});
});
I expect that since I'm using separate classes for each togglebutton it should work. However, it's only setting off one of the links or the right side slide-out nav link.
why you are reassigning element selection?
var $toggleButton = $('.toggle-button-work'),
$menuWrap = $('.menu-wrap-work'),
$toggleButton = $('.toggle-button-about'),
$menuWrap = $('.menu-wrap-about');
you should assign to on diferent variables each element
Basically I have a navbar with 11 links, and I want it to be responsive. The goal is, as window gets narrower, a 12th link will appear as a ddl that will include the 11th element, 10th and so on. The text in links is variable in length based on language, so the links are not equal in width.
This is the example of the markup (partial).
https://jsbin.com/fijakipesu/edit?html
What is the best approach to achieve this?
starting screen
Create the buttons and then hide it for desktop users and show the complete navigation.
With #media you can show the buttons and hide the navigation items for mobile devices.
When the user clicks on the button or hover it, they get the navigation items.
HTML:
<button class='menu-button0'>Click me</button>
<div id='showMe'>link1, link2, link3</div>
CSS, when mobile device visits your page:
#showMe(display:none;)
.menu-button0:hover + #showMe{display:block;}
CSS, when desktop device visits your page:
.menu-button0{display:none;}
Found this and is working like a charm. For anyone who is trying to achieve that responsive/progressive menu, try it.
http://jsfiddle.net/abhitalks/860LzgLL/
var elemWidth, fitCount, fixedWidth = 120,
$menu = $("ul#menu"), $collectedSet;
collect();
$(window).resize(collect);
function collect() {
elemWidth = $menu.width();
fitCount = Math.floor(elemWidth / fixedWidth) - 1;
$collectedSet = $menu.children(":gt(" + fitCount + ")");
$("#submenu").empty().append($collectedSet.clone());
}
I went with a variant of StefanB's as this allowed me to play with the widths of the items a little more by simply checking if the item right coord was overlapping the "menu" space....:
function collect() {
$menu.children().css({"display": "block", "width": "auto"});
var elemLeft= $menu.offset().left + $menu.outerWidth();
$allElements = $menu.children();
$collectedSet = $allElements.filter(function() {
var right = $(this).offset().left + $(this).outerWidth();
return (right + 40) > elemLeft;
});
$("#submenu").empty().append($collectedSet.clone());
$collectedSet.css({"display": "none", "width": "0"});
}
I'm working on a project over at github pages, which I replace a bootstrap .dropdown with .dropup if the div's overflow-y: scroll will cause the dropdown menu to be cutoff / overflow. You can see the function working properly at this jsfiddle. Notice if you click on the ellipsis icon to the right on the top rows, it will drop down, if you click on the icon on the bottom rows, it will drop up.
Now, my actual implementation (github page), the code is exactly the same (below), but it wants to replace all .dropdown classes with .dropup when opened, including the top-most row which gets cut off, seen in the photo below.
I've been struggling with this for a week and can't quite figure it out. I've tried a few different things that I thought fixed it but ended up just being a hack and didn't work on mobile, or replaced some but not all etc.
Here is the Javascript / jQuery I'm using, which can be seen in the jsfiddle and my github source here.
$(document).on("shown.bs.dropdown", ".dropdown", function () {
// calculate the required sizes, spaces
var $ul = $(this).children(".dropdown-menu");
var $button = $(this).children(".song-menu");
var ulOffset = $ul.offset();
// how much space would be left on the top if the dropdown opened that direction
var spaceUp = (ulOffset.top - $button.height() - $ul.height()) - $('#playlist').scrollTop();
// how much space is left at the bottom
var spaceDown = $('#playlist').scrollTop() + $('#playlist').height() - ((ulOffset.top + 10) + $ul.height());
// switch to dropup only if there is no space at the bottom AND there is space at the top, or there isn't either but it would be still better fit
if (spaceDown < 0 && (spaceUp >= 0 || spaceUp > spaceDown))
$(this).addClass("dropup");
}).on("hidden.bs.dropdown", ".dropdown", function() {
// always reset after close
$(this).removeClass("dropup");
});
Edit:
To clear up any confusion, here's an example of the behavior without my added .dropup function. jsfiddle Notice when you click the last menu item, it opens the menu but requires scrolling. I specifically want to remove the .dropdown class and add .dropup in this case, so no scrolling is required.
It took some basic math, but I managed to figure out what you desired to do. This code changes the bootstrap classes between dropup and dropdown depending on the room available for a normal dropdown.
I calculated this by detracting the height of the button, dropdownmenu and how far the button was scrolled down in the scrollContainer from the height of the scrollContainer. I got the value how much the div was scrolled down by using the buttons offset and detracting the offset from the scrollContainer.
Here is my jQuery (I selected the .playlist class because this was attached to your scrollContainer, but you should replace it by an id or select it by other means):
$(".dropdown, .dropup").click(function(){
var dropdownClassCheck = $(this).hasClass('dropdown');
var buttonOffset = $(this).offset().top;
var scrollboxOffset = $('.playlist').offset().top;
var buttonHeight = $(this).height();
var scrollBoxHeight = $('.playlist').height();
var dropDownButtonHeight = $(this).children('ul').height();
dropdownSpaceCheck = scrollBoxHeight>buttonOffset-scrollboxOffset+buttonHeight+dropDownButtonHeight;
if(dropdownClassCheck && !dropdownSpaceCheck){
$(this).removeClass('dropdown').addClass('dropup');
}
else if(!dropdownClassCheck && dropdownSpaceCheck){
$(this).removeClass('dropup').addClass('dropdown');
}
});
A working JSFiddle
Let me know if there are parts of the code that could be improved/done easier or if there are any problems with my solution.
I have not thoroughly checked, but .scrollTop() is probably why the code fails when combined with other elements in the DOM, so here is a solution without it:
function checkHeights(){
// LOOP through each dropdown
$('.dropdown,.dropup').each(function(index,element){
var $dropDown = $(element),
$dropDownMenu = $dropDown.find('.dropdown-menu'),
dropDownTop = $dropDown.offset().top,
visibleHeight = $dropDown.height(),
hiddenHeight = $dropDownMenu.height(),
ddTop = dropDownTop - hiddenHeight,
ddBottom = dropDownTop + visibleHeight + hiddenHeight;
// LOOP through all parents
$dropDown.parents().each(function(ix,el){
var $el = $(el);
// CHECK if any of them have overflow property set
if( $el.css('overflow') !== 'visible' ){
var limitTop = $el.offset().top,
limitBottom = limitTop + $el.height();
// CHECK if parent is better fit when dropped upside
if( limitBottom < ddBottom && ( ddTop - limitTop ) > ( limitBottom - ddBottom ) )
$dropDown.removeClass('dropdown').addClass('dropup');
else
$dropDown.removeClass('dropup').addClass('dropdown');
// BREAK LOOP
return false;
}
});
});
}
$(document).ready(function() {
checkHeights();
$('.playlist').scroll(checkHeights);
});
JS Fiddle here.
This one does not require any class or id given to it except for dropdown,dropdown-menu, and dropup (all of which are Bootstrap defaults) and would work fine even if there are multiple playlists on page.
UPDATE
The code is modified and wrapped in a function in order to allow being called when scroll event fires.
I think that the problem it's that you have a big header, and the jsFiddle don't. So ulOffset.top it's always big, and spaceDown is always negative
Replace parent div.dropdown with div.dropup.
I'm doing a mobile App with jQuery mobile 1.4.3. I'm trying to build a navigation bar that changes dynamically, If the user has logged in the navigation bar will show 4 options, if not it will show 3 options. The problems:
Once I click the bar some times it turns all blue.
I'm sure I'm not using the correct code.
The navigation bar disappears for some time when I click in a button.
The blue click highlight is not persistent for the page click.
What I need is a fixed navigation bar that smoothly changes pages when clicked :)
http://jsfiddle.net/claire89/toxtcbhe/14/
var statusLogin = null;
$(document).on('pagecontainershow', function (e, ui) {
var myNavbar = null;
if (statusLogin == null) {
myNavbar = $('<div data-role="footer" data-id="footer" data-position="fixed"><div data-role="navbar"><ul><li>Menu</li><li>Sugestions</li><li>History</li><li>Settings</li></ul></div></div>');
$('.ui-content').append(myNavbar).trigger('create');
} else {
myNavbar = $('<div data-role="footer" data-id="footer" data-position="fixed"><div data-role="navbar"><ul><li>Menu</li><li>History</li><li>Settings</li></ul></div></div>').appendTo('.ui-content');
$('.content').append(myNavbar).trigger('create');
}
$("[data-role='navbar']").navbar();
$("[data-role='header'], [data-role='footer']").toolbar();
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
var activePageId = activePage[0].id;
switch (activePageId) {
case 'listMenuPage':
alert("listMenuPage");
break;
case 'sugestionsPage':
alert("sugestionsPage");
break;
case 'settingsPage':
alert("settingsPage");
break;
case 'historyPage':
alert("historyPage");
break;
default:
}
});
footer div should be a direct child of page div, you should not place it inside content div. Moreover, you need to .remove() footer or navbar once you leave a page before you inject a new one. Otherwise, you will end up adding duplicating both footer and navbar in same page whenever the same page is shown.
Another note, when you inject toolbar dynamically, you need to reset the height of active page $.mobile.resetActivePageHeight() as toolbars adds padding to page, if height isn't reset, the page will scroll.
For better results, use pagecontainerbeforeshow to inject footer and navbar, and pagecontainerhide to remove them.
var statusLogin = null;
$(document).on('pagecontainerbeforeshow', function (e, ui) {
/* ui.toPage was introduced in 1.4.3
* can be used instead of "getActivePage"
* on pagecontainer events
*/
var activePage = $(ui.toPage),
activePageId = activePage[0].id,
myNavbar = "";
if (statusLogin == null) {
myNavbar = $('<tags></tags>');
activePage.append(myNavbar);
} else {
myNavbar = $('<tags></tags>');
activePage.append(myNavbar);
}
/* create footer and navbar
* add active class to button based on page's ID
*/
$("[data-role='footer']")
.toolbar()
.find("a[href=#" + activePageId + "]")
.addClass("ui-btn-active");
/* reset height of active page */
$.mobile.resetActivePageHeight();
}).on("pagecontainerhide", function (e, ui) {
/* remove footer once page is hidden */
$(".ui-footer", ui.prevPage).remove();
});
Demo