1,804 articles and 14,876 comments as of Saturday, May 14th, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Thursday, November 5, 2009

JQuery For Everyone: Live LoadTip

This code is nothing new to the wonderful people who help support EndUserSharePoint by attending our online workshops. But if you haven’t had a chance to attend the online workshop, this example code replaces the AOP LoadTip example.

I mentioned in a previous post how event delegation, using jQuery’s live events, can create a listener waiting for an event no matter where it happens. By handling the event target, we can achieve the same results as the AOP version with more elegance.

<script type="text/javascript">
    if(typeof jQuery=="undefined"){
        var jQPath="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/";
        document.write("<script src='",jQPath,"jquery.min.js' type='text/javascript'><\/script>");
    }
</script>
<style type="text/css">
    #loadTip {
        background: #6F9DD9;
        color: #fff;
        border: 2px solid #6F9DD9;
        font-size: 10px;
        padding: 3px;
        width: 342px;
        display: none;
        position: absolute;
        text-align: right;
    }
    #tipContent {
        background: #fff;
        padding: 3px;
    }
</style>
<script type="text/javascript">
/*
 * Copyright (c) 2009 Paul Grenier (endusersharepoint.com)
 * Licensed under the MIT (MIT-LICENSE.txt)
 */
(function () {
    jQuery.fn.calcHTML = function () {
        var arrayList = $(this);
        arrayList = $.grep(arrayList, function (e, i) {
            return ($(e).text().match(/&lt\;.+?&gt\;|<.+?>/));
        });
        return $(arrayList).each(function (i, e) {
            $(e).html($(e).text().replace(/&lt;(.+?)&gt;/g, '<$1>'));
        });
    };
    var handleError = function () {
        return true;
    },
    createLoadTip = function () {
        var html = "<span>click to close </span>" +
            "<img style='vertical-align:text-top;' " +
            "src='/_layouts/images/menudark.gif' alt=''/>";
        $(document.createElement("div")).attr("id", "loadTip").html(html).appendTo("body");
        $(document.createElement("div")).attr("id", "tipContent").appendTo("#loadTip");
        $("#loadTip").click(function (e) {
            $("#loadTip").hide();
        });
    },
    defaults = {
        links:  "a[href*='DispForm.aspx']",	//tags that trigger a preview
        type:   "link",				//descriptive name sometimes used in cleanupCSS()
        key:    "a",                            //find the target url by this key element's attribute
        target: "",                             //specify the target
        suffix: "",				//appended to the target url
        delay:  500,				//delay in ms
        selector:   "table.ms-formtable:first",	//selector used on target page
        remove: "",				//selector(s) of removed elements from target page
        source: "",				//source parameter appended to urls in preview
        html:   "td[id='SPFieldCalculated']"	//fields needing re-rendering
    },
    cleanupCSS = function (p, o) {
        switch (o.type) {
        case "discussion":
            //nothing to do
            break;
        default:
            $("h3.ms-standardheader", p).css({"font-size": "1em"});
            $("td", p).removeAttr("width");
            $("td.ms-formbody[cellIndex='1']", p).css({width: "100%"});
        }
    },
    callback = function (event, p, o) {
        if (p.contents().length === 0) {
            return setTimeout(callback(event, p, o), 100);
        }
        $("#loadTip").show();
        var r = o.remove,
            h = o.html,
            a = event.target.href,
            x = event.pageX,
            winx = $(window).width(),
            y = event.pageY,
            winy = $(window).height(),
            ly = p.height(),
            lx = p.width();
        if (ly + y + 22 > winy) {
            y = y - ly - 22;
        }
        if (lx + x + 9 > winx) {
            x = x - lx - 9;
        }
        if (y < 0) {
            y = 0;
        }
        if (ly > winy) {
            $("#loadTip").css({"overflow-y": "auto", "height": winy});
        }
        if (r && r.length > 0) {
            $(r, p).remove();
        }
        if (h && h.length > 0) {
            $(h, p).calcHTML();
        }
        $("#loadTip").css({"top": y, "left": x});
    },
    fire_preview = function (e, p, o) {
        p.empty();
        p.load(o.target + o.suffix + " " + o.selector, function () {
            p.data("loadTip", o.target);
            cleanupCSS(p, o);
            callback(e, p, o);
        });
    },
    bind = function (p, options) {
        window.onerror = handleError;
        var o = $.extend({}, defaults, options);
        $(o.links).live("mouseover", function (event) {
            var elm = $(event.target);
            switch (o.key) {
            case "a":
				if (elm[0].tagName == "A") {
					o.target = elm.attr("href");
				} else {
					o.target = elm.parents("a:first").attr("href");
				}
                break;
            case "table":
                elm = elm.parents("table[ctxname]");
                o.target = "/" + elm.attr("dref").replace(/\s/g, "%20") +
                "/Forms/DispForm.aspx?ID=" + elm.attr("id");
                break;
            case "img":
                elm = elm.parents("a");
                o.target = elm.attr("href");
                break;
            default:
            //fall through to pass target override
            }
            $("#loadTip").css({"top": -1000, "left": -1000, "height": ""});
            if (loadTip.timer) {
                clearTimeout(loadTip.timer);
            }
            if (p.data("loadTip") === o.target) {
                return callback(event, p, o);
            }
            loadTip.timer = setTimeout(function () {
                fire_preview(event, p, o);
            }, o.delay);
            event.stopImmediatePropagation();
        });
        $(o.links).live("mouseout", function (event) {
            clearTimeout(loadTip.timer);
            event.stopImmediatePropagation();
        });
    };
    loadTip = function (options) {
        if ($("#loadTip").length === 0) {
            createLoadTip();
        }
        bind($("#tipContent"), options);
    };
}());
$(function(){
    loadTip();
    //loadTip({type: "wiki", links: "a[href*='.aspx']:has(img.ms-hidden)", key: "table"});
    //loadTip({type: "thumbnail", links: "a[href*='Forms/DispForm.aspx']", key: "img"});
    //loadTip({type: "person", links: "a[href*='userdisp.aspx']", suffix: "&Force=1"});
    //loadTip({type: "discussion", links: "a[href*='Flat.aspx']", selector: "table.ms-disc", remove: "[id^='ToggleQuotedText'], tr.ms-viewheadertr"});
    //loadTip({type: "excel document", links: "a[href$='.xls']:has(img.ms-hidden)", key: "table"});
    //loadTip({type: "excel document", links: "a[href$='.xlsx']:has(img.ms-hidden)", key: "table"});
    //loadTip({type: "word document", links: "a[href$='.doc']:has(img.ms-hidden)", key: "table"});
    //loadTip({type: "word document", links: "a[href$='.docx']:has(img.ms-hidden)", key: "table"});
    //loadTip({type: "powerpoint document", links: "a[href$='.ppt']:has(img.ms-hidden)", key: "table"});
    //loadTip({type: "powerpoint document", links: "a[href$='.pptx']:has(img.ms-hidden)", key: "table"});
});
</script>

I commented out several examples of “loatTip-able” links. By default, only the items pointing to a dispform.aspx page will be displayed. Keeping with the traditions of jQuery plugins, there are lots of options which can change the behavior of tip box.

View all entries in this series: PaulGrenier-JQuery for Everyone»
Entries in this series:
  1. JQuery for Everyone: Accordion Left Nav
  2. JQuery for Everyone: Print (Any) Web Part
  3. JQuery for Everyone: HTML Calculated Column
  4. JQuery for Everyone: Dressing-up Links Pt1
  5. JQuery for Everyone: Dressing-up Links Pt2
  6. JQuery for Everyone: Dressing-up Links Pt3
  7. JQuery for Everyone: Cleaning Windows Pt1
  8. JQuery for Everyone: Cleaning Windows Pt2
  9. JQuery for Everyone: Fixing the Gantt View
  10. JQuery for Everyone: Dynamically Sizing Excel Web Parts
  11. JQuery for Everyone: Manually Resizing Web Parts
  12. JQuery for Everyone: Total Calculated Columns
  13. JQuery for Everyone: Total of Time Differences
  14. JQuery for Everyone: Fixing Configured Web Part Height
  15. JQuery for Everyone: Expand/Collapse All Groups
  16. JQuery for Everyone: Preview Pane for Multiple Lists
  17. JQuery for Everyone: Preview Pane for Calendar View
  18. JQuery for Everyone: Degrading Dynamic Script Loader
  19. JQuery for Everyone: Force Checkout
  20. JQuery for Everyone: Replacing [Today]
  21. JQuery for Everyone: Whether They Want It Or Not
  22. JQuery for Everyone: Linking the Attachment Icon
  23. JQuery for Everyone: Aspect-Oriented Programming with jQuery
  24. JQuery for Everyone: AOP in Action - loadTip Gone Wild
  25. JQuery for Everyone: Wiki Outbound Links
  26. JQuery for Everyone: Collapse Text in List View
  27. JQuery for Everyone: AOP in Action - Clone List Header
  28. JQuery for Everyone: $.grep and calcHTML Revisited
  29. JQuery for Everyone: Evolution of the Preview
  30. JQuery for Everyone: Create a Client-Side Object Model
  31. JQuery for Everyone: Print (Any) Web Part(s) Plugin
  32. JQuery for Everyone: Minimal AOP and Elegant Modularity
  33. JQuery for Everyone: Cookies and Plugins
  34. JQuery for Everyone: Live Events vs. AOP
  35. JQuery for Everyone: Live Preview Pane
  36. JQuery for Everyone: Pre-populate Form Fields
  37. JQuery for Everyone: Get XML List Data with OWSSVR.DLL (RPC)
  38. Use Firebug in IE
  39. JQuery for Everyone: Extending OWS API for Calculated Columns
  40. JQuery for Everyone: Accordion Left-nav with Cookies Speed Test
  41. JQuery for Everyone: Email a List of People with OWS
  42. JQuery for Everyone: Faster than Document.Ready
  43. jQuery for Everyone: Collapse or Prepopulate Form Fields
  44. jQuery for Everyone: Hourly Summary Web Part
  45. jQuery for Everyone: "Read More..." On a Blog Site
  46. jQuery for Everyone: Slick Speed Test
  47. jQuery for Everyone: The SharePoint Game Changer
  48. JQuery For Everyone: Live LoadTip
 

Please Join the Discussion

39 Responses to “JQuery For Everyone: Live LoadTip”
  1. Robin says:

    Paul,

    The old version allowed one to popup a users details when the cursor was placed over a user name in the “assigned to” column. This made it convenient to view the “assigned to” users phone number, email and other details. This new version seems to be missing this function. Is that by design?

  2. AutoSponge says:

    Robin,

    Remove the comment (”//”) from the third commented example. It has type: person.

  3. domdom says:

    I tried this script on a link list and it didn’t work. Apparently the column linked to the DisplayForm is shown as an image which sits above the A itself. I had to add the following if code to the binding fucntion:

    case "a":
      o.target = elm.attr("href");
      if (o.target == ""){
        elm = elm.parents("a");
        o.target = elm.attr("href");
      }
      break;
    

    Otherwise it works beautifully.
    Thanks again for all the good work!
    Dominique

  4. Paul says:

    Hello Paul,

    This is great. I’m getting strange behavior on the Month view for events that span multiple days as they are not popping up when hovering over. On single day view and weekly view the multiple day events work fine.

    Single day events work fine on any view.

    Can you duplicate this? Any ideas?

  5. Ravi says:

    Hi,
    I have a sharepoint page in which i have added the calendar view to a webpart. I also have CEWP below that contains this script. I am able to see only the url in the popup. It is not showing Title, location, start time etc. What i am missing. Correct me please…..

  6. AutoSponge says:

    @Paul,

    I made a slight change to the code that should now work with multi-day events. You’ll need to copy/paste the new version.

    @Ravi,

    This sounds like a custom page. CSS changes, or customized DispForm.aspx can cause things not to to work. I’ve only tested this with default pages and theme.

  7. Paul says:

    Thank you – works perfectly!

  8. Ravi says:

    I found the problem in webpart page. The actual jquery works based on [[ if(!group)group="#MSO_ContentTable"; ]] MSO_ContentTable as main content. If you put this in webpart[custom] page, it will not work. Get the view source of your page and find out the main content id[in my case it is “ctl00_MSO_ContentDiv”. It is working perfectly.

    Thank you very much.

  9. Timmy says:

    I have tried inserting the above code in CEWP on the page with my list items, and it is not working (no pop-up box). Do I need to add this code to the “last version” of LoadTip to make this work?

  10. Alex says:

    Paul, you have amazing work! Thanks so much!
    I have implemented the tooltip in a CEWP to show list items in several webparts on my “dashboard” page and it works flawlessly, except for 2 scenarios:

    1. The tooltip pops up BEHIND some javascript or flash components. I have tried to add in the z-index in the css with no luck.

    2. I have two columns I would like to show: title and message. Sometimes the messsage has long links in it and a lot of text and people usually copy and paste the text from an email which results in weird text. The pop-up in this case become huge (literally takes up the whole window) and due to issue 1, can barely be seen at times.

    Your help is greatly appreciated!
    Thanks again!
    Alex

  11. SteveC says:

    I have a puzzle on the “remove” option
    I have a document library with 3 columns, “Title, Name, and URL” – which is a hyperlink.

    remove: “td[id!='SPFieldURL']” does what I want — it just shows a URL in the hover form. (It oddly doesn’t show the field name though).

    However, remove: “td[id='SPFieldTitle'],td[id='SPFieldName']” does not behanve as expected. It shows ALL fields, and including all 3 titles, and just “whites out” the content od the removed items.

    Have you tried this?

  12. SteveC says:

    Actaully, now that I read the above post I’m starting to understand how this works — the behavior makes sense.

    So the question becomes: Is there any way to select entire Fields from the DispForm and choose not to show them?

  13. SteveC says:

    This syntax will remove specific unwanted rows : I’m sure there is a more elegant way of doing this as this is a manual process.

    remove: “tr:eq(0),tr:eq(1),tr:eq(2),tr:eq(3),tr:eq(4),tr:eq(5),tr:eq(6),tr:eq(7)”

    The above removes numbered occurences of a – entire row from the DispForm.aspx file. Only useful if you use this in a specific document library that you know which columns you don’t want to display.

  14. Jason says:

    Requote:
    I have tried inserting the above code in CEWP on the page with my list items, and it is not working (no pop-up box). Do I need to add this code to the “last version” of LoadTip to make this work?

    Am I missing something here (obviously). How dod I get this to work?

  15. SteveC says:

    To get it to work I had to enable (uncomment) the lines at the bottom of the code. There was no “default” tooltip. So, if you want it to work on a Microsoft Word .doc or .docx, uncomment those lines.

  16. David Phillips says:

    (For ‘Field’ read ‘Column’)Great piece of coding and I love the enhancement in this version that gives the ability to remove field data from the display which I’ve used to hide around 8 data fields. However the ToolTip height is not being adjusted to take account of the hidden data and there is a lot of blue space at the bottom. Is it possible to set the height to adjust dynamically based on the fields displayed?

  17. David Phillips says:

    Ignore my last email about ‘removing’ data displayed and height adjustment, must have been a quirk when viewing still in Edit mode. Once saved and published it works perfectly, thanks again.

    David

  18. Timmy says:

    Does this work on a List? I am unable to get this to work by entering in CEWP.

  19. AutoSponge says:

    @Timmy,

    Yes, it was primarily designed for a list. Make sure your list items have links to the default DispForm.aspx page. If you use something else, you’ll need to adjust the script/configuration as needed.

  20. Mylene says:

    I’m using Internet Explorer 7 to view this site but cannot view the code due to page errors. Can you email me the code please. It is exactly what I’m looking for to use to preview data in a calendar event.
    Thank You :-)

    • Mylene – This is not a page error. We have just migrated the site to a new server and have not finished updating the code content. Give me five minutes and the code in this article will be available. — Mark

  21. Ron says:

    Hi Paul,
    I have one question which is not related to above post but i don’t know how to contact you so i am going to ask here

    How can i traverse HTML Comments in DOM using Jquery ?do you have any idea on this

    Thanks

  22. AutoSponge says:

    Ron,

    Normally comments are not parsed, so the only method I can think of involves using jQuery’s AJAX methods to call the page as a text file then use regex filters to find the comments in the text.

  23. Ron says:

    Thanks Paul,
    I thought there should be method like in JavaScript we can use get ElementbyTagName(”!”) .

    Thanks for Reply

  24. AutoSponge says:

    I don’t know if this is the most efficient method but it works and seems to do the job quickly (should work in all browsers):

    function findComments(node){
    	var node = node ? node : this.document,
    		arr = node.childNodes,
    		i = arr.length,
    		output = [], input = [], k;
    
    	while (i--) {
    		if (arr[i].nodeType === 8) {
    			output.push(arr[i]);
    		} else if (arr[i].hasChildNodes()) {
    			input = findComments(arr[i]);
    			k = input.length;
    			while(k--){
    				output.push(input[k]);
    			}
    		}
    	}
    
    	return output;
    }
    
    findComments();
    
  25. Ron says:

    Thanks Paul

  26. Ron says:

    Hi Paul;
    I was Trying to Set Value in People Picker Control with Current Logged in User in sharepoint.
    So far I have done following Jquery which give me Current logged in User but i cant set it to People Picker.

    Here is Jquery

    $(document).ready(function() {
         var CurrentUser = $("a:contains('Welcome')").text();
         var User = CurrentUser.substr(8,CurrentUser.length);
         $("textarea[title='People Picker']").text(User);
    });

    I know i doing something silly here thats why its not working can you please suggest me

    Thanks

  27. AutoSponge says:

    @Ron,

    See my examples of using the people picker field http://www.endusersharepoint.com/2009/04/20/jquery-for-everyone-pre-populate-form-fields/ (line 53) and http://spff.codeplex.com/. There are really two fields, a textarea and a div.

    $("textarea[title='People Picker']")
    $("div[title='People Picker']")

    For the textarea you want to update the val() or .value. For the div, you want to update the text() or html().

  28. Gus says:

    Hi, I originally asked this question in the wrong post so I’ll reiterate here. We’re using the above script but need to set its target to a different support file, lets say DispForm2.aspx. Changing or hardcoding the target doesnt appear to be working, it still fetches the value of the old DispForm file. I’ve checked the target attribute in the fire_preview function and it does point to the new file we specified, however it doesnt work.

    Any clue as to why? I did take your suggestion in your reply, but it did not work sadly.

  29. AutoSponge says:

    @Gus,

    In the bind function (line 117), target is selected from the DOM based on the target type (SharePoint puts the link in different places). You want this to be dynamic so it gets the right ID value. The target option you can pass is an override, it will not pick the link up dynamically but always use the hardcoded override (think static page).

    You probably just need to change links option to a[href*='DispForm2.aspx'] and if you customized that form, you’ll need to change the selector as well (targets the area of the page to be previewed).

  30. Gus says:

    Thanks for your reply, I’ve managed to solve the problem. It was a combination of issues, illegal characters in the URL string combined with the fact that overriding the target attribute using the function paramater doesn’t work, because a link is always issued a value in your if clause, no matter what the value sent in was or what the default target was.

    Anyway, keep up your good work.

  31. Jim says:

    Is there a way to get the popup window to close without clicking on it? maybe a timer

  32. Joel says:

    1st of all thank you for this script.

    I have a problem with this one, I have document library with folder, it works perfectly when you put a file at the root folder of the document library but if you put the file in another level the script doesn’t work…
    There’s a solution with that ?

    Thank you very much.

  33. Marc S says:

    Hi AutoSponge,

    Thanks for providing this useful script.

    I’m attempting to use it to display the attached items on a list item and I’m getting some odd behaviour. When I define parameters to remove rows from the DispForm like SteveC in a previous post ( “tr:eq(0),tr:eq(2)”) the first time the LoadTip is displayed correctly. If I then close the tip and hover over the link again the LoadTip displays incorrectly.
    (IE the list has five columns and I am displaying column2, column4, and column5 in the LoadTip, on the second display of LoadTip only column4 is displayed, after that nothing is displayed).

    Is there a better way to define the selectors of removed rows from the target page?

    Cheers,
    Marc S

  34. Christy says:

    Is it possible to point the tip to come up on a “name” not “title?

  35. Tony Parker says:

    Hi, love the solution but am struggling with one problem.

    If I hover over my loadtip url at the top of the page it appears as it should at the top of the page but the further down the page I go it starts to appear next to my mouse icon where as I need it to start at the top of the page. Is there a way to control this behaviour?

    • Michael says:

      Hello Paul, hello all,
      run into the same problem like Mark C. does. Repetetive hovering over the same list element decreases the number of shown informations, ends up in an empty box.

      Refresh of webpage (F5) fix this for the next view, then again rows are reduced.

      I am only interested to display one row, so I can get the informations about attachments (mainly name/title of attachment). This is the last row in my view.

      So iI would aks for two tipps, if possible:

      a) Can you show me how I can only address the Attachment part of my list?
      b) Or can can show me to touch only some elements out of the list (remove all, add #1,#5,#x)?

      Finally: Thanks for the script as is, I always have learned from this (and sometimes I understand more of the code behind as with this example)

      Thanks a lot for your work!

      Kind regards
      Michael

  36. Ben says:

    Hi there,
    Great bit of code that I can really see being useful on my current project.

    A question for the people here — has anyone got this working once a regular list has been converted to a Data View Web Part in SPD?

    I have found that the tooltips do not appear and that a “Stack overflow at line 30″ error is intermittently thrown.

    Anyone else discovered a workaround for this?

    Many thanks
    Ben


Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!