Dec
21
Written by:
Michael Washington
12/21/2013 8:22 PM
You can implement an alternative menu in your Visual Studio LightSwitch HTML Client application. In this example we will implement the Multi-level push menu.
You can see the menu in action in the video below:
Implementing The Menu
First, we import the .css files and .js files and add references to them in the default.html page.
The jquery.multilevelpushmenu.menu.js file stores the structure of the menu:
// JS Aray instead HTML Markup
var arrMenu = [
{
title: 'Multi-Push Sample',
icon: 'fa fa-reorder',
items: [
{
name: 'Main',
icon: 'fa fa-bullhorn',
link: '#'
},
{
name: 'Section One',
icon: 'fa fa-html5',
link: '#',
items: [
{
title: 'Section One',
icon: 'fa fa-html5',
items: [
{
name: 'Sub Section',
icon: 'fa fa-code-fork',
link: '#',
},
]
}
]
},
{
name: 'Page Two',
icon: 'fa fa-bullhorn',
link: '#'
}
]
}
];
This produces the menu shown above.
(Note: You can get a list of the icons you can use for the “icon:” value at this link: http://fontawesome.io/icons/)
The menu needs to know what Divs to push to the right when it is expanded.
When we look at a running LightSwitch application in the JavaScript debugger, we see that LightSwitch dynamically creates Divs for each screen that is opened. The id is always a random value so we only have the data-role=”page” to use to locate the Divs.
The jquery.multilevelpushmenu.utility.js file contains a utility method, updateContainersToPush(), that will be called by code that will be implemented in each of the screens, to determine what Divs have been dynamically created, that need to be added to the containersToPush property of the menu:
function updateContainersToPush() {
// Array hold the ContainersToPush
var arrContainersToPush = [];
// Loop thru each LightSwitch page named 'page'
$("div[data-role*='page']").each(function () {
// Add the page to the array
var LightSwitchPage = $(this)[0];
arrContainersToPush.push(LightSwitchPage);
});
// Loop thru each LightSwitch header page named 'header'
$("div[data-role*='header']").each(function () {
// Add the page to the array
var LightSwitchHeaderPage = $(this)[0];
arrContainersToPush.push(LightSwitchHeaderPage);
});
// Set the containersToPush for the menu
$('#menu').multilevelpushmenu('option', 'containersToPush', arrContainersToPush);
};
We also add additional .css and .js references that are required for the menu.
We also add a Div to the default.htm page that the menu will be injected into.
We add the following .css to the LightSwitch user-customization.css file:
/* Customizations for multilevel push menu */
/* Move header to the right */
.msls-logo, .msls-title-container {
margin-left: 2em;
}
/* Hide the back button */
.msls-back-button-contain {
display: none;
}
/* set Z-Index so elements are clickable */
.multilevelpushmenu_wrapper {
z-index: 9000;
}
/* set Z-Index so elements are clickable */
.msls-ctl-list {
z-index: 10000;
}
/* Fix font of header */
.multilevelpushmenu_wrapper h2 {
text-shadow: initial;
color: #FFFFFF;
}
The Screens
The first screen to load in the application is the Main screen. It is the screen that will create the menu in its JavaScript code.
We use the following code to create the menu and to open the other screens when their link is clicked:
myapp.Main.spacerContent_render = function (element, contentItem) {
if ($('#menu')[0].innerHTML == "") {
// Create Menu
$('#menu').multilevelpushmenu({
menu: arrMenu,
collapsed: true,
containersToPush: [$("div[data-role*='page']"), $("div[data-role*='header']")],
overlapWidth: 40,
onItemClick: function () {
// First argument is original event object
var event = arguments[0],
// Second argument is menu level object containing clicked item (<div> element)
$menuLevelHolder = arguments[1],
// Third argument is clicked item (<li> element)
$item = arguments[2],
// Fourth argument is instance settings/options object
options = arguments[3];
var itemName = $item.find('a:first').text();
// Collapse menu
$('#menu').multilevelpushmenu('collapse');
// Open Page
if (itemName == 'Main') {
myapp.showMain();
}
if (itemName == 'Sub Section') {
myapp.showSubSection();
}
if (itemName == 'Page Two') {
myapp.showPageTwo();
}
}
});
} else {
// Menu already created
// Update Menu containers to push
updateContainersToPush();
};
};
Also, on every screen we use a Custom Control to move the content of the page to the right to leave room for the menu.
We use the following setting for the control:
On each subsequent page we use code (in the render of the spacer Custom Control) like the example below, to add the page to array of Divs to be pushed to the right when the menu is expanded:
myapp.PageTwo.spacerContent_render = function (element, contentItem) {
// Update Menu containers to push
updateContainersToPush();
};
We have to run this code in the render method of a control on the page, because the page cannot be added to the array until after the page has been fully rendered.
Download
The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
(you must have Visual Studio 2013 Professional (or higher), installed to run the code)
33 comment(s) so far...
Hi, Great. It works. Nice.
One issue though.
When the screen has tabs, I don't know how to make it render right. Any fix for this? Regards Sven
By Sven on
12/23/2013 12:37 AM
|
Hi Made it work but then I noticed that autocomplete box render below lists/grids. Think it has to do with the Changes in user customization file.
Besides that Little problem. Great work! Sven
By Sven on
12/23/2013 5:36 AM
|
@Sven - You will want to locate the .class of the control and alter the user customization file to adjust the z-index.
By Michael Washington on
12/23/2013 5:43 AM
|
Hi,
I am planning to use Wijmo menu. It seems that the "Main" default title of Lightswitch is still there in the Main page whilst for the rest the menu is disabled. Is it possible to make the "Main" default title for main page invisible as well?
Cliff
By Cliff Lo on
1/28/2014 4:43 AM
|
@Cliff Lo - You should be able to do this with .css code. I have no code examples, sorry.
By Michael Washington on
1/28/2014 5:23 AM
|
Comment /* set Z-Index so elements are clickable */ /* .msls-ctl-list { z-index: 10000; } */
Go to Github and download updated version of multi level push menu https://github.com/adgsm/multi-level-push-menu
copy and replace file in the project: jquery.multilevelpushmenu.min.js
By Daniel Ramirez on
3/7/2014 7:43 AM
|
@Daniel Ramirez - Thanks :)
By Michael Washington on
3/7/2014 8:33 AM
|
That's really gr8! A bit painfull to add space container on every page though lol What about multi-tabs page? Where do you put the space container? Tks.
By François on
6/11/2014 8:38 AM
|
@François - You raise valid points. However, it is doable. I did not try multi-tabs pages so I am not sure how they will be handled.
By Michael Washington on
6/11/2014 9:46 AM
|
Tks Michael, I'll try to see how to place a spacer on the created code or something else. Did you ever try to publish an app on Azure with that menu? For some reason the ul element get sa display:none; style and hence the menu is empty.
By François on
6/13/2014 9:24 AM
|
The display:none is due to the font-awesome link not being https while my websites is. I downloaded and included font-awesome in my project and it works :-)
By François on
6/13/2014 9:24 AM
|
@François - Thanks for following up. I am glad you got it working.
By Michael Washington on
6/13/2014 9:24 AM
|
What if the decision to push or not push (that is the question lol) depends on the screen size. For example on a phone I'm happy with the push but on a desktop I would like the menu to always be displayed. Any easy way to set that up or I have to dig into the js files? Tks.
By François on
6/18/2014 3:53 AM
|
@François - I see no easy answers.
By Michael Washington on
6/18/2014 3:53 AM
|
FYI, I moved the if(innerhtml=="") code of the first page into updateContainerToPush as otherwise the menu would disapear when hitting F5 on a page different from the home page.
By François on
7/12/2014 4:45 AM
|
Hey Michael,
I tried this out in VS LightSwitch 2013 Update 3 and am getting some weird behavior when the menu pushes out. The title of the page doesn't simply slide over as far as the menu provides, it slides almost to the center of the screen. Also, the content of the page (everything below the heading) is somewhat behind the push menu.
Any idea on how to update the CSS/JavaScript to make this work with the latest version of LightSwitch?
By cmsmith on
10/12/2014 10:57 AM
|
@cmsmith - Sorry, when they update the .css in LightSwitch it throws everything off. I spent hours to get the .css working in this example :) My advice is to remove my hacks and start over.
By Michael Washington on
10/12/2014 11:00 AM
|
Yeah, I updated this project to the latest version of LightSwitch and am seeing the same results that I have in my sample project. Just to let you know :)
By cmsmith on
10/12/2014 11:03 AM
|
I'll hack on it a little bit and see if I can fix it. If I can, I'll post the fix here.
By cmsmith on
10/12/2014 11:04 AM
|
Ok, figured it out.
In juery.multilevelpushmenu.js remove this block:
// Loop thru each LightSwitch header page named 'header' $("div[data-role*='header']").each(function () { // Add the page to the array var LightSwitchHeaderPage = $(this)[0]; arrContainersToPush.push(LightSwitchHeaderPage); });
In the Main.lsml in the Customer Control remove this:
$("div[data-role*='header']")
from the containersToPush variable.
It appears that pushing and "pulling" the data-role='page' is enough for LightSwitch now. I think they wrapped everything in data-role="page". The header was being pushed twice.
If you want, I can update the project you have on your site to the latest version and send you a link to my dropbox of the zip.
By cmsmith on
10/12/2014 11:21 AM
|
** Custom control, not Customer control.
By cmsmith on
10/12/2014 11:22 AM
|
Oh, and not jquery.multilevelpushmenu.js, jquery.multilevelpushmenu.utility.js
Typing too fast!!
By cmsmith on
10/12/2014 11:23 AM
|
@cmsmith - Thanks!
By Michael Washington on
10/12/2014 11:35 AM
|
Hi guys,
Were you able to fix the issue with the content being behind the push menu in the latest version of LightSwitch? I see that there are comments about it above.
Thanks, Martin
By Martin on
10/15/2014 1:56 PM
|
@Martin - No I have not worked on it, too busy sorry :(
By Michael Washington on
10/15/2014 1:57 PM
|
@Martin -- You have to make sure to change the control's CSS styling to have a higher z-index than that of the push menu. I noticed this with the LightSwitch table control; it was "behind" the push menu. I added '.msls-table' to the z-index callout in the CSS that Michael provided:
.msls-ctl-list .msls-table { z-index: 10000; }
There will be other's that won't work, especially custom stuff that you do yourself. Just add the root div's class to that CSS callout and it should work.
@Michael, I have this completely working as expected in the latest version of LightSwitch.
By cmsmith on
10/18/2014 4:03 PM
|
@cmsmith - Glad you have it working. Email me if you want me to post it :)
By Michael Washington on
10/18/2014 4:40 PM
|
Hi Michael.
First of all thanks to share all valuable lightswitch articles , michael i have 1 question regarding to push menu application, in that you have designed a menu in verticle bar so there is any way to show the menu is horizontally at the place of vertically.
Please find few minutes in your busy schedule and reply me.
Thanks in advance,
Manish Yadav
By manish on
11/1/2014 4:54 AM
|
@manish - I am sure there is a way but I do not have any examples.
By Michael Washington on
11/1/2014 4:55 AM
|
Hi, Michael. Thx a lot for your very helpful work! I tried to improve your solution See http://d-fens.ch/2014/12/08/extending-the-lightswitch-html-client-with-a-cascading-push-menu/ what do you think? Best regards, Carsten
By Carsten Kreissl on
12/8/2014 8:22 AM
|
@Carsten Kreissl - Excellent! I have not been able to work on this, it was really only a "start", so I am glad that you have basically fixed it :)
By Michael Washington on
12/8/2014 9:12 AM
|
this menu is brilliant, however my header bar isn't adjusting and I cant for the life of me work out why, any suggestions, heres the problem I have with the menu closed and open:
closed: https://plus.google.com/117523380313133603846/posts/PPF2oUuY49d?pid=6101539793825316578&oid=117523380313133603846
open: https://plus.google.com/117523380313133603846/posts/PPF2oUuY49d?pid=6101539792892032914&oid=117523380313133603846
cheers for any advice
By Ash on
1/7/2015 4:46 AM
|
I Love this menu too and I think managed to take out the step of adding the Custom Control spacerContent by adding the following to the user-customization.css:
/*Fix move everything right*/ .ui-page-active { margin-left: 30px; }
Please let me know if it helps you out!
Cheers Grant
By Grant on
6/18/2016 9:50 AM
|