1

我正在实现一个非常简单的用例,但我不仅没有找到解决方案,而且找不到任何谈论它的文章,就好像我是唯一的一样。

我希望我的自定义 Javascript 在给定 SharePoint 网站的每个页面上执行。

容易,你会说。嗯,不。远非如此,就像 SharePoint 一样。

重现步骤 :

  • 创建开箱即用的发布网站
  • 使用我在下面描述的任何方式包括下面的自定义 javascript
  • 转到站点,到主页。这是一个发布站点,因此默认情况下,您应该在左侧导航窗格中至少默认包含“主页”和“文档”。
  • 第一次加载页面时,javascript 会执行。现在,单击“文档”。页面更改但未执行Javascript 。

那是因为 SharePoint 使用Ajax。即使MDS被禁用。它通过 URL 中的哈希 (#) 使用 Ajax。

例如,它转换了一个非常无害的链接,如下所示:

<a href src="/SitePages/Home.aspx">

单击它时进入此 URL:

https://your-url/sites/your-site/_layouts/15/start.aspx#/SitePages/Home.aspx

这是我的 Javascript :

if (ExecuteOrDelayUntilScriptLoaded && _spBodyOnLoadFunctionNames) {
    _spBodyOnLoadFunctionNames.push(ExecuteOrDelayUntilScriptLoaded(
        function () {
            alert("It's working!");
        }, "sp.js"));
} 

因此,我尝试了以下包含 Javascript 的方法:

  1. 通过用户自定义操作。我已经使用这个非常方便的页面来添加它,但这不相关。该操作已添加到站点,我可以在第一次加载时在 DOM 中看到 JS。但是当我点击页面中的链接并且SP使用Ajax之后,它不会再次执行它。
  2. 通过修改母版页——即:seattle.html。起初我以这种方式将其包含在其他本地包含项下:

<head runat="服务器">

...

<!--SPM:<SharePoint:ScriptLink language="javascript" name="suitelinks.js" OnDemand="true" runat="server" Localizable="false"/>-->

<!--SPM:<SharePoint:ScriptLink language="javascript" Name="~sitecollection/SiteAssets/MYJAVASCRIPT.js" runat="server"/>-->

但后来我读到了AjaxDelta(这里:https ://msdn.microsoft.com/fr-fr/library/office/dn456543.aspx ),我将我的包含(仍在标题中)移动到 <AjaxDelta> 中,就像这样:

<head runat="服务器">

...

<!--SPM:<SharePoint:AjaxDelta id="DeltaPlaceHolderAdditionalPageHead" Container="false" runat="server">-->

<!--SPM:<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server"/>-->

<!--SPM:<SharePoint:DelegateControl runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/>-->

<!--SPM:<SharePoint:ScriptLink language="javascript" Name="~sitecollection/SiteAssets/MYJAVASCRIPT.js" runat="server"/>-->

<!--SPM:</SharePoint:AjaxDelta>-->

...但没有任何效果。通过单击 SharePoint 的“托管”链接在同一站点的页面之间切换时,永远不会执行 Javascript。

我正在寻找一种能够优雅地处理 SharePoint 的 Ajax 的解决方案,而不是劫持页面上每个超链接的繁重和冒险的解决方案。例如,我尝试将我的代码挂钩到ajaxNavigate方法(例如:addNavigate),但我不确定我是否了解那里实际发生的情况以及它是否对我有任何帮助。

编辑 :

  • 似乎有一个共识(例如,最底部),无论如何都会执行用户自定义操作——因为据称 SharePoint 出于某种原因将他们的 ScriptLink 放入 AjaxDelta。好吧,这不是我亲眼目睹的。

  • 还有一个共识是这个问题可以通过使用“ RegisterModuleInit ”来解决。这对我也不起作用。

我非常困惑。我认为当用户单击链接然后单击“返回”时,这两种解决方案确实解决了导航问题。但它没有解决 SharePoint 巧妙的“托管”、充满 Ajax 的超链接。

4

1 回答 1

0

我终于找到了一个迄今为止似乎从未失败过的解决方案。这真是一种解脱。

简短回答:使用 asyncDeltaManager.add_endRequest

这个 MSDN 讨论提出了一种简单的实现方法: https ://social.msdn.microsoft.com/Forums/office/en-US/1ae292b4-3589-46f6-bedc-7bd9dc741f1b/javascript-code-to-execute-after -all-the-elements-and-css-are-loaded?forum=appsforsharepoint

$(function () {
  ExecuteOrDelayUntilScriptLoaded(function () {
      if (typeof asyncDeltaManager != "undefined")
           asyncDeltaManager.add_endRequest(MYCUSTOMCODE); //execute it after any ajax event
      else 
           MYCUSTOMCODE(); //execute it at first load
  }, "start.js");
});

这显示了如何将它正确地包含在 SharePoint 的循环中(使用 ExecuteOrDelayUntilScriptLoaded ) https://sharepoint.stackexchange.com/questions/171490/javacript-only-executed-on-first-page-load

完整的解决方案(对象“LefeCycleHelper”),由 Mx https://sharepoint.stackexchange.com/questions/192974/where-to-place-a-js-script-with-whom-i-need-to-get -an-div-id/193009#193009

//use an IIFE to create a scope and dont dirty the global scope
(function (_) {

// use strict to ensure we dont code stupid
'use strict';

var initHandlers = [];
var initMDSHandlers = [];

var ensureSharePoint = function (handler) {
    var sodLoaded = typeof (_v_dictSod) !== 'undefined' && _v_dictSod['sp.js'] != null && _v_dictSod['sp.js'].state === Sods.loaded;

    if (sodLoaded) {
        handler();
    } else {
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () { });
        SP.SOD.executeOrDelayUntilScriptLoaded(handler, 'sp.js');
    }
};

var initMDS = function () {
    for (var i = 0; i < initMDSHandlers.length; i++) {
        initMDSHandlers[i]();
    }
};

var init = function () {
    // Register MDS handler
    if ('undefined' != typeof g_MinimalDownload && g_MinimalDownload && (window.location.pathname.toLowerCase()).endsWith('/_layouts/15/start.aspx') && 'undefined' != typeof asyncDeltaManager) {
        asyncDeltaManager.add_endRequest(initMDS);
    } else {
        for (var i = 0; i < initHandlers.length; i++) {
            initHandlers[i]();
        }
    }
};

var registerInit = function (handler) {
    initHandlers.push(handler);
};

var registerInitMDS = function (handler) {
    initMDSHandlers.push(handler);
};

var domReady = (function (handler) {
    var fns = [];
    var listener;
    var loaded = (document.documentElement.doScroll ? /^loaded|^c/ : /^loaded|^i|^c/).test(document.readyState);

    if (!loaded) {
        document.addEventListener('DOMContentLoaded', listener = function () {
            document.removeEventListener('DOMContentLoaded', listener);
            loaded = 1;
            while (listener = fns.shift()) listener();
        });
    }

    return function (fn) {
        loaded ? setTimeout(fn, 0) : fns.push(fn);
    };
})();


var attachToLoad = function (functionToAttach) {
    registerInit(functionToAttach);
    registerInitMDS(functionToAttach);
   domReady(function () {
       init();
    });
};

_.AttachToLoad = attachToLoad;

// THIS WILL PROTECT YOUR GLOBAL VAR FROM THE GARBAGE COLLECTOR
window.LifeCycleHelper = _;
if (window.Function != 'undefined' && typeof (Function.registerNamespace) == 'function') {
    Function.registerNamespace('LifeCycleHelper');
}
})({});

var theCodeYouWantToRun = function () {
    alert('theCodeYouWantToRun');
};

window.LifeCycleHelper.AttachToLoad(theCodeYouWantToRun); 
于 2018-03-06T13:43:11.613 回答