I'm working in SharePoint 2013 and I'm building a dynamic multi-level menu system. Basically there are two components, a list where users add their menu items, and a page where using REST API and Dynamic CSS, the menu items are displayed.
Here is a representational sample of the REST API Code:
$(function () {
$.ajax({
url: "/sites/regulatory3/_api/web/lists/GetByTitle('Navigation')/items?$orderby=LVL2Sequence",
type: "GET",
headers: {
"accept": "application/json;odata=verbose"
},
}).success(function (data) {
var listItemInfo = '';
listItemInfo += "<nav><ul id='nav'>"
//Level 1 LVL1Sequence 1
$.each(data.d.results, function (key, value) {
//alert("Sequence " + value.Sequence);
if(value.Level == 1){
if(value.Sequence == 1){
//listItemInfo += value.Title;
listItemInfo += "<li><a href='#'>" + value.Title + "</a><ul>";
}
}
});
//TopItemID 1 Level 2 LVL2Sequence All
$.each(data.d.results, function (key, value) {
if(value.Level == 2){
if(value.TopItemID == 1){
listItemInfo += "<li><a href='" + value.Link + "'>" + value.Title + "</a></li>";
}
}
});
//Level 1 LVL1Sequence 2
$.each(data.d.results, function (key, value) {
//alert("Sequence " + value.Sequence);
if(value.Level == 1){
if(value.Sequence == 2){
//listItemInfo += value.Title;
listItemInfo += "</ul></li><li><a href='#'>" + value.Title + "</a><ul>";
}
}
});
//TopItemID 2 Level 2 LVL2Sequence All
$.each(data.d.results, function (key, value) {
if(value.Level == 2){
if(value.TopItemID == 2){
listItemInfo += "<li><a href='" + value.Link + "'>" + value.Title + "</a></li>";
}
}
});
listItemInfo += "</ul></li></ul></nav>"
return $("#w").html(listItemInfo);;
alert("REST API");
});
failure(function (data) {
alert("Failure");
});
});
Here is the Dynamic CSS code, this gives the menu an accordion effect:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" type="text/javascript"></script><!-- <script type="text/javascript" language="javascript" charset="utf-8" src="nav.js"></script> -->
<!--[if lt IE 9]>
<script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script>
$(document).ready(function(){
$("#nav > li > a").on("click", function(e){
if($(this).parent().has("ul")) {
e.preventDefault();
}
if(!$(this).hasClass("open")) {
// hide any open menus and remove all other classes
$("#nav li ul").slideUp(350);
$("#nav li a").removeClass("open");
// open our new menu and add the open class
$(this).next("ul").slideDown(350);
$(this).addClass("open");
}
else if($(this).hasClass("open")) {
$(this).removeClass("open");
$(this).next("ul").slideUp(350);
}
});
});
</script>
Here is the CSS code, this adds the menu style:
<style>
#sideNavBox {DISPLAY: none}
#contentBox {MARGIN-LEFT: 5px}
ol, ul, li {
padding: 0;
}
menu, nav, section { display: block; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
strong { font-weight: bold; }
table { border-collapse: collapse; border-spacing: 0; }
h1 { font-family: 'Merienda', 'Trebuchet MS', Verdana, sans-serif; font-size: 1em; line-height: 1.7em; margin-bottom: 20px; font-weight: bold; letter-spacing: -0.03em; color: #675d90; text-shadow: 2px 2px 0px rgba(255,255,255,0.65); text-align: center; }
#w { display: block; width: 400px; margin: 0 auto; margin-left: 0px; padding-top: 5px; }
/* nav menu styles */
#nav {
display: block;
width: 150px;
margin: 0 auto;
margin-left: 0px;
-webkit-box-shadow: 3px 2px 3px rgba(0,0,0,0.7);
-moz-box-shadow: 3px 2px 3px rgba(0,0,0,0.7);
box-shadow: 3px 2px 3px rgba(0,0,0,0.7);
}
#nav li { }
#nav > li > a {
display: block;
padding: 16px 18px;
font-size: 0.7em;
font-weight: bold;
color: #d4d4d4;
text-decoration: none;
border-bottom: 1px solid #212121;
background-color: #343434;
background: -webkit-gradient(linear, left top, left bottom, from(#948c6f), to(#292929));
background: -webkit-linear-gradient(top, #595959, #292929);
background: -moz-linear-gradient(top, #595959, #292929);
background: -ms-linear-gradient(top, #595959, #292929);
background: -o-linear-gradient(top, #595959, #292929);
background: linear-gradient(top, #595959, #292929);
}
#nav > li > a:hover, #nav > li > a.open {
color: #e9e9e9;
border-bottom-color: #384f76;
background-color: #6985b5;
background: -webkit-gradient(linear, left top, left bottom, from(#6985b5), to(#456397));
background: -webkit-linear-gradient(top, #ff8c00, #456397);
background: -moz-linear-gradient(top, #ff8c00, #456397);
background: -ms-linear-gradient(top, #ff8c00, #456397);
background: -o-linear-gradient(top, #ff8c00, #456397);
background: linear-gradient(top, #ff8c00, #456397);
}
#nav li ul { display: none; background: #f09609; }
#nav li ul li a {
display: block;
background: none;
padding: 10px 0px;
padding-left: 10px;
font-size: 0.7em;
text-decoration: none;
font-weight: bold;
color: white;
border-bottom-style: solid;
border-bottom-color: orange;
text-shadow: 1px 1px 0px #000;
}
#nav li ul li a:hover {
background: -webkit-gradient(linear, left top, left bottom, from(#456397), to(#000000));
background: -webkit-linear-gradient(top, #456397, #000000);
background: -moz-linear-gradient(top, #456397, #000000);
background: -ms-linear-gradient(top, #456397, #000000);
background: -o-linear-gradient(top, #456397, #000000);
background: linear-gradient(top, #456397, #000000);
}
</style>
And here is the HTML, the Dynamic HTML generated by the REST API code injects into this :
<div id="w"></div>
So here is the problem I'm having. The REST API code works fine and it creates the Dynamic HTML, injecting it into the HTML tag and the Dynamic CSS works fine, but they don't work well together. If I run the REST API code the menu items are created, but the menu isn't dynamic. If, after running the REST API code I changed the tag id from "w" to anything else, for example "w1", the Dynamic CSS code works fine:
Some of the things I've tried include (but are not limited to):
Adding break; to various points in the REST API code
Adding return; to various points in the REST API code
Functions to change the id attribute of the tag - these work but I just can't seem to put them in the right place in the code, no matter where I put them they run before the REST API code and so the REST API doesn't write anything because the id attribute is already changed:
function changeToW1(){
$('#w').attr('id', 'w1');
alert("Change W to W1");
}
function changeToW() {
$('#w1').attr('id', 'w');
alert("Change W1 to W");
}
Nothing works but it seems like somehow the REST API code just won't "let go" of the tag and so the Dynamic CSS code won't attach to the tag.
I know this is somewhat complex but if anyone thinks they can help please provide guidance and code samples, and I'll try your suggestions quickly.
Thanks!
Tom