zoukankan      html  css  js  c++  java
  • [转载]Customizing the Context Menu of Document Library Items

     

    Customizing the Context Menu of Document Library Items

    Each document in a document library has a context menu with items such as Check In, Check Out, View Properties, Edit Properties, and others. This menu is created by the AddListMenuItems JavaScript function of the Ows.js file located in the path, C:"Program Files"Common Files"Microsoft Shared"web server extensions"60"TEMPLATE"LAYOUTS"1033. The function starts as shown in the following example.

    Copy Code

    function AddListMenuItems(m, ctx)

    {

       if (typeof(Custom_AddListMenuItems) != "undefined")

       {

          if (Custom_AddListMenuItems(m, ctx))          

             return;

       }

       // ...

    }

    This code checks whether another function named Custom_AddListMenuItems exists, and if it does, it calls it. That function is not defined by Windows SharePoint Services itself but is a function that you can write. The function serves as an injection point to add your own menu items to the document's standard context menu. If the function returns a value of true, the standard AddListMenuItems exits immediately; otherwise, it adds the default items. Here is an example implementation that adds a new item called "Say hello" and a separator line. The new item command item shows a greeting message when clicked.

    Copy Code

    function Custom_AddDocLibMenuItems(m, ctx)

    {

       CAMOpt(m, 'Say hello', 'alert("Hello there!");

          ', '/images/greeting.gif');

       CAMSep(m);

       return false;

    }

    As you see, you can add a new item by calling CAMOpt, which takes as input the target menu (received as a parameter by the Custom_AddDocLibMenuItems function), the name of the item, the JavaScript that runs when the item is clicked, and the URL of an image shown to the left of the item. CAMSep adds the separator line.

    This example is simple to write and understand but is not realistic. You typically need to add new commands according to a number of rules and conditions that make up your business logic. For example, some commands may be available only to picture documents; others may be available only if the item is not checked out or according to the current user's roles.

    You could also retrieve some of this information from the JavaScript code, by using DHTML DOC to read them directly from the page's HTML, or from the ctx parameter that represents the context. However, in more complex cases, you must retrieve the list of available commands from the server, because only there you can run your business logic and perhaps get the commands from a custom database. Typically, you want to do this if you are implementing a workflow solution where each document has its own process state, with commands associated to it.

    The solution for this situation is to have the Custom_AddDocLibMenuItems dynamically call a custom ASP.NET page. This page takes the ID of the document library and the specific item on the query string, and returns an XML string containing all the information for the commands available for that particular document. These commands are available according to the document's process status (or some other custom business logic). The returned XML may be something like the following.

    Copy Code

    <?xml version="1.0" encoding="UTF-8" ?>

    <Commands>

       <Command>

          <Name><![CDATA[Say hello]]></Name>

          <ImageUrl><![CDATA[/images/greeting.gif]]></ImageUrl>

          <Script><![CDATA[alert('Hello there');]]></Script>

       </Command>

       ...other commands...

    </Commands>

    The sample page that generates this XML can return either one or two commands:

    ·         If the document is an image (its FieldType attribute is "GIF", "BMP", "JPG" or "PNG"), it returns a command that opens the file in a secondary browser window, without toolbars, menu bars, and status bar.

    ·         For any type of document, it returns a command that, when clicked, runs a search for that document's title on the Google search service.

    In reality, you could do both these things directly from the JavaScript function, but this is just an example to show how to write and call server-side logic from the client, for each document's context menu. The following code example shows the sample page's Load event handler.

    Copy Code

    SPWeb web = SPControl.GetContextWeb(this.Context);

    Guid listID = new Guid(this.Request.Params["ListID"]);

    int itemID = int.Parse(this.Request.Params["ItemID"]);

    SPListItem item = web.Lists[listID].Items.GetItemById(itemID);

    string fileUrl = (web.Url + "/" + item.File.Url);

    string fileName = item["Name"].ToString();

    this.Response.ClearHeaders();

    this.Response.ClearContent();

    this.Response.Cache.SetCacheability(HttpCacheability.NoCache);

    this.Response.AddHeader("Content-type", "text/xml" );

    string cmdPattern = @"<Command>

       <Name><![CDATA[{0}]]></Name>

       <ImageUrl><![CDATA[{1}]]></ImageUrl>

       <Script><![CDATA[{2}]]></Script>

    </Command>";

    this.Response.Write(@"<?xml version=""1.0"" encoding=""UTF-8"" ?>");

    this.Response.Write("<Commands>");

    string fileType = item["File_x0020_Type"].ToString().ToUpper();

    if ( fileType == "BMP" || fileType == "GIF" ||

       fileType == "JPG" || fileType == "PNG" )

    {

       string jsOpenWin = "window.open('" + fileUrl +

       "', '', 'menubar=no,toolbar=no,status=no,scrollbars=yes,resizable=yes');";

       this.Response.Write(string.Format(cmdPattern, "View in new window",

          Page.ResolveUrl("~/images/preview.gif"), jsOpenWin));

    }

    string jsSearch = "location.href='http://www.google.com/search?q=" +

       fileName + "';";

    this.Response.Write(string.Format(cmdPattern, "Search on the web",

       Page.ResolveUrl("~/images/search.gif"), jsSearch));

    this.Response.Write("</Commands>");

    this.Response.End();

    At this point, Custom_AddDocLibMenuItems is written as a generic function that uses the XMLHTTP Microsoft ActiveX object to send a request to the custom ASP.NET page. The function passes the current list and document IDs to the query string and then parses the returned XML. For each <Command> element it finds, it adds a new menu item with the specified name, image, and JavaScript URL, as shown in the following example.

    Copy Code

    <script language="javascript">

    function Custom_AddDocLibMenuItems(m, ctx)

    {

       var request;

       var url = ctx.HttpRoot +

          "/_layouts/CustomMenuItems/GetCommands.aspx?ListID=" +

          ctx.listName + "&ItemID=" + currentItemID + "&DateTime=" + Date();

       if ( window.XMLHttpRequest )

       {

          request = new XMLHttpRequest();

          request.open("GET", url, false);

          req.send(null);

       }

       else if ( window.ActiveXObject )

       {

          request = new ActiveXObject("Microsoft.XMLHTTP");

          if ( request )

          {

             request.open("GET", url, false);

             request.send();

          }

       }

      

       if ( request )

       {  

          var commands = request.responseXML.getElementsByTagName("Command");

          // for each command found in the returned XML, extract the name,

          // image Url and script, and a new menu item with these properties

          for ( var i = 0; i < commands.length; i++ )

          {

             var cmdName = commands[i].getElementsByTagName(

                "Name")[0].firstChild.nodeValue;

             var imageUrl = commands[i].getElementsByTagName(

                "ImageUrl")[0].firstChild.nodeValue;

             var js = commands[i].getElementsByTagName(

                "Script")[0].firstChild.nodeValue;

             CAMOpt(m, cmdName, js, imageUrl);

          }

          // if at least one command was actually added, add a separator

          if ( commands.length > 0 )

             CAMSep(m);

          // returning false makes SharePoint render the rest of the

             standard menu

          return false;

       }

    }

    </script>

    Notice that the function appends the current date and time to the query string of the GetCommands.aspx page that is called. This is done so that each request is different from a previous one, to avoid caching of the response XML. This is necessary if you are implementing a workflow solution, and a different user may change the document's state after you load the document library's page. If you consider that the Custom_AddDocLibMenuItems function is called every time the drop-down menu pops up, this trick allows you to retrieve the commands to the real current document state, without refreshing the whole page. Figure 3 shows the customized menu.

    Figure 3. The new items for the document's context menu

    In this sample implementation, GetCommands.aspx returns commands with simple JavaScript code associated to them. However, in a real workflow, you typically return JavaScript that executes another XMLHTTP request to a page that actually performs some server-side action on the clicked document.

     

  • 相关阅读:
    【神经网络】LSTM 网络
    【Linux】利用Xvfb关闭chrome的图形化输出
    性能测试面试题:如何找到并发数、平均响应时间、tps的最佳平衡点?
    jmeter引用jar包的3种方式
    flask如何返回真正意义上的json字符串?以及中文如何正常显示?
    记录一次群答问:requests获取cookie
    【笔试题】python文件操作
    JMeter5.1开发http协议接口之form表单脚本
    【笔试题】面向对象小测试(二)
    【笔试题】面向对象小测试(一)
  • 原文地址:https://www.cnblogs.com/jianyi0115/p/1105818.html
Copyright © 2011-2022 走看看