0

I've been working on a simple app part (my first!) for SharePoint Online which simply creates a table of all the subsites, one site (hyperlinked) per row. It's working great but the problem is I can't figure out how to get the app part to size itself properly. In a perfect world, it would dynamically size both the width and the height, but I can't get it to do either. I've been working with the solutions provided here and here, but neither end up doing the trick. This is almost assuredly due to an implementation detail that I've screwed up.

In one of the above links, it mentioned that referencing the id of the div containing the content, so I wrapped my table in a div, but it didn't make a difference. I'll throw all my Internet points at someone who can help me out with this! :)

The code I'm currently using is included below and it has a hard-coded value of 1000 for newHeight just to prove that the resizing method works -- it does. Now I need to figure out how to get the height of content in the table so that I can dynamically set this. How do I get the height of the table (or probably more correctly the div wrapping the table) so that I can use it to calculate the necessary height? It seems that the table isn't generated until after I need it because I never get a value that makes sense.

SubsiteListAppPart.aspx

<WebPartPages:AllowFraming ID="AllowFraming" runat="server"/>

<html>
<head>
    <title></title>

    <script type="text/javascript" src="../Scripts/jquery-1.9.1.min.js"></script>
    <script type="text/javascript" src="/_layouts/15/MicrosoftAjax.js"></script>
    <script type="text/javascript" src="../Scripts/SubsiteListAppPart.js"></script>

    <link rel="Stylesheet" type="text/css" href="../Content/SubsiteListAppPart.css" />

    <script type="text/javascript">
        // Set the style of the client web part page to be consistent with the host web.
        (function () {
            'use strict';

            var hostUrl = '';
            if (document.URL.indexOf('?') != -1) {
                var params = document.URL.split('?')[1].split('&');
                for (var i = 0; i < params.length; i++) {
                    var p = decodeURIComponent(params[i]);
                    if (/^SPHostUrl=/i.test(p)) {
                        hostUrl = p.split('=')[1];
                        document.write('<link rel="stylesheet" href="' + hostUrl + '/_layouts/15/defaultcss.ashx" />');
                        break;
                    }
                }
            }
            if (hostUrl == '') {
                document.write('<link rel="stylesheet" href="/_layouts/15/1033/styles/themable/corev15.css" />');
            }
        })();
    </script>
</head>
<body>
</body>
</html>

SubsiteListAppPart.js

var context;
var web;
var parentWeb;
var user;
var spHostUrl;
var parentContext;
var webCollection;
var lists;
var senderId;

$(document).ready(
    function () {
        //Get the URI decoded SharePoint site url from the SPHostUrl parameter.
        spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));

        //Build absolute path to the layouts root with the spHostUrl
        var layoutsRoot = spHostUrl + '/_layouts/15/';

        $.getScript(layoutsRoot + "SP.Runtime.js", function () {
            $.getScript(layoutsRoot + "SP.js", execOperation);
        }
        );
    }
)

function getQueryStringParameter(urlParameterKey) {
    var params = document.URL.split('?')[1].split('&');
    var strParams = '';
    for (var i = 0; i < params.length; i = i + 1) {
        var singleParam = params[i].split('=');
        if (singleParam[0] == urlParameterKey)
            return decodeURIComponent(singleParam[1]);
    }
}

function execOperation() {
    // get context and then username
    context = new SP.ClientContext.get_current();
    web = context.get_web();
    parentContext = new SP.AppContextSite(context, spHostUrl);
    parentWeb = parentContext.get_web();
    getSubWebsToDisplay();
    var senderId;

    var params = document.URL.split("?")[1].split("&");
    for (var i = 0; i < params.length; i = i + 1) {
        var param = params[i].split("=");
        if (param[0].toLowerCase() == "senderid")
            senderId = decodeURIComponent(param[1]);
    }

    var newHeight = 1000,
        resizeMessage = '<message senderId={Sender_ID}>resize({Width}, {Height})</message>';
    if (senderId) {
        resizeMessage = resizeMessage.replace("{Sender_ID}", senderId);
        resizeMessage = resizeMessage.replace("{Height}", newHeight);
        resizeMessage = resizeMessage.replace("{Width}", "100%");

        window.parent.postMessage(resizeMessage, "*");
    }
}

function getSubWebsToDisplay() {
        // Get the available SharePoint subwebs, and then set them into
        // the context.
    if (context != undefined && context != null) {
        webCollection = parentWeb.getSubwebsForCurrentUser(null);
        context.load(webCollection);
        context.executeQueryAsync(Function.createDelegate
        (this, GetSubwebsToDisplaySuccess),
        Function.createDelegate(this, GetSubwebsToDisplayFail));
    }
}

function GetSubwebsToDisplaySuccess(sender, args) {
    // Success getting the subwebs. Set references to the subweb
    // elements and the list of available subwebs.
    var subwebEnumerator = webCollection.getEnumerator();

    // get the reference for the body
    var body = document.getElementsByTagName("body")[0];
    var tbl = document.createElement("table");
    var tblBody = document.createElement("tbody");
    // Traverse the elements of the collection, and load the name of
    // each list into the dropdown list box.
    var i = 1;
    while (subwebEnumerator.moveNext()) {
        var row = document.createElement("tr");
        for (var j = 1; j < 2; j++) {
            var cell = document.createElement("td");
            var a = document.createElement("a");
            a.innerHTML = subwebEnumerator.get_current().get_title();
            a.href = subwebEnumerator.get_current().get_url();
            cell.appendChild(a);
            row.appendChild(cell);
        }
        i++;
        tblBody.appendChild(row);
    }

    // put the <tbody> in the <table>
    tbl.appendChild(tblBody);
    // appends <table> into <body>
    body.appendChild(tbl);
    // sets the border attribute of tbl to 2;
    //tbl.setAttribute("border", "2");
    $('table').wrap("<div id='tblDiv'></div>");
}

function GetSubwebsToDisplayFail(sender, args) {
    // Lists couldn’t be loaded - display error.
    alert('failed to get list. Error:' + args.get_message());
}
0

I figured it out and the code can be seen at the end of this post. It did seem to be an issue with my asynchronous call context.executeQueryAsync(Function.createDelegate (this,GetSubwebsToDisplaySuccess), Function.createDelegate(this, GetSubwebsToDisplayFail)) not having completed by the time I was trying to find the height of the content. I moved the relevant bit of code to the end of the GetSubwebsToDisplaySuccess function and all was well. The disappointing part of all this is that my load time for the app part didn't increase significantly enough to use it in production. It went from a 57 second structured navigation load time to a 20 seconds app part load time. Oh well, I learned a bunch along the way.

var context;
var web;
var parentWeb;
var user;
var spHostUrl;
var parentContext;
var webCollection;

$(document).ready(
    function () {
        //Get the URI decoded SharePoint site url from the SPHostUrl parameter.
        spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));

        //Build absolute path to the layouts root with the spHostUrl
        var layoutsRoot = spHostUrl + '/_layouts/15/';

        $.getScript(layoutsRoot + "SP.Runtime.js", function () {
            $.getScript(layoutsRoot + "SP.js", execOperation);
        });
    }
)

function getQueryStringParameter(urlParameterKey) {
    var params = document.URL.split('?')[1].split('&');
    var strParams = '';
    for (var i = 0; i < params.length; i = i + 1) {
        var singleParam = params[i].split('=');
        if (singleParam[0] == urlParameterKey)
            return decodeURIComponent(singleParam[1]);
    }
}

function execOperation() {
    // get context and then username
    context = new SP.ClientContext.get_current();
    web = context.get_web();
    parentContext = new SP.AppContextSite(context, spHostUrl);
    parentWeb = parentContext.get_web();
    getSubWebsToDisplay();
}

function getSubWebsToDisplay() {
    // Get the available SharePoint subwebs, and then set them into
    // the context.
    if (context != undefined && context != null) {
        webCollection = parentWeb.getSubwebsForCurrentUser(null);
        context.load(webCollection);
        context.executeQueryAsync(Function.createDelegate
        (this, GetSubwebsToDisplaySuccess),
        Function.createDelegate(this, GetSubwebsToDisplayFail));
    }
}

function GetSubwebsToDisplaySuccess(sender, args) {
    // Success getting the subwebs. Set references to the subweb
    // elements and the list of available subwebs.
    var subwebEnumerator = webCollection.getEnumerator();

    // get the reference for the body
    var body = document.getElementsByTagName("body")[0];
    var tbl = document.createElement("table");
    var tblBody = document.createElement("tbody");
    // Traverse the elements of the collection, and load the name of
    // each list into the dropdown list box.
    var i = 1;
    while (subwebEnumerator.moveNext()) {
        var row = document.createElement("tr");
        for (var j = 1; j < 2; j++) {
            var cell = document.createElement("td");
            var a = document.createElement("a");
            a.innerHTML = subwebEnumerator.get_current().get_title();
            a.href = subwebEnumerator.get_current().get_url();
            cell.appendChild(a);
            row.appendChild(cell);
        }
        i++;
        tblBody.appendChild(row);
    }

    // put the <tbody> in the <table>
    tbl.appendChild(tblBody);
    // appends <table> into <body>
    body.appendChild(tbl);
    // sets the border attribute of tbl to 2;
    //tbl.setAttribute("border", "2");

    var senderId;

    var params = document.URL.split("?")[1].split("&");
    for (var i = 0; i < params.length; i = i + 1) {
        var param = params[i].split("=");
        if (param[0].toLowerCase() == "senderid")
            senderId = decodeURIComponent(param[1]);
    }

    var newHeight = document.body.scrollHeight,
        resizeMessage = '<message senderId={Sender_ID}>resize({Width}, {Height})</message>';
    if (senderId) {
        resizeMessage = resizeMessage.replace("{Sender_ID}", senderId);
        resizeMessage = resizeMessage.replace("{Height}", newHeight);
        resizeMessage = resizeMessage.replace("{Width}", "100%");

        window.parent.postMessage(resizeMessage, "*");
    }
}

function GetSubwebsToDisplayFail(sender, args) {
    // Lists couldn’t be loaded - display error.
    alert('failed to get list. Error:' + args.get_message());
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.