Login / Status
developer.Resource
Home . Documentation . Document Library . Core Documentation
Sponsors
hosted by punkt.deTYPO3 and Open Source Magazine

Chapter 5. Content Objects (cObject)

5.1. Introduction

Content objects (cObjects) are what makes TypoScript spin around. They provide chunks of content of various kinds from images, text/html input, input from a file, selected records from a database or even a PHP-script which you choose to write yourself.

The TEXT and HTML cObjects are explained allready. They are widely used, but primarily because of their stdWrap properties.

COA

An array of cObjects. A quick demonstration:

page.10 = COA
page.10.10 = TEXT
page.10.10 {
  value = This is the page title:
  wrap = <font face="verdana" size=1>|</font>
  wrap2 = | <BR>
  case = upper
}
page.10.20 = TEXT
page.10.20.field = title

outputs this:

That could fit into one line actually, but whether or not that's an advantage depends on your situation.

page.10 = TEXT
page.10.field = title
page.10.wrap = <font face="verdana" size=1>THIS IS THE PAGE TITLE:</font><BR> |

So lets take another example:

page.10 = COA
# Header to this section
page.10.10 = TEXT
page.10.10 {
  value = This is the page title:
  wrap = <font face="verdana" size=1>|</font>
  wrap2 = | <BR>
  case = upper
}
# Output page title / subtitle
page.10.20 = COA
page.10.20 {
  10 = TEXT
  10.field = title
  10.wrap = Page title: <B> | </B><BR>
  20 = TEXT
  20.field = subtitle
  20.wrap = Subtitle: <B> |</B>
}

outputs this:

Challenge (cObject/1)

I would like that the subtitle is sent off to the browser only if it's present. What are you going to do?

Challenge (cObject/2)

Make it so that the whole COA (page.10) is sent off to the browser only if the subtitle is present.

Challenge (cObject/3)

Make it so that the whole COA (page.10) is sent off to the browser only if we are on level 2 and forth in the rootline (that is, if we're on a subpage to eg. "Content elements")

FILE

This is very simple, so I'll just make a short example:

page.10 = FILE
page.10.file = fileadmin/tsbyex/include_me.txt

outputs:

This is a simple textfile with a few HTML-tags in. 

... which is the exact content of the file. Notice that the .file property is a "resource" datatype which means that files must reside in the media/, fileadmin/, uploads/ or typo3temp/ folder. This is a security feature in order to prevent TS-programmers from including everything on the server.

This is technically setup by the array $allowedPaths = Array ("media/","fileadmin/","uploads/","typo3temp/"); from class t3lib_tstemplate

If you include image-files, they are shown as <IMG-tags> instead.

IMAGE

Includes an image with <img>-tag.

Example:

page.10 = IMAGE
page.10.file = fileadmin/tsbyex/alligator.jpg

This inserts a nice picture of a baby alligator (courtesy of me, snapshot from Florida).

The .file property is an "imgResource" (pronounced "image resource") and there are more options and possibilities for that than you dream of. So we'll get back to that.

But lets try just a few things with the image. This example sets the width to 200 pixels and adds a link to the image that shows it in another window in the original size:

page.10 = IMAGE
page.10 {
  file = fileadmin/tsbyex/alligator.jpg

  file.width = 200

  imageLinkWrap = 1

  imageLinkWrap.enable = 1

}

Reload the page. The image is now 200 pixels wide in the browser. Try to click the image, and a new browser window will open with the original image in.

Questions (cObject/4)

What did Typo3 do to the image when the size was set to 200 pixels? Was only the HTML-code changed or was the image actually scaled? Look at the filenames of the first example without file.width and the current example. What are the names and location?

Challenge (cObject/5)

Refering to the ->imageLinkWrap object in TSref, can you make the imageLinkWrap open the enlarged image in a JavaScript window?

IMG_RESOURCE

This does the same as the IMAGE cObject but the very important difference is that the <IMG>-tag is not wrapped around the file.

Example:

page.10 = IMG_RESOURCE
page.10 {
  file = fileadmin/tsbyex/alligator.jpg
  file.width = 200
}

outputs:

typo3temp/3de305c72b.jpg 

Now, that's not very exiting in itself, so ...

Challenge (cObject/6)

Can you make the image the background image of a table?

CLEARGIF

Inserts a clear gif-file, clear.gif:

page.10 = CLEARGIF
page.10.width = 200

outputs this HTML-code:

<img src="clear.gif" width=200 height=1 border=0><BR>

Notice the <BR>-tag is always prepended.

You're always free to use the clear.gif file which are found in the root of the site.

HRULER

This inserts a horizontal "ruler". Not the HTML-kind, but made with a table and a background color.

Example:

page.5 = TEXT
page.5.value = Before ruler
page.10 = HRULER
page.10 {
  lineThickness = 3
  lineColor = red
}
page.15 = TEXT
page.15.value = After ruler

outputs this:

Challenge (cObject/7)

Play around with the other properties and see what they do. Check the source-code.

Also, are you able to set the space above (10 pixels) and below (20 pixels) the ruler in order to create space to the text?

CTABLE and OTABLE

These cObjects are meant supply you with quick tables to position your content.

Example of OTABLE:

page.10 = OTABLE
page.10 {
  tableParams = border=1
  offset = 10,10
  10 = TEXT
  10.value = What a cute little alligator! Dear Lord, may it never grow up!
  10.wrap = |<BR>
  20 = IMAGE
  20.file = fileadmin/tsbyex/alligator.jpg
  20.file.width=200
}

outputs this:

It should be obvious what offset does here. But normally you would like some other parameters for the <table>-tag. So this might be a better solution:

page.10 = OTABLE
page.10 {
  tableParams = border=0 cellpadding=0 cellspacing=0 width=100
  offset = 10,10
...

If you don't specify .tableParams, "<TABLE border=0 cellspacing=0 cellpadding=0>" becomes the default <TABLE>-start tag.

Challenge (cObject/8)

Setup a OTABLE that is able to precisely set the offset from upperleft corner to "0, 20" and where the content is in a column of 250 pixels. Hint: Setting the bodytag margins requires you to look at the properties of the PAGE-object.

Example of CTABLE:

A CTABLE is a little more feature packed than the simple and yet useful OTABLE. It features a content column and four surrounding column. These may be useful for putting menus in. But lets take a look at a simple example first:

page.bodyTagMargins = 0
page.10 = CTABLE
page.10 {
  tableParams = border=1 cellpadding=0 cellspacing=0
  offset = 0,20
  c.10 = TEXT
  c.10.value = CONTENT cell
}

outputs something totally identical to the OTABLE setup like this:

page.bodyTagMargins = 0
page.10 = OTABLE
page.10 {
  tableParams = border=1 cellpadding=0 cellspacing=0
  offset = 0,20
  10 = TEXT
  10.value = CONTENT cell
}

The same except from the fact that CTABLE adds "valign=top" to the <td>-tags.

Now lets look at a more complex example:

page.bodyTagMargins = 0
page.10 = CTABLE
page.10 {
  tableParams = border=1 cellpadding=0 cellspacing=0
  offset = 0,20
  c.10 = TEXT
  c.10.value = CONTENT cell
  rm.10 = TEXT
  rm.10.value = RIGHT cell
  lm.10 = TEXT
  lm.10.value = LEFT cell
  tm.10 = TEXT
  tm.10.value = TOP cell
  bm.10 = TEXT
  bm.10.value = BOTTOM cell
}

In this case we use all five "content cells" of the CTABLE and it looks like this:

Now, you can you any cObjects you like  in the cells. But there are two features yet to check out. With ".cMargin" you can add margins between the cells all the way around and with cWidth you can automatically space out the content cell to a certain width with a clear-gif.

Try to add:

...
  offset = 0,20
  cMargins = 10,20,30,40

  cWidth=300

  rm.TDParams = bgcolor=red valign=bottom

...

... and you'll get:

Notice that the RIGHT cell (rm) had some extra parameters specified that made the table-cell red in the background.

Just for fun, lets take a look at this TypoScript in the Object Browser:

Educading, isn't it...

TEMPLATE

Sometimes you may want to use a HTML template instead of doing it all in TypoScript. This is what the TEMPLATE object is for.

Example:

To make the TEMPLATE work, this is all you need:

page.10 = TEMPLATE
page.10.template = FILE
page.10.template.file = fileadmin/tsbyex/template.html

...and this is apparently what you get:

But after a closer inspection of the source-code it's revealed that the whole file is inserted:

...
// End Hiding Script -->
</script>
</head>
<body bgcolor="#FFFFFF">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>

<head>

<title>Untitled</title>

</head>

<body>

This is a template that demonstrates the concept of subparts and markers.

<!-- ###DOCUMENT### -->

This is a <i>###SIMPLE_WORD###</i> textfile with a few HTML-tags in.<br>

<br>

Check out the <!--###LINK###-->link to the front page.<!--###LINK###-->

<!-- ###DOCUMENT###-->

</body>

</html>

</body></html>

... and that was not the point - unless we wanted the whole file to be inserted of course. But that's easily fixed, because for the TEMPLATE cObject you can define a "subpart" to work on. Subparts are confined by two markers (which by default is a- and prepended with "###") and those markers may or may not be in an HTML-comment.

Our subpart is "###DOCUMENT###", so try this:

page.10 = TEMPLATE
page.10.template = FILE
page.10.template.file = fileadmin/tsbyex/template.html

page.10.workOnSubpart = DOCUMENT

Much better. The HTML-source now displays this:

...

</head>

<body bgcolor="#FFFFFF">

This is a <i>###SIMPLE_WORD###</i> textfile with a few HTML-tags in.<br>

<br>

Check out the <!--###LINK###-->link to the front page.<!--###LINK###-->

</body></html>

Now the point is to

substitute ###SIMPLE_WORD### with the page title and substitute the ###LINK### subpart with itself, but linked to the frontpage of the website (and that's a tough one!)

Example:

page.10 = TEMPLATE
page.10 {
  template = FILE
  template.file = fileadmin/tsbyex/template.html
  workOnSubpart = DOCUMENT
  marks.SIMPLE_WORD = TEXT
  marks.SIMPLE_WORD.field = title
  subparts.LINK = TEXT
  subparts.LINK.current = 1
  subparts.LINK.debugFunc = 1
}

This outputs this:

And the HTML-source code looks like this:

...
// End Hiding Script -->
</script>
</head>
<body bgcolor="#FFFFFF">
This is a <i>Content elements</i> textfile with a few HTML-tags in.<br>
<br>
Check out the link to the front page.
</body></html>

As you can see the marker SIMPLE_WORDS has been correctly substituted. The LINK-subpart also seems to be processed. At least the HTML-comments are gone. But the value is not processed further than that. But that's on purpose in order to investigate a little detail:

According to the TSref, "In addition the current-value is loaded with the content of each subpart just before the cObject for the subpart is parsed." So what the lines ...

  subparts.LINK = TEXT
  subparts.LINK.current = 1
  subparts.LINK.debugFunc = 1

... did was to load the TEXT cObject with the value of the "current" register (see stdWrap) and because I was curious about what content the TEXT-object actually was, I investigated it by the ".debugFunc = 1" flag which - just like debugData demonstrated earlier (see stdWrap) - outputs the value during the "execution" of the TypoScript.

So now I move to the next level - encapsulating the the subpart LINK with a link.

...
  subparts.LINK = TEXT
  subparts.LINK.current = 1

  subparts.LINK.typolink {

    parameter = 1

  }

}

This adds the correct link-tag to the subpart and it now links to page with id=1.

In this case id=1 happens to be the "frontpage" of my site, but I would like a more flexible solution, so what I'm going to do is to fetch the uid of the page on level 0 in the rootline. We know howto already (.data = leveluid:0 - see stdWrap and datatypes in TSref), but we don't know, if the .parameter property of the "typolink" object has stdWrap-properties... (get to the reference, find the typolink function .... looking. ... YES!).

...
  subparts.LINK = TEXT
  subparts.LINK.current = 1
  subparts.LINK.typolink {
    parameter.data = leveluid:0
  }
}

Challenge (cObject/9)

Can you make the link jump the the page on level 1 in the rootline instead of the front page? Can you define the target of the link to be "_blank"? And can you also wrap the link in <B>-tags?

FORM

Of cource you can create forms manually, but the advantage of letting Typo3 do it is that the syntax is simple enough to teach it to non-techies and you can have it automatically validated (simple way) by JavaScript.

Example:

page.10 = FORM
page.10.data = Label | input
page.10.layout = ###LABEL###: ###FIELD###<BR>

This is the absolute minimum of information needed to create a form.

The .data property takes input that is conforms to the syntax defined in TSref and .layout is a minitemplate where ###LABEL### and ###FIELD### represents respectively the label and field inserted.

First of all, how do we add more fields? Well normally the input that generates the form comes from a text-field in the database, normally "bodytext" of a tt_content record. In that input every line represents a new element. We cannot do that with string-input directly to the .data property, so the workaround is that entering a double-"|" equals a linebreak. Therefore...

page.10 = FORM

page.10.data = Name|input    ||    Address|textarea    ||    Send|submit|Send the form

page.10.layout = ###LABEL###: ###FIELD###<BR>

...generates this:

The tslib/index_ts.php script (which is the main front-end script, see Typo3Overview, F1) is able to send formmail-emails. To create a working email form you have to at least setup this:

page.10 = FORM
page.10.data = Name|*input,40 || Address|textarea,40,10 || Send it...|formtype_mail=submit|Send the form || |subject=hidden|This is the subject

page.10.recipient = your@email.com

page.10.layout = ###LABEL###: ###FIELD###<BR>

page.10.locationData = 1

page.10.REQ=1

page.10.REQ.layout = ###LABEL### (Required): ###FIELD###<BR>

Notice the changes in red:

  • The input fields are given a size parameter

  • as is the textarea

  • the submit-button is named "formtype_mail" in order for the script to realize that a mail is being sent

  • the subject is set

  • the recipient is set

  • locationData is set ON (required if the index_ts.php script is going to send the mail)

  • REQ is introduced which enables the check for required-field (which the "Name" field is marked as due to the asterisk in front of the word "input")

  • REQ.layout is introduced as an alternative layout to the required fields.

It looks like this:

If you would like to go into details with this, please see the default form-definitions in the static_template "styles.content (default)" / styles.content.mailform

CASE

This cObject provides yet a "control structure" to TypoScript. It works like a switch-construct:

Example:

page.10 = CASE
page.10.key = cheese
page.10.cheese = IMAGE
page.10.cheese {
  file = fileadmin/tsbyex/alligator.jpg
  file.width=200
  wrap = Cheese.... &nbsp;| &nbsp; is what this guy says
}
page.10.tomatoes = TEXT
page.10.tomatoes.value = Tomatoes are so tasty
page.10.default = TEXT
page.10.default.value = If nothing else is going on, this happens...

This is the result:

As you see, because the reserved property "key" in the array of the CASE cObject is assigned the value "cheese" the content of the cObject "page.10.cheese" is fetched! (The list of reserved properties are "setCurrent", "key", "default", "stdWrap" and "if")

Try to enter "tomatoes" instead! Or leave it blank - in which case the "page.10.default" cObject is rendered.

The useful part is when you have some data to input into the .key property instead of fixed values. Lets reconstruct the the script a bit:

temp.cheese = IMAGE
temp.cheese {
  file = fileadmin/tsbyex/alligator.jpg
  file.width=200
  wrap = Cheese.... &nbsp;| &nbsp; is what this guy says
}
temp.tomatoes = TEXT
temp.tomatoes.value = Tomatoes are so tasty
temp.default = TEXT
temp.default.value = If nothing else is going on, this happens...
page.10 = CASE
page.10.key.data = level:1
page.10.1 < temp.cheese
page.10.2 < temp.tomatoes
page.10.default < temp.default
page.20 = TEXT
page.20.data = level:1
page.20.wrap = <HR> | - 
page.30 = TEXT
page.30.field = title

This is the result:

Try to hit the pages "Startpage", "Content elements", "Insert content" and because each is at it's specific level, it presents specific content.

...
page.10.1 < temp.cheese
page.10.2 < temp.tomatoes
page.10.default < temp.default
...

Another little hint was my use of temporary objects created in the temp. toplevel object (read about this elsewhere). It can be very useful to define chunks of TypoScript in that toplevel object and later in the script copy the chunks into the correct position. This creates an opportunity to get a better overview of your TypoScripts.

Challenge

Take a little time to look into the static_template "content (default)". Try to get a grasp on the CASE cObject used in the tt_content toplevel object. Whenever necessary, refer to "styles.content (default)" which provides a lot of premade objects for use in "content (default)"

LOAD_REGISTER

This cObject does not return any values. Rather you can use it to set some values in the "register". It's a kind of way to pass values around between the TypoScript objects but it is a hack in order to enable just a tiny degree of this. Remember TypoScript is not "executed" like a JavaScript. It's still just a bunch of configuration.

But anyway this example shows how it works:

page.10 = LOAD_REGISTER
page.10.MY_VALUE = The register value!
page.5 = TEXT
page.5.value = The default value
page.5.override.data = register:MY_VALUE
page.5.wrap = | <HR>
page.15 < page.5

This is the result:

Explanation:

Consider the TypoScript:

The object at position "5" in the cObject array of the PAGE object "page" is 'executed" before position "10" which is where the register MY_VALUE is set for the first time. Because the register value until then was empty "page.5" returned the value of the .value property. That was "The default value"

When "page.10" is executed the register-value is set.

When "page.20" is executed, the register is not empty anymore, therefore the value overrides the default value. And the output becomes "The register value!"

Challenge

Try to look at the static_templates "TEMPLATE; FIRST" and "TEMPLATE; MM". They both utilize this feature. To accomplish what?



TYPO3 Core API

TSRef

TYPO3 Coding Guidelines