Cesium Entity Description not working click event on button

Hello all,

I am new to Cesium and has some exposure to Google Earth.i wanna do fire an event on info box link .
but it's not working i have set allow script property for iframe in CesiumUnminified file .

Thanks
Gorav

Hi,

Here’s some code you can paste into Cesium Sandcastle to register a click handler on a button in the infoBox.

  --Ed.

var viewer = new Cesium.Viewer(‘cesiumContainer’);
var toolbar = document.getElementById(‘toolbar’);
var numClicks = 0;

// CAUTION: Only disable iframe sandbox if the descriptions come from a trusted source.
viewer.infoBox.frame.setAttribute(‘sandbox’, ‘allow-same-origin allow-popups allow-forms allow-scripts allow-top-navigation’);

function updateDisplay() {
toolbar.innerHTML = 'Number of times you clicked either button: ’ + numClicks;
}
updateDisplay();

var entity = viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
billboard :{
image : ‘…/images/Cesium_Logo_overlay.png’
},
name : ‘Click tester in Exton, PA’,
description :
‘This an entity description with a clickable button in it.’ +

’ +
‘Click here

});
viewer.selectedEntity = entity;

viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-117.13, 32.81),
billboard :{
image : ‘…/images/Cesium_Logo_overlay.png’
},
name : ‘Click tester in San Diego, CA’,
description :

’ +
‘Also click here
’ +
‘This is another place you can click.’
});

// Since the viewer is newly constructed, the iframe is still about:blank.
// This listens for the iframe to change to the Cesium description template,
// which only happens once at startup.
//
viewer.infoBox.frame.addEventListener(‘load’, function() {
//
// Now that the description is loaded, register a click listener inside
// the document of the iframe.
//
viewer.infoBox.frame.contentDocument.body.addEventListener(‘click’, function(e) {
//
// The document body will be rewritten when the selectedEntity changes,
// but this body listener will survive. Now it must determine if it was
// one of the clickable buttons.
//
if (e.target && e.target.className === ‘click-test-button’) {
++numClicks;
updateDisplay();
}
}, false);
}, false);

1 Like

Awesome, so the string value of entity.description ends up being the HTML code of viewer.infoBox.frame.contentDocument .

I found out that you can get away with just setting these properties for this particular case

viewer.infoBox.frame.setAttribute(‘sandbox’, ‘allow-scripts allow-same-origin’);

Basically yes. If you use “inspect element” (right-click in any of Chrome, Firefox, IE, Opera) you can see in the inspector that there’s a bit of boilerplate around the HTML string. The description string is injected into a div which becomes the only element in the body of the iframe’s document. The head of that document contains a reference to the default stylesheet, “InfoBoxDescription.css”.

A few versions ago (1.6 and prior, maybe?) we didn’t use an iframe, the description box was a normal div in the page. For security against un-trusted descriptions, we ran the description string through Google’s Caja script, to sanitize it. But the default settings there were extremely strict, as they need to be, and many seemingly simple HTML tags were being removed for the sake of security. So the description couldn’t handle much in the way of custom styling, and the whole mechanism depended on an open network connection to Caja.

Luckily, browser support for “sandboxed” iframes has improved a lot over the past year, and is now robust enough that we felt we should make the switch. So, no more dependency on Caja and its heavy-handed filtering. Instead, your HTML description is injected into a sandboxed iframe complete with custom images and custom styling. Even if it’s a user-supplied description string, they shouldn’t be able to run scripts or steal login auth cookies etc. so long as the sandboxing is left on. If you turn the sandboxing off, make sure all of your descriptions come from “trusted data” within your own app, not anything supplied by users (or, run the user-supplied stuff through Caja or similar).

–Ed.

Thanks for all of the info! I forgot Matt mentioned about entity.description earlier https://groups.google.com/d/msg/cesium-dev/imIpoZHvKrM/wAGl_7rhs2cJ If the infoBox is limited to 40% 480px width, I assume that the contained iFrame is also limited to this? Perhaps the infoBox could be movable and resizeable via public properties? I know you can change style via private properties https://groups.google.com/d/msg/cesium-dev/imIpoZHvKrM/RmjVCgaxATAJ

Hi Hyper Sonic,

We encourage folks to supply their own CSS that overrides Cesium’s defaults. Give this a try:

  1. Load up the Sandcastle CZML Demo.

  2. Click on the “HTML Body & CSS” tab on the left side, it’s the 2nd tab there.

  3. Note the top 3 lines are a block, and line 2 in particular imports the Sandcastle (bucket) styles, which in turn import all the Cesium styles.

  4. Inject the following new lines, between lines 2 and 3 (so after the @import, but before the end of the style block):

    .cesium-infoBox {
    width: 70%;
    max-width: none;
    }

Click Run (F8) with these changes and select any object in the scene. It’s fairly easy to override a lot of Cesium’s style choices in this manner.

–Ed.

Thanks for the CSS example. So that alters elements whom’s class is cesium.infoBox. While CSS is great for initializing, I believe JavaScript manipulation is needed for dynamic control.

Adding this to the end of http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=CZML.html&label=Showcases

viewer.infoBox._element.style.maxWidth=“none”;
viewer.clock.onTick.addEventListener(function(clock)
{
var time = new Date().getTime();
time = Math.floor(time/100);//100ms
var percent = time % 100;
if(percent<10){percent=100;}
viewer.infoBox._element.style.width=percent.toString()+"%";
});

``

Dynamically alters the width of the infoBox. This particular example may not be particularly useful, however, lets say an infoBox had a ‘read more’ link where it expands a summary into a full blown in depth article. It could be useful in those cases.

I really depends on your use case, most of the width stuff can be handled via media queries in CSS.

Whenever possible I recommend adding additional complexity to the DOM. If you start using JS to just keep modifying element styles directly on the DOM it will be much more difficult to alter later if you need to restyle or re-theme your application. In my experience that happens way to often and I don’t want to have to refactor javascript to make things look a new kind of pretty.

should read “recommend against adding complexity”

Ya Media queries in CSS are great for adapting to various screen sizes, aspect ratios, and such. What about a expand/collapse button for the infoBox? In Google Earth some popup windows have a button which opens up a large window to display more information, then a ‘Back to Google Earth button’ for when you want to exit the large window.