On Hover Popup

  • 4
  • Question
  • Updated 2 months ago
  • Answered
I've looked at a few other community posts, but I was wondering if anyone has some samples of on hover popups.  

I'm trying to create a on hover display for the reference field list using "li.ui-menu-item" but it's not working. I'm referencing .hover() https://api.jquery.com/hover/

Any help is appreciated. 
Photo of Josef Lagorio

Josef Lagorio

  • 3,260 Points 3k badge 2x thumb

Posted 1 year ago

  • 4
Photo of Josef Lagorio

Josef Lagorio

  • 3,260 Points 3k badge 2x thumb
bump
Photo of Josef Lagorio

Josef Lagorio

  • 3,260 Points 3k badge 2x thumb
Anyone?
Photo of Josef Lagorio

Josef Lagorio

  • 3,260 Points 3k badge 2x thumb
bump
Photo of Peter Hale

Peter Hale, Employee

  • 330 Points 250 badge 2x thumb
I found a lilttle hover popup tutorial here:
http://creativeindividual.co.uk/2011/02/create-a-pop-up-div-in-jquery/

I then used that example to update a template field in a table to implement it.  Here's what I did:

1. Put a wrapper at the bottom below the table with a little Rich Text editor with some text to show in the popup.
2. Rename the Unique ID of the wrapper.  For example "hoverText"
3. Add an In-line JS snippet to have the following:
(function(skuid){
var $ = skuid.$;
$(document.body).one('pageload',function(){

$(".hoverDiv").hover(
            function(e) {
                $("#hoverText").show()
                  .css('top', e.pageY)
                  .css('left', e.pageX)
                  .appendTo('body');
              }, function() {
                $("#hoverText").hide();
              }     
);
});
})(skuid);
4.  Add a template field to a table (or whereever you want the popup to appear with the following in the template:
<div class="hoverDiv">Some Text</div>

This is what my example looks like when I hover over my "Some Text" template.  I'm sure you can have many different variations here, but this could be a good start.


For the li.ui-menu-item, try doing an inspection to see if you're using the right element
Photo of Peter Hale

Peter Hale, Employee

  • 330 Points 250 badge 2x thumb
I think there's a way to get the row that you're hovering over.  Try this:
                // figure what row I'm on
                var row = $(this).parents(".nx-item");
                if ( row ) {
                    var rowData = $(row).data("object");
                    console.log(rowData);
                }
Photo of Peter Hale

Peter Hale, Employee

  • 330 Points 250 badge 2x thumb
This code snippet should be in the hover function (the first one, where it shows the element)
Photo of Josef Lagorio

Josef Lagorio

  • 3,260 Points 3k badge 2x thumb
Hmm...seems to be working well but no matter what I try, I cannot target the WhatId. I've tried looping through the object to grab the WhatId but that doesnt work either. 

I think
var rowObjectData = Object.values(rowData);
gets me closed, but still can't figure out how to go down one more level. 
Photo of Josef Lagorio

Josef Lagorio

  • 3,260 Points 3k badge 2x thumb
Yaahoooo! GOT IT! Thanks for the help, Peter! 

var whatid = rowData.row.WhatId; did the trick! 

(Edited)
Photo of sudhanshu arora

sudhanshu arora

  • 60 Points
Thank you sir. it helps me alot.
Photo of Jack Sanford

Jack Sanford, Champion

  • 9,550 Points 5k badge 2x thumb
Josef could you post your final solution? Trying to replicate something like this. Thank you both for sharing!
Photo of Parminder Dhillon

Parminder Dhillon

  • 140 Points 100 badge 2x thumb
Hi Arne


Could you post a working version of a sample skuid page with the hover working? I have struggled with the above and could not get it working.

Thanks
Photo of Arne-Per Heurberg

Arne-Per Heurberg

  • 2,354 Points 2k badge 2x thumb
Hi Parminder- are you looking for just the hover or the use of WhatId?
Photo of Parminder Dhillon

Parminder Dhillon

  • 140 Points 100 badge 2x thumb
Hi Arne,

I am looking for details on how to implement a hover (as defined in a Wrapper in the example above) when the mouse point passed over another wrapper control and its contents.

I am not sure what you mean by WhatId - It would be useful to pass the value of the record Id field of the data record displayed in the Wrapper the mouse is being moved over to the Hover component - but it is not critical.

Hope this makes sense!

Thanks in advance for your help. I am on the latest version of Spark.
Photo of Arne-Per Heurberg

Arne-Per Heurberg

  • 2,354 Points 2k badge 2x thumb
<skuidpage unsavedchangeswarning="yes" personalizationmode="server" showsidebar="true" useviewportmeta="true" showheader="true" theme="Classic">
<models>
<model id="Opporunity" limit="20" query="true" createrowifnonefound="false" datasource="salesforce" sobject="Opportunity">
<fields>
<field id="Name"/>
<field id="StageName"/>
<field id="OwnerId"/>
<field id="Owner.Name"/>
<field id="AccountId"/>
<field id="Account.Name"/>
</fields>
<conditions/>
<actions/>
</model>
<model id="Account_Tooltip" limit="1" query="false" createrowifnonefound="false" datasource="salesforce" sobject="Account" doclone="">
<fields>
<field id="Id"/>
<field id="Name"/>
<field id="OwnerId"/>
<field id="Owner.Name"/>
<field id="Type"/>
</fields>
<conditions>
<condition type="fieldvalue" value="" enclosevalueinquotes="true" field="Id" state="filterableoff" inactive="true" name="Id"/>
</conditions>
<actions/>
</model>
</models>
<components>
<skootable showconditions="true" showsavecancel="true" showerrorsinline="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" alwaysresetpagination="false" createrecords="true" model="Opporunity" buttonposition="" mode="read" allowcolumnreordering="true" responsive="true" uniqueid="sk-3ue6_n-357">
<fields>
<field id="Name" hideable="true" uniqueid="fi-3ueFJl-474" valuehalign="" type=""/>
<field id="AccountId" hideable="true" uniqueid="fi-3ueY1G-676" snippet="accountTooltip"/>
<field id="StageName" hideable="true" uniqueid="fi-3ueFJk-473" snippet="accountTooltip" type="CUSTOM"/>
<field id="OwnerId" hideable="true" uniqueid="fi-3ueFJl-475"/>
</fields>
<rowactions>
<action type="edit"/>
<action type="delete"/>
</rowactions>
<massactions usefirstitemasdefault="true">
<action type="massupdate"/>
<action type="massdelete"/>
</massactions>
<views>
<view type="standard"/>
</views>
</skootable>
<wrapper uniqueid="hoverText" cssclass="hoverText">
<components>
<richtext multiple="false" uniqueid="sk-31rd-545" model="Account_Tooltip">
<contents>&lt;p&gt;{{#Name}}Account:{{Name}} {{/Name}}&lt;/p&gt;
</contents>
</richtext>
</components>
<styles>
<styleitem type="background" bgtype="none"/>
<styleitem type="border"/>
<styleitem type="size" height="collapse" width="full"/>
</styles>
<interactions/>
<renderconditions logictype="and"/>
</wrapper>
</components>
<resources>
<labels/>
<javascript>
<jsitem location="inlinesnippet" name="accountTooltip" cachelocation="false">field = arguments[0];
var value = skuid.utils.decodeHTML(arguments[1]), 
metadata = field.metadata, 
$ = skuid.$; 

// Run the standard renderer and add a CSS class for tooltip
if (field.mode == 'read') { 
    field.element.addClass('hoverText');
    skuid.ui.fieldRenderers[metadata.displaytype][field.mode](field,value); 
}
if (field.mode == 'edit') {
    field.element.removeClass('hoverText');
    skuid.ui.fieldRenderers[metadata.displaytype][field.mode](field,value); 
}</jsitem>
<jsitem location="inline" name="onHoverAccountPopUp" cachelocation="false" url="">(function(skuid){
var $ = skuid.$;

$(document.body).one('pageload',function() {
  var moveLeft = 20;
  var moveDown = 10;
 
  $('.nx-field.hoverText').hover(function(e) {
    console.log('hey i am hovering');
    
    $ = skuid.$;
    
    var row = $
    (this).parents(".nx-item");

    var rowData = $ (row).data('object');
           if (row) {
            var accountId= rowData.row.AccountId;
            var accountModel = skuid.model.getModel('Account_Tooltip');
        var IdFilter = accountModel.getConditionByName('Id',false);

            //Set the Model Condition
            accountModel.setCondition(IdFilter, accountId);
            accountModel.updateData();
        }
      
    if (rowData.mode == 'read')  { 
      $('#hoverText').show(); 
    }}, 
    
    function() {
    $("#hoverText").hide();
    });
  $('.nx-field.hoverText').mousemove(function(e) {
     
    $('#hoverText').css('top', e.pageY+moveDown ).css('left', e.pageX - moveLeft).appendTo('body');
   });

});

})(skuid);

</jsitem>
<jsitem location="inlinesnippet" name="newSnippet" cachelocation="false">/* (function(skuid){
var $ = skuid.$;
$(function() {
  var moveLeft = 20;
  var moveDown = 10;
 
  $(".nx-field.hoverText").hover(function(e) {
    $ = skuid.$;
    
    var row = $
    (this).parents(".nx-item");

    var rowData = $ (row).data("object");
        if (row) {
            
            //var rowData = $ (row).data("object");
            var whatid = rowData.row.WhatId;
            var refString = String(whatid);
            var refLength = refString.substring(0, 3);
            
            var oppModel = skuid.model.getModel('opportunityPopUp');
        var oppidFilter = oppModel.getConditionByName('Id',false);
            var accountModel = skuid.model.getModel('accountPopUp');
            var accountidFilter = accountModel.getConditionByName('Id',false);
            var campaignModel = skuid.model.getModel('campaignPopUp');
            var campaignidFilter = campaignModel.getConditionByName('Id',false);

            if (refLength === "006"){
                
                    //Remove the Account and Campaign Model's conditions
                    campaignModel.setCondition(campaignidFilter, "null");
                campaignModel.updateData();
                accountModel.setCondition(accountidFilter, "null");
                accountModel.updateData();
                
                //Set the Opp Model Condition
                    oppModel.setCondition(oppidFilter, whatid);
                    oppModel.updateData();
                    }
            
            //Determine if the row's related to is an Account and update the accountPopup model
            else if (refLength === "001") {
                    
                    //Remove the Opp and Campaign Model's conditions
                oppModel.setCondition(oppidFilter, "null");
                oppModel.updateData();
                campaignModel.setCondition(campaignidFilter, "null");
                campaignModel.updateData();
                
                //Set the Account Model Condition
                accountModel.setCondition(accountidFilter, whatid);
                    accountModel.updateData();
                        
                    }

            //Determine if the row's related to is an Campaign and update the campaignPopup model
            else if (refLength === "701") {
                
                    //Remove the Opp and Account Model's conditions
                oppModel.setCondition(oppidFilter, "null");
                oppModel.updateData();
                accountModel.setCondition(accountidFilter, "null");
                accountModel.updateData();
                
                    //Set the Campaign Model Condition
                    campaignModel.setCondition(campaignidFilter, whatid);
                    campaignModel.updateData();
                    }
        }
        
    if (rowData.mode == 'read')  { 
      $('#hoverText').show(); 
    }}, 
    
    function() {
    $("#hoverText").hide();
    });

  $(".nx-field.hoverText").mousemove(function(e) {
    $("#hoverText").css('top', e.pageY + moveDown).css('left', e.pageX + moveLeft);
   });

});

})(skuid);

*/</jsitem>
</javascript>
<css>
<cssitem location="inline" name="onHoverCSS" cachelocation="false">/* HOVER STYLES */
#hoverText {
  display: none;
  position: absolute;
  width: auto;
padding: 10px;
  background: white;
  color: #000000;
  border: 2px solid #145db3;
  font-size: 90%;
  z-index: 10000;
  box-shadow: 2px 4px 5px 0 #515151;
  border-radius: 1em;
}
</cssitem>
</css>
<actionsequences uniqueid="sk-3ud-PP-310"/>
</resources>
<styles>
<styleitem type="background" bgtype="none"/>
</styles>
</skuidpage>

Photo of Arne-Per Heurberg

Arne-Per Heurberg

  • 2,354 Points 2k badge 2x thumb
Hi Parminder, I was goofing around with it but have included (commented out)Josef's WhatId solution as well. I don't use the same objects and was just doing proof of concept. lmk if you need the WhatId to work. I will be looking at that shortly. This is working on the latest SPARK APIv1. Cheers
Photo of John Dahlberg

John Dahlberg, Champion

  • 3,914 Points 3k badge 2x thumb
For those wishing to get more sophisticated with the WhatId, here's a code segment that identifies the object type from a polymorphic field within a Field Snippet.  This uses Skuid's API to match the field's lookup value from the available objects within the lookup field.  That makes it dynamic and agnostic to the object selected within the lookup field.  That way you don't have to specify the object structure in the javascript.  This also works for other polymorphic field like owner and File lookup references.   

        skuid.$.each(field.metadata.referenceTo,function(){
            if (this.keyPrefix == fieldprefix){
                objectname = this.label.replace(/\s+/g, '_').replace('&','and');
            }
        });

We use this to dynamically render include pages in hover and popup displays, similar to Salesforce Classic native hover content.  With consistent naming conventions, you can leverage a generalized utility to work across Salesforce's object structure.  Here's an example of generating a popup utility based on dynamically determining the object type and passing it as a variable to another snippet:

        skuid.snippet.getSnippet('PopupPageInclude')({
            row: field.row,
            model: field.model,
            name:  fielddisplay,
            fieldId: value,
            objname: objectname,
            template: objectname+'Detail',
        });

Here's the generalized popup utility (PopupPageInclude Snippet), which will work for any Salesforce object where there's a matching page defined: 

var context = arguments[0];
var popupXMLString = 
'<popup title="'+context.objname.replace(/_/g, ' ')+': '+context.name+'" width="90%">'
+ '<components>'
+'<includepanel type="skuid" uniqueid="popupPageInclude" pagename="SF_'+context.template+'" module="" querystring="Id='+context.fieldId+'" showloading="false"/>'
+'</components>'
+'</popup>';
var popupXML = skuid.utils.makeXMLDoc(popupXMLString);
popup = skuid.utils.createPopupFromPopupXML(popupXML);


To get this to work, you would also need pages defined that can receive an Id parameter and be titled accordingly:

SF_OpportunityDetail
SF_CampaignDetail
SF_UserDetail
etc.
Photo of John Dahlberg

John Dahlberg, Champion

  • 3,914 Points 3k badge 2x thumb
 One callout is that the replace functions convert the objectname to a more usable string by replacing spaces with underscores and swapping out the "&" character (i.e. D&B company), which will cause an XML error.
Photo of Arne-Per Heurberg

Arne-Per Heurberg

  • 2,350 Points 2k badge 2x thumb
thanks John. That is on the menu for this week :)
Photo of John Dahlberg

John Dahlberg, Champion

  • 3,914 Points 3k badge 2x thumb
Same concept can work for hover content:

var showInsightPage = function(event){
    if (cellElem[0].childNodes[0].classList[0] !== "InsightText"){
    cellElem[0].childNodes[0].setAttribute("class", "InsightText");
        var tooltip = document.createElement('div');
        tooltip.setAttribute("class", "InsightText-tooltip");

        skuid.$.each(field.metadata.referenceTo,function(){
            fieldprefix = value.substring(0,3);
            if (this.keyPrefix == fieldprefix){
                objectname = this.label.replace(/\s+/g, '_').replace('&','and');

        var hoverTemplate = 'SF_Hover_'+objectname;
        var hoverContent = 
            '<includepanel type="skuid" uniqueid="" pagename="'+hoverTemplate+'" module="" querystring="Id='+value+'" showloading="false"/>';
        var includeXML = skuid.utils.makeXMLDoc(hoverContent);
        var include = skuid.component.factory({ definition: includeXML});
        include.element.appendTo(tooltip);        

            }
        });
    cellElem[0].childNodes[0].appendChild(tooltip);


    }
};


Here's the CSS along with some Skuid specific tweaks:

.InsightText{
     color:#000;
     display:inline;
     position:relative
}
.InsightText-tooltip{
     display:block;
     visibility:hidden;
     overflow-y:auto;
     overflow-x:visible;
     box-sizing:border-box;
     height:0;
     cursor:help;
     background:#D6E0E1;
     color:#000;
     font-size:14px;
     z-index:9999;
     position:absolute;
     width:300px;
     border-radius:5px;
     box-shadow: 0 2px 2px 0 #6D6E70;
     left: 120px;
     bottom: 35px;
}
:hover+.InsightText-tooltip{
     margin-bottom:0;
     height:auto;
     visibility:visible;
     padding:3px 3px;
     z-index:9999;
     display: block;
}
.InsightText-tooltip .nx-page{
    background:transparent;
}
.InsightText-tooltip .nx-page-content{
    background:transparent;
}
.InsightText:hover .InsightText-tooltip{
    display: block;
}
.InsightText-tooltip:hover{
    display:block;
}
.InsightText-tooltip .nx-basicfieldeditor-section{
    margin:0;
    
}
.InsightText-tooltip .nx-basicfieldeditor-item{
    padding:0;
}
.InsightText-tooltip .nx-basicfieldeditor-item-label{
    padding: 1px 0 1px 0;
}
Photo of John Dahlberg

John Dahlberg, Champion

  • 3,914 Points 3k badge 2x thumb
Also - add this to the snippet:

field.element.on('click',"a",showPopupPageInclude);
Photo of John Dahlberg

John Dahlberg, Champion

  • 3,914 Points 3k badge 2x thumb
Sorry - wrong function. this is the hover one:

field.element.on('mouseover',"a",showInsightPage);