Javascript: Check if a component is currently visible (by component ID)?

Is there a way to check if a component (with a given component ID) is currently visible on the screen in Javascript?

I can check if it is “rendered” with

skuid.component.getById(‘COMPONENTID’).isRendered

but this isn’t enough, as it turns out that it being rendered and it being currently visible on the screen have different implications. For instance if I tell it to render with .render(), even if it “isRendered”, if it’s not currently visible on the screen this will cause an error.

Is there a way to check on the component’s actual visibility (the component not being hidden)?

Thanks!

Hi Mark, that sounds like a cool idea to check rendered vs. visible. I’m sure there are different ways to check it - we got help from our solutions engineers and can show you one way to achieve it. The following sample page contains three wrapper components of different colours, and a JS snippet which checks if the purple wrapper component is completely visible. The snippet is triggered by a button click. You can see the result in the browser console (visibility true/false). We hope that this idea is helpful for you:

var params = arguments[0], $ = skuid.$; var component = skuid.component.getById('purple'); var docViewTop = $(window).scrollTop(); var docViewBottom = docViewTop + $(window).height(); var elemTop = $(component.element).offset().top; var elemBottom = elemTop + $(component.element).height(); var result= ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); console.log("visibility "+ result);

Hi Luzie,

Thanks for the update. Interesting hack, but not quite what I’m looking for. The XML page example depends on the Y location of the element on the screen and assumes that it is visible as long as its Y location is within screen bounds.

Here I’ve moved the colors into a tab set where an element’s visibility is dependent on it being within the currently selected tab and this method now breaks, causing an error when not yet rendered, and showing “visible” after rendering whether or not its tab is selected and it is actually visible:

<skuidpage personalizationmode="server" showsidebar="false" showheader="false" globalfeedbackenabled="false">
<models/>
<components>
<wrapper uniqueid="sk-2Qyg-384">
<components>
<buttonset uniqueid="sk-2Qyg-385" position="center">
<buttons>
<button type="multi" label="check purple's visibility in the browser console" uniqueid="sk-2Qyg-386">
<actions>
<action type="custom" snippet="newSnippet"/>
</actions>
</button>
</buttons>
<renderconditions logictype="and"/>
</buttonset>
</components>
<styles>
<styleitem type="background"/>
<styleitem type="border" margin="none" borders="all">
<styles>
<styleitem property="border" value="16px solid transparent"/>
<styleitem property="box-sizing" value="border-box"/>
</styles>
</styleitem>
<styleitem type="size"/>
</styles>
</wrapper>
<tabset rememberlastusertab="false" defertabrendering="true" uniqueid="sk-2RoA-302">
<tabs>
<tab name="Orange">
<components>
<wrapper uniqueid="orange">
<components/>
<styles>
<styleitem type="background" bgtype="color">
<styles>
<styleitem property="background-color" value="orange"/>
</styles>
</styleitem>
<styleitem type="border"/>
<styleitem type="size" height="custom">
<styles>
<styleitem property="min-height" value="600px"/>
</styles>
</styleitem>
</styles>
</wrapper>
</components>
</tab>
<tab name="Green" loadlazypanels="true">
<components>
<wrapper uniqueid="green">
<components/>
<styles>
<styleitem type="background" bgtype="color">
<styles>
<styleitem property="background-color" value="green"/>
</styles>
</styleitem>
<styleitem type="border"/>
<styleitem type="size" height="custom">
<styles>
<styleitem property="min-height" value="600px"/>
</styles>
</styleitem>
</styles>
</wrapper>
</components>
</tab>
<tab name="Purple" loadlazypanels="true">
<components>
<wrapper uniqueid="purple">
<components/>
<styles>
<styleitem type="background" bgtype="color">
<styles>
<styleitem property="background-color" value="purple"/>
</styles>
</styleitem>
<styleitem type="border"/>
<styleitem type="size" height="custom">
<styles>
<styleitem property="min-height" value="600px"/>
</styles>
</styleitem>
</styles>
</wrapper>
</components>
</tab>
</tabs>
</tabset>
<wrapper uniqueid="sk-2QyT-316">
<components>
<buttonset uniqueid="sk-2CE1-633" position="center">
<buttons>
<button type="multi" label="check purple's visibility in the browser console" uniqueid="sk-2CE1-634">
<actions>
<action type="custom" snippet="newSnippet"/>
</actions>
</button>
</buttons>
<renderconditions logictype="and"/>
</buttonset>
</components>
<styles>
<styleitem type="background"/>
<styleitem type="border" margin="none" borders="all">
<styles>
<styleitem property="border" value="16px solid transparent"/>
<styleitem property="box-sizing" value="border-box"/>
</styles>
</styleitem>
<styleitem type="size"/>
</styles>
</wrapper>
</components>
<resources>
<labels/>
<javascript>
<jsitem location="inlinesnippet" name="newSnippet" cachelocation="false">var params = arguments[0],
$ = skuid.$;
var component = skuid.component.getById('purple');
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(component.element).offset().top;
var elemBottom = elemTop + $(component.element).height();
var result= ((elemBottom &amp;lt;= docViewBottom) &amp;amp;&amp;amp; (elemTop &amp;gt;= docViewTop));
console.log("visibility "+ result);</jsitem>
</javascript>
<css/>
<actionsequences/>
</resources>
<styles>
<styleitem type="background" bgtype="none"/>
</styles>
</skuidpage>

Is there any more direct way of checking visibility? Currently my strategy is to keep calling a function to re-render the object and in a try/catch, keep catching the error when it tries to render while the element isn’t visible, and re running the function until the element becomes visible again and an error isn’t caught; not an ideal solution – pretty messy, would be preferable to find a more direct way of dealing with this.

Thanks!

did you ever find a different a solution?

Wrote this in your other post but here it is again:

function to wait for an element to be visible on the screen and then runs the callback when it is:

//&nbsp;skuid.custom.waitForElement(fparams,callback)<br>//&nbsp;wait&nbsp;for&nbsp;an&nbsp;element&nbsp;to&nbsp;be&nbsp;ready&nbsp;on&nbsp;the&nbsp;screen&nbsp;before&nbsp;performing&nbsp;the&nbsp;callback&nbsp;function<br>//&nbsp;fparams&nbsp;=&nbsp;{<br>//&nbsp;&nbsp;initEle:&nbsp;function&nbsp;to&nbsp;initialize&nbsp;the&nbsp;element&nbsp;/&nbsp;check&nbsp;if&nbsp;the&nbsp;element&nbsp;is&nbsp;initialized,<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;should&nbsp;return&nbsp;the&nbsp;initialized&nbsp;element.&nbsp;Takes&nbsp;context&nbsp;as&nbsp;a&nbsp;variable.<br>//&nbsp;&nbsp;context:&nbsp;passed&nbsp;context&nbsp;or&nbsp;defaults&nbsp;to&nbsp;window<br>//&nbsp;&nbsp;chunkTime:&nbsp;time&nbsp;between&nbsp;chunks,&nbsp;defaults&nbsp;to&nbsp;250<br>//&nbsp;}<br>skuid.custom.waitForElement&nbsp;=&nbsp;function&nbsp;(fparams,&nbsp;callback)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;fparams&nbsp;=&nbsp;fparams&nbsp;||&nbsp;{};<br>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;initEle&nbsp;=&nbsp;fparams.initEle&nbsp;||&nbsp;undefined;<br>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;element&nbsp;=&nbsp;fparams.element&nbsp;||&nbsp;undefined;<br>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;context&nbsp;=&nbsp;fparams.context&nbsp;||&nbsp;window;<br>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;chunkTime&nbsp;=&nbsp;fparams.chunkTime&nbsp;||&nbsp;250;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;doChunk&nbsp;()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;ele;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(initEle&nbsp;===&nbsp;undefined&nbsp;&amp;&amp;&nbsp;element&nbsp;!==&nbsp;undefined)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ele&nbsp;=&nbsp;element;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;if&nbsp;(initEle&nbsp;!==&nbsp;undefined)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ele&nbsp;=&nbsp;initEle.call(context);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(typeof&nbsp;ele&nbsp;!==&nbsp;'undefined')&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;error&nbsp;=&nbsp;false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;callback.call(context,&nbsp;ele);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(err)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error&nbsp;=&nbsp;true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log('Still&nbsp;waiting&nbsp;for&nbsp;element..&nbsp;Error:&nbsp;${err}');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!error)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log('Wait&nbsp;for&nbsp;element&nbsp;complete.');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clearInterval(ourInterval);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log('Still&nbsp;waiting&nbsp;for&nbsp;element..');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Keep&nbsp;trying&nbsp;to&nbsp;get&nbsp;the&nbsp;element&nbsp;and&nbsp;perform&nbsp;the&nbsp;callback&nbsp;until&nbsp;there&nbsp;isn't&nbsp;an&nbsp;error<br>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;ourInterval&nbsp;=&nbsp;setInterval(doChunk,&nbsp;chunkTime);
};

thanks! that is better than what I did. Stay safe and well