I’m trying to work through my first HTML5 templates in Caspar.
I built a simple HTML5-template that has an image as background with a text on it.
I’m able to play out this template and to set the texts from my client.
So far so good.
Now I like to resize my image depending on the length of the text (controlled by the Caspar Client). So as far as I understood I have to set the img.width property of my HTML element. But how can I manage that?
To manipulate the text I send
Dim data As New CasparCGDataCollection
data.SetData(.Controls.Find("txt_" & i + 1, True).FirstOrDefault().Tag, .Controls.Find("txt_" & i + 1, True).FirstOrDefault().Text)
CasparDevice.Channels(1).CG.Add(cglayer, .cbx_template_folder.SelectedItem & "/" & .cbx_templates.SelectedItem, data)
But that doesn’t work for the width attribute. I tried:
/*
* Data sent from CasparCG Client as templateData
* is pushed into corresponding HTML id element
*
* Usage:
* insert a script reference in the HTML template header.
* ex: <script type="text/javascript" src="CasparCG.js"></script>
* Make sure that the id that you refer to is the innermost tag.
* Everything within that tag id will be replaced by the value sent from CasparCG
*
* put together by Tomas Linden
* modified by Øjvind Søgaard Andersen
*
Structure of data sent from CasparCG:
<templateData>
<componentData id="#idCaspar#">
<data id="text" value="#valCaspar#" />
</componentData>
:
:
<componentData id="#idCaspar#">
<data id="text" value="#valCaspar#" />
</componentData>
</templateData>
*/
// Global variable for data from CasparCG
var dataCaspar = {};
// Replace characters that could become a problem if left as is
function escapeHtml(unsafe) {
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
}
// Parse templateData into an XML object
function parseCaspar(str) {
var xmlDoc;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(str, "text/xml");
}
dataCaspar = XML2JSON(xmlDoc.documentElement.childNodes);
}
// Make the XML templateData message into a more simple key:value object
function XML2JSON(node) {
var data = {}; // resulting object
for (k = 0; k < node.length; k++) {
var idCaspar = node[k].getAttribute("id");
var valCaspar = node[k].childNodes[0].getAttribute("value");
if (idCaspar != undefined && valCaspar != undefined) {
data[idCaspar] = valCaspar;
};
}
return data;
}
// Main function to insert data
function dataInsert(dataCaspar) {
for (var idCaspar in dataCaspar) {
var idTemplate = document.getElementById(idCaspar);
if (idTemplate != undefined) {
idTemplate.innerHTML = escapeHtml(dataCaspar[idCaspar]);
}
}
}
// Call for a update of data from CasparCG client
function update(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
}
// insert data from CasparCg client when activated
function play(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
gwd.actions.timeline.gotoAndPlay('document.body', 'start');
}
// Call for a next from CasparCG client
function next() {
gwd.actions.timeline.play('document.body');
}
// Call for a stop from CasparCG client
function stop() {
gwd.actions.timeline.gotoAndPlay('document.body', 'out');
}
// Call for a update and jump to preview (out)
function preview(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
gwd.actions.timeline.gotoAndPause('document.body', 'out');
}
As a guiding note: I would never send such information from the client. Because it makes the client too dependent on the template. Adapting the size of a background element to the text length can be done inside the template using javascript or some css tricks. To be able to set that from the client, it would need to know what font and size the template uses. And that should always be left to the template, so that you can use a different template, without changeant anything in the client (beside telling it to use the other template).
Are you sending the unit along with the value? like "1920px" or "100vw" instead of just "1920".
I agree with you, but sometimes the templates need to be a bit flexible. It doesn’t make sense to switch templates just to change the text’s color. If it’s done correctly and in a controlled way, templates should be more dynamic. A background width is not one of those cases though.
Thanks rrebuffo for the hint with the unit. I obviously got the whole HTML idea wrong. Of course I haven’t sent the unit alongside the value. Doing this it works brilliantly.
That’s the problem if you only have my semi-knowledge.
And thank you didi for your remarks which I appreciate very much. Of course you’re right. Putting this logic or funtionality into the HTML itself should be the better way.
The challenge is that I don’t have the actual draft from our design department. So I can’t really work with the template. So I use my time to fiddle around with Caspar and HTML to get used to it and to check out what works for me and what doesn’t.
I’m looking forward to getting the actaul draft. Maybe I come back to you then to get it as dynamic as possible. Thanks.
By the way:
This is a great forum. You always get an immediate and qualified answer to any request. Perfect help (not only) for beginners like me.
hahaha. I an far away to be called like that. I was hit by the Flash EOL like a shock, around October last year and started with HTML template building beginning of this year. So I am still digging in the dark most of the time.
The good thing with JavaScript is, that it is very similar to ActionScript (Flash) so that at least the syntax is not completely new to me…
I now got the draft from our design department. They did a pretty good job graphically but didn’t work with a timeline as I expected it.
They actually load an animation class (i.e. “animation_in”). For the out animation they remove the animation class from the document and load another class (“animation_out”). Pretty weird for me but works fine with two buttons.
My challenge is now to “press” these button from caspar.js script. And here ends my js knowledge.
function play(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
jQuery('body').removeClass('animation_in animation_out').addClass('animation_in');
}
Sometimes when doing CSS animations by swapping classes the browser cannot keep up and it helps to force a repaint - which in turn will trigger the CSS transitions.
I don’t quite get it.
You suggest to insert a dummy command into caspar.js to force the template to repaint?
Something like:
function play(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
jQuery('body').removeClass('animation_in animation_out').addClass('animation_in');
var elem = document.scrollingElement;
}
I tried that but it doesn’t help.
I’m still not sure if my call for the jQuery function is correct.
Is it possible to use that call this way?
The actual thing from the example is <some-element>.offsetHeight; -part. Hard to tell details, since we do not know what your parseCaspar(str) and dataInsert(dataCaspar) functions are doing and what your template HTML is like…
OK.
Unfortunately I can’t give you the whole template but here is at least the caspar.js I’m using:
/*
* Data sent from CasparCG Client as templateData
* is pushed into corresponding HTML id element
*
* Usage:
* insert a script reference in the HTML template header.
* ex: <script type="text/javascript" src="CasparCG.js"></script>
* Make sure that the id that you refer to is the innermost tag.
* Everything within that tag id will be replaced by the value sent from CasparCG
*
* put together by Tomas Linden
* modified by Øjvind Søgaard Andersen
*
Structure of data sent from CasparCG:
<templateData>
<componentData id="#idCaspar#">
<data id="text" value="#valCaspar#" />
</componentData>
:
:
<componentData id="#idCaspar#">
<data id="text" value="#valCaspar#" />
</componentData>
</templateData>
*/
// Global variable for data from CasparCG
var dataCaspar = {};
// Replace characters that could become a problem if left as is
function escapeHtml(unsafe) {
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
}
// Parse templateData into an XML object
function parseCaspar(str) {
var xmlDoc;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(str, "text/xml");
}
dataCaspar = XML2JSON(xmlDoc.documentElement.childNodes);
}
// Make the XML templateData message into a more simple key:value object
function XML2JSON(node) {
var data = {}; // resulting object
for (k = 0; k < node.length; k++) {
var idCaspar = node[k].getAttribute("id");
var valCaspar = node[k].childNodes[0].getAttribute("value");
if (idCaspar != undefined && valCaspar != undefined) {
data[idCaspar] = valCaspar;
};
}
return data;
}
// Main function to insert data
function dataInsert(dataCaspar) {
for (var idCaspar in dataCaspar) {
var idTemplate = document.getElementById(idCaspar);
if (idTemplate != undefined) {
idTemplate.innerHTML = escapeHtml(dataCaspar[idCaspar]);
}
}
}
// Call for a update of data from CasparCG client
function update(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
}
// insert data from CasparCg client when activated
function play(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
jQuery('body').removeClass('animation_in animation_out').addClass('animation_in');
}
// Call for a next from CasparCG client
function next() {
}
// Call for a stop from CasparCG client
function stop() {
jQuery('body').addClass('animation_out');
}
// Call for a update and jump to preview (out)
function preview(str) {
parseCaspar(str); // Parse templateData into an XML object
dataInsert(dataCaspar); // Insert data
}
The recent template contains two buttons that start and stop the animations. It’s done by loading the classes “animation_in” and “animation_out”.
All I try to do is call the “addClass” function from the caspar.js instead of the buttons.
Sorry I cannot get more precise but it’s copyright related material in the HTML.
CasparCG Client calls the play() function in the template when it’s started with the PLAY command (F2). This happens automatically.
To me, it looks like your template should already work. It has the play() function implemented and it is swapping the CSS classes… No need to do any further “button clicks” anywhere.