Spring16 Community Builder/Lightning: Javascript in can’t find ElementById on lightning component on page

With the introduction of Spring ’16 (currently in Preview), the Community Builder for Template based communities like Napili was updated to allow access to the <head> of the page similarly to how you could access scripts in Site.com Studio previously. This allows for the addition of external javascript to the page. I have been having a lot of trouble implementing Salesforce Live Agent into a lightning component so I thought this would be a huge win for me, allowing me to put the javascript in the head where it belonged the whole time, and make sure it always executes.

However, for whatever reason – it seems that the javascript loading in the <head> is unable to find the ElementById in the body? In the below code examples, you will see the head where I drop in Salesforces javascript code for Live Agent buttons, which uses getElementById to display a different element if offline/online. You’ll see that I added console.logs to try to find a fault. All 3 console.logs show up in the console, so its definitely reaching them all.

Also, when I manually view the page source of the community page where the lightning component is, and manually try to do a Find for the ElementID, the only reference I find in the source code is my single reference in the <head> – the body doesn’t even have any content that resembles the html markup in my lightning component.

Is this issue being caused because…:

  1. The <head>‘s inability to see the elements/IDs of elements within lightning components on the page?
  2. The <head> initializes before the lightning component is rendered and so there is no Element by that ID to find at the time of execution?
  3. The ID doesn’t show up in the source of the page when manually searching so the <head> probably can’t see it either?
  4. Some other reason that I can’t think of?

Your time and insight are appreciated!

Live Agent Deployment Javascript in <head>:

<script type='text/javascript'>
    liveagent.init('https://d.la4-c1cs-was.salesforceliveagent.com/chat', '*****Removed*****', '*****Removed*****');
    console.log('MSIMM - Live Agent Initialized');
</script>

<script type="text/javascript">
    if (!window._laq) { 
        window._laq = []; 
        console.log('MSIMM - !window._laq');
    }
    window._laq.push(function(){
        liveagent.showWhenOnline('ABCD1234',     document.getElementById('liveagent_button_online_ABCD1234'));
        liveagent.showWhenOffline('ABCD1234',     document.getElementById('liveagent_button_offline_ABCD1234'));
        console.log('MSIMM - window._laq.push');
    });
</script>

The ElementIDs above are found in a lightning component on our home page. It is a very simple component that is mostly HTML:

<aura:component implements="forceCommunity:availableForAllPageTypes" controller="MSI_PermissionUtil">
<ltng:require scripts="" styles="/resource/MSIImages5/msiImages.css"/>
<aura:handler name="init" value="{!this}" action="{!c.init}" />  

<!-- use this to make after render actions -->
<aura:attribute name="isDoneRenderingLPB" type="Boolean" default="false"/>
<aura:handler event="aura:doneRendering" action="{!c.onAfterRender}"/>    

<div class="container-fluid">
    <div class="row">
        <div class="col-sm-4 col-md-4 msiBoxCol">
            <a href="" id="liveagent_button_online_ABCD1234" class="thumbnail msiBox1" style=" text-align:center;padding-bottom: 2em;" onclick="{!c.startChat}">
                <div class="msi-img1" style="padding-top:20px;"></div>
                <h3>Live Chat Online</h3>
            </a>

            <a href="" id="liveagent_button_offline_ABCD1234" class="thumbnail msiBox1" style=" text-align:center;padding-bottom: 2em;display: none;">
                <div class="msi-img1" style="padding-top:20px;"></div>
                <h3>Live Chat Offline</h3>
            </a>

        </div>
    </div>
</div>

Answer

My particular issue ended up being an uncaught exception when trying to execute liveagent.showWhenOnline or showWhenOffline. It originally didn’t show in my console, but once I caught it, it indicated that I wasn’t ‘allowed’ to change the button after the live agent had already been initialized.

Further digging yielded that this was a custom error built into the deployment.js:

if(q.connection.isRunning())throw Error("You cannot add a button after page initialization.")

The error indicated page initialization, but I had already tried adding my code to the lightning init actions as well as the after render actions so I threw both of those ideas out right away. That left only one thing. If you take a look at the code in my question you will see that the first line in my head was liveagent.init(). This init was happening before the button display actions, so by the time we tried to display the correct button it was too late.

I ultimately ended up moving all of the code out of the head, only leaving the external reference to the deployment.js:

<script type='text/javascript' src='https://c.la1s1.saleforceliveagent.com/content/g/deployment.js'></script>

and I moved the rest of the code into the controller of the lightning component, and changed the order so that showWhenOnline and showWhenOffline execute before liveagent.init():

init : function(component, event, helper) {

if (!window._laq) { 
window._laq = []; 
console.log('0000 - !window._laq');
}

window._laq.push(function(){
liveagent.showWhenOnline('ABCD1234', document.getElementById('liveagent_button_online_ABCD1234'));
liveagent.showWhenOffline('ABCD1234', document.getElementById('liveagent_button_offline_ABCD1234'));
console.log('0000 - window._laq.push');
});

liveagent.init('https://d.la4-c1cs-was.salesforceliveagent.com/chat', '***Removed***', '***Removed***');
console.log('0000 - Live Agent Initialized');

},

Then you just call the init function from the lightning components controller during init of your lightning component and it checks which button to set before finally initializing the chat/button on the component.

I hope this helps someone else get through this challenge, it’s been quite a ride!

EDIT:: A user in the comments section has asked me to provide the contents of the startChat function in the Lightning Components Controller:

startChat : function(component, event, helper) {
        liveagent.startChat('573U0000000TTzY');
    },

Attribution
Source : Link , Question Author : Morgan Marchese , Answer Author : Morgan Marchese

Leave a Comment